62
62
/ "rest-api-spec"
63
63
/ "api"
64
64
)
65
+ GLOBAL_QUERY_PARAMS = {
66
+ "pretty" : "Optional[bool]" ,
67
+ "human" : "Optional[bool]" ,
68
+ "error_trace" : "Optional[bool]" ,
69
+ "format" : "Optional[str]" ,
70
+ "filter_path" : "Optional[Union[str, Collection[str]]]" ,
71
+ "request_timeout" : "Optional[Union[int, float]]" ,
72
+ "ignore" : "Optional[Union[int, Collection[int]]]" ,
73
+ "opaque_id" : "Optional[str]" ,
74
+ }
65
75
66
76
jinja_env = Environment (
67
77
loader = FileSystemLoader ([CODE_ROOT / "utils" / "templates" ]),
@@ -78,15 +88,20 @@ def blacken(filename):
78
88
79
89
@lru_cache ()
80
90
def is_valid_url (url ):
81
- return http .request ("HEAD" , url ).status == 200
91
+ return 200 <= http .request ("HEAD" , url ).status < 400
82
92
83
93
84
94
class Module :
85
- def __init__ (self , namespace ):
95
+ def __init__ (self , namespace , is_pyi = False ):
86
96
self .namespace = namespace
97
+ self .is_pyi = is_pyi
87
98
self ._apis = []
88
99
self .parse_orig ()
89
100
101
+ if not is_pyi :
102
+ self .pyi = Module (namespace , is_pyi = True )
103
+ self .pyi .orders = self .orders [:]
104
+
90
105
def add (self , api ):
91
106
self ._apis .append (api )
92
107
@@ -128,17 +143,23 @@ def dump(self):
128
143
f .write (self .header )
129
144
for api in self ._apis :
130
145
f .write (api .to_python ())
131
- blacken (self .filepath )
146
+
147
+ if not self .is_pyi :
148
+ self .pyi .dump ()
132
149
133
150
@property
134
151
def filepath (self ):
135
- return CODE_ROOT / f"elasticsearch/_async/client/{ self .namespace } .py"
152
+ return (
153
+ CODE_ROOT
154
+ / f"elasticsearch/_async/client/{ self .namespace } .py{ 'i' if self .is_pyi else '' } "
155
+ )
136
156
137
157
138
158
class API :
139
- def __init__ (self , namespace , name , definition ):
159
+ def __init__ (self , namespace , name , definition , is_pyi = False ):
140
160
self .namespace = namespace
141
161
self .name = name
162
+ self .is_pyi = is_pyi
142
163
143
164
# overwrite the dict to maintain key order
144
165
definition ["params" ] = {
@@ -187,6 +208,7 @@ def all_parts(self):
187
208
parts [p ]["required" ] = all (
188
209
p in url .get ("parts" , {}) for url in self ._def ["url" ]["paths" ]
189
210
)
211
+ parts [p ]["type" ] = "Any"
190
212
191
213
for k , sub in SUBSTITUTIONS .items ():
192
214
if k in parts :
@@ -233,6 +255,19 @@ def query_params(self):
233
255
if k not in self .all_parts
234
256
)
235
257
258
+ @property
259
+ def all_func_params (self ):
260
+ """Parameters that will be in the '@query_params' decorator list
261
+ and parameters that will be in the function signature.
262
+ This doesn't include
263
+ """
264
+ params = list (self ._def .get ("params" , {}).keys ())
265
+ for url in self ._def ["url" ]["paths" ]:
266
+ params .extend (url .get ("parts" , {}).keys ())
267
+ if self .body :
268
+ params .append ("body" )
269
+ return params
270
+
236
271
@property
237
272
def path (self ):
238
273
return max (
@@ -279,12 +314,18 @@ def required_parts(self):
279
314
return required
280
315
281
316
def to_python (self ):
282
- try :
283
- t = jinja_env .get_template (f"overrides/{ self .namespace } /{ self .name } " )
284
- except TemplateNotFound :
285
- t = jinja_env .get_template ("base" )
317
+ if self .is_pyi :
318
+ t = jinja_env .get_template ("base_pyi" )
319
+ else :
320
+ try :
321
+ t = jinja_env .get_template (f"overrides/{ self .namespace } /{ self .name } " )
322
+ except TemplateNotFound :
323
+ t = jinja_env .get_template ("base" )
324
+
286
325
return t .render (
287
- api = self , substitutions = {v : k for k , v in SUBSTITUTIONS .items ()}
326
+ api = self ,
327
+ substitutions = {v : k for k , v in SUBSTITUTIONS .items ()},
328
+ global_query_params = GLOBAL_QUERY_PARAMS ,
288
329
)
289
330
290
331
@@ -313,6 +354,7 @@ def read_modules():
313
354
modules [namespace ] = Module (namespace )
314
355
315
356
modules [namespace ].add (API (namespace , name , api ))
357
+ modules [namespace ].pyi .add (API (namespace , name , api , is_pyi = True ))
316
358
317
359
return modules
318
360
@@ -340,7 +382,14 @@ def dump_modules(modules):
340
382
filepaths = []
341
383
for root , _ , filenames in os .walk (CODE_ROOT / "elasticsearch/_async" ):
342
384
for filename in filenames :
343
- if filename .endswith (".py" ) and filename != "utils.py" :
385
+ if (
386
+ filename .rpartition ("." )[- 1 ]
387
+ in (
388
+ "py" ,
389
+ "pyi" ,
390
+ )
391
+ and not filename .startswith ("utils.py" )
392
+ ):
344
393
filepaths .append (os .path .join (root , filename ))
345
394
346
395
unasync .unasync_files (filepaths , rules )
0 commit comments