wry 0.2.3.dev1__py3-none-any.whl → 0.2.4.dev2__py3-none-any.whl

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.
wry/__init__.py CHANGED
@@ -46,7 +46,7 @@ Example:
46
46
  Coming soon - this package is under active development.
47
47
  """
48
48
 
49
- # Version is managed by poetry-dynamic-versioning from git tags
49
+ # Version is managed by setuptools-scm from git tags
50
50
  try:
51
51
  from ._version import __commit_id__, __version__
52
52
 
@@ -91,6 +91,9 @@ AutoOption = AutoClickParameter.OPTION
91
91
  AutoArgument = AutoClickParameter.ARGUMENT
92
92
  AutoExclude = AutoClickParameter.EXCLUDE
93
93
 
94
+ # Help system
95
+ from .help_system import get_help_content, print_help, show_help_index # noqa: E402
96
+
94
97
  # Re-export all public APIs
95
98
  __all__ = [
96
99
  # Core functionality
@@ -115,6 +118,11 @@ __all__ = [
115
118
  # Convenience exports
116
119
  "AutoOption",
117
120
  "AutoArgument",
121
+ "AutoExclude",
122
+ # Help system
123
+ "get_help_content",
124
+ "print_help",
125
+ "show_help_index",
118
126
  # Version info
119
127
  "__version__",
120
128
  "__version_full__",
wry/_version.py CHANGED
@@ -1,14 +1,34 @@
1
- # file generated by poetry-dynamic-versioning
2
- from typing import TYPE_CHECKING
1
+ # file generated by setuptools-scm
2
+ # don't change, don't track in version control
3
3
 
4
- __version__: str = "0.2.3.dev1" # This will be replaced during build
5
- __version_tuple__: tuple[int, ...] = (0, 2, 3, "dev1") # This will be replaced during build
6
- __commit_id__: str | None = None # This will be replaced during build
7
-
8
- # For compatibility with setuptools-scm test expectations
9
- VERSION_TUPLE = __version_tuple__
10
- COMMIT_ID = __commit_id__
4
+ __all__ = [
5
+ "__version__",
6
+ "__version_tuple__",
7
+ "version",
8
+ "version_tuple",
9
+ "__commit_id__",
10
+ "commit_id",
11
+ ]
11
12
 
13
+ TYPE_CHECKING = False
12
14
  if TYPE_CHECKING:
13
- # Version will be injected by poetry-dynamic-versioning
14
- pass
15
+ from typing import Tuple
16
+ from typing import Union
17
+
18
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
19
+ COMMIT_ID = Union[str, None]
20
+ else:
21
+ VERSION_TUPLE = object
22
+ COMMIT_ID = object
23
+
24
+ version: str
25
+ __version__: str
26
+ __version_tuple__: VERSION_TUPLE
27
+ version_tuple: VERSION_TUPLE
28
+ commit_id: COMMIT_ID
29
+ __commit_id__: COMMIT_ID
30
+
31
+ __version__ = version = '0.2.4.dev2'
32
+ __version_tuple__ = version_tuple = (0, 2, 4, 'dev2')
33
+
34
+ __commit_id__ = commit_id = None
wry/help_system.py ADDED
@@ -0,0 +1,161 @@
1
+ """Help system for wry package.
2
+
3
+ Provides different levels of documentation:
4
+ - Quick help (README summary)
5
+ - AI Knowledge Base (for LLMs)
6
+ - Source tracking guide
7
+ - Architecture documentation
8
+ """
9
+
10
+ from pathlib import Path
11
+ from typing import Literal
12
+
13
+ HelpType = Literal["readme", "ai", "sources", "architecture", "examples"]
14
+
15
+
16
+ def get_help_content(help_type: HelpType = "readme") -> str:
17
+ """Get help content of specified type.
18
+
19
+ Args:
20
+ help_type: Type of help to retrieve
21
+ - "readme": Main README documentation
22
+ - "ai": AI/LLM knowledge base
23
+ - "sources": Source tracking documentation
24
+ - "architecture": Architecture and design
25
+ - "examples": List of examples
26
+
27
+ Returns:
28
+ Help content as string
29
+ """
30
+ # Get package root directory
31
+ package_root = Path(__file__).parent.parent
32
+
33
+ if help_type == "readme":
34
+ readme_path = package_root / "README.md"
35
+ if readme_path.exists():
36
+ return readme_path.read_text()
37
+ return "README.md not found"
38
+
39
+ elif help_type == "ai":
40
+ ai_kb_path = package_root / "AI_KNOWLEDGE_BASE.md"
41
+ if ai_kb_path.exists():
42
+ return ai_kb_path.read_text()
43
+ return "AI_KNOWLEDGE_BASE.md not found"
44
+
45
+ elif help_type == "sources":
46
+ # Extract source tracking section from AI knowledge base
47
+ ai_kb_path = package_root / "AI_KNOWLEDGE_BASE.md"
48
+ if ai_kb_path.exists():
49
+ content = ai_kb_path.read_text()
50
+ # Find test coverage section
51
+ if "## Test Coverage Summary" in content:
52
+ start = content.index("## Test Coverage Summary")
53
+ # Find next major section or end
54
+ next_section = content.find("\n## Common Issues", start + 1)
55
+ if next_section > 0:
56
+ return "# Source Tracking - " + content[start:next_section]
57
+ # Try another section
58
+ next_section = content.find("\n## ", start + 1)
59
+ if next_section > 0:
60
+ return "# Source Tracking - " + content[start:next_section]
61
+ return "# Source Tracking - " + content[start:]
62
+ return "Source tracking documentation not found"
63
+
64
+ elif help_type == "architecture":
65
+ # Extract architecture section from README
66
+ readme_path = package_root / "README.md"
67
+ if readme_path.exists():
68
+ content = readme_path.read_text()
69
+ # Find architecture section
70
+ if "## Architecture" in content:
71
+ start = content.index("## Architecture")
72
+ # Find next major section
73
+ next_section = content.find("\n## ", start + 1)
74
+ if next_section > 0:
75
+ return content[start:next_section]
76
+ return content[start:]
77
+ return "Architecture documentation not found"
78
+
79
+ elif help_type == "examples":
80
+ examples_dir = package_root / "examples"
81
+ if examples_dir.exists():
82
+ examples = []
83
+ examples.append("# wry Examples\n")
84
+ examples.append("\nAvailable examples in examples/ directory:\n")
85
+
86
+ for example_file in sorted(examples_dir.glob("*.py")):
87
+ # Read first docstring
88
+ content = example_file.read_text()
89
+ lines = content.split("\n")
90
+ description = ""
91
+ if lines and lines[0].startswith('"""'):
92
+ # Multi-line docstring
93
+ for line in lines[1:]:
94
+ if '"""' in line:
95
+ break
96
+ description += line.strip() + " "
97
+
98
+ examples.append(f"\n**{example_file.name}**")
99
+ if description:
100
+ examples.append(f" {description.strip()}")
101
+ examples.append(f" Run: `python examples/{example_file.name}`")
102
+
103
+ return "\n".join(examples)
104
+ return "Examples directory not found"
105
+
106
+
107
+ def print_help(help_type: HelpType = "readme", pager: bool = True) -> None:
108
+ """Print help content, optionally using a pager.
109
+
110
+ Args:
111
+ help_type: Type of help to display
112
+ pager: If True, use click's pager for long content
113
+ """
114
+ import click
115
+
116
+ content = get_help_content(help_type)
117
+
118
+ if pager and len(content.split("\n")) > 50:
119
+ click.echo_via_pager(content)
120
+ else:
121
+ click.echo(content)
122
+
123
+
124
+ def show_help_index() -> None:
125
+ """Show index of available help topics."""
126
+ import click
127
+
128
+ click.echo("=" * 60)
129
+ click.echo("wry Help System")
130
+ click.echo("=" * 60)
131
+ click.echo()
132
+ click.echo("Available help topics:")
133
+ click.echo()
134
+ click.echo(" readme - Main README documentation (default)")
135
+ click.echo(" ai - AI/LLM Knowledge Base (comprehensive)")
136
+ click.echo(" sources - Source tracking test coverage")
137
+ click.echo(" architecture - Architecture and design documentation")
138
+ click.echo(" examples - List of available examples")
139
+ click.echo()
140
+ click.echo("Usage:")
141
+ click.echo(" python -m wry.help_system [topic]")
142
+ click.echo(" python -m wry.help_system ai")
143
+ click.echo()
144
+ click.echo("Or in Python:")
145
+ click.echo(" from wry.help_system import print_help")
146
+ click.echo(" print_help('ai')")
147
+ click.echo()
148
+
149
+
150
+ if __name__ == "__main__":
151
+ import sys
152
+
153
+ if len(sys.argv) > 1:
154
+ help_type_arg = sys.argv[1]
155
+ if help_type_arg in ["readme", "ai", "sources", "architecture", "examples"]:
156
+ print_help(help_type_arg) # type: ignore
157
+ else:
158
+ print(f"Unknown help type: {help_type_arg}")
159
+ show_help_index()
160
+ else:
161
+ show_help_index()
@@ -1,33 +1,46 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wry
3
- Version: 0.2.3.dev1
3
+ Version: 0.2.4.dev2
4
4
  Summary: Why Repeat Yourself? - Define your CLI once with Pydantic models
