blob: 0dec2589d150517326071b9da045f179a7af917f [file] [log] [blame]
Larry Hastings31826802013-10-19 00:09:25 -07001#!/usr/bin/env python3
2#
3# Argument Clinic
4# Copyright 2012-2013 by Larry Hastings.
5# Licensed to the PSF under a contributor agreement.
6#
7
8import abc
9import ast
10import atexit
Larry Hastings31826802013-10-19 00:09:25 -070011import collections
12import contextlib
13import functools
14import hashlib
15import inspect
16import io
17import itertools
18import os
Larry Hastingsbebf7352014-01-17 17:47:17 -080019import pprint
Larry Hastings31826802013-10-19 00:09:25 -070020import re
21import shlex
22import sys
23import tempfile
24import textwrap
Georg Brandlaabebde2014-01-16 06:53:54 +010025import traceback
Larry Hastingsbebf7352014-01-17 17:47:17 -080026import uuid
Larry Hastings31826802013-10-19 00:09:25 -070027
Larry Hastings31826802013-10-19 00:09:25 -070028# TODO:
Larry Hastings31826802013-10-19 00:09:25 -070029#
30# soon:
31#
32# * allow mixing any two of {positional-only, positional-or-keyword,
33# keyword-only}
34# * dict constructor uses positional-only and keyword-only
35# * max and min use positional only with an optional group
36# and keyword-only
37#
Larry Hastings31826802013-10-19 00:09:25 -070038
Larry Hastingsebdcb502013-11-23 14:54:00 -080039version = '1'
40
Larry Hastings31826802013-10-19 00:09:25 -070041_empty = inspect._empty
42_void = inspect._void
43
Larry Hastings4a55fc52014-01-12 11:09:57 -080044NoneType = type(None)
Larry Hastings31826802013-10-19 00:09:25 -070045
46class Unspecified:
47 def __repr__(self):
48 return '<Unspecified>'
49
50unspecified = Unspecified()
51
52
53class Null:
54 def __repr__(self):
55 return '<Null>'
56
57NULL = Null()
58
59
Larry Hastings2a727912014-01-16 11:32:01 -080060class Unknown:
61 def __repr__(self):
62 return '<Unknown>'
63
64unknown = Unknown()
65
66
Larry Hastings31826802013-10-19 00:09:25 -070067def _text_accumulator():
68 text = []
69 def output():
70 s = ''.join(text)
71 text.clear()
72 return s
73 return text, text.append, output
74
75
76def text_accumulator():
77 """
78 Creates a simple text accumulator / joiner.
79
80 Returns a pair of callables:
81 append, output
82 "append" appends a string to the accumulator.
83 "output" returns the contents of the accumulator
84 joined together (''.join(accumulator)) and
85 empties the accumulator.
86 """
87 text, append, output = _text_accumulator()
88 return append, output
89
90
Larry Hastingsbebf7352014-01-17 17:47:17 -080091def warn_or_fail(fail=False, *args, filename=None, line_number=None):
Larry Hastings31826802013-10-19 00:09:25 -070092 joined = " ".join([str(a) for a in args])
93 add, output = text_accumulator()
Larry Hastingsbebf7352014-01-17 17:47:17 -080094 if fail:
95 add("Error")
96 else:
97 add("Warning")
Larry Hastings31826802013-10-19 00:09:25 -070098 if clinic:
99 if filename is None:
100 filename = clinic.filename
101 if clinic.block_parser and (line_number is None):
102 line_number = clinic.block_parser.line_number
103 if filename is not None:
104 add(' in file "' + filename + '"')
105 if line_number is not None:
106 add(" on line " + str(line_number))
107 add(':\n')
108 add(joined)
109 print(output())
Larry Hastingsbebf7352014-01-17 17:47:17 -0800110 if fail:
111 sys.exit(-1)
Larry Hastings31826802013-10-19 00:09:25 -0700112
113
Larry Hastingsbebf7352014-01-17 17:47:17 -0800114def warn(*args, filename=None, line_number=None):
115 return warn_or_fail(False, *args, filename=filename, line_number=line_number)
116
117def fail(*args, filename=None, line_number=None):
118 return warn_or_fail(True, *args, filename=filename, line_number=line_number)
119
Larry Hastings31826802013-10-19 00:09:25 -0700120
121def quoted_for_c_string(s):
122 for old, new in (
Zachary Ware9d7849f2014-01-25 03:26:20 -0600123 ('\\', '\\\\'), # must be first!
Larry Hastings31826802013-10-19 00:09:25 -0700124 ('"', '\\"'),
125 ("'", "\\'"),
126 ):
127 s = s.replace(old, new)
128 return s
129
Larry Hastings4903e002014-01-18 00:26:16 -0800130def c_repr(s):
131 return '"' + s + '"'
132
133
Larry Hastingsdfcd4672013-10-27 02:49:39 -0700134is_legal_c_identifier = re.compile('^[A-Za-z_][A-Za-z0-9_]*$').match
135
136def is_legal_py_identifier(s):
137 return all(is_legal_c_identifier(field) for field in s.split('.'))
138
Larry Hastingsbebf7352014-01-17 17:47:17 -0800139# identifiers that are okay in Python but aren't a good idea in C.
140# so if they're used Argument Clinic will add "_value" to the end
141# of the name in C.
Larry Hastings31826802013-10-19 00:09:25 -0700142c_keywords = set("""
Larry Hastings5c661892014-01-24 06:17:25 -0800143asm auto break case char const continue default do double
144else enum extern float for goto if inline int long
145register return short signed sizeof static struct switch
Larry Hastingsbebf7352014-01-17 17:47:17 -0800146typedef typeof union unsigned void volatile while
Larry Hastings31826802013-10-19 00:09:25 -0700147""".strip().split())
148
Larry Hastingsdfcd4672013-10-27 02:49:39 -0700149def ensure_legal_c_identifier(s):
150 # for now, just complain if what we're given isn't legal
151 if not is_legal_c_identifier(s):
152 fail("Illegal C identifier: {}".format(s))
153 # but if we picked a C keyword, pick something else
Larry Hastings31826802013-10-19 00:09:25 -0700154 if s in c_keywords:
155 return s + "_value"
156 return s
157
158def rstrip_lines(s):
159 text, add, output = _text_accumulator()
160 for line in s.split('\n'):
161 add(line.rstrip())
162 add('\n')
163 text.pop()
164 return output()
165
166def linear_format(s, **kwargs):
167 """
168 Perform str.format-like substitution, except:
169 * The strings substituted must be on lines by
170 themselves. (This line is the "source line".)
171 * If the substitution text is empty, the source line
172 is removed in the output.
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800173 * If the field is not recognized, the original line
174 is passed unmodified through to the output.
Larry Hastings31826802013-10-19 00:09:25 -0700175 * If the substitution text is not empty:
176 * Each line of the substituted text is indented
177 by the indent of the source line.
178 * A newline will be added to the end.
179 """
180
181 add, output = text_accumulator()
182 for line in s.split('\n'):
183 indent, curly, trailing = line.partition('{')
184 if not curly:
185 add(line)
186 add('\n')
187 continue
188
189 name, curl, trailing = trailing.partition('}')
190 if not curly or name not in kwargs:
191 add(line)
192 add('\n')
193 continue
194
195 if trailing:
196 fail("Text found after {" + name + "} block marker! It must be on a line by itself.")
197 if indent.strip():
198 fail("Non-whitespace characters found before {" + name + "} block marker! It must be on a line by itself.")
199
200 value = kwargs[name]
201 if not value:
202 continue
203
204 value = textwrap.indent(rstrip_lines(value), indent)
205 add(value)
206 add('\n')
207
208 return output()[:-1]
209
Larry Hastingsbebf7352014-01-17 17:47:17 -0800210def indent_all_lines(s, prefix):
211 """
212 Returns 's', with 'prefix' prepended to all lines.
213
214 If the last line is empty, prefix is not prepended
215 to it. (If s is blank, returns s unchanged.)
216
217 (textwrap.indent only adds to non-blank lines.)
218 """
219 split = s.split('\n')
220 last = split.pop()
221 final = []
222 for line in split:
223 final.append(prefix)
224 final.append(line)
225 final.append('\n')
226 if last:
227 final.append(prefix)
228 final.append(last)
229 return ''.join(final)
230
231def suffix_all_lines(s, suffix):
232 """
233 Returns 's', with 'suffix' appended to all lines.
234
235 If the last line is empty, suffix is not appended
236 to it. (If s is blank, returns s unchanged.)
237 """
238 split = s.split('\n')
239 last = split.pop()
240 final = []
241 for line in split:
242 final.append(line)
243 final.append(suffix)
244 final.append('\n')
245 if last:
246 final.append(last)
247 final.append(suffix)
248 return ''.join(final)
249
250
Larry Hastingsebdcb502013-11-23 14:54:00 -0800251def version_splitter(s):
252 """Splits a version string into a tuple of integers.
253
254 The following ASCII characters are allowed, and employ
255 the following conversions:
256 a -> -3
257 b -> -2
258 c -> -1
259 (This permits Python-style version strings such as "1.4b3".)
260 """
261 version = []
262 accumulator = []
263 def flush():
264 if not accumulator:
Larry Hastings2a727912014-01-16 11:32:01 -0800265 raise ValueError('Unsupported version string: ' + repr(s))
Larry Hastingsebdcb502013-11-23 14:54:00 -0800266 version.append(int(''.join(accumulator)))
267 accumulator.clear()
268
269 for c in s:
270 if c.isdigit():
271 accumulator.append(c)
272 elif c == '.':
273 flush()
274 elif c in 'abc':
275 flush()
276 version.append('abc'.index(c) - 3)
277 else:
278 raise ValueError('Illegal character ' + repr(c) + ' in version string ' + repr(s))
279 flush()
280 return tuple(version)
281
282def version_comparitor(version1, version2):
283 iterator = itertools.zip_longest(version_splitter(version1), version_splitter(version2), fillvalue=0)
284 for i, (a, b) in enumerate(iterator):
285 if a < b:
286 return -1
287 if a > b:
288 return 1
289 return 0
290
Larry Hastings31826802013-10-19 00:09:25 -0700291
292class CRenderData:
293 def __init__(self):
294
295 # The C statements to declare variables.
296 # Should be full lines with \n eol characters.
297 self.declarations = []
298
299 # The C statements required to initialize the variables before the parse call.
300 # Should be full lines with \n eol characters.
301 self.initializers = []
302
Larry Hastingsc2047262014-01-25 20:43:29 -0800303 # The C statements needed to dynamically modify the values
304 # parsed by the parse call, before calling the impl.
305 self.modifications = []
306
Larry Hastings31826802013-10-19 00:09:25 -0700307 # The entries for the "keywords" array for PyArg_ParseTuple.
308 # Should be individual strings representing the names.
309 self.keywords = []
310
311 # The "format units" for PyArg_ParseTuple.
312 # Should be individual strings that will get
313 self.format_units = []
314
315 # The varargs arguments for PyArg_ParseTuple.
316 self.parse_arguments = []
317
318 # The parameter declarations for the impl function.
319 self.impl_parameters = []
320
321 # The arguments to the impl function at the time it's called.
322 self.impl_arguments = []
323
324 # For return converters: the name of the variable that
325 # should receive the value returned by the impl.
326 self.return_value = "return_value"
327
328 # For return converters: the code to convert the return
329 # value from the parse function. This is also where
330 # you should check the _return_value for errors, and
331 # "goto exit" if there are any.
332 self.return_conversion = []
333
334 # The C statements required to clean up after the impl call.
335 self.cleanup = []
336
337
338class Language(metaclass=abc.ABCMeta):
339
340 start_line = ""
341 body_prefix = ""
342 stop_line = ""
343 checksum_line = ""
344
345 @abc.abstractmethod
Larry Hastingsbebf7352014-01-17 17:47:17 -0800346 def render(self, clinic, signatures):
Larry Hastings31826802013-10-19 00:09:25 -0700347 pass
348
349 def validate(self):
350 def assert_only_one(field, token='dsl_name'):
351 line = getattr(self, field)
352 token = '{' + token + '}'
353 if len(line.split(token)) != 2:
354 fail(self.__class__.__name__ + " " + field + " must contain " + token + " exactly once!")
355 assert_only_one('start_line')
356 assert_only_one('stop_line')
357 assert_only_one('checksum_line')
358 assert_only_one('checksum_line', 'checksum')
359
360 if len(self.body_prefix.split('{dsl_name}')) >= 3:
361 fail(self.__class__.__name__ + " body_prefix may contain " + token + " once at most!")
362
363
364
365class PythonLanguage(Language):
366
367 language = 'Python'
Larry Hastings61272b72014-01-07 12:41:53 -0800368 start_line = "#/*[{dsl_name} input]"
Larry Hastings31826802013-10-19 00:09:25 -0700369 body_prefix = "#"
Larry Hastings61272b72014-01-07 12:41:53 -0800370 stop_line = "#[{dsl_name} start generated code]*/"
371 checksum_line = "#/*[{dsl_name} end generated code: checksum={checksum}]*/"
Larry Hastings31826802013-10-19 00:09:25 -0700372
373
374def permute_left_option_groups(l):
375 """
376 Given [1, 2, 3], should yield:
377 ()
378 (3,)
379 (2, 3)
380 (1, 2, 3)
381 """
382 yield tuple()
383 accumulator = []
384 for group in reversed(l):
385 accumulator = list(group) + accumulator
386 yield tuple(accumulator)
387
388
389def permute_right_option_groups(l):
390 """
391 Given [1, 2, 3], should yield:
392 ()
393 (1,)
394 (1, 2)
395 (1, 2, 3)
396 """
397 yield tuple()
398 accumulator = []
399 for group in l:
400 accumulator.extend(group)
401 yield tuple(accumulator)
402
403
404def permute_optional_groups(left, required, right):
405 """
406 Generator function that computes the set of acceptable
407 argument lists for the provided iterables of
408 argument groups. (Actually it generates a tuple of tuples.)
409
410 Algorithm: prefer left options over right options.
411
412 If required is empty, left must also be empty.
413 """
414 required = tuple(required)
415 result = []
416
417 if not required:
418 assert not left
419
420 accumulator = []
421 counts = set()
422 for r in permute_right_option_groups(right):
423 for l in permute_left_option_groups(left):
424 t = l + required + r
425 if len(t) in counts:
426 continue
427 counts.add(len(t))
428 accumulator.append(t)
429
430 accumulator.sort(key=len)
431 return tuple(accumulator)
432
433
434class CLanguage(Language):
435
Larry Hastings61272b72014-01-07 12:41:53 -0800436 body_prefix = "#"
Larry Hastings31826802013-10-19 00:09:25 -0700437 language = 'C'
Larry Hastings61272b72014-01-07 12:41:53 -0800438 start_line = "/*[{dsl_name} input]"
Larry Hastings31826802013-10-19 00:09:25 -0700439 body_prefix = ""
Larry Hastings61272b72014-01-07 12:41:53 -0800440 stop_line = "[{dsl_name} start generated code]*/"
441 checksum_line = "/*[{dsl_name} end generated code: checksum={checksum}]*/"
Larry Hastings31826802013-10-19 00:09:25 -0700442
Larry Hastingsbebf7352014-01-17 17:47:17 -0800443 def render(self, clinic, signatures):
Larry Hastings31826802013-10-19 00:09:25 -0700444 function = None
445 for o in signatures:
446 if isinstance(o, Function):
447 if function:
448 fail("You may specify at most one function per block.\nFound a block containing at least two:\n\t" + repr(function) + " and " + repr(o))
449 function = o
Larry Hastingsbebf7352014-01-17 17:47:17 -0800450 return self.render_function(clinic, function)
Larry Hastings31826802013-10-19 00:09:25 -0700451
452 def docstring_for_c_string(self, f):
453 text, add, output = _text_accumulator()
454 # turn docstring into a properly quoted C string
455 for line in f.docstring.split('\n'):
456 add('"')
457 add(quoted_for_c_string(line))
458 add('\\n"\n')
459
460 text.pop()
461 add('"')
462 return ''.join(text)
463
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800464 _templates = {}
465 # the templates will be run through str.format(),
466 # so actual curly-braces need to be doubled up.
467 templates_source = """
468__________________________________________________
469
470docstring_prototype
471
472PyDoc_VAR({c_basename}__doc__);
473__________________________________________________
474
475docstring_definition
476
477PyDoc_STRVAR({c_basename}__doc__,
478{docstring});
479__________________________________________________
480
481impl_definition
482
483static {impl_return_type}
484{c_basename}_impl({impl_parameters})
485__________________________________________________
486
487parser_prototype_noargs
488
489static PyObject *
490{c_basename}({self_type}{self_name}, PyObject *Py_UNUSED(ignored))
491__________________________________________________
492
493parser_prototype_meth_o
494
495# SLIGHT HACK
496# METH_O uses {impl_parameters} for the parser!
497
498static PyObject *
499{c_basename}({impl_parameters})
500__________________________________________________
501
502parser_prototype_varargs
503
504static PyObject *
505{c_basename}({self_type}{self_name}, PyObject *args)
506__________________________________________________
507
508parser_prototype_keyword
509
510static PyObject *
511{c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
512__________________________________________________
513
514parser_prototype_init
515
516static int
517{c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
518__________________________________________________
519
520parser_definition_simple_no_parsing
521
522{{
523 return {c_basename}_impl({impl_arguments});
524}}
525__________________________________________________
526
527parser_definition_start
528
529{{
530 {return_value_declaration}
531 {declarations}
532 {initializers}
533{empty line}
534__________________________________________________
535
536parser_definition_end
537
538 {return_conversion}
539
540{exit_label}
541 {cleanup}
542 return return_value;
543}}
544__________________________________________________
545
546parser_definition_impl_call
547
Larry Hastingsc2047262014-01-25 20:43:29 -0800548 {modifications}
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800549 {return_value} = {c_basename}_impl({impl_arguments});
550__________________________________________________
551
552parser_definition_unpack_tuple
553
554 if (!PyArg_UnpackTuple(args, "{name}",
555 {unpack_min}, {unpack_max},
556 {parse_arguments}))
557 goto exit;
558__________________________________________________
559
560parser_definition_parse_tuple
561
562 if (!PyArg_ParseTuple(args,
563 "{format_units}:{name}",
564 {parse_arguments}))
565 goto exit;
566__________________________________________________
567
568parser_definition_option_groups
569 {option_group_parsing}
570
571__________________________________________________
572
573parser_definition_parse_tuple_and_keywords
574
575 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
576 "{format_units}:{name}", _keywords,
577 {parse_arguments}))
578 goto exit;
579__________________________________________________
580
581parser_definition_no_positional
582
Larry Hastingsc2047262014-01-25 20:43:29 -0800583 if ({self_type_check}!_PyArg_NoPositional("{name}", args))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800584 goto exit;
585
586__________________________________________________
587
588parser_definition_no_keywords
589
Larry Hastingsc2047262014-01-25 20:43:29 -0800590 if ({self_type_check}!_PyArg_NoKeywords("{name}", kwargs))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800591 goto exit;
592
593__________________________________________________
594
595methoddef_define
596
597#define {methoddef_name} \\
598 {{"{name}", (PyCFunction){c_basename}, {methoddef_flags}, {c_basename}__doc__}},
599__________________________________________________
600""".rstrip()
601
602 title = ''
603 buffer = []
604 line = None
605 for line in templates_source.split('\n'):
606 line = line.rstrip()
607 if line.startswith('# '):
608 # comment
609 continue
610 if line.startswith("_____"):
611 if not buffer:
612 continue
613 assert title not in _templates, "defined template twice: " + repr(title)
614 buffer = '\n'.join(buffer).rstrip()
615 buffer = buffer.replace('{empty line}', '')
616 _templates[title] = buffer
617 buffer = []
618 title = ''
619 continue
620 if not title:
621 if not line:
622 continue
623 title = line
624 continue
625 if not (line or buffer):
626 # throw away leading blank lines
627 continue
628 buffer.append(line)
629
630 assert not title, 'ensure templates_source ends with ______ (still adding to ' + repr(title) + ")"
631
632 del templates_source
633 del title
634 del buffer
635 del line
636
637 # for name, value in _templates.items():
638 # print(name + ":")
639 # pprint.pprint(value)
640 # print()
Larry Hastings31826802013-10-19 00:09:25 -0700641
Larry Hastingsbebf7352014-01-17 17:47:17 -0800642 def output_templates(self, f):
643 parameters = list(f.parameters.values())
Larry Hastings5c661892014-01-24 06:17:25 -0800644 assert parameters
645 assert isinstance(parameters[0].converter, self_converter)
646 del parameters[0]
Larry Hastingsbebf7352014-01-17 17:47:17 -0800647 converters = [p.converter for p in parameters]
648
649 has_option_groups = parameters and (parameters[0].group or parameters[-1].group)
650 default_return_converter = (not f.return_converter or
651 f.return_converter.type == 'PyObject *')
652
653 positional = parameters and (parameters[-1].kind == inspect.Parameter.POSITIONAL_ONLY)
654 all_boring_objects = False # yes, this will be false if there are 0 parameters, it's fine
655 first_optional = len(parameters)
656 for i, p in enumerate(parameters):
657 c = p.converter
658 if type(c) != object_converter:
659 break
660 if c.format_unit != 'O':
661 break
662 if p.default is not unspecified:
663 first_optional = min(first_optional, i)
664 else:
665 all_boring_objects = True
666
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800667 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
668
Larry Hastingsbebf7352014-01-17 17:47:17 -0800669 meth_o = (len(parameters) == 1 and
670 parameters[0].kind == inspect.Parameter.POSITIONAL_ONLY and
671 not converters[0].is_optional() and
672 isinstance(converters[0], object_converter) and
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800673 converters[0].format_unit == 'O' and
674 not new_or_init)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800675
676 # we have to set seven things before we're done:
677 #
678 # docstring_prototype
679 # docstring_definition
680 # impl_prototype
681 # methoddef_define
682 # parser_prototype
683 # parser_definition
684 # impl_definition
Larry Hastingsbebf7352014-01-17 17:47:17 -0800685
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800686 templates = self._templates
Larry Hastingsbebf7352014-01-17 17:47:17 -0800687
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800688 return_value_declaration = "PyObject *return_value = NULL;"
Larry Hastings31826802013-10-19 00:09:25 -0700689
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800690 methoddef_define = templates['methoddef_define']
Larry Hastings5c661892014-01-24 06:17:25 -0800691 if new_or_init and not f.docstring:
692 docstring_prototype = docstring_definition = ''
693 else:
694 docstring_prototype = templates['docstring_prototype']
695 docstring_definition = templates['docstring_definition']
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800696 impl_definition = templates['impl_definition']
Larry Hastingsbebf7352014-01-17 17:47:17 -0800697 impl_prototype = parser_prototype = parser_definition = None
698
Larry Hastingsc2047262014-01-25 20:43:29 -0800699 parser_body_fields = ()
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800700 def parser_body(prototype, *fields):
701 nonlocal parser_body_fields
702 add, output = text_accumulator()
703 add(prototype)
704 parser_body_fields = fields
705 fields = list(fields)
706 fields.insert(0, 'parser_definition_start')
707 fields.append('parser_definition_impl_call')
708 fields.append('parser_definition_end')
709 for field in fields:
710 add('\n')
711 add(templates[field])
712 return output()
Larry Hastingsbebf7352014-01-17 17:47:17 -0800713
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800714 def insert_keywords(s):
715 return linear_format(s, declarations="static char *_keywords[] = {{{keywords}, NULL}};\n{declarations}")
Larry Hastingsbebf7352014-01-17 17:47:17 -0800716
717 if not parameters:
718 # no parameters, METH_NOARGS
719
720 flags = "METH_NOARGS"
721
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800722 parser_prototype = templates['parser_prototype_noargs']
723 parser_definition = parser_prototype
Larry Hastingsbebf7352014-01-17 17:47:17 -0800724
725 if default_return_converter:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800726 parser_definition = parser_prototype + '\n' + templates['parser_definition_simple_no_parsing']
Larry Hastingsbebf7352014-01-17 17:47:17 -0800727 else:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800728 parser_definition = parser_body(parser_prototype)
Larry Hastings31826802013-10-19 00:09:25 -0700729
Larry Hastingsbebf7352014-01-17 17:47:17 -0800730 elif meth_o:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800731 flags = "METH_O"
732 # impl_definition = templates['parser_prototype_meth_o']
733
Larry Hastingsbebf7352014-01-17 17:47:17 -0800734 if default_return_converter:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800735 # maps perfectly to METH_O, doesn't need a return converter.
736 # so we skip making a parse function
737 # and call directly into the impl function.
Larry Hastingsbebf7352014-01-17 17:47:17 -0800738 impl_prototype = parser_prototype = parser_definition = ''
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800739 impl_definition = templates['parser_prototype_meth_o']
Larry Hastingsbebf7352014-01-17 17:47:17 -0800740 else:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800741 parser_prototype = templates['parser_prototype_meth_o']
742 parser_definition = parser_body(parser_prototype)
Larry Hastings31826802013-10-19 00:09:25 -0700743
Larry Hastingsbebf7352014-01-17 17:47:17 -0800744 elif has_option_groups:
745 # positional parameters with option groups
746 # (we have to generate lots of PyArg_ParseTuple calls
747 # in a big switch statement)
Larry Hastings31826802013-10-19 00:09:25 -0700748
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800749 flags = "METH_VARARGS"
750 parser_prototype = templates['parser_prototype_varargs']
Larry Hastings31826802013-10-19 00:09:25 -0700751
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800752 parser_definition = parser_body(parser_prototype, 'parser_definition_option_groups')
Larry Hastings31826802013-10-19 00:09:25 -0700753
Larry Hastingsbebf7352014-01-17 17:47:17 -0800754 elif positional and all_boring_objects:
755 # positional-only, but no option groups,
756 # and nothing but normal objects:
757 # PyArg_UnpackTuple!
Larry Hastings31826802013-10-19 00:09:25 -0700758
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800759 flags = "METH_VARARGS"
760 parser_prototype = templates['parser_prototype_varargs']
Larry Hastings31826802013-10-19 00:09:25 -0700761
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800762 parser_definition = parser_body(parser_prototype, 'parser_definition_unpack_tuple')
Larry Hastingsbebf7352014-01-17 17:47:17 -0800763
764 elif positional:
765 # positional-only, but no option groups
766 # we only need one call to PyArg_ParseTuple
767
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800768 flags = "METH_VARARGS"
769 parser_prototype = templates['parser_prototype_varargs']
Larry Hastingsbebf7352014-01-17 17:47:17 -0800770
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800771 parser_definition = parser_body(parser_prototype, 'parser_definition_parse_tuple')
Larry Hastingsbebf7352014-01-17 17:47:17 -0800772
773 else:
774 # positional-or-keyword arguments
775 flags = "METH_VARARGS|METH_KEYWORDS"
776
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800777 parser_prototype = templates['parser_prototype_keyword']
Larry Hastingsbebf7352014-01-17 17:47:17 -0800778
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800779 parser_definition = parser_body(parser_prototype, 'parser_definition_parse_tuple_and_keywords')
780 parser_definition = insert_keywords(parser_definition)
Larry Hastings31826802013-10-19 00:09:25 -0700781
Larry Hastings31826802013-10-19 00:09:25 -0700782
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800783 if new_or_init:
784 methoddef_define = ''
785
786 if f.kind == METHOD_NEW:
787 parser_prototype = templates['parser_prototype_keyword']
788 else:
789 return_value_declaration = "int return_value = -1;"
790 parser_prototype = templates['parser_prototype_init']
791
792 fields = list(parser_body_fields)
793 parses_positional = 'METH_NOARGS' not in flags
794 parses_keywords = 'METH_KEYWORDS' in flags
795 if parses_keywords:
796 assert parses_positional
797
798 if not parses_keywords:
799 fields.insert(0, 'parser_definition_no_keywords')
800 if not parses_positional:
801 fields.insert(0, 'parser_definition_no_positional')
802
803 parser_definition = parser_body(parser_prototype, *fields)
804 if parses_keywords:
805 parser_definition = insert_keywords(parser_definition)
806
Larry Hastings31826802013-10-19 00:09:25 -0700807
Larry Hastingsbebf7352014-01-17 17:47:17 -0800808 if f.methoddef_flags:
Larry Hastingsbebf7352014-01-17 17:47:17 -0800809 flags += '|' + f.methoddef_flags
Larry Hastings31826802013-10-19 00:09:25 -0700810
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800811 methoddef_define = methoddef_define.replace('{methoddef_flags}', flags)
Larry Hastings31826802013-10-19 00:09:25 -0700812
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800813 # add ';' to the end of parser_prototype and impl_prototype
814 # (they mustn't be None, but they could be an empty string.)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800815 assert parser_prototype is not None
Larry Hastingsbebf7352014-01-17 17:47:17 -0800816 if parser_prototype:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800817 assert not parser_prototype.endswith(';')
Larry Hastingsbebf7352014-01-17 17:47:17 -0800818 parser_prototype += ';'
Larry Hastings31826802013-10-19 00:09:25 -0700819
Larry Hastingsbebf7352014-01-17 17:47:17 -0800820 if impl_prototype is None:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800821 impl_prototype = impl_definition
822 if impl_prototype:
823 impl_prototype += ";"
Larry Hastings31826802013-10-19 00:09:25 -0700824
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800825 parser_definition = parser_definition.replace("{return_value_declaration}", return_value_declaration)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800826
827 d = {
828 "docstring_prototype" : docstring_prototype,
829 "docstring_definition" : docstring_definition,
830 "impl_prototype" : impl_prototype,
831 "methoddef_define" : methoddef_define,
832 "parser_prototype" : parser_prototype,
833 "parser_definition" : parser_definition,
834 "impl_definition" : impl_definition,
835 }
836
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800837 # make sure we didn't forget to assign something,
838 # and wrap each non-empty value in \n's
Larry Hastingsbebf7352014-01-17 17:47:17 -0800839 d2 = {}
840 for name, value in d.items():
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800841 assert value is not None, "got a None value for template " + repr(name)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800842 if value:
843 value = '\n' + value + '\n'
844 d2[name] = value
845 return d2
Larry Hastings31826802013-10-19 00:09:25 -0700846
847 @staticmethod
848 def group_to_variable_name(group):
849 adjective = "left_" if group < 0 else "right_"
850 return "group_" + adjective + str(abs(group))
851
852 def render_option_group_parsing(self, f, template_dict):
853 # positional only, grouped, optional arguments!
854 # can be optional on the left or right.
855 # here's an example:
856 #
857 # [ [ [ A1 A2 ] B1 B2 B3 ] C1 C2 ] D1 D2 D3 [ E1 E2 E3 [ F1 F2 F3 ] ]
858 #
859 # Here group D are required, and all other groups are optional.
860 # (Group D's "group" is actually None.)
861 # We can figure out which sets of arguments we have based on
862 # how many arguments are in the tuple.
863 #
864 # Note that you need to count up on both sides. For example,
865 # you could have groups C+D, or C+D+E, or C+D+E+F.
866 #
867 # What if the number of arguments leads us to an ambiguous result?
868 # Clinic prefers groups on the left. So in the above example,
869 # five arguments would map to B+C, not C+D.
870
871 add, output = text_accumulator()
872 parameters = list(f.parameters.values())
Larry Hastings5c661892014-01-24 06:17:25 -0800873 if isinstance(parameters[0].converter, self_converter):
874 del parameters[0]
Larry Hastings31826802013-10-19 00:09:25 -0700875
876 groups = []
877 group = None
878 left = []
879 right = []
880 required = []
881 last = unspecified
882
883 for p in parameters:
884 group_id = p.group
885 if group_id != last:
886 last = group_id
887 group = []
888 if group_id < 0:
889 left.append(group)
890 elif group_id == 0:
891 group = required
892 else:
893 right.append(group)
894 group.append(p)
895
896 count_min = sys.maxsize
897 count_max = -1
898
Larry Hastings2a727912014-01-16 11:32:01 -0800899 add("switch (PyTuple_GET_SIZE(args)) {{\n")
Larry Hastings31826802013-10-19 00:09:25 -0700900 for subset in permute_optional_groups(left, required, right):
901 count = len(subset)
902 count_min = min(count_min, count)
903 count_max = max(count_max, count)
904
Larry Hastings583baa82014-01-12 08:49:30 -0800905 if count == 0:
906 add(""" case 0:
907 break;
908""")
909 continue
910
Larry Hastings31826802013-10-19 00:09:25 -0700911 group_ids = {p.group for p in subset} # eliminate duplicates
912 d = {}
913 d['count'] = count
914 d['name'] = f.name
915 d['groups'] = sorted(group_ids)
916 d['format_units'] = "".join(p.converter.format_unit for p in subset)
917
918 parse_arguments = []
919 for p in subset:
920 p.converter.parse_argument(parse_arguments)
921 d['parse_arguments'] = ", ".join(parse_arguments)
922
923 group_ids.discard(0)
924 lines = [self.group_to_variable_name(g) + " = 1;" for g in group_ids]
925 lines = "\n".join(lines)
926
927 s = """
928 case {count}:
929 if (!PyArg_ParseTuple(args, "{format_units}:{name}", {parse_arguments}))
Larry Hastings46258262014-01-22 03:05:49 -0800930 goto exit;
Larry Hastings31826802013-10-19 00:09:25 -0700931 {group_booleans}
932 break;
933"""[1:]
934 s = linear_format(s, group_booleans=lines)
935 s = s.format_map(d)
936 add(s)
937
938 add(" default:\n")
939 s = ' PyErr_SetString(PyExc_TypeError, "{} requires {} to {} arguments");\n'
940 add(s.format(f.full_name, count_min, count_max))
Larry Hastings46258262014-01-22 03:05:49 -0800941 add(' goto exit;\n')
Larry Hastings31826802013-10-19 00:09:25 -0700942 add("}}")
943 template_dict['option_group_parsing'] = output()
944
Larry Hastingsbebf7352014-01-17 17:47:17 -0800945 def render_function(self, clinic, f):
Larry Hastings31826802013-10-19 00:09:25 -0700946 if not f:
947 return ""
948
949 add, output = text_accumulator()
950 data = CRenderData()
951
Larry Hastings31826802013-10-19 00:09:25 -0700952 parameters = list(f.parameters.values())
Larry Hastings5c661892014-01-24 06:17:25 -0800953 assert parameters, "We should always have a 'self' at this point!"
954
Larry Hastings31826802013-10-19 00:09:25 -0700955 converters = [p.converter for p in parameters]
956
Larry Hastings5c661892014-01-24 06:17:25 -0800957 templates = self.output_templates(f)
958
959 f_self = parameters[0]
960 selfless = parameters[1:]
961 assert isinstance(f_self.converter, self_converter), "No self parameter in " + repr(f.full_name) + "!"
962
963 last_group = 0
964 first_optional = len(selfless)
965 positional = selfless and selfless[-1].kind == inspect.Parameter.POSITIONAL_ONLY
966 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
967 default_return_converter = (not f.return_converter or
968 f.return_converter.type == 'PyObject *')
969 has_option_groups = False
970
971 # offset i by -1 because first_optional needs to ignore self
972 for i, p in enumerate(parameters, -1):
973 c = p.converter
974
975 if (i != -1) and (p.default is not unspecified):
976 first_optional = min(first_optional, i)
977
978 # insert group variable
979 group = p.group
980 if last_group != group:
981 last_group = group
982 if group:
983 group_name = self.group_to_variable_name(group)
984 data.impl_arguments.append(group_name)
985 data.declarations.append("int " + group_name + " = 0;")
986 data.impl_parameters.append("int " + group_name)
987 has_option_groups = True
988
989 c.render(p, data)
990
991 if has_option_groups and (not positional):
992 fail("You cannot use optional groups ('[' and ']')\nunless all parameters are positional-only ('/').")
993
994 # HACK
995 # when we're METH_O, but have a custom return converter,
996 # we use "impl_parameters" for the parsing function
997 # because that works better. but that means we must
998 # supress actually declaring the impl's parameters
999 # as variables in the parsing function. but since it's
1000 # METH_O, we have exactly one anyway, so we know exactly
1001 # where it is.
1002 if ("METH_O" in templates['methoddef_define'] and
1003 not default_return_converter):
1004 data.declarations.pop(0)
1005
Larry Hastings31826802013-10-19 00:09:25 -07001006 template_dict = {}
1007
1008 full_name = f.full_name
1009 template_dict['full_name'] = full_name
1010
Larry Hastings5c661892014-01-24 06:17:25 -08001011 if new_or_init:
1012 name = f.cls.name
1013 else:
1014 name = f.name
1015
Larry Hastings31826802013-10-19 00:09:25 -07001016 template_dict['name'] = name
1017
Larry Hastings8666e652014-01-12 14:12:59 -08001018 if f.c_basename:
1019 c_basename = f.c_basename
1020 else:
1021 fields = full_name.split(".")
1022 if fields[-1] == '__new__':
1023 fields.pop()
1024 c_basename = "_".join(fields)
Larry Hastings5c661892014-01-24 06:17:25 -08001025
Larry Hastings31826802013-10-19 00:09:25 -07001026 template_dict['c_basename'] = c_basename
1027
1028 methoddef_name = "{}_METHODDEF".format(c_basename.upper())
1029 template_dict['methoddef_name'] = methoddef_name
1030
1031 template_dict['docstring'] = self.docstring_for_c_string(f)
1032
Larry Hastingsc2047262014-01-25 20:43:29 -08001033 template_dict['self_name'] = template_dict['self_type'] = template_dict['self_type_check'] = ''
Larry Hastings5c661892014-01-24 06:17:25 -08001034 f_self.converter.set_template_dict(template_dict)
Larry Hastingsebdcb502013-11-23 14:54:00 -08001035
Larry Hastings31826802013-10-19 00:09:25 -07001036 f.return_converter.render(f, data)
1037 template_dict['impl_return_type'] = f.return_converter.type
1038
1039 template_dict['declarations'] = "\n".join(data.declarations)
1040 template_dict['initializers'] = "\n\n".join(data.initializers)
Larry Hastingsc2047262014-01-25 20:43:29 -08001041 template_dict['modifications'] = '\n\n'.join(data.modifications)
Larry Hastings31826802013-10-19 00:09:25 -07001042 template_dict['keywords'] = '"' + '", "'.join(data.keywords) + '"'
1043 template_dict['format_units'] = ''.join(data.format_units)
1044 template_dict['parse_arguments'] = ', '.join(data.parse_arguments)
1045 template_dict['impl_parameters'] = ", ".join(data.impl_parameters)
1046 template_dict['impl_arguments'] = ", ".join(data.impl_arguments)
1047 template_dict['return_conversion'] = "".join(data.return_conversion).rstrip()
1048 template_dict['cleanup'] = "".join(data.cleanup)
1049 template_dict['return_value'] = data.return_value
1050
Larry Hastings5c661892014-01-24 06:17:25 -08001051 # used by unpack tuple code generator
1052 ignore_self = -1 if isinstance(converters[0], self_converter) else 0
1053 unpack_min = first_optional
1054 unpack_max = len(selfless)
1055 template_dict['unpack_min'] = str(unpack_min)
1056 template_dict['unpack_max'] = str(unpack_max)
Larry Hastingsb7ccb202014-01-18 23:50:21 -08001057
Larry Hastingsbebf7352014-01-17 17:47:17 -08001058 if has_option_groups:
Larry Hastings31826802013-10-19 00:09:25 -07001059 self.render_option_group_parsing(f, template_dict)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001060
Larry Hastingsbebf7352014-01-17 17:47:17 -08001061 for name, destination in clinic.field_destinations.items():
1062 template = templates[name]
1063 if has_option_groups:
1064 template = linear_format(template,
1065 option_group_parsing=template_dict['option_group_parsing'])
Larry Hastings31826802013-10-19 00:09:25 -07001066 template = linear_format(template,
Larry Hastingsbebf7352014-01-17 17:47:17 -08001067 declarations=template_dict['declarations'],
1068 return_conversion=template_dict['return_conversion'],
1069 initializers=template_dict['initializers'],
Larry Hastingsc2047262014-01-25 20:43:29 -08001070 modifications=template_dict['modifications'],
Larry Hastingsbebf7352014-01-17 17:47:17 -08001071 cleanup=template_dict['cleanup'],
1072 )
Larry Hastings31826802013-10-19 00:09:25 -07001073
Larry Hastingsbebf7352014-01-17 17:47:17 -08001074 # Only generate the "exit:" label
1075 # if we have any gotos
1076 need_exit_label = "goto exit;" in template
1077 template = linear_format(template,
1078 exit_label="exit:" if need_exit_label else ''
1079 )
Larry Hastings31826802013-10-19 00:09:25 -07001080
Larry Hastingsbebf7352014-01-17 17:47:17 -08001081 s = template.format_map(template_dict)
Larry Hastings31826802013-10-19 00:09:25 -07001082
Larry Hastingsbebf7352014-01-17 17:47:17 -08001083 if clinic.line_prefix:
1084 s = indent_all_lines(s, clinic.line_prefix)
1085 if clinic.line_suffix:
1086 s = suffix_all_lines(s, clinic.line_suffix)
1087
1088 destination.append(s)
1089
1090 return clinic.get_destination('block').dump()
1091
Larry Hastings31826802013-10-19 00:09:25 -07001092
1093
Larry Hastings5c661892014-01-24 06:17:25 -08001094
Larry Hastings31826802013-10-19 00:09:25 -07001095@contextlib.contextmanager
1096def OverrideStdioWith(stdout):
1097 saved_stdout = sys.stdout
1098 sys.stdout = stdout
1099 try:
1100 yield
1101 finally:
1102 assert sys.stdout is stdout
1103 sys.stdout = saved_stdout
1104
1105
1106def create_regex(before, after):
1107 """Create an re object for matching marker lines."""
1108 pattern = r'^{}(\w+){}$'
1109 return re.compile(pattern.format(re.escape(before), re.escape(after)))
1110
1111
1112class Block:
1113 r"""
1114 Represents a single block of text embedded in
1115 another file. If dsl_name is None, the block represents
1116 verbatim text, raw original text from the file, in
1117 which case "input" will be the only non-false member.
1118 If dsl_name is not None, the block represents a Clinic
1119 block.
1120
1121 input is always str, with embedded \n characters.
1122 input represents the original text from the file;
1123 if it's a Clinic block, it is the original text with
1124 the body_prefix and redundant leading whitespace removed.
1125
1126 dsl_name is either str or None. If str, it's the text
1127 found on the start line of the block between the square
1128 brackets.
1129
1130 signatures is either list or None. If it's a list,
1131 it may only contain clinic.Module, clinic.Class, and
1132 clinic.Function objects. At the moment it should
1133 contain at most one of each.
1134
1135 output is either str or None. If str, it's the output
1136 from this block, with embedded '\n' characters.
1137
1138 indent is either str or None. It's the leading whitespace
1139 that was found on every line of input. (If body_prefix is
1140 not empty, this is the indent *after* removing the
1141 body_prefix.)
1142
1143 preindent is either str or None. It's the whitespace that
1144 was found in front of every line of input *before* the
1145 "body_prefix" (see the Language object). If body_prefix
1146 is empty, preindent must always be empty too.
1147
1148 To illustrate indent and preindent: Assume that '_'
1149 represents whitespace. If the block processed was in a
1150 Python file, and looked like this:
1151 ____#/*[python]
1152 ____#__for a in range(20):
1153 ____#____print(a)
1154 ____#[python]*/
1155 "preindent" would be "____" and "indent" would be "__".
1156
1157 """
1158 def __init__(self, input, dsl_name=None, signatures=None, output=None, indent='', preindent=''):
1159 assert isinstance(input, str)
1160 self.input = input
1161 self.dsl_name = dsl_name
1162 self.signatures = signatures or []
1163 self.output = output
1164 self.indent = indent
1165 self.preindent = preindent
1166
1167
1168class BlockParser:
1169 """
1170 Block-oriented parser for Argument Clinic.
1171 Iterator, yields Block objects.
1172 """
1173
1174 def __init__(self, input, language, *, verify=True):
1175 """
1176 "input" should be a str object
1177 with embedded \n characters.
1178
1179 "language" should be a Language object.
1180 """
1181 language.validate()
1182
1183 self.input = collections.deque(reversed(input.splitlines(keepends=True)))
1184 self.block_start_line_number = self.line_number = 0
1185
1186 self.language = language
1187 before, _, after = language.start_line.partition('{dsl_name}')
1188 assert _ == '{dsl_name}'
1189 self.start_re = create_regex(before, after)
1190 self.verify = verify
1191 self.last_checksum_re = None
1192 self.last_dsl_name = None
1193 self.dsl_name = None
Larry Hastingsbebf7352014-01-17 17:47:17 -08001194 self.first_block = True
Larry Hastings31826802013-10-19 00:09:25 -07001195
1196 def __iter__(self):
1197 return self
1198
1199 def __next__(self):
Larry Hastingsbebf7352014-01-17 17:47:17 -08001200 while True:
1201 if not self.input:
1202 raise StopIteration
Larry Hastings31826802013-10-19 00:09:25 -07001203
Larry Hastingsbebf7352014-01-17 17:47:17 -08001204 if self.dsl_name:
1205 return_value = self.parse_clinic_block(self.dsl_name)
1206 self.dsl_name = None
1207 self.first_block = False
1208 return return_value
1209 block = self.parse_verbatim_block()
1210 if self.first_block and not block.input:
1211 continue
1212 self.first_block = False
1213 return block
1214
Larry Hastings31826802013-10-19 00:09:25 -07001215
1216 def is_start_line(self, line):
1217 match = self.start_re.match(line.lstrip())
1218 return match.group(1) if match else None
1219
1220 def _line(self):
1221 self.line_number += 1
1222 return self.input.pop()
1223
1224 def parse_verbatim_block(self):
1225 add, output = text_accumulator()
1226 self.block_start_line_number = self.line_number
1227
1228 while self.input:
1229 line = self._line()
1230 dsl_name = self.is_start_line(line)
1231 if dsl_name:
1232 self.dsl_name = dsl_name
1233 break
1234 add(line)
1235
1236 return Block(output())
1237
1238 def parse_clinic_block(self, dsl_name):
1239 input_add, input_output = text_accumulator()
1240 self.block_start_line_number = self.line_number + 1
Larry Hastings90261132014-01-07 12:21:08 -08001241 stop_line = self.language.stop_line.format(dsl_name=dsl_name)
Larry Hastings31826802013-10-19 00:09:25 -07001242 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1243
Larry Hastings90261132014-01-07 12:21:08 -08001244 def is_stop_line(line):
1245 # make sure to recognize stop line even if it
1246 # doesn't end with EOL (it could be the very end of the file)
1247 if not line.startswith(stop_line):
1248 return False
1249 remainder = line[len(stop_line):]
1250 return (not remainder) or remainder.isspace()
1251
Larry Hastings31826802013-10-19 00:09:25 -07001252 # consume body of program
1253 while self.input:
1254 line = self._line()
Larry Hastings90261132014-01-07 12:21:08 -08001255 if is_stop_line(line) or self.is_start_line(line):
Larry Hastings31826802013-10-19 00:09:25 -07001256 break
1257 if body_prefix:
1258 line = line.lstrip()
1259 assert line.startswith(body_prefix)
1260 line = line[len(body_prefix):]
1261 input_add(line)
1262
1263 # consume output and checksum line, if present.
1264 if self.last_dsl_name == dsl_name:
1265 checksum_re = self.last_checksum_re
1266 else:
1267 before, _, after = self.language.checksum_line.format(dsl_name=dsl_name, checksum='{checksum}').partition('{checksum}')
1268 assert _ == '{checksum}'
1269 checksum_re = create_regex(before, after)
1270 self.last_dsl_name = dsl_name
1271 self.last_checksum_re = checksum_re
1272
1273 # scan forward for checksum line
1274 output_add, output_output = text_accumulator()
1275 checksum = None
1276 while self.input:
1277 line = self._line()
1278 match = checksum_re.match(line.lstrip())
1279 checksum = match.group(1) if match else None
1280 if checksum:
1281 break
1282 output_add(line)
1283 if self.is_start_line(line):
1284 break
1285
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07001286 output = output_output()
Larry Hastings31826802013-10-19 00:09:25 -07001287 if checksum:
Larry Hastings31826802013-10-19 00:09:25 -07001288 if self.verify:
1289 computed = compute_checksum(output)
1290 if checksum != computed:
Antoine Pitroucc1d31e2014-01-14 20:52:01 +01001291 fail("Checksum mismatch!\nExpected: {}\nComputed: {}\n"
1292 "Suggested fix: remove all generated code including "
Larry Hastingsbebf7352014-01-17 17:47:17 -08001293 "the end marker,\n"
1294 "or use the '-f' option."
Antoine Pitroucc1d31e2014-01-14 20:52:01 +01001295 .format(checksum, computed))
Larry Hastings31826802013-10-19 00:09:25 -07001296 else:
1297 # put back output
Larry Hastingseb31e9d2014-01-06 11:10:08 -08001298 output_lines = output.splitlines(keepends=True)
1299 self.line_number -= len(output_lines)
1300 self.input.extend(reversed(output_lines))
Larry Hastings31826802013-10-19 00:09:25 -07001301 output = None
1302
1303 return Block(input_output(), dsl_name, output=output)
1304
1305
1306class BlockPrinter:
1307
1308 def __init__(self, language, f=None):
1309 self.language = language
1310 self.f = f or io.StringIO()
1311
1312 def print_block(self, block):
1313 input = block.input
1314 output = block.output
1315 dsl_name = block.dsl_name
1316 write = self.f.write
1317
Larry Hastings31826802013-10-19 00:09:25 -07001318 assert not ((dsl_name == None) ^ (output == None)), "you must specify dsl_name and output together, dsl_name " + repr(dsl_name)
1319
1320 if not dsl_name:
1321 write(input)
1322 return
1323
1324 write(self.language.start_line.format(dsl_name=dsl_name))
1325 write("\n")
1326
1327 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1328 if not body_prefix:
1329 write(input)
1330 else:
1331 for line in input.split('\n'):
1332 write(body_prefix)
1333 write(line)
1334 write("\n")
1335
1336 write(self.language.stop_line.format(dsl_name=dsl_name))
1337 write("\n")
1338
Larry Hastingsbebf7352014-01-17 17:47:17 -08001339 output = ''.join(block.output)
Larry Hastings31826802013-10-19 00:09:25 -07001340 if output:
Larry Hastings31826802013-10-19 00:09:25 -07001341 if not output.endswith('\n'):
Larry Hastingsbebf7352014-01-17 17:47:17 -08001342 output += '\n'
1343 write(output)
Larry Hastings31826802013-10-19 00:09:25 -07001344
1345 write(self.language.checksum_line.format(dsl_name=dsl_name, checksum=compute_checksum(output)))
1346 write("\n")
1347
Larry Hastingsbebf7352014-01-17 17:47:17 -08001348 def write(self, text):
1349 self.f.write(text)
1350
1351
1352class Destination:
1353 def __init__(self, name, type, clinic, *args):
1354 self.name = name
1355 self.type = type
1356 self.clinic = clinic
1357 valid_types = ('buffer', 'file', 'suppress', 'two-pass')
1358 if type not in valid_types:
1359 fail("Invalid destination type " + repr(type) + " for " + name + " , must be " + ', '.join(valid_types))
1360 extra_arguments = 1 if type == "file" else 0
1361 if len(args) < extra_arguments:
1362 fail("Not enough arguments for destination " + name + " new " + type)
1363 if len(args) > extra_arguments:
1364 fail("Too many arguments for destination " + name + " new " + type)
1365 if type =='file':
1366 d = {}
Larry Hastingsc2047262014-01-25 20:43:29 -08001367 filename = clinic.filename
1368 d['path'] = filename
1369 dirname, basename = os.path.split(filename)
1370 if not dirname:
1371 dirname = '.'
1372 d['dirname'] = dirname
1373 d['basename'] = basename
1374 d['basename_root'], d['basename_extension'] = os.path.splitext(filename)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001375 self.filename = args[0].format_map(d)
1376 if type == 'two-pass':
1377 self.id = None
1378
1379 self.text, self.append, self._dump = _text_accumulator()
1380
1381 def __repr__(self):
1382 if self.type == 'file':
1383 file_repr = " " + repr(self.filename)
1384 else:
1385 file_repr = ''
1386 return "".join(("<Destination ", self.name, " ", self.type, file_repr, ">"))
1387
1388 def clear(self):
1389 if self.type != 'buffer':
1390 fail("Can't clear destination" + self.name + " , it's not of type buffer")
1391 self.text.clear()
1392
1393 def dump(self):
1394 if self.type == 'two-pass':
1395 if self.id is None:
1396 self.id = str(uuid.uuid4())
1397 return self.id
1398 fail("You can only dump a two-pass buffer exactly once!")
1399 return self._dump()
1400
Larry Hastings31826802013-10-19 00:09:25 -07001401
1402# maps strings to Language objects.
1403# "languages" maps the name of the language ("C", "Python").
1404# "extensions" maps the file extension ("c", "py").
1405languages = { 'C': CLanguage, 'Python': PythonLanguage }
Larry Hastings6d2ea212014-01-05 02:50:45 -08001406extensions = { name: CLanguage for name in "c cc cpp cxx h hh hpp hxx".split() }
1407extensions['py'] = PythonLanguage
Larry Hastings31826802013-10-19 00:09:25 -07001408
1409
1410# maps strings to callables.
1411# these callables must be of the form:
1412# def foo(name, default, *, ...)
1413# The callable may have any number of keyword-only parameters.
1414# The callable must return a CConverter object.
1415# The callable should not call builtins.print.
1416converters = {}
1417
1418# maps strings to callables.
1419# these callables follow the same rules as those for "converters" above.
1420# note however that they will never be called with keyword-only parameters.
1421legacy_converters = {}
1422
1423
1424# maps strings to callables.
1425# these callables must be of the form:
1426# def foo(*, ...)
1427# The callable may have any number of keyword-only parameters.
1428# The callable must return a CConverter object.
1429# The callable should not call builtins.print.
1430return_converters = {}
1431
1432class Clinic:
Larry Hastingsbebf7352014-01-17 17:47:17 -08001433
1434 presets_text = """
1435preset original
1436everything block
1437docstring_prototype suppress
1438parser_prototype suppress
1439
1440preset file
1441everything file
1442docstring_prototype suppress
1443parser_prototype suppress
1444impl_definition block
1445
1446preset buffer
1447everything buffer
1448docstring_prototype suppress
1449impl_prototype suppress
1450parser_prototype suppress
1451impl_definition block
1452
1453preset partial-buffer
1454everything buffer
1455docstring_prototype block
1456impl_prototype suppress
1457methoddef_define block
1458parser_prototype block
1459impl_definition block
1460
1461preset two-pass
1462everything buffer
1463docstring_prototype two-pass
1464impl_prototype suppress
1465methoddef_define two-pass
1466parser_prototype two-pass
1467impl_definition block
1468
1469"""
1470
Larry Hastings31826802013-10-19 00:09:25 -07001471 def __init__(self, language, printer=None, *, verify=True, filename=None):
1472 # maps strings to Parser objects.
1473 # (instantiated from the "parsers" global.)
1474 self.parsers = {}
1475 self.language = language
Larry Hastingsbebf7352014-01-17 17:47:17 -08001476 if printer:
1477 fail("Custom printers are broken right now")
Larry Hastings31826802013-10-19 00:09:25 -07001478 self.printer = printer or BlockPrinter(language)
1479 self.verify = verify
1480 self.filename = filename
1481 self.modules = collections.OrderedDict()
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001482 self.classes = collections.OrderedDict()
Larry Hastings2a727912014-01-16 11:32:01 -08001483 self.functions = []
Larry Hastings31826802013-10-19 00:09:25 -07001484
Larry Hastingsbebf7352014-01-17 17:47:17 -08001485 self.line_prefix = self.line_suffix = ''
1486
1487 self.destinations = {}
1488 self.add_destination("block", "buffer")
1489 self.add_destination("suppress", "suppress")
1490 self.add_destination("buffer", "buffer")
1491 self.add_destination("two-pass", "two-pass")
1492 if filename:
Larry Hastingsc2047262014-01-25 20:43:29 -08001493 self.add_destination("file", "file", "{dirname}/clinic/{basename}.h")
Larry Hastingsbebf7352014-01-17 17:47:17 -08001494
1495 d = self.destinations.get
1496 self.field_destinations = collections.OrderedDict((
1497 ('docstring_prototype', d('suppress')),
1498 ('docstring_definition', d('block')),
1499 ('methoddef_define', d('block')),
1500 ('impl_prototype', d('block')),
1501 ('parser_prototype', d('suppress')),
1502 ('parser_definition', d('block')),
1503 ('impl_definition', d('block')),
1504 ))
1505
1506 self.field_destinations_stack = []
1507
1508 self.presets = {}
1509 preset = None
1510 for line in self.presets_text.strip().split('\n'):
1511 line = line.strip()
1512 if not line:
1513 continue
1514 name, value = line.split()
1515 if name == 'preset':
1516 self.presets[value] = preset = collections.OrderedDict()
1517 continue
1518
1519 destination = self.get_destination(value)
1520
1521 if name == 'everything':
1522 for name in self.field_destinations:
1523 preset[name] = destination
1524 continue
1525
1526 assert name in self.field_destinations
1527 preset[name] = destination
1528
Larry Hastings31826802013-10-19 00:09:25 -07001529 global clinic
1530 clinic = self
1531
Larry Hastingsbebf7352014-01-17 17:47:17 -08001532 def get_destination(self, name, default=unspecified):
1533 d = self.destinations.get(name)
1534 if not d:
1535 if default is not unspecified:
1536 return default
1537 fail("Destination does not exist: " + repr(name))
1538 return d
1539
1540 def add_destination(self, name, type, *args):
1541 if name in self.destinations:
1542 fail("Destination already exists: " + repr(name))
1543 self.destinations[name] = Destination(name, type, self, *args)
1544
Larry Hastings31826802013-10-19 00:09:25 -07001545 def parse(self, input):
1546 printer = self.printer
1547 self.block_parser = BlockParser(input, self.language, verify=self.verify)
1548 for block in self.block_parser:
1549 dsl_name = block.dsl_name
1550 if dsl_name:
1551 if dsl_name not in self.parsers:
1552 assert dsl_name in parsers, "No parser to handle {!r} block.".format(dsl_name)
1553 self.parsers[dsl_name] = parsers[dsl_name](self)
1554 parser = self.parsers[dsl_name]
Georg Brandlaabebde2014-01-16 06:53:54 +01001555 try:
1556 parser.parse(block)
1557 except Exception:
1558 fail('Exception raised during parsing:\n' +
1559 traceback.format_exc().rstrip())
Larry Hastings31826802013-10-19 00:09:25 -07001560 printer.print_block(block)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001561
1562 second_pass_replacements = {}
1563
1564 for name, destination in self.destinations.items():
1565 if destination.type == 'suppress':
1566 continue
1567 output = destination._dump()
1568
1569 if destination.type == 'two-pass':
1570 if destination.id:
1571 second_pass_replacements[destination.id] = output
1572 elif output:
1573 fail("Two-pass buffer " + repr(name) + " not empty at end of file!")
1574 continue
1575
1576 if output:
1577
1578 block = Block("", dsl_name="clinic", output=output)
1579
1580 if destination.type == 'buffer':
1581 block.input = "dump " + name + "\n"
1582 warn("Destination buffer " + repr(name) + " not empty at end of file, emptying.")
1583 printer.write("\n")
1584 printer.print_block(block)
1585 continue
1586
1587 if destination.type == 'file':
1588 try:
Larry Hastingsc2047262014-01-25 20:43:29 -08001589 dirname = os.path.dirname(destination.filename)
1590 try:
1591 os.makedirs(dirname)
1592 except FileExistsError:
1593 if not os.path.isdir(dirname):
1594 fail("Can't write to destination {}, "
1595 "can't make directory {}!".format(
1596 destination.filename, dirname))
Larry Hastingsbebf7352014-01-17 17:47:17 -08001597 with open(destination.filename, "rt") as f:
1598 parser_2 = BlockParser(f.read(), language=self.language)
1599 blocks = list(parser_2)
1600 if (len(blocks) != 1) or (blocks[0].input != 'preserve\n'):
1601 fail("Modified destination file " + repr(destination.filename) + ", not overwriting!")
1602 except FileNotFoundError:
1603 pass
1604
1605 block.input = 'preserve\n'
1606 printer_2 = BlockPrinter(self.language)
1607 printer_2.print_block(block)
1608 with open(destination.filename, "wt") as f:
1609 f.write(printer_2.f.getvalue())
1610 continue
1611 text = printer.f.getvalue()
1612
1613 if second_pass_replacements:
1614 printer_2 = BlockPrinter(self.language)
1615 parser_2 = BlockParser(text, self.language)
1616 changed = False
1617 for block in parser_2:
1618 if block.dsl_name:
1619 for id, replacement in second_pass_replacements.items():
1620 if id in block.output:
1621 changed = True
1622 block.output = block.output.replace(id, replacement)
1623 printer_2.print_block(block)
1624 if changed:
1625 text = printer_2.f.getvalue()
1626
1627 return text
1628
Larry Hastings31826802013-10-19 00:09:25 -07001629
1630 def _module_and_class(self, fields):
1631 """
1632 fields should be an iterable of field names.
1633 returns a tuple of (module, class).
1634 the module object could actually be self (a clinic object).
1635 this function is only ever used to find the parent of where
1636 a new class/module should go.
1637 """
1638 in_classes = False
1639 parent = module = self
1640 cls = None
1641 so_far = []
1642
1643 for field in fields:
1644 so_far.append(field)
1645 if not in_classes:
1646 child = parent.modules.get(field)
1647 if child:
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001648 parent = module = child
Larry Hastings31826802013-10-19 00:09:25 -07001649 continue
1650 in_classes = True
1651 if not hasattr(parent, 'classes'):
1652 return module, cls
1653 child = parent.classes.get(field)
1654 if not child:
1655 fail('Parent class or module ' + '.'.join(so_far) + " does not exist.")
1656 cls = parent = child
1657
1658 return module, cls
1659
1660
1661def parse_file(filename, *, verify=True, output=None, encoding='utf-8'):
1662 extension = os.path.splitext(filename)[1][1:]
1663 if not extension:
1664 fail("Can't extract file type for file " + repr(filename))
1665
1666 try:
1667 language = extensions[extension]()
1668 except KeyError:
1669 fail("Can't identify file type for file " + repr(filename))
1670
1671 clinic = Clinic(language, verify=verify, filename=filename)
1672
1673 with open(filename, 'r', encoding=encoding) as f:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001674 raw = f.read()
1675
1676 cooked = clinic.parse(raw)
1677 if cooked == raw:
1678 return
Larry Hastings31826802013-10-19 00:09:25 -07001679
1680 directory = os.path.dirname(filename) or '.'
1681
1682 with tempfile.TemporaryDirectory(prefix="clinic", dir=directory) as tmpdir:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001683 bytes = cooked.encode(encoding)
Larry Hastings31826802013-10-19 00:09:25 -07001684 tmpfilename = os.path.join(tmpdir, os.path.basename(filename))
1685 with open(tmpfilename, "wb") as f:
1686 f.write(bytes)
1687 os.replace(tmpfilename, output or filename)
1688
1689
1690def compute_checksum(input):
1691 input = input or ''
1692 return hashlib.sha1(input.encode('utf-8')).hexdigest()
1693
1694
1695
1696
1697class PythonParser:
1698 def __init__(self, clinic):
1699 pass
1700
1701 def parse(self, block):
1702 s = io.StringIO()
1703 with OverrideStdioWith(s):
1704 exec(block.input)
1705 block.output = s.getvalue()
1706
1707
1708class Module:
1709 def __init__(self, name, module=None):
1710 self.name = name
1711 self.module = self.parent = module
1712
1713 self.modules = collections.OrderedDict()
1714 self.classes = collections.OrderedDict()
1715 self.functions = []
1716
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001717 def __repr__(self):
1718 return "<clinic.Module " + repr(self.name) + " at " + str(id(self)) + ">"
1719
Larry Hastings31826802013-10-19 00:09:25 -07001720class Class:
Larry Hastingsc2047262014-01-25 20:43:29 -08001721 def __init__(self, name, module=None, cls=None, typedef=None, type_object=None):
Larry Hastings31826802013-10-19 00:09:25 -07001722 self.name = name
1723 self.module = module
1724 self.cls = cls
Larry Hastingsc2047262014-01-25 20:43:29 -08001725 self.typedef = typedef
1726 self.type_object = type_object
Larry Hastings31826802013-10-19 00:09:25 -07001727 self.parent = cls or module
1728
1729 self.classes = collections.OrderedDict()
1730 self.functions = []
1731
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001732 def __repr__(self):
1733 return "<clinic.Class " + repr(self.name) + " at " + str(id(self)) + ">"
1734
Larry Hastings8666e652014-01-12 14:12:59 -08001735unsupported_special_methods = set("""
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001736
Larry Hastings8666e652014-01-12 14:12:59 -08001737__abs__
1738__add__
1739__and__
1740__bytes__
1741__call__
1742__complex__
1743__delitem__
1744__divmod__
1745__eq__
1746__float__
1747__floordiv__
1748__ge__
1749__getattr__
1750__getattribute__
1751__getitem__
1752__gt__
1753__hash__
1754__iadd__
1755__iand__
1756__idivmod__
1757__ifloordiv__
1758__ilshift__
1759__imod__
1760__imul__
1761__index__
1762__int__
1763__invert__
1764__ior__
1765__ipow__
1766__irshift__
1767__isub__
1768__iter__
1769__itruediv__
1770__ixor__
1771__le__
1772__len__
1773__lshift__
1774__lt__
1775__mod__
1776__mul__
1777__neg__
1778__new__
1779__next__
1780__or__
1781__pos__
1782__pow__
1783__radd__
1784__rand__
1785__rdivmod__
1786__repr__
1787__rfloordiv__
1788__rlshift__
1789__rmod__
1790__rmul__
1791__ror__
1792__round__
1793__rpow__
1794__rrshift__
1795__rshift__
1796__rsub__
1797__rtruediv__
1798__rxor__
1799__setattr__
1800__setitem__
1801__str__
1802__sub__
1803__truediv__
1804__xor__
1805
1806""".strip().split())
1807
1808
Larry Hastings5c661892014-01-24 06:17:25 -08001809INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW = """
1810INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW
1811""".replace(",", "").strip().split()
Larry Hastings31826802013-10-19 00:09:25 -07001812
1813class Function:
1814 """
1815 Mutable duck type for inspect.Function.
1816
1817 docstring - a str containing
1818 * embedded line breaks
1819 * text outdented to the left margin
1820 * no trailing whitespace.
1821 It will always be true that
1822 (not docstring) or ((not docstring[0].isspace()) and (docstring.rstrip() == docstring))
1823 """
1824
1825 def __init__(self, parameters=None, *, name,
1826 module, cls=None, c_basename=None,
1827 full_name=None,
1828 return_converter, return_annotation=_empty,
1829 docstring=None, kind=CALLABLE, coexist=False):
1830 self.parameters = parameters or collections.OrderedDict()
1831 self.return_annotation = return_annotation
1832 self.name = name
1833 self.full_name = full_name
1834 self.module = module
1835 self.cls = cls
1836 self.parent = cls or module
1837 self.c_basename = c_basename
1838 self.return_converter = return_converter
1839 self.docstring = docstring or ''
1840 self.kind = kind
1841 self.coexist = coexist
Larry Hastingsebdcb502013-11-23 14:54:00 -08001842 self.self_converter = None
1843
1844 @property
1845 def methoddef_flags(self):
Larry Hastings8666e652014-01-12 14:12:59 -08001846 if self.kind in (METHOD_INIT, METHOD_NEW):
1847 return None
Larry Hastingsebdcb502013-11-23 14:54:00 -08001848 flags = []
1849 if self.kind == CLASS_METHOD:
1850 flags.append('METH_CLASS')
1851 elif self.kind == STATIC_METHOD:
1852 flags.append('METH_STATIC')
1853 else:
1854 assert self.kind == CALLABLE, "unknown kind: " + repr(self.kind)
1855 if self.coexist:
1856 flags.append('METH_COEXIST')
1857 return '|'.join(flags)
Larry Hastings31826802013-10-19 00:09:25 -07001858
1859 def __repr__(self):
1860 return '<clinic.Function ' + self.name + '>'
1861
1862
1863class Parameter:
1864 """
1865 Mutable duck type of inspect.Parameter.
1866 """
1867
1868 def __init__(self, name, kind, *, default=_empty,
1869 function, converter, annotation=_empty,
1870 docstring=None, group=0):
1871 self.name = name
1872 self.kind = kind
1873 self.default = default
1874 self.function = function
1875 self.converter = converter
1876 self.annotation = annotation
1877 self.docstring = docstring or ''
1878 self.group = group
1879
1880 def __repr__(self):
1881 return '<clinic.Parameter ' + self.name + '>'
1882
1883 def is_keyword_only(self):
1884 return self.kind == inspect.Parameter.KEYWORD_ONLY
1885
Larry Hastings31826802013-10-19 00:09:25 -07001886
Larry Hastings31826802013-10-19 00:09:25 -07001887
1888def add_c_converter(f, name=None):
1889 if not name:
1890 name = f.__name__
1891 if not name.endswith('_converter'):
1892 return f
1893 name = name[:-len('_converter')]
1894 converters[name] = f
1895 return f
1896
1897def add_default_legacy_c_converter(cls):
1898 # automatically add converter for default format unit
1899 # (but without stomping on the existing one if it's already
1900 # set, in case you subclass)
1901 if ((cls.format_unit != 'O&') and
1902 (cls.format_unit not in legacy_converters)):
1903 legacy_converters[cls.format_unit] = cls
1904 return cls
1905
1906def add_legacy_c_converter(format_unit, **kwargs):
1907 """
1908 Adds a legacy converter.
1909 """
1910 def closure(f):
1911 if not kwargs:
1912 added_f = f
1913 else:
1914 added_f = functools.partial(f, **kwargs)
1915 legacy_converters[format_unit] = added_f
1916 return f
1917 return closure
1918
1919class CConverterAutoRegister(type):
1920 def __init__(cls, name, bases, classdict):
1921 add_c_converter(cls)
1922 add_default_legacy_c_converter(cls)
1923
1924class CConverter(metaclass=CConverterAutoRegister):
1925 """
1926 For the init function, self, name, function, and default
1927 must be keyword-or-positional parameters. All other
Larry Hastings2a727912014-01-16 11:32:01 -08001928 parameters must be keyword-only.
Larry Hastings31826802013-10-19 00:09:25 -07001929 """
1930
Larry Hastings78cf85c2014-01-04 12:44:57 -08001931 # The C type to use for this variable.
1932 # 'type' should be a Python string specifying the type, e.g. "int".
1933 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07001934 type = None
Larry Hastings31826802013-10-19 00:09:25 -07001935
1936 # The Python default value for this parameter, as a Python value.
Larry Hastings78cf85c2014-01-04 12:44:57 -08001937 # Or the magic value "unspecified" if there is no default.
Larry Hastings2a727912014-01-16 11:32:01 -08001938 # Or the magic value "unknown" if this value is a cannot be evaluated
1939 # at Argument-Clinic-preprocessing time (but is presumed to be valid
1940 # at runtime).
Larry Hastings31826802013-10-19 00:09:25 -07001941 default = unspecified
1942
Larry Hastings4a55fc52014-01-12 11:09:57 -08001943 # If not None, default must be isinstance() of this type.
1944 # (You can also specify a tuple of types.)
1945 default_type = None
1946
Larry Hastings31826802013-10-19 00:09:25 -07001947 # "default" converted into a C value, as a string.
1948 # Or None if there is no default.
1949 c_default = None
1950
Larry Hastings2a727912014-01-16 11:32:01 -08001951 # "default" converted into a Python value, as a string.
1952 # Or None if there is no default.
1953 py_default = None
1954
Larry Hastingsabc716b2013-11-20 09:13:52 -08001955 # The default value used to initialize the C variable when
1956 # there is no default, but not specifying a default may
1957 # result in an "uninitialized variable" warning. This can
1958 # easily happen when using option groups--although
1959 # properly-written code won't actually use the variable,
1960 # the variable does get passed in to the _impl. (Ah, if
1961 # only dataflow analysis could inline the static function!)
1962 #
1963 # This value is specified as a string.
1964 # Every non-abstract subclass should supply a valid value.
1965 c_ignored_default = 'NULL'
1966
Larry Hastings31826802013-10-19 00:09:25 -07001967 # The C converter *function* to be used, if any.
1968 # (If this is not None, format_unit must be 'O&'.)
1969 converter = None
Larry Hastingsebdcb502013-11-23 14:54:00 -08001970
Larry Hastings78cf85c2014-01-04 12:44:57 -08001971 # Should Argument Clinic add a '&' before the name of
1972 # the variable when passing it into the _impl function?
Larry Hastings31826802013-10-19 00:09:25 -07001973 impl_by_reference = False
Larry Hastings78cf85c2014-01-04 12:44:57 -08001974
1975 # Should Argument Clinic add a '&' before the name of
1976 # the variable when passing it into PyArg_ParseTuple (AndKeywords)?
Larry Hastings31826802013-10-19 00:09:25 -07001977 parse_by_reference = True
Larry Hastings78cf85c2014-01-04 12:44:57 -08001978
1979 #############################################################
1980 #############################################################
1981 ## You shouldn't need to read anything below this point to ##
1982 ## write your own converter functions. ##
1983 #############################################################
1984 #############################################################
1985
1986 # The "format unit" to specify for this variable when
1987 # parsing arguments using PyArg_ParseTuple (AndKeywords).
1988 # Custom converters should always use the default value of 'O&'.
1989 format_unit = 'O&'
1990
1991 # What encoding do we want for this variable? Only used
1992 # by format units starting with 'e'.
1993 encoding = None
1994
Larry Hastings77561cc2014-01-07 12:13:13 -08001995 # Should this object be required to be a subclass of a specific type?
1996 # If not None, should be a string representing a pointer to a
1997 # PyTypeObject (e.g. "&PyUnicode_Type").
1998 # Only used by the 'O!' format unit (and the "object" converter).
1999 subclass_of = None
2000
Larry Hastings78cf85c2014-01-04 12:44:57 -08002001 # Do we want an adjacent '_length' variable for this variable?
2002 # Only used by format units ending with '#'.
Larry Hastings31826802013-10-19 00:09:25 -07002003 length = False
2004
Larry Hastings5c661892014-01-24 06:17:25 -08002005 # Should we show this parameter in the generated
2006 # __text_signature__? This is *almost* always True.
Larry Hastingsc2047262014-01-25 20:43:29 -08002007 # (It's only False for __new__, __init__, and METH_STATIC functions.)
Larry Hastings5c661892014-01-24 06:17:25 -08002008 show_in_signature = True
2009
2010 # Overrides the name used in a text signature.
2011 # The name used for a "self" parameter must be one of
2012 # self, type, or module; however users can set their own.
2013 # This lets the self_converter overrule the user-settable
2014 # name, *just* for the text signature.
2015 # Only set by self_converter.
2016 signature_name = None
2017
2018 # keep in sync with self_converter.__init__!
Larry Hastings2a727912014-01-16 11:32:01 -08002019 def __init__(self, name, function, default=unspecified, *, c_default=None, py_default=None, annotation=unspecified, **kwargs):
Larry Hastings31826802013-10-19 00:09:25 -07002020 self.function = function
2021 self.name = name
2022
2023 if default is not unspecified:
Larry Hastings2a727912014-01-16 11:32:01 -08002024 if self.default_type and not isinstance(default, (self.default_type, Unknown)):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002025 if isinstance(self.default_type, type):
2026 types_str = self.default_type.__name__
2027 else:
2028 types_str = ', '.join((cls.__name__ for cls in self.default_type))
2029 fail("{}: default value {!r} for field {} is not of type {}".format(
2030 self.__class__.__name__, default, name, types_str))
Larry Hastings31826802013-10-19 00:09:25 -07002031 self.default = default
Larry Hastings2a727912014-01-16 11:32:01 -08002032
Larry Hastingsb4705752014-01-18 21:54:15 -08002033 if c_default:
2034 self.c_default = c_default
2035 if py_default:
2036 self.py_default = py_default
Larry Hastings2a727912014-01-16 11:32:01 -08002037
Larry Hastings31826802013-10-19 00:09:25 -07002038 if annotation != unspecified:
2039 fail("The 'annotation' parameter is not currently permitted.")
Larry Hastings31826802013-10-19 00:09:25 -07002040 self.converter_init(**kwargs)
2041
2042 def converter_init(self):
2043 pass
2044
2045 def is_optional(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002046 return (self.default is not unspecified)
Larry Hastings31826802013-10-19 00:09:25 -07002047
Larry Hastings5c661892014-01-24 06:17:25 -08002048 def _render_self(self, parameter, data):
2049 self.parameter = parameter
2050 original_name = self.name
2051 name = ensure_legal_c_identifier(original_name)
2052
2053 # impl_arguments
2054 s = ("&" if self.impl_by_reference else "") + name
2055 data.impl_arguments.append(s)
2056 if self.length:
2057 data.impl_arguments.append(self.length_name())
2058
2059 # impl_parameters
2060 data.impl_parameters.append(self.simple_declaration(by_reference=self.impl_by_reference))
2061 if self.length:
2062 data.impl_parameters.append("Py_ssize_clean_t " + self.length_name())
2063
2064 def _render_non_self(self, parameter, data):
Larry Hastingsabc716b2013-11-20 09:13:52 -08002065 self.parameter = parameter
Larry Hastings90261132014-01-07 12:21:08 -08002066 original_name = self.name
2067 name = ensure_legal_c_identifier(original_name)
Larry Hastings31826802013-10-19 00:09:25 -07002068
2069 # declarations
2070 d = self.declaration()
2071 data.declarations.append(d)
2072
2073 # initializers
2074 initializers = self.initialize()
2075 if initializers:
2076 data.initializers.append('/* initializers for ' + name + ' */\n' + initializers.rstrip())
2077
Larry Hastingsc2047262014-01-25 20:43:29 -08002078 # modifications
2079 modifications = self.modify()
2080 if modifications:
2081 data.modifications.append('/* modifications for ' + name + ' */\n' + modifications.rstrip())
2082
Larry Hastings31826802013-10-19 00:09:25 -07002083 # keywords
Larry Hastings90261132014-01-07 12:21:08 -08002084 data.keywords.append(original_name)
Larry Hastings31826802013-10-19 00:09:25 -07002085
2086 # format_units
2087 if self.is_optional() and '|' not in data.format_units:
2088 data.format_units.append('|')
2089 if parameter.is_keyword_only() and '$' not in data.format_units:
2090 data.format_units.append('$')
2091 data.format_units.append(self.format_unit)
2092
2093 # parse_arguments
2094 self.parse_argument(data.parse_arguments)
2095
Larry Hastings31826802013-10-19 00:09:25 -07002096 # cleanup
2097 cleanup = self.cleanup()
2098 if cleanup:
2099 data.cleanup.append('/* Cleanup for ' + name + ' */\n' + cleanup.rstrip() + "\n")
2100
Larry Hastings5c661892014-01-24 06:17:25 -08002101 def render(self, parameter, data):
2102 """
2103 parameter is a clinic.Parameter instance.
2104 data is a CRenderData instance.
2105 """
2106 self._render_self(parameter, data)
2107 self._render_non_self(parameter, data)
2108
Larry Hastingsebdcb502013-11-23 14:54:00 -08002109 def length_name(self):
2110 """Computes the name of the associated "length" variable."""
2111 if not self.length:
2112 return None
2113 return ensure_legal_c_identifier(self.name) + "_length"
2114
Larry Hastings31826802013-10-19 00:09:25 -07002115 # Why is this one broken out separately?
2116 # For "positional-only" function parsing,
2117 # which generates a bunch of PyArg_ParseTuple calls.
2118 def parse_argument(self, list):
2119 assert not (self.converter and self.encoding)
2120 if self.format_unit == 'O&':
2121 assert self.converter
2122 list.append(self.converter)
2123
2124 if self.encoding:
Larry Hastings77561cc2014-01-07 12:13:13 -08002125 list.append(c_repr(self.encoding))
2126 elif self.subclass_of:
2127 list.append(self.subclass_of)
Larry Hastings31826802013-10-19 00:09:25 -07002128
Larry Hastingsebdcb502013-11-23 14:54:00 -08002129 legal_name = ensure_legal_c_identifier(self.name)
2130 s = ("&" if self.parse_by_reference else "") + legal_name
Larry Hastings31826802013-10-19 00:09:25 -07002131 list.append(s)
2132
Larry Hastingsebdcb502013-11-23 14:54:00 -08002133 if self.length:
2134 list.append("&" + self.length_name())
2135
Larry Hastings31826802013-10-19 00:09:25 -07002136 #
2137 # All the functions after here are intended as extension points.
2138 #
2139
2140 def simple_declaration(self, by_reference=False):
2141 """
2142 Computes the basic declaration of the variable.
2143 Used in computing the prototype declaration and the
2144 variable declaration.
2145 """
2146 prototype = [self.type]
2147 if by_reference or not self.type.endswith('*'):
2148 prototype.append(" ")
2149 if by_reference:
2150 prototype.append('*')
Larry Hastingsdfcd4672013-10-27 02:49:39 -07002151 prototype.append(ensure_legal_c_identifier(self.name))
Larry Hastings31826802013-10-19 00:09:25 -07002152 return "".join(prototype)
2153
2154 def declaration(self):
2155 """
2156 The C statement to declare this variable.
2157 """
2158 declaration = [self.simple_declaration()]
Larry Hastingsabc716b2013-11-20 09:13:52 -08002159 default = self.c_default
2160 if not default and self.parameter.group:
2161 default = self.c_ignored_default
2162 if default:
Larry Hastings31826802013-10-19 00:09:25 -07002163 declaration.append(" = ")
Larry Hastingsabc716b2013-11-20 09:13:52 -08002164 declaration.append(default)
Larry Hastings31826802013-10-19 00:09:25 -07002165 declaration.append(";")
Larry Hastingsebdcb502013-11-23 14:54:00 -08002166 if self.length:
2167 declaration.append('\nPy_ssize_clean_t ')
2168 declaration.append(self.length_name())
2169 declaration.append(';')
Larry Hastings3f144c22014-01-06 10:34:00 -08002170 s = "".join(declaration)
2171 # double up curly-braces, this string will be used
2172 # as part of a format_map() template later
2173 s = s.replace("{", "{{")
2174 s = s.replace("}", "}}")
2175 return s
Larry Hastings31826802013-10-19 00:09:25 -07002176
2177 def initialize(self):
2178 """
2179 The C statements required to set up this variable before parsing.
2180 Returns a string containing this code indented at column 0.
2181 If no initialization is necessary, returns an empty string.
2182 """
2183 return ""
2184
Larry Hastingsc2047262014-01-25 20:43:29 -08002185 def modify(self):
2186 """
2187 The C statements required to modify this variable after parsing.
2188 Returns a string containing this code indented at column 0.
2189 If no initialization is necessary, returns an empty string.
2190 """
2191 return ""
2192
Larry Hastings31826802013-10-19 00:09:25 -07002193 def cleanup(self):
2194 """
2195 The C statements required to clean up after this variable.
2196 Returns a string containing this code indented at column 0.
2197 If no cleanup is necessary, returns an empty string.
2198 """
2199 return ""
2200
2201
2202class bool_converter(CConverter):
2203 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002204 default_type = bool
Larry Hastings31826802013-10-19 00:09:25 -07002205 format_unit = 'p'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002206 c_ignored_default = '0'
Larry Hastings31826802013-10-19 00:09:25 -07002207
2208 def converter_init(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002209 if self.default is not unspecified:
2210 self.default = bool(self.default)
2211 self.c_default = str(int(self.default))
Larry Hastings31826802013-10-19 00:09:25 -07002212
2213class char_converter(CConverter):
2214 type = 'char'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002215 default_type = str
Larry Hastings31826802013-10-19 00:09:25 -07002216 format_unit = 'c'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002217 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002218
Larry Hastings4a55fc52014-01-12 11:09:57 -08002219 def converter_init(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002220 if isinstance(self.default, str) and (len(self.default) != 1):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002221 fail("char_converter: illegal default value " + repr(self.default))
2222
2223
Larry Hastings31826802013-10-19 00:09:25 -07002224@add_legacy_c_converter('B', bitwise=True)
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002225class unsigned_char_converter(CConverter):
Serhiy Storchaka49776ef2014-01-19 00:38:36 +02002226 type = 'unsigned char'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002227 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002228 format_unit = 'b'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002229 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002230
2231 def converter_init(self, *, bitwise=False):
2232 if bitwise:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002233 self.format_unit = 'B'
Larry Hastings31826802013-10-19 00:09:25 -07002234
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002235class byte_converter(unsigned_char_converter): pass
2236
Larry Hastings31826802013-10-19 00:09:25 -07002237class short_converter(CConverter):
2238 type = 'short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002239 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002240 format_unit = 'h'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002241 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002242
2243class unsigned_short_converter(CConverter):
2244 type = 'unsigned short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002245 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002246 format_unit = 'H'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002247 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002248
2249 def converter_init(self, *, bitwise=False):
2250 if not bitwise:
2251 fail("Unsigned shorts must be bitwise (for now).")
2252
Larry Hastingsebdcb502013-11-23 14:54:00 -08002253@add_legacy_c_converter('C', types='str')
Larry Hastings31826802013-10-19 00:09:25 -07002254class int_converter(CConverter):
2255 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002256 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002257 format_unit = 'i'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002258 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002259
Larry Hastingsebdcb502013-11-23 14:54:00 -08002260 def converter_init(self, *, types='int'):
2261 if types == 'str':
2262 self.format_unit = 'C'
2263 elif types != 'int':
2264 fail("int_converter: illegal 'types' argument")
Larry Hastings31826802013-10-19 00:09:25 -07002265
2266class unsigned_int_converter(CConverter):
2267 type = 'unsigned int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002268 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002269 format_unit = 'I'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002270 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002271
2272 def converter_init(self, *, bitwise=False):
2273 if not bitwise:
2274 fail("Unsigned ints must be bitwise (for now).")
2275
2276class long_converter(CConverter):
2277 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002278 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002279 format_unit = 'l'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002280 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002281
2282class unsigned_long_converter(CConverter):
2283 type = 'unsigned long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002284 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002285 format_unit = 'k'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002286 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002287
2288 def converter_init(self, *, bitwise=False):
2289 if not bitwise:
2290 fail("Unsigned longs must be bitwise (for now).")
2291
2292class PY_LONG_LONG_converter(CConverter):
2293 type = 'PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002294 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002295 format_unit = 'L'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002296 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002297
2298class unsigned_PY_LONG_LONG_converter(CConverter):
2299 type = 'unsigned PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002300 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002301 format_unit = 'K'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002302 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002303
2304 def converter_init(self, *, bitwise=False):
2305 if not bitwise:
2306 fail("Unsigned PY_LONG_LONGs must be bitwise (for now).")
2307
2308class Py_ssize_t_converter(CConverter):
2309 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002310 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002311 format_unit = 'n'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002312 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002313
2314
2315class float_converter(CConverter):
2316 type = 'float'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002317 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002318 format_unit = 'f'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002319 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002320
2321class double_converter(CConverter):
2322 type = 'double'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002323 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002324 format_unit = 'd'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002325 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002326
2327
2328class Py_complex_converter(CConverter):
2329 type = 'Py_complex'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002330 default_type = complex
Larry Hastings31826802013-10-19 00:09:25 -07002331 format_unit = 'D'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002332 c_ignored_default = "{0.0, 0.0}"
Larry Hastings31826802013-10-19 00:09:25 -07002333
2334
2335class object_converter(CConverter):
2336 type = 'PyObject *'
2337 format_unit = 'O'
2338
Larry Hastings4a55fc52014-01-12 11:09:57 -08002339 def converter_init(self, *, converter=None, type=None, subclass_of=None):
2340 if converter:
2341 if subclass_of:
2342 fail("object: Cannot pass in both 'converter' and 'subclass_of'")
2343 self.format_unit = 'O&'
2344 self.converter = converter
2345 elif subclass_of:
Larry Hastings31826802013-10-19 00:09:25 -07002346 self.format_unit = 'O!'
Larry Hastings77561cc2014-01-07 12:13:13 -08002347 self.subclass_of = subclass_of
Larry Hastings4a55fc52014-01-12 11:09:57 -08002348
Larry Hastings77561cc2014-01-07 12:13:13 -08002349 if type is not None:
2350 self.type = type
Larry Hastings31826802013-10-19 00:09:25 -07002351
2352
Larry Hastingsebdcb502013-11-23 14:54:00 -08002353@add_legacy_c_converter('s#', length=True)
Larry Hastings2a727912014-01-16 11:32:01 -08002354@add_legacy_c_converter('y', types="bytes")
2355@add_legacy_c_converter('y#', types="bytes", length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002356@add_legacy_c_converter('z', nullable=True)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002357@add_legacy_c_converter('z#', nullable=True, length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002358class str_converter(CConverter):
2359 type = 'const char *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002360 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002361 format_unit = 's'
2362
Larry Hastingsebdcb502013-11-23 14:54:00 -08002363 def converter_init(self, *, encoding=None, types="str",
2364 length=False, nullable=False, zeroes=False):
2365
2366 types = set(types.strip().split())
2367 bytes_type = set(("bytes",))
2368 str_type = set(("str",))
2369 all_3_type = set(("bytearray",)) | bytes_type | str_type
2370 is_bytes = types == bytes_type
2371 is_str = types == str_type
2372 is_all_3 = types == all_3_type
2373
2374 self.length = bool(length)
2375 format_unit = None
2376
2377 if encoding:
2378 self.encoding = encoding
2379
2380 if is_str and not (length or zeroes or nullable):
2381 format_unit = 'es'
2382 elif is_all_3 and not (length or zeroes or nullable):
2383 format_unit = 'et'
2384 elif is_str and length and zeroes and not nullable:
2385 format_unit = 'es#'
2386 elif is_all_3 and length and not (nullable or zeroes):
2387 format_unit = 'et#'
2388
2389 if format_unit.endswith('#'):
Larry Hastings5c661892014-01-24 06:17:25 -08002390 fail("Sorry: code using format unit ", repr(format_unit), "probably doesn't work properly yet.\nGive Larry your test case and he'll it.")
Larry Hastingsebdcb502013-11-23 14:54:00 -08002391 # TODO set pointer to NULL
2392 # TODO add cleanup for buffer
2393 pass
2394
2395 else:
2396 if zeroes:
2397 fail("str_converter: illegal combination of arguments (zeroes is only legal with an encoding)")
2398
2399 if is_bytes and not (nullable or length):
2400 format_unit = 'y'
2401 elif is_bytes and length and not nullable:
2402 format_unit = 'y#'
2403 elif is_str and not (nullable or length):
2404 format_unit = 's'
2405 elif is_str and length and not nullable:
2406 format_unit = 's#'
2407 elif is_str and nullable and not length:
2408 format_unit = 'z'
2409 elif is_str and nullable and length:
2410 format_unit = 'z#'
2411
2412 if not format_unit:
2413 fail("str_converter: illegal combination of arguments")
2414 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002415
2416
2417class PyBytesObject_converter(CConverter):
2418 type = 'PyBytesObject *'
2419 format_unit = 'S'
2420
2421class PyByteArrayObject_converter(CConverter):
2422 type = 'PyByteArrayObject *'
2423 format_unit = 'Y'
2424
2425class unicode_converter(CConverter):
2426 type = 'PyObject *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002427 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002428 format_unit = 'U'
2429
Larry Hastingsebdcb502013-11-23 14:54:00 -08002430@add_legacy_c_converter('u#', length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002431@add_legacy_c_converter('Z', nullable=True)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002432@add_legacy_c_converter('Z#', nullable=True, length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002433class Py_UNICODE_converter(CConverter):
2434 type = 'Py_UNICODE *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002435 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002436 format_unit = 'u'
2437
Larry Hastingsebdcb502013-11-23 14:54:00 -08002438 def converter_init(self, *, nullable=False, length=False):
2439 format_unit = 'Z' if nullable else 'u'
2440 if length:
2441 format_unit += '#'
2442 self.length = True
2443 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002444
Larry Hastingsebdcb502013-11-23 14:54:00 -08002445#
2446# We define three string conventions for buffer types in the 'types' argument:
2447# 'buffer' : any object supporting the buffer interface
2448# 'rwbuffer': any object supporting the buffer interface, but must be writeable
2449# 'robuffer': any object supporting the buffer interface, but must not be writeable
2450#
2451@add_legacy_c_converter('s*', types='str bytes bytearray buffer')
2452@add_legacy_c_converter('z*', types='str bytes bytearray buffer', nullable=True)
2453@add_legacy_c_converter('w*', types='bytearray rwbuffer')
Larry Hastings31826802013-10-19 00:09:25 -07002454class Py_buffer_converter(CConverter):
2455 type = 'Py_buffer'
2456 format_unit = 'y*'
2457 impl_by_reference = True
Larry Hastings4a55fc52014-01-12 11:09:57 -08002458 c_ignored_default = "{NULL, NULL}"
Larry Hastings31826802013-10-19 00:09:25 -07002459
Larry Hastingsebdcb502013-11-23 14:54:00 -08002460 def converter_init(self, *, types='bytes bytearray buffer', nullable=False):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002461 if self.default not in (unspecified, None):
2462 fail("The only legal default value for Py_buffer is None.")
Larry Hastings3f144c22014-01-06 10:34:00 -08002463 self.c_default = self.c_ignored_default
Larry Hastingsebdcb502013-11-23 14:54:00 -08002464 types = set(types.strip().split())
2465 bytes_type = set(('bytes',))
2466 bytearray_type = set(('bytearray',))
2467 buffer_type = set(('buffer',))
2468 rwbuffer_type = set(('rwbuffer',))
2469 robuffer_type = set(('robuffer',))
2470 str_type = set(('str',))
2471 bytes_bytearray_buffer_type = bytes_type | bytearray_type | buffer_type
2472
2473 format_unit = None
2474 if types == (str_type | bytes_bytearray_buffer_type):
2475 format_unit = 's*' if not nullable else 'z*'
Larry Hastings31826802013-10-19 00:09:25 -07002476 else:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002477 if nullable:
2478 fail('Py_buffer_converter: illegal combination of arguments (nullable=True)')
2479 elif types == (bytes_bytearray_buffer_type):
2480 format_unit = 'y*'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002481 elif types == (bytearray_type | rwbuffer_type):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002482 format_unit = 'w*'
2483 if not format_unit:
2484 fail("Py_buffer_converter: illegal combination of arguments")
2485
2486 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002487
2488 def cleanup(self):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002489 name = ensure_legal_c_identifier(self.name)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002490 return "".join(["if (", name, ".obj)\n PyBuffer_Release(&", name, ");\n"])
Larry Hastingsebdcb502013-11-23 14:54:00 -08002491
2492
Larry Hastings5c661892014-01-24 06:17:25 -08002493def correct_name_for_self(f):
2494 if f.kind in (CALLABLE, METHOD_INIT):
2495 if f.cls:
2496 return "PyObject *", "self"
2497 return "PyModuleDef *", "module"
2498 if f.kind == STATIC_METHOD:
2499 return "void *", "null"
2500 if f.kind in (CLASS_METHOD, METHOD_NEW):
2501 return "PyTypeObject *", "type"
2502 raise RuntimeError("Unhandled type of function f: " + repr(f.kind))
2503
Larry Hastingsc2047262014-01-25 20:43:29 -08002504def required_type_for_self_for_parser(f):
2505 type, _ = correct_name_for_self(f)
2506 if f.kind in (METHOD_INIT, METHOD_NEW, STATIC_METHOD, CLASS_METHOD):
2507 return type
2508 return None
2509
Larry Hastings5c661892014-01-24 06:17:25 -08002510
Larry Hastingsebdcb502013-11-23 14:54:00 -08002511class self_converter(CConverter):
2512 """
2513 A special-case converter:
2514 this is the default converter used for "self".
2515 """
Larry Hastings5c661892014-01-24 06:17:25 -08002516 type = None
2517 format_unit = ''
2518
2519
Larry Hastings78cf85c2014-01-04 12:44:57 -08002520 def converter_init(self, *, type=None):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002521 f = self.function
Larry Hastings5c661892014-01-24 06:17:25 -08002522 default_type, default_name = correct_name_for_self(f)
2523 self.signature_name = default_name
2524 self.type = type or self.type or default_type
Larry Hastingsebdcb502013-11-23 14:54:00 -08002525
Larry Hastings5c661892014-01-24 06:17:25 -08002526 kind = self.function.kind
2527 new_or_init = kind in (METHOD_NEW, METHOD_INIT)
2528
2529 if (kind == STATIC_METHOD) or new_or_init:
2530 self.show_in_signature = False
2531
2532 # tp_new (METHOD_NEW) functions are of type newfunc:
2533 # typedef PyObject *(*newfunc)(struct _typeobject *, PyObject *, PyObject *);
2534 # PyTypeObject is a typedef for struct _typeobject.
2535 #
2536 # tp_init (METHOD_INIT) functions are of type initproc:
2537 # typedef int (*initproc)(PyObject *, PyObject *, PyObject *);
2538 #
2539 # All other functions generated by Argument Clinic are stored in
2540 # PyMethodDef structures, in the ml_meth slot, which is of type PyCFunction:
2541 # typedef PyObject *(*PyCFunction)(PyObject *, PyObject *);
2542 # However! We habitually cast these functions to PyCFunction,
2543 # since functions that accept keyword arguments don't fit this signature
2544 # but are stored there anyway. So strict type equality isn't important
2545 # for these functions.
2546 #
2547 # So:
2548 #
2549 # * The name of the first parameter to the impl and the parsing function will always
2550 # be self.name.
2551 #
2552 # * The type of the first parameter to the impl will always be of self.type.
2553 #
2554 # * If the function is neither tp_new (METHOD_NEW) nor tp_init (METHOD_INIT):
2555 # * The type of the first parameter to the parsing function is also self.type.
2556 # This means that if you step into the parsing function, your "self" parameter
2557 # is of the correct type, which may make debugging more pleasant.
2558 #
2559 # * Else if the function is tp_new (METHOD_NEW):
2560 # * The type of the first parameter to the parsing function is "PyTypeObject *",
2561 # so the type signature of the function call is an exact match.
2562 # * If self.type != "PyTypeObject *", we cast the first parameter to self.type
2563 # in the impl call.
2564 #
2565 # * Else if the function is tp_init (METHOD_INIT):
2566 # * The type of the first parameter to the parsing function is "PyObject *",
2567 # so the type signature of the function call is an exact match.
2568 # * If self.type != "PyObject *", we cast the first parameter to self.type
2569 # in the impl call.
2570
2571 @property
2572 def parser_type(self):
Larry Hastingsc2047262014-01-25 20:43:29 -08002573 return required_type_for_self_for_parser(self.function) or self.type
Larry Hastings78cf85c2014-01-04 12:44:57 -08002574
Larry Hastingsebdcb502013-11-23 14:54:00 -08002575 def render(self, parameter, data):
Larry Hastings5c661892014-01-24 06:17:25 -08002576 """
2577 parameter is a clinic.Parameter instance.
2578 data is a CRenderData instance.
2579 """
2580 if self.function.kind == STATIC_METHOD:
2581 return
2582
2583 self._render_self(parameter, data)
2584
2585 if self.type != self.parser_type:
2586 # insert cast to impl_argument[0], aka self.
2587 # we know we're in the first slot in all the CRenderData lists,
2588 # because we render parameters in order, and self is always first.
2589 assert len(data.impl_arguments) == 1
2590 assert data.impl_arguments[0] == self.name
2591 data.impl_arguments[0] = '(' + self.type + ")" + data.impl_arguments[0]
2592
2593 def set_template_dict(self, template_dict):
2594 template_dict['self_name'] = self.name
2595 template_dict['self_type'] = self.parser_type
Larry Hastingsc2047262014-01-25 20:43:29 -08002596 template_dict['self_type_check'] = '({self_name} == {self_type_object}) &&\n '
Larry Hastingsebdcb502013-11-23 14:54:00 -08002597
Larry Hastings31826802013-10-19 00:09:25 -07002598
2599
2600def add_c_return_converter(f, name=None):
2601 if not name:
2602 name = f.__name__
2603 if not name.endswith('_return_converter'):
2604 return f
2605 name = name[:-len('_return_converter')]
2606 return_converters[name] = f
2607 return f
2608
2609
2610class CReturnConverterAutoRegister(type):
2611 def __init__(cls, name, bases, classdict):
2612 add_c_return_converter(cls)
2613
2614class CReturnConverter(metaclass=CReturnConverterAutoRegister):
2615
Larry Hastings78cf85c2014-01-04 12:44:57 -08002616 # The C type to use for this variable.
2617 # 'type' should be a Python string specifying the type, e.g. "int".
2618 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07002619 type = 'PyObject *'
Larry Hastings78cf85c2014-01-04 12:44:57 -08002620
2621 # The Python default value for this parameter, as a Python value.
2622 # Or the magic value "unspecified" if there is no default.
Larry Hastings31826802013-10-19 00:09:25 -07002623 default = None
2624
Larry Hastings2a727912014-01-16 11:32:01 -08002625 def __init__(self, *, py_default=None, **kwargs):
2626 self.py_default = py_default
Larry Hastings31826802013-10-19 00:09:25 -07002627 try:
2628 self.return_converter_init(**kwargs)
2629 except TypeError as e:
2630 s = ', '.join(name + '=' + repr(value) for name, value in kwargs.items())
2631 sys.exit(self.__class__.__name__ + '(' + s + ')\n' + str(e))
2632
2633 def return_converter_init(self):
2634 pass
2635
2636 def declare(self, data, name="_return_value"):
2637 line = []
2638 add = line.append
2639 add(self.type)
2640 if not self.type.endswith('*'):
2641 add(' ')
2642 add(name + ';')
2643 data.declarations.append(''.join(line))
2644 data.return_value = name
2645
2646 def err_occurred_if(self, expr, data):
2647 data.return_conversion.append('if (({}) && PyErr_Occurred())\n goto exit;\n'.format(expr))
2648
2649 def err_occurred_if_null_pointer(self, variable, data):
2650 data.return_conversion.append('if ({} == NULL)\n goto exit;\n'.format(variable))
2651
2652 def render(self, function, data):
2653 """
2654 function is a clinic.Function instance.
2655 data is a CRenderData instance.
2656 """
2657 pass
2658
2659add_c_return_converter(CReturnConverter, 'object')
2660
Larry Hastings78cf85c2014-01-04 12:44:57 -08002661class NoneType_return_converter(CReturnConverter):
2662 def render(self, function, data):
2663 self.declare(data)
2664 data.return_conversion.append('''
2665if (_return_value != Py_None)
2666 goto exit;
2667return_value = Py_None;
2668Py_INCREF(Py_None);
2669'''.strip())
2670
Larry Hastings4a55fc52014-01-12 11:09:57 -08002671class bool_return_converter(CReturnConverter):
Larry Hastings31826802013-10-19 00:09:25 -07002672 type = 'int'
2673
2674 def render(self, function, data):
2675 self.declare(data)
2676 self.err_occurred_if("_return_value == -1", data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002677 data.return_conversion.append('return_value = PyBool_FromLong((long)_return_value);\n')
Larry Hastings31826802013-10-19 00:09:25 -07002678
2679class long_return_converter(CReturnConverter):
2680 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002681 conversion_fn = 'PyLong_FromLong'
2682 cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07002683
2684 def render(self, function, data):
2685 self.declare(data)
2686 self.err_occurred_if("_return_value == -1", data)
2687 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08002688 ''.join(('return_value = ', self.conversion_fn, '(', self.cast, '_return_value);\n')))
Larry Hastings31826802013-10-19 00:09:25 -07002689
Larry Hastings4a55fc52014-01-12 11:09:57 -08002690class int_return_converter(long_return_converter):
2691 type = 'int'
2692 cast = '(long)'
Larry Hastings31826802013-10-19 00:09:25 -07002693
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002694class init_return_converter(long_return_converter):
2695 """
2696 Special return converter for __init__ functions.
2697 """
2698 type = 'int'
2699 cast = '(long)'
2700
2701 def render(self, function, data):
2702 pass
2703
Larry Hastings4a55fc52014-01-12 11:09:57 -08002704class unsigned_long_return_converter(long_return_converter):
2705 type = 'unsigned long'
2706 conversion_fn = 'PyLong_FromUnsignedLong'
2707
2708class unsigned_int_return_converter(unsigned_long_return_converter):
2709 type = 'unsigned int'
2710 cast = '(unsigned long)'
2711
2712class Py_ssize_t_return_converter(long_return_converter):
Larry Hastings31826802013-10-19 00:09:25 -07002713 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002714 conversion_fn = 'PyLong_FromSsize_t'
2715
2716class size_t_return_converter(long_return_converter):
2717 type = 'size_t'
2718 conversion_fn = 'PyLong_FromSize_t'
2719
2720
2721class double_return_converter(CReturnConverter):
2722 type = 'double'
2723 cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07002724
2725 def render(self, function, data):
2726 self.declare(data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002727 self.err_occurred_if("_return_value == -1.0", data)
Larry Hastings31826802013-10-19 00:09:25 -07002728 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08002729 'return_value = PyFloat_FromDouble(' + self.cast + '_return_value);\n')
2730
2731class float_return_converter(double_return_converter):
2732 type = 'float'
2733 cast = '(double)'
Larry Hastings31826802013-10-19 00:09:25 -07002734
2735
2736class DecodeFSDefault_return_converter(CReturnConverter):
2737 type = 'char *'
2738
2739 def render(self, function, data):
2740 self.declare(data)
2741 self.err_occurred_if_null_pointer("_return_value", data)
2742 data.return_conversion.append(
2743 'return_value = PyUnicode_DecodeFSDefault(_return_value);\n')
2744
2745
2746class IndentStack:
2747 def __init__(self):
2748 self.indents = []
2749 self.margin = None
2750
2751 def _ensure(self):
2752 if not self.indents:
2753 fail('IndentStack expected indents, but none are defined.')
2754
2755 def measure(self, line):
2756 """
2757 Returns the length of the line's margin.
2758 """
2759 if '\t' in line:
2760 fail('Tab characters are illegal in the Clinic DSL.')
2761 stripped = line.lstrip()
2762 if not len(stripped):
2763 # we can't tell anything from an empty line
2764 # so just pretend it's indented like our current indent
2765 self._ensure()
2766 return self.indents[-1]
2767 return len(line) - len(stripped)
2768
2769 def infer(self, line):
2770 """
2771 Infer what is now the current margin based on this line.
2772 Returns:
2773 1 if we have indented (or this is the first margin)
2774 0 if the margin has not changed
2775 -N if we have dedented N times
2776 """
2777 indent = self.measure(line)
2778 margin = ' ' * indent
2779 if not self.indents:
2780 self.indents.append(indent)
2781 self.margin = margin
2782 return 1
2783 current = self.indents[-1]
2784 if indent == current:
2785 return 0
2786 if indent > current:
2787 self.indents.append(indent)
2788 self.margin = margin
2789 return 1
2790 # indent < current
2791 if indent not in self.indents:
2792 fail("Illegal outdent.")
2793 outdent_count = 0
2794 while indent != current:
2795 self.indents.pop()
2796 current = self.indents[-1]
2797 outdent_count -= 1
2798 self.margin = margin
2799 return outdent_count
2800
2801 @property
2802 def depth(self):
2803 """
2804 Returns how many margins are currently defined.
2805 """
2806 return len(self.indents)
2807
2808 def indent(self, line):
2809 """
2810 Indents a line by the currently defined margin.
2811 """
2812 return self.margin + line
2813
2814 def dedent(self, line):
2815 """
2816 Dedents a line by the currently defined margin.
2817 (The inverse of 'indent'.)
2818 """
2819 margin = self.margin
2820 indent = self.indents[-1]
2821 if not line.startswith(margin):
2822 fail('Cannot dedent, line does not start with the previous margin:')
2823 return line[indent:]
2824
2825
2826class DSLParser:
2827 def __init__(self, clinic):
2828 self.clinic = clinic
2829
2830 self.directives = {}
2831 for name in dir(self):
2832 # functions that start with directive_ are added to directives
2833 _, s, key = name.partition("directive_")
2834 if s:
2835 self.directives[key] = getattr(self, name)
2836
2837 # functions that start with at_ are too, with an @ in front
2838 _, s, key = name.partition("at_")
2839 if s:
2840 self.directives['@' + key] = getattr(self, name)
2841
2842 self.reset()
2843
2844 def reset(self):
2845 self.function = None
2846 self.state = self.state_dsl_start
2847 self.parameter_indent = None
2848 self.keyword_only = False
2849 self.group = 0
2850 self.parameter_state = self.ps_start
Larry Hastingsc2047262014-01-25 20:43:29 -08002851 self.seen_positional_with_default = False
Larry Hastings31826802013-10-19 00:09:25 -07002852 self.indent = IndentStack()
2853 self.kind = CALLABLE
2854 self.coexist = False
Larry Hastings2a727912014-01-16 11:32:01 -08002855 self.parameter_continuation = ''
Larry Hastingsbebf7352014-01-17 17:47:17 -08002856 self.preserve_output = False
Larry Hastings31826802013-10-19 00:09:25 -07002857
Larry Hastingsebdcb502013-11-23 14:54:00 -08002858 def directive_version(self, required):
2859 global version
2860 if version_comparitor(version, required) < 0:
2861 fail("Insufficient Clinic version!\n Version: " + version + "\n Required: " + required)
2862
Larry Hastings31826802013-10-19 00:09:25 -07002863 def directive_module(self, name):
2864 fields = name.split('.')
2865 new = fields.pop()
2866 module, cls = self.clinic._module_and_class(fields)
2867 if cls:
2868 fail("Can't nest a module inside a class!")
Larry Hastingsc2047262014-01-25 20:43:29 -08002869
2870 if name in module.classes:
2871 fail("Already defined module " + repr(name) + "!")
2872
Larry Hastings31826802013-10-19 00:09:25 -07002873 m = Module(name, module)
2874 module.modules[name] = m
2875 self.block.signatures.append(m)
2876
Larry Hastingsc2047262014-01-25 20:43:29 -08002877 def directive_class(self, name, typedef, type_object):
Larry Hastings31826802013-10-19 00:09:25 -07002878 fields = name.split('.')
2879 in_classes = False
2880 parent = self
2881 name = fields.pop()
2882 so_far = []
2883 module, cls = self.clinic._module_and_class(fields)
2884
Larry Hastingsc2047262014-01-25 20:43:29 -08002885 parent = cls or module
2886 if name in parent.classes:
2887 fail("Already defined class " + repr(name) + "!")
2888
2889 c = Class(name, module, cls, typedef, type_object)
2890 parent.classes[name] = c
Larry Hastings31826802013-10-19 00:09:25 -07002891 self.block.signatures.append(c)
2892
Larry Hastingsbebf7352014-01-17 17:47:17 -08002893 def directive_set(self, name, value):
2894 if name not in ("line_prefix", "line_suffix"):
2895 fail("unknown variable", repr(name))
2896
2897 value = value.format_map({
2898 'block comment start': '/*',
2899 'block comment end': '*/',
2900 })
2901
2902 self.clinic.__dict__[name] = value
2903
2904 def directive_destination(self, name, command, *args):
Zachary Ware071baa62014-01-21 23:07:12 -06002905 if command == 'new':
2906 self.clinic.add_destination(name, *args)
Larry Hastingsbebf7352014-01-17 17:47:17 -08002907 return
2908
Zachary Ware071baa62014-01-21 23:07:12 -06002909 if command == 'clear':
Larry Hastingsbebf7352014-01-17 17:47:17 -08002910 self.clinic.get_destination(name).clear()
2911 fail("unknown destination command", repr(command))
2912
2913
2914 def directive_output(self, field, destination=''):
2915 fd = self.clinic.field_destinations
2916
2917 if field == "preset":
2918 preset = self.clinic.presets.get(destination)
2919 if not preset:
2920 fail("Unknown preset " + repr(destination) + "!")
2921 fd.update(preset)
2922 return
2923
2924 if field == "push":
2925 self.clinic.field_destinations_stack.append(fd.copy())
2926 return
2927
2928 if field == "pop":
2929 if not self.clinic.field_destinations_stack:
2930 fail("Can't 'output pop', stack is empty!")
2931 previous_fd = self.clinic.field_destinations_stack.pop()
2932 fd.update(previous_fd)
2933 return
2934
2935 # secret command for debugging!
2936 if field == "print":
2937 self.block.output.append(pprint.pformat(fd))
2938 self.block.output.append('\n')
2939 return
2940
2941 d = self.clinic.get_destination(destination)
2942
2943 if field == "everything":
2944 for name in list(fd):
2945 fd[name] = d
2946 return
2947
2948 if field not in fd:
2949 fail("Invalid field " + repr(field) + ", must be one of:\n " + ", ".join(valid_fields))
2950 fd[field] = d
2951
2952 def directive_dump(self, name):
2953 self.block.output.append(self.clinic.get_destination(name).dump())
2954
2955 def directive_print(self, *args):
2956 self.block.output.append(' '.join(args))
2957 self.block.output.append('\n')
2958
2959 def directive_preserve(self):
2960 if self.preserve_output:
2961 fail("Can't have preserve twice in one block!")
2962 self.preserve_output = True
2963
Larry Hastings31826802013-10-19 00:09:25 -07002964 def at_classmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002965 if self.kind is not CALLABLE:
2966 fail("Can't set @classmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07002967 self.kind = CLASS_METHOD
2968
2969 def at_staticmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002970 if self.kind is not CALLABLE:
2971 fail("Can't set @staticmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07002972 self.kind = STATIC_METHOD
2973
2974 def at_coexist(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002975 if self.coexist:
2976 fail("Called @coexist twice!")
Larry Hastings31826802013-10-19 00:09:25 -07002977 self.coexist = True
2978
2979 def parse(self, block):
2980 self.reset()
2981 self.block = block
Larry Hastingsbebf7352014-01-17 17:47:17 -08002982 self.saved_output = self.block.output
2983 block.output = []
Larry Hastings31826802013-10-19 00:09:25 -07002984 block_start = self.clinic.block_parser.line_number
2985 lines = block.input.split('\n')
2986 for line_number, line in enumerate(lines, self.clinic.block_parser.block_start_line_number):
2987 if '\t' in line:
2988 fail('Tab characters are illegal in the Clinic DSL.\n\t' + repr(line), line_number=block_start)
2989 self.state(line)
2990
2991 self.next(self.state_terminal)
2992 self.state(None)
2993
Larry Hastingsbebf7352014-01-17 17:47:17 -08002994 block.output.extend(self.clinic.language.render(clinic, block.signatures))
2995
2996 if self.preserve_output:
2997 if block.output:
2998 fail("'preserve' only works for blocks that don't produce any output!")
2999 block.output = self.saved_output
Larry Hastings31826802013-10-19 00:09:25 -07003000
3001 @staticmethod
3002 def ignore_line(line):
3003 # ignore comment-only lines
3004 if line.lstrip().startswith('#'):
3005 return True
3006
3007 # Ignore empty lines too
3008 # (but not in docstring sections!)
3009 if not line.strip():
3010 return True
3011
3012 return False
3013
3014 @staticmethod
3015 def calculate_indent(line):
3016 return len(line) - len(line.strip())
3017
3018 def next(self, state, line=None):
3019 # real_print(self.state.__name__, "->", state.__name__, ", line=", line)
3020 self.state = state
3021 if line is not None:
3022 self.state(line)
3023
3024 def state_dsl_start(self, line):
3025 # self.block = self.ClinicOutputBlock(self)
3026 if self.ignore_line(line):
3027 return
3028 self.next(self.state_modulename_name, line)
3029
3030 def state_modulename_name(self, line):
3031 # looking for declaration, which establishes the leftmost column
3032 # line should be
3033 # modulename.fnname [as c_basename] [-> return annotation]
3034 # square brackets denote optional syntax.
3035 #
Larry Hastings4a714d42014-01-14 22:22:41 -08003036 # alternatively:
3037 # modulename.fnname [as c_basename] = modulename.existing_fn_name
3038 # clones the parameters and return converter from that
3039 # function. you can't modify them. you must enter a
3040 # new docstring.
3041 #
Larry Hastings31826802013-10-19 00:09:25 -07003042 # (but we might find a directive first!)
3043 #
3044 # this line is permitted to start with whitespace.
3045 # we'll call this number of spaces F (for "function").
3046
3047 if not line.strip():
3048 return
3049
3050 self.indent.infer(line)
3051
3052 # is it a directive?
3053 fields = shlex.split(line)
3054 directive_name = fields[0]
3055 directive = self.directives.get(directive_name, None)
3056 if directive:
Larry Hastingsbebf7352014-01-17 17:47:17 -08003057 try:
3058 directive(*fields[1:])
3059 except TypeError as e:
3060 fail(str(e))
Larry Hastings31826802013-10-19 00:09:25 -07003061 return
3062
Larry Hastings4a714d42014-01-14 22:22:41 -08003063 # are we cloning?
3064 before, equals, existing = line.rpartition('=')
3065 if equals:
3066 full_name, _, c_basename = before.partition(' as ')
3067 full_name = full_name.strip()
3068 c_basename = c_basename.strip()
3069 existing = existing.strip()
3070 if (is_legal_py_identifier(full_name) and
3071 (not c_basename or is_legal_c_identifier(c_basename)) and
3072 is_legal_py_identifier(existing)):
3073 # we're cloning!
3074 fields = [x.strip() for x in existing.split('.')]
3075 function_name = fields.pop()
3076 module, cls = self.clinic._module_and_class(fields)
3077
3078 for existing_function in (cls or module).functions:
3079 if existing_function.name == function_name:
3080 break
3081 else:
3082 existing_function = None
3083 if not existing_function:
Larry Hastingsc2047262014-01-25 20:43:29 -08003084 print("class", cls, "module", module, "exsiting", existing)
3085 print("cls. functions", cls.functions)
Larry Hastings4a714d42014-01-14 22:22:41 -08003086 fail("Couldn't find existing function " + repr(existing) + "!")
3087
3088 fields = [x.strip() for x in full_name.split('.')]
3089 function_name = fields.pop()
3090 module, cls = self.clinic._module_and_class(fields)
3091
3092 if not (existing_function.kind == self.kind and existing_function.coexist == self.coexist):
3093 fail("'kind' of function and cloned function don't match! (@classmethod/@staticmethod/@coexist)")
3094 self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename,
3095 return_converter=existing_function.return_converter, kind=existing_function.kind, coexist=existing_function.coexist)
3096
3097 self.function.parameters = existing_function.parameters.copy()
3098
3099 self.block.signatures.append(self.function)
3100 (cls or module).functions.append(self.function)
3101 self.next(self.state_function_docstring)
3102 return
3103
Larry Hastings31826802013-10-19 00:09:25 -07003104 line, _, returns = line.partition('->')
3105
3106 full_name, _, c_basename = line.partition(' as ')
3107 full_name = full_name.strip()
3108 c_basename = c_basename.strip() or None
3109
Larry Hastingsdfcd4672013-10-27 02:49:39 -07003110 if not is_legal_py_identifier(full_name):
3111 fail("Illegal function name: {}".format(full_name))
3112 if c_basename and not is_legal_c_identifier(c_basename):
3113 fail("Illegal C basename: {}".format(c_basename))
3114
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003115 return_converter = None
3116 if returns:
Larry Hastings31826802013-10-19 00:09:25 -07003117 ast_input = "def x() -> {}: pass".format(returns)
3118 module = None
3119 try:
3120 module = ast.parse(ast_input)
3121 except SyntaxError:
3122 pass
3123 if not module:
3124 fail("Badly-formed annotation for " + full_name + ": " + returns)
3125 try:
3126 name, legacy, kwargs = self.parse_converter(module.body[0].returns)
Antoine Pitroud7fb7912014-01-14 21:02:43 +01003127 if legacy:
3128 fail("Legacy converter {!r} not allowed as a return converter"
3129 .format(name))
Larry Hastings31826802013-10-19 00:09:25 -07003130 if name not in return_converters:
Antoine Pitroud7fb7912014-01-14 21:02:43 +01003131 fail("No available return converter called " + repr(name))
Larry Hastings31826802013-10-19 00:09:25 -07003132 return_converter = return_converters[name](**kwargs)
3133 except ValueError:
3134 fail("Badly-formed annotation for " + full_name + ": " + returns)
3135
3136 fields = [x.strip() for x in full_name.split('.')]
3137 function_name = fields.pop()
3138 module, cls = self.clinic._module_and_class(fields)
3139
Larry Hastings8666e652014-01-12 14:12:59 -08003140 fields = full_name.split('.')
3141 if fields[-1] == '__new__':
3142 if (self.kind != CLASS_METHOD) or (not cls):
3143 fail("__new__ must be a class method!")
3144 self.kind = METHOD_NEW
3145 elif fields[-1] == '__init__':
3146 if (self.kind != CALLABLE) or (not cls):
3147 fail("__init__ must be a normal method, not a class or static method!")
3148 self.kind = METHOD_INIT
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003149 if not return_converter:
3150 return_converter = init_return_converter()
Larry Hastings8666e652014-01-12 14:12:59 -08003151 elif fields[-1] in unsupported_special_methods:
Larry Hastings5c661892014-01-24 06:17:25 -08003152 fail(fields[-1] + " is a special method and cannot be converted to Argument Clinic! (Yet.)")
Larry Hastings8666e652014-01-12 14:12:59 -08003153
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003154 if not return_converter:
3155 return_converter = CReturnConverter()
3156
Larry Hastings31826802013-10-19 00:09:25 -07003157 if not module:
3158 fail("Undefined module used in declaration of " + repr(full_name.strip()) + ".")
3159 self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename,
3160 return_converter=return_converter, kind=self.kind, coexist=self.coexist)
3161 self.block.signatures.append(self.function)
Larry Hastings5c661892014-01-24 06:17:25 -08003162
3163 # insert a self converter automatically
Larry Hastingsc2047262014-01-25 20:43:29 -08003164 type, name = correct_name_for_self(self.function)
3165 kwargs = {}
3166 if cls and type == "PyObject *":
3167 kwargs['type'] = cls.typedef
3168 sc = self.function.self_converter = self_converter(name, self.function, **kwargs)
Larry Hastings5c661892014-01-24 06:17:25 -08003169 p_self = Parameter(sc.name, inspect.Parameter.POSITIONAL_ONLY, function=self.function, converter=sc)
3170 self.function.parameters[sc.name] = p_self
3171
Larry Hastings4a714d42014-01-14 22:22:41 -08003172 (cls or module).functions.append(self.function)
Larry Hastings31826802013-10-19 00:09:25 -07003173 self.next(self.state_parameters_start)
3174
3175 # Now entering the parameters section. The rules, formally stated:
3176 #
3177 # * All lines must be indented with spaces only.
3178 # * The first line must be a parameter declaration.
3179 # * The first line must be indented.
3180 # * This first line establishes the indent for parameters.
3181 # * We'll call this number of spaces P (for "parameter").
3182 # * Thenceforth:
3183 # * Lines indented with P spaces specify a parameter.
3184 # * Lines indented with > P spaces are docstrings for the previous
3185 # parameter.
3186 # * We'll call this number of spaces D (for "docstring").
3187 # * All subsequent lines indented with >= D spaces are stored as
3188 # part of the per-parameter docstring.
3189 # * All lines will have the first D spaces of the indent stripped
3190 # before they are stored.
3191 # * It's illegal to have a line starting with a number of spaces X
3192 # such that P < X < D.
3193 # * A line with < P spaces is the first line of the function
3194 # docstring, which ends processing for parameters and per-parameter
3195 # docstrings.
3196 # * The first line of the function docstring must be at the same
3197 # indent as the function declaration.
3198 # * It's illegal to have any line in the parameters section starting
3199 # with X spaces such that F < X < P. (As before, F is the indent
3200 # of the function declaration.)
3201 #
Larry Hastings31826802013-10-19 00:09:25 -07003202 # Also, currently Argument Clinic places the following restrictions on groups:
3203 # * Each group must contain at least one parameter.
3204 # * Each group may contain at most one group, which must be the furthest
3205 # thing in the group from the required parameters. (The nested group
3206 # must be the first in the group when it's before the required
3207 # parameters, and the last thing in the group when after the required
3208 # parameters.)
3209 # * There may be at most one (top-level) group to the left or right of
3210 # the required parameters.
3211 # * You must specify a slash, and it must be after all parameters.
3212 # (In other words: either all parameters are positional-only,
3213 # or none are.)
3214 #
3215 # Said another way:
3216 # * Each group must contain at least one parameter.
3217 # * All left square brackets before the required parameters must be
3218 # consecutive. (You can't have a left square bracket followed
3219 # by a parameter, then another left square bracket. You can't
3220 # have a left square bracket, a parameter, a right square bracket,
3221 # and then a left square bracket.)
3222 # * All right square brackets after the required parameters must be
3223 # consecutive.
3224 #
3225 # These rules are enforced with a single state variable:
3226 # "parameter_state". (Previously the code was a miasma of ifs and
3227 # separate boolean state variables.) The states are:
3228 #
Larry Hastingsc2047262014-01-25 20:43:29 -08003229 # [ [ a, b, ] c, ] d, e, f=3, [ g, h, [ i ] ] / <- line
3230 # 01 2 3 4 5 6 7 <- state transitions
Larry Hastings31826802013-10-19 00:09:25 -07003231 #
3232 # 0: ps_start. before we've seen anything. legal transitions are to 1 or 3.
3233 # 1: ps_left_square_before. left square brackets before required parameters.
3234 # 2: ps_group_before. in a group, before required parameters.
Larry Hastingsc2047262014-01-25 20:43:29 -08003235 # 3: ps_required. required parameters, positional-or-keyword or positional-only
3236 # (we don't know yet). (renumber left groups!)
3237 # 4: ps_optional. positional-or-keyword or positional-only parameters that
3238 # now must have default values.
3239 # 5: ps_group_after. in a group, after required parameters.
3240 # 6: ps_right_square_after. right square brackets after required parameters.
3241 # 7: ps_seen_slash. seen slash.
Larry Hastings31826802013-10-19 00:09:25 -07003242 ps_start, ps_left_square_before, ps_group_before, ps_required, \
Larry Hastingsc2047262014-01-25 20:43:29 -08003243 ps_optional, ps_group_after, ps_right_square_after, ps_seen_slash = range(8)
Larry Hastings31826802013-10-19 00:09:25 -07003244
3245 def state_parameters_start(self, line):
3246 if self.ignore_line(line):
3247 return
3248
3249 # if this line is not indented, we have no parameters
3250 if not self.indent.infer(line):
3251 return self.next(self.state_function_docstring, line)
3252
Larry Hastings2a727912014-01-16 11:32:01 -08003253 self.parameter_continuation = ''
Larry Hastings31826802013-10-19 00:09:25 -07003254 return self.next(self.state_parameter, line)
3255
3256
3257 def to_required(self):
3258 """
3259 Transition to the "required" parameter state.
3260 """
3261 if self.parameter_state != self.ps_required:
3262 self.parameter_state = self.ps_required
3263 for p in self.function.parameters.values():
3264 p.group = -p.group
3265
3266 def state_parameter(self, line):
Larry Hastings2a727912014-01-16 11:32:01 -08003267 if self.parameter_continuation:
3268 line = self.parameter_continuation + ' ' + line.lstrip()
3269 self.parameter_continuation = ''
3270
Larry Hastings31826802013-10-19 00:09:25 -07003271 if self.ignore_line(line):
3272 return
3273
3274 assert self.indent.depth == 2
3275 indent = self.indent.infer(line)
3276 if indent == -1:
3277 # we outdented, must be to definition column
3278 return self.next(self.state_function_docstring, line)
3279
3280 if indent == 1:
3281 # we indented, must be to new parameter docstring column
3282 return self.next(self.state_parameter_docstring_start, line)
3283
Larry Hastings2a727912014-01-16 11:32:01 -08003284 line = line.rstrip()
3285 if line.endswith('\\'):
3286 self.parameter_continuation = line[:-1]
3287 return
3288
Larry Hastings31826802013-10-19 00:09:25 -07003289 line = line.lstrip()
3290
3291 if line in ('*', '/', '[', ']'):
3292 self.parse_special_symbol(line)
3293 return
3294
3295 if self.parameter_state in (self.ps_start, self.ps_required):
3296 self.to_required()
3297 elif self.parameter_state == self.ps_left_square_before:
3298 self.parameter_state = self.ps_group_before
3299 elif self.parameter_state == self.ps_group_before:
3300 if not self.group:
3301 self.to_required()
Larry Hastingsc2047262014-01-25 20:43:29 -08003302 elif self.parameter_state in (self.ps_group_after, self.ps_optional):
Larry Hastings31826802013-10-19 00:09:25 -07003303 pass
3304 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003305 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".a)")
Larry Hastings31826802013-10-19 00:09:25 -07003306
Larry Hastings2a727912014-01-16 11:32:01 -08003307 base, equals, default = line.rpartition('=')
3308 if not equals:
3309 base = default
3310 default = None
Larry Hastingsc2047262014-01-25 20:43:29 -08003311
Larry Hastings31826802013-10-19 00:09:25 -07003312 module = None
3313 try:
Larry Hastings2a727912014-01-16 11:32:01 -08003314 ast_input = "def x({}): pass".format(base)
Larry Hastings31826802013-10-19 00:09:25 -07003315 module = ast.parse(ast_input)
3316 except SyntaxError:
Larry Hastings2a727912014-01-16 11:32:01 -08003317 try:
Larry Hastingsc2047262014-01-25 20:43:29 -08003318 # the last = was probably inside a function call, like
3319 # i: int(nullable=True)
3320 # so assume there was no actual default value.
Larry Hastings2a727912014-01-16 11:32:01 -08003321 default = None
3322 ast_input = "def x({}): pass".format(line)
3323 module = ast.parse(ast_input)
3324 except SyntaxError:
3325 pass
Larry Hastings31826802013-10-19 00:09:25 -07003326 if not module:
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07003327 fail("Function " + self.function.name + " has an invalid parameter declaration:\n\t" + line)
Larry Hastings31826802013-10-19 00:09:25 -07003328
3329 function_args = module.body[0].args
3330 parameter = function_args.args[0]
3331
Larry Hastings16c51912014-01-07 11:53:01 -08003332 parameter_name = parameter.arg
3333 name, legacy, kwargs = self.parse_converter(parameter.annotation)
3334
Larry Hastings2a727912014-01-16 11:32:01 -08003335 if not default:
Larry Hastingsc2047262014-01-25 20:43:29 -08003336 if self.parameter_state == self.ps_optional:
3337 fail("Can't have a parameter without a default (" + repr(parameter_name) + ")\nafter a parameter with a default!")
Larry Hastings2a727912014-01-16 11:32:01 -08003338 value = unspecified
3339 if 'py_default' in kwargs:
3340 fail("You can't specify py_default without specifying a default value!")
3341 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003342 if self.parameter_state == self.ps_required:
3343 self.parameter_state = self.ps_optional
Larry Hastings2a727912014-01-16 11:32:01 -08003344 default = default.strip()
Zachary Ware021bb872014-01-24 22:52:30 -06003345 bad = False
Larry Hastings2a727912014-01-16 11:32:01 -08003346 ast_input = "x = {}".format(default)
Larry Hastingsc2047262014-01-25 20:43:29 -08003347 bad = False
Larry Hastings2a727912014-01-16 11:32:01 -08003348 try:
3349 module = ast.parse(ast_input)
3350
Larry Hastings5c661892014-01-24 06:17:25 -08003351 if 'c_default' not in kwargs:
3352 # we can only represent very simple data values in C.
3353 # detect whether default is okay, via a blacklist
3354 # of disallowed ast nodes.
3355 class DetectBadNodes(ast.NodeVisitor):
3356 bad = False
3357 def bad_node(self, node):
3358 self.bad = True
Larry Hastings2a727912014-01-16 11:32:01 -08003359
Larry Hastings5c661892014-01-24 06:17:25 -08003360 # inline function call
3361 visit_Call = bad_node
3362 # inline if statement ("x = 3 if y else z")
3363 visit_IfExp = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003364
Larry Hastings5c661892014-01-24 06:17:25 -08003365 # comprehensions and generator expressions
3366 visit_ListComp = visit_SetComp = bad_node
3367 visit_DictComp = visit_GeneratorExp = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003368
Larry Hastings5c661892014-01-24 06:17:25 -08003369 # literals for advanced types
3370 visit_Dict = visit_Set = bad_node
3371 visit_List = visit_Tuple = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003372
Larry Hastings5c661892014-01-24 06:17:25 -08003373 # "starred": "a = [1, 2, 3]; *a"
3374 visit_Starred = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003375
Larry Hastings5c661892014-01-24 06:17:25 -08003376 # allow ellipsis, for now
3377 # visit_Ellipsis = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003378
Larry Hastings5c661892014-01-24 06:17:25 -08003379 blacklist = DetectBadNodes()
3380 blacklist.visit(module)
3381 bad = blacklist.bad
3382 else:
3383 # if they specify a c_default, we can be more lenient about the default value.
Zachary Ware021bb872014-01-24 22:52:30 -06003384 # but at least make an attempt at ensuring it's a valid expression.
3385 try:
3386 value = eval(default)
3387 if value == unspecified:
3388 fail("'unspecified' is not a legal default value!")
3389 except NameError:
3390 pass # probably a named constant
3391 except Exception as e:
3392 fail("Malformed expression given as default value\n"
3393 "{!r} caused {!r}".format(default, e))
Larry Hastings5c661892014-01-24 06:17:25 -08003394 if bad:
Larry Hastings2a727912014-01-16 11:32:01 -08003395 fail("Unsupported expression as default value: " + repr(default))
3396
3397 expr = module.body[0].value
3398 # mild hack: explicitly support NULL as a default value
3399 if isinstance(expr, ast.Name) and expr.id == 'NULL':
3400 value = NULL
3401 py_default = 'None'
3402 c_default = "NULL"
3403 elif (isinstance(expr, ast.BinOp) or
3404 (isinstance(expr, ast.UnaryOp) and not isinstance(expr.operand, ast.Num))):
3405 c_default = kwargs.get("c_default")
3406 if not (isinstance(c_default, str) and c_default):
3407 fail("When you specify an expression (" + repr(default) + ") as your default value,\nyou MUST specify a valid c_default.")
3408 py_default = default
3409 value = unknown
3410 elif isinstance(expr, ast.Attribute):
3411 a = []
3412 n = expr
3413 while isinstance(n, ast.Attribute):
3414 a.append(n.attr)
3415 n = n.value
3416 if not isinstance(n, ast.Name):
3417 fail("Unsupported default value " + repr(default) + " (looked like a Python constant)")
3418 a.append(n.id)
3419 py_default = ".".join(reversed(a))
3420
3421 c_default = kwargs.get("c_default")
3422 if not (isinstance(c_default, str) and c_default):
3423 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3424
3425 try:
3426 value = eval(py_default)
3427 except NameError:
3428 value = unknown
3429 else:
3430 value = ast.literal_eval(expr)
3431 py_default = repr(value)
3432 if isinstance(value, (bool, None.__class__)):
3433 c_default = "Py_" + py_default
3434 elif isinstance(value, str):
Larry Hastings4903e002014-01-18 00:26:16 -08003435 c_default = c_repr(value)
Larry Hastings2a727912014-01-16 11:32:01 -08003436 else:
3437 c_default = py_default
3438
3439 except SyntaxError as e:
3440 fail("Syntax error: " + repr(e.text))
3441 except (ValueError, AttributeError):
3442 value = unknown
Larry Hastings4a55fc52014-01-12 11:09:57 -08003443 c_default = kwargs.get("c_default")
Larry Hastings2a727912014-01-16 11:32:01 -08003444 py_default = default
Larry Hastings4a55fc52014-01-12 11:09:57 -08003445 if not (isinstance(c_default, str) and c_default):
3446 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3447
Larry Hastings2a727912014-01-16 11:32:01 -08003448 kwargs.setdefault('c_default', c_default)
3449 kwargs.setdefault('py_default', py_default)
Larry Hastings31826802013-10-19 00:09:25 -07003450
Larry Hastings31826802013-10-19 00:09:25 -07003451 dict = legacy_converters if legacy else converters
3452 legacy_str = "legacy " if legacy else ""
3453 if name not in dict:
3454 fail('{} is not a valid {}converter'.format(name, legacy_str))
3455 converter = dict[name](parameter_name, self.function, value, **kwargs)
3456
3457 kind = inspect.Parameter.KEYWORD_ONLY if self.keyword_only else inspect.Parameter.POSITIONAL_OR_KEYWORD
Larry Hastings5c661892014-01-24 06:17:25 -08003458
3459 if isinstance(converter, self_converter):
3460 if len(self.function.parameters) == 1:
3461 if (self.parameter_state != self.ps_required):
3462 fail("A 'self' parameter cannot be marked optional.")
3463 if value is not unspecified:
3464 fail("A 'self' parameter cannot have a default value.")
3465 if self.group:
3466 fail("A 'self' parameter cannot be in an optional group.")
3467 kind = inspect.Parameter.POSITIONAL_ONLY
3468 self.parameter_state = self.ps_start
3469 self.function.parameters.clear()
3470 else:
3471 fail("A 'self' parameter, if specified, must be the very first thing in the parameter block.")
3472
Larry Hastings31826802013-10-19 00:09:25 -07003473 p = Parameter(parameter_name, kind, function=self.function, converter=converter, default=value, group=self.group)
Larry Hastingsbebf7352014-01-17 17:47:17 -08003474
3475 if parameter_name in self.function.parameters:
3476 fail("You can't have two parameters named " + repr(parameter_name) + "!")
Larry Hastings31826802013-10-19 00:09:25 -07003477 self.function.parameters[parameter_name] = p
3478
3479 def parse_converter(self, annotation):
3480 if isinstance(annotation, ast.Str):
3481 return annotation.s, True, {}
3482
3483 if isinstance(annotation, ast.Name):
3484 return annotation.id, False, {}
3485
Larry Hastings4a55fc52014-01-12 11:09:57 -08003486 if not isinstance(annotation, ast.Call):
3487 fail("Annotations must be either a name, a function call, or a string.")
Larry Hastings31826802013-10-19 00:09:25 -07003488
3489 name = annotation.func.id
3490 kwargs = {node.arg: ast.literal_eval(node.value) for node in annotation.keywords}
3491 return name, False, kwargs
3492
3493 def parse_special_symbol(self, symbol):
3494 if self.parameter_state == self.ps_seen_slash:
3495 fail("Function " + self.function.name + " specifies " + symbol + " after /, which is unsupported.")
3496
3497 if symbol == '*':
3498 if self.keyword_only:
3499 fail("Function " + self.function.name + " uses '*' more than once.")
3500 self.keyword_only = True
3501 elif symbol == '[':
3502 if self.parameter_state in (self.ps_start, self.ps_left_square_before):
3503 self.parameter_state = self.ps_left_square_before
3504 elif self.parameter_state in (self.ps_required, self.ps_group_after):
3505 self.parameter_state = self.ps_group_after
3506 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003507 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".b)")
Larry Hastings31826802013-10-19 00:09:25 -07003508 self.group += 1
3509 elif symbol == ']':
3510 if not self.group:
3511 fail("Function " + self.function.name + " has a ] without a matching [.")
3512 if not any(p.group == self.group for p in self.function.parameters.values()):
3513 fail("Function " + self.function.name + " has an empty group.\nAll groups must contain at least one parameter.")
3514 self.group -= 1
3515 if self.parameter_state in (self.ps_left_square_before, self.ps_group_before):
3516 self.parameter_state = self.ps_group_before
3517 elif self.parameter_state in (self.ps_group_after, self.ps_right_square_after):
3518 self.parameter_state = self.ps_right_square_after
3519 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003520 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".c)")
Larry Hastings31826802013-10-19 00:09:25 -07003521 elif symbol == '/':
Larry Hastingsc2047262014-01-25 20:43:29 -08003522 # ps_required and ps_optional are allowed here, that allows positional-only without option groups
Larry Hastings31826802013-10-19 00:09:25 -07003523 # to work (and have default values!)
Larry Hastingsc2047262014-01-25 20:43:29 -08003524 if (self.parameter_state not in (self.ps_required, self.ps_optional, self.ps_right_square_after, self.ps_group_before)) or self.group:
3525 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".d)")
Larry Hastings31826802013-10-19 00:09:25 -07003526 if self.keyword_only:
3527 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
3528 self.parameter_state = self.ps_seen_slash
3529 # fixup preceeding parameters
3530 for p in self.function.parameters.values():
Larry Hastings5c661892014-01-24 06:17:25 -08003531 if (p.kind != inspect.Parameter.POSITIONAL_OR_KEYWORD and not isinstance(p.converter, self_converter)):
Larry Hastings31826802013-10-19 00:09:25 -07003532 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
3533 p.kind = inspect.Parameter.POSITIONAL_ONLY
3534
3535 def state_parameter_docstring_start(self, line):
3536 self.parameter_docstring_indent = len(self.indent.margin)
3537 assert self.indent.depth == 3
3538 return self.next(self.state_parameter_docstring, line)
3539
3540 # every line of the docstring must start with at least F spaces,
3541 # where F > P.
3542 # these F spaces will be stripped.
3543 def state_parameter_docstring(self, line):
3544 stripped = line.strip()
3545 if stripped.startswith('#'):
3546 return
3547
3548 indent = self.indent.measure(line)
3549 if indent < self.parameter_docstring_indent:
3550 self.indent.infer(line)
3551 assert self.indent.depth < 3
3552 if self.indent.depth == 2:
3553 # back to a parameter
3554 return self.next(self.state_parameter, line)
3555 assert self.indent.depth == 1
3556 return self.next(self.state_function_docstring, line)
3557
3558 assert self.function.parameters
3559 last_parameter = next(reversed(list(self.function.parameters.values())))
3560
3561 new_docstring = last_parameter.docstring
3562
3563 if new_docstring:
3564 new_docstring += '\n'
3565 if stripped:
3566 new_docstring += self.indent.dedent(line)
3567
3568 last_parameter.docstring = new_docstring
3569
3570 # the final stanza of the DSL is the docstring.
3571 def state_function_docstring(self, line):
Larry Hastings31826802013-10-19 00:09:25 -07003572 if self.group:
3573 fail("Function " + self.function.name + " has a ] without a matching [.")
3574
3575 stripped = line.strip()
3576 if stripped.startswith('#'):
3577 return
3578
3579 new_docstring = self.function.docstring
3580 if new_docstring:
3581 new_docstring += "\n"
3582 if stripped:
3583 line = self.indent.dedent(line).rstrip()
3584 else:
3585 line = ''
3586 new_docstring += line
3587 self.function.docstring = new_docstring
3588
3589 def format_docstring(self):
3590 f = self.function
3591
Larry Hastings5c661892014-01-24 06:17:25 -08003592 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
3593 if new_or_init and not f.docstring:
3594 # don't render a docstring at all, no signature, nothing.
3595 return f.docstring
3596
Larry Hastings31826802013-10-19 00:09:25 -07003597 add, output = text_accumulator()
3598 parameters = list(f.parameters.values())
3599
3600 ##
3601 ## docstring first line
3602 ##
3603
Larry Hastings5c661892014-01-24 06:17:25 -08003604 if new_or_init:
Larry Hastings46258262014-01-22 03:05:49 -08003605 assert f.cls
3606 add(f.cls.name)
3607 else:
3608 add(f.name)
Larry Hastings31826802013-10-19 00:09:25 -07003609 add('(')
3610
3611 # populate "right_bracket_count" field for every parameter
Larry Hastings5c661892014-01-24 06:17:25 -08003612 assert parameters, "We should always have a self parameter. " + repr(f)
3613 assert isinstance(parameters[0].converter, self_converter)
3614 parameters[0].right_bracket_count = 0
3615 parameters_after_self = parameters[1:]
3616 if parameters_after_self:
Larry Hastings31826802013-10-19 00:09:25 -07003617 # for now, the only way Clinic supports positional-only parameters
Larry Hastings5c661892014-01-24 06:17:25 -08003618 # is if all of them are positional-only...
3619 #
3620 # ... except for self! self is always positional-only.
3621
3622 positional_only_parameters = [p.kind == inspect.Parameter.POSITIONAL_ONLY for p in parameters_after_self]
3623 if parameters_after_self[0].kind == inspect.Parameter.POSITIONAL_ONLY:
Larry Hastings31826802013-10-19 00:09:25 -07003624 assert all(positional_only_parameters)
3625 for p in parameters:
3626 p.right_bracket_count = abs(p.group)
3627 else:
3628 # don't put any right brackets around non-positional-only parameters, ever.
Larry Hastings5c661892014-01-24 06:17:25 -08003629 for p in parameters_after_self:
Larry Hastings31826802013-10-19 00:09:25 -07003630 p.right_bracket_count = 0
3631
3632 right_bracket_count = 0
3633
3634 def fix_right_bracket_count(desired):
3635 nonlocal right_bracket_count
3636 s = ''
3637 while right_bracket_count < desired:
3638 s += '['
3639 right_bracket_count += 1
3640 while right_bracket_count > desired:
3641 s += ']'
3642 right_bracket_count -= 1
3643 return s
3644
3645 added_star = False
3646 add_comma = False
3647
3648 for p in parameters:
Larry Hastings5c661892014-01-24 06:17:25 -08003649 if not p.converter.show_in_signature:
3650 continue
3651
Larry Hastings31826802013-10-19 00:09:25 -07003652 assert p.name
3653
3654 if p.is_keyword_only() and not added_star:
3655 added_star = True
3656 if add_comma:
3657 add(', ')
3658 add('*')
Larry Hastings5c661892014-01-24 06:17:25 -08003659 add_comma = True
Larry Hastings31826802013-10-19 00:09:25 -07003660
Larry Hastings5c661892014-01-24 06:17:25 -08003661 name = p.converter.signature_name or p.name
3662 a = [name]
Larry Hastings31826802013-10-19 00:09:25 -07003663 if p.converter.is_optional():
3664 a.append('=')
Larry Hastingsc4fe0922014-01-19 02:27:34 -08003665 value = p.converter.py_default
3666 if not value:
Larry Hastings66575782014-01-19 03:01:23 -08003667 value = repr(p.converter.default)
Larry Hastingsc4fe0922014-01-19 02:27:34 -08003668 a.append(value)
Larry Hastings31826802013-10-19 00:09:25 -07003669 s = fix_right_bracket_count(p.right_bracket_count)
3670 s += "".join(a)
3671 if add_comma:
3672 add(', ')
3673 add(s)
3674 add_comma = True
3675
3676 add(fix_right_bracket_count(0))
3677 add(')')
3678
Larry Hastings2a727912014-01-16 11:32:01 -08003679 # PEP 8 says:
3680 #
3681 # The Python standard library will not use function annotations
3682 # as that would result in a premature commitment to a particular
3683 # annotation style. Instead, the annotations are left for users
3684 # to discover and experiment with useful annotation styles.
3685 #
3686 # therefore this is commented out:
3687 #
3688 # if f.return_converter.py_default:
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003689 # add(' -> ')
Larry Hastings2a727912014-01-16 11:32:01 -08003690 # add(f.return_converter.py_default)
Larry Hastings31826802013-10-19 00:09:25 -07003691
3692 docstring_first_line = output()
3693
3694 # now fix up the places where the brackets look wrong
3695 docstring_first_line = docstring_first_line.replace(', ]', ',] ')
3696
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003697 # okay. now we're officially building the "parameters" section.
Larry Hastings31826802013-10-19 00:09:25 -07003698 # create substitution text for {parameters}
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003699 spacer_line = False
Larry Hastings31826802013-10-19 00:09:25 -07003700 for p in parameters:
3701 if not p.docstring.strip():
3702 continue
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003703 if spacer_line:
3704 add('\n')
3705 else:
3706 spacer_line = True
Larry Hastings31826802013-10-19 00:09:25 -07003707 add(" ")
3708 add(p.name)
3709 add('\n')
3710 add(textwrap.indent(rstrip_lines(p.docstring.rstrip()), " "))
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003711 parameters = output()
3712 if parameters:
3713 parameters += '\n'
Larry Hastings31826802013-10-19 00:09:25 -07003714
3715 ##
3716 ## docstring body
3717 ##
3718
3719 docstring = f.docstring.rstrip()
3720 lines = [line.rstrip() for line in docstring.split('\n')]
3721
3722 # Enforce the summary line!
3723 # The first line of a docstring should be a summary of the function.
3724 # It should fit on one line (80 columns? 79 maybe?) and be a paragraph
3725 # by itself.
3726 #
3727 # Argument Clinic enforces the following rule:
3728 # * either the docstring is empty,
3729 # * or it must have a summary line.
3730 #
3731 # Guido said Clinic should enforce this:
3732 # http://mail.python.org/pipermail/python-dev/2013-June/127110.html
3733
3734 if len(lines) >= 2:
3735 if lines[1]:
3736 fail("Docstring for " + f.full_name + " does not have a summary line!\n" +
3737 "Every non-blank function docstring must start with\n" +
3738 "a single line summary followed by an empty line.")
3739 elif len(lines) == 1:
3740 # the docstring is only one line right now--the summary line.
3741 # add an empty line after the summary line so we have space
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003742 # between it and the {parameters} we're about to add.
Larry Hastings31826802013-10-19 00:09:25 -07003743 lines.append('')
3744
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003745 parameters_marker_count = len(docstring.split('{parameters}')) - 1
3746 if parameters_marker_count > 1:
3747 fail('You may not specify {parameters} more than once in a docstring!')
3748
3749 if not parameters_marker_count:
3750 # insert after summary line
3751 lines.insert(2, '{parameters}')
3752
3753 # insert at front of docstring
3754 lines.insert(0, docstring_first_line)
Larry Hastings31826802013-10-19 00:09:25 -07003755
3756 docstring = "\n".join(lines)
3757
3758 add(docstring)
3759 docstring = output()
3760
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003761 docstring = linear_format(docstring, parameters=parameters)
Larry Hastings31826802013-10-19 00:09:25 -07003762 docstring = docstring.rstrip()
3763
3764 return docstring
3765
3766 def state_terminal(self, line):
3767 """
3768 Called when processing the block is done.
3769 """
3770 assert not line
3771
3772 if not self.function:
3773 return
3774
3775 if self.keyword_only:
3776 values = self.function.parameters.values()
3777 if not values:
3778 no_parameter_after_star = True
3779 else:
3780 last_parameter = next(reversed(list(values)))
3781 no_parameter_after_star = last_parameter.kind != inspect.Parameter.KEYWORD_ONLY
3782 if no_parameter_after_star:
3783 fail("Function " + self.function.name + " specifies '*' without any parameters afterwards.")
3784
3785 # remove trailing whitespace from all parameter docstrings
3786 for name, value in self.function.parameters.items():
3787 if not value:
3788 continue
3789 value.docstring = value.docstring.rstrip()
3790
3791 self.function.docstring = self.format_docstring()
3792
3793
Larry Hastings5c661892014-01-24 06:17:25 -08003794
3795
Larry Hastings31826802013-10-19 00:09:25 -07003796# maps strings to callables.
3797# the callable should return an object
3798# that implements the clinic parser
3799# interface (__init__ and parse).
3800#
3801# example parsers:
3802# "clinic", handles the Clinic DSL
3803# "python", handles running Python code
3804#
3805parsers = {'clinic' : DSLParser, 'python': PythonParser}
3806
3807
3808clinic = None
3809
3810
3811def main(argv):
3812 import sys
3813
3814 if sys.version_info.major < 3 or sys.version_info.minor < 3:
3815 sys.exit("Error: clinic.py requires Python 3.3 or greater.")
3816
3817 import argparse
3818 cmdline = argparse.ArgumentParser()
3819 cmdline.add_argument("-f", "--force", action='store_true')
3820 cmdline.add_argument("-o", "--output", type=str)
Larry Hastings5c661892014-01-24 06:17:25 -08003821 cmdline.add_argument("-v", "--verbose", action='store_true')
Larry Hastings31826802013-10-19 00:09:25 -07003822 cmdline.add_argument("--converters", action='store_true')
Larry Hastingsdcd340e2013-11-23 14:58:45 -08003823 cmdline.add_argument("--make", action='store_true')
Larry Hastings31826802013-10-19 00:09:25 -07003824 cmdline.add_argument("filename", type=str, nargs="*")
3825 ns = cmdline.parse_args(argv)
3826
3827 if ns.converters:
3828 if ns.filename:
3829 print("Usage error: can't specify --converters and a filename at the same time.")
3830 print()
3831 cmdline.print_usage()
3832 sys.exit(-1)
3833 converters = []
3834 return_converters = []
3835 ignored = set("""
3836 add_c_converter
3837 add_c_return_converter
3838 add_default_legacy_c_converter
3839 add_legacy_c_converter
3840 """.strip().split())
3841 module = globals()
3842 for name in module:
3843 for suffix, ids in (
3844 ("_return_converter", return_converters),
3845 ("_converter", converters),
3846 ):
3847 if name in ignored:
3848 continue
3849 if name.endswith(suffix):
3850 ids.append((name, name[:-len(suffix)]))
3851 break
3852 print()
3853
3854 print("Legacy converters:")
3855 legacy = sorted(legacy_converters)
3856 print(' ' + ' '.join(c for c in legacy if c[0].isupper()))
3857 print(' ' + ' '.join(c for c in legacy if c[0].islower()))
3858 print()
3859
3860 for title, attribute, ids in (
3861 ("Converters", 'converter_init', converters),
3862 ("Return converters", 'return_converter_init', return_converters),
3863 ):
3864 print(title + ":")
3865 longest = -1
3866 for name, short_name in ids:
3867 longest = max(longest, len(short_name))
3868 for name, short_name in sorted(ids, key=lambda x: x[1].lower()):
3869 cls = module[name]
3870 callable = getattr(cls, attribute, None)
3871 if not callable:
3872 continue
3873 signature = inspect.signature(callable)
3874 parameters = []
3875 for parameter_name, parameter in signature.parameters.items():
3876 if parameter.kind == inspect.Parameter.KEYWORD_ONLY:
3877 if parameter.default != inspect.Parameter.empty:
3878 s = '{}={!r}'.format(parameter_name, parameter.default)
3879 else:
3880 s = parameter_name
3881 parameters.append(s)
3882 print(' {}({})'.format(short_name, ', '.join(parameters)))
Larry Hastings31826802013-10-19 00:09:25 -07003883 print()
Larry Hastings2a727912014-01-16 11:32:01 -08003884 print("All converters also accept (c_default=None, py_default=None, annotation=None).")
3885 print("All return converters also accept (py_default=None).")
Larry Hastings31826802013-10-19 00:09:25 -07003886 sys.exit(0)
3887
Larry Hastingsdcd340e2013-11-23 14:58:45 -08003888 if ns.make:
3889 if ns.output or ns.filename:
3890 print("Usage error: can't use -o or filenames with --make.")
3891 print()
3892 cmdline.print_usage()
3893 sys.exit(-1)
3894 for root, dirs, files in os.walk('.'):
Larry Hastings5c661892014-01-24 06:17:25 -08003895 for rcs_dir in ('.svn', '.git', '.hg', 'build'):
Larry Hastingsdcd340e2013-11-23 14:58:45 -08003896 if rcs_dir in dirs:
3897 dirs.remove(rcs_dir)
3898 for filename in files:
Larry Hastings5c661892014-01-24 06:17:25 -08003899 if not (filename.endswith('.c') or filename.endswith('.h')):
Larry Hastingsdcd340e2013-11-23 14:58:45 -08003900 continue
3901 path = os.path.join(root, filename)
Larry Hastings5c661892014-01-24 06:17:25 -08003902 if ns.verbose:
3903 print(path)
Larry Hastingsdcd340e2013-11-23 14:58:45 -08003904 parse_file(path, verify=not ns.force)
3905 return
3906
Larry Hastings31826802013-10-19 00:09:25 -07003907 if not ns.filename:
3908 cmdline.print_usage()
3909 sys.exit(-1)
3910
3911 if ns.output and len(ns.filename) > 1:
3912 print("Usage error: can't use -o with multiple filenames.")
3913 print()
3914 cmdline.print_usage()
3915 sys.exit(-1)
3916
3917 for filename in ns.filename:
Larry Hastings5c661892014-01-24 06:17:25 -08003918 if ns.verbose:
3919 print(filename)
Larry Hastings31826802013-10-19 00:09:25 -07003920 parse_file(filename, output=ns.output, verify=not ns.force)
3921
3922
3923if __name__ == "__main__":
3924 sys.exit(main(sys.argv[1:]))