crackerjack 0.28.0__tar.gz → 0.29.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.

Potentially problematic release.


This version of crackerjack might be problematic. Click here for more details.

Files changed (46) hide show
  1. {crackerjack-0.28.0 → crackerjack-0.29.0}/CLAUDE.md +160 -3
  2. {crackerjack-0.28.0 → crackerjack-0.29.0}/PKG-INFO +636 -52
  3. {crackerjack-0.28.0 → crackerjack-0.29.0}/README.md +635 -51
  4. {crackerjack-0.28.0 → crackerjack-0.29.0}/crackerjack/__main__.py +8 -0
  5. {crackerjack-0.28.0 → crackerjack-0.29.0}/crackerjack/crackerjack.py +647 -48
  6. {crackerjack-0.28.0 → crackerjack-0.29.0}/crackerjack/interactive.py +7 -16
  7. {crackerjack-0.28.0 → crackerjack-0.29.0/crackerjack}/pyproject.toml +2 -0
  8. {crackerjack-0.28.0/crackerjack → crackerjack-0.29.0}/pyproject.toml +3 -1
  9. {crackerjack-0.28.0 → crackerjack-0.29.0}/tests/test_crackerjack.py +460 -4
  10. {crackerjack-0.28.0 → crackerjack-0.29.0}/tests/test_crackerjack_runner.py +1 -0
  11. {crackerjack-0.28.0 → crackerjack-0.29.0}/tests/test_interactive_run.py +21 -36
  12. {crackerjack-0.28.0 → crackerjack-0.29.0}/tests/test_structured_errors.py +1 -0
  13. {crackerjack-0.28.0 → crackerjack-0.29.0}/uv.lock +70 -2
  14. {crackerjack-0.28.0 → crackerjack-0.29.0}/.envrc +0 -0
  15. {crackerjack-0.28.0 → crackerjack-0.29.0}/.github/FUNDING.yml +0 -0
  16. {crackerjack-0.28.0 → crackerjack-0.29.0}/.gitignore +0 -0
  17. {crackerjack-0.28.0 → crackerjack-0.29.0}/.libcst.codemod.yaml +0 -0
  18. {crackerjack-0.28.0 → crackerjack-0.29.0}/.pre-commit-config-ai.yaml +0 -0
  19. {crackerjack-0.28.0 → crackerjack-0.29.0}/.pre-commit-config-fast.yaml +0 -0
  20. {crackerjack-0.28.0 → crackerjack-0.29.0}/.pre-commit-config.yaml +0 -0
  21. {crackerjack-0.28.0 → crackerjack-0.29.0}/LICENSE +0 -0
  22. {crackerjack-0.28.0 → crackerjack-0.29.0}/README-AI-AGENT.md +0 -0
  23. {crackerjack-0.28.0 → crackerjack-0.29.0}/RULES.md +0 -0
  24. {crackerjack-0.28.0 → crackerjack-0.29.0}/crackerjack/.gitignore +0 -0
  25. {crackerjack-0.28.0 → crackerjack-0.29.0}/crackerjack/.libcst.codemod.yaml +0 -0
  26. {crackerjack-0.28.0 → crackerjack-0.29.0}/crackerjack/.pdm.toml +0 -0
  27. {crackerjack-0.28.0 → crackerjack-0.29.0}/crackerjack/.pre-commit-config-ai.yaml +0 -0
  28. {crackerjack-0.28.0 → crackerjack-0.29.0}/crackerjack/.pre-commit-config-fast.yaml +0 -0
  29. {crackerjack-0.28.0 → crackerjack-0.29.0}/crackerjack/.pre-commit-config.yaml +0 -0
  30. {crackerjack-0.28.0 → crackerjack-0.29.0}/crackerjack/__init__.py +0 -0
  31. {crackerjack-0.28.0 → crackerjack-0.29.0}/crackerjack/errors.py +0 -0
  32. {crackerjack-0.28.0 → crackerjack-0.29.0}/crackerjack/py313.py +0 -0
  33. {crackerjack-0.28.0 → crackerjack-0.29.0}/tests/TESTING.md +0 -0
  34. {crackerjack-0.28.0 → crackerjack-0.29.0}/tests/__init__.py +0 -0
  35. {crackerjack-0.28.0 → crackerjack-0.29.0}/tests/conftest.py +0 -0
  36. {crackerjack-0.28.0 → crackerjack-0.29.0}/tests/data/comments_sample.txt +0 -0
  37. {crackerjack-0.28.0 → crackerjack-0.29.0}/tests/data/docstrings_sample.txt +0 -0
  38. {crackerjack-0.28.0 → crackerjack-0.29.0}/tests/data/expected_comments_sample.txt +0 -0
  39. {crackerjack-0.28.0 → crackerjack-0.29.0}/tests/data/init.py +0 -0
  40. {crackerjack-0.28.0 → crackerjack-0.29.0}/tests/test_errors.py +0 -0
  41. {crackerjack-0.28.0 → crackerjack-0.29.0}/tests/test_interactive.py +0 -0
  42. {crackerjack-0.28.0 → crackerjack-0.29.0}/tests/test_main.py +0 -0
  43. {crackerjack-0.28.0 → crackerjack-0.29.0}/tests/test_multiline_functions.py +0 -0
  44. {crackerjack-0.28.0 → crackerjack-0.29.0}/tests/test_py313_advanced.py +0 -0
  45. {crackerjack-0.28.0 → crackerjack-0.29.0}/tests/test_py313_features.py +0 -0
  46. {crackerjack-0.28.0 → crackerjack-0.29.0}/tests/test_pytest_features.py +0 -0