5
+ Author-email: Tyler House <26489166+tahouse@users.noreply.github.com>
5
6
  License: MIT
6
- License-File: LICENSE
7
+ Project-URL: Homepage, https://github.com/tahouse/wry
8
+ Project-URL: Documentation, https://github.com/tahouse/wry#readme
9
+ Project-URL: Repository, https://github.com/tahouse/wry
10
+ Project-URL: Issues, https://github.com/tahouse/wry/issues
11
+ Project-URL: Changelog, https://github.com/tahouse/wry/blob/main/CHANGELOG.md
7
12
  Keywords: cli,pydantic,click,wry,dry,configuration,type-safe
8
- Author: Tyler House
9
- Author-email: 26489166+tahouse@users.noreply.github.com
10
- Requires-Python: >=3.10,<4.0
11
- Classifier: Development Status :: 1 - Planning
13
+ Classifier: Development Status :: 4 - Beta
12
14
  Classifier: Intended Audience :: Developers
13
15
  Classifier: License :: OSI Approved :: MIT License
14
16
  Classifier: Programming Language :: Python :: 3
15
17
  Classifier: Programming Language :: Python :: 3.10
16
18
  Classifier: Programming Language :: Python :: 3.11
17
19
  Classifier: Programming Language :: Python :: 3.12
