onepaste 1.3.1__tar.gz → 1.3.2__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.
- {onepaste-1.3.1 → onepaste-1.3.2}/.github/workflows/publish.yml +7 -0
- {onepaste-1.3.1 → onepaste-1.3.2}/.gitignore +22 -20
- {onepaste-1.3.1 → onepaste-1.3.2}/PKG-INFO +2 -1
- {onepaste-1.3.1 → onepaste-1.3.2}/PUBLISHING.md +1 -0
- {onepaste-1.3.1 → onepaste-1.3.2}/README.md +1 -0
- {onepaste-1.3.1 → onepaste-1.3.2}/onepaste/__init__.py +1 -1
- {onepaste-1.3.1 → onepaste-1.3.2}/onepaste/collector.py +19 -7
- {onepaste-1.3.1 → onepaste-1.3.2}/pyproject.toml +1 -1
- {onepaste-1.3.1 → onepaste-1.3.2}/tests/test_collector.py +22 -0
- onepaste-1.3.2/website/package-lock.json +1062 -0
- {onepaste-1.3.1 → onepaste-1.3.2}/LICENSE +0 -0
- {onepaste-1.3.1 → onepaste-1.3.2}/onepaste/__main__.py +0 -0
- {onepaste-1.3.1 → onepaste-1.3.2}/onepaste/cli.py +0 -0
- {onepaste-1.3.1 → onepaste-1.3.2}/onepaste/config.py +0 -0
- {onepaste-1.3.1 → onepaste-1.3.2}/onepaste/formatter.py +0 -0
- {onepaste-1.3.1 → onepaste-1.3.2}/onepaste/gitignore.py +0 -0
- {onepaste-1.3.1 → onepaste-1.3.2}/onepaste/output.py +0 -0
- {onepaste-1.3.1 → onepaste-1.3.2}/onepaste/selector.py +0 -0
- {onepaste-1.3.1 → onepaste-1.3.2}/onepaste/splitter.py +0 -0
- {onepaste-1.3.1 → onepaste-1.3.2}/onepaste/tokens.py +0 -0
- {onepaste-1.3.1 → onepaste-1.3.2}/onepaste/uninstall.py +0 -0
- {onepaste-1.3.1 → onepaste-1.3.2}/tests/conftest.py +0 -0
- {onepaste-1.3.1 → onepaste-1.3.2}/tests/test_cli.py +0 -0
- {onepaste-1.3.1 → onepaste-1.3.2}/tests/test_config.py +0 -0
- {onepaste-1.3.1 → onepaste-1.3.2}/tests/test_formatter.py +0 -0
- {onepaste-1.3.1 → onepaste-1.3.2}/tests/test_output.py +0 -0
- {onepaste-1.3.1 → onepaste-1.3.2}/tests/test_splitter.py +0 -0
- {onepaste-1.3.1 → onepaste-1.3.2}/tests/test_tokens.py +0 -0
|
@@ -3,6 +3,8 @@ name: Publish to PyPI
|
|
|
3
3
|
on:
|
|
4
4
|
release:
|
|
5
5
|
types: [published]
|
|
6
|
+
push:
|
|
7
|
+
tags: ["v*"]
|
|
6
8
|
workflow_dispatch:
|
|
7
9
|
|
|
8
10
|
jobs:
|
|
@@ -35,3 +37,8 @@ jobs:
|
|
|
35
37
|
|
|
36
38
|
- name: Publish to PyPI
|
|
37
39
|
uses: pypa/gh-action-pypi-publish@release/v1
|
|
40
|
+
with:
|
|
41
|
+
# Primary path: OIDC trusted publishing (no secret needed).
|
|
42
|
+
# Optional fallback: add a repo secret named PYPI_API_TOKEN and it
|
|
43
|
+
# takes precedence automatically; leave it unset for pure OIDC.
|
|
44
|
+
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
@@ -13,13 +13,13 @@ __pycache__/
|
|
|
13
13
|
|
|
14
14
|
# Distribution / packaging
|
|
15
15
|
.Python
|
|
16
|
-
build/
|
|
16
|
+
/build/
|
|
17
17
|
develop-eggs/
|
|
18
|
-
dist/
|
|
18
|
+
/dist/
|
|
19
19
|
downloads/
|
|
20
20
|
eggs/
|
|
21
21
|
.eggs/
|
|
22
|
-
lib/
|
|
22
|
+
/lib/
|
|
23
23
|
lib64/
|
|
24
24
|
parts/
|
|
25
25
|
sdist/
|
|
@@ -52,7 +52,7 @@ coverage.xml
|
|
|
52
52
|
*.py,cover
|
|
53
53
|
.hypothesis/
|
|
54
54
|
.pytest_cache/
|
|
55
|
-
cover/
|
|
55
|
+
/cover/
|
|
56
56
|
|
|
57
57
|
# Translations
|
|
58
58
|
*.mo
|
|
@@ -76,7 +76,7 @@ docs/_build/
|
|
|
76
76
|
|
|
77
77
|
# PyBuilder
|
|
78
78
|
.pybuilder/
|
|
79
|
-
target/
|
|
79
|
+
/target/
|
|
80
80
|
|
|
81
81
|
# Jupyter Notebook
|
|
82
82
|
.ipynb_checkpoints
|
|
@@ -111,9 +111,9 @@ celerybeat.pid
|
|
|
111
111
|
# Environments
|
|
112
112
|
.env
|
|
113
113
|
.venv
|
|
114
|
-
env/
|
|
115
|
-
venv/
|
|
116
|
-
ENV/
|
|
114
|
+
/env/
|
|
115
|
+
/venv/
|
|
116
|
+
/ENV/
|
|
117
117
|
env.bak/
|
|
118
118
|
venv.bak/
|
|
119
119
|
|
|
@@ -225,12 +225,12 @@ code_collection*.md
|
|
|
225
225
|
code_collection*.manifest.json
|
|
226
226
|
*.collection.txt
|
|
227
227
|
*.collection.md
|
|
228
|
-
output/
|
|
229
|
-
collected_code/
|
|
228
|
+
/output/
|
|
229
|
+
/collected_code/
|
|
230
230
|
|
|
231
231
|
# 临时文件
|
|
232
|
-
tmp/
|
|
233
|
-
temp/
|
|
232
|
+
/tmp/
|
|
233
|
+
/temp/
|
|
234
234
|
*.tmp
|
|
235
235
|
*.temp
|
|
236
236
|
|
|
@@ -251,7 +251,7 @@ config.local.json
|
|
|
251
251
|
|
|
252
252
|
# 日志文件
|
|
253
253
|
*.log
|
|
254
|
-
logs/
|
|
254
|
+
/logs/
|
|
255
255
|
|
|
256
256
|
# --- Environment ---
|
|
257
257
|
# Conda
|
|
@@ -262,10 +262,10 @@ Anaconda*/
|
|
|
262
262
|
|
|
263
263
|
# NPM (如果项目中有前端部分)
|
|
264
264
|
node_modules/
|
|
265
|
-
package-lock.json
|
|
266
|
-
yarn.lock
|
|
265
|
+
/package-lock.json/
|
|
266
|
+
/yarn.lock/
|
|
267
267
|
.npm
|
|
268
|
-
|
|
268
|
+
/.npmrc/
|
|
269
269
|
|
|
270
270
|
# --- Docker ---
|
|
271
271
|
# (如果将来添加 Docker 支持)
|
|
@@ -274,7 +274,7 @@ docker-compose.override.yml
|
|
|
274
274
|
|
|
275
275
|
# --- Documentation ---
|
|
276
276
|
# 生成的文档
|
|
277
|
-
site/
|
|
277
|
+
/site/
|
|
278
278
|
docs/_build/
|
|
279
279
|
|
|
280
280
|
# --- Security ---
|
|
@@ -302,8 +302,8 @@ collected_*.txt
|
|
|
302
302
|
!collected_example.txt
|
|
303
303
|
|
|
304
304
|
# 测试输出
|
|
305
|
-
test_output/
|
|
306
|
-
test_results/
|
|
305
|
+
/test_output/
|
|
306
|
+
/test_results/
|
|
307
307
|
|
|
308
308
|
# 性能分析
|
|
309
309
|
*.prof
|
|
@@ -312,4 +312,6 @@ test_results/
|
|
|
312
312
|
# 数据库
|
|
313
313
|
*.db
|
|
314
314
|
*.sqlite
|
|
315
|
-
*.sqlite3
|
|
315
|
+
*.sqlite3
|
|
316
|
+
# Website lockfile MUST be tracked (reproducible Vercel builds)
|
|
317
|
+
!website/package-lock.json
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: onepaste
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.2
|
|
4
4
|
Summary: Collect project code files into a single output for AI assistants
|
|
5
5
|
Project-URL: Homepage, https://github.com/emVisible/codecollector
|
|
6
6
|
Project-URL: Repository, https://github.com/emVisible/codecollector.git
|
|
@@ -40,6 +40,7 @@ Description-Content-Type: text/markdown
|
|
|
40
40
|
[](https://pypi.org/project/onepaste/)
|
|
41
41
|
[](https://pypi.org/project/onepaste/)
|
|
42
42
|
[](LICENSE)
|
|
43
|
+
[](https://github.com/emVisible/onepaste/actions/workflows/publish.yml)
|
|
43
44
|
|
|
44
45
|
Collect project code into LLM-ready Markdown. Select a directory, press Enter, copy and paste.
|
|
45
46
|
|
|
@@ -31,6 +31,7 @@ Uses PyPI Trusted Publishing (OIDC) — no secrets stored in GitHub.
|
|
|
31
31
|
- Workflow filename: `publish.yml`
|
|
32
32
|
- Environment name: `pypi`
|
|
33
33
|
2. Release: create a GitHub *Release* (or run the workflow manually via `workflow_dispatch`).
|
|
34
|
+
Alternatively: `git tag vX.Y.Z && git push origin vX.Y.Z` triggers the same workflow.
|
|
34
35
|
|
|
35
36
|
The workflow runs tests, builds, twine-checks, then publishes.
|
|
36
37
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
[](https://pypi.org/project/onepaste/)
|
|
4
4
|
[](https://pypi.org/project/onepaste/)
|
|
5
5
|
[](LICENSE)
|
|
6
|
+
[](https://github.com/emVisible/onepaste/actions/workflows/publish.yml)
|
|
6
7
|
|
|
7
8
|
Collect project code into LLM-ready Markdown. Select a directory, press Enter, copy and paste.
|
|
8
9
|
|
|
@@ -150,16 +150,28 @@ class FileCollector:
|
|
|
150
150
|
|
|
151
151
|
def _path_in_excluded_dir(self, file_path: Path) -> bool:
|
|
152
152
|
try:
|
|
153
|
-
|
|
153
|
+
rel = file_path.relative_to(self.config.root_path)
|
|
154
154
|
except ValueError:
|
|
155
|
-
|
|
156
|
-
|
|
155
|
+
try:
|
|
156
|
+
rel = file_path.resolve().relative_to(self.config.root_path.resolve())
|
|
157
|
+
except ValueError:
|
|
158
|
+
return False
|
|
159
|
+
return any(part in self.config.all_exclude_dirs for part in rel.parts[:-1])
|
|
157
160
|
|
|
158
161
|
def _should_exclude_dir(self, dir_path: Path) -> bool:
|
|
159
|
-
"""Check if a directory should be excluded.
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
162
|
+
"""Check if a directory should be excluded.
|
|
163
|
+
|
|
164
|
+
Exclusion names match path segments *relative to the collection root*
|
|
165
|
+
only — never absolute ancestors (e.g. a /tmp-based temp dir must not
|
|
166
|
+
trip the "tmp" rule).
|
|
167
|
+
"""
|
|
168
|
+
try:
|
|
169
|
+
segments = dir_path.relative_to(self.config.root_path).parts
|
|
170
|
+
except ValueError:
|
|
171
|
+
segments = (dir_path.name,)
|
|
172
|
+
|
|
173
|
+
if any(part in self.config.all_exclude_dirs for part in segments):
|
|
174
|
+
return True
|
|
163
175
|
|
|
164
176
|
if self._git_files is None and self._gitignore:
|
|
165
177
|
if self._gitignore.is_ignored(dir_path, is_dir=True):
|
|
@@ -92,6 +92,28 @@ class TestGitignoreFiltering:
|
|
|
92
92
|
assert "secret_key.txt" in names
|
|
93
93
|
|
|
94
94
|
|
|
95
|
+
class TestExcludesAreRootScoped:
|
|
96
|
+
def test_suspicious_ancestor_names_do_not_prune(self, tmp_path: Path):
|
|
97
|
+
"""Regression: exclusion names must match segments relative to the
|
|
98
|
+
collection root, never absolute ancestors (CI runs under /tmp)."""
|
|
99
|
+
root = tmp_path / "tmp" / "build" / "env" / "proj"
|
|
100
|
+
(root / "src").mkdir(parents=True)
|
|
101
|
+
(root / "a.py").write_text("x = 1\n")
|
|
102
|
+
(root / "src" / "b.py").write_text("y = 2\n")
|
|
103
|
+
(root / "build").mkdir() # a REAL excluded dir inside the project
|
|
104
|
+
(root / "build" / "junk.py").write_text("junk\n")
|
|
105
|
+
|
|
106
|
+
names = _rel_names(_collect(root), root)
|
|
107
|
+
|
|
108
|
+
assert "a.py" in names
|
|
109
|
+
assert "src/b.py" in names
|
|
110
|
+
assert not any(n.startswith("build/") for n in names)
|
|
111
|
+
|
|
112
|
+
def test_real_excluded_dirs_inside_root_still_pruned(self, project_dir: Path):
|
|
113
|
+
fc = _collect(project_dir)
|
|
114
|
+
assert all("node_modules" not in fp.parts for fp in fc.collected_files)
|
|
115
|
+
|
|
116
|
+
|
|
95
117
|
class TestGlobPatterns:
|
|
96
118
|
def test_include_overrides_extension_whitelist(self, project_dir: Path):
|
|
97
119
|
names = _rel_names(
|