ostruct-cli 0.8.2__py3-none-any.whl → 0.8.3__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.
- ostruct/cli/click_options.py +111 -8
- ostruct/cli/code_interpreter.py +210 -17
- ostruct/cli/commands/run.py +56 -0
- ostruct/cli/config.py +20 -1
- ostruct/cli/errors.py +2 -30
- ostruct/cli/file_info.py +55 -20
- ostruct/cli/file_utils.py +19 -3
- ostruct/cli/json_extract.py +75 -0
- ostruct/cli/model_creation.py +1 -1
- ostruct/cli/runner.py +461 -180
- ostruct/cli/sentinel.py +29 -0
- ostruct/cli/template_optimizer.py +11 -7
- ostruct/cli/template_processor.py +243 -115
- ostruct/cli/template_rendering.py +41 -1
- ostruct/cli/template_validation.py +41 -3
- ostruct/cli/types.py +14 -1
- {ostruct_cli-0.8.2.dist-info → ostruct_cli-0.8.3.dist-info}/METADATA +88 -2
- {ostruct_cli-0.8.2.dist-info → ostruct_cli-0.8.3.dist-info}/RECORD +21 -19
- {ostruct_cli-0.8.2.dist-info → ostruct_cli-0.8.3.dist-info}/LICENSE +0 -0
- {ostruct_cli-0.8.2.dist-info → ostruct_cli-0.8.3.dist-info}/WHEEL +0 -0
- {ostruct_cli-0.8.2.dist-info → ostruct_cli-0.8.3.dist-info}/entry_points.txt +0 -0
@@ -50,6 +50,7 @@ Notes:
|
|
50
50
|
"""
|
51
51
|
|
52
52
|
import logging
|
53
|
+
import re
|
53
54
|
from typing import (
|
54
55
|
Any,
|
55
56
|
Callable,
|
@@ -150,6 +151,45 @@ def find_loop_vars(nodes: List[Node]) -> Set[str]:
|
|
150
151
|
return loop_vars
|
151
152
|
|
152
153
|
|
154
|
+
def _extract_variable_name_from_jinja_error(error_message: str) -> str:
|
155
|
+
"""Extract the actual variable name from a Jinja2 UndefinedError message.
|
156
|
+
|
157
|
+
Handles various Jinja2 error message formats:
|
158
|
+
- "'variable_name' is undefined"
|
159
|
+
- "'object_description' has no attribute 'property_name'"
|
160
|
+
- Other formats
|
161
|
+
|
162
|
+
Args:
|
163
|
+
error_message: The string representation of the Jinja2 UndefinedError
|
164
|
+
|
165
|
+
Returns:
|
166
|
+
The extracted variable name, or a sanitized version if parsing fails
|
167
|
+
"""
|
168
|
+
# Pattern 1: Standard undefined variable: "'variable_name' is undefined"
|
169
|
+
match = re.match(r"'([^']+)' is undefined", error_message)
|
170
|
+
if match:
|
171
|
+
return match.group(1)
|
172
|
+
|
173
|
+
# Pattern 2: Attribute access on object: "'object' has no attribute 'property'"
|
174
|
+
# In this case, we want to extract just the property name, not the object description
|
175
|
+
match = re.match(r"'[^']+' has no attribute '([^']+)'", error_message)
|
176
|
+
if match:
|
177
|
+
property_name = match.group(1)
|
178
|
+
return property_name
|
179
|
+
|
180
|
+
# Pattern 3: Try to find any quoted identifier that looks like a variable name
|
181
|
+
# Look for quoted strings that contain only valid Python identifier characters
|
182
|
+
quoted_parts: List[str] = re.findall(r"'([^']+)'", error_message)
|
183
|
+
for part in quoted_parts:
|
184
|
+
# Check if this looks like a variable name (not a class name or description)
|
185
|
+
if re.match(r"^[a-zA-Z_][a-zA-Z0-9_]*$", part) and "." not in part:
|
186
|
+
return part
|
187
|
+
|
188
|
+
# Fallback: If we can't parse it properly, return a generic message
|
189
|
+
# This avoids exposing internal class names to users
|
190
|
+
return "unknown_variable"
|
191
|
+
|
192
|
+
|
153
193
|
def validate_template_placeholders(
|
154
194
|
template: str, template_context: Optional[Dict[str, Any]] = None
|
155
195
|
) -> None:
|
@@ -343,9 +383,7 @@ def validate_template_placeholders(
|
|
343
383
|
env.from_string(template).render(validation_context)
|
344
384
|
except jinja2.UndefinedError as e:
|
345
385
|
# Convert Jinja2 undefined errors to TaskTemplateVariableError with helpful message
|
346
|
-
var_name = str(e)
|
347
|
-
1
|
348
|
-
] # Extract variable name from error message
|
386
|
+
var_name = _extract_variable_name_from_jinja_error(str(e))
|
349
387
|
error_msg = (
|
350
388
|
f"Missing required template variable: {var_name}\n"
|
351
389
|
f"Available variables: {', '.join(sorted(available_vars))}\n"
|
ostruct/cli/types.py
CHANGED
@@ -35,7 +35,6 @@ class CLIParams(TypedDict, total=False):
|
|
35
35
|
no_progress: bool
|
36
36
|
api_key: Optional[str]
|
37
37
|
verbose: bool
|
38
|
-
debug_openai_stream: bool
|
39
38
|
show_model_schema: bool
|
40
39
|
debug_validation: bool
|
41
40
|
temperature: Optional[float]
|
@@ -76,3 +75,17 @@ class CLIParams(TypedDict, total=False):
|
|
76
75
|
tool_files: List[
|
77
76
|
Tuple[str, str]
|
78
77
|
] # List of (tool, path) tuples from --file-for
|
78
|
+
web_search: bool
|
79
|
+
debug: bool
|
80
|
+
show_templates: bool
|
81
|
+
debug_templates: bool
|
82
|
+
show_context: bool
|
83
|
+
show_context_detailed: bool
|
84
|
+
show_pre_optimization: bool
|
85
|
+
show_optimization_diff: bool
|
86
|
+
no_optimization: bool
|
87
|
+
show_optimization_steps: bool
|
88
|
+
optimization_step_detail: str
|
89
|
+
help_debug: bool
|
90
|
+
enabled_features: List[str] # List of feature names to enable
|
91
|
+
disabled_features: List[str] # List of feature names to disable
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: ostruct-cli
|
3
|
-
Version: 0.8.
|
3
|
+
Version: 0.8.3
|
4
4
|
Summary: CLI for OpenAI Structured Output with Multi-Tool Integration
|
5
5
|
Author: Yaniv Golan
|
6
6
|
Author-email: yaniv@golan.name
|
@@ -22,6 +22,7 @@ Requires-Dist: chardet (>=5.0.0,<6.0)
|
|
22
22
|
Requires-Dist: click (>=8.1.7,<9.0)
|
23
23
|
Requires-Dist: flake8 (>=6.0,<7.0) ; extra == "dev"
|
24
24
|
Requires-Dist: flake8-pyproject (>=1.2.3,<2.0) ; extra == "dev"
|
25
|
+
Requires-Dist: hypothesis (>=6.0.0,<7.0) ; extra == "dev"
|
25
26
|
Requires-Dist: ijson (>=3.2.3,<4.0)
|
26
27
|
Requires-Dist: jinja2 (>=3.1.2,<4.0)
|
27
28
|
Requires-Dist: jsonschema (>=4.23.0,<5.0)
|
@@ -37,6 +38,7 @@ Requires-Dist: pygments (>=2.15.0,<3.0)
|
|
37
38
|
Requires-Dist: pytest (>=8.3.4,<9.0) ; extra == "dev"
|
38
39
|
Requires-Dist: pytest-asyncio (>=0.25.2,<1.0) ; extra == "dev"
|
39
40
|
Requires-Dist: pytest-mock (>=3.14.0,<4.0) ; extra == "dev"
|
41
|
+
Requires-Dist: pytest-rerunfailures (>=12.0,<13.0) ; extra == "dev"
|
40
42
|
Requires-Dist: python-dotenv (>=1.0.1,<2.0) ; extra == "dev"
|
41
43
|
Requires-Dist: pyyaml (>=6.0.2,<7.0)
|
42
44
|
Requires-Dist: sphinx (>=7.0,<8.0) ; extra == "dev"
|
@@ -302,7 +304,7 @@ ostruct run analysis.j2 schema.json -fc data.csv
|
|
302
304
|
ostruct run search.j2 schema.json -fs documentation.pdf
|
303
305
|
|
304
306
|
# Web Search (real-time information)
|
305
|
-
ostruct run research.j2 schema.json --web-search -V topic="latest AI developments"
|
307
|
+
ostruct run research.j2 schema.json --enable-tool web-search -V topic="latest AI developments"
|
306
308
|
|
307
309
|
# Multiple tools with one file
|
308
310
|
ostruct run template.j2 schema.json --file-for code-interpreter shared.json --file-for file-search shared.json
|
@@ -370,6 +372,7 @@ tools:
|
|
370
372
|
code_interpreter:
|
371
373
|
auto_download: true
|
372
374
|
output_directory: "./output"
|
375
|
+
download_strategy: "two_pass_sentinel" # Enable reliable file downloads
|
373
376
|
|
374
377
|
mcp:
|
375
378
|
custom_server: "https://my-mcp-server.com"
|
@@ -384,6 +387,35 @@ Load custom configuration:
|
|
384
387
|
ostruct --config my-config.yaml run template.j2 schema.json
|
385
388
|
```
|
386
389
|
|
390
|
+
### Code Interpreter File Downloads
|
391
|
+
|
392
|
+
**Important**: If you're using Code Interpreter with structured output (JSON schemas), you may need to enable the two-pass download strategy to ensure files are downloaded reliably.
|
393
|
+
|
394
|
+
#### Option 1: CLI Flags (Recommended for one-off usage)
|
395
|
+
|
396
|
+
```bash
|
397
|
+
# Enable reliable file downloads for this run
|
398
|
+
ostruct run template.j2 schema.json -fc data.csv --enable-feature ci-download-hack
|
399
|
+
|
400
|
+
# Force single-pass mode (override config)
|
401
|
+
ostruct run template.j2 schema.json -fc data.csv --disable-feature ci-download-hack
|
402
|
+
```
|
403
|
+
|
404
|
+
#### Option 2: Configuration File (Recommended for persistent settings)
|
405
|
+
|
406
|
+
```yaml
|
407
|
+
# ostruct.yaml
|
408
|
+
tools:
|
409
|
+
code_interpreter:
|
410
|
+
download_strategy: "two_pass_sentinel" # Enables reliable file downloads
|
411
|
+
auto_download: true
|
412
|
+
output_directory: "./downloads"
|
413
|
+
```
|
414
|
+
|
415
|
+
**Why this is needed**: OpenAI's structured output mode can prevent file download annotations from being generated. The two-pass strategy works around this by making two API calls: one to generate files (without structured output), then another to ensure schema compliance. For detailed technical information, see [docs/known-issues/2025-06-responses-ci-file-output.md](docs/known-issues/2025-06-responses-ci-file-output.md).
|
416
|
+
|
417
|
+
**Performance**: The two-pass strategy approximately doubles token usage but ensures reliable file downloads when using structured output with Code Interpreter.
|
418
|
+
|
387
419
|
## Get Started Quickly
|
388
420
|
|
389
421
|
🚀 **New to ostruct?** Follow our [step-by-step quickstart guide](https://ostruct.readthedocs.io/en/latest/user-guide/quickstart.html) featuring Juno the beagle for a hands-on introduction.
|
@@ -628,6 +660,60 @@ The registry file is stored at `~/.openai_structured/config/models.yml` and is a
|
|
628
660
|
|
629
661
|
The update command uses HTTP conditional requests (If-Modified-Since headers) to check if the remote registry has changed before downloading, ensuring efficient updates.
|
630
662
|
|
663
|
+
# Testing
|
664
|
+
|
665
|
+
## Running Tests
|
666
|
+
|
667
|
+
The test suite is divided into two categories:
|
668
|
+
|
669
|
+
### Regular Tests (Default)
|
670
|
+
|
671
|
+
```bash
|
672
|
+
# Run all tests (skips live tests by default)
|
673
|
+
pytest
|
674
|
+
|
675
|
+
# Run specific test file
|
676
|
+
pytest tests/test_config.py
|
677
|
+
|
678
|
+
# Run with verbose output
|
679
|
+
pytest -v
|
680
|
+
```
|
681
|
+
|
682
|
+
### Live Tests
|
683
|
+
|
684
|
+
Live tests make real API calls to OpenAI and require a valid API key. They are skipped by default.
|
685
|
+
|
686
|
+
```bash
|
687
|
+
# Run only live tests (requires OPENAI_API_KEY)
|
688
|
+
pytest -m live
|
689
|
+
|
690
|
+
# Run all tests including live tests
|
691
|
+
pytest -m "live or not live"
|
692
|
+
|
693
|
+
# Run specific live test
|
694
|
+
pytest tests/test_responses_annotations.py -m live
|
695
|
+
```
|
696
|
+
|
697
|
+
**Live tests include:**
|
698
|
+
|
699
|
+
- Tests that make actual OpenAI API calls
|
700
|
+
- Tests that run `ostruct` commands via subprocess
|
701
|
+
- Tests that verify real API behavior and file downloads
|
702
|
+
|
703
|
+
**Requirements for live tests:**
|
704
|
+
|
705
|
+
- Valid `OPENAI_API_KEY` environment variable
|
706
|
+
- Internet connection
|
707
|
+
- May incur API costs
|
708
|
+
|
709
|
+
## Test Markers
|
710
|
+
|
711
|
+
- `@pytest.mark.live` - Tests that make real API calls or run actual commands
|
712
|
+
- `@pytest.mark.no_fs` - Tests that need real filesystem (not pyfakefs)
|
713
|
+
- `@pytest.mark.slow` - Performance/stress tests
|
714
|
+
- `@pytest.mark.flaky` - Tests that may need reruns
|
715
|
+
- `@pytest.mark.mock_openai` - Tests using mocked OpenAI client
|
716
|
+
|
631
717
|
<!--
|
632
718
|
MAINTAINER NOTE: After editing this README, please test GitHub rendering by:
|
633
719
|
1. Creating a draft PR or pushing to a test branch
|
@@ -3,31 +3,32 @@ ostruct/cli/__init__.py,sha256=e-DtWRviCr3fIAJH4cB4UAvles3-rqnhJaTOlBn9TKs,871
|
|
3
3
|
ostruct/cli/base_errors.py,sha256=o-877bJJA8yJWISRPy0KyL6wDu1-_avddmQIfVePuFM,5989
|
4
4
|
ostruct/cli/cache_manager.py,sha256=ej3KrRfkKKZ_lEp2JswjbJ5bW2ncsvna9NeJu81cqqs,5192
|
5
5
|
ostruct/cli/cli.py,sha256=ZUkQ-iwk4KCKeetPMlvSDwxfXIe4h1-yP80SfJgvi_o,4098
|
6
|
-
ostruct/cli/click_options.py,sha256=
|
7
|
-
ostruct/cli/code_interpreter.py,sha256=
|
6
|
+
ostruct/cli/click_options.py,sha256=FbRMfoFgg5icdgewPS8cePSYv6yTnxbRxyDvfFDdRaI,31845
|
7
|
+
ostruct/cli/code_interpreter.py,sha256=lnnyEvUh2pGObN9ENpr-X4p0C0oIWiyG1CFQWW4akBQ,16726
|
8
8
|
ostruct/cli/commands/__init__.py,sha256=3NHz-WZ9XqrnWWMksoV2MpYpHnjA-EO9lsrBOYeHcjY,723
|
9
9
|
ostruct/cli/commands/list_models.py,sha256=yeuQpUGAmRr4uOHS7teuVHkC9dkqN0yKDOEw_n-ehi0,4662
|
10
10
|
ostruct/cli/commands/quick_ref.py,sha256=zpD7kI3sfrcc9CiRkzWdASTNX5jAk3HFB7MilzlCsag,2004
|
11
|
-
ostruct/cli/commands/run.py,sha256=
|
11
|
+
ostruct/cli/commands/run.py,sha256=Cm9Yuf0DLt5CqKfgAYubhQRcvLdK1vqIIuz_ynjfhQ4,6640
|
12
12
|
ostruct/cli/commands/update_registry.py,sha256=7DQrPlCJScPVgE2HbFAM7UMap-EdYu58AQWfpI-H7Gw,2483
|
13
|
-
ostruct/cli/config.py,sha256=
|
13
|
+
ostruct/cli/config.py,sha256=7tKI1gWLpTISn5OorGWIx66N1J7XW2aq30hPNISZzQ0,9958
|
14
14
|
ostruct/cli/cost_estimation.py,sha256=08hyE-kM5QYzj7y-KB3lMD_RxCMoM_Ve3-IQlSpJAo4,4483
|
15
|
-
ostruct/cli/errors.py,sha256=
|
15
|
+
ostruct/cli/errors.py,sha256=sVOM_ZKvrtnmT8_WR-DfX2crs6HmvmwrbNQlxm-5_Ew,24669
|
16
16
|
ostruct/cli/exit_codes.py,sha256=gdvB1dpu0LalEUZrofpk5K6aTQ24n5AfkAK5umludHU,365
|
17
17
|
ostruct/cli/explicit_file_processor.py,sha256=B6yUPbyn6MVd81GcyMVpORFwyaHFFESLwFixp2B6M5w,19767
|
18
18
|
ostruct/cli/field_utils.py,sha256=bcRi1qQ0Ac2UCfrKSQ677_yu-VzaShm_zN7QLf98qc0,1939
|
19
|
-
ostruct/cli/file_info.py,sha256=
|
19
|
+
ostruct/cli/file_info.py,sha256=s8AHPtyU3__2LRJCCIEPuODYM43is4Y2Q_VDhBOl3XU,17395
|
20
20
|
ostruct/cli/file_list.py,sha256=alRAguq4tj1zH0_qlWaRoyHo1G1Xmxqu9Xd4QP-zYP0,20268
|
21
21
|
ostruct/cli/file_search.py,sha256=N12mkji2ttvItLVPyAWE3KEfhTv8hV5IXPrQME2UFdE,15313
|
22
|
-
ostruct/cli/file_utils.py,sha256=
|
22
|
+
ostruct/cli/file_utils.py,sha256=JZprQ-1LHQzI3eBfeCIS6VmxTa2fGUZHygGC8gcwpJM,24367
|
23
|
+
ostruct/cli/json_extract.py,sha256=ZleIxat8g-JnA9VVqWgJaKxN7QzL25itQ8aP0Gb5e4Q,2650
|
23
24
|
ostruct/cli/mcp_integration.py,sha256=EXIz_KbYC4srWZxuKVkINeaHgHvEYB9l1uhptpLNn5I,18774
|
24
|
-
ostruct/cli/model_creation.py,sha256=
|
25
|
+
ostruct/cli/model_creation.py,sha256=HGo8Qv7eBF8Co463IR7RcbTCQcaOvd_cBGuRodRCAa4,23261
|
25
26
|
ostruct/cli/model_validation.py,sha256=j2az3q88-Ljm2cMMgZ8p_-gcp1vKQnWCknnw0y0YlAw,6675
|
26
27
|
ostruct/cli/path_utils.py,sha256=j44q1OoLkqMErgK-qEuhuIZ1VyzqRIvNgxR1et9PoXA,4813
|
27
28
|
ostruct/cli/progress.py,sha256=rj9nVEco5UeZORMbzd7mFJpFGJjbH9KbBFh5oTE5Anw,3415
|
28
29
|
ostruct/cli/progress_reporting.py,sha256=MBjALM4pmPd_d9YuXqH162-tkC6DDKYmz-pJPSGLTfk,13669
|
29
30
|
ostruct/cli/registry_updates.py,sha256=ohiHdlfrocvThpR_ZjMyqulDKFjRM1hIFKOlNzpaqHg,5138
|
30
|
-
ostruct/cli/runner.py,sha256=
|
31
|
+
ostruct/cli/runner.py,sha256=_xiT9_ywk5lNz3P1qFpqOcJGwXqAE4xQ8Zxc9p6x0Ko,65192
|
31
32
|
ostruct/cli/schema_utils.py,sha256=9LnsjxEKg6RIfXQB3nS3pyDggm5n-4-thXf92897gJU,3590
|
32
33
|
ostruct/cli/schema_validation.py,sha256=ohEuxJ0KF93qphj0JSZDnrxDn0C2ZU37g-U2JY03onM,8154
|
33
34
|
ostruct/cli/security/__init__.py,sha256=CQpkCgTFYlA1p6atpQeNgIKtE4LZGUKt4EbytbGKpCs,846
|
@@ -41,6 +42,7 @@ ostruct/cli/security/security_manager.py,sha256=HFCqJ5kAhaZlFnPTEs6MKNM8JeE2q79d
|
|
41
42
|
ostruct/cli/security/symlink_resolver.py,sha256=wtZdJ_T_0FOy6B1P5ty1odEXQk9vr8BzlWeAFD4huJE,16744
|
42
43
|
ostruct/cli/security/types.py,sha256=15yuG_T4CXyAFFFdSWLjVS7ACmDGIPXhQpZ8awcDwCQ,2991
|
43
44
|
ostruct/cli/security/windows_paths.py,sha256=qxC2H2kLwtmQ7YePYde3UrmOJcGnsLEebDLh242sUaI,13453
|
45
|
+
ostruct/cli/sentinel.py,sha256=69faYPrhVJmEpYNLsCtf1HF96aan3APqXZdIjxBNZYo,798
|
44
46
|
ostruct/cli/serialization.py,sha256=ec0UswDE2onwtZVUoZaMCsGv6zW_tSKdBng2qVo6Ucs,704
|
45
47
|
ostruct/cli/services.py,sha256=nLYUbF3DDNuilh7j9q_atUOjTAWta7bxTS3G-zkveaA,21621
|
46
48
|
ostruct/cli/template_debug.py,sha256=1tP3pTdvQwHcMneYnpWnS2Jr5EQijjyCSQDh5DPXvDE,24698
|
@@ -49,21 +51,21 @@ ostruct/cli/template_env.py,sha256=7ZcGKyqlkV-ZS2sSUvzyaLsnlvPmfCKUG0epIV8TD6o,1
|
|
49
51
|
ostruct/cli/template_extensions.py,sha256=_lomtDGMGxMfpw05v_-daJ0JbhRm_r_-uEJlPAjbpkI,2699
|
50
52
|
ostruct/cli/template_filters.py,sha256=S9ad8she0lXRr0PDQVkNrPWbZg7GnybptEXUMkQKOyo,20657
|
51
53
|
ostruct/cli/template_io.py,sha256=yUWO-8rZnSdX97DTMSEX8fG9CP1ISsOhm2NZN3Fab9A,8821
|
52
|
-
ostruct/cli/template_optimizer.py,sha256=
|
53
|
-
ostruct/cli/template_processor.py,sha256=
|
54
|
-
ostruct/cli/template_rendering.py,sha256=
|
54
|
+
ostruct/cli/template_optimizer.py,sha256=gwngZ5XrIkU5BrjFibWT0VRf9WrH6NS4SAlrUzme1C8,16684
|
55
|
+
ostruct/cli/template_processor.py,sha256=hp9_ZQmVdN6JwCSQJoHB1mVq_p0sTZSojb7c4Y4Vjvs,47301
|
56
|
+
ostruct/cli/template_rendering.py,sha256=41f6An7cpI04z2qyesmnXgPVMD1je3ePA6Xz8uuA06U,16705
|
55
57
|
ostruct/cli/template_schema.py,sha256=ckH4rUZnEgfm_BHS9LnMGr8LtDxRmZ0C6UBVrSp8KTc,19604
|
56
58
|
ostruct/cli/template_utils.py,sha256=MZdXXjL-x-IXX-5Y8GWopGNBkDE2ItLdCuCl0QWFR_U,14968
|
57
|
-
ostruct/cli/template_validation.py,sha256=
|
59
|
+
ostruct/cli/template_validation.py,sha256=9L1JgM87NIV8JZUoDUT4dRjSDfBl9L8Yl2aVL_ahkmA,14294
|
58
60
|
ostruct/cli/token_utils.py,sha256=r4KPEO3Sec18Q6mU0aClK6XGShvusgUggXEQgEPPlaA,1369
|
59
61
|
ostruct/cli/token_validation.py,sha256=gmyPJ7B2gC_jSx_1wKZq87DEoFulj23X1XnVpO_aRNA,9930
|
60
|
-
ostruct/cli/types.py,sha256=
|
62
|
+
ostruct/cli/types.py,sha256=6nARJ4MF5HIank0t6KGU-PPHC0VpFh3R8fNJZBXwgbA,2903
|
61
63
|
ostruct/cli/unattended_operation.py,sha256=kI95SSVJC_taxORXQYrce_qLEnuKc6edwn9tMOye-qs,9383
|
62
64
|
ostruct/cli/utils.py,sha256=uY7c0NaINHWfnl77FcPE3TmYUXv3RqEeUTjrCMDij9A,922
|
63
65
|
ostruct/cli/validators.py,sha256=lbxAUUVS5TPJ7HdYZ5yB7gUjJqfcClZCuh0oktoq0E0,15291
|
64
66
|
ostruct/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
65
|
-
ostruct_cli-0.8.
|
66
|
-
ostruct_cli-0.8.
|
67
|
-
ostruct_cli-0.8.
|
68
|
-
ostruct_cli-0.8.
|
69
|
-
ostruct_cli-0.8.
|
67
|
+
ostruct_cli-0.8.3.dist-info/LICENSE,sha256=DmGAkaYzhrdzTB9Y2Rvfzd3mJiF9ZrTOhxN8t6wrfHA,1098
|
68
|
+
ostruct_cli-0.8.3.dist-info/METADATA,sha256=mBsqO645XWKto3RgifluCxqkilYH0C14wWrm1Pa6P6I,24827
|
69
|
+
ostruct_cli-0.8.3.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
70
|
+
ostruct_cli-0.8.3.dist-info/entry_points.txt,sha256=NFq9IuqHVTem0j9zKjV8C1si_zGcP1RL6Wbvt9fUDXw,48
|
71
|
+
ostruct_cli-0.8.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|