wagapi 0.2.0__tar.gz → 0.2.2__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.
- {wagapi-0.2.0 → wagapi-0.2.2}/PKG-INFO +12 -12
- {wagapi-0.2.0 → wagapi-0.2.2}/README.md +11 -11
- {wagapi-0.2.0 → wagapi-0.2.2}/pyproject.toml +1 -1
- {wagapi-0.2.0 → wagapi-0.2.2}/tests/test_commands.py +22 -0
- wagapi-0.2.2/wagapi/__init__.py +1 -0
- {wagapi-0.2.0 → wagapi-0.2.2}/wagapi/cli.py +12 -1
- {wagapi-0.2.0 → wagapi-0.2.2}/wagapi/commands/pages.py +2 -2
- wagapi-0.2.2/wagapi/commands/schema.py +87 -0
- {wagapi-0.2.0 → wagapi-0.2.2}/wagapi/formatting/output.py +25 -2
- wagapi-0.2.0/wagapi/__init__.py +0 -1
- wagapi-0.2.0/wagapi/commands/schema.py +0 -43
- {wagapi-0.2.0 → wagapi-0.2.2}/.github/workflows/publish.yml +0 -0
- {wagapi-0.2.0 → wagapi-0.2.2}/.gitignore +0 -0
- {wagapi-0.2.0 → wagapi-0.2.2}/tests/__init__.py +0 -0
- {wagapi-0.2.0 → wagapi-0.2.2}/tests/conftest.py +0 -0
- {wagapi-0.2.0 → wagapi-0.2.2}/tests/test_client.py +0 -0
- {wagapi-0.2.0 → wagapi-0.2.2}/tests/test_config.py +0 -0
- {wagapi-0.2.0 → wagapi-0.2.2}/tests/test_markdown.py +0 -0
- {wagapi-0.2.0 → wagapi-0.2.2}/wagapi/__main__.py +0 -0
- {wagapi-0.2.0 → wagapi-0.2.2}/wagapi/client.py +0 -0
- {wagapi-0.2.0 → wagapi-0.2.2}/wagapi/commands/__init__.py +0 -0
- {wagapi-0.2.0 → wagapi-0.2.2}/wagapi/commands/images.py +0 -0
- {wagapi-0.2.0 → wagapi-0.2.2}/wagapi/commands/init.py +0 -0
- {wagapi-0.2.0 → wagapi-0.2.2}/wagapi/config.py +0 -0
- {wagapi-0.2.0 → wagapi-0.2.2}/wagapi/exceptions.py +0 -0
- {wagapi-0.2.0 → wagapi-0.2.2}/wagapi/formatting/__init__.py +0 -0
- {wagapi-0.2.0 → wagapi-0.2.2}/wagapi/formatting/markdown.py +0 -0
- {wagapi-0.2.0 → wagapi-0.2.2}/wagapi/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wagapi
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: CLI client for the Wagtail Write API, optimised for LLM orchestration
|
|
5
5
|
Project-URL: Repository, https://github.com/tomdyson/wagapi
|
|
6
6
|
Project-URL: Issues, https://github.com/tomdyson/wagapi/issues
|
|
@@ -121,13 +121,13 @@ wagapi schema testapp.BlogPage
|
|
|
121
121
|
|
|
122
122
|
```bash
|
|
123
123
|
wagapi pages list
|
|
124
|
-
wagapi pages get
|
|
124
|
+
wagapi pages get 3 # use an ID from the list above
|
|
125
125
|
```
|
|
126
126
|
|
|
127
127
|
### 5. Create a page
|
|
128
128
|
|
|
129
129
|
```bash
|
|
130
|
-
wagapi pages create testapp.BlogPage --parent
|
|
130
|
+
wagapi pages create testapp.BlogPage --parent /blog/ \
|
|
131
131
|
--title "Iris Murdoch" \
|
|
132
132
|
--body "## A Philosopher and Novelist
|
|
133
133
|
|
|
@@ -142,10 +142,10 @@ The `--body` flag accepts markdown, which is auto-converted to StreamField block
|
|
|
142
142
|
|
|
143
143
|
```bash
|
|
144
144
|
# Publish a draft (use the page ID returned by create)
|
|
145
|
-
wagapi pages publish
|
|
145
|
+
wagapi pages publish <ID>
|
|
146
146
|
|
|
147
147
|
# Update a page
|
|
148
|
-
wagapi pages update
|
|
148
|
+
wagapi pages update <ID> --title "Iris Murdoch: The Sovereignty of Good"
|
|
149
149
|
|
|
150
150
|
# Create and publish in one step, using a URL path as parent
|
|
151
151
|
wagapi pages create testapp.BlogPage --parent /blog/ \
|
|
@@ -155,20 +155,20 @@ wagapi pages create testapp.BlogPage --parent /blog/ \
|
|
|
155
155
|
--publish
|
|
156
156
|
|
|
157
157
|
# Unpublish
|
|
158
|
-
wagapi pages unpublish
|
|
158
|
+
wagapi pages unpublish <ID>
|
|
159
159
|
|
|
160
160
|
# Delete (prompts for confirmation)
|
|
161
|
-
wagapi pages delete
|
|
161
|
+
wagapi pages delete <ID>
|
|
162
162
|
```
|
|
163
163
|
|
|
164
164
|
### 7. Inspect requests
|
|
165
165
|
|
|
166
166
|
```bash
|
|
167
167
|
# See HTTP request/response details
|
|
168
|
-
wagapi -v pages get
|
|
168
|
+
wagapi -v pages get <ID>
|
|
169
169
|
|
|
170
170
|
# Preview without executing
|
|
171
|
-
wagapi --dry-run pages create testapp.SimplePage --parent
|
|
171
|
+
wagapi --dry-run pages create testapp.SimplePage --parent /home/ --title "Test"
|
|
172
172
|
```
|
|
173
173
|
|
|
174
174
|
### 8. Pipe-friendly JSON output
|
|
@@ -184,7 +184,7 @@ Force a format with `--json` or `--human`:
|
|
|
184
184
|
|
|
185
185
|
```bash
|
|
186
186
|
wagapi --human pages list
|
|
187
|
-
wagapi --json pages get
|
|
187
|
+
wagapi --json pages get 42
|
|
188
188
|
```
|
|
189
189
|
|
|
190
190
|
## Configuration
|
|
@@ -305,14 +305,14 @@ She argued that moral progress comes from **attention**."
|
|
|
305
305
|
**With extra fields:**
|
|
306
306
|
|
|
307
307
|
```bash
|
|
308
|
-
wagapi pages create testapp.BlogPage --parent
|
|
308
|
+
wagapi pages create testapp.BlogPage --parent /blog/ \
|
|
309
309
|
--title "Iris Murdoch" --field published_date:2026-04-06
|
|
310
310
|
```
|
|
311
311
|
|
|
312
312
|
**Raw mode for full StreamField control:**
|
|
313
313
|
|
|
314
314
|
```bash
|
|
315
|
-
wagapi pages create testapp.BlogPage --parent
|
|
315
|
+
wagapi pages create testapp.BlogPage --parent /blog/ \
|
|
316
316
|
--title "Iris Murdoch" --raw \
|
|
317
317
|
--field 'body:[{"type":"paragraph","value":"<p>Hello</p>","id":"abc123"}]'
|
|
318
318
|
```
|
|
@@ -91,13 +91,13 @@ wagapi schema testapp.BlogPage
|
|
|
91
91
|
|
|
92
92
|
```bash
|
|
93
93
|
wagapi pages list
|
|
94
|
-
wagapi pages get
|
|
94
|
+
wagapi pages get 3 # use an ID from the list above
|
|
95
95
|
```
|
|
96
96
|
|
|
97
97
|
### 5. Create a page
|
|
98
98
|
|
|
99
99
|
```bash
|
|
100
|
-
wagapi pages create testapp.BlogPage --parent
|
|
100
|
+
wagapi pages create testapp.BlogPage --parent /blog/ \
|
|
101
101
|
--title "Iris Murdoch" \
|
|
102
102
|
--body "## A Philosopher and Novelist
|
|
103
103
|
|
|
@@ -112,10 +112,10 @@ The `--body` flag accepts markdown, which is auto-converted to StreamField block
|
|
|
112
112
|
|
|
113
113
|
```bash
|
|
114
114
|
# Publish a draft (use the page ID returned by create)
|
|
115
|
-
wagapi pages publish
|
|
115
|
+
wagapi pages publish <ID>
|
|
116
116
|
|
|
117
117
|
# Update a page
|
|
118
|
-
wagapi pages update
|
|
118
|
+
wagapi pages update <ID> --title "Iris Murdoch: The Sovereignty of Good"
|
|
119
119
|
|
|
120
120
|
# Create and publish in one step, using a URL path as parent
|
|
121
121
|
wagapi pages create testapp.BlogPage --parent /blog/ \
|
|
@@ -125,20 +125,20 @@ wagapi pages create testapp.BlogPage --parent /blog/ \
|
|
|
125
125
|
--publish
|
|
126
126
|
|
|
127
127
|
# Unpublish
|
|
128
|
-
wagapi pages unpublish
|
|
128
|
+
wagapi pages unpublish <ID>
|
|
129
129
|
|
|
130
130
|
# Delete (prompts for confirmation)
|
|
131
|
-
wagapi pages delete
|
|
131
|
+
wagapi pages delete <ID>
|
|
132
132
|
```
|
|
133
133
|
|
|
134
134
|
### 7. Inspect requests
|
|
135
135
|
|
|
136
136
|
```bash
|
|
137
137
|
# See HTTP request/response details
|
|
138
|
-
wagapi -v pages get
|
|
138
|
+
wagapi -v pages get <ID>
|
|
139
139
|
|
|
140
140
|
# Preview without executing
|
|
141
|
-
wagapi --dry-run pages create testapp.SimplePage --parent
|
|
141
|
+
wagapi --dry-run pages create testapp.SimplePage --parent /home/ --title "Test"
|
|
142
142
|
```
|
|
143
143
|
|
|
144
144
|
### 8. Pipe-friendly JSON output
|
|
@@ -154,7 +154,7 @@ Force a format with `--json` or `--human`:
|
|
|
154
154
|
|
|
155
155
|
```bash
|
|
156
156
|
wagapi --human pages list
|
|
157
|
-
wagapi --json pages get
|
|
157
|
+
wagapi --json pages get 42
|
|
158
158
|
```
|
|
159
159
|
|
|
160
160
|
## Configuration
|
|
@@ -275,14 +275,14 @@ She argued that moral progress comes from **attention**."
|
|
|
275
275
|
**With extra fields:**
|
|
276
276
|
|
|
277
277
|
```bash
|
|
278
|
-
wagapi pages create testapp.BlogPage --parent
|
|
278
|
+
wagapi pages create testapp.BlogPage --parent /blog/ \
|
|
279
279
|
--title "Iris Murdoch" --field published_date:2026-04-06
|
|
280
280
|
```
|
|
281
281
|
|
|
282
282
|
**Raw mode for full StreamField control:**
|
|
283
283
|
|
|
284
284
|
```bash
|
|
285
|
-
wagapi pages create testapp.BlogPage --parent
|
|
285
|
+
wagapi pages create testapp.BlogPage --parent /blog/ \
|
|
286
286
|
--title "Iris Murdoch" --raw \
|
|
287
287
|
--field 'body:[{"type":"paragraph","value":"<p>Hello</p>","id":"abc123"}]'
|
|
288
288
|
```
|
|
@@ -97,6 +97,28 @@ def test_pages_list(runner):
|
|
|
97
97
|
assert "Hello" in result.output
|
|
98
98
|
|
|
99
99
|
|
|
100
|
+
@respx.mock
|
|
101
|
+
def test_pages_list_with_parent(runner):
|
|
102
|
+
data = {
|
|
103
|
+
"meta": {"total_count": 1},
|
|
104
|
+
"items": [
|
|
105
|
+
{
|
|
106
|
+
"id": 42,
|
|
107
|
+
"title": "Hello",
|
|
108
|
+
"meta": {"type": "blog.BlogPage", "live": True},
|
|
109
|
+
}
|
|
110
|
+
],
|
|
111
|
+
}
|
|
112
|
+
route = respx.get(f"{BASE_URL}/pages/").mock(
|
|
113
|
+
return_value=Response(200, json=data)
|
|
114
|
+
)
|
|
115
|
+
with mock.patch.dict("os.environ", ENV):
|
|
116
|
+
result = runner.invoke(cli, ["pages", "list", "--parent", "5"])
|
|
117
|
+
assert result.exit_code == 0
|
|
118
|
+
assert route.called
|
|
119
|
+
assert "parent" in str(route.calls[0].request.url)
|
|
120
|
+
|
|
121
|
+
|
|
100
122
|
@respx.mock
|
|
101
123
|
def test_pages_get(runner):
|
|
102
124
|
data = {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.2.2"
|
|
@@ -35,7 +35,18 @@ def handle_api_errors(fn):
|
|
|
35
35
|
except WagapiError as exc:
|
|
36
36
|
click.echo(f"Error: {exc}", err=True)
|
|
37
37
|
if hasattr(exc, "details") and exc.details:
|
|
38
|
-
|
|
38
|
+
details = exc.details
|
|
39
|
+
# Format field-level validation errors readably
|
|
40
|
+
if isinstance(details, dict) and "details" in details:
|
|
41
|
+
for item in details["details"]:
|
|
42
|
+
field = item.get("field", "")
|
|
43
|
+
msg = item.get("message", str(item))
|
|
44
|
+
if field:
|
|
45
|
+
click.echo(f" {field}: {msg}", err=True)
|
|
46
|
+
else:
|
|
47
|
+
click.echo(f" {msg}", err=True)
|
|
48
|
+
else:
|
|
49
|
+
click.echo(f"Details: {details}", err=True)
|
|
39
50
|
sys.exit(exc.exit_code)
|
|
40
51
|
|
|
41
52
|
return wrapper
|
|
@@ -91,7 +91,7 @@ def list_pages(
|
|
|
91
91
|
if page_type:
|
|
92
92
|
params["type"] = page_type
|
|
93
93
|
if parent:
|
|
94
|
-
params["
|
|
94
|
+
params["parent"] = parent
|
|
95
95
|
if descendant_of:
|
|
96
96
|
params["descendant_of"] = descendant_of
|
|
97
97
|
if status:
|
|
@@ -259,7 +259,7 @@ def delete(ctx: Context, page_id: int, yes: bool):
|
|
|
259
259
|
|
|
260
260
|
ctx.client.delete_page(page_id)
|
|
261
261
|
result = output(
|
|
262
|
-
page_id,
|
|
262
|
+
{"id": page_id, "deleted": True},
|
|
263
263
|
format_page_deleted,
|
|
264
264
|
force_json=ctx.force_json,
|
|
265
265
|
force_human=ctx.force_human,
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from wagapi.cli import Context, handle_api_errors, pass_ctx
|
|
6
|
+
from wagapi.exceptions import UsageError
|
|
7
|
+
from wagapi.formatting.output import (
|
|
8
|
+
format_json,
|
|
9
|
+
format_schema_detail,
|
|
10
|
+
format_schema_list,
|
|
11
|
+
output,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _build_example_command(page_type: str, data: dict) -> str:
|
|
16
|
+
"""Generate an example wagapi create command from schema data."""
|
|
17
|
+
create_schema = data.get("create_schema", {})
|
|
18
|
+
properties = create_schema.get("properties", {})
|
|
19
|
+
required = set(create_schema.get("required", []))
|
|
20
|
+
has_streamfield = bool(data.get("streamfield_blocks"))
|
|
21
|
+
|
|
22
|
+
# CLI handles type and parent itself; action is internal
|
|
23
|
+
skip = {"type", "parent", "action"}
|
|
24
|
+
|
|
25
|
+
parts = [f"wagapi pages create {page_type}", "--parent <ID_OR_PATH>"]
|
|
26
|
+
|
|
27
|
+
for field_name in properties:
|
|
28
|
+
if field_name in skip:
|
|
29
|
+
continue
|
|
30
|
+
if field_name not in required:
|
|
31
|
+
continue
|
|
32
|
+
prop = properties[field_name]
|
|
33
|
+
|
|
34
|
+
# StreamField body → use --body flag
|
|
35
|
+
if field_name == "body" and prop.get("type") == "array":
|
|
36
|
+
parts.append('--body "Your content here (markdown)"')
|
|
37
|
+
continue
|
|
38
|
+
|
|
39
|
+
# Derive a placeholder from the field type
|
|
40
|
+
ftype = prop.get("type", "")
|
|
41
|
+
if ftype == "string":
|
|
42
|
+
parts.append(f'--field {field_name}:"..."')
|
|
43
|
+
elif ftype == "integer":
|
|
44
|
+
parts.append(f"--field {field_name}:<ID>")
|
|
45
|
+
elif ftype == "array":
|
|
46
|
+
parts.append(f"--field {field_name}:[]")
|
|
47
|
+
else:
|
|
48
|
+
parts.append(f'--field {field_name}:"..."')
|
|
49
|
+
|
|
50
|
+
# title is always a CLI flag, not --field
|
|
51
|
+
parts = [p for p in parts if not p.startswith("--field title:")]
|
|
52
|
+
if "title" in required:
|
|
53
|
+
parts.insert(2, '--title "Your Title"')
|
|
54
|
+
|
|
55
|
+
return " \\\n ".join(parts)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@click.command()
|
|
59
|
+
@click.argument("page_type", required=False, default=None)
|
|
60
|
+
@pass_ctx
|
|
61
|
+
@handle_api_errors
|
|
62
|
+
def schema(ctx: Context, page_type: str | None) -> None:
|
|
63
|
+
"""List page types, or show the schema for a specific type."""
|
|
64
|
+
if not ctx.client:
|
|
65
|
+
raise UsageError(
|
|
66
|
+
"Not configured. Run 'wagapi init' or set WAGAPI_URL and WAGAPI_TOKEN."
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
if page_type:
|
|
70
|
+
data = ctx.client.get_page_type_schema(page_type)
|
|
71
|
+
data["example_cli"] = _build_example_command(page_type, data)
|
|
72
|
+
result = output(
|
|
73
|
+
data,
|
|
74
|
+
format_schema_detail,
|
|
75
|
+
force_json=ctx.force_json,
|
|
76
|
+
force_human=ctx.force_human,
|
|
77
|
+
)
|
|
78
|
+
else:
|
|
79
|
+
data = ctx.client.list_page_types()
|
|
80
|
+
result = output(
|
|
81
|
+
data,
|
|
82
|
+
format_schema_list,
|
|
83
|
+
force_json=ctx.force_json,
|
|
84
|
+
force_human=ctx.force_human,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
click.echo(result)
|
|
@@ -53,8 +53,8 @@ def format_page_updated(data: dict) -> str:
|
|
|
53
53
|
return f'✓ Updated page {data["id"]} "{data.get("title", "")}" ({status})'
|
|
54
54
|
|
|
55
55
|
|
|
56
|
-
def format_page_deleted(
|
|
57
|
-
return f
|
|
56
|
+
def format_page_deleted(data: dict) -> str:
|
|
57
|
+
return f'✓ Deleted page {data["id"]}'
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
def format_page_published(data: dict) -> str:
|
|
@@ -75,6 +75,25 @@ def format_page_detail(data: dict) -> str:
|
|
|
75
75
|
]
|
|
76
76
|
if meta.get("html_url"):
|
|
77
77
|
lines.append(f' URL: {meta["html_url"]}')
|
|
78
|
+
if meta.get("parent_id"):
|
|
79
|
+
lines.append(f' Parent: {meta["parent_id"]}')
|
|
80
|
+
|
|
81
|
+
# Show custom fields (skip meta, id, title, slug which are already shown)
|
|
82
|
+
skip = {"id", "title", "slug", "meta", "alias_of"}
|
|
83
|
+
for key, value in data.items():
|
|
84
|
+
if key in skip or value is None:
|
|
85
|
+
continue
|
|
86
|
+
if isinstance(value, list) and value and isinstance(value[0], dict) and "type" in value[0]:
|
|
87
|
+
# StreamField — summarise block types
|
|
88
|
+
block_types = [b.get("type", "?") for b in value]
|
|
89
|
+
lines.append(f" {key}: [{', '.join(block_types)}] ({len(value)} blocks)")
|
|
90
|
+
elif isinstance(value, list) and value:
|
|
91
|
+
lines.append(f" {key}: {len(value)} items")
|
|
92
|
+
elif isinstance(value, list):
|
|
93
|
+
pass # skip empty lists
|
|
94
|
+
else:
|
|
95
|
+
lines.append(f" {key}: {value}")
|
|
96
|
+
|
|
78
97
|
return "\n".join(lines)
|
|
79
98
|
|
|
80
99
|
|
|
@@ -170,6 +189,10 @@ def format_schema_detail(data: dict) -> str:
|
|
|
170
189
|
block_names = [b.get("type", b.get("name", "?")) for b in blocks] if isinstance(blocks, list) else list(blocks.keys()) if isinstance(blocks, dict) else []
|
|
171
190
|
lines.append(f" {field_name}: {', '.join(block_names)}")
|
|
172
191
|
|
|
192
|
+
if data.get("example_cli"):
|
|
193
|
+
lines.append("")
|
|
194
|
+
lines.append(f" Example:\n {data['example_cli'].replace(chr(10), chr(10) + ' ')}")
|
|
195
|
+
|
|
173
196
|
return "\n".join(lines)
|
|
174
197
|
|
|
175
198
|
|
wagapi-0.2.0/wagapi/__init__.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.1.0"
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import click
|
|
4
|
-
|
|
5
|
-
from wagapi.cli import Context, handle_api_errors, pass_ctx
|
|
6
|
-
from wagapi.exceptions import UsageError
|
|
7
|
-
from wagapi.formatting.output import (
|
|
8
|
-
format_json,
|
|
9
|
-
format_schema_detail,
|
|
10
|
-
format_schema_list,
|
|
11
|
-
output,
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@click.command()
|
|
16
|
-
@click.argument("page_type", required=False, default=None)
|
|
17
|
-
@pass_ctx
|
|
18
|
-
@handle_api_errors
|
|
19
|
-
def schema(ctx: Context, page_type: str | None) -> None:
|
|
20
|
-
"""List page types, or show the schema for a specific type."""
|
|
21
|
-
if not ctx.client:
|
|
22
|
-
raise UsageError(
|
|
23
|
-
"Not configured. Run 'wagapi init' or set WAGAPI_URL and WAGAPI_TOKEN."
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
if page_type:
|
|
27
|
-
data = ctx.client.get_page_type_schema(page_type)
|
|
28
|
-
result = output(
|
|
29
|
-
data,
|
|
30
|
-
format_schema_detail,
|
|
31
|
-
force_json=ctx.force_json,
|
|
32
|
-
force_human=ctx.force_human,
|
|
33
|
-
)
|
|
34
|
-
else:
|
|
35
|
-
data = ctx.client.list_page_types()
|
|
36
|
-
result = output(
|
|
37
|
-
data,
|
|
38
|
-
format_schema_list,
|
|
39
|
-
force_json=ctx.force_json,
|
|
40
|
-
force_human=ctx.force_human,
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
click.echo(result)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|