@@ -202,6 +202,75 @@ python -m crackerjack -b minor
202
202
  python -m crackerjack -b major
203
203
  ```
204
204
 
205
+ #### PyPI Authentication Setup
206
+
207
+ Crackerjack provides enhanced PyPI authentication with automatic validation and helpful error messages. Choose one of these authentication methods:
208
+
209
+ **Method 1: Environment Variable (Recommended)**
210
+
211
+ ```bash
212
+ # Set PyPI token as environment variable
213
+ export UV_PUBLISH_TOKEN=pypi-your-token-here
214
+
215
+ # Publish with token authentication
216
+ python -m crackerjack -p patch
217
+ ```
218
+
219
+ **Method 2: Keyring Integration**
220
+
221
+ ```bash
222
+ # Install keyring globally or in current environment
223
+ uv tool install keyring
224
+
225
+ # Store PyPI token in keyring
226
+ keyring set https://upload.pypi.org/legacy/ __token__
227
+ # Enter your PyPI token when prompted
228
+
229
+ # Ensure keyring provider is configured in pyproject.toml
230
+ [tool.uv]
231
+ keyring-provider = "subprocess"
232
+
233
+ # Publish with keyring authentication
234
+ python -m crackerjack -p patch
235
+ ```
236
+
237
+ **Method 3: Environment Variable for Keyring Provider**
238
+
239
+ ```bash
240
+ # Set keyring provider via environment
241
+ export UV_KEYRING_PROVIDER=subprocess
242
+
243
+ # Publish (will use keyring for authentication)
244
+ python -m crackerjack -p patch
245
+ ```
246
+
247
+ #### Authentication Validation
248
+
249
+ Crackerjack automatically validates your authentication setup before publishing and provides helpful feedback:
250
+
251
+ - ✅ **Token Found**: When UV_PUBLISH_TOKEN is set
252
+ - ✅ **Keyring Ready**: When keyring is configured and token is stored
253
+ - ⚠️ **Setup Needed**: When authentication needs configuration
254
+
255
+ If publishing fails due to authentication issues, crackerjack will display helpful setup instructions.
256
+
257
+ #### PyPI Token Best Practices
258
+
259
+ 1. **Generate Project-Specific Tokens**: Create separate PyPI tokens for each project
260
+ 1. **Use Scoped Tokens**: Limit token scope to the specific package you're publishing
261
+ 1. **Secure Storage**: Use environment variables or keyring - never hardcode tokens
262
+ 1. **Token Format**: PyPI tokens start with `pypi-` (e.g., `pypi-AgEIcHlwaS5vcmcCJGZm...`)
263
+
264
+ #### Troubleshooting Authentication
265
+
266
+ If you encounter authentication issues:
267
+
268
+ 1. **Check Token Format**: Ensure your token starts with `pypi-`
269
+ 1. **Verify Environment Variable**: `echo $UV_PUBLISH_TOKEN` should show your token
270
+ 1. **Test Keyring**: `keyring get https://upload.pypi.org/legacy/ __token__` should return your token
271
+ 1. **Check Configuration**: Ensure `keyring-provider = "subprocess"` in pyproject.toml
272
+ 1. **Install Keyring**: `uv tool install keyring` if using keyring authentication
273
+
205
274
  ### Git Operations