18
- Classifier: Programming Language :: Python :: 3.13
19
- Classifier: Programming Language :: Python :: 3.14
20
20
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
21
  Classifier: Topic :: System :: System Shells
22
22
  Classifier: Topic :: Utilities
23
- Requires-Dist: annotated-types (>=0.6.0,<0.7.0)
24
- Requires-Dist: click (>=8.0,<9.0)
25
- Requires-Dist: pydantic (>=2.9.2,<3.0.0)
26
- Requires-Dist: pydantic-core (>=2.23.4,<3.0.0)
27
- Project-URL: Documentation, https://github.com/tahouse/wry#readme
28
- Project-URL: Homepage, https://github.com/tahouse/wry
29
- Project-URL: Repository, https://github.com/tahouse/wry
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.10
30
25
  Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: click>=8.0
28
+ Requires-Dist: pydantic>=2.9.2
29
+ Requires-Dist: annotated-types>=0.6.0
30
+ Requires-Dist: pydantic-core>=2.23.4
31
+ Provides-Extra: dev
32
+ Requires-Dist: pytest>=8.4.2; extra == "dev"
33
+ Requires-Dist: pytest-cov>=7.0.0; extra == "dev"
34
+ Requires-Dist: pytest-xdist>=3.8.0; extra == "dev"
35
+ Requires-Dist: coverage[toml]>=7.10.7; extra == "dev"
36
+ Requires-Dist: ruff>=0.13.2; extra == "dev"
37
+ Requires-Dist: mypy>=1.18.2; extra == "dev"
38
+ Requires-Dist: build>=1.2.1; extra == "dev"
39
+ Requires-Dist: twine>=6.0.0; extra == "dev"
40
+ Requires-Dist: pre-commit>=3.8.0; extra == "dev"
41
+ Requires-Dist: safety>=3.2.3; extra == "dev"
42
+ Requires-Dist: bandit[toml]>=1.7.5; extra == "dev"
43
+ Dynamic: license-file
31
44
 
