contextzip 0.2.2__tar.gz → 0.2.3__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 (25) hide show
  1. {contextzip-0.2.2 → contextzip-0.2.3}/PKG-INFO +2 -2
  2. {contextzip-0.2.2 → contextzip-0.2.3}/contextzip/__init__.py +1 -1
  3. {contextzip-0.2.2 → contextzip-0.2.3}/contextzip/detector.py +2 -2
  4. {contextzip-0.2.2 → contextzip-0.2.3}/contextzip/filters.py +17 -6
  5. {contextzip-0.2.2 → contextzip-0.2.3}/contextzip/packager.py +6 -1
  6. {contextzip-0.2.2 → contextzip-0.2.3}/contextzip/rules/base.py +14 -1
  7. contextzip-0.2.3/contextzip/rules/ruby.py +41 -0
  8. {contextzip-0.2.2 → contextzip-0.2.3}/contextzip.egg-info/PKG-INFO +2 -2
  9. {contextzip-0.2.2 → contextzip-0.2.3}/contextzip.egg-info/SOURCES.txt +1 -0
  10. {contextzip-0.2.2 → contextzip-0.2.3}/pyproject.toml +2 -2
  11. {contextzip-0.2.2 → contextzip-0.2.3}/LICENSE +0 -0
  12. {contextzip-0.2.2 → contextzip-0.2.3}/README.md +0 -0
  13. {contextzip-0.2.2 → contextzip-0.2.3}/contextzip/cli.py +0 -0
  14. {contextzip-0.2.2 → contextzip-0.2.3}/contextzip/clipboard.py +0 -0
  15. {contextzip-0.2.2 → contextzip-0.2.3}/contextzip/git.py +0 -0
  16. {contextzip-0.2.2 → contextzip-0.2.3}/contextzip/rules/__init__.py +0 -0
  17. {contextzip-0.2.2 → contextzip-0.2.3}/contextzip/rules/go.py +0 -0
  18. {contextzip-0.2.2 → contextzip-0.2.3}/contextzip/rules/node.py +0 -0
  19. {contextzip-0.2.2 → contextzip-0.2.3}/contextzip/rules/python.py +0 -0
  20. {contextzip-0.2.2 → contextzip-0.2.3}/contextzip/rules/rust.py +0 -0
  21. {contextzip-0.2.2 → contextzip-0.2.3}/contextzip.egg-info/dependency_links.txt +0 -0
  22. {contextzip-0.2.2 → contextzip-0.2.3}/contextzip.egg-info/entry_points.txt +0 -0
  23. {contextzip-0.2.2 → contextzip-0.2.3}/contextzip.egg-info/requires.txt +0 -0
  24. {contextzip-0.2.2 → contextzip-0.2.3}/contextzip.egg-info/top_level.txt +0 -0
  25. {contextzip-0.2.2 → contextzip-0.2.3}/setup.cfg +0 -0
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: contextzip
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: Intelligently package your codebase for AI tools
5
5
  Author-email: Deepesh <akadeepesh@gmail.com>
6
6
  License-Expression: MIT
7
7
  Project-URL: Homepage, https://github.com/akadeepesh/contextzip
8
8
  Project-URL: Repository, https://github.com/akadeepesh/contextzip
9
9
  Project-URL: Issues, https://github.com/akadeepesh/contextzip/issues
10
- Keywords: ai,cli,developer-tools,context,zip,llm
10
+ Keywords: ai,cli,developer-tools,context,zip,llm,claude,chatgpt,code-packaging
11
11
  Classifier: Development Status :: 4 - Beta
12
12
  Classifier: Environment :: Console
13
13
  Classifier: Intended Audience :: Developers
@@ -1,3 +1,3 @@
1
1
  """contextzip — intelligent codebase packager for AI tools."""
2
2
 
