parse-sdk 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
parse_sdk/scaffold.py ADDED
@@ -0,0 +1,273 @@
1
+ """The committed `parse_apis` scaffold + reserved-name vocabulary.
2
+
3
+ `parse init` materializes a minimal, *committed* `parse_apis` distribution
4
+ (`pyproject.toml`, `src/parse_apis/__init__.py`, `src/parse_apis/py.typed`) and
5
+ `parse sync` fills the generated, gitignored payload around it. The scaffold
6
+ carries no API key, no user id, and no per-key inventory, so it is safe to
7
+ commit; only the generated slug packages / manifest / agent indexes are ignored.
8
+
9
+ This module owns the static scaffold text and the set of names a generated slug
10
+ directory may never take (because, as a directory under `src/parse_apis/`, the
11
+ name would shadow or be confused with a package-level scaffold/generated
12
+ member). Reservation is compared case-insensitively so it also holds on
13
+ case-insensitive filesystems (macOS/APFS, Windows).
14
+ """
15
+ from __future__ import annotations
16
+
17
+ import keyword
18
+ import re
19
+ from pathlib import Path
20
+ from typing import List
21
+
22
+ # Runtime errors re-exported by the committed scaffold. Key-independent and
23
+ # runtime-owned, so they carry no per-key metadata and are safe to commit
24
+ # (define `__all__` in the committed scaffold, not "post-sync").
25
+ _REEXPORTED = [
26
+ "ParseError",
27
+ "AuthError",
28
+ "ForbiddenError",
29
+ "NotFoundError",
30
+ "BadRequestError",
31
+ "QuotaExceededError",
32
+ "RateLimitError",
33
+ "UpstreamError",
34
+ "PaginationError",
35
+ "PaginationLimitError",
36
+ "RequestMeta",
37
+ ]
38
+
39
+ # Case-folded names a generated slug directory may not take. Derived from the
40
+ # package-level scaffold members (`__init__.py`, `py.typed`) and the generated
41
+ # top-level artifacts (`_manifest.json`, `AGENTS.md`, `CLAUDE.md`) plus the
42
+ # runtime module names a reader would confuse with `parse_sdk._runtime` /
43
+ # `parse_sdk.config`. `__init__` is load-bearing — a `parse_apis/__init__/`
44
+ # directory is shadowed by the package initializer and becomes unimportable.
45
+ RESERVED_SLUGS = frozenset({
46
+ "__init__",
47
+ "__main__",
48
+ "py",
49
+ "py.typed",
50
+ "pyproject",
51
+ "_manifest",
52
+ "_runtime",
53
+ "_config",
54
+ "agents",
55
+ "claude",
56
+ })
57
+
58
+
59
+ def is_reserved_slug(name: str) -> bool:
60
+ """True if ``name`` collides (case-insensitively) with a package-level
61
+ scaffold/generated member and must be suffixed before use as a slug dir."""
62
+ return name.casefold() in RESERVED_SLUGS
63
+
64
+
65
+ _SLUG_UNSAFE = re.compile(r"[^0-9A-Za-z_]")
66
+
67
+
68
+ def safe_slug(name: str) -> str:
69
+ """A filesystem- and import-safe slug: a valid Python identifier.
70
+
71
+ A server slug is an arbitrary value used BOTH as a directory name under
72
+ ``src/parse_apis/`` AND as an import path (``parse_apis.<slug>``). A hostile
73
+ or malformed slug (``../../etc``, ``a/b``, ``.``, ``""``) must never escape
74
+ the package directory (a path-traversal that `rmtree`/`copytree` would then
75
+ act on — audit SEC-1) or break imports. Any character outside
76
+ ``[0-9A-Za-z_]`` is replaced with ``_``; a leading digit is prefixed; an
77
+ empty result falls back to ``"api"``. Reserved/collision handling is the
78
+ caller's job (see ``cli._assign_slugs``).
79
+ """
80
+ cleaned = _SLUG_UNSAFE.sub("_", name)
81
+ if not cleaned:
82
+ return "api"
83
+ if cleaned[0].isdigit():
84
+ cleaned = "_" + cleaned
85
+ # A slug that is a (hard) Python keyword (``class``, ``for``, ``from``, ...)
86
+ # is a valid identifier shape but ``from parse_apis.<slug> import`` is a
87
+ # SyntaxError — suffix it just like a reserved name. Soft keywords
88
+ # (``match``/``case``/``type``/``_``) are NOT suffixed: they are not reserved,
89
+ # so they are valid module names and import fine.
90
+ if keyword.iskeyword(cleaned):
91
+ cleaned = cleaned + "_"
92
+ return cleaned
93
+
94
+
95
+ def render_scaffold_init() -> str:
96
+ """The committed ``src/parse_apis/__init__.py``.
97
+
98
+ Importable before any slug exists (so installers have a valid dependency
99
+ target), re-exports the runtime errors by object identity, exposes no
100
+ credential writer, and gives a clear "run parse sync" diagnostic for
101
+ top-level helper access to a not-yet-generated slug.
102
+ """
103
+ names = ",\n ".join(_REEXPORTED)
104
+ all_list = ",\n ".join(f'"{n}"' for n in _REEXPORTED)
105
+ return f'''"""Parse typed APIs.
106
+
107
+ Generated, typed clients for your Parse APIs appear here as submodules after
108
+ `parse sync`:
109
+
110
+ from parse_apis.<slug> import <Root>
111
+
112
+ Runtime errors are re-exported from `parse_sdk` so callers can
113
+ `from parse_apis import RateLimitError` without importing the engine directly.
114
+ This file is the committed scaffold — `parse sync` only writes the generated
115
+ payload around it.
116
+ """
117
+ from __future__ import annotations
118
+
119
+ from parse_sdk import (
120
+ {names},
121
+ )
122
+
123
+ __all__ = [
124
+ {all_list},
125
+ ]
126
+
127
+
128
+ def __getattr__(name: str):
129
+ # Submodule imports (`from parse_apis.<slug> import ...`) are handled by the
130
+ # import system; this only fires for attribute access on the package itself.
131
+ raise AttributeError(
132
+ f"module 'parse_apis' has no attribute {{name!r}}. "
133
+ f"If {{name!r}} is one of your Parse APIs, run `uv run parse sync` to generate it."
134
+ )
135
+ '''
136
+
137
+
138
+ def render_scaffold_pyproject(parse_sdk_version: str) -> str:
139
+ """The committed ``parse_apis/pyproject.toml``.
140
+
141
+ Pins ``parse-sdk`` to the EXACT version the clients were generated against
142
+ because generated code subclasses the underscore-private
143
+ ``parse_sdk._runtime`` bases by name, so a loose range would let a fresh
144
+ `uv sync` pull a runtime the on-disk code was never generated for. `parse
145
+ init`/`sync` restamp this as the engine moves; regeneration is the upgrade
146
+ path.
147
+ """
148
+ return f'''[build-system]
149
+ requires = ["hatchling"]
150
+ build-backend = "hatchling.build"
151
+
152
+ [project]
153
+ name = "parse-apis"
154
+ version = "0.0.0"
155
+ requires-python = ">=3.10"
156
+ dependencies = [
157
+ "parse-sdk=={parse_sdk_version}",
158
+ ]
159
+
160
+ [tool.hatch.build.targets.wheel]
161
+ packages = ["src/parse_apis"]
162
+ '''
163
+
164
+
165
+ def render_gitignore_block() -> str:
166
+ """Deny-by-default ignore block for the consumer's ``.gitignore``.
167
+
168
+ Ignore EVERYTHING under the generated package and re-include only
169
+ the committed scaffold members, so any future top-level generated file is
170
+ ignored by construction — not by a hand-maintained per-filename allowlist
171
+ that leaks per-key data the day codegen adds an artifact.
172
+ """
173
+ return (
174
+ "# Parse SDK — generated payload is per-key (reveals your API inventory).\n"
175
+ "# Ignore everything under the generated package; keep only the committed scaffold.\n"
176
+ "parse_apis/src/parse_apis/*\n"
177
+ "!parse_apis/src/parse_apis/__init__.py\n"
178
+ "!parse_apis/src/parse_apis/py.typed\n"
179
+ ".parse/\n"
180
+ )
181
+
182
+
183
+ def render_workflow_core() -> str:
184
+ """Steady-state workflow block shared (SSOT) by the committed root pointer
185
+ and ``parse help``: the whoami/list/sync workflow, the import model, and the
186
+ ``limit=`` cost rule. No leading/trailing blank lines so each caller controls
187
+ its own surrounding spacing."""
188
+ return (
189
+ "Workflow (run from the project root):\n"
190
+ "- Check auth / base URL / host-trust: uv run parse whoami --json\n"
191
+ "- See which APIs your key can call: uv run parse list --json\n"
192
+ "- Generate / refresh typed clients: uv run parse sync --json\n"
193
+ " (machine-readable status: written / skipped / quarantined / failures)\n"
194
+ "\n"
195
+ "Import a client: from parse_apis.<slug> import <Root>\n"
196
+ "The exact <slug> and <Root> come from the generated tree, not `parse list`\n"
197
+ "(sync may sanitize/pin slugs): read `src/parse_apis/<slug>/README.md`, or\n"
198
+ "`uv run parse sync --json` (its `written[]` lists each slug + root).\n"
199
+ "\n"
200
+ "Before list/search calls, pass `limit=` unless exhaustive traversal is\n"
201
+ "explicitly requested — each page is a live, billed request."
202
+ )
203
+
204
+
205
+ def render_root_pointer() -> str:
206
+ """The committed top-level agent pointer (``parse_apis/AGENTS.md`` and the
207
+ byte-identical ``parse_apis/CLAUDE.md``).
208
+
209
+ The cold-start surface — the first file an agent reads when it opens
210
+ ``parse_apis/``, and (unlike the generated index) it survives a fresh clone.
211
+ It names the workflow (via ``render_workflow_core``), one fresh-clone
212
+ recovery line (the generated tree is absent until ``parse init``/``sync``;
213
+ routes to ``parse help``/``parse doctor``), the ``limit=`` cost rule, and
214
+ where the on-demand reference lives. Kept tiny so it costs ~O(1) context;
215
+ refreshed content-compared on every sync. No HTML sentinel.
216
+ """
217
+ return (
218
+ "# Parse APIs — start here\n"
219
+ "\n"
220
+ "This package holds typed clients for this project's Parse APIs, generated\n"
221
+ "by the `parse` CLI (installed editable — imports resolve from any cwd).\n"
222
+ "`parse sync` overwrites generated files; change an API at parse.bot, then\n"
223
+ "re-sync.\n"
224
+ "\n"
225
+ "Fresh checkout? The generated tree (clients, per-API READMEs/examples,\n"
226
+ "`src/parse_apis/CLAUDE.md`) does not exist until `uv run parse init` (or\n"
227
+ "`uv run parse login` + `uv run parse sync`); until then importing a generated\n"
228
+ "client raises ModuleNotFoundError. Guided setup: `uv run parse help`;\n"
229
+ "diagnose a broken install: `uv run parse doctor`.\n"
230
+ "\n"
231
+ f"{render_workflow_core()}\n"
232
+ "\n"
233
+ "Conventions + the API index (generated; appear after `parse sync`):\n"
234
+ "`src/parse_apis/CLAUDE.md`. Per-API (generated): `src/parse_apis/<slug>/README.md`\n"
235
+ "+ runnable `example.py`.\n"
236
+ )
237
+
238
+
239
+ def write_scaffold(project_dir: Path, parse_sdk_version: str) -> List[Path]:
240
+ """Write the committed scaffold under ``project_dir/parse_apis``.
241
+
242
+ Idempotent: overwrites the scaffold files (they are static modulo the
243
+ version stamp) and never touches generated payload. Returns the paths
244
+ written, sorted.
245
+ """
246
+ project_dir = Path(project_dir)
247
+ root = project_dir / "parse_apis"
248
+ pkg = root / "src" / "parse_apis"
249
+ pkg.mkdir(parents=True, exist_ok=True)
250
+
251
+ written: List[Path] = []
252
+
253
+ pyproject = root / "pyproject.toml"
254
+ pyproject.write_text(render_scaffold_pyproject(parse_sdk_version))
255
+ written.append(pyproject)
256
+
257
+ init = pkg / "__init__.py"
258
+ init.write_text(render_scaffold_init())
259
+ written.append(init)
260
+
261
+ py_typed = pkg / "py.typed"
262
+ py_typed.write_text("")
263
+ written.append(py_typed)
264
+
265
+ # Committed cold-start pointer at the package top (sibling to pyproject,
266
+ # outside the src/parse_apis gitignore glob → tracked). Byte-identical pair.
267
+ pointer = render_root_pointer()
268
+ for name in ("AGENTS.md", "CLAUDE.md"):
269
+ ptr = root / name
270
+ ptr.write_text(pointer)
271
+ written.append(ptr)
272
+
273
+ return sorted(written)
@@ -0,0 +1,177 @@
1
+ Metadata-Version: 2.4
2
+ Name: parse-sdk
3
+ Version: 0.1.0
4
+ Summary: Dynamic-yet-typed Python SDK for Parse APIs
5
+ Project-URL: Homepage, https://parse.bot
6
+ Project-URL: Changelog, https://pypi.org/project/parse-sdk/#history
7
+ Author-email: Parse <team@parse.bot>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: agents,api-client,codegen,parse,scraping,sdk
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.10
22
+ Requires-Dist: click>=8.1
23
+ Requires-Dist: httpx>=0.27
24
+ Requires-Dist: tomli>=1.1.0; python_version < '3.11'
25
+ Provides-Extra: dev
26
+ Requires-Dist: pyright>=1.1.408; extra == 'dev'
27
+ Requires-Dist: pytest>=8; extra == 'dev'
28
+ Requires-Dist: tomli>=2; (python_version < '3.11') and extra == 'dev'
29
+ Description-Content-Type: text/markdown
30
+
31
+ # parse-sdk
32
+
33
+ Typed Python SDK tooling for [Parse](https://parse.bot) APIs.
34
+
35
+ `parse-sdk` is the shared **runtime + CLI**. It generates a project-local
36
+ `parse_apis` package — a real, installed, editable dependency — that holds the
37
+ typed client for every API your key can call. Your application code imports from
38
+ `parse_apis`; `parse-sdk` provides the runtime bases and errors those clients use.
39
+
40
+ ## Quickstart
41
+
42
+ In a uv-managed project (`uv init` first if you don't have a `pyproject.toml`):
43
+
44
+ ```bash
45
+ uv add parse-sdk # installs the runtime + `parse` CLI into your project
46
+ uv run parse init # prompts for your API key, then scaffolds + syncs parse_apis
47
+ ```
48
+
49
+ Non-interactive (CI, agents, scripts): authenticate first with
50
+ `uv run parse login --api-key YOUR_KEY` (add `--base-url …` for a non-default
51
+ host), or export `PARSE_API_KEY` — then `uv run parse init` runs without prompts.
52
+
53
+ `parse init` is the one-time setup. It:
54
+
55
+ 1. ensures credentials (prompts and stores to `~/.config/parse/credentials`, or run `parse login` first);
56
+ 2. creates the committed `parse_apis` scaffold;
57
+ 3. records `parse_apis` as an **editable path dependency** (and a `[tool.uv.sources]` entry);
58
+ 4. appends a deny-by-default `.gitignore` block (commits the scaffold, ignores generated payload);
59
+ 5. migrates — or safely refuses — any legacy flat `parse_apis/` layout;
60
+ 6. runs the first `parse sync`.
61
+
62
+ Then use it:
63
+
64
+ ```python
65
+ from parse_apis.reddit_com_api import Reddit # generated, typed client (slugs look like <domain>_<tld>_api)
66
+ from parse_apis import RateLimitError # runtime errors, re-exported
67
+
68
+ reddit = Reddit() # picks up `parse login` credentials
69
+ try:
70
+ # Navigate from a constructible resource, with a bounded fetch:
71
+ for post in reddit.subreddit("smallbusiness").search_posts(query="hiring", limit=10):
72
+ print(post.title)
73
+ except RateLimitError:
74
+ ...
75
+ ```
76
+
77
+ (The exact methods are generated from *your* API's spec — `parse_apis/<slug>/README.md`
78
+ and `example.py` document each client's real surface.)
79
+
80
+ ```bash
81
+ uv run python app.py # run your app in the project environment
82
+ uv run parse sync # later: refresh after you change APIs in Parse
83
+ ```
84
+
85
+ ## Running commands (`uv run` vs. activation)
86
+
87
+ `uv add parse-sdk` installs the `parse` console script into your project's `.venv`,
88
+ which isn't on your shell `PATH` by default. Two equivalent ways to reach it:
89
+
90
+ - **`uv run parse <cmd>`** — runs the venv's `parse` with no activation, auto-syncing first. (Recommended.)
91
+ - **`source .venv/bin/activate`** then `parse <cmd>` directly.
92
+
93
+ Prefer one of these over a global `uv tool install parse-sdk`: codegen must run with
94
+ the **same** pinned `parse-sdk` your project runs against (see *Versioning* below), and a
95
+ global copy can drift out of sync. Your end users running their *app* never invoke `parse` —
96
+ they just `import parse_apis`.
97
+
98
+ ## On-disk layout
99
+
100
+ ```text
101
+ parse_apis/
102
+ pyproject.toml # committed: name="parse-apis", pinned parse-sdk==X
103
+ src/parse_apis/
104
+ __init__.py # committed scaffold — re-exports runtime errors
105
+ py.typed # committed
106
+ reddit/__init__.py # generated (gitignored)
107
+ _manifest.json # generated (gitignored)
108
+ AGENTS.md CLAUDE.md # generated cross-API index (gitignored)
109
+ ```
110
+
111
+ Commit the three scaffold files; the generated payload is per-key (it reveals your API
112
+ inventory) and stays gitignored. `parse sync` builds the next payload in a staging tree,
113
+ self-tests it (secret scan, import-model, no-stale-docs), and promotes it with an atomic
114
+ directory swap — a failed sync never leaves broken or secret-bearing files in your project.
115
+
116
+ ## Import model
117
+
118
+ - Application code imports generated clients from `parse_apis.<slug>`.
119
+ - Runtime errors/base types are re-exported from `parse_apis` (sourced from `parse_sdk`).
120
+ - Because `parse_apis` is an **installed** editable package, imports resolve from any
121
+ directory — no `sys.path` or editor `extraPaths` tricks.
122
+ - Generated files are project-local and differ per Parse API key.
123
+
124
+ ## Fresh clone & CI (post-publish)
125
+
126
+ ```bash
127
+ uv sync # installs deps incl. the editable parse_apis scaffold
128
+ uv run parse sync # regenerate the per-key payload
129
+ uv run pytest && uv run pyright # pyright must run against the PROJECT env —
130
+ # add both as dev deps (`uv add --dev pytest pyright`);
131
+ # a bare/global `pyright` can't resolve parse_apis
132
+ ```
133
+
134
+ The committed scaffold is a valid dependency target before any slugs exist, so `uv sync`
135
+ succeeds on a clean checkout.
136
+
137
+ ## CLI
138
+
139
+ | Command | What it does |
140
+ | --- | --- |
141
+ | `parse login` | Save API key + base URL to local credentials. No project changes. |
142
+ | `parse init` | One-time: ensure creds, scaffold `parse_apis`, record deps + gitignore, first sync. |
143
+ | `parse sync` | Regenerate the typed payload into `parse_apis/src/parse_apis` (staged + atomic). |
144
+ | `parse clean` | Remove generated payload; keep the committed scaffold. |
145
+ | `parse list` | Print the APIs the current key can call (no generation). |
146
+ | `parse whoami` | Show the current key + base URL. |
147
+
148
+ Run `parse <cmd> --help` for full per-command help.
149
+
150
+ ## Versioning
151
+
152
+ `parse_apis/pyproject.toml` pins the **exact** `parse-sdk` it was generated against — generated
153
+ code subclasses the runtime by name. After upgrading `parse-sdk`, **re-run `parse sync`** to
154
+ regenerate against the new runtime; `init`/`sync` restamp the pin.
155
+
156
+ ## Env vars
157
+
158
+ | Var | Default | Notes |
159
+ | --- | --- | --- |
160
+ | `PARSE_API_KEY` | – | Auth for real requests (or use `parse login`). |
161
+ | `PARSE_API_BASE_URL` | `https://api.parse.bot` | Locally: `http://localhost:8001`. |
162
+
163
+ ## Changelog
164
+
165
+ Release history is on the PyPI project page:
166
+ <https://pypi.org/project/parse-sdk/#history>.
167
+
168
+ ## Security
169
+
170
+ To report a security issue, email **security@parse.bot** — please do not open
171
+ a public issue.
172
+
173
+ ## License
174
+
175
+ [MIT](LICENSE) © 2026 Parse. The license covers the `parse-sdk` runtime,
176
+ codegen, and CLI; use of the Parse API/service is governed separately by
177
+ Parse's terms.
@@ -0,0 +1,26 @@
1
+ parse_sdk/__init__.py,sha256=cUCmf5MtpnAf14LKuwZXCnADVYxg1QwH1FWz3EesWmg,1434
2
+ parse_sdk/_labels.py,sha256=pX9ZQ7ZyOo1f3ZIKOqrbH1_H54XO-0s-ZBsjJKw6cSU,1877
3
+ parse_sdk/_oauth.py,sha256=HifVNsECBu1ZLx6da6hHMz5odcOTsAIVynn5_g1M_U4,13427
4
+ parse_sdk/_project.py,sha256=ivMCJ857OMjjAsGXdkewa0cDfKzljlrrGikshTrlwjg,8160
5
+ parse_sdk/_runtime.py,sha256=6E5ekavCouRUFAs3fxaquIvvpjCOz9VflQ9wZsGmoLk,107463
6
+ parse_sdk/_sanitize.py,sha256=kp6v_QiE60KMZZEfzqOSZS6D3RrMzipa9RGps6ZXeS0,788
7
+ parse_sdk/_sync.py,sha256=-uT_iYxsstEcOudP9XLD5CtB_keCXWHqBSQ_QELJfp0,42928
8
+ parse_sdk/checks.py,sha256=Cqsv_cnf118YC5gHRVy_XE65q6MOPVNLpf_xhrsIflg,31375
9
+ parse_sdk/cli.py,sha256=iiJDfqjmgxCIbWwxZ-wwbi6ItDFCnNciaxxXuGwL1xg,79440
10
+ parse_sdk/cli_help.py,sha256=tWuzg49Yphu1qQo47y8UOixYoil_bFOYGMY174w5h5k,4274
11
+ parse_sdk/codegen_reconcile.py,sha256=6_vRNX-Q4WuuUd3dk4QUi5IgiGT9fxU9C3L9hHAjPQ4,7961
12
+ parse_sdk/codegen_v2.py,sha256=MPC_XAfQFK0b8RLBZL1oKx1vnUHhbGubykUegNMASjg,169864
13
+ parse_sdk/config.py,sha256=5R2h-WNYp5gJKZ1L_dXS7Ex_eo0FxHTTBz127o7MuoU,16064
14
+ parse_sdk/docgen.py,sha256=qD6Zqr5TsWNwIa19auO-7C04s2aPvVsFuJpsmHvvH-A,29702
15
+ parse_sdk/doctor.py,sha256=6J7lA2_S1IF1jYII_PI94PCPU386UfU6x1rBagYC3Ns,14509
16
+ parse_sdk/migrate.py,sha256=VHATy8TTYijVwpZdM4Gt7z-SBzVU7HTcIb5sALRQZ3M,8998
17
+ parse_sdk/preview.py,sha256=6v10VM-WYFZ-slWrFQ826zo_TcMy8Z1xk-1DLYYAW-8,26595
18
+ parse_sdk/resource_surface.py,sha256=zrGlNxxLXkGBLVopDxRipYpMVZO6ORSRCZ8lRiQOXqQ,9682
19
+ parse_sdk/sample_gate.py,sha256=cnVa70vvtzy-CHcmKJNdn76Ob2sPYW2NalXZbVdbCkI,10757
20
+ parse_sdk/scaffold.py,sha256=8kh9ROdcVmPA6rX2lyYP2f_xPOC4DHxWpDECESh_jIo,10728
21
+ parse_sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
+ parse_sdk-0.1.0.dist-info/METADATA,sha256=sEwJ_1WpSVnxCNPCtK8H40lFkf7M-rXKIBdYqmo-XVY,7356
23
+ parse_sdk-0.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
24
+ parse_sdk-0.1.0.dist-info/entry_points.txt,sha256=NmdGaxEvLmPom9KsbpKXv5vZ3PrVeYLuT88Ka3YcI-s,44
25
+ parse_sdk-0.1.0.dist-info/licenses/LICENSE,sha256=bw_tWB6oxPxx0sPmtPQocG-4JH-_f2jjI3GhmapEQ2o,1062
26
+ parse_sdk-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.30.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ parse = parse_sdk.cli:cli
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Parse
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.