Skip to content

Commit ff95e71

Browse files
Support x-linode-cli-skip at attribute level (#857)
1 parent 049d772 commit ff95e71

6 files changed

Lines changed: 242 additions & 0 deletions

File tree

linodecli/baked/request.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ def _parse_request_model(
160160
for k, v in properties.items():
161161
k = escape_arg_segment(k)
162162

163+
# Skip attributes with x-linode-cli-skip extension
164+
if v.extensions.get("linode-cli-skip"):
165+
continue
166+
163167
# Handle nested objects which aren't read-only and have properties
164168
if (
165169
v.type == "object"

linodecli/baked/response.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,10 @@ def _parse_response_model(schema, prefix=None, nested_list_depth=0):
193193
for k, v in properties.items():
194194
pref = prefix + "." + k if prefix else k
195195

196+
# Skip attributes with x-linode-cli-skip extension
197+
if v.extensions.get("linode-cli-skip"):
198+
continue
199+
196200
if (
197201
v.type == "object"
198202
and v.properties is None
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
openapi: 3.0.1
2+
info:
3+
title: API Specification for x-linode-cli-skip Tests
4+
version: 1.0.0
5+
servers:
6+
- url: http://localhost/v4
7+
8+
paths:
9+
/skip/test:
10+
x-linode-cli-command: skip-test
11+
get:
12+
summary: Test GET with skipped response attributes
13+
operationId: getSkipTest
14+
x-linode-cli-action: list
15+
description: List items with some attributes skipped
16+
responses:
17+
'200':
18+
description: Successful response with skipped attributes
19+
content:
20+
application/json:
21+
schema:
22+
type: object
23+
properties:
24+
data:
25+
type: array
26+
items:
27+
$ref: '#/components/schemas/SkipTestResponse'
28+
page:
29+
$ref: '#/components/schemas/PaginationEnvelope/properties/page'
30+
pages:
31+
$ref: '#/components/schemas/PaginationEnvelope/properties/pages'
32+
results:
33+
$ref: '#/components/schemas/PaginationEnvelope/properties/results'
34+
post:
35+
summary: Create with skipped request attributes
36+
operationId: createSkipTest
37+
x-linode-cli-action: create
38+
description: Create an item with some request attributes skipped
39+
requestBody:
40+
description: Parameters for creating the item
41+
required: true
42+
content:
43+
application/json:
44+
schema:
45+
required:
46+
- visible_field
47+
allOf:
48+
- $ref: '#/components/schemas/SkipTestRequest'
49+
responses:
50+
'200':
51+
description: Successful response
52+
content:
53+
application/json:
54+
schema:
55+
$ref: '#/components/schemas/SkipTestResponse'
56+
57+
components:
58+
schemas:
59+
PaginationEnvelope:
60+
type: object
61+
properties:
62+
pages:
63+
type: integer
64+
readOnly: true
65+
description: The total number of pages.
66+
example: 1
67+
page:
68+
type: integer
69+
readOnly: true
70+
description: The current page.
71+
example: 1
72+
results:
73+
type: integer
74+
readOnly: true
75+
description: The total number of results.
76+
example: 1
77+
78+
SkipTestRequest:
79+
type: object
80+
description: Request object with skipped fields
81+
properties:
82+
visible_field:
83+
type: string
84+
description: This field should be visible
85+
skipped_request_field:
86+
type: string
87+
x-linode-cli-skip: true
88+
description: This field should be skipped in request
89+
another_visible_field:
90+
type: integer
91+
description: Another visible field
92+
skipped_both_field:
93+
type: string
94+
x-linode-cli-skip: true
95+
description: This field should be skipped in both request and response
96+
nested_object:
97+
type: object
98+
properties:
99+
nested_visible_field:
100+
type: string
101+
description: This nested field should be visible
102+
nested_skipped_field:
103+
type: string
104+
x-linode-cli-skip: true
105+
description: This nested field should be skipped
106+
107+
SkipTestResponse:
108+
type: object
109+
description: Response object with skipped fields
110+
properties:
111+
id:
112+
type: integer
113+
readOnly: true
114+
description: The unique ID
115+
visible_field:
116+
type: string
117+
description: This field should be visible
118+
skipped_response_field:
119+
type: string
120+
x-linode-cli-skip: true
121+
description: This field should be skipped in response
122+
another_visible_field:
123+
type: integer
124+
description: Another visible field
125+
skipped_both_field:
126+
type: string
127+
x-linode-cli-skip: true
128+
description: This field should be skipped in both request and response
129+
nested_object:
130+
type: object
131+
properties:
132+
nested_visible_field:
133+
type: string
134+
description: This nested field should be visible
135+
nested_skipped_field:
136+
type: string
137+
x-linode-cli-skip: true
138+
description: This nested field should be skipped

tests/unit/conftest.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,42 @@ def get_openapi_for_docs_url_tests() -> OpenAPI:
381381
return _get_parsed_spec("docs_url_test.yaml")
382382

383383

384+
@pytest.fixture
385+
def get_skip_test_operation():
386+
"""
387+
Creates a CLI operation for testing x-linode-cli-skip on response attributes.
388+
389+
GET http://localhost/v4/skip/test
390+
"""
391+
spec = _get_parsed_spec("skip_attribute_test.yaml")
392+
path = list(spec.paths.values())[0]
393+
394+
return make_test_operation(
395+
path.extensions.get("linode-cli-command", "default"),
396+
getattr(path, "get"),
397+
"get",
398+
path.parameters,
399+
)
400+
401+
402+
@pytest.fixture
403+
def post_skip_test_operation():
404+
"""
405+
Creates a CLI operation for testing x-linode-cli-skip on request attributes.
406+
407+
POST http://localhost/v4/skip/test
408+
"""
409+
spec = _get_parsed_spec("skip_attribute_test.yaml")
410+
path = list(spec.paths.values())[0]
411+
412+
return make_test_operation(
413+
path.extensions.get("linode-cli-command", "default"),
414+
getattr(path, "post"),
415+
"post",
416+
path.parameters,
417+
)
418+
419+
384420
@pytest.fixture
385421
def mocked_config():
386422
"""

tests/unit/test_request.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,20 @@ def test_handle_one_ofs(self, post_operation_with_one_ofs):
2121
assert arg_map[k].datatype == v[0]
2222
assert arg_map[k].description == v[1]
2323
assert arg_map[k].required == v[2]
24+
25+
def test_skip_request_attributes(self, post_skip_test_operation):
26+
"""
27+
Test that request attributes with x-linode-cli-skip extension are excluded.
28+
"""
29+
args = post_skip_test_operation.args
30+
arg_map = {arg.path: arg for arg in args}
31+
32+
# These fields should be present
33+
assert "visible_field" in arg_map
34+
assert "another_visible_field" in arg_map
35+
assert "nested_object.nested_visible_field" in arg_map
36+
37+
# These fields should be skipped
38+
assert "skipped_request_field" not in arg_map
39+
assert "skipped_both_field" not in arg_map
40+
assert "nested_object.nested_skipped_field" not in arg_map

tests/unit/test_response.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,46 @@ def test_array_of_objects_property(self, list_operation_for_response_test):
122122
{"subkey1": "item1", "subkey2": True},
123123
{"subkey1": "item2", "subkey2": False},
124124
]
125+
126+
def test_skip_response_attributes(self, get_skip_test_operation):
127+
"""
128+
Test that response attributes with x-linode-cli-skip extension are excluded.
129+
"""
130+
model = get_skip_test_operation.response_model
131+
attr_map = {attr.name: attr for attr in model.attrs}
132+
133+
# These fields should be present
134+
assert "id" in attr_map
135+
assert "visible_field" in attr_map
136+
assert "another_visible_field" in attr_map
137+
assert "nested_object.nested_visible_field" in attr_map
138+
139+
# These fields should be skipped
140+
assert "skipped_response_field" not in attr_map
141+
assert "skipped_both_field" not in attr_map
142+
assert "nested_object.nested_skipped_field" not in attr_map
143+
144+
def test_skip_attributes_in_both_request_and_response(
145+
self, post_skip_test_operation, get_skip_test_operation
146+
):
147+
"""
148+
Test that attributes marked with x-linode-cli-skip are excluded from both
149+
request and response models.
150+
"""
151+
# Test request model
152+
request_args = post_skip_test_operation.args
153+
request_arg_map = {arg.path: arg for arg in request_args}
154+
155+
# Test response model
156+
response_model = get_skip_test_operation.response_model
157+
response_attr_map = {attr.name: attr for attr in response_model.attrs}
158+
159+
# The skipped_both_field should not appear in either model
160+
assert "skipped_both_field" not in request_arg_map
161+
assert "skipped_both_field" not in response_attr_map
162+
163+
# But visible fields should appear in both
164+
assert "visible_field" in request_arg_map
165+
assert "visible_field" in response_attr_map
166+
assert "another_visible_field" in request_arg_map
167+
assert "another_visible_field" in response_attr_map

0 commit comments

Comments
 (0)