3
- __version__ = "0.2.2"
3
+ __version__ = "0.2.3"
@@ -120,7 +120,7 @@ _RULES: list[_Rule] = [
120
120
  # ── Ruby ─────────────────────────────────────────────────────────────
121
121
  _Rule(
122
122
  name="Ruby",
123
- module="base", # no dedicated rule module yet; base covers it
123
+ module="ruby",
124
124
  check=lambda p: _file_exists(p, "Gemfile"),
125
125
  weight=2,
126
126
  ),
@@ -215,4 +215,4 @@ def _dep_present_py(project_dir: Path, dep: str) -> bool:
215
215
  except Exception:
216
216
  pass
217
217
 
218
- return False
218
+ return False
@@ -35,6 +35,7 @@ _RULE_REGISTRY: dict[str, str] = {
35
35
  "python": "contextzip.rules.python",
36
36
  "rust": "contextzip.rules.rust",
37
37
  "go": "contextzip.rules.go",
38
+ "ruby": "contextzip.rules.ruby",
38
39
  }
39
40
 
40
41
  # Files larger than this trigger a warning (but are still included)
@@ -184,10 +185,10 @@ def resolve_files_from_git(
184
185
  Build a :class:`ResolveResult` from a pre-selected list of files reported
185
186
  by git (modified, added, untracked).
186
187
 
187
- Unlike :func:`resolve_files`, this function does **not** apply exclusion
188
- specsthe caller has already determined which files to include via
189
- ``git status``. Size and binary checks are still performed so that the
190
- usual warnings appear in the CLI output.
188
+ Applies the base exclusion spec as a safety floor even though git selected
189
+ the files a git-tracked ``.env`` or secret key file must still be blocked.
190
+ Size and binary checks are also performed so that the usual warnings appear
191
+ in the CLI output.
191
192
 
192
193
  Parameters
193
194
  ----------
@@ -197,6 +198,10 @@ def resolve_files_from_git(
197
198
  project_dir:
198
199
  Absolute path to the project root (used for relative-path guards).
199
200
  """
201
+ # Build the base spec once — this is our safety floor regardless of what
202
+ # git reports as changed. It blocks .env, secrets, binaries, etc.
203
+ base_spec = build_spec(rule_modules=["base"])
204
+
200
205
  result = ResolveResult()
201
206
 
202
207
  for abs_path in sorted(git_files):
@@ -217,11 +222,17 @@ def resolve_files_from_git(
217
222
 
218
223
  # ── Guard: must be under project_dir ────────────────────────────────
219
224
  try:
220
- abs_path.relative_to(project_dir)
225
+ rel = abs_path.relative_to(project_dir)
221
226
  except ValueError:
222
227
  result.skipped.append((abs_path, "outside project tree"))
223
228
  continue
224
229
 
230
+ # ── Base safety floor — block secrets / binaries even if git-tracked ─
231
+ rel_str = rel.as_posix()
232
+ if _any_parent_excluded(rel, base_spec) or base_spec.match_file(rel_str):
233
+ result.excluded.append(abs_path)
234
+ continue
235
+
225
236
  # ── Readability / stat check ─────────────────────────────────────────
226
237
  try:
227
238
  file_size = abs_path.stat().st_size
@@ -293,4 +304,4 @@ def _is_binary(path: Path) -> bool:
293
304
  chunk = fh.read(_BINARY_PEEK)
294
305
  return b"\x00" in chunk
295
306
  except OSError:
296
- return False
307
+ return False
@@ -115,6 +115,11 @@ def create_zip(
115
115
 
116
116
  try:
117
117
  file_size = abs_path.stat().st_size
118
+ except OSError as e:
119
+ skipped_in_zip.append((abs_path, f"stat failed: {e}"))
120
+ continue
121
+
122
+ try:
118
123
  zf.write(abs_path, arcname=rel.as_posix())
119
124
  uncompressed += file_size
120
125
  file_count += 1
@@ -123,7 +128,7 @@ def create_zip(
123
128
  except OSError as e:
124
129
  skipped_in_zip.append((abs_path, str(e)))
125
130
  finally:
126
- progress.advance(task, abs_path.stat().st_size if abs_path.exists() else 0)
131
+ progress.advance(task, file_size)
127
132
 
128
133
  compressed = zip_path.stat().st_size
129
134
 
@@ -5,7 +5,6 @@ Universal exclusion rules applied to every project regardless of language.
5
5
  PATTERNS = [
6
6
  # Version control
7
7
  ".git/",
8
- ".gitignore",
9
8
  ".svn/",
10
9
  ".hg/",
11
10
 
@@ -64,4 +63,18 @@ PATTERNS = [
64
63
 
65
64
  # The output zip itself (avoid recursion)
66
65
  "*_context_*.zip",
66
+
67
+ # GitHub / repo governance (not useful as AI context)
68
+ "CHANGELOG.md",
69
+ "CHANGELOG",
70
+ "CONTRIBUTING.md",
71
+ "CONTRIBUTING",
72
+ "LICENSE",
73
+ "LICENSE.md",
74
+ "LICENSE.txt",
75
+ "SECURITY.md",
76
+ "CODE_OF_CONDUCT.md",
77
+ ".github/ISSUE_TEMPLATE/",
78
+ ".github/PULL_REQUEST_TEMPLATE.md",
79
+ ".github/PULL_REQUEST_TEMPLATE/",
67
80
  ]
@@ -0,0 +1,41 @@
1
+ """
2
+ Ruby / Rails / Bundler exclusion rules.
3
+ """
4
+
5
+ PATTERNS = [
6
+ # Bundler
7
+ "vendor/bundle/",
8
+ ".bundle/",
9
+ "Gemfile.lock",
10
+
11
+ # Ruby version managers
12
+ ".ruby-version",
13
+ ".ruby-gemset",
14
+ ".rvmrc",
15
+
16
+ # Built gems
17
+ "*.gem",
18
+ "pkg/",
19
+
20
+ # Rails-specific
21
+ "tmp/", # runtime temp (also in base, fine to repeat)
22
+ "log/", # request logs (also in base)
23
+ "public/assets/", # precompiled assets (sprockets / propshaft)
24
+ "public/packs/", # webpacker output
25
+ "storage/", # ActiveStorage blobs
26
+ ".byebug_history",
27
+
28
+ # Test coverage
29
+ "coverage/",
30
+
31
+ # Documentation
32
+ "doc/",
33
+ "rdoc/",
34
+
35
+ # Spring (Rails app preloader)
36
+ ".spring/",
37
+
38
+ # Compiled C extensions
39
+ "*.bundle",
40
+ "*.so", # also in base, explicit here for clarity
41
+ ]
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: contextzip
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: Intelligently package your codebase for AI tools
5
5
  Author-email: Deepesh <akadeepesh@gmail.com>
6
6
  License-Expression: MIT
7
7
  Project-URL: Homepage, https://github.com/akadeepesh/contextzip
8
8
  Project-URL: Repository, https://github.com/akadeepesh/contextzip
9
9
  Project-URL: Issues, https://github.com/akadeepesh/contextzip/issues
10
- Keywords: ai,cli,developer-tools,context,zip,llm
10
+ Keywords: ai,cli,developer-tools,context,zip,llm,claude,chatgpt,code-packaging
11
11
  Classifier: Development Status :: 4 - Beta
12
12
  Classifier: Environment :: Console
13
13
  Classifier: Intended Audience :: Developers
@@ -19,4 +19,5 @@ contextzip/rules/base.py
19
19
  contextzip/rules/go.py
20
20
  contextzip/rules/node.py
21
21
  contextzip/rules/python.py
22
+ contextzip/rules/ruby.py
22
23
  contextzip/rules/rust.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "contextzip"
7
- version = "0.2.2"
7
+ version = "0.2.3"
8
8
  description = "Intelligently package your codebase for AI tools"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -13,7 +13,7 @@ license-files = ["LICENSE"]
13
13
  authors = [
14
14
  { name = "Deepesh", email = "akadeepesh@gmail.com" }
15
15
  ]
16
- keywords = ["ai", "cli", "developer-tools", "context", "zip", "llm"]
16
+ keywords = ["ai", "cli", "developer-tools", "context", "zip", "llm", "claude", "chatgpt", "code-packaging"]
17
17
  classifiers = [
18
18
  "Development Status :: 4 - Beta",
19
19
  "Environment :: Console",
File without changes
File without changes
File without changes
File without changes
File without changes