pygitcode 0.1.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.
- pygitcode-0.1.0/LICENSE +21 -0
- pygitcode-0.1.0/PKG-INFO +249 -0
- pygitcode-0.1.0/README.md +209 -0
- pygitcode-0.1.0/pyproject.toml +128 -0
- pygitcode-0.1.0/setup.cfg +4 -0
- pygitcode-0.1.0/src/gitcode_cli/__init__.py +3 -0
- pygitcode-0.1.0/src/gitcode_cli/cli.py +44 -0
- pygitcode-0.1.0/src/gitcode_cli/cli_compat.py +116 -0
- pygitcode-0.1.0/src/gitcode_cli/client.py +71 -0
- pygitcode-0.1.0/src/gitcode_cli/commands/__init__.py +0 -0
- pygitcode-0.1.0/src/gitcode_cli/commands/auth.py +23 -0
- pygitcode-0.1.0/src/gitcode_cli/commands/issue.py +338 -0
- pygitcode-0.1.0/src/gitcode_cli/commands/pr.py +497 -0
- pygitcode-0.1.0/src/gitcode_cli/config.py +39 -0
- pygitcode-0.1.0/src/gitcode_cli/context.py +14 -0
- pygitcode-0.1.0/src/gitcode_cli/errors.py +23 -0
- pygitcode-0.1.0/src/gitcode_cli/formatters.py +163 -0
- pygitcode-0.1.0/src/gitcode_cli/repo.py +43 -0
- pygitcode-0.1.0/src/gitcode_cli/services/__init__.py +6 -0
- pygitcode-0.1.0/src/gitcode_cli/services/issues.py +33 -0
- pygitcode-0.1.0/src/gitcode_cli/services/pulls.py +51 -0
- pygitcode-0.1.0/src/gitcode_cli/utils.py +118 -0
- pygitcode-0.1.0/src/pygitcode.egg-info/PKG-INFO +249 -0
- pygitcode-0.1.0/src/pygitcode.egg-info/SOURCES.txt +26 -0
- pygitcode-0.1.0/src/pygitcode.egg-info/dependency_links.txt +1 -0
- pygitcode-0.1.0/src/pygitcode.egg-info/entry_points.txt +2 -0
- pygitcode-0.1.0/src/pygitcode.egg-info/requires.txt +12 -0
- pygitcode-0.1.0/src/pygitcode.egg-info/top_level.txt +1 -0
pygitcode-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 pygitcode contributors
|
|
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.
|
pygitcode-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pygitcode
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A CLI tool for GitCode (api.gitcode.com), modeled after GitHub CLI.
|
|
5
|
+
Author-email: codeasier <825770651@qq.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/yourusername/pygitcode
|
|
8
|
+
Project-URL: Documentation, https://github.com/yourusername/pygitcode#readme
|
|
9
|
+
Project-URL: Repository, https://github.com/yourusername/pygitcode.git
|
|
10
|
+
Project-URL: Issues, https://github.com/yourusername/pygitcode/issues
|
|
11
|
+
Keywords: gitcode,cli,git,api,vcs,developer-tools
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
23
|
+
Classifier: Topic :: Utilities
|
|
24
|
+
Classifier: Typing :: Typed
|
|
25
|
+
Requires-Python: >=3.9
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: click>=8.0
|
|
29
|
+
Requires-Dist: httpx>=0.24
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
32
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
33
|
+
Requires-Dist: pytest-mock>=3.14; extra == "dev"
|
|
34
|
+
Requires-Dist: respx>=0.21; extra == "dev"
|
|
35
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
36
|
+
Requires-Dist: black>=24.0; extra == "dev"
|
|
37
|
+
Requires-Dist: basedpyright>=1.19; extra == "dev"
|
|
38
|
+
Requires-Dist: pre-commit>=3.0; extra == "dev"
|
|
39
|
+
Dynamic: license-file
|
|
40
|
+
|
|
41
|
+
# pygitcode
|
|
42
|
+
|
|
43
|
+
> A CLI tool for [GitCode](https://gitcode.com/) (`api.gitcode.com`), modeled after GitHub CLI (`gh`).
|
|
44
|
+
|
|
45
|
+
[](https://pypi.org/project/pygitcode/)
|
|
46
|
+
[](https://pypi.org/project/pygitcode/)
|
|
47
|
+
[](https://github.com/yourusername/pygitcode/blob/main/LICENSE)
|
|
48
|
+
[](https://github.com/yourusername/pygitcode/actions)
|
|
49
|
+
|
|
50
|
+
## Installation
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install pygitcode
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
This exposes the `gc` command in your shell.
|
|
57
|
+
|
|
58
|
+
## Quick Start
|
|
59
|
+
|
|
60
|
+
### Authentication
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# Login with your GitCode personal access token
|
|
64
|
+
gc auth login
|
|
65
|
+
|
|
66
|
+
# Or set environment variable
|
|
67
|
+
export GC_TOKEN=your_token_here
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Issues
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# List issues (with filtering options)
|
|
74
|
+
gc issue list
|
|
75
|
+
gc issue list --state closed --author @me
|
|
76
|
+
gc issue list --label bug --label "help wanted"
|
|
77
|
+
gc issue list --web # Open in browser
|
|
78
|
+
|
|
79
|
+
# View an issue (with comments)
|
|
80
|
+
gc issue view 42
|
|
81
|
+
gc issue view 42 --comments
|
|
82
|
+
gc issue view 42 --web
|
|
83
|
+
|
|
84
|
+
# Create an issue
|
|
85
|
+
gc issue create -t "Bug report" -b "Something is broken"
|
|
86
|
+
gc issue create --web # Create in browser
|
|
87
|
+
|
|
88
|
+
# Edit an issue (add/remove labels, assignees)
|
|
89
|
+
gc issue edit 42 -t "Updated title"
|
|
90
|
+
gc issue edit 42 --add-label bug --remove-label "in progress"
|
|
91
|
+
gc issue edit 42 --add-assignee @me --remove-assignee otheruser
|
|
92
|
+
|
|
93
|
+
# Comment on an issue
|
|
94
|
+
gc issue comment 42 -b "Thanks for the report!"
|
|
95
|
+
gc issue comment 42 --editor # Use system editor
|
|
96
|
+
|
|
97
|
+
# Close / reopen / delete
|
|
98
|
+
gc issue close 42
|
|
99
|
+
gc issue reopen 42
|
|
100
|
+
gc issue delete 42
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Pull Requests
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
# List PRs (with filtering options)
|
|
107
|
+
gc pr list
|
|
108
|
+
gc pr list --state merged --author @me
|
|
109
|
+
gc pr list --base main --draft
|
|
110
|
+
gc pr list --web # Open in browser
|
|
111
|
+
|
|
112
|
+
# View a PR (identifier optional - infers from current branch)
|
|
113
|
+
gc pr view # View PR for current branch
|
|
114
|
+
gc pr view 42 # By number
|
|
115
|
+
gc pr view https://gitcode.com/owner/repo/pulls/42
|
|
116
|
+
gc pr view feature-branch
|
|
117
|
+
|
|
118
|
+
# Create a PR (auto-detects current branch and default base)
|
|
119
|
+
gc pr create -t "Add new feature"
|
|
120
|
+
|
|
121
|
+
# Create with auto-fill from commits
|
|
122
|
+
gc pr create --fill # Use latest commit
|
|
123
|
+
gc pr create --fill-first # Use first commit
|
|
124
|
+
gc pr create --fill-verbose # Use all commits for body
|
|
125
|
+
|
|
126
|
+
# Create with editor
|
|
127
|
+
gc pr create --editor
|
|
128
|
+
|
|
129
|
+
# Preview without creating
|
|
130
|
+
gc pr create --dry-run
|
|
131
|
+
|
|
132
|
+
# Create in browser
|
|
133
|
+
gc pr create --web
|
|
134
|
+
|
|
135
|
+
# Close / merge / reopen (identifier optional)
|
|
136
|
+
gc pr close # Close PR for current branch
|
|
137
|
+
gc pr close 42 -c "Closing as stale"
|
|
138
|
+
gc pr close --delete-branch # Delete remote branch too
|
|
139
|
+
|
|
140
|
+
gc pr merge # Merge PR for current branch
|
|
141
|
+
gc pr merge 42 -s # Squash merge
|
|
142
|
+
gc pr merge --rebase
|
|
143
|
+
|
|
144
|
+
# Edit a PR (add/remove labels, assignees, reviewers)
|
|
145
|
+
gc pr edit 42 -t "New title"
|
|
146
|
+
gc pr edit --add-label bug --remove-label "needs review"
|
|
147
|
+
gc pr edit --add-reviewer @me --remove-reviewer otheruser
|
|
148
|
+
|
|
149
|
+
# Mark as ready or convert to draft
|
|
150
|
+
gc pr ready # Mark current branch's PR as ready
|
|
151
|
+
gc pr ready --undo # Convert back to draft
|
|
152
|
+
|
|
153
|
+
# Comment / review / diff (identifier optional)
|
|
154
|
+
gc pr comment -b "LGTM"
|
|
155
|
+
gc pr comment --path src/file.py --position 5 -b "Suggestion"
|
|
156
|
+
|
|
157
|
+
gc pr review --approve
|
|
158
|
+
gc pr review --comment -b "Looks good but needs tests"
|
|
159
|
+
gc pr review --request-changes -b "Missing documentation"
|
|
160
|
+
|
|
161
|
+
gc pr diff # View diff for current branch's PR
|
|
162
|
+
gc pr diff 42
|
|
163
|
+
|
|
164
|
+
# Checkout a PR (identifier optional)
|
|
165
|
+
gc pr checkout # Checkout PR for current branch? (prompts if ambiguous)
|
|
166
|
+
gc pr checkout 42
|
|
167
|
+
gc pr checkout -b local-branch-name
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Global Options
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
# Use a different repo without cd-ing into it
|
|
174
|
+
gc issue list -R owner/repo
|
|
175
|
+
gc pr list -R owner/repo
|
|
176
|
+
|
|
177
|
+
# Output as JSON with field selection
|
|
178
|
+
gc issue list --json number,title,state,author
|
|
179
|
+
gc pr list --json number,title,state,head,base
|
|
180
|
+
|
|
181
|
+
# Filter with jq
|
|
182
|
+
gc issue list -q '.[] | select(.state == "open")'
|
|
183
|
+
gc pr list -q '.[] | select(.draft == true)'
|
|
184
|
+
|
|
185
|
+
# Format with Go-style templates
|
|
186
|
+
gc issue list -t '{{.number}} {{.title}} ({{.state}})'
|
|
187
|
+
gc pr view -t 'PR #{{.number}}: {{.title}}\n{{.body}}'
|
|
188
|
+
|
|
189
|
+
# Open in browser
|
|
190
|
+
gc issue view 42 -w
|
|
191
|
+
gc pr view -w
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Alignment with `gh` CLI
|
|
195
|
+
|
|
196
|
+
`pygitcode` aims to be as familiar as possible to `gh` users:
|
|
197
|
+
|
|
198
|
+
| Feature | `gh` | `gc` |
|
|
199
|
+
|---------|------|------|
|
|
200
|
+
| PR identifier optional (current branch inference) | ✅ | ✅ |
|
|
201
|
+
| `--fill` / `--fill-first` / `--fill-verbose` | ✅ | ✅ |
|
|
202
|
+
| `--editor` | ✅ | ✅ |
|
|
203
|
+
| `--dry-run` | ✅ | ✅ |
|
|
204
|
+
| `--web` (create/view in browser) | ✅ | ✅ |
|
|
205
|
+
| `--remove-*` flags for edit commands | ✅ | ✅ |
|
|
206
|
+
| `pr ready --undo` (convert to draft) | ✅ | ✅ |
|
|
207
|
+
| `pr review --comment` / `--request-changes` | ✅ | ✅ (fallback) |
|
|
208
|
+
| `--json fields` | ✅ | ✅ |
|
|
209
|
+
| `-q jq` filtering | ✅ | ✅ |
|
|
210
|
+
| `-t template` formatting | ✅ | ✅ |
|
|
211
|
+
| Command aliases (`ls` → `list`, `new` → `create`) | ✅ | ✅ |
|
|
212
|
+
| Multi-value options (`--label bug --label feature`) | ✅ | ✅ |
|
|
213
|
+
|
|
214
|
+
### Known Limitations (GitCode API differences)
|
|
215
|
+
|
|
216
|
+
- **PR comment model**: GitCode uses `path + position`, not GitHub's `line/side/commit`
|
|
217
|
+
- **PR review**: GitCode review API differs from GitHub; `--comment` and `--request-changes` fall back to PR comments
|
|
218
|
+
- **Issue create/update API**: GitCode puts `repo` in request body, not URL path
|
|
219
|
+
|
|
220
|
+
## Development
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
# Clone
|
|
224
|
+
git clone https://github.com/yourusername/pygitcode.git
|
|
225
|
+
cd pygitcode
|
|
226
|
+
|
|
227
|
+
# Install in editable mode with dev dependencies
|
|
228
|
+
pip install -e ".[dev]"
|
|
229
|
+
|
|
230
|
+
# Install pre-commit hooks
|
|
231
|
+
pre-commit install
|
|
232
|
+
|
|
233
|
+
# Run all checks manually
|
|
234
|
+
pre-commit run --all-files
|
|
235
|
+
|
|
236
|
+
# Or run individually
|
|
237
|
+
python -m pytest tests/unit/ --cov=gitcode_cli
|
|
238
|
+
python -m ruff check src/ tests/
|
|
239
|
+
python -m ruff format src/ tests/
|
|
240
|
+
python -m basedpyright src/
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Roadmap
|
|
244
|
+
|
|
245
|
+
See [ROADMAP.md](ROADMAP.md) for planned features and current gaps.
|
|
246
|
+
|
|
247
|
+
## License
|
|
248
|
+
|
|
249
|
+
MIT
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# pygitcode
|
|
2
|
+
|
|
3
|
+
> A CLI tool for [GitCode](https://gitcode.com/) (`api.gitcode.com`), modeled after GitHub CLI (`gh`).
|
|
4
|
+
|
|
5
|
+
[](https://pypi.org/project/pygitcode/)
|
|
6
|
+
[](https://pypi.org/project/pygitcode/)
|
|
7
|
+
[](https://github.com/yourusername/pygitcode/blob/main/LICENSE)
|
|
8
|
+
[](https://github.com/yourusername/pygitcode/actions)
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pip install pygitcode
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
This exposes the `gc` command in your shell.
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
### Authentication
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# Login with your GitCode personal access token
|
|
24
|
+
gc auth login
|
|
25
|
+
|
|
26
|
+
# Or set environment variable
|
|
27
|
+
export GC_TOKEN=your_token_here
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Issues
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# List issues (with filtering options)
|
|
34
|
+
gc issue list
|
|
35
|
+
gc issue list --state closed --author @me
|
|
36
|
+
gc issue list --label bug --label "help wanted"
|
|
37
|
+
gc issue list --web # Open in browser
|
|
38
|
+
|
|
39
|
+
# View an issue (with comments)
|
|
40
|
+
gc issue view 42
|
|
41
|
+
gc issue view 42 --comments
|
|
42
|
+
gc issue view 42 --web
|
|
43
|
+
|
|
44
|
+
# Create an issue
|
|
45
|
+
gc issue create -t "Bug report" -b "Something is broken"
|
|
46
|
+
gc issue create --web # Create in browser
|
|
47
|
+
|
|
48
|
+
# Edit an issue (add/remove labels, assignees)
|
|
49
|
+
gc issue edit 42 -t "Updated title"
|
|
50
|
+
gc issue edit 42 --add-label bug --remove-label "in progress"
|
|
51
|
+
gc issue edit 42 --add-assignee @me --remove-assignee otheruser
|
|
52
|
+
|
|
53
|
+
# Comment on an issue
|
|
54
|
+
gc issue comment 42 -b "Thanks for the report!"
|
|
55
|
+
gc issue comment 42 --editor # Use system editor
|
|
56
|
+
|
|
57
|
+
# Close / reopen / delete
|
|
58
|
+
gc issue close 42
|
|
59
|
+
gc issue reopen 42
|
|
60
|
+
gc issue delete 42
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Pull Requests
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# List PRs (with filtering options)
|
|
67
|
+
gc pr list
|
|
68
|
+
gc pr list --state merged --author @me
|
|
69
|
+
gc pr list --base main --draft
|
|
70
|
+
gc pr list --web # Open in browser
|
|
71
|
+
|
|
72
|
+
# View a PR (identifier optional - infers from current branch)
|
|
73
|
+
gc pr view # View PR for current branch
|
|
74
|
+
gc pr view 42 # By number
|
|
75
|
+
gc pr view https://gitcode.com/owner/repo/pulls/42
|
|
76
|
+
gc pr view feature-branch
|
|
77
|
+
|
|
78
|
+
# Create a PR (auto-detects current branch and default base)
|
|
79
|
+
gc pr create -t "Add new feature"
|
|
80
|
+
|
|
81
|
+
# Create with auto-fill from commits
|
|
82
|
+
gc pr create --fill # Use latest commit
|
|
83
|
+
gc pr create --fill-first # Use first commit
|
|
84
|
+
gc pr create --fill-verbose # Use all commits for body
|
|
85
|
+
|
|
86
|
+
# Create with editor
|
|
87
|
+
gc pr create --editor
|
|
88
|
+
|
|
89
|
+
# Preview without creating
|
|
90
|
+
gc pr create --dry-run
|
|
91
|
+
|
|
92
|
+
# Create in browser
|
|
93
|
+
gc pr create --web
|
|
94
|
+
|
|
95
|
+
# Close / merge / reopen (identifier optional)
|
|
96
|
+
gc pr close # Close PR for current branch
|
|
97
|
+
gc pr close 42 -c "Closing as stale"
|
|
98
|
+
gc pr close --delete-branch # Delete remote branch too
|
|
99
|
+
|
|
100
|
+
gc pr merge # Merge PR for current branch
|
|
101
|
+
gc pr merge 42 -s # Squash merge
|
|
102
|
+
gc pr merge --rebase
|
|
103
|
+
|
|
104
|
+
# Edit a PR (add/remove labels, assignees, reviewers)
|
|
105
|
+
gc pr edit 42 -t "New title"
|
|
106
|
+
gc pr edit --add-label bug --remove-label "needs review"
|
|
107
|
+
gc pr edit --add-reviewer @me --remove-reviewer otheruser
|
|
108
|
+
|
|
109
|
+
# Mark as ready or convert to draft
|
|
110
|
+
gc pr ready # Mark current branch's PR as ready
|
|
111
|
+
gc pr ready --undo # Convert back to draft
|
|
112
|
+
|
|
113
|
+
# Comment / review / diff (identifier optional)
|
|
114
|
+
gc pr comment -b "LGTM"
|
|
115
|
+
gc pr comment --path src/file.py --position 5 -b "Suggestion"
|
|
116
|
+
|
|
117
|
+
gc pr review --approve
|
|
118
|
+
gc pr review --comment -b "Looks good but needs tests"
|
|
119
|
+
gc pr review --request-changes -b "Missing documentation"
|
|
120
|
+
|
|
121
|
+
gc pr diff # View diff for current branch's PR
|
|
122
|
+
gc pr diff 42
|
|
123
|
+
|
|
124
|
+
# Checkout a PR (identifier optional)
|
|
125
|
+
gc pr checkout # Checkout PR for current branch? (prompts if ambiguous)
|
|
126
|
+
gc pr checkout 42
|
|
127
|
+
gc pr checkout -b local-branch-name
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Global Options
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# Use a different repo without cd-ing into it
|
|
134
|
+
gc issue list -R owner/repo
|
|
135
|
+
gc pr list -R owner/repo
|
|
136
|
+
|
|
137
|
+
# Output as JSON with field selection
|
|
138
|
+
gc issue list --json number,title,state,author
|
|
139
|
+
gc pr list --json number,title,state,head,base
|
|
140
|
+
|
|
141
|
+
# Filter with jq
|
|
142
|
+
gc issue list -q '.[] | select(.state == "open")'
|
|
143
|
+
gc pr list -q '.[] | select(.draft == true)'
|
|
144
|
+
|
|
145
|
+
# Format with Go-style templates
|
|
146
|
+
gc issue list -t '{{.number}} {{.title}} ({{.state}})'
|
|
147
|
+
gc pr view -t 'PR #{{.number}}: {{.title}}\n{{.body}}'
|
|
148
|
+
|
|
149
|
+
# Open in browser
|
|
150
|
+
gc issue view 42 -w
|
|
151
|
+
gc pr view -w
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Alignment with `gh` CLI
|
|
155
|
+
|
|
156
|
+
`pygitcode` aims to be as familiar as possible to `gh` users:
|
|
157
|
+
|
|
158
|
+
| Feature | `gh` | `gc` |
|
|
159
|
+
|---------|------|------|
|
|
160
|
+
| PR identifier optional (current branch inference) | ✅ | ✅ |
|
|
161
|
+
| `--fill` / `--fill-first` / `--fill-verbose` | ✅ | ✅ |
|
|
162
|
+
| `--editor` | ✅ | ✅ |
|
|
163
|
+
| `--dry-run` | ✅ | ✅ |
|
|
164
|
+
| `--web` (create/view in browser) | ✅ | ✅ |
|
|
165
|
+
| `--remove-*` flags for edit commands | ✅ | ✅ |
|
|
166
|
+
| `pr ready --undo` (convert to draft) | ✅ | ✅ |
|
|
167
|
+
| `pr review --comment` / `--request-changes` | ✅ | ✅ (fallback) |
|
|
168
|
+
| `--json fields` | ✅ | ✅ |
|
|
169
|
+
| `-q jq` filtering | ✅ | ✅ |
|
|
170
|
+
| `-t template` formatting | ✅ | ✅ |
|
|
171
|
+
| Command aliases (`ls` → `list`, `new` → `create`) | ✅ | ✅ |
|
|
172
|
+
| Multi-value options (`--label bug --label feature`) | ✅ | ✅ |
|
|
173
|
+
|
|
174
|
+
### Known Limitations (GitCode API differences)
|
|
175
|
+
|
|
176
|
+
- **PR comment model**: GitCode uses `path + position`, not GitHub's `line/side/commit`
|
|
177
|
+
- **PR review**: GitCode review API differs from GitHub; `--comment` and `--request-changes` fall back to PR comments
|
|
178
|
+
- **Issue create/update API**: GitCode puts `repo` in request body, not URL path
|
|
179
|
+
|
|
180
|
+
## Development
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# Clone
|
|
184
|
+
git clone https://github.com/yourusername/pygitcode.git
|
|
185
|
+
cd pygitcode
|
|
186
|
+
|
|
187
|
+
# Install in editable mode with dev dependencies
|
|
188
|
+
pip install -e ".[dev]"
|
|
189
|
+
|
|
190
|
+
# Install pre-commit hooks
|
|
191
|
+
pre-commit install
|
|
192
|
+
|
|
193
|
+
# Run all checks manually
|
|
194
|
+
pre-commit run --all-files
|
|
195
|
+
|
|
196
|
+
# Or run individually
|
|
197
|
+
python -m pytest tests/unit/ --cov=gitcode_cli
|
|
198
|
+
python -m ruff check src/ tests/
|
|
199
|
+
python -m ruff format src/ tests/
|
|
200
|
+
python -m basedpyright src/
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Roadmap
|
|
204
|
+
|
|
205
|
+
See [ROADMAP.md](ROADMAP.md) for planned features and current gaps.
|
|
206
|
+
|
|
207
|
+
## License
|
|
208
|
+
|
|
209
|
+
MIT
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "pygitcode"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "A CLI tool for GitCode (api.gitcode.com), modeled after GitHub CLI."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "codeasier", email = "825770651@qq.com" },
|
|
14
|
+
]
|
|
15
|
+
keywords = ["gitcode", "cli", "git", "api", "vcs", "developer-tools"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Environment :: Console",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"Operating System :: OS Independent",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3.9",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Programming Language :: Python :: 3.13",
|
|
27
|
+
"Topic :: Software Development :: Version Control :: Git",
|
|
28
|
+
"Topic :: Utilities",
|
|
29
|
+
"Typing :: Typed",
|
|
30
|
+
]
|
|
31
|
+
dependencies = [
|
|
32
|
+
"click>=8.0",
|
|
33
|
+
"httpx>=0.24",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[project.optional-dependencies]
|
|
37
|
+
dev = [
|
|
38
|
+
"pytest>=8.0",
|
|
39
|
+
"pytest-cov>=5.0",
|
|
40
|
+
"pytest-mock>=3.14",
|
|
41
|
+
"respx>=0.21",
|
|
42
|
+
"ruff>=0.6",
|
|
43
|
+
"black>=24.0",
|
|
44
|
+
"basedpyright>=1.19",
|
|
45
|
+
"pre-commit>=3.0",
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
[project.urls]
|
|
49
|
+
Homepage = "https://github.com/yourusername/pygitcode"
|
|
50
|
+
Documentation = "https://github.com/yourusername/pygitcode#readme"
|
|
51
|
+
Repository = "https://github.com/yourusername/pygitcode.git"
|
|
52
|
+
Issues = "https://github.com/yourusername/pygitcode/issues"
|
|
53
|
+
|
|
54
|
+
[project.scripts]
|
|
55
|
+
gc = "gitcode_cli.cli:main"
|
|
56
|
+
|
|
57
|
+
[tool.setuptools.packages.find]
|
|
58
|
+
where = ["src"]
|
|
59
|
+
|
|
60
|
+
# --- pytest ---
|
|
61
|
+
[tool.pytest.ini_options]
|
|
62
|
+
testpaths = ["tests"]
|
|
63
|
+
pythonpath = ["src"]
|
|
64
|
+
addopts = [
|
|
65
|
+
"--cov=gitcode_cli",
|
|
66
|
+
"--cov-report=term-missing",
|
|
67
|
+
"--cov-report=html",
|
|
68
|
+
"--cov-fail-under=90",
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
# --- ruff ---
|
|
72
|
+
[tool.ruff]
|
|
73
|
+
target-version = "py39"
|
|
74
|
+
line-length = 120
|
|
75
|
+
src = ["src"]
|
|
76
|
+
|
|
77
|
+
[tool.ruff.lint]
|
|
78
|
+
select = [
|
|
79
|
+
"E", # pycodestyle errors
|
|
80
|
+
"W", # pycodestyle warnings
|
|
81
|
+
"F", # Pyflakes
|
|
82
|
+
"I", # isort
|
|
83
|
+
"N", # pep8-naming
|
|
84
|
+
"UP", # pyupgrade
|
|
85
|
+
"B", # flake8-bugbear
|
|
86
|
+
"C4", # flake8-comprehensions
|
|
87
|
+
"SIM", # flake8-simplify
|
|
88
|
+
"ARG", # flake8-unused-arguments
|
|
89
|
+
"PL", # Pylint
|
|
90
|
+
]
|
|
91
|
+
ignore = [
|
|
92
|
+
"PLR2004", # Magic value used in comparison
|
|
93
|
+
"PLR0913", # Too many arguments in function definition (common for Click commands and API methods)
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
[tool.ruff.lint.per-file-ignores]
|
|
97
|
+
"tests/**" = ["ARG", "PLC0415", "SIM117"]
|
|
98
|
+
"tests/conftest.py" = ["ARG", "PLC0415", "F401"]
|
|
99
|
+
|
|
100
|
+
[tool.ruff.lint.pydocstyle]
|
|
101
|
+
convention = "google"
|
|
102
|
+
|
|
103
|
+
[tool.ruff.format]
|
|
104
|
+
quote-style = "double"
|
|
105
|
+
indent-style = "space"
|
|
106
|
+
|
|
107
|
+
# --- black ---
|
|
108
|
+
[tool.black]
|
|
109
|
+
line-length = 120
|
|
110
|
+
target-version = ["py39", "py310", "py311", "py312", "py313"]
|
|
111
|
+
include = "\\.pyi?$"
|
|
112
|
+
|
|
113
|
+
# --- basedpyright ---
|
|
114
|
+
[tool.basedpyright]
|
|
115
|
+
pythonVersion = "3.9"
|
|
116
|
+
include = ["src"]
|
|
117
|
+
typeCheckingMode = "standard"
|
|
118
|
+
reportMissingTypeStubs = false
|
|
119
|
+
reportAny = false
|
|
120
|
+
reportUnknownMemberType = false
|
|
121
|
+
reportUnknownVariableType = false
|
|
122
|
+
reportUnknownArgumentType = false
|
|
123
|
+
reportUnknownParameterType = false
|
|
124
|
+
reportOptionalSubscript = false
|
|
125
|
+
reportOptionalMemberAccess = false
|
|
126
|
+
reportOptionalIterable = false
|
|
127
|
+
reportOptionalOperand = false
|
|
128
|
+
reportMissingImports = false
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from . import __version__
|
|
6
|
+
from .commands.auth import auth_group
|
|
7
|
+
from .commands.issue import issue_group
|
|
8
|
+
from .commands.pr import pr_group
|
|
9
|
+
from .config import get_token
|
|
10
|
+
from .context import AppContext
|
|
11
|
+
from .errors import GCError
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@click.group(context_settings={"help_option_names": ["-h", "--help"]})
|
|
15
|
+
@click.version_option(version=__version__, prog_name="gc")
|
|
16
|
+
@click.option("--repo", "repo_name", "-R", help="Select another repository using the [HOST/]OWNER/REPO format.")
|
|
17
|
+
@click.option("--token", hidden=True, help="Override authentication token.")
|
|
18
|
+
@click.pass_context
|
|
19
|
+
def main(ctx: click.Context, repo_name: str | None, token: str | None) -> None:
|
|
20
|
+
ctx.ensure_object(dict)
|
|
21
|
+
try:
|
|
22
|
+
resolved_token = token or get_token()
|
|
23
|
+
except GCError:
|
|
24
|
+
resolved_token = token
|
|
25
|
+
ctx.obj["app"] = AppContext(token=resolved_token or "", repo=repo_name)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@main.result_callback()
|
|
29
|
+
def process_result(*_args: object, **_kwargs: object) -> None:
|
|
30
|
+
return None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@main.command("version")
|
|
34
|
+
def version_command() -> None:
|
|
35
|
+
click.echo(f"gc version {__version__}")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
main.add_command(auth_group)
|
|
39
|
+
main.add_command(issue_group)
|
|
40
|
+
main.add_command(pr_group)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
if __name__ == "__main__": # pragma: no cover
|
|
44
|
+
main()
|