32
45
  # wry - Why Repeat Yourself? CLI
33
46
 
@@ -104,9 +117,14 @@ Hello Bob, you are 35 years old!
104
117
 
105
118
  ## Value Source Tracking
106
119
 
107
- wry can track where each configuration value came from. You have two options:
120
+ wry tracks where each configuration value came from, supporting all four sources:
108
121
 
109
- ### Option 1: Direct Instantiation (No Source Tracking)
122
+ - **DEFAULT**: Values from model field defaults
123
+ - **ENV**: Values from environment variables
124
+ - **JSON**: Values from configuration files (via `--config`)
125
+ - **CLI**: Values from command-line arguments
126
+
127
+ ### Basic Usage (No Source Tracking)
110
128
 
111
129
  ```python
112
130
  @click.command()
@@ -114,10 +132,12 @@ wry can track where each configuration value came from. You have two options:
114
132
  def main(**kwargs):
115
133
  # Simple instantiation - no source tracking
116
134
  config = AppArgs(**kwargs)
117
- # config.source.* will always show CLI regardless of actual source
135
+ # Works fine, but config.source.* will always show CLI
118
136
  ```
119
137
 
120
- ### Option 2: With @click.pass_context (Full Source Tracking)
138
+ ### Full Source Tracking (Recommended)
139
+
140
+ To enable accurate source tracking, use `@click.pass_context` and `from_click_context()`:
121
141
 
122
142
  ```python
123
143
  @click.command()
@@ -127,7 +147,7 @@ def main(ctx, **kwargs):
127
147
  # Full source tracking with context
128
148
  config = AppArgs.from_click_context(ctx, **kwargs)
129
149
 
130
- # Now sources are accurate
150
+ # Check individual field sources
131
151
  print(config.source.name) # ValueSource.CLI
132
152
  print(config.source.age) # ValueSource.ENV
133
153
  print(config.source.verbose) # ValueSource.DEFAULT
@@ -137,11 +157,37 @@ def main(ctx, **kwargs):
137
157
  # {
138
158
  # ValueSource.CLI: ['name'],
139
159
  # ValueSource.ENV: ['age'],
160
+ # ValueSource.JSON: ['timeout'],
140
161
  # ValueSource.DEFAULT: ['verbose']
141
162
  # }
142
163
  ```
143
164
 
144
- **Note**: `from_click_context()` requires a Click context. If you don't need source tracking, use direct instantiation.
165
+ ### Comprehensive Example
166
+
167
+ See `examples/source_tracking_comprehensive.py` for a complete example showing all four sources working together. Run it with:
168
+
169
+ ```bash
170
+ # With defaults only
171
+ python examples/source_tracking_comprehensive.py
172
+
173
+ # With environment variables
174
+ export MYAPP_TIMEOUT=120
175
+ export MYAPP_DEBUG=true
176
+ python examples/source_tracking_comprehensive.py
177
+
178
+ # Mix all sources (CLI > ENV > JSON > DEFAULT)
179
+ export MYAPP_TIMEOUT=120
180
+ python examples/source_tracking_comprehensive.py --config examples/sample_config.json --port 3000
181
+ ```
182
+
183
+ **Output shows source for each field:**
184
+ ```
185
+ host = json-server.com [from JSON]
186
+ port = 3000 [from CLI] ← CLI overrides JSON
187
+ debug = True [from ENV]
188
+ timeout = 120 [from ENV]
189
+ log_level = DEBUG [from JSON]
190
+ ```
145
191
 
146
192
  ## Configuration Precedence
147
193
 
@@ -363,14 +409,11 @@ cd wry
363
409
  python -m venv venv
364
410
  source venv/bin/activate # On Windows: venv\Scripts\activate
365
411
 
366
- # Install Poetry (if not already installed)
367
- pip install poetry
368
-
369
- # Install all dependencies in development mode
370
- poetry install
412
+ # Install package in development mode with dev dependencies
413
+ pip install -e ".[dev]"
371
414
 
372
415
  # Install pre-commit hooks
373
- poetry run pre-commit install
416
+ pre-commit install
374
417
  ```
375
418
 
376
419
  ### Running Tests
@@ -431,8 +474,7 @@ To ensure consistent behavior between local development and CI:
431
474
  Install the exact versions used in CI:
432
475
 
433
476
  ```bash
434
- poetry update
435
- poetry install
477
+ pip install -e ".[dev]" --upgrade
436
478
  ```
437
479
 
438
480
  ### Coverage Requirements
@@ -517,42 +559,43 @@ We welcome contributions! Please follow these guidelines to ensure a smooth proc
517
559
 
518
560
  ### Development Setup
519
561
 
520
- We use Poetry for dependency management to ensure consistent environments:
562
+ We use standard Python virtual environments and pip for dependency management:
521
563
 
522
564
  ```bash
523
- # Install Poetry (if not already installed)
524
- curl -sSL https://install.python-poetry.org | python3 -
525
-
526
- # Install dependencies (including dev dependencies)
527
- poetry install
565
+ # Create virtual environment
566
+ python -m venv venv
567
+ source venv/bin/activate # On Windows: venv\Scripts\activate
528
568
 
529
- # Activate the virtual environment
530
- poetry shell
569
+ # Install package in development mode with all dependencies
570
+ pip install -e ".[dev]"
531
571
  ```
532
572
 
533
- **Important**: Poetry automatically creates an isolated virtual environment and uses `poetry.lock` to ensure everyone has the exact same dependencies.
573
+ **Note**: All dependencies are specified in `pyproject.toml`. The `[dev]` extra includes testing, linting, and development tools.
534
574
 
535
- ### Common Poetry Commands
575
+ ### Common Development Commands
536
576
 
537
577
  ```bash
538
- # Install dependencies from lock file
539
- poetry install
578
+ # Install package in editable mode
579
+ pip install -e ".[dev]"
540
580
 
541
- # Update dependencies within version constraints
542
- poetry update
581
+ # Update dependencies
582
+ pip install -e ".[dev]" --upgrade
543
583
 
544
- # Add a new dependency
545
- poetry add package-name
584
+ # Show installed packages
585
+ pip list
546
586
 
547
- # Add a development dependency
548
- poetry add --group dev package-name
587
+ # Run tests
588
+ pytest
549
589
 
550
- # Show installed packages
551
- poetry show
590
+ # Run with coverage
591
+ pytest --cov=wry
592
+
593
+ # Run linting
594
+ ruff check wry tests
595
+ ruff format wry tests
552
596
 
553
- # Run commands in the Poetry environment
554
- poetry run python script.py
555
- poetry run pytest
597
+ # Run type checking
598
+ mypy wry
556
599
  ```
557
600
 
558
601
  ### Getting Started
@@ -582,9 +625,10 @@ poetry run pytest
582
625
  1. **Set up development environment**:
583
626
 
584
627
  ```bash
585
- poetry install # Creates venv and installs all dependencies
586
- poetry shell # Activate the virtual environment
587
- poetry run pre-commit install # Set up git hooks
628
+ python -m venv venv # Create virtual environment
629
+ source venv/bin/activate # Activate it
630
+ pip install -e ".[dev]" # Install with dev dependencies
631
+ pre-commit install # Set up git hooks
588
632
  ```
589
633
 
590
634
  2. **Make your changes**:
@@ -597,13 +641,16 @@ poetry run pytest
597
641
 
598
642
  ```bash
599
643
  # Run tests
600
- poetry run pytest
644
+ pytest
601
645
 
602
- # Check coverage (must be 100%)
603
- poetry run pytest --cov=wry --cov-report=term-missing
646
+ # Check coverage (must be ≥90%)
647
+ pytest --cov=wry --cov-report=term-missing
604
648
 
605
649
  # Run linting
606
- poetry run pre-commit run --all-files
650
+ pre-commit run --all-files
651
+ # Or run individual tools:
652
+ ruff check wry tests
653
+ mypy wry
607
654
  ```
608
655
 
609
656
  4. **Commit your changes**:
@@ -709,4 +756,3 @@ If you're interested in this feature, please provide feedback!
709
756
  - Built on top of [Click](https://click.palletsprojects.com/) and [Pydantic](https://pydantic-docs.helpmanual.io/)
710
757
  - Inspired by the DRY (Don't Repeat Yourself) principle
711
758
  We'd also like to acknowledgme `pydanclick`, which uses a similar clean syntax (no kwargs to command functions). The code for this feature will be independently written given that `wry` supports source tracking, constraint help text creation, instantiation from config files, and several other features not supported by `pydanclick`.
712
-
@@ -1,16 +1,18 @@
1
- wry/__init__.py,sha256=KDP1HwNl2_eF0QDE6p-ST6YAjrATnifnqaG0ECPr29Q,3305
2
- wry/_version.py,sha256=qmVMHVs6fvYQY9UunIZhHjcS7ZXKE-ONNZzMlBtZL7w,520
1
+ wry/__init__.py,sha256=r42j1WbOhUjsB3lXyhX7H1vZATs2glLoeoxw69uAB_U,3496
2
+ wry/_version.py,sha256=6GrTD3GXfrueUne3XEARvK2os8mc6r-itoSIHvfA0Ok,717
3
3
  wry/auto_model.py,sha256=YY71mkYr46P3O4cjY8fN0AmothtPcvsDqvk1eQM4VbE,6927
4
4
  wry/click_integration.py,sha256=XDeNDHGh99Now77vrGMo151xp0KjWZYm7nTuIHh6CU4,31775
5
+ wry/help_system.py,sha256=zSryjsOXAWz9HyCpybwuFWrlaP9gwbMNIexuAWTcCns,5731
6
+ wry/multi_model.py,sha256=f6Hf5NMfIZtdXc6t00iTPtUEbiWnQZiC7NKVchQ7QU4,5978
7
+ wry/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
8
  wry/core/__init__.py,sha256=24Mu7qGzaFde8tAnyJOPPkD1ScZq-iSXNlDdAWSw_mg,894
6
9
  wry/core/accessors.py,sha256=Kn5dziklgcMWClOjbeJSwWNHOCQkpAWV9b1uH9ZGUPI,3708
7
10
  wry/core/env_utils.py,sha256=8TCgVPr7n5-YNThEVC5MvAG6qB0TW5MJkO1YT5yHZYI,4051
8
11
  wry/core/field_utils.py,sha256=nDFkbzfIf7mNJm6T5BuqcZ1mYUVIKinXfw77xpK_FK0,4134
9
12
  wry/core/model.py,sha256=CP0zElttAqpFHj2yD8O8CgMSm9VpSAT46nXcnCHw38U,25150
10
13
  wry/core/sources.py,sha256=4uboTc23f_CXiD3ql767-TvrGfe6xXN5NhXEIfNxD2U,1171
11
- wry/multi_model.py,sha256=f6Hf5NMfIZtdXc6t00iTPtUEbiWnQZiC7NKVchQ7QU4,5978
12
- wry/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- wry-0.2.3.dev1.dist-info/METADATA,sha256=viAAgfrP7T93g7xksj9_P9iTXjRx1b2G2-WQ-90Dm3g,19922
14
- wry-0.2.3.dev1.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
15
- wry-0.2.3.dev1.dist-info/licenses/LICENSE,sha256=0EfVapSdYZQRHpfqCVAO5OeyT2xMu8cxPKaRkWWdb2g,1068
16
- wry-0.2.3.dev1.dist-info/RECORD,,
14
+ wry-0.2.4.dev2.dist-info/licenses/LICENSE,sha256=0EfVapSdYZQRHpfqCVAO5OeyT2xMu8cxPKaRkWWdb2g,1068
15
+ wry-0.2.4.dev2.dist-info/METADATA,sha256=B269hopOo1ZmxLSonkPmMhwsisWk2D2u-yAcCBLVZ6g,21429
16
+ wry-0.2.4.dev2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
17
+ wry-0.2.4.dev2.dist-info/top_level.txt,sha256=ytpYWd5uCeQpPCdTYaB1Vjzp4C5em03WpUKn3SiDDY8,4
18
+ wry-0.2.4.dev2.dist-info/RECORD,,
@@ -1,4 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.2.1
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ wry