ostruct-cli 0.8.8__py3-none-any.whl → 0.8.29__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/cli.py +30 -0
- ostruct/cli/errors.py +16 -1
- ostruct/cli/file_info.py +28 -6
- ostruct/cli/file_list.py +39 -0
- ostruct/cli/utils.py +30 -0
- ostruct/cli/validators.py +17 -0
- {ostruct_cli-0.8.8.dist-info → ostruct_cli-0.8.29.dist-info}/METADATA +78 -15
- {ostruct_cli-0.8.8.dist-info → ostruct_cli-0.8.29.dist-info}/RECORD +11 -11
- {ostruct_cli-0.8.8.dist-info → ostruct_cli-0.8.29.dist-info}/LICENSE +0 -0
- {ostruct_cli-0.8.8.dist-info → ostruct_cli-0.8.29.dist-info}/WHEEL +0 -0
- {ostruct_cli-0.8.8.dist-info → ostruct_cli-0.8.29.dist-info}/entry_points.txt +0 -0
ostruct/cli/cli.py
CHANGED
@@ -18,6 +18,33 @@ from .errors import (
|
|
18
18
|
)
|
19
19
|
from .exit_codes import ExitCode
|
20
20
|
from .registry_updates import get_update_notification
|
21
|
+
from .utils import fix_surrogate_escapes
|
22
|
+
|
23
|
+
|
24
|
+
def fix_argv_encoding() -> None:
|
25
|
+
"""Fix UTF-8 encoding issues in sys.argv.
|
26
|
+
|
27
|
+
This function addresses the surrogate escape issue where Python's sys.argv
|
28
|
+
contains surrogate characters (e.g., a backslash followed by 'udce2')
|
29
|
+
when processing command line arguments with non-ASCII characters. This
|
30
|
+
commonly happens with filenames containing characters like en dash (–) or
|
31
|
+
other Unicode characters.
|
32
|
+
|
33
|
+
The fix detects arguments containing surrogate escapes and converts them
|
34
|
+
back to proper UTF-8 strings.
|
35
|
+
"""
|
36
|
+
try:
|
37
|
+
fixed_argv = []
|
38
|
+
for arg in sys.argv:
|
39
|
+
fixed_argv.append(fix_surrogate_escapes(arg))
|
40
|
+
|
41
|
+
# Replace sys.argv with the fixed version
|
42
|
+
sys.argv = fixed_argv
|
43
|
+
|
44
|
+
except Exception:
|
45
|
+
# If anything goes wrong with the encoding fix, continue with original argv
|
46
|
+
# This ensures the CLI doesn't break even if the fix fails
|
47
|
+
pass
|
21
48
|
|
22
49
|
|
23
50
|
def create_cli_group() -> click.Group:
|
@@ -108,6 +135,9 @@ def create_cli() -> click.Command:
|
|
108
135
|
|
109
136
|
def main() -> None:
|
110
137
|
"""Main entry point for the CLI."""
|
138
|
+
# Fix UTF-8 encoding issues in command line arguments before processing
|
139
|
+
fix_argv_encoding()
|
140
|
+
|
111
141
|
# Load environment variables from .env file
|
112
142
|
load_dotenv()
|
113
143
|
|
ostruct/cli/errors.py
CHANGED
@@ -291,7 +291,22 @@ class TemplateValidationError(TaskTemplateError):
|
|
291
291
|
class SystemPromptError(TaskTemplateError):
|
292
292
|
"""Raised when there are issues with system prompt loading or processing."""
|
293
293
|
|
294
|
-
|
294
|
+
def __init__(
|
295
|
+
self,
|
296
|
+
message: str,
|
297
|
+
context: Optional[Dict[str, Any]] = None,
|
298
|
+
) -> None:
|
299
|
+
"""Initialize system prompt error.
|
300
|
+
|
301
|
+
Args:
|
302
|
+
message: Error message
|
303
|
+
context: Additional error context
|
304
|
+
"""
|
305
|
+
super().__init__(
|
306
|
+
message,
|
307
|
+
context=context,
|
308
|
+
exit_code=ExitCode.VALIDATION_ERROR,
|
309
|
+
)
|
295
310
|
|
296
311
|
|
297
312
|
class SchemaError(CLIError):
|
ostruct/cli/file_info.py
CHANGED
@@ -156,23 +156,45 @@ class FileInfo:
|
|
156
156
|
Returns a path relative to the security manager's base directory.
|
157
157
|
This ensures consistent path handling across the entire codebase.
|
158
158
|
|
159
|
+
For paths outside the base directory but within allowed directories,
|
160
|
+
returns the absolute path.
|
161
|
+
|
159
162
|
Example:
|
160
163
|
security_manager = SecurityManager(base_dir="/base")
|
161
164
|
file_info = FileInfo("/base/file.txt", security_manager)
|
162
165
|
print(file_info.path) # Outputs: "file.txt"
|
163
166
|
|
167
|
+
# With allowed directory outside base:
|
168
|
+
file_info = FileInfo("/tmp/file.txt", security_manager)
|
169
|
+
print(file_info.path) # Outputs: "/tmp/file.txt"
|
170
|
+
|
164
171
|
Returns:
|
165
|
-
str: Path relative to security manager's base directory
|
172
|
+
str: Path relative to security manager's base directory, or absolute path
|
173
|
+
if outside base directory but within allowed directories
|
166
174
|
|
167
175
|
Raises:
|
168
|
-
ValueError: If the path is not within the base directory
|
176
|
+
ValueError: If the path is not within the base directory or allowed directories
|
169
177
|
"""
|
178
|
+
abs_path = Path(self.abs_path)
|
179
|
+
base_dir = Path(self.__security_manager.base_dir)
|
180
|
+
|
170
181
|
try:
|
171
|
-
abs_path = Path(self.abs_path)
|
172
|
-
base_dir = Path(self.__security_manager.base_dir)
|
173
182
|
return str(abs_path.relative_to(base_dir))
|
174
|
-
except ValueError
|
175
|
-
|
183
|
+
except ValueError:
|
184
|
+
# Path is outside base_dir, check if it's in allowed directories
|
185
|
+
if self.__security_manager.is_path_allowed(abs_path):
|
186
|
+
logger.debug(
|
187
|
+
"Path outside base_dir but allowed, returning absolute path: %s",
|
188
|
+
abs_path,
|
189
|
+
)
|
190
|
+
return str(abs_path)
|
191
|
+
|
192
|
+
# Should never reach here if SecurityManager validation was done properly
|
193
|
+
logger.error(
|
194
|
+
"Error making path relative: %s is not within base directory %s",
|
195
|
+
abs_path,
|
196
|
+
base_dir,
|
197
|
+
)
|
176
198
|
raise ValueError(
|
177
199
|
f"Path {abs_path} must be within base directory {base_dir}"
|
178
200
|
)
|
ostruct/cli/file_list.py
CHANGED
@@ -320,6 +320,45 @@ class FileInfoList(List[FileInfo]):
|
|
320
320
|
# Single file from file mapping
|
321
321
|
return self[0].name
|
322
322
|
|
323
|
+
@property
|
324
|
+
def extension(self) -> str:
|
325
|
+
"""Get the file extension of a single file without dot.
|
326
|
+
|
327
|
+
Returns:
|
328
|
+
str: Extension of the single file from file mapping.
|
329
|
+
|
330
|
+
Raises:
|
331
|
+
ValueError: If the list is empty or contains multiple files.
|
332
|
+
"""
|
333
|
+
with self._lock:
|
334
|
+
if not self:
|
335
|
+
var_name = self._var_alias or "file_list"
|
336
|
+
raise ValueError(
|
337
|
+
f"No files in '{var_name}'. Cannot access .extension property."
|
338
|
+
)
|
339
|
+
|
340
|
+
# Check for multiple files or directory mapping
|
341
|
+
if len(self) > 1:
|
342
|
+
var_name = self._var_alias or "file_list"
|
343
|
+
raise ValueError(
|
344
|
+
f"'{var_name}' contains {len(self)} files. "
|
345
|
+
f"Use '{{{{ {var_name}[0].extension }}}}' for the first file, "
|
346
|
+
f"'{{{{ {var_name}|single.extension }}}}' if expecting exactly one file, "
|
347
|
+
f"or loop over files with '{{%% for file in {var_name} %%}}{{{{ file.extension }}}}{{%% endfor %%}}'."
|
348
|
+
)
|
349
|
+
|
350
|
+
if self._from_dir:
|
351
|
+
var_name = self._var_alias or "file_list"
|
352
|
+
raise ValueError(
|
353
|
+
f"'{var_name}' contains files from directory mapping. "
|
354
|
+
f"Use '{{{{ {var_name}[0].extension }}}}' for the first file, "
|
355
|
+
f"'{{{{ {var_name}|single.extension }}}}' if expecting exactly one file, "
|
356
|
+
f"or loop over files with '{{%% for file in {var_name} %%}}{{{{ file.extension }}}}{{%% endfor %%}}'."
|
357
|
+
)
|
358
|
+
|
359
|
+
# Single file from file mapping
|
360
|
+
return self[0].extension
|
361
|
+
|
323
362
|
@property
|
324
363
|
def names(self) -> List[str]:
|
325
364
|
"""Get all filenames as a list."""
|
ostruct/cli/utils.py
CHANGED
@@ -5,6 +5,36 @@ from typing import Tuple
|
|
5
5
|
from .errors import VariableNameError, VariableValueError
|
6
6
|
|
7
7
|
|
8
|
+
def fix_surrogate_escapes(text: str) -> str:
|
9
|
+
"""Fix UTF-8 encoding issues caused by surrogate escapes.
|
10
|
+
|
11
|
+
This function addresses the issue where Python's sys.argv contains
|
12
|
+
surrogate characters (e.g., a backslash followed by 'udce2') when
|
13
|
+
processing command line arguments with non-ASCII characters. This
|
14
|
+
commonly happens with filenames containing characters like en dash (–)
|
15
|
+
or other Unicode characters.
|
16
|
+
|
17
|
+
Args:
|
18
|
+
text: String that may contain surrogate escape characters
|
19
|
+
|
20
|
+
Returns:
|
21
|
+
String with surrogate escapes converted back to proper UTF-8
|
22
|
+
"""
|
23
|
+
try:
|
24
|
+
# Check if the text contains surrogate characters
|
25
|
+
if any(0xDC00 <= ord(c) <= 0xDFFF for c in text):
|
26
|
+
# Convert surrogate escapes back to bytes, then decode as UTF-8
|
27
|
+
# This handles the case where Python used surrogateescape error handling
|
28
|
+
byte_data = text.encode("utf-8", "surrogateescape")
|
29
|
+
return byte_data.decode("utf-8")
|
30
|
+
else:
|
31
|
+
# No surrogate characters, return as-is
|
32
|
+
return text
|
33
|
+
except (UnicodeError, UnicodeDecodeError, UnicodeEncodeError):
|
34
|
+
# If conversion fails, return the original text
|
35
|
+
return text
|
36
|
+
|
37
|
+
|
8
38
|
def parse_mapping(mapping: str) -> Tuple[str, str]:
|
9
39
|
"""Parse a mapping string in the format 'name=value'.
|
10
40
|
|
ostruct/cli/validators.py
CHANGED
@@ -26,6 +26,7 @@ from .template_processor import (
|
|
26
26
|
)
|
27
27
|
from .template_utils import validate_json_schema
|
28
28
|
from .types import CLIParams
|
29
|
+
from .utils import fix_surrogate_escapes
|
29
30
|
|
30
31
|
logger = logging.getLogger(__name__)
|
31
32
|
|
@@ -145,6 +146,9 @@ def validate_variable(
|
|
145
146
|
|
146
147
|
result = []
|
147
148
|
for var in value:
|
149
|
+
# Fix any surrogate escape issues in the variable string
|
150
|
+
var = fix_surrogate_escapes(var)
|
151
|
+
|
148
152
|
if "=" not in var:
|
149
153
|
raise click.BadParameter(
|
150
154
|
f"Variable must be in format name=value: {var}"
|
@@ -152,6 +156,11 @@ def validate_variable(
|
|
152
156
|
name, val = var.split("=", 1)
|
153
157
|
name = name.strip()
|
154
158
|
val = val.strip()
|
159
|
+
|
160
|
+
# Fix surrogate escapes in both name and value
|
161
|
+
name = fix_surrogate_escapes(name)
|
162
|
+
val = fix_surrogate_escapes(val)
|
163
|
+
|
155
164
|
if not name.isidentifier():
|
156
165
|
raise click.BadParameter(f"Invalid variable name: {name}")
|
157
166
|
result.append((name, val))
|
@@ -179,6 +188,9 @@ def validate_json_variable(
|
|
179
188
|
|
180
189
|
result = []
|
181
190
|
for var in value:
|
191
|
+
# Fix any surrogate escape issues in the variable string
|
192
|
+
var = fix_surrogate_escapes(var)
|
193
|
+
|
182
194
|
if "=" not in var:
|
183
195
|
raise InvalidJSONError(
|
184
196
|
f"JSON variable must be in format name='{'json':\"value\"}': {var}"
|
@@ -186,6 +198,11 @@ def validate_json_variable(
|
|
186
198
|
name, json_str = var.split("=", 1)
|
187
199
|
name = name.strip()
|
188
200
|
json_str = json_str.strip()
|
201
|
+
|
202
|
+
# Fix surrogate escapes in both name and JSON string
|
203
|
+
name = fix_surrogate_escapes(name)
|
204
|
+
json_str = fix_surrogate_escapes(json_str)
|
205
|
+
|
189
206
|
if not name.isidentifier():
|
190
207
|
raise VariableNameError(f"Invalid variable name: {name}")
|
191
208
|
try:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: ostruct-cli
|
3
|
-
Version: 0.8.
|
3
|
+
Version: 0.8.29
|
4
4
|
Summary: CLI for OpenAI Structured Output with Multi-Tool Integration
|
5
5
|
Author: Yaniv Golan
|
6
6
|
Author-email: yaniv@golan.name
|
@@ -27,7 +27,7 @@ Requires-Dist: ijson (>=3.2.3,<4.0)
|
|
27
27
|
Requires-Dist: jinja2 (>=3.1.2,<4.0)
|
28
28
|
Requires-Dist: jsonschema (>=4.23.0,<5.0)
|
29
29
|
Requires-Dist: mypy (>=1.0,<2.0) ; extra == "dev"
|
30
|
-
Requires-Dist: myst-parser (>=
|
30
|
+
Requires-Dist: myst-parser (>=3.0.0,<4.0) ; extra == "docs"
|
31
31
|
Requires-Dist: openai (==1.81.0)
|
32
32
|
Requires-Dist: openai-model-registry (>=0.7.0,<1.0)
|
33
33
|
Requires-Dist: pre-commit (>=4.1.0,<5.0) ; extra == "dev"
|
@@ -42,9 +42,9 @@ Requires-Dist: pytest-rerunfailures (>=12.0,<13.0) ; extra == "dev"
|
|
42
42
|
Requires-Dist: python-dotenv (>=1.0.1,<2.0)
|
43
43
|
Requires-Dist: python-dotenv (>=1.0.1,<2.0) ; extra == "dev"
|
44
44
|
Requires-Dist: pyyaml (>=6.0.2,<7.0)
|
45
|
-
Requires-Dist: sphinx (>=7.0,<8.0) ; extra == "dev"
|
46
|
-
Requires-Dist: sphinx (>=7.0,<8.0) ; extra == "docs"
|
47
|
-
Requires-Dist: sphinx-design (>=0.
|
45
|
+
Requires-Dist: sphinx (>=7.0.0,<8.0) ; extra == "dev"
|
46
|
+
Requires-Dist: sphinx (>=7.0.0,<8.0) ; extra == "docs"
|
47
|
+
Requires-Dist: sphinx-design (>=0.4.1,<1.0) ; extra == "docs"
|
48
48
|
Requires-Dist: sphinx-rtd-theme (>=1.0,<2.0) ; extra == "docs"
|
49
49
|
Requires-Dist: tenacity (>=8.2.3,<9.0) ; extra == "examples"
|
50
50
|
Requires-Dist: tiktoken (==0.9.0)
|
@@ -216,23 +216,84 @@ Break down words into their components, showing their origins, meanings, and hie
|
|
216
216
|
|
217
217
|
## Installation
|
218
218
|
|
219
|
-
|
219
|
+
We provide multiple installation methods to suit different user needs. Choose the one that's right for you.
|
220
220
|
|
221
|
-
|
221
|
+
<details>
|
222
|
+
<summary><strong>Recommended: pipx (Python Users)</strong></summary>
|
223
|
+
|
224
|
+
For users who have Python installed, `pipx` is the recommended installation method. It installs `ostruct` in an isolated environment, preventing conflicts with other Python packages.
|
225
|
+
|
226
|
+
1. **Install pipx**:
|
227
|
+
|
228
|
+
```bash
|
229
|
+
python3 -m pip install --user pipx
|
230
|
+
python3 -m pipx ensurepath
|
231
|
+
```
|
232
|
+
|
233
|
+
*(Restart your terminal after running `ensurepath` to update your `PATH`)*
|
234
|
+
|
235
|
+
2. **Install ostruct-cli**:
|
236
|
+
|
237
|
+
```bash
|
238
|
+
pipx install ostruct-cli
|
239
|
+
```
|
240
|
+
|
241
|
+
</details>
|
242
|
+
|
243
|
+
<details>
|
244
|
+
<summary><strong>macOS: Homebrew</strong></summary>
|
245
|
+
|
246
|
+
If you're on macOS and use Homebrew, you can install `ostruct` with a single command:
|
247
|
+
|
248
|
+
```bash
|
249
|
+
brew install yaniv-golan/ostruct/ostruct-cli
|
250
|
+
```
|
251
|
+
|
252
|
+
</details>
|
253
|
+
|
254
|
+
<details>
|
255
|
+
<summary><strong>Standalone Binaries (No Python Required)</strong></summary>
|
256
|
+
|
257
|
+
We provide pre-compiled .zip archives for macOS, Windows, and Linux that do not require Python to be installed.
|
258
|
+
|
259
|
+
1. Go to the [**Latest Release**](https://github.com/yaniv-golan/ostruct/releases/latest) page.
|
260
|
+
2. Download the `.zip` file for your operating system (e.g., `ostruct-macos-latest.zip`, `ostruct-windows-latest.zip`, `ostruct-ubuntu-latest.zip`).
|
261
|
+
3. Extract the `.zip` file. This will create a folder (e.g., `ostruct-macos-amd64`).
|
262
|
+
4. On macOS/Linux, make the executable inside the extracted folder runnable:
|
263
|
+
|
264
|
+
```bash
|
265
|
+
chmod +x /path/to/ostruct-macos-amd64/ostruct
|
266
|
+
```
|
267
|
+
|
268
|
+
5. Run the executable from within the extracted folder, as it depends on bundled libraries in the same directory.
|
269
|
+
|
270
|
+
</details>
|
271
|
+
|
272
|
+
<details>
|
273
|
+
<summary><strong>Docker</strong></summary>
|
274
|
+
|
275
|
+
If you prefer to use Docker, you can run `ostruct` from our official container image available on the GitHub Container Registry.
|
222
276
|
|
223
277
|
```bash
|
224
|
-
|
278
|
+
docker run -it --rm \
|
279
|
+
-v "$(pwd)":/app \
|
280
|
+
-w /app \
|
281
|
+
ghcr.io/yaniv-golan/ostruct:latest \
|
282
|
+
run template.j2 schema.json -ft input.txt
|
225
283
|
```
|
226
284
|
|
227
|
-
This
|
285
|
+
This command mounts the current directory into the container and runs `ostruct`.
|
228
286
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
- Configure your shell PATH automatically
|
233
|
-
- Verify the installation works
|
287
|
+
</details>
|
288
|
+
|
289
|
+
### Uninstallation
|
234
290
|
|
235
|
-
|
291
|
+
To uninstall `ostruct`, use the method corresponding to how you installed it:
|
292
|
+
|
293
|
+
- **pipx**: `pipx uninstall ostruct-cli`
|
294
|
+
- **Homebrew**: `brew uninstall ostruct-cli`
|
295
|
+
- **Binaries**: Simply delete the binary file.
|
296
|
+
- **Docker**: No uninstallation is needed for the image itself, but you can remove it with `docker rmi ghcr.io/yaniv-golan/ostruct:latest`.
|
236
297
|
|
237
298
|
### Manual Installation
|
238
299
|
|
@@ -446,6 +507,8 @@ tools:
|
|
446
507
|
|
447
508
|
🚀 **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.
|
448
509
|
|
510
|
+
📝 **Template Scripting:** Learn ostruct's templating capabilities with the [template scripting guide](https://ostruct.readthedocs.io/en/latest/user-guide/ostruct_template_scripting_guide.html) - no prior Jinja2 knowledge required!
|
511
|
+
|
449
512
|
📖 **Full Documentation:** <https://ostruct.readthedocs.io/>
|
450
513
|
|
451
514
|
### Quick Start
|
@@ -2,7 +2,7 @@ ostruct/__init__.py,sha256=X6zo6V7ZNMv731Wi388aTVQngD1410ExGwGx4J6lpyo,187
|
|
2
2
|
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
|
-
ostruct/cli/cli.py,sha256=
|
5
|
+
ostruct/cli/cli.py,sha256=QtWoNskOvus9gYvxjSxdhXRpbdwIYwA9Di1f93bkVpE,5266
|
6
6
|
ostruct/cli/click_options.py,sha256=UWLBIkfVMXcIMXInJFWNYNO9Ieg8YrJEzRfkKungy48,31730
|
7
7
|
ostruct/cli/code_interpreter.py,sha256=lnnyEvUh2pGObN9ENpr-X4p0C0oIWiyG1CFQWW4akBQ,16726
|
8
8
|
ostruct/cli/commands/__init__.py,sha256=3NHz-WZ9XqrnWWMksoV2MpYpHnjA-EO9lsrBOYeHcjY,723
|
@@ -12,12 +12,12 @@ ostruct/cli/commands/run.py,sha256=Cm9Yuf0DLt5CqKfgAYubhQRcvLdK1vqIIuz_ynjfhQ4,6
|
|
12
12
|
ostruct/cli/commands/update_registry.py,sha256=7DQrPlCJScPVgE2HbFAM7UMap-EdYu58AQWfpI-H7Gw,2483
|
13
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=Akw-_pAuvy18PKrlYdkpF0sNBrc82M4rGKtDWuPQpQg,25065
|
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=
|
20
|
-
ostruct/cli/file_list.py,sha256=
|
19
|
+
ostruct/cli/file_info.py,sha256=B5mFX9AI9-H6yM2FhcdVtwibFS6NbZplXPW9vYjozOs,18336
|
20
|
+
ostruct/cli/file_list.py,sha256=upaXaQVmuxwjdmXzTRlvttMZjnpv_B2JzvmhoWTvsUg,21978
|
21
21
|
ostruct/cli/file_search.py,sha256=N12mkji2ttvItLVPyAWE3KEfhTv8hV5IXPrQME2UFdE,15313
|
22
22
|
ostruct/cli/file_utils.py,sha256=JZprQ-1LHQzI3eBfeCIS6VmxTa2fGUZHygGC8gcwpJM,24367
|
23
23
|
ostruct/cli/json_extract.py,sha256=ZleIxat8g-JnA9VVqWgJaKxN7QzL25itQ8aP0Gb5e4Q,2650
|
@@ -61,11 +61,11 @@ ostruct/cli/token_utils.py,sha256=r4KPEO3Sec18Q6mU0aClK6XGShvusgUggXEQgEPPlaA,13
|
|
61
61
|
ostruct/cli/token_validation.py,sha256=gmyPJ7B2gC_jSx_1wKZq87DEoFulj23X1XnVpO_aRNA,9930
|
62
62
|
ostruct/cli/types.py,sha256=6nARJ4MF5HIank0t6KGU-PPHC0VpFh3R8fNJZBXwgbA,2903
|
63
63
|
ostruct/cli/unattended_operation.py,sha256=kI95SSVJC_taxORXQYrce_qLEnuKc6edwn9tMOye-qs,9383
|
64
|
-
ostruct/cli/utils.py,sha256=
|
65
|
-
ostruct/cli/validators.py,sha256=
|
64
|
+
ostruct/cli/utils.py,sha256=DV8KAx46rl3GgXLydVhrP6A1xY7ofyir3hEKUslSfek,2149
|
65
|
+
ostruct/cli/validators.py,sha256=VbafaT7QyKAqpnHbqpibE3xkuaZ74e6zQ7Ih3WbzyRI,15844
|
66
66
|
ostruct/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
67
|
-
ostruct_cli-0.8.
|
68
|
-
ostruct_cli-0.8.
|
69
|
-
ostruct_cli-0.8.
|
70
|
-
ostruct_cli-0.8.
|
71
|
-
ostruct_cli-0.8.
|
67
|
+
ostruct_cli-0.8.29.dist-info/LICENSE,sha256=DmGAkaYzhrdzTB9Y2Rvfzd3mJiF9ZrTOhxN8t6wrfHA,1098
|
68
|
+
ostruct_cli-0.8.29.dist-info/METADATA,sha256=t-6EX_pD42Nt54cN-XFCc9yQVbbF5NasLGUwnempZL0,28124
|
69
|
+
ostruct_cli-0.8.29.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
70
|
+
ostruct_cli-0.8.29.dist-info/entry_points.txt,sha256=NFq9IuqHVTem0j9zKjV8C1si_zGcP1RL6Wbvt9fUDXw,48
|
71
|
+
ostruct_cli-0.8.29.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|