206
275
 
207
276
  ```bash
@@ -376,6 +445,32 @@ Crackerjack follows a single-file architecture for simplicity and maintainabilit
376
445
  - Use built-in collection types (`list[str]`, `dict[str, int]`) instead of typing equivalents
377
446
  - Leverage Python 3.13+ performance and language improvements
378
447
 
448
+ 1. **Zen of Python Philosophy**: Follow the Zen of Python principles (PEP 20) in all code:
449
+
450
+ - **Beautiful is better than ugly** - Write clean, readable code with clear intent
451
+ - **Explicit is better than implicit** - Be clear about what code does, avoid magic
452
+ - **Simple is better than complex** - Choose simple solutions over complex ones
453
+ - **Complex is better than complicated** - When complexity is needed, keep it organized
454
+ - **Flat is better than nested** - Avoid deep nesting, prefer flat structure
455
+ - **Sparse is better than dense** - Use whitespace and clear formatting
456
+ - **Readability counts** - Prioritize code that humans can easily understand
457
+ - **Special cases aren't special enough to break the rules** - Apply standards consistently
458
+ - **Practicality beats purity** - Favor working solutions over theoretical perfection
459
+ - **Errors should never pass silently** - Handle exceptions explicitly
460
+ - **In the face of ambiguity, refuse the temptation to guess** - Be explicit about assumptions
461
+ - **There should be one obvious way to do it** - Prefer established patterns
462
+ - **Now is better than never** - Don't postpone necessary improvements
463
+ - **If the implementation is hard to explain, it's a bad idea** - Keep solutions understandable
464
+ - **Namespaces are one honking great idea** - Use clear, descriptive names and organization
465
+
466
+ **Apply these principles to:**
467
+
468
+ - **Crackerjack development**: All contributions should embody Zen principles
469
+ - **Generated code**: AI assistants should generate Zen-compliant code
470
+ - **Project templates**: Code created by crackerjack should follow Zen principles
471
+ - **Documentation**: Examples and templates should demonstrate Zen philosophy
472
+ - **Code reviews**: Evaluate code against Zen principles for quality
473
+
379
474
  1. **Testing Approach**:
380
475
 
381
476
  - Write unit tests for all functionality
@@ -464,13 +559,13 @@ When generating code, AI assistants MUST follow these standards to ensure compli
464
559
 
465
560
  **Code Complexity Management (Complexipy):**
466
561
 
467
- - **CRITICAL**: Keep cognitive complexity under 20 per function/method
562
+ - **CRITICAL**: Keep cognitive complexity under 15 per function/method
468
563
  - Break complex methods into smaller helper functions (3-5 helper functions are better than 1 complex function)
469
564
  - Use descriptive function names that explain their purpose
470
565
  - Prefer multiple small functions over one large function
471
566
  - **Pattern for refactoring complex methods:**
472
567
  ```python
473
- # Bad - High complexity (>20)
568
+ # Bad - High complexity (>15)
474
569
  def complex_method(self, data):
475
570
  # 50+ lines with multiple nested if/else, loops, etc.
476
571
 
@@ -712,12 +807,23 @@ By following these guidelines during code generation, AI assistants will produce
712
807
 
713
808
  **MANDATORY: Always Apply These Standards When Generating Code**
714
809
 
810
+ 1. **Zen of Python Compliance**: Ensure all generated code follows Zen principles:
811
+
812
+ - **Readability first**: Code should be immediately understandable
813
+ - **Explicit over implicit**: Clear intent, no hidden behavior or magic
814
+ - **Simple solutions**: Choose the most straightforward approach that works
815
+ - **Consistent patterns**: Use established Python idioms and conventions
816
+ - **Proper error handling**: Never ignore exceptions, handle them explicitly
817
+ - **Clear naming**: Use descriptive names that explain purpose and intent
818
+ - **Flat structure**: Avoid deep nesting, prefer early returns and flat logic
819
+ - **One obvious way**: Use well-known Python patterns over clever alternatives
820
+
715
821
  1. **Pre-Generation Checklist:**
716
822
 
717
823
  - Use tuples `()` for `in` membership testing, never lists `[]`
718
824
  - Don't pass default values that match the function's default (e.g., `None` for optional parameters)
719
825
  - Add complete type annotations to ALL function parameters
720
- - Keep cognitive complexity under 20 per function
826
+ - Keep cognitive complexity under 15 per function
721
827
  - Implement ALL protocol properties when creating test classes
722
828
 
723
829
  1. **Common Patterns to Always Follow:**
@@ -741,11 +847,62 @@ By following these guidelines during code generation, AI assistants will produce
741
847
  progress_file: str | None = None # Required
742
848
  ```
743
849
 
850
+ 1. **Zen-Inspired Code Examples:**
851
+
852
+ ```python
853
+ # Beautiful is better than ugly - Clean, clear intent
854
+ def process_user_data(user_id: str, data: dict[str, Any]) -> ProcessResult:
855
+ if not user_id:
856
+ raise ValueError("User ID is required")
857
+
858
+ return ProcessResult(
859
+ user_id=user_id,
860
+ processed_data=_transform_data(data),
861
+ timestamp=datetime.now(UTC),
862
+ )
863
+
864
+
865
+ # Explicit is better than implicit - Clear about what happens
866
+ def send_notification(user: User, *, force_send: bool = False) -> bool:
867
+ if not user.email:
868
+ if force_send:
869
+ raise ValueError("Cannot force send without email")
870
+ return False
871
+
872
+ return _email_service.send(user.email, template="welcome")
873
+
874
+
875
+ # Simple is better than complex - Direct, understandable logic
876
+ def validate_config(config: dict[str, Any]) -> None:
877
+ required_keys = ("database_url", "api_key", "redis_url")
878
+
879
+ for key in required_keys:
880
+ if key not in config:
881
+ raise ConfigError(f"Missing required config: {key}")
882
+
883
+
884
+ # Flat is better than nested - Early returns, avoid deep nesting
885
+ def process_request(request: Request) -> Response:
886
+ if not request.user.is_authenticated:
887
+ return Response.unauthorized()
888
+
889
+ if not request.has_permission("read"):
890
+ return Response.forbidden()
891
+
892
+ if not request.data:
893
+ return Response.bad_request("No data provided")
894
+
895
+ # Main logic here, not nested 4 levels deep
896
+ result = _process_data(request.data)
897
+ return Response.success(result)
898
+ ```
899
+
744
900
  1. **Quality Gate Strategy:**
745
901
 
746
902
  - Write code that would pass `python -m crackerjack --comprehensive` on first try
747
903
  - Prioritize these checks: Refurb FURB109, FURB120, Pyright reportMissingParameterType, Complexipy \<20
748
904
  - When refactoring complex code, break into 3-5 helper methods with single responsibilities
905
+ - **Apply Zen principles**: Every function should be easily explainable in plain English
749
906
 
750
907
  1. **Testing Integration:**
751
908