toapi 2.1.2__tar.gz → 2.2.0__tar.gz

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.
Files changed (75) hide show
  1. toapi-2.2.0/.github/workflows/ci.yml +29 -0
  2. toapi-2.2.0/.gitignore +105 -0
  3. toapi-2.2.0/.omc/project-memory.json +174 -0
  4. toapi-2.2.0/.omc/state/agent-replay-86181004-c476-471f-90d2-1c64e40fb749.jsonl +4 -0
  5. toapi-2.2.0/.omc/state/hud-stdin-cache.json +1 -0
  6. toapi-2.2.0/.omc/state/idle-notif-cooldown.json +5 -0
  7. toapi-2.2.0/.omc/state/last-tool-error.json +7 -0
  8. toapi-2.2.0/.omc/state/mission-state.json +79 -0
  9. toapi-2.2.0/.omc/state/sessions/86181004-c476-471f-90d2-1c64e40fb749/hud-state.json +6 -0
  10. toapi-2.2.0/.omc/state/subagent-tracking.json +26 -0
  11. toapi-2.2.0/.pre-commit-config.yaml +7 -0
  12. toapi-2.2.0/LICENSE +21 -0
  13. toapi-2.2.0/PKG-INFO +117 -0
  14. {toapi-2.1.2 → toapi-2.2.0}/README.md +0 -12
  15. toapi-2.2.0/docs/CNAME +1 -0
  16. toapi-2.2.0/docs/about/contributing.md +62 -0
  17. toapi-2.2.0/docs/about/installation.md +86 -0
  18. toapi-2.2.0/docs/about/release-notes.md +32 -0
  19. toapi-2.2.0/docs/articles/index.md +0 -0
  20. toapi-2.2.0/docs/articles/release.md +96 -0
  21. toapi-2.2.0/docs/diagram.png +0 -0
  22. toapi-2.2.0/docs/imgs/introducing-1.png +0 -0
  23. toapi-2.2.0/docs/imgs/introducing-2.png +0 -0
  24. toapi-2.2.0/docs/imgs/introducing-3.png +0 -0
  25. toapi-2.2.0/docs/imgs/introducing-4.png +0 -0
  26. toapi-2.2.0/docs/imgs/runinglog.png +0 -0
  27. toapi-2.2.0/docs/imgs/runningitems.png +0 -0
  28. toapi-2.2.0/docs/imgs/runningresult.png +0 -0
  29. toapi-2.2.0/docs/imgs/runningstatus.png +0 -0
  30. toapi-2.2.0/docs/imgs/step-0-1.png +0 -0
  31. toapi-2.2.0/docs/index.md +227 -0
  32. toapi-2.2.0/docs/logo.png +0 -0
  33. toapi-2.2.0/docs/quickstart.md +0 -0
  34. toapi-2.2.0/docs/topics/api.md +90 -0
  35. toapi-2.2.0/docs/topics/cache.md +136 -0
  36. toapi-2.2.0/docs/topics/item.md +45 -0
  37. toapi-2.2.0/docs/topics/selector.md +57 -0
  38. toapi-2.2.0/docs/topics/settings.md +48 -0
  39. toapi-2.2.0/docs/topics/storage.md +67 -0
  40. toapi-2.2.0/docs/tutorials/introducing.md +28 -0
  41. toapi-2.2.0/docs/tutorials/step0-creating-new-project.md +41 -0
  42. toapi-2.2.0/docs/tutorials/step1-global-settings.md +39 -0
  43. toapi-2.2.0/docs/tutorials/step2-redis.md +48 -0
  44. toapi-2.2.0/docs/tutorials/step3-sqlite3.md +50 -0
  45. toapi-2.2.0/docs/tutorials/step4-defining-items.md +61 -0
  46. toapi-2.2.0/docs/tutorials/step5-deploy.md +95 -0
  47. toapi-2.2.0/examples/click/app.py +14 -0
  48. toapi-2.2.0/examples/click/static/main.js +0 -0
  49. toapi-2.2.0/examples/click/templates/index.html +75 -0
  50. toapi-2.2.0/examples/hackernews_page.py +32 -0
  51. toapi-2.2.0/mkdocs.yml +56 -0
  52. toapi-2.2.0/pyproject.toml +58 -0
  53. toapi-2.2.0/tests/test_toapi.py +55 -0
  54. toapi-2.2.0/toapi/__init__.py +7 -0
  55. {toapi-2.1.2 → toapi-2.2.0}/toapi/api.py +38 -33
  56. toapi-2.2.0/toapi/cli.py +11 -0
  57. {toapi-2.1.2 → toapi-2.2.0}/toapi/item.py +3 -4
  58. {toapi-2.1.2 → toapi-2.2.0}/toapi/log.py +4 -4
  59. toapi-2.2.0/uv.lock +1434 -0
  60. toapi-2.1.2/MANIFEST.in +0 -2
  61. toapi-2.1.2/PKG-INFO +0 -14
  62. toapi-2.1.2/requirements.txt +0 -21
  63. toapi-2.1.2/setup.cfg +0 -13
  64. toapi-2.1.2/setup.py +0 -44
  65. toapi-2.1.2/tests/test_toapi.py +0 -51
  66. toapi-2.1.2/toapi/__init__.py +0 -4
  67. toapi-2.1.2/toapi/cli.py +0 -11
  68. toapi-2.1.2/toapi.egg-info/PKG-INFO +0 -14
  69. toapi-2.1.2/toapi.egg-info/SOURCES.txt +0 -19
  70. toapi-2.1.2/toapi.egg-info/dependency_links.txt +0 -1
  71. toapi-2.1.2/toapi.egg-info/entry_points.txt +0 -3
  72. toapi-2.1.2/toapi.egg-info/not-zip-safe +0 -1
  73. toapi-2.1.2/toapi.egg-info/requires.txt +0 -7
  74. toapi-2.1.2/toapi.egg-info/top_level.txt +0 -1
  75. /toapi-2.1.2/LICENSE → /toapi-2.2.0/docs/about/license.md +0 -0
@@ -0,0 +1,29 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ python: ["3.10", "3.11", "3.12"]
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: astral-sh/setup-uv@v3
18
+ with:
19
+ enable-cache: true
20
+ - name: Set up Python
21
+ run: uv python install ${{ matrix.python }}
22
+ - name: Install dependencies
23
+ run: uv sync --all-extras --dev
24
+ - name: Lint
25
+ run: |
26
+ uv run ruff check .
27
+ uv run ruff format --check .
28
+ - name: Test
29
+ run: uv run pytest --cov=toapi
toapi-2.2.0/.gitignore ADDED
@@ -0,0 +1,105 @@
1
+ .idea/
2
+ # Byte-compiled / optimized / DLL files
3
+ __pycache__/
4
+ *.py[cod]
5
+ *$py.class
6
+ .html/
7
+ # C extensions
8
+ *.so
9
+ .pytest_cache/
10
+ # Distribution / packaging
11
+ .Python
12
+ env/
13
+ env27/
14
+ build/
15
+ develop-eggs/
16
+ dist/
17
+ downloads/
18
+ eggs/
19
+ .eggs/
20
+ lib/
21
+ lib64/
22
+ parts/
23
+ sdist/
24
+ var/
25
+ wheels/
26
+ *.egg-info/
27
+ .installed.cfg
28
+ *.egg
29
+
30
+ # PyInstaller
31
+ # Usually these files are written by a python script from a template
32
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
33
+ *.manifest
34
+ *.spec
35
+
36
+ # Installer logs
37
+ pip-log.txt
38
+ pip-delete-this-directory.txt
39
+
40
+ # Unit test / coverage reports
41
+ htmlcov/
42
+ .tox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ .hypothesis/
50
+
51
+ # Translations
52
+ *.mo
53
+ *.pot
54
+
55
+ # Django stuff:
56
+ *.log
57
+ local_settings.py
58
+
59
+ # Flask stuff:
60
+ instance/
61
+ .webassets-cache
62
+
63
+ # Scrapy stuff:
64
+ .scrapy
65
+
66
+ # Sphinx documentation
67
+ docs/_build/
68
+
69
+ # PyBuilder
70
+ target/
71
+
72
+ # Jupyter Notebook
73
+ .ipynb_checkpoints
74
+
75
+ # pyenv
76
+ .python-version
77
+
78
+ # celery beat schedule file
79
+ celerybeat-schedule
80
+
81
+ # SageMath parsed files
82
+ *.sage.py
83
+
84
+ # dotenv
85
+ .env
86
+
87
+ # virtualenv
88
+ .venv
89
+ venv/
90
+ ENV/
91
+
92
+ # Spyder project settings
93
+ .spyderproject
94
+ .spyproject
95
+
96
+ # Rope project settings
97
+ .ropeproject
98
+
99
+ # mkdocs documentation
100
+ /site
101
+
102
+ # mypy
103
+ .mypy_cache/
104
+ /tests/data.sqlite
105
+ /examples/toapi-pic/data.sqlite
@@ -0,0 +1,174 @@
1
+ {
2
+ "version": "1.0.0",
3
+ "lastScanned": 1779434703584,
4
+ "projectRoot": "/Users/elliot/Documents/Code/toapi",
5
+ "techStack": {
6
+ "languages": [
7
+ {
8
+ "name": "Python",
9
+ "version": "^3.8",
10
+ "confidence": "high",
11
+ "markers": [
12
+ "pyproject.toml"
13
+ ]
14
+ }
15
+ ],
16
+ "frameworks": [],
17
+ "packageManager": "poetry",
18
+ "runtime": null
19
+ },
20
+ "build": {
21
+ "buildCommand": null,
22
+ "testCommand": "pytest",
23
+ "lintCommand": "ruff check",
24
+ "devCommand": null,
25
+ "scripts": {}
26
+ },
27
+ "conventions": {
28
+ "namingStyle": null,
29
+ "importStyle": null,
30
+ "testPattern": null,
31
+ "fileOrganization": null
32
+ },
33
+ "structure": {
34
+ "isMonorepo": false,
35
+ "workspaces": [],
36
+ "mainDirectories": [
37
+ "docs",
38
+ "examples",
39
+ "tests"
40
+ ],
41
+ "gitBranches": {
42
+ "defaultBranch": "master",
43
+ "branchingStrategy": null
44
+ }
45
+ },
46
+ "customNotes": [],
47
+ "directoryMap": {
48
+ "docs": {
49
+ "path": "docs",
50
+ "purpose": "Documentation",
51
+ "fileCount": 5,
52
+ "lastAccessed": 1779434703569,
53
+ "keyFiles": [
54
+ "CNAME",
55
+ "diagram.png",
56
+ "index.md",
57
+ "logo.png",
58
+ "quickstart.md"
59
+ ]
60
+ },
61
+ "examples": {
62
+ "path": "examples",
63
+ "purpose": "Example code",
64
+ "fileCount": 1,
65
+ "lastAccessed": 1779434703569,
66
+ "keyFiles": [
67
+ "hackernews_page.py"
68
+ ]
69
+ },
70
+ "tests": {
71
+ "path": "tests",
72
+ "purpose": "Test files",
73
+ "fileCount": 1,
74
+ "lastAccessed": 1779434703569,
75
+ "keyFiles": [
76
+ "test_toapi.py"
77
+ ]
78
+ },
79
+ "toapi": {
80
+ "path": "toapi",
81
+ "purpose": null,
82
+ "fileCount": 5,
83
+ "lastAccessed": 1779434703570,
84
+ "keyFiles": [
85
+ "__init__.py",
86
+ "api.py",
87
+ "cli.py",
88
+ "item.py",
89
+ "log.py"
90
+ ]
91
+ }
92
+ },
93
+ "hotPaths": [
94
+ {
95
+ "path": "pyproject.toml",
96
+ "accessCount": 7,
97
+ "lastAccessed": 1779435734082,
98
+ "type": "file"
99
+ },
100
+ {
101
+ "path": "toapi/api.py",
102
+ "accessCount": 4,
103
+ "lastAccessed": 1779435005253,
104
+ "type": "file"
105
+ },
106
+ {
107
+ "path": "toapi/__init__.py",
108
+ "accessCount": 4,
109
+ "lastAccessed": 1779435605203,
110
+ "type": "file"
111
+ },
112
+ {
113
+ "path": ".pre-commit-config.yaml",
114
+ "accessCount": 3,
115
+ "lastAccessed": 1779434999306,
116
+ "type": "file"
117
+ },
118
+ {
119
+ "path": "toapi/item.py",
120
+ "accessCount": 3,
121
+ "lastAccessed": 1779435568476,
122
+ "type": "file"
123
+ },
124
+ {
125
+ "path": ".travis.yml",
126
+ "accessCount": 2,
127
+ "lastAccessed": 1779434902331,
128
+ "type": "file"
129
+ },
130
+ {
131
+ "path": ".flake8",
132
+ "accessCount": 2,
133
+ "lastAccessed": 1779434903048,
134
+ "type": "file"
135
+ },
136
+ {
137
+ "path": "toapi/cli.py",
138
+ "accessCount": 2,
139
+ "lastAccessed": 1779435596581,
140
+ "type": "file"
141
+ },
142
+ {
143
+ "path": "README.md",
144
+ "accessCount": 1,
145
+ "lastAccessed": 1779434789416,
146
+ "type": "file"
147
+ },
148
+ {
149
+ "path": "toapi/log.py",
150
+ "accessCount": 1,
151
+ "lastAccessed": 1779434808975,
152
+ "type": "file"
153
+ },
154
+ {
155
+ "path": "poetry.lock",
156
+ "accessCount": 1,
157
+ "lastAccessed": 1779434809861,
158
+ "type": "file"
159
+ },
160
+ {
161
+ "path": "tests/test_toapi.py",
162
+ "accessCount": 1,
163
+ "lastAccessed": 1779434815385,
164
+ "type": "file"
165
+ },
166
+ {
167
+ "path": "LICENSE",
168
+ "accessCount": 1,
169
+ "lastAccessed": 1779434833764,
170
+ "type": "file"
171
+ }
172
+ ],
173
+ "userDirectives": []
174
+ }
@@ -0,0 +1,4 @@
1
+ {"t":0,"agent":"aae2d16","agent_type":"Explore","event":"agent_start","parent_mode":"none"}
2
+ {"t":0,"agent":"a324b3e","agent_type":"Explore","event":"agent_start","parent_mode":"none"}
3
+ {"t":0,"agent":"a324b3e","agent_type":"Explore","event":"agent_stop","success":true,"duration_ms":87042}
4
+ {"t":0,"agent":"aae2d16","agent_type":"Explore","event":"agent_stop","success":true,"duration_ms":105179}
@@ -0,0 +1 @@
1
+ {"session_id":"86181004-c476-471f-90d2-1c64e40fb749","transcript_path":"/Users/elliot/.claude/projects/-Users-elliot-Documents-Code-toapi/86181004-c476-471f-90d2-1c64e40fb749.jsonl","cwd":"/Users/elliot/Documents/Code/toapi","effort":{"level":"xhigh"},"session_name":"modernize-toapi-dependencies","model":{"id":"claude-opus-4-7[1m]","display_name":"Opus 4.7 (1M context)"},"workspace":{"current_dir":"/Users/elliot/Documents/Code/toapi","project_dir":"/Users/elliot/Documents/Code/toapi","added_dirs":[]},"version":"2.1.144","output_style":{"name":"default"},"cost":{"total_cost_usd":3.1557453,"total_duration_ms":1033890,"total_api_duration_ms":569612,"total_lines_added":260,"total_lines_removed":99},"context_window":{"total_input_tokens":82733,"total_output_tokens":961,"context_window_size":1000000,"current_usage":{"input_tokens":6,"output_tokens":961,"cache_creation_input_tokens":1867,"cache_read_input_tokens":80860},"used_percentage":8,"remaining_percentage":92},"exceeds_200k_tokens":false,"fast_mode":false,"thinking":{"enabled":true},"rate_limits":{"five_hour":{"used_percentage":34,"resets_at":1779440400},"seven_day":{"used_percentage":80,"resets_at":1779570000}}}
@@ -0,0 +1,5 @@
1
+ {
2
+ "lastSentAt": "2026-05-22T07:40:42.602Z",
3
+ "repoSignature": "{\"repo\":\"elliotgao2/toapi\",\"headSha\":\"6ae043cab28d16beb0be1bd9b1cd0fdc9c19baa6\",\"dirty\":true,\"openPrNumbers\":[127,135,138],\"openIssueNumbers\":[129,130,131,132,134,139],\"failingRunIds\":[24379413758,25783406210]}",
4
+ "backlogZero": false
5
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "tool_name": "Bash",
3
+ "tool_input_preview": "{\"command\":\"ls /opt/homebrew/bin/python3* /usr/local/bin/python3* /opt/nanobrew/prefix/bin/python3* 2>/dev/null; echo \\\"---\\\"; ls /opt/homebrew/opt 2>/dev/null | grep -i python; echo \\\"---\\\"; which py...",
4
+ "error": "Exit code 1\n/opt/homebrew/bin/python3\n/opt/homebrew/bin/python3-config\n/opt/homebrew/bin/python3.13\n/opt/homebrew/bin/python3.13-config\n/opt/homebrew/bin/python3.14\n/opt/homebrew/bin/python3.14-config\n/opt/nanobrew/prefix/bin/python3\n/opt/nanobrew/prefix/bin/python3-config\n/opt/nanobrew/prefix/bin/python3.13\n/opt/nanobrew/prefix/bin/python3.13-config\n/opt/nanobrew/prefix/bin/python3.14\n/opt/nanobrew/prefix/bin/python3.14-config\n/usr/local/bin/python3\n/usr/local/bin/python3-config\n/usr/local/bin/...",
5
+ "timestamp": "2026-05-22T07:30:24.107Z",
6
+ "retry_count": 2
7
+ }
@@ -0,0 +1,79 @@
1
+ {
2
+ "updatedAt": "2026-05-22T07:27:37.778Z",
3
+ "missions": [
4
+ {
5
+ "id": "session:86181004-c476-471f-90d2-1c64e40fb749:none",
6
+ "source": "session",
7
+ "name": "none",
8
+ "objective": "Session mission",
9
+ "createdAt": "2026-05-22T07:25:52.599Z",
10
+ "updatedAt": "2026-05-22T07:27:37.778Z",
11
+ "status": "done",
12
+ "workerCount": 2,
13
+ "taskCounts": {
14
+ "total": 2,
15
+ "pending": 0,
16
+ "blocked": 0,
17
+ "inProgress": 0,
18
+ "completed": 2,
19
+ "failed": 0
20
+ },
21
+ "agents": [
22
+ {
23
+ "name": "Explore:aae2d16",
24
+ "role": "Explore",
25
+ "ownership": "aae2d161a0ef7e8e0",
26
+ "status": "done",
27
+ "currentStep": null,
28
+ "latestUpdate": "completed",
29
+ "completedSummary": null,
30
+ "updatedAt": "2026-05-22T07:27:37.778Z"
31
+ },
32
+ {
33
+ "name": "Explore:a324b3e",
34
+ "role": "Explore",
35
+ "ownership": "a324b3eaed6783abe",
36
+ "status": "done",
37
+ "currentStep": null,
38
+ "latestUpdate": "completed",
39
+ "completedSummary": null,
40
+ "updatedAt": "2026-05-22T07:27:37.526Z"
41
+ }
42
+ ],
43
+ "timeline": [
44
+ {
45
+ "id": "session-start:aae2d161a0ef7e8e0:2026-05-22T07:25:52.599Z",
46
+ "at": "2026-05-22T07:25:52.599Z",
47
+ "kind": "update",
48
+ "agent": "Explore:aae2d16",
49
+ "detail": "started Explore:aae2d16",
50
+ "sourceKey": "session-start:aae2d161a0ef7e8e0"
51
+ },
52
+ {
53
+ "id": "session-start:a324b3eaed6783abe:2026-05-22T07:26:10.484Z",
54
+ "at": "2026-05-22T07:26:10.484Z",
55
+ "kind": "update",
56
+ "agent": "Explore:a324b3e",
57
+ "detail": "started Explore:a324b3e",
58
+ "sourceKey": "session-start:a324b3eaed6783abe"
59
+ },
60
+ {
61
+ "id": "session-stop:a324b3eaed6783abe:2026-05-22T07:27:37.526Z",
62
+ "at": "2026-05-22T07:27:37.526Z",
63
+ "kind": "completion",
64
+ "agent": "Explore:a324b3e",
65
+ "detail": "completed",
66
+ "sourceKey": "session-stop:a324b3eaed6783abe"
67
+ },
68
+ {
69
+ "id": "session-stop:aae2d161a0ef7e8e0:2026-05-22T07:27:37.778Z",
70
+ "at": "2026-05-22T07:27:37.778Z",
71
+ "kind": "completion",
72
+ "agent": "Explore:aae2d16",
73
+ "detail": "completed",
74
+ "sourceKey": "session-stop:aae2d161a0ef7e8e0"
75
+ }
76
+ ]
77
+ }
78
+ ]
79
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "timestamp": "2026-05-22T07:25:44.780Z",
3
+ "backgroundTasks": [],
4
+ "sessionStartTimestamp": "2026-05-22T07:25:03.600Z",
5
+ "sessionId": "86181004-c476-471f-90d2-1c64e40fb749"
6
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "agents": [
3
+ {
4
+ "agent_id": "aae2d161a0ef7e8e0",
5
+ "agent_type": "Explore",
6
+ "started_at": "2026-05-22T07:25:52.599Z",
7
+ "parent_mode": "none",
8
+ "status": "completed",
9
+ "completed_at": "2026-05-22T07:27:37.778Z",
10
+ "duration_ms": 105179
11
+ },
12
+ {
13
+ "agent_id": "a324b3eaed6783abe",
14
+ "agent_type": "Explore",
15
+ "started_at": "2026-05-22T07:26:10.484Z",
16
+ "parent_mode": "none",
17
+ "status": "completed",
18
+ "completed_at": "2026-05-22T07:27:37.526Z",
19
+ "duration_ms": 87042
20
+ }
21
+ ],
22
+ "total_spawned": 2,
23
+ "total_completed": 2,
24
+ "total_failed": 0,
25
+ "last_updated": "2026-05-22T07:27:37.880Z"
26
+ }
@@ -0,0 +1,7 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.6.9
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ - id: ruff-format
toapi-2.2.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Elliot Gao
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.
toapi-2.2.0/PKG-INFO ADDED
@@ -0,0 +1,117 @@
1
+ Metadata-Version: 2.4
2
+ Name: toapi
3
+ Version: 2.2.0
4
+ Summary: Every web site provides APIs.
5
+ Project-URL: homepage, https://github.com/gaojiuli/toapi
6
+ Project-URL: repository, https://github.com/gaojiuli/toapi
7
+ Project-URL: documentation, https://gaojiuli.github.io/toapi/
8
+ Author-email: Elliot Gao <gaojiuli@gmail.com>
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Requires-Python: >=3.10
12
+ Requires-Dist: charset-normalizer>=3.3
13
+ Requires-Dist: click>=8.1
14
+ Requires-Dist: colorama>=0.4.6
15
+ Requires-Dist: cssselect>=1.2
16
+ Requires-Dist: flask>=3.0
17
+ Requires-Dist: htmlfetcher>=0.0.6
18
+ Requires-Dist: htmlparsing>=0.1.5
19
+ Requires-Dist: requests>=2.32
20
+ Description-Content-Type: text/markdown
21
+
22
+ # Toapi
23
+
24
+ [![Build](https://travis-ci.org/gaojiuli/toapi.svg?branch=master)](https://travis-ci.org/gaojiuli/toapi)
25
+ [![Coverage](https://codecov.io/gh/gaojiuli/toapi/branch/master/graph/badge.svg)](https://codecov.io/gh/gaojiuli/toapi)
26
+ [![Python](https://img.shields.io/pypi/pyversions/toapi.svg)](https://pypi.python.org/pypi/toapi/)
27
+ [![Version](https://img.shields.io/pypi/v/toapi.svg)](https://pypi.python.org/pypi/toapi/)
28
+ [![License](https://img.shields.io/pypi/l/toapi.svg)](https://pypi.python.org/pypi/toapi/)
29
+
30
+ ## Overview
31
+
32
+ Toapi give you the ability to make every web site provides APIs.
33
+
34
+ - v1.0.0 Documentation: [http://www.toapi.org](http://www.toapi.org)
35
+ - Awesome: [https://github.com/toapi/awesome-toapi](https://github.com/toapi/awesome-toapi)
36
+ - Organization: [https://github.com/toapi](https://github.com/toapi)
37
+
38
+ ## Features
39
+
40
+ - Automatic converting HTML web site to API service.
41
+ - Automatic caching every page of source site.
42
+ - Automatic caching every request.
43
+ - Support merging multiple web sites into one API service.
44
+
45
+ ## Get Started
46
+
47
+ ### Installation
48
+
49
+ ```text
50
+ $ pip install toapi
51
+ ```
52
+
53
+ ### Usage
54
+
55
+ create `app.py` and copy the code:
56
+
57
+ ```python
58
+ from flask import request
59
+ from htmlparsing import Attr, Text
60
+ from toapi import Api, Item
61
+
62
+ api = Api()
63
+
64
+
65
+ @api.site('https://news.ycombinator.com')
66
+ @api.list('.athing')
67
+ @api.route('/posts?page={page}', '/news?p={page}')
68
+ @api.route('/posts', '/news?p=1')
69
+ class Post(Item):
70
+ url = Attr('.storylink', 'href')
71
+ title = Text('.storylink')
72
+
73
+
74
+ @api.site('https://news.ycombinator.com')
75
+ @api.route('/posts?page={page}', '/news?p={page}')
76
+ @api.route('/posts', '/news?p=1')
77
+ class Page(Item):
78
+ next_page = Attr('.morelink', 'href')
79
+
80
+ def clean_next_page(self, value):
81
+ return api.convert_string('/' + value, '/news?p={page}', request.host_url.strip('/') + '/posts?page={page}')
82
+
83
+
84
+ api.run(debug=True, host='0.0.0.0', port=5000)
85
+ ```
86
+
87
+ run `python app.py`
88
+
89
+ then open your browser and visit `http://127.0.0.1:5000/posts?page=1`
90
+
91
+ you will get the result like:
92
+
93
+ ```json
94
+ {
95
+ "Page": {
96
+ "next_page": "http://127.0.0.1:5000/posts?page=2"
97
+ },
98
+ "Post": [
99
+ {
100
+ "title": "Mathematicians Crack the Cursed Curve",
101
+ "url": "https://www.quantamagazine.org/mathematicians-crack-the-cursed-curve-20171207/"
102
+ },
103
+ {
104
+ "title": "Stuffing a Tesla Drivetrain into a 1981 Honda Accord",
105
+ "url": "https://jalopnik.com/this-glorious-madman-stuffed-a-p85-tesla-drivetrain-int-1823461909"
106
+ }
107
+ ]
108
+ }
109
+ ```
110
+
111
+
112
+ ## Contributing
113
+
114
+ Write code and test code and pull request.
115
+
116
+
117
+
@@ -6,17 +6,10 @@
6
6
  [![Version](https://img.shields.io/pypi/v/toapi.svg)](https://pypi.python.org/pypi/toapi/)
7
7
  [![License](https://img.shields.io/pypi/l/toapi.svg)](https://pypi.python.org/pypi/toapi/)
8
8
 
9
-
10
- ![Toapi](logo.png)
11
-
12
9
  ## Overview
13
10
 
14
11
  Toapi give you the ability to make every web site provides APIs.
15
12
 
16
- Version v2.0.0, Completely rewrote.
17
-
18
- More elegant. More pythonic
19
-
20
13
  - v1.0.0 Documentation: [http://www.toapi.org](http://www.toapi.org)
21
14
  - Awesome: [https://github.com/toapi/awesome-toapi](https://github.com/toapi/awesome-toapi)
22
15
  - Organization: [https://github.com/toapi](https://github.com/toapi)
@@ -34,8 +27,6 @@ More elegant. More pythonic
34
27
 
35
28
  ```text
36
29
  $ pip install toapi
37
- $ toapi -v
38
- toapi, version 2.0.0
39
30
  ```
40
31
 
41
32
  ### Usage
@@ -96,9 +87,6 @@ you will get the result like:
96
87
  }
97
88
  ```
98
89
 
99
- ## Todo
100
-
101
- 1. Visualization. Create toapi project in a web page by drag and drop.
102
90
 
103
91
  ## Contributing
104
92
 
toapi-2.2.0/docs/CNAME ADDED
@@ -0,0 +1 @@
1
+ www.toapi.org