blob: 86df329a726b1ab089be43a20f7895153bc385ff [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
19import re
20import shlex
21import sys
22import tempfile
23import textwrap
24
Larry Hastings31826802013-10-19 00:09:25 -070025# TODO:
Larry Hastings31826802013-10-19 00:09:25 -070026#
27# soon:
28#
29# * allow mixing any two of {positional-only, positional-or-keyword,
30# keyword-only}
31# * dict constructor uses positional-only and keyword-only
32# * max and min use positional only with an optional group
33# and keyword-only
34#
Larry Hastings31826802013-10-19 00:09:25 -070035
Larry Hastingsebdcb502013-11-23 14:54:00 -080036version = '1'
37
Larry Hastings31826802013-10-19 00:09:25 -070038_empty = inspect._empty
39_void = inspect._void
40
Larry Hastings4a55fc52014-01-12 11:09:57 -080041NoneType = type(None)
Larry Hastings31826802013-10-19 00:09:25 -070042
43class Unspecified:
44 def __repr__(self):
45 return '<Unspecified>'
46
47unspecified = Unspecified()
48
49
50class Null:
51 def __repr__(self):
52 return '<Null>'
53
54NULL = Null()
55
56
57def _text_accumulator():
58 text = []
59 def output():
60 s = ''.join(text)
61 text.clear()
62 return s
63 return text, text.append, output
64
65
66def text_accumulator():
67 """
68 Creates a simple text accumulator / joiner.
69
70 Returns a pair of callables:
71 append, output
72 "append" appends a string to the accumulator.
73 "output" returns the contents of the accumulator
74 joined together (''.join(accumulator)) and
75 empties the accumulator.
76 """
77 text, append, output = _text_accumulator()
78 return append, output
79
80
81def fail(*args, filename=None, line_number=None):
82 joined = " ".join([str(a) for a in args])
83 add, output = text_accumulator()
84 add("Error")
85 if clinic:
86 if filename is None:
87 filename = clinic.filename
88 if clinic.block_parser and (line_number is None):
89 line_number = clinic.block_parser.line_number
90 if filename is not None:
91 add(' in file "' + filename + '"')
92 if line_number is not None:
93 add(" on line " + str(line_number))
94 add(':\n')
95 add(joined)
96 print(output())
97 sys.exit(-1)
98
99
100
101def quoted_for_c_string(s):
102 for old, new in (
103 ('"', '\\"'),
104 ("'", "\\'"),
105 ):
106 s = s.replace(old, new)
107 return s
108
Larry Hastingsdfcd4672013-10-27 02:49:39 -0700109is_legal_c_identifier = re.compile('^[A-Za-z_][A-Za-z0-9_]*$').match
110
111def is_legal_py_identifier(s):
112 return all(is_legal_c_identifier(field) for field in s.split('.'))
113
Larry Hastings8666e652014-01-12 14:12:59 -0800114# though it's called c_keywords, really it's a list of parameter names
115# that are okay in Python but aren't a good idea in C. so if they're used
116# Argument Clinic will add "_value" to the end of the name in C.
117# (We added "args", "type", "module", "self", "cls", and "null"
118# just to be safe, even though they're not C keywords.)
Larry Hastings31826802013-10-19 00:09:25 -0700119c_keywords = set("""
Larry Hastings8666e652014-01-12 14:12:59 -0800120args asm auto break case char cls const continue default do double
Larry Hastingsed4a1c52013-11-18 09:32:13 -0800121else enum extern float for goto if inline int long module null
122register return self short signed sizeof static struct switch
Larry Hastings8666e652014-01-12 14:12:59 -0800123type typedef typeof union unsigned void volatile while
Larry Hastings31826802013-10-19 00:09:25 -0700124""".strip().split())
125
Larry Hastingsdfcd4672013-10-27 02:49:39 -0700126def ensure_legal_c_identifier(s):
127 # for now, just complain if what we're given isn't legal
128 if not is_legal_c_identifier(s):
129 fail("Illegal C identifier: {}".format(s))
130 # but if we picked a C keyword, pick something else
Larry Hastings31826802013-10-19 00:09:25 -0700131 if s in c_keywords:
132 return s + "_value"
133 return s
134
135def rstrip_lines(s):
136 text, add, output = _text_accumulator()
137 for line in s.split('\n'):
138 add(line.rstrip())
139 add('\n')
140 text.pop()
141 return output()
142
143def linear_format(s, **kwargs):
144 """
145 Perform str.format-like substitution, except:
146 * The strings substituted must be on lines by
147 themselves. (This line is the "source line".)
148 * If the substitution text is empty, the source line
149 is removed in the output.
150 * If the substitution text is not empty:
151 * Each line of the substituted text is indented
152 by the indent of the source line.
153 * A newline will be added to the end.
154 """
155
156 add, output = text_accumulator()
157 for line in s.split('\n'):
158 indent, curly, trailing = line.partition('{')
159 if not curly:
160 add(line)
161 add('\n')
162 continue
163
164 name, curl, trailing = trailing.partition('}')
165 if not curly or name not in kwargs:
166 add(line)
167 add('\n')
168 continue
169
170 if trailing:
171 fail("Text found after {" + name + "} block marker! It must be on a line by itself.")
172 if indent.strip():
173 fail("Non-whitespace characters found before {" + name + "} block marker! It must be on a line by itself.")
174
175 value = kwargs[name]
176 if not value:
177 continue
178
179 value = textwrap.indent(rstrip_lines(value), indent)
180 add(value)
181 add('\n')
182
183 return output()[:-1]
184
Larry Hastingsebdcb502013-11-23 14:54:00 -0800185def version_splitter(s):
186 """Splits a version string into a tuple of integers.
187
188 The following ASCII characters are allowed, and employ
189 the following conversions:
190 a -> -3
191 b -> -2
192 c -> -1
193 (This permits Python-style version strings such as "1.4b3".)
194 """
195 version = []
196 accumulator = []
197 def flush():
198 if not accumulator:
199 raise ValueError('Malformed version string: ' + repr(s))
200 version.append(int(''.join(accumulator)))
201 accumulator.clear()
202
203 for c in s:
204 if c.isdigit():
205 accumulator.append(c)
206 elif c == '.':
207 flush()
208 elif c in 'abc':
209 flush()
210 version.append('abc'.index(c) - 3)
211 else:
212 raise ValueError('Illegal character ' + repr(c) + ' in version string ' + repr(s))
213 flush()
214 return tuple(version)
215
216def version_comparitor(version1, version2):
217 iterator = itertools.zip_longest(version_splitter(version1), version_splitter(version2), fillvalue=0)
218 for i, (a, b) in enumerate(iterator):
219 if a < b:
220 return -1
221 if a > b:
222 return 1
223 return 0
224
Larry Hastings31826802013-10-19 00:09:25 -0700225
226class CRenderData:
227 def __init__(self):
228
229 # The C statements to declare variables.
230 # Should be full lines with \n eol characters.
231 self.declarations = []
232
233 # The C statements required to initialize the variables before the parse call.
234 # Should be full lines with \n eol characters.
235 self.initializers = []
236
237 # The entries for the "keywords" array for PyArg_ParseTuple.
238 # Should be individual strings representing the names.
239 self.keywords = []
240
241 # The "format units" for PyArg_ParseTuple.
242 # Should be individual strings that will get
243 self.format_units = []
244
245 # The varargs arguments for PyArg_ParseTuple.
246 self.parse_arguments = []
247
248 # The parameter declarations for the impl function.
249 self.impl_parameters = []
250
251 # The arguments to the impl function at the time it's called.
252 self.impl_arguments = []
253
254 # For return converters: the name of the variable that
255 # should receive the value returned by the impl.
256 self.return_value = "return_value"
257
258 # For return converters: the code to convert the return
259 # value from the parse function. This is also where
260 # you should check the _return_value for errors, and
261 # "goto exit" if there are any.
262 self.return_conversion = []
263
264 # The C statements required to clean up after the impl call.
265 self.cleanup = []
266
267
268class Language(metaclass=abc.ABCMeta):
269
270 start_line = ""
271 body_prefix = ""
272 stop_line = ""
273 checksum_line = ""
274
275 @abc.abstractmethod
276 def render(self, block):
277 pass
278
279 def validate(self):
280 def assert_only_one(field, token='dsl_name'):
281 line = getattr(self, field)
282 token = '{' + token + '}'
283 if len(line.split(token)) != 2:
284 fail(self.__class__.__name__ + " " + field + " must contain " + token + " exactly once!")
285 assert_only_one('start_line')
286 assert_only_one('stop_line')
287 assert_only_one('checksum_line')
288 assert_only_one('checksum_line', 'checksum')
289
290 if len(self.body_prefix.split('{dsl_name}')) >= 3:
291 fail(self.__class__.__name__ + " body_prefix may contain " + token + " once at most!")
292
293
294
295class PythonLanguage(Language):
296
297 language = 'Python'
Larry Hastings61272b72014-01-07 12:41:53 -0800298 start_line = "#/*[{dsl_name} input]"
Larry Hastings31826802013-10-19 00:09:25 -0700299 body_prefix = "#"
Larry Hastings61272b72014-01-07 12:41:53 -0800300 stop_line = "#[{dsl_name} start generated code]*/"
301 checksum_line = "#/*[{dsl_name} end generated code: checksum={checksum}]*/"
Larry Hastings31826802013-10-19 00:09:25 -0700302
303
304def permute_left_option_groups(l):
305 """
306 Given [1, 2, 3], should yield:
307 ()
308 (3,)
309 (2, 3)
310 (1, 2, 3)
311 """
312 yield tuple()
313 accumulator = []
314 for group in reversed(l):
315 accumulator = list(group) + accumulator
316 yield tuple(accumulator)
317
318
319def permute_right_option_groups(l):
320 """
321 Given [1, 2, 3], should yield:
322 ()
323 (1,)
324 (1, 2)
325 (1, 2, 3)
326 """
327 yield tuple()
328 accumulator = []
329 for group in l:
330 accumulator.extend(group)
331 yield tuple(accumulator)
332
333
334def permute_optional_groups(left, required, right):
335 """
336 Generator function that computes the set of acceptable
337 argument lists for the provided iterables of
338 argument groups. (Actually it generates a tuple of tuples.)
339
340 Algorithm: prefer left options over right options.
341
342 If required is empty, left must also be empty.
343 """
344 required = tuple(required)
345 result = []
346
347 if not required:
348 assert not left
349
350 accumulator = []
351 counts = set()
352 for r in permute_right_option_groups(right):
353 for l in permute_left_option_groups(left):
354 t = l + required + r
355 if len(t) in counts:
356 continue
357 counts.add(len(t))
358 accumulator.append(t)
359
360 accumulator.sort(key=len)
361 return tuple(accumulator)
362
363
364class CLanguage(Language):
365
Larry Hastings61272b72014-01-07 12:41:53 -0800366 body_prefix = "#"
Larry Hastings31826802013-10-19 00:09:25 -0700367 language = 'C'
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 def render(self, signatures):
374 function = None
375 for o in signatures:
376 if isinstance(o, Function):
377 if function:
378 fail("You may specify at most one function per block.\nFound a block containing at least two:\n\t" + repr(function) + " and " + repr(o))
379 function = o
380 return self.render_function(function)
381
382 def docstring_for_c_string(self, f):
383 text, add, output = _text_accumulator()
384 # turn docstring into a properly quoted C string
385 for line in f.docstring.split('\n'):
386 add('"')
387 add(quoted_for_c_string(line))
388 add('\\n"\n')
389
390 text.pop()
391 add('"')
392 return ''.join(text)
393
394 impl_prototype_template = "{c_basename}_impl({impl_parameters})"
395
396 @staticmethod
397 def template_base(*args):
Larry Hastings8666e652014-01-12 14:12:59 -0800398 # HACK suppress methoddef define for METHOD_NEW and METHOD_INIT
399 base = """
Larry Hastings31826802013-10-19 00:09:25 -0700400PyDoc_STRVAR({c_basename}__doc__,
401{docstring});
Larry Hastings8666e652014-01-12 14:12:59 -0800402"""
Larry Hastings31826802013-10-19 00:09:25 -0700403
Larry Hastings8666e652014-01-12 14:12:59 -0800404 if args[-1] == None:
405 return base
406
407 flags = '|'.join(f for f in args if f)
408 return base + """
Larry Hastings31826802013-10-19 00:09:25 -0700409#define {methoddef_name} \\
Larry Hastingsebdcb502013-11-23 14:54:00 -0800410 {{"{name}", (PyCFunction){c_basename}, {methoddef_flags}, {c_basename}__doc__}},
411""".replace('{methoddef_flags}', flags)
Larry Hastings31826802013-10-19 00:09:25 -0700412
Larry Hastingsebdcb502013-11-23 14:54:00 -0800413 def meth_noargs_template(self, methoddef_flags=""):
414 return self.template_base("METH_NOARGS", methoddef_flags) + """
Larry Hastings31826802013-10-19 00:09:25 -0700415static {impl_return_type}
416{impl_prototype};
417
418static PyObject *
Larry Hastings3cceb382014-01-04 11:09:09 -0800419{c_basename}({self_type}{self_name}, PyObject *Py_UNUSED(ignored))
Larry Hastings31826802013-10-19 00:09:25 -0700420{{
421 PyObject *return_value = NULL;
422 {declarations}
423 {initializers}
424
425 {return_value} = {c_basename}_impl({impl_arguments});
426 {return_conversion}
427
428{exit_label}
429 {cleanup}
430 return return_value;
431}}
432
433static {impl_return_type}
434{impl_prototype}
435"""
436
Larry Hastingsebdcb502013-11-23 14:54:00 -0800437 def meth_o_template(self, methoddef_flags=""):
438 return self.template_base("METH_O", methoddef_flags) + """
Larry Hastings31826802013-10-19 00:09:25 -0700439static PyObject *
440{c_basename}({impl_parameters})
441"""
442
Larry Hastingsebdcb502013-11-23 14:54:00 -0800443 def meth_o_return_converter_template(self, methoddef_flags=""):
444 return self.template_base("METH_O", methoddef_flags) + """
Larry Hastings31826802013-10-19 00:09:25 -0700445static {impl_return_type}
446{impl_prototype};
447
448static PyObject *
449{c_basename}({impl_parameters})
450{{
451 PyObject *return_value = NULL;
452 {declarations}
453 {initializers}
454 _return_value = {c_basename}_impl({impl_arguments});
455 {return_conversion}
456
457{exit_label}
458 {cleanup}
459 return return_value;
460}}
461
462static {impl_return_type}
463{impl_prototype}
464"""
465
Larry Hastingsebdcb502013-11-23 14:54:00 -0800466 def option_group_template(self, methoddef_flags=""):
467 return self.template_base("METH_VARARGS", methoddef_flags) + """
Larry Hastings31826802013-10-19 00:09:25 -0700468static {impl_return_type}
469{impl_prototype};
470
471static PyObject *
Larry Hastingsebdcb502013-11-23 14:54:00 -0800472{c_basename}({self_type}{self_name}, PyObject *args)
Larry Hastings31826802013-10-19 00:09:25 -0700473{{
474 PyObject *return_value = NULL;
475 {declarations}
476 {initializers}
477
478 {option_group_parsing}
479 {return_value} = {c_basename}_impl({impl_arguments});
480 {return_conversion}
481
482{exit_label}
483 {cleanup}
484 return return_value;
485}}
486
487static {impl_return_type}
488{impl_prototype}
489"""
490
Larry Hastingsebdcb502013-11-23 14:54:00 -0800491 def keywords_template(self, methoddef_flags=""):
492 return self.template_base("METH_VARARGS|METH_KEYWORDS", methoddef_flags) + """
Larry Hastings31826802013-10-19 00:09:25 -0700493static {impl_return_type}
494{impl_prototype};
495
496static PyObject *
Larry Hastingsebdcb502013-11-23 14:54:00 -0800497{c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
Larry Hastings31826802013-10-19 00:09:25 -0700498{{
499 PyObject *return_value = NULL;
500 static char *_keywords[] = {{{keywords}, NULL}};
501 {declarations}
502 {initializers}
503
504 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
505 "{format_units}:{name}", _keywords,
506 {parse_arguments}))
507 goto exit;
508 {return_value} = {c_basename}_impl({impl_arguments});
509 {return_conversion}
510
511{exit_label}
512 {cleanup}
513 return return_value;
514}}
515
516static {impl_return_type}
517{impl_prototype}
518"""
519
Larry Hastingsebdcb502013-11-23 14:54:00 -0800520 def positional_only_template(self, methoddef_flags=""):
521 return self.template_base("METH_VARARGS", methoddef_flags) + """
Larry Hastings31826802013-10-19 00:09:25 -0700522static {impl_return_type}
523{impl_prototype};
524
525static PyObject *
Larry Hastingsebdcb502013-11-23 14:54:00 -0800526{c_basename}({self_type}{self_name}, PyObject *args)
Larry Hastings31826802013-10-19 00:09:25 -0700527{{
528 PyObject *return_value = NULL;
529 {declarations}
530 {initializers}
531
532 if (!PyArg_ParseTuple(args,
533 "{format_units}:{name}",
534 {parse_arguments}))
535 goto exit;
536 {return_value} = {c_basename}_impl({impl_arguments});
537 {return_conversion}
538
539{exit_label}
540 {cleanup}
541 return return_value;
542}}
543
544static {impl_return_type}
545{impl_prototype}
546"""
547
548 @staticmethod
549 def group_to_variable_name(group):
550 adjective = "left_" if group < 0 else "right_"
551 return "group_" + adjective + str(abs(group))
552
553 def render_option_group_parsing(self, f, template_dict):
554 # positional only, grouped, optional arguments!
555 # can be optional on the left or right.
556 # here's an example:
557 #
558 # [ [ [ A1 A2 ] B1 B2 B3 ] C1 C2 ] D1 D2 D3 [ E1 E2 E3 [ F1 F2 F3 ] ]
559 #
560 # Here group D are required, and all other groups are optional.
561 # (Group D's "group" is actually None.)
562 # We can figure out which sets of arguments we have based on
563 # how many arguments are in the tuple.
564 #
565 # Note that you need to count up on both sides. For example,
566 # you could have groups C+D, or C+D+E, or C+D+E+F.
567 #
568 # What if the number of arguments leads us to an ambiguous result?
569 # Clinic prefers groups on the left. So in the above example,
570 # five arguments would map to B+C, not C+D.
571
572 add, output = text_accumulator()
573 parameters = list(f.parameters.values())
574
575 groups = []
576 group = None
577 left = []
578 right = []
579 required = []
580 last = unspecified
581
582 for p in parameters:
583 group_id = p.group
584 if group_id != last:
585 last = group_id
586 group = []
587 if group_id < 0:
588 left.append(group)
589 elif group_id == 0:
590 group = required
591 else:
592 right.append(group)
593 group.append(p)
594
595 count_min = sys.maxsize
596 count_max = -1
597
598 add("switch (PyTuple_Size(args)) {{\n")
599 for subset in permute_optional_groups(left, required, right):
600 count = len(subset)
601 count_min = min(count_min, count)
602 count_max = max(count_max, count)
603
Larry Hastings583baa82014-01-12 08:49:30 -0800604 if count == 0:
605 add(""" case 0:
606 break;
607""")
608 continue
609
Larry Hastings31826802013-10-19 00:09:25 -0700610 group_ids = {p.group for p in subset} # eliminate duplicates
611 d = {}
612 d['count'] = count
613 d['name'] = f.name
614 d['groups'] = sorted(group_ids)
615 d['format_units'] = "".join(p.converter.format_unit for p in subset)
616
617 parse_arguments = []
618 for p in subset:
619 p.converter.parse_argument(parse_arguments)
620 d['parse_arguments'] = ", ".join(parse_arguments)
621
622 group_ids.discard(0)
623 lines = [self.group_to_variable_name(g) + " = 1;" for g in group_ids]
624 lines = "\n".join(lines)
625
626 s = """
627 case {count}:
628 if (!PyArg_ParseTuple(args, "{format_units}:{name}", {parse_arguments}))
629 return NULL;
630 {group_booleans}
631 break;
632"""[1:]
633 s = linear_format(s, group_booleans=lines)
634 s = s.format_map(d)
635 add(s)
636
637 add(" default:\n")
638 s = ' PyErr_SetString(PyExc_TypeError, "{} requires {} to {} arguments");\n'
639 add(s.format(f.full_name, count_min, count_max))
640 add(' return NULL;\n')
641 add("}}")
642 template_dict['option_group_parsing'] = output()
643
644 def render_function(self, f):
645 if not f:
646 return ""
647
648 add, output = text_accumulator()
649 data = CRenderData()
650
Larry Hastings31826802013-10-19 00:09:25 -0700651 parameters = list(f.parameters.values())
652 converters = [p.converter for p in parameters]
653
654 template_dict = {}
655
656 full_name = f.full_name
657 template_dict['full_name'] = full_name
658
659 name = full_name.rpartition('.')[2]
660 template_dict['name'] = name
661
Larry Hastings8666e652014-01-12 14:12:59 -0800662 if f.c_basename:
663 c_basename = f.c_basename
664 else:
665 fields = full_name.split(".")
666 if fields[-1] == '__new__':
667 fields.pop()
668 c_basename = "_".join(fields)
Larry Hastings31826802013-10-19 00:09:25 -0700669 template_dict['c_basename'] = c_basename
670
671 methoddef_name = "{}_METHODDEF".format(c_basename.upper())
672 template_dict['methoddef_name'] = methoddef_name
673
674 template_dict['docstring'] = self.docstring_for_c_string(f)
675
Larry Hastings31826802013-10-19 00:09:25 -0700676 positional = has_option_groups = False
677
678 if parameters:
679 last_group = 0
680
681 for p in parameters:
682 c = p.converter
683
684 # insert group variable
685 group = p.group
686 if last_group != group:
687 last_group = group
688 if group:
689 group_name = self.group_to_variable_name(group)
690 data.impl_arguments.append(group_name)
691 data.declarations.append("int " + group_name + " = 0;")
692 data.impl_parameters.append("int " + group_name)
693 has_option_groups = True
694 c.render(p, data)
695
696 positional = parameters[-1].kind == inspect.Parameter.POSITIONAL_ONLY
Larry Hastings4a55fc52014-01-12 11:09:57 -0800697 if has_option_groups and (not positional):
698 fail("You cannot use optional groups ('[' and ']')\nunless all parameters are positional-only ('/').")
Larry Hastings31826802013-10-19 00:09:25 -0700699
Larry Hastingsebdcb502013-11-23 14:54:00 -0800700 # now insert our "self" (or whatever) parameters
701 # (we deliberately don't call render on self converters)
702 stock_self = self_converter('self', f)
703 template_dict['self_name'] = stock_self.name
704 template_dict['self_type'] = stock_self.type
705 data.impl_parameters.insert(0, f.self_converter.type + ("" if f.self_converter.type.endswith('*') else " ") + f.self_converter.name)
706 if f.self_converter.type != stock_self.type:
707 self_cast = '(' + f.self_converter.type + ')'
708 else:
709 self_cast = ''
710 data.impl_arguments.insert(0, self_cast + stock_self.name)
711
Larry Hastings31826802013-10-19 00:09:25 -0700712 f.return_converter.render(f, data)
713 template_dict['impl_return_type'] = f.return_converter.type
714
715 template_dict['declarations'] = "\n".join(data.declarations)
716 template_dict['initializers'] = "\n\n".join(data.initializers)
717 template_dict['keywords'] = '"' + '", "'.join(data.keywords) + '"'
718 template_dict['format_units'] = ''.join(data.format_units)
719 template_dict['parse_arguments'] = ', '.join(data.parse_arguments)
720 template_dict['impl_parameters'] = ", ".join(data.impl_parameters)
721 template_dict['impl_arguments'] = ", ".join(data.impl_arguments)
722 template_dict['return_conversion'] = "".join(data.return_conversion).rstrip()
723 template_dict['cleanup'] = "".join(data.cleanup)
724 template_dict['return_value'] = data.return_value
725
726 template_dict['impl_prototype'] = self.impl_prototype_template.format_map(template_dict)
727
728 default_return_converter = (not f.return_converter or
729 f.return_converter.type == 'PyObject *')
730
731 if not parameters:
Larry Hastings3cceb382014-01-04 11:09:09 -0800732 template = self.meth_noargs_template(f.methoddef_flags)
Larry Hastings31826802013-10-19 00:09:25 -0700733 elif (len(parameters) == 1 and
734 parameters[0].kind == inspect.Parameter.POSITIONAL_ONLY and
735 not converters[0].is_optional() and
736 isinstance(converters[0], object_converter) and
737 converters[0].format_unit == 'O'):
738 if default_return_converter:
Larry Hastingsebdcb502013-11-23 14:54:00 -0800739 template = self.meth_o_template(f.methoddef_flags)
Larry Hastings31826802013-10-19 00:09:25 -0700740 else:
741 # HACK
742 # we're using "impl_parameters" for the
743 # non-impl function, because that works
744 # better for METH_O. but that means we
Larry Hastingsebdcb502013-11-23 14:54:00 -0800745 # must supress actually declaring the
Larry Hastings31826802013-10-19 00:09:25 -0700746 # impl's parameters as variables in the
747 # non-impl. but since it's METH_O, we
Larry Hastingsebdcb502013-11-23 14:54:00 -0800748 # only have one anyway, so
749 # we don't have any problem finding it.
Larry Hastings31826802013-10-19 00:09:25 -0700750 declarations_copy = list(data.declarations)
751 before, pyobject, after = declarations_copy[0].partition('PyObject *')
752 assert not before, "hack failed, see comment"
753 assert pyobject, "hack failed, see comment"
754 assert after and after[0].isalpha(), "hack failed, see comment"
755 del declarations_copy[0]
756 template_dict['declarations'] = "\n".join(declarations_copy)
Larry Hastingsebdcb502013-11-23 14:54:00 -0800757 template = self.meth_o_return_converter_template(f.methoddef_flags)
Larry Hastings31826802013-10-19 00:09:25 -0700758 elif has_option_groups:
759 self.render_option_group_parsing(f, template_dict)
Larry Hastingsebdcb502013-11-23 14:54:00 -0800760 template = self.option_group_template(f.methoddef_flags)
Larry Hastings31826802013-10-19 00:09:25 -0700761 template = linear_format(template,
762 option_group_parsing=template_dict['option_group_parsing'])
763 elif positional:
Larry Hastingsebdcb502013-11-23 14:54:00 -0800764 template = self.positional_only_template(f.methoddef_flags)
Larry Hastings31826802013-10-19 00:09:25 -0700765 else:
Larry Hastingsebdcb502013-11-23 14:54:00 -0800766 template = self.keywords_template(f.methoddef_flags)
Larry Hastings31826802013-10-19 00:09:25 -0700767
768 template = linear_format(template,
769 declarations=template_dict['declarations'],
770 return_conversion=template_dict['return_conversion'],
771 initializers=template_dict['initializers'],
772 cleanup=template_dict['cleanup'],
773 )
774
775 # Only generate the "exit:" label
776 # if we have any gotos
777 need_exit_label = "goto exit;" in template
778 template = linear_format(template,
779 exit_label="exit:" if need_exit_label else ''
780 )
781
782 return template.format_map(template_dict)
783
784
785@contextlib.contextmanager
786def OverrideStdioWith(stdout):
787 saved_stdout = sys.stdout
788 sys.stdout = stdout
789 try:
790 yield
791 finally:
792 assert sys.stdout is stdout
793 sys.stdout = saved_stdout
794
795
796def create_regex(before, after):
797 """Create an re object for matching marker lines."""
798 pattern = r'^{}(\w+){}$'
799 return re.compile(pattern.format(re.escape(before), re.escape(after)))
800
801
802class Block:
803 r"""
804 Represents a single block of text embedded in
805 another file. If dsl_name is None, the block represents
806 verbatim text, raw original text from the file, in
807 which case "input" will be the only non-false member.
808 If dsl_name is not None, the block represents a Clinic
809 block.
810
811 input is always str, with embedded \n characters.
812 input represents the original text from the file;
813 if it's a Clinic block, it is the original text with
814 the body_prefix and redundant leading whitespace removed.
815
816 dsl_name is either str or None. If str, it's the text
817 found on the start line of the block between the square
818 brackets.
819
820 signatures is either list or None. If it's a list,
821 it may only contain clinic.Module, clinic.Class, and
822 clinic.Function objects. At the moment it should
823 contain at most one of each.
824
825 output is either str or None. If str, it's the output
826 from this block, with embedded '\n' characters.
827
828 indent is either str or None. It's the leading whitespace
829 that was found on every line of input. (If body_prefix is
830 not empty, this is the indent *after* removing the
831 body_prefix.)
832
833 preindent is either str or None. It's the whitespace that
834 was found in front of every line of input *before* the
835 "body_prefix" (see the Language object). If body_prefix
836 is empty, preindent must always be empty too.
837
838 To illustrate indent and preindent: Assume that '_'
839 represents whitespace. If the block processed was in a
840 Python file, and looked like this:
841 ____#/*[python]
842 ____#__for a in range(20):
843 ____#____print(a)
844 ____#[python]*/
845 "preindent" would be "____" and "indent" would be "__".
846
847 """
848 def __init__(self, input, dsl_name=None, signatures=None, output=None, indent='', preindent=''):
849 assert isinstance(input, str)
850 self.input = input
851 self.dsl_name = dsl_name
852 self.signatures = signatures or []
853 self.output = output
854 self.indent = indent
855 self.preindent = preindent
856
857
858class BlockParser:
859 """
860 Block-oriented parser for Argument Clinic.
861 Iterator, yields Block objects.
862 """
863
864 def __init__(self, input, language, *, verify=True):
865 """
866 "input" should be a str object
867 with embedded \n characters.
868
869 "language" should be a Language object.
870 """
871 language.validate()
872
873 self.input = collections.deque(reversed(input.splitlines(keepends=True)))
874 self.block_start_line_number = self.line_number = 0
875
876 self.language = language
877 before, _, after = language.start_line.partition('{dsl_name}')
878 assert _ == '{dsl_name}'
879 self.start_re = create_regex(before, after)
880 self.verify = verify
881 self.last_checksum_re = None
882 self.last_dsl_name = None
883 self.dsl_name = None
884
885 def __iter__(self):
886 return self
887
888 def __next__(self):
889 if not self.input:
890 raise StopIteration
891
892 if self.dsl_name:
893 return_value = self.parse_clinic_block(self.dsl_name)
894 self.dsl_name = None
895 return return_value
896 return self.parse_verbatim_block()
897
898 def is_start_line(self, line):
899 match = self.start_re.match(line.lstrip())
900 return match.group(1) if match else None
901
902 def _line(self):
903 self.line_number += 1
904 return self.input.pop()
905
906 def parse_verbatim_block(self):
907 add, output = text_accumulator()
908 self.block_start_line_number = self.line_number
909
910 while self.input:
911 line = self._line()
912 dsl_name = self.is_start_line(line)
913 if dsl_name:
914 self.dsl_name = dsl_name
915 break
916 add(line)
917
918 return Block(output())
919
920 def parse_clinic_block(self, dsl_name):
921 input_add, input_output = text_accumulator()
922 self.block_start_line_number = self.line_number + 1
Larry Hastings90261132014-01-07 12:21:08 -0800923 stop_line = self.language.stop_line.format(dsl_name=dsl_name)
Larry Hastings31826802013-10-19 00:09:25 -0700924 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
925
Larry Hastings90261132014-01-07 12:21:08 -0800926 def is_stop_line(line):
927 # make sure to recognize stop line even if it
928 # doesn't end with EOL (it could be the very end of the file)
929 if not line.startswith(stop_line):
930 return False
931 remainder = line[len(stop_line):]
932 return (not remainder) or remainder.isspace()
933
Larry Hastings31826802013-10-19 00:09:25 -0700934 # consume body of program
935 while self.input:
936 line = self._line()
Larry Hastings90261132014-01-07 12:21:08 -0800937 if is_stop_line(line) or self.is_start_line(line):
Larry Hastings31826802013-10-19 00:09:25 -0700938 break
939 if body_prefix:
940 line = line.lstrip()
941 assert line.startswith(body_prefix)
942 line = line[len(body_prefix):]
943 input_add(line)
944
945 # consume output and checksum line, if present.
946 if self.last_dsl_name == dsl_name:
947 checksum_re = self.last_checksum_re
948 else:
949 before, _, after = self.language.checksum_line.format(dsl_name=dsl_name, checksum='{checksum}').partition('{checksum}')
950 assert _ == '{checksum}'
951 checksum_re = create_regex(before, after)
952 self.last_dsl_name = dsl_name
953 self.last_checksum_re = checksum_re
954
955 # scan forward for checksum line
956 output_add, output_output = text_accumulator()
957 checksum = None
958 while self.input:
959 line = self._line()
960 match = checksum_re.match(line.lstrip())
961 checksum = match.group(1) if match else None
962 if checksum:
963 break
964 output_add(line)
965 if self.is_start_line(line):
966 break
967
Larry Hastingsef3b1fb2013-10-22 23:26:23 -0700968 output = output_output()
Larry Hastings31826802013-10-19 00:09:25 -0700969 if checksum:
Larry Hastings31826802013-10-19 00:09:25 -0700970 if self.verify:
971 computed = compute_checksum(output)
972 if checksum != computed:
973 fail("Checksum mismatch!\nExpected: {}\nComputed: {}".format(checksum, computed))
974 else:
975 # put back output
Larry Hastingseb31e9d2014-01-06 11:10:08 -0800976 output_lines = output.splitlines(keepends=True)
977 self.line_number -= len(output_lines)
978 self.input.extend(reversed(output_lines))
Larry Hastings31826802013-10-19 00:09:25 -0700979 output = None
980
981 return Block(input_output(), dsl_name, output=output)
982
983
984class BlockPrinter:
985
986 def __init__(self, language, f=None):
987 self.language = language
988 self.f = f or io.StringIO()
989
990 def print_block(self, block):
991 input = block.input
992 output = block.output
993 dsl_name = block.dsl_name
994 write = self.f.write
995
Larry Hastings31826802013-10-19 00:09:25 -0700996 assert not ((dsl_name == None) ^ (output == None)), "you must specify dsl_name and output together, dsl_name " + repr(dsl_name)
997
998 if not dsl_name:
999 write(input)
1000 return
1001
1002 write(self.language.start_line.format(dsl_name=dsl_name))
1003 write("\n")
1004
1005 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1006 if not body_prefix:
1007 write(input)
1008 else:
1009 for line in input.split('\n'):
1010 write(body_prefix)
1011 write(line)
1012 write("\n")
1013
1014 write(self.language.stop_line.format(dsl_name=dsl_name))
1015 write("\n")
1016
1017 output = block.output
1018 if output:
1019 write(output)
1020 if not output.endswith('\n'):
1021 write('\n')
1022
1023 write(self.language.checksum_line.format(dsl_name=dsl_name, checksum=compute_checksum(output)))
1024 write("\n")
1025
1026
1027# maps strings to Language objects.
1028# "languages" maps the name of the language ("C", "Python").
1029# "extensions" maps the file extension ("c", "py").
1030languages = { 'C': CLanguage, 'Python': PythonLanguage }
Larry Hastings6d2ea212014-01-05 02:50:45 -08001031extensions = { name: CLanguage for name in "c cc cpp cxx h hh hpp hxx".split() }
1032extensions['py'] = PythonLanguage
Larry Hastings31826802013-10-19 00:09:25 -07001033
1034
1035# maps strings to callables.
1036# these callables must be of the form:
1037# def foo(name, default, *, ...)
1038# The callable may have any number of keyword-only parameters.
1039# The callable must return a CConverter object.
1040# The callable should not call builtins.print.
1041converters = {}
1042
1043# maps strings to callables.
1044# these callables follow the same rules as those for "converters" above.
1045# note however that they will never be called with keyword-only parameters.
1046legacy_converters = {}
1047
1048
1049# maps strings to callables.
1050# these callables must be of the form:
1051# def foo(*, ...)
1052# The callable may have any number of keyword-only parameters.
1053# The callable must return a CConverter object.
1054# The callable should not call builtins.print.
1055return_converters = {}
1056
1057class Clinic:
1058 def __init__(self, language, printer=None, *, verify=True, filename=None):
1059 # maps strings to Parser objects.
1060 # (instantiated from the "parsers" global.)
1061 self.parsers = {}
1062 self.language = language
1063 self.printer = printer or BlockPrinter(language)
1064 self.verify = verify
1065 self.filename = filename
1066 self.modules = collections.OrderedDict()
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001067 self.classes = collections.OrderedDict()
Larry Hastings31826802013-10-19 00:09:25 -07001068
1069 global clinic
1070 clinic = self
1071
1072 def parse(self, input):
1073 printer = self.printer
1074 self.block_parser = BlockParser(input, self.language, verify=self.verify)
1075 for block in self.block_parser:
1076 dsl_name = block.dsl_name
1077 if dsl_name:
1078 if dsl_name not in self.parsers:
1079 assert dsl_name in parsers, "No parser to handle {!r} block.".format(dsl_name)
1080 self.parsers[dsl_name] = parsers[dsl_name](self)
1081 parser = self.parsers[dsl_name]
1082 parser.parse(block)
1083 printer.print_block(block)
1084 return printer.f.getvalue()
1085
1086 def _module_and_class(self, fields):
1087 """
1088 fields should be an iterable of field names.
1089 returns a tuple of (module, class).
1090 the module object could actually be self (a clinic object).
1091 this function is only ever used to find the parent of where
1092 a new class/module should go.
1093 """
1094 in_classes = False
1095 parent = module = self
1096 cls = None
1097 so_far = []
1098
1099 for field in fields:
1100 so_far.append(field)
1101 if not in_classes:
1102 child = parent.modules.get(field)
1103 if child:
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001104 parent = module = child
Larry Hastings31826802013-10-19 00:09:25 -07001105 continue
1106 in_classes = True
1107 if not hasattr(parent, 'classes'):
1108 return module, cls
1109 child = parent.classes.get(field)
1110 if not child:
1111 fail('Parent class or module ' + '.'.join(so_far) + " does not exist.")
1112 cls = parent = child
1113
1114 return module, cls
1115
1116
1117def parse_file(filename, *, verify=True, output=None, encoding='utf-8'):
1118 extension = os.path.splitext(filename)[1][1:]
1119 if not extension:
1120 fail("Can't extract file type for file " + repr(filename))
1121
1122 try:
1123 language = extensions[extension]()
1124 except KeyError:
1125 fail("Can't identify file type for file " + repr(filename))
1126
1127 clinic = Clinic(language, verify=verify, filename=filename)
1128
1129 with open(filename, 'r', encoding=encoding) as f:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001130 raw = f.read()
1131
1132 cooked = clinic.parse(raw)
1133 if cooked == raw:
1134 return
Larry Hastings31826802013-10-19 00:09:25 -07001135
1136 directory = os.path.dirname(filename) or '.'
1137
1138 with tempfile.TemporaryDirectory(prefix="clinic", dir=directory) as tmpdir:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001139 bytes = cooked.encode(encoding)
Larry Hastings31826802013-10-19 00:09:25 -07001140 tmpfilename = os.path.join(tmpdir, os.path.basename(filename))
1141 with open(tmpfilename, "wb") as f:
1142 f.write(bytes)
1143 os.replace(tmpfilename, output or filename)
1144
1145
1146def compute_checksum(input):
1147 input = input or ''
1148 return hashlib.sha1(input.encode('utf-8')).hexdigest()
1149
1150
1151
1152
1153class PythonParser:
1154 def __init__(self, clinic):
1155 pass
1156
1157 def parse(self, block):
1158 s = io.StringIO()
1159 with OverrideStdioWith(s):
1160 exec(block.input)
1161 block.output = s.getvalue()
1162
1163
1164class Module:
1165 def __init__(self, name, module=None):
1166 self.name = name
1167 self.module = self.parent = module
1168
1169 self.modules = collections.OrderedDict()
1170 self.classes = collections.OrderedDict()
1171 self.functions = []
1172
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001173 def __repr__(self):
1174 return "<clinic.Module " + repr(self.name) + " at " + str(id(self)) + ">"
1175
Larry Hastings31826802013-10-19 00:09:25 -07001176class Class:
1177 def __init__(self, name, module=None, cls=None):
1178 self.name = name
1179 self.module = module
1180 self.cls = cls
1181 self.parent = cls or module
1182
1183 self.classes = collections.OrderedDict()
1184 self.functions = []
1185
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001186 def __repr__(self):
1187 return "<clinic.Class " + repr(self.name) + " at " + str(id(self)) + ">"
1188
Larry Hastings8666e652014-01-12 14:12:59 -08001189unsupported_special_methods = set("""
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001190
Larry Hastings8666e652014-01-12 14:12:59 -08001191__abs__
1192__add__
1193__and__
1194__bytes__
1195__call__
1196__complex__
1197__delitem__
1198__divmod__
1199__eq__
1200__float__
1201__floordiv__
1202__ge__
1203__getattr__
1204__getattribute__
1205__getitem__
1206__gt__
1207__hash__
1208__iadd__
1209__iand__
1210__idivmod__
1211__ifloordiv__
1212__ilshift__
1213__imod__
1214__imul__
1215__index__
1216__int__
1217__invert__
1218__ior__
1219__ipow__
1220__irshift__
1221__isub__
1222__iter__
1223__itruediv__
1224__ixor__
1225__le__
1226__len__
1227__lshift__
1228__lt__
1229__mod__
1230__mul__
1231__neg__
1232__new__
1233__next__
1234__or__
1235__pos__
1236__pow__
1237__radd__
1238__rand__
1239__rdivmod__
1240__repr__
1241__rfloordiv__
1242__rlshift__
1243__rmod__
1244__rmul__
1245__ror__
1246__round__
1247__rpow__
1248__rrshift__
1249__rshift__
1250__rsub__
1251__rtruediv__
1252__rxor__
1253__setattr__
1254__setitem__
1255__str__
1256__sub__
1257__truediv__
1258__xor__
1259
1260""".strip().split())
1261
1262
1263INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW = range(6)
Larry Hastings31826802013-10-19 00:09:25 -07001264
1265class Function:
1266 """
1267 Mutable duck type for inspect.Function.
1268
1269 docstring - a str containing
1270 * embedded line breaks
1271 * text outdented to the left margin
1272 * no trailing whitespace.
1273 It will always be true that
1274 (not docstring) or ((not docstring[0].isspace()) and (docstring.rstrip() == docstring))
1275 """
1276
1277 def __init__(self, parameters=None, *, name,
1278 module, cls=None, c_basename=None,
1279 full_name=None,
1280 return_converter, return_annotation=_empty,
1281 docstring=None, kind=CALLABLE, coexist=False):
1282 self.parameters = parameters or collections.OrderedDict()
1283 self.return_annotation = return_annotation
1284 self.name = name
1285 self.full_name = full_name
1286 self.module = module
1287 self.cls = cls
1288 self.parent = cls or module
1289 self.c_basename = c_basename
1290 self.return_converter = return_converter
1291 self.docstring = docstring or ''
1292 self.kind = kind
1293 self.coexist = coexist
Larry Hastingsebdcb502013-11-23 14:54:00 -08001294 self.self_converter = None
1295
1296 @property
1297 def methoddef_flags(self):
Larry Hastings8666e652014-01-12 14:12:59 -08001298 if self.kind in (METHOD_INIT, METHOD_NEW):
1299 return None
Larry Hastingsebdcb502013-11-23 14:54:00 -08001300 flags = []
1301 if self.kind == CLASS_METHOD:
1302 flags.append('METH_CLASS')
1303 elif self.kind == STATIC_METHOD:
1304 flags.append('METH_STATIC')
1305 else:
1306 assert self.kind == CALLABLE, "unknown kind: " + repr(self.kind)
1307 if self.coexist:
1308 flags.append('METH_COEXIST')
1309 return '|'.join(flags)
Larry Hastings31826802013-10-19 00:09:25 -07001310
1311 def __repr__(self):
1312 return '<clinic.Function ' + self.name + '>'
1313
1314
1315class Parameter:
1316 """
1317 Mutable duck type of inspect.Parameter.
1318 """
1319
1320 def __init__(self, name, kind, *, default=_empty,
1321 function, converter, annotation=_empty,
1322 docstring=None, group=0):
1323 self.name = name
1324 self.kind = kind
1325 self.default = default
1326 self.function = function
1327 self.converter = converter
1328 self.annotation = annotation
1329 self.docstring = docstring or ''
1330 self.group = group
1331
1332 def __repr__(self):
1333 return '<clinic.Parameter ' + self.name + '>'
1334
1335 def is_keyword_only(self):
1336 return self.kind == inspect.Parameter.KEYWORD_ONLY
1337
1338py_special_values = {
1339 NULL: "None",
1340}
1341
1342def py_repr(o):
1343 special = py_special_values.get(o)
1344 if special:
1345 return special
1346 return repr(o)
1347
1348
1349c_special_values = {
1350 NULL: "NULL",
1351 None: "Py_None",
1352}
1353
1354def c_repr(o):
1355 special = c_special_values.get(o)
1356 if special:
1357 return special
1358 if isinstance(o, str):
1359 return '"' + quoted_for_c_string(o) + '"'
1360 return repr(o)
1361
1362def add_c_converter(f, name=None):
1363 if not name:
1364 name = f.__name__
1365 if not name.endswith('_converter'):
1366 return f
1367 name = name[:-len('_converter')]
1368 converters[name] = f
1369 return f
1370
1371def add_default_legacy_c_converter(cls):
1372 # automatically add converter for default format unit
1373 # (but without stomping on the existing one if it's already
1374 # set, in case you subclass)
1375 if ((cls.format_unit != 'O&') and
1376 (cls.format_unit not in legacy_converters)):
1377 legacy_converters[cls.format_unit] = cls
1378 return cls
1379
1380def add_legacy_c_converter(format_unit, **kwargs):
1381 """
1382 Adds a legacy converter.
1383 """
1384 def closure(f):
1385 if not kwargs:
1386 added_f = f
1387 else:
1388 added_f = functools.partial(f, **kwargs)
1389 legacy_converters[format_unit] = added_f
1390 return f
1391 return closure
1392
1393class CConverterAutoRegister(type):
1394 def __init__(cls, name, bases, classdict):
1395 add_c_converter(cls)
1396 add_default_legacy_c_converter(cls)
1397
1398class CConverter(metaclass=CConverterAutoRegister):
1399 """
1400 For the init function, self, name, function, and default
1401 must be keyword-or-positional parameters. All other
1402 parameters (including "required" and "doc_default")
1403 must be keyword-only.
1404 """
1405
Larry Hastings78cf85c2014-01-04 12:44:57 -08001406 # The C type to use for this variable.
1407 # 'type' should be a Python string specifying the type, e.g. "int".
1408 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07001409 type = None
Larry Hastings31826802013-10-19 00:09:25 -07001410
1411 # The Python default value for this parameter, as a Python value.
Larry Hastings78cf85c2014-01-04 12:44:57 -08001412 # Or the magic value "unspecified" if there is no default.
Larry Hastings31826802013-10-19 00:09:25 -07001413 default = unspecified
1414
Larry Hastings4a55fc52014-01-12 11:09:57 -08001415 # If not None, default must be isinstance() of this type.
1416 # (You can also specify a tuple of types.)
1417 default_type = None
1418
Larry Hastings31826802013-10-19 00:09:25 -07001419 # "default" as it should appear in the documentation, as a string.
1420 # Or None if there is no default.
1421 doc_default = None
1422
Larry Hastingsabc716b2013-11-20 09:13:52 -08001423 # "default" converted into a str for rendering into Python code.
1424 py_default = None
1425
Larry Hastings31826802013-10-19 00:09:25 -07001426 # "default" converted into a C value, as a string.
1427 # Or None if there is no default.
1428 c_default = None
1429
Larry Hastingsabc716b2013-11-20 09:13:52 -08001430 # The default value used to initialize the C variable when
1431 # there is no default, but not specifying a default may
1432 # result in an "uninitialized variable" warning. This can
1433 # easily happen when using option groups--although
1434 # properly-written code won't actually use the variable,
1435 # the variable does get passed in to the _impl. (Ah, if
1436 # only dataflow analysis could inline the static function!)
1437 #
1438 # This value is specified as a string.
1439 # Every non-abstract subclass should supply a valid value.
1440 c_ignored_default = 'NULL'
1441
Larry Hastings31826802013-10-19 00:09:25 -07001442 # The C converter *function* to be used, if any.
1443 # (If this is not None, format_unit must be 'O&'.)
1444 converter = None
Larry Hastingsebdcb502013-11-23 14:54:00 -08001445
Larry Hastings78cf85c2014-01-04 12:44:57 -08001446 # Should Argument Clinic add a '&' before the name of
1447 # the variable when passing it into the _impl function?
Larry Hastings31826802013-10-19 00:09:25 -07001448 impl_by_reference = False
Larry Hastings78cf85c2014-01-04 12:44:57 -08001449
1450 # Should Argument Clinic add a '&' before the name of
1451 # the variable when passing it into PyArg_ParseTuple (AndKeywords)?
Larry Hastings31826802013-10-19 00:09:25 -07001452 parse_by_reference = True
Larry Hastings78cf85c2014-01-04 12:44:57 -08001453
1454 #############################################################
1455 #############################################################
1456 ## You shouldn't need to read anything below this point to ##
1457 ## write your own converter functions. ##
1458 #############################################################
1459 #############################################################
1460
1461 # The "format unit" to specify for this variable when
1462 # parsing arguments using PyArg_ParseTuple (AndKeywords).
1463 # Custom converters should always use the default value of 'O&'.
1464 format_unit = 'O&'
1465
1466 # What encoding do we want for this variable? Only used
1467 # by format units starting with 'e'.
1468 encoding = None
1469
Larry Hastings77561cc2014-01-07 12:13:13 -08001470 # Should this object be required to be a subclass of a specific type?
1471 # If not None, should be a string representing a pointer to a
1472 # PyTypeObject (e.g. "&PyUnicode_Type").
1473 # Only used by the 'O!' format unit (and the "object" converter).
1474 subclass_of = None
1475
Larry Hastings78cf85c2014-01-04 12:44:57 -08001476 # Do we want an adjacent '_length' variable for this variable?
1477 # Only used by format units ending with '#'.
Larry Hastings31826802013-10-19 00:09:25 -07001478 length = False
1479
Larry Hastings16c51912014-01-07 11:53:01 -08001480 def __init__(self, name, function, default=unspecified, *, doc_default=None, c_default=None, py_default=None, required=False, annotation=unspecified, **kwargs):
Larry Hastings31826802013-10-19 00:09:25 -07001481 self.function = function
1482 self.name = name
1483
1484 if default is not unspecified:
Larry Hastings4a55fc52014-01-12 11:09:57 -08001485 if self.default_type and not isinstance(default, self.default_type):
1486 if isinstance(self.default_type, type):
1487 types_str = self.default_type.__name__
1488 else:
1489 types_str = ', '.join((cls.__name__ for cls in self.default_type))
1490 fail("{}: default value {!r} for field {} is not of type {}".format(
1491 self.__class__.__name__, default, name, types_str))
Larry Hastings31826802013-10-19 00:09:25 -07001492 self.default = default
Larry Hastings16c51912014-01-07 11:53:01 -08001493 self.py_default = py_default if py_default is not None else py_repr(default)
Larry Hastings31826802013-10-19 00:09:25 -07001494 self.doc_default = doc_default if doc_default is not None else self.py_default
Larry Hastings16c51912014-01-07 11:53:01 -08001495 self.c_default = c_default if c_default is not None else c_repr(default)
Larry Hastings4a55fc52014-01-12 11:09:57 -08001496 else:
1497 self.py_default = py_default
1498 self.doc_default = doc_default
1499 self.c_default = c_default
Larry Hastings31826802013-10-19 00:09:25 -07001500 if annotation != unspecified:
1501 fail("The 'annotation' parameter is not currently permitted.")
1502 self.required = required
1503 self.converter_init(**kwargs)
1504
1505 def converter_init(self):
1506 pass
1507
1508 def is_optional(self):
1509 return (self.default is not unspecified) and (not self.required)
1510
1511 def render(self, parameter, data):
1512 """
1513 parameter is a clinic.Parameter instance.
1514 data is a CRenderData instance.
1515 """
Larry Hastingsabc716b2013-11-20 09:13:52 -08001516 self.parameter = parameter
Larry Hastings90261132014-01-07 12:21:08 -08001517 original_name = self.name
1518 name = ensure_legal_c_identifier(original_name)
Larry Hastings31826802013-10-19 00:09:25 -07001519
1520 # declarations
1521 d = self.declaration()
1522 data.declarations.append(d)
1523
1524 # initializers
1525 initializers = self.initialize()
1526 if initializers:
1527 data.initializers.append('/* initializers for ' + name + ' */\n' + initializers.rstrip())
1528
1529 # impl_arguments
1530 s = ("&" if self.impl_by_reference else "") + name
1531 data.impl_arguments.append(s)
Larry Hastingsebdcb502013-11-23 14:54:00 -08001532 if self.length:
1533 data.impl_arguments.append(self.length_name())
Larry Hastings31826802013-10-19 00:09:25 -07001534
1535 # keywords
Larry Hastings90261132014-01-07 12:21:08 -08001536 data.keywords.append(original_name)
Larry Hastings31826802013-10-19 00:09:25 -07001537
1538 # format_units
1539 if self.is_optional() and '|' not in data.format_units:
1540 data.format_units.append('|')
1541 if parameter.is_keyword_only() and '$' not in data.format_units:
1542 data.format_units.append('$')
1543 data.format_units.append(self.format_unit)
1544
1545 # parse_arguments
1546 self.parse_argument(data.parse_arguments)
1547
1548 # impl_parameters
1549 data.impl_parameters.append(self.simple_declaration(by_reference=self.impl_by_reference))
Larry Hastingsebdcb502013-11-23 14:54:00 -08001550 if self.length:
1551 data.impl_parameters.append("Py_ssize_clean_t " + self.length_name())
Larry Hastings31826802013-10-19 00:09:25 -07001552
1553 # cleanup
1554 cleanup = self.cleanup()
1555 if cleanup:
1556 data.cleanup.append('/* Cleanup for ' + name + ' */\n' + cleanup.rstrip() + "\n")
1557
Larry Hastingsebdcb502013-11-23 14:54:00 -08001558 def length_name(self):
1559 """Computes the name of the associated "length" variable."""
1560 if not self.length:
1561 return None
1562 return ensure_legal_c_identifier(self.name) + "_length"
1563
Larry Hastings31826802013-10-19 00:09:25 -07001564 # Why is this one broken out separately?
1565 # For "positional-only" function parsing,
1566 # which generates a bunch of PyArg_ParseTuple calls.
1567 def parse_argument(self, list):
1568 assert not (self.converter and self.encoding)
1569 if self.format_unit == 'O&':
1570 assert self.converter
1571 list.append(self.converter)
1572
1573 if self.encoding:
Larry Hastings77561cc2014-01-07 12:13:13 -08001574 list.append(c_repr(self.encoding))
1575 elif self.subclass_of:
1576 list.append(self.subclass_of)
Larry Hastings31826802013-10-19 00:09:25 -07001577
Larry Hastingsebdcb502013-11-23 14:54:00 -08001578 legal_name = ensure_legal_c_identifier(self.name)
1579 s = ("&" if self.parse_by_reference else "") + legal_name
Larry Hastings31826802013-10-19 00:09:25 -07001580 list.append(s)
1581
Larry Hastingsebdcb502013-11-23 14:54:00 -08001582 if self.length:
1583 list.append("&" + self.length_name())
1584
Larry Hastings31826802013-10-19 00:09:25 -07001585 #
1586 # All the functions after here are intended as extension points.
1587 #
1588
1589 def simple_declaration(self, by_reference=False):
1590 """
1591 Computes the basic declaration of the variable.
1592 Used in computing the prototype declaration and the
1593 variable declaration.
1594 """
1595 prototype = [self.type]
1596 if by_reference or not self.type.endswith('*'):
1597 prototype.append(" ")
1598 if by_reference:
1599 prototype.append('*')
Larry Hastingsdfcd4672013-10-27 02:49:39 -07001600 prototype.append(ensure_legal_c_identifier(self.name))
Larry Hastings31826802013-10-19 00:09:25 -07001601 return "".join(prototype)
1602
1603 def declaration(self):
1604 """
1605 The C statement to declare this variable.
1606 """
1607 declaration = [self.simple_declaration()]
Larry Hastingsabc716b2013-11-20 09:13:52 -08001608 default = self.c_default
1609 if not default and self.parameter.group:
1610 default = self.c_ignored_default
1611 if default:
Larry Hastings31826802013-10-19 00:09:25 -07001612 declaration.append(" = ")
Larry Hastingsabc716b2013-11-20 09:13:52 -08001613 declaration.append(default)
Larry Hastings31826802013-10-19 00:09:25 -07001614 declaration.append(";")
Larry Hastingsebdcb502013-11-23 14:54:00 -08001615 if self.length:
1616 declaration.append('\nPy_ssize_clean_t ')
1617 declaration.append(self.length_name())
1618 declaration.append(';')
Larry Hastings3f144c22014-01-06 10:34:00 -08001619 s = "".join(declaration)
1620 # double up curly-braces, this string will be used
1621 # as part of a format_map() template later
1622 s = s.replace("{", "{{")
1623 s = s.replace("}", "}}")
1624 return s
Larry Hastings31826802013-10-19 00:09:25 -07001625
1626 def initialize(self):
1627 """
1628 The C statements required to set up this variable before parsing.
1629 Returns a string containing this code indented at column 0.
1630 If no initialization is necessary, returns an empty string.
1631 """
1632 return ""
1633
1634 def cleanup(self):
1635 """
1636 The C statements required to clean up after this variable.
1637 Returns a string containing this code indented at column 0.
1638 If no cleanup is necessary, returns an empty string.
1639 """
1640 return ""
1641
1642
1643class bool_converter(CConverter):
1644 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08001645 default_type = bool
Larry Hastings31826802013-10-19 00:09:25 -07001646 format_unit = 'p'
Larry Hastingsabc716b2013-11-20 09:13:52 -08001647 c_ignored_default = '0'
Larry Hastings31826802013-10-19 00:09:25 -07001648
1649 def converter_init(self):
1650 self.default = bool(self.default)
1651 self.c_default = str(int(self.default))
1652
1653class char_converter(CConverter):
1654 type = 'char'
Larry Hastings4a55fc52014-01-12 11:09:57 -08001655 default_type = str
Larry Hastings31826802013-10-19 00:09:25 -07001656 format_unit = 'c'
Larry Hastingsabc716b2013-11-20 09:13:52 -08001657 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07001658
Larry Hastings4a55fc52014-01-12 11:09:57 -08001659 def converter_init(self):
1660 if len(self.default) != 1:
1661 fail("char_converter: illegal default value " + repr(self.default))
1662
1663
Larry Hastings31826802013-10-19 00:09:25 -07001664@add_legacy_c_converter('B', bitwise=True)
1665class byte_converter(CConverter):
1666 type = 'byte'
Larry Hastings4a55fc52014-01-12 11:09:57 -08001667 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07001668 format_unit = 'b'
Larry Hastingsabc716b2013-11-20 09:13:52 -08001669 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07001670
1671 def converter_init(self, *, bitwise=False):
1672 if bitwise:
Larry Hastingsebdcb502013-11-23 14:54:00 -08001673 self.format_unit = 'B'
Larry Hastings31826802013-10-19 00:09:25 -07001674
1675class short_converter(CConverter):
1676 type = 'short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08001677 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07001678 format_unit = 'h'
Larry Hastingsabc716b2013-11-20 09:13:52 -08001679 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07001680
1681class unsigned_short_converter(CConverter):
1682 type = 'unsigned short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08001683 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07001684 format_unit = 'H'
Larry Hastingsabc716b2013-11-20 09:13:52 -08001685 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07001686
1687 def converter_init(self, *, bitwise=False):
1688 if not bitwise:
1689 fail("Unsigned shorts must be bitwise (for now).")
1690
Larry Hastingsebdcb502013-11-23 14:54:00 -08001691@add_legacy_c_converter('C', types='str')
Larry Hastings31826802013-10-19 00:09:25 -07001692class int_converter(CConverter):
1693 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08001694 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07001695 format_unit = 'i'
Larry Hastingsabc716b2013-11-20 09:13:52 -08001696 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07001697
Larry Hastingsebdcb502013-11-23 14:54:00 -08001698 def converter_init(self, *, types='int'):
1699 if types == 'str':
1700 self.format_unit = 'C'
1701 elif types != 'int':
1702 fail("int_converter: illegal 'types' argument")
Larry Hastings31826802013-10-19 00:09:25 -07001703
1704class unsigned_int_converter(CConverter):
1705 type = 'unsigned int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08001706 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07001707 format_unit = 'I'
Larry Hastingsabc716b2013-11-20 09:13:52 -08001708 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07001709
1710 def converter_init(self, *, bitwise=False):
1711 if not bitwise:
1712 fail("Unsigned ints must be bitwise (for now).")
1713
1714class long_converter(CConverter):
1715 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08001716 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07001717 format_unit = 'l'
Larry Hastingsabc716b2013-11-20 09:13:52 -08001718 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07001719
1720class unsigned_long_converter(CConverter):
1721 type = 'unsigned long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08001722 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07001723 format_unit = 'k'
Larry Hastingsabc716b2013-11-20 09:13:52 -08001724 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07001725
1726 def converter_init(self, *, bitwise=False):
1727 if not bitwise:
1728 fail("Unsigned longs must be bitwise (for now).")
1729
1730class PY_LONG_LONG_converter(CConverter):
1731 type = 'PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08001732 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07001733 format_unit = 'L'
Larry Hastingsabc716b2013-11-20 09:13:52 -08001734 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07001735
1736class unsigned_PY_LONG_LONG_converter(CConverter):
1737 type = 'unsigned PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08001738 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07001739 format_unit = 'K'
Larry Hastingsabc716b2013-11-20 09:13:52 -08001740 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07001741
1742 def converter_init(self, *, bitwise=False):
1743 if not bitwise:
1744 fail("Unsigned PY_LONG_LONGs must be bitwise (for now).")
1745
1746class Py_ssize_t_converter(CConverter):
1747 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08001748 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07001749 format_unit = 'n'
Larry Hastingsabc716b2013-11-20 09:13:52 -08001750 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07001751
1752
1753class float_converter(CConverter):
1754 type = 'float'
Larry Hastings4a55fc52014-01-12 11:09:57 -08001755 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07001756 format_unit = 'f'
Larry Hastingsabc716b2013-11-20 09:13:52 -08001757 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07001758
1759class double_converter(CConverter):
1760 type = 'double'
Larry Hastings4a55fc52014-01-12 11:09:57 -08001761 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07001762 format_unit = 'd'
Larry Hastingsabc716b2013-11-20 09:13:52 -08001763 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07001764
1765
1766class Py_complex_converter(CConverter):
1767 type = 'Py_complex'
Larry Hastings4a55fc52014-01-12 11:09:57 -08001768 default_type = complex
Larry Hastings31826802013-10-19 00:09:25 -07001769 format_unit = 'D'
Larry Hastingsabc716b2013-11-20 09:13:52 -08001770 c_ignored_default = "{0.0, 0.0}"
Larry Hastings31826802013-10-19 00:09:25 -07001771
1772
1773class object_converter(CConverter):
1774 type = 'PyObject *'
1775 format_unit = 'O'
1776
Larry Hastings4a55fc52014-01-12 11:09:57 -08001777 def converter_init(self, *, converter=None, type=None, subclass_of=None):
1778 if converter:
1779 if subclass_of:
1780 fail("object: Cannot pass in both 'converter' and 'subclass_of'")
1781 self.format_unit = 'O&'
1782 self.converter = converter
1783 elif subclass_of:
Larry Hastings31826802013-10-19 00:09:25 -07001784 self.format_unit = 'O!'
Larry Hastings77561cc2014-01-07 12:13:13 -08001785 self.subclass_of = subclass_of
Larry Hastings4a55fc52014-01-12 11:09:57 -08001786
Larry Hastings77561cc2014-01-07 12:13:13 -08001787 if type is not None:
1788 self.type = type
Larry Hastings31826802013-10-19 00:09:25 -07001789
1790
Larry Hastingsebdcb502013-11-23 14:54:00 -08001791@add_legacy_c_converter('s#', length=True)
1792@add_legacy_c_converter('y', type="bytes")
1793@add_legacy_c_converter('y#', type="bytes", length=True)
Larry Hastings31826802013-10-19 00:09:25 -07001794@add_legacy_c_converter('z', nullable=True)
Larry Hastingsebdcb502013-11-23 14:54:00 -08001795@add_legacy_c_converter('z#', nullable=True, length=True)
Larry Hastings31826802013-10-19 00:09:25 -07001796class str_converter(CConverter):
1797 type = 'const char *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08001798 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07001799 format_unit = 's'
1800
Larry Hastingsebdcb502013-11-23 14:54:00 -08001801 def converter_init(self, *, encoding=None, types="str",
1802 length=False, nullable=False, zeroes=False):
1803
1804 types = set(types.strip().split())
1805 bytes_type = set(("bytes",))
1806 str_type = set(("str",))
1807 all_3_type = set(("bytearray",)) | bytes_type | str_type
1808 is_bytes = types == bytes_type
1809 is_str = types == str_type
1810 is_all_3 = types == all_3_type
1811
1812 self.length = bool(length)
1813 format_unit = None
1814
1815 if encoding:
1816 self.encoding = encoding
1817
1818 if is_str and not (length or zeroes or nullable):
1819 format_unit = 'es'
1820 elif is_all_3 and not (length or zeroes or nullable):
1821 format_unit = 'et'
1822 elif is_str and length and zeroes and not nullable:
1823 format_unit = 'es#'
1824 elif is_all_3 and length and not (nullable or zeroes):
1825 format_unit = 'et#'
1826
1827 if format_unit.endswith('#'):
Larry Hastings2f9a9aa2013-11-24 04:23:35 -08001828 print("Warning: code using format unit ", repr(format_unit), "probably doesn't work properly.")
Larry Hastingsebdcb502013-11-23 14:54:00 -08001829 # TODO set pointer to NULL
1830 # TODO add cleanup for buffer
1831 pass
1832
1833 else:
1834 if zeroes:
1835 fail("str_converter: illegal combination of arguments (zeroes is only legal with an encoding)")
1836
1837 if is_bytes and not (nullable or length):
1838 format_unit = 'y'
1839 elif is_bytes and length and not nullable:
1840 format_unit = 'y#'
1841 elif is_str and not (nullable or length):
1842 format_unit = 's'
1843 elif is_str and length and not nullable:
1844 format_unit = 's#'
1845 elif is_str and nullable and not length:
1846 format_unit = 'z'
1847 elif is_str and nullable and length:
1848 format_unit = 'z#'
1849
1850 if not format_unit:
1851 fail("str_converter: illegal combination of arguments")
1852 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07001853
1854
1855class PyBytesObject_converter(CConverter):
1856 type = 'PyBytesObject *'
1857 format_unit = 'S'
1858
1859class PyByteArrayObject_converter(CConverter):
1860 type = 'PyByteArrayObject *'
1861 format_unit = 'Y'
1862
1863class unicode_converter(CConverter):
1864 type = 'PyObject *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08001865 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07001866 format_unit = 'U'
1867
Larry Hastingsebdcb502013-11-23 14:54:00 -08001868@add_legacy_c_converter('u#', length=True)
Larry Hastings31826802013-10-19 00:09:25 -07001869@add_legacy_c_converter('Z', nullable=True)
Larry Hastingsebdcb502013-11-23 14:54:00 -08001870@add_legacy_c_converter('Z#', nullable=True, length=True)
Larry Hastings31826802013-10-19 00:09:25 -07001871class Py_UNICODE_converter(CConverter):
1872 type = 'Py_UNICODE *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08001873 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07001874 format_unit = 'u'
1875
Larry Hastingsebdcb502013-11-23 14:54:00 -08001876 def converter_init(self, *, nullable=False, length=False):
1877 format_unit = 'Z' if nullable else 'u'
1878 if length:
1879 format_unit += '#'
1880 self.length = True
1881 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07001882
Larry Hastingsebdcb502013-11-23 14:54:00 -08001883#
1884# We define three string conventions for buffer types in the 'types' argument:
1885# 'buffer' : any object supporting the buffer interface
1886# 'rwbuffer': any object supporting the buffer interface, but must be writeable
1887# 'robuffer': any object supporting the buffer interface, but must not be writeable
1888#
1889@add_legacy_c_converter('s*', types='str bytes bytearray buffer')
1890@add_legacy_c_converter('z*', types='str bytes bytearray buffer', nullable=True)
1891@add_legacy_c_converter('w*', types='bytearray rwbuffer')
Larry Hastings31826802013-10-19 00:09:25 -07001892class Py_buffer_converter(CConverter):
1893 type = 'Py_buffer'
1894 format_unit = 'y*'
1895 impl_by_reference = True
Larry Hastings4a55fc52014-01-12 11:09:57 -08001896 c_ignored_default = "{NULL, NULL}"
Larry Hastings31826802013-10-19 00:09:25 -07001897
Larry Hastingsebdcb502013-11-23 14:54:00 -08001898 def converter_init(self, *, types='bytes bytearray buffer', nullable=False):
Larry Hastings4a55fc52014-01-12 11:09:57 -08001899 if self.default not in (unspecified, None):
1900 fail("The only legal default value for Py_buffer is None.")
Larry Hastings3f144c22014-01-06 10:34:00 -08001901 self.c_default = self.c_ignored_default
Larry Hastingsebdcb502013-11-23 14:54:00 -08001902 types = set(types.strip().split())
1903 bytes_type = set(('bytes',))
1904 bytearray_type = set(('bytearray',))
1905 buffer_type = set(('buffer',))
1906 rwbuffer_type = set(('rwbuffer',))
1907 robuffer_type = set(('robuffer',))
1908 str_type = set(('str',))
1909 bytes_bytearray_buffer_type = bytes_type | bytearray_type | buffer_type
1910
1911 format_unit = None
1912 if types == (str_type | bytes_bytearray_buffer_type):
1913 format_unit = 's*' if not nullable else 'z*'
Larry Hastings31826802013-10-19 00:09:25 -07001914 else:
Larry Hastingsebdcb502013-11-23 14:54:00 -08001915 if nullable:
1916 fail('Py_buffer_converter: illegal combination of arguments (nullable=True)')
1917 elif types == (bytes_bytearray_buffer_type):
1918 format_unit = 'y*'
Larry Hastings4a55fc52014-01-12 11:09:57 -08001919 elif types == (bytearray_type | rwbuffer_type):
Larry Hastingsebdcb502013-11-23 14:54:00 -08001920 format_unit = 'w*'
1921 if not format_unit:
1922 fail("Py_buffer_converter: illegal combination of arguments")
1923
1924 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07001925
1926 def cleanup(self):
Larry Hastingsebdcb502013-11-23 14:54:00 -08001927 name = ensure_legal_c_identifier(self.name)
Larry Hastings4a55fc52014-01-12 11:09:57 -08001928 return "".join(["if (", name, ".obj)\n PyBuffer_Release(&", name, ");\n"])
Larry Hastingsebdcb502013-11-23 14:54:00 -08001929
1930
1931class self_converter(CConverter):
1932 """
1933 A special-case converter:
1934 this is the default converter used for "self".
1935 """
1936 type = "PyObject *"
Larry Hastings78cf85c2014-01-04 12:44:57 -08001937 def converter_init(self, *, type=None):
Larry Hastingsebdcb502013-11-23 14:54:00 -08001938 f = self.function
Larry Hastings8666e652014-01-12 14:12:59 -08001939 if f.kind in (CALLABLE, METHOD_INIT):
Larry Hastingsebdcb502013-11-23 14:54:00 -08001940 if f.cls:
1941 self.name = "self"
1942 else:
1943 self.name = "module"
1944 self.type = "PyModuleDef *"
1945 elif f.kind == STATIC_METHOD:
1946 self.name = "null"
1947 self.type = "void *"
1948 elif f.kind == CLASS_METHOD:
1949 self.name = "cls"
1950 self.type = "PyTypeObject *"
Larry Hastings8666e652014-01-12 14:12:59 -08001951 elif f.kind == METHOD_NEW:
1952 self.name = "type"
1953 self.type = "PyTypeObject *"
Larry Hastingsebdcb502013-11-23 14:54:00 -08001954
Larry Hastings78cf85c2014-01-04 12:44:57 -08001955 if type:
1956 self.type = type
1957
Larry Hastingsebdcb502013-11-23 14:54:00 -08001958 def render(self, parameter, data):
1959 fail("render() should never be called on self_converter instances")
1960
Larry Hastings31826802013-10-19 00:09:25 -07001961
1962
1963def add_c_return_converter(f, name=None):
1964 if not name:
1965 name = f.__name__
1966 if not name.endswith('_return_converter'):
1967 return f
1968 name = name[:-len('_return_converter')]
1969 return_converters[name] = f
1970 return f
1971
1972
1973class CReturnConverterAutoRegister(type):
1974 def __init__(cls, name, bases, classdict):
1975 add_c_return_converter(cls)
1976
1977class CReturnConverter(metaclass=CReturnConverterAutoRegister):
1978
Larry Hastings78cf85c2014-01-04 12:44:57 -08001979 # The C type to use for this variable.
1980 # 'type' should be a Python string specifying the type, e.g. "int".
1981 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07001982 type = 'PyObject *'
Larry Hastings78cf85c2014-01-04 12:44:57 -08001983
1984 # The Python default value for this parameter, as a Python value.
1985 # Or the magic value "unspecified" if there is no default.
Larry Hastings31826802013-10-19 00:09:25 -07001986 default = None
1987
1988 def __init__(self, *, doc_default=None, **kwargs):
1989 self.doc_default = doc_default
1990 try:
1991 self.return_converter_init(**kwargs)
1992 except TypeError as e:
1993 s = ', '.join(name + '=' + repr(value) for name, value in kwargs.items())
1994 sys.exit(self.__class__.__name__ + '(' + s + ')\n' + str(e))
1995
1996 def return_converter_init(self):
1997 pass
1998
1999 def declare(self, data, name="_return_value"):
2000 line = []
2001 add = line.append
2002 add(self.type)
2003 if not self.type.endswith('*'):
2004 add(' ')
2005 add(name + ';')
2006 data.declarations.append(''.join(line))
2007 data.return_value = name
2008
2009 def err_occurred_if(self, expr, data):
2010 data.return_conversion.append('if (({}) && PyErr_Occurred())\n goto exit;\n'.format(expr))
2011
2012 def err_occurred_if_null_pointer(self, variable, data):
2013 data.return_conversion.append('if ({} == NULL)\n goto exit;\n'.format(variable))
2014
2015 def render(self, function, data):
2016 """
2017 function is a clinic.Function instance.
2018 data is a CRenderData instance.
2019 """
2020 pass
2021
2022add_c_return_converter(CReturnConverter, 'object')
2023
Larry Hastings78cf85c2014-01-04 12:44:57 -08002024class NoneType_return_converter(CReturnConverter):
2025 def render(self, function, data):
2026 self.declare(data)
2027 data.return_conversion.append('''
2028if (_return_value != Py_None)
2029 goto exit;
2030return_value = Py_None;
2031Py_INCREF(Py_None);
2032'''.strip())
2033
Larry Hastings4a55fc52014-01-12 11:09:57 -08002034class bool_return_converter(CReturnConverter):
Larry Hastings31826802013-10-19 00:09:25 -07002035 type = 'int'
2036
2037 def render(self, function, data):
2038 self.declare(data)
2039 self.err_occurred_if("_return_value == -1", data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002040 data.return_conversion.append('return_value = PyBool_FromLong((long)_return_value);\n')
Larry Hastings31826802013-10-19 00:09:25 -07002041
2042class long_return_converter(CReturnConverter):
2043 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002044 conversion_fn = 'PyLong_FromLong'
2045 cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07002046
2047 def render(self, function, data):
2048 self.declare(data)
2049 self.err_occurred_if("_return_value == -1", data)
2050 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08002051 ''.join(('return_value = ', self.conversion_fn, '(', self.cast, '_return_value);\n')))
Larry Hastings31826802013-10-19 00:09:25 -07002052
Larry Hastings4a55fc52014-01-12 11:09:57 -08002053class int_return_converter(long_return_converter):
2054 type = 'int'
2055 cast = '(long)'
Larry Hastings31826802013-10-19 00:09:25 -07002056
Larry Hastings4a55fc52014-01-12 11:09:57 -08002057class unsigned_long_return_converter(long_return_converter):
2058 type = 'unsigned long'
2059 conversion_fn = 'PyLong_FromUnsignedLong'
2060
2061class unsigned_int_return_converter(unsigned_long_return_converter):
2062 type = 'unsigned int'
2063 cast = '(unsigned long)'
2064
2065class Py_ssize_t_return_converter(long_return_converter):
Larry Hastings31826802013-10-19 00:09:25 -07002066 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002067 conversion_fn = 'PyLong_FromSsize_t'
2068
2069class size_t_return_converter(long_return_converter):
2070 type = 'size_t'
2071 conversion_fn = 'PyLong_FromSize_t'
2072
2073
2074class double_return_converter(CReturnConverter):
2075 type = 'double'
2076 cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07002077
2078 def render(self, function, data):
2079 self.declare(data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002080 self.err_occurred_if("_return_value == -1.0", data)
Larry Hastings31826802013-10-19 00:09:25 -07002081 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08002082 'return_value = PyFloat_FromDouble(' + self.cast + '_return_value);\n')
2083
2084class float_return_converter(double_return_converter):
2085 type = 'float'
2086 cast = '(double)'
Larry Hastings31826802013-10-19 00:09:25 -07002087
2088
2089class DecodeFSDefault_return_converter(CReturnConverter):
2090 type = 'char *'
2091
2092 def render(self, function, data):
2093 self.declare(data)
2094 self.err_occurred_if_null_pointer("_return_value", data)
2095 data.return_conversion.append(
2096 'return_value = PyUnicode_DecodeFSDefault(_return_value);\n')
2097
2098
2099class IndentStack:
2100 def __init__(self):
2101 self.indents = []
2102 self.margin = None
2103
2104 def _ensure(self):
2105 if not self.indents:
2106 fail('IndentStack expected indents, but none are defined.')
2107
2108 def measure(self, line):
2109 """
2110 Returns the length of the line's margin.
2111 """
2112 if '\t' in line:
2113 fail('Tab characters are illegal in the Clinic DSL.')
2114 stripped = line.lstrip()
2115 if not len(stripped):
2116 # we can't tell anything from an empty line
2117 # so just pretend it's indented like our current indent
2118 self._ensure()
2119 return self.indents[-1]
2120 return len(line) - len(stripped)
2121
2122 def infer(self, line):
2123 """
2124 Infer what is now the current margin based on this line.
2125 Returns:
2126 1 if we have indented (or this is the first margin)
2127 0 if the margin has not changed
2128 -N if we have dedented N times
2129 """
2130 indent = self.measure(line)
2131 margin = ' ' * indent
2132 if not self.indents:
2133 self.indents.append(indent)
2134 self.margin = margin
2135 return 1
2136 current = self.indents[-1]
2137 if indent == current:
2138 return 0
2139 if indent > current:
2140 self.indents.append(indent)
2141 self.margin = margin
2142 return 1
2143 # indent < current
2144 if indent not in self.indents:
2145 fail("Illegal outdent.")
2146 outdent_count = 0
2147 while indent != current:
2148 self.indents.pop()
2149 current = self.indents[-1]
2150 outdent_count -= 1
2151 self.margin = margin
2152 return outdent_count
2153
2154 @property
2155 def depth(self):
2156 """
2157 Returns how many margins are currently defined.
2158 """
2159 return len(self.indents)
2160
2161 def indent(self, line):
2162 """
2163 Indents a line by the currently defined margin.
2164 """
2165 return self.margin + line
2166
2167 def dedent(self, line):
2168 """
2169 Dedents a line by the currently defined margin.
2170 (The inverse of 'indent'.)
2171 """
2172 margin = self.margin
2173 indent = self.indents[-1]
2174 if not line.startswith(margin):
2175 fail('Cannot dedent, line does not start with the previous margin:')
2176 return line[indent:]
2177
2178
2179class DSLParser:
2180 def __init__(self, clinic):
2181 self.clinic = clinic
2182
2183 self.directives = {}
2184 for name in dir(self):
2185 # functions that start with directive_ are added to directives
2186 _, s, key = name.partition("directive_")
2187 if s:
2188 self.directives[key] = getattr(self, name)
2189
2190 # functions that start with at_ are too, with an @ in front
2191 _, s, key = name.partition("at_")
2192 if s:
2193 self.directives['@' + key] = getattr(self, name)
2194
2195 self.reset()
2196
2197 def reset(self):
2198 self.function = None
2199 self.state = self.state_dsl_start
2200 self.parameter_indent = None
2201 self.keyword_only = False
2202 self.group = 0
2203 self.parameter_state = self.ps_start
2204 self.indent = IndentStack()
2205 self.kind = CALLABLE
2206 self.coexist = False
2207
Larry Hastingsebdcb502013-11-23 14:54:00 -08002208 def directive_version(self, required):
2209 global version
2210 if version_comparitor(version, required) < 0:
2211 fail("Insufficient Clinic version!\n Version: " + version + "\n Required: " + required)
2212
Larry Hastings31826802013-10-19 00:09:25 -07002213 def directive_module(self, name):
2214 fields = name.split('.')
2215 new = fields.pop()
2216 module, cls = self.clinic._module_and_class(fields)
2217 if cls:
2218 fail("Can't nest a module inside a class!")
2219 m = Module(name, module)
2220 module.modules[name] = m
2221 self.block.signatures.append(m)
2222
2223 def directive_class(self, name):
2224 fields = name.split('.')
2225 in_classes = False
2226 parent = self
2227 name = fields.pop()
2228 so_far = []
2229 module, cls = self.clinic._module_and_class(fields)
2230
Larry Hastings31826802013-10-19 00:09:25 -07002231 c = Class(name, module, cls)
Larry Hastings31826802013-10-19 00:09:25 -07002232 if cls:
2233 cls.classes[name] = c
Larry Hastingsed4a1c52013-11-18 09:32:13 -08002234 else:
2235 module.classes[name] = c
Larry Hastings31826802013-10-19 00:09:25 -07002236 self.block.signatures.append(c)
2237
2238 def at_classmethod(self):
2239 assert self.kind is CALLABLE
2240 self.kind = CLASS_METHOD
2241
2242 def at_staticmethod(self):
2243 assert self.kind is CALLABLE
2244 self.kind = STATIC_METHOD
2245
2246 def at_coexist(self):
2247 assert self.coexist == False
2248 self.coexist = True
2249
Larry Hastingsebdcb502013-11-23 14:54:00 -08002250
Larry Hastings31826802013-10-19 00:09:25 -07002251 def parse(self, block):
2252 self.reset()
2253 self.block = block
2254 block_start = self.clinic.block_parser.line_number
2255 lines = block.input.split('\n')
2256 for line_number, line in enumerate(lines, self.clinic.block_parser.block_start_line_number):
2257 if '\t' in line:
2258 fail('Tab characters are illegal in the Clinic DSL.\n\t' + repr(line), line_number=block_start)
2259 self.state(line)
2260
2261 self.next(self.state_terminal)
2262 self.state(None)
2263
2264 block.output = self.clinic.language.render(block.signatures)
2265
2266 @staticmethod
2267 def ignore_line(line):
2268 # ignore comment-only lines
2269 if line.lstrip().startswith('#'):
2270 return True
2271
2272 # Ignore empty lines too
2273 # (but not in docstring sections!)
2274 if not line.strip():
2275 return True
2276
2277 return False
2278
2279 @staticmethod
2280 def calculate_indent(line):
2281 return len(line) - len(line.strip())
2282
2283 def next(self, state, line=None):
2284 # real_print(self.state.__name__, "->", state.__name__, ", line=", line)
2285 self.state = state
2286 if line is not None:
2287 self.state(line)
2288
2289 def state_dsl_start(self, line):
2290 # self.block = self.ClinicOutputBlock(self)
2291 if self.ignore_line(line):
2292 return
2293 self.next(self.state_modulename_name, line)
2294
2295 def state_modulename_name(self, line):
2296 # looking for declaration, which establishes the leftmost column
2297 # line should be
2298 # modulename.fnname [as c_basename] [-> return annotation]
2299 # square brackets denote optional syntax.
2300 #
2301 # (but we might find a directive first!)
2302 #
2303 # this line is permitted to start with whitespace.
2304 # we'll call this number of spaces F (for "function").
2305
2306 if not line.strip():
2307 return
2308
2309 self.indent.infer(line)
2310
2311 # is it a directive?
2312 fields = shlex.split(line)
2313 directive_name = fields[0]
2314 directive = self.directives.get(directive_name, None)
2315 if directive:
2316 directive(*fields[1:])
2317 return
2318
2319 line, _, returns = line.partition('->')
2320
2321 full_name, _, c_basename = line.partition(' as ')
2322 full_name = full_name.strip()
2323 c_basename = c_basename.strip() or None
2324
Larry Hastingsdfcd4672013-10-27 02:49:39 -07002325 if not is_legal_py_identifier(full_name):
2326 fail("Illegal function name: {}".format(full_name))
2327 if c_basename and not is_legal_c_identifier(c_basename):
2328 fail("Illegal C basename: {}".format(c_basename))
2329
Larry Hastings31826802013-10-19 00:09:25 -07002330 if not returns:
2331 return_converter = CReturnConverter()
2332 else:
2333 ast_input = "def x() -> {}: pass".format(returns)
2334 module = None
2335 try:
2336 module = ast.parse(ast_input)
2337 except SyntaxError:
2338 pass
2339 if not module:
2340 fail("Badly-formed annotation for " + full_name + ": " + returns)
2341 try:
2342 name, legacy, kwargs = self.parse_converter(module.body[0].returns)
2343 assert not legacy
2344 if name not in return_converters:
2345 fail("Error: No available return converter called " + repr(name))
2346 return_converter = return_converters[name](**kwargs)
2347 except ValueError:
2348 fail("Badly-formed annotation for " + full_name + ": " + returns)
2349
2350 fields = [x.strip() for x in full_name.split('.')]
2351 function_name = fields.pop()
2352 module, cls = self.clinic._module_and_class(fields)
2353
Larry Hastings8666e652014-01-12 14:12:59 -08002354 fields = full_name.split('.')
2355 if fields[-1] == '__new__':
2356 if (self.kind != CLASS_METHOD) or (not cls):
2357 fail("__new__ must be a class method!")
2358 self.kind = METHOD_NEW
2359 elif fields[-1] == '__init__':
2360 if (self.kind != CALLABLE) or (not cls):
2361 fail("__init__ must be a normal method, not a class or static method!")
2362 self.kind = METHOD_INIT
2363 elif fields[-1] in unsupported_special_methods:
2364 fail(fields[-1] + " should not be converted to Argument Clinic! (Yet.)")
2365
Larry Hastings31826802013-10-19 00:09:25 -07002366 if not module:
2367 fail("Undefined module used in declaration of " + repr(full_name.strip()) + ".")
2368 self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename,
2369 return_converter=return_converter, kind=self.kind, coexist=self.coexist)
2370 self.block.signatures.append(self.function)
2371 self.next(self.state_parameters_start)
2372
2373 # Now entering the parameters section. The rules, formally stated:
2374 #
2375 # * All lines must be indented with spaces only.
2376 # * The first line must be a parameter declaration.
2377 # * The first line must be indented.
2378 # * This first line establishes the indent for parameters.
2379 # * We'll call this number of spaces P (for "parameter").
2380 # * Thenceforth:
2381 # * Lines indented with P spaces specify a parameter.
2382 # * Lines indented with > P spaces are docstrings for the previous
2383 # parameter.
2384 # * We'll call this number of spaces D (for "docstring").
2385 # * All subsequent lines indented with >= D spaces are stored as
2386 # part of the per-parameter docstring.
2387 # * All lines will have the first D spaces of the indent stripped
2388 # before they are stored.
2389 # * It's illegal to have a line starting with a number of spaces X
2390 # such that P < X < D.
2391 # * A line with < P spaces is the first line of the function
2392 # docstring, which ends processing for parameters and per-parameter
2393 # docstrings.
2394 # * The first line of the function docstring must be at the same
2395 # indent as the function declaration.
2396 # * It's illegal to have any line in the parameters section starting
2397 # with X spaces such that F < X < P. (As before, F is the indent
2398 # of the function declaration.)
2399 #
2400 ##############
2401 #
2402 # Also, currently Argument Clinic places the following restrictions on groups:
2403 # * Each group must contain at least one parameter.
2404 # * Each group may contain at most one group, which must be the furthest
2405 # thing in the group from the required parameters. (The nested group
2406 # must be the first in the group when it's before the required
2407 # parameters, and the last thing in the group when after the required
2408 # parameters.)
2409 # * There may be at most one (top-level) group to the left or right of
2410 # the required parameters.
2411 # * You must specify a slash, and it must be after all parameters.
2412 # (In other words: either all parameters are positional-only,
2413 # or none are.)
2414 #
2415 # Said another way:
2416 # * Each group must contain at least one parameter.
2417 # * All left square brackets before the required parameters must be
2418 # consecutive. (You can't have a left square bracket followed
2419 # by a parameter, then another left square bracket. You can't
2420 # have a left square bracket, a parameter, a right square bracket,
2421 # and then a left square bracket.)
2422 # * All right square brackets after the required parameters must be
2423 # consecutive.
2424 #
2425 # These rules are enforced with a single state variable:
2426 # "parameter_state". (Previously the code was a miasma of ifs and
2427 # separate boolean state variables.) The states are:
2428 #
2429 # [ [ a, b, ] c, ] d, e, f, [ g, h, [ i ] ] / <- line
2430 # 01 2 3 4 5 6 <- state transitions
2431 #
2432 # 0: ps_start. before we've seen anything. legal transitions are to 1 or 3.
2433 # 1: ps_left_square_before. left square brackets before required parameters.
2434 # 2: ps_group_before. in a group, before required parameters.
2435 # 3: ps_required. required parameters. (renumber left groups!)
2436 # 4: ps_group_after. in a group, after required parameters.
2437 # 5: ps_right_square_after. right square brackets after required parameters.
2438 # 6: ps_seen_slash. seen slash.
2439 ps_start, ps_left_square_before, ps_group_before, ps_required, \
2440 ps_group_after, ps_right_square_after, ps_seen_slash = range(7)
2441
2442 def state_parameters_start(self, line):
2443 if self.ignore_line(line):
2444 return
2445
2446 # if this line is not indented, we have no parameters
2447 if not self.indent.infer(line):
2448 return self.next(self.state_function_docstring, line)
2449
2450 return self.next(self.state_parameter, line)
2451
2452
2453 def to_required(self):
2454 """
2455 Transition to the "required" parameter state.
2456 """
2457 if self.parameter_state != self.ps_required:
2458 self.parameter_state = self.ps_required
2459 for p in self.function.parameters.values():
2460 p.group = -p.group
2461
2462 def state_parameter(self, line):
2463 if self.ignore_line(line):
2464 return
2465
2466 assert self.indent.depth == 2
2467 indent = self.indent.infer(line)
2468 if indent == -1:
2469 # we outdented, must be to definition column
2470 return self.next(self.state_function_docstring, line)
2471
2472 if indent == 1:
2473 # we indented, must be to new parameter docstring column
2474 return self.next(self.state_parameter_docstring_start, line)
2475
2476 line = line.lstrip()
2477
2478 if line in ('*', '/', '[', ']'):
2479 self.parse_special_symbol(line)
2480 return
2481
2482 if self.parameter_state in (self.ps_start, self.ps_required):
2483 self.to_required()
2484 elif self.parameter_state == self.ps_left_square_before:
2485 self.parameter_state = self.ps_group_before
2486 elif self.parameter_state == self.ps_group_before:
2487 if not self.group:
2488 self.to_required()
2489 elif self.parameter_state == self.ps_group_after:
2490 pass
2491 else:
2492 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ")")
2493
2494 ast_input = "def x({}): pass".format(line)
2495 module = None
2496 try:
2497 module = ast.parse(ast_input)
2498 except SyntaxError:
2499 pass
2500 if not module:
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07002501 fail("Function " + self.function.name + " has an invalid parameter declaration:\n\t" + line)
Larry Hastings31826802013-10-19 00:09:25 -07002502
2503 function_args = module.body[0].args
2504 parameter = function_args.args[0]
2505
Larry Hastings16c51912014-01-07 11:53:01 -08002506 py_default = None
2507
2508 parameter_name = parameter.arg
2509 name, legacy, kwargs = self.parse_converter(parameter.annotation)
2510
Larry Hastings31826802013-10-19 00:09:25 -07002511 if function_args.defaults:
2512 expr = function_args.defaults[0]
2513 # mild hack: explicitly support NULL as a default value
2514 if isinstance(expr, ast.Name) and expr.id == 'NULL':
2515 value = NULL
Larry Hastings16c51912014-01-07 11:53:01 -08002516 elif isinstance(expr, ast.Attribute):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002517 c_default = kwargs.get("c_default")
2518 if not (isinstance(c_default, str) and c_default):
2519 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
2520
Larry Hastings16c51912014-01-07 11:53:01 -08002521 a = []
2522 n = expr
2523 while isinstance(n, ast.Attribute):
2524 a.append(n.attr)
2525 n = n.value
2526 if not isinstance(n, ast.Name):
2527 fail("Malformed default value (looked like a Python constant)")
2528 a.append(n.id)
2529 py_default = ".".join(reversed(a))
Larry Hastings16c51912014-01-07 11:53:01 -08002530 kwargs["py_default"] = py_default
Larry Hastings4a55fc52014-01-12 11:09:57 -08002531 value = eval(py_default)
Larry Hastings31826802013-10-19 00:09:25 -07002532 else:
2533 value = ast.literal_eval(expr)
2534 else:
2535 value = unspecified
2536
Larry Hastings31826802013-10-19 00:09:25 -07002537 dict = legacy_converters if legacy else converters
2538 legacy_str = "legacy " if legacy else ""
2539 if name not in dict:
2540 fail('{} is not a valid {}converter'.format(name, legacy_str))
2541 converter = dict[name](parameter_name, self.function, value, **kwargs)
2542
Larry Hastingsebdcb502013-11-23 14:54:00 -08002543 # special case: if it's the self converter,
2544 # don't actually add it to the parameter list
2545 if isinstance(converter, self_converter):
2546 if self.function.parameters or (self.parameter_state != self.ps_required):
2547 fail("The 'self' parameter, if specified, must be the very first thing in the parameter block.")
2548 if self.function.self_converter:
2549 fail("You can't specify the 'self' parameter more than once.")
2550 self.function.self_converter = converter
2551 self.parameter_state = self.ps_start
2552 return
2553
Larry Hastings31826802013-10-19 00:09:25 -07002554 kind = inspect.Parameter.KEYWORD_ONLY if self.keyword_only else inspect.Parameter.POSITIONAL_OR_KEYWORD
2555 p = Parameter(parameter_name, kind, function=self.function, converter=converter, default=value, group=self.group)
2556 self.function.parameters[parameter_name] = p
2557
2558 def parse_converter(self, annotation):
2559 if isinstance(annotation, ast.Str):
2560 return annotation.s, True, {}
2561
2562 if isinstance(annotation, ast.Name):
2563 return annotation.id, False, {}
2564
Larry Hastings4a55fc52014-01-12 11:09:57 -08002565 if not isinstance(annotation, ast.Call):
2566 fail("Annotations must be either a name, a function call, or a string.")
Larry Hastings31826802013-10-19 00:09:25 -07002567
2568 name = annotation.func.id
2569 kwargs = {node.arg: ast.literal_eval(node.value) for node in annotation.keywords}
2570 return name, False, kwargs
2571
2572 def parse_special_symbol(self, symbol):
2573 if self.parameter_state == self.ps_seen_slash:
2574 fail("Function " + self.function.name + " specifies " + symbol + " after /, which is unsupported.")
2575
2576 if symbol == '*':
2577 if self.keyword_only:
2578 fail("Function " + self.function.name + " uses '*' more than once.")
2579 self.keyword_only = True
2580 elif symbol == '[':
2581 if self.parameter_state in (self.ps_start, self.ps_left_square_before):
2582 self.parameter_state = self.ps_left_square_before
2583 elif self.parameter_state in (self.ps_required, self.ps_group_after):
2584 self.parameter_state = self.ps_group_after
2585 else:
2586 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ")")
2587 self.group += 1
2588 elif symbol == ']':
2589 if not self.group:
2590 fail("Function " + self.function.name + " has a ] without a matching [.")
2591 if not any(p.group == self.group for p in self.function.parameters.values()):
2592 fail("Function " + self.function.name + " has an empty group.\nAll groups must contain at least one parameter.")
2593 self.group -= 1
2594 if self.parameter_state in (self.ps_left_square_before, self.ps_group_before):
2595 self.parameter_state = self.ps_group_before
2596 elif self.parameter_state in (self.ps_group_after, self.ps_right_square_after):
2597 self.parameter_state = self.ps_right_square_after
2598 else:
2599 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ")")
2600 elif symbol == '/':
2601 # ps_required is allowed here, that allows positional-only without option groups
2602 # to work (and have default values!)
2603 if (self.parameter_state not in (self.ps_required, self.ps_right_square_after, self.ps_group_before)) or self.group:
2604 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ")")
2605 if self.keyword_only:
2606 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
2607 self.parameter_state = self.ps_seen_slash
2608 # fixup preceeding parameters
2609 for p in self.function.parameters.values():
2610 if p.kind != inspect.Parameter.POSITIONAL_OR_KEYWORD:
2611 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
2612 p.kind = inspect.Parameter.POSITIONAL_ONLY
2613
2614 def state_parameter_docstring_start(self, line):
2615 self.parameter_docstring_indent = len(self.indent.margin)
2616 assert self.indent.depth == 3
2617 return self.next(self.state_parameter_docstring, line)
2618
2619 # every line of the docstring must start with at least F spaces,
2620 # where F > P.
2621 # these F spaces will be stripped.
2622 def state_parameter_docstring(self, line):
2623 stripped = line.strip()
2624 if stripped.startswith('#'):
2625 return
2626
2627 indent = self.indent.measure(line)
2628 if indent < self.parameter_docstring_indent:
2629 self.indent.infer(line)
2630 assert self.indent.depth < 3
2631 if self.indent.depth == 2:
2632 # back to a parameter
2633 return self.next(self.state_parameter, line)
2634 assert self.indent.depth == 1
2635 return self.next(self.state_function_docstring, line)
2636
2637 assert self.function.parameters
2638 last_parameter = next(reversed(list(self.function.parameters.values())))
2639
2640 new_docstring = last_parameter.docstring
2641
2642 if new_docstring:
2643 new_docstring += '\n'
2644 if stripped:
2645 new_docstring += self.indent.dedent(line)
2646
2647 last_parameter.docstring = new_docstring
2648
2649 # the final stanza of the DSL is the docstring.
2650 def state_function_docstring(self, line):
Larry Hastings31826802013-10-19 00:09:25 -07002651 if self.group:
2652 fail("Function " + self.function.name + " has a ] without a matching [.")
2653
2654 stripped = line.strip()
2655 if stripped.startswith('#'):
2656 return
2657
2658 new_docstring = self.function.docstring
2659 if new_docstring:
2660 new_docstring += "\n"
2661 if stripped:
2662 line = self.indent.dedent(line).rstrip()
2663 else:
2664 line = ''
2665 new_docstring += line
2666 self.function.docstring = new_docstring
2667
2668 def format_docstring(self):
2669 f = self.function
2670
2671 add, output = text_accumulator()
2672 parameters = list(f.parameters.values())
2673
2674 ##
2675 ## docstring first line
2676 ##
2677
Larry Hastings44e2eaa2013-11-23 15:37:55 -08002678 add(f.name)
Larry Hastings31826802013-10-19 00:09:25 -07002679 add('(')
2680
2681 # populate "right_bracket_count" field for every parameter
2682 if parameters:
2683 # for now, the only way Clinic supports positional-only parameters
2684 # is if all of them are positional-only.
2685 positional_only_parameters = [p.kind == inspect.Parameter.POSITIONAL_ONLY for p in parameters]
2686 if parameters[0].kind == inspect.Parameter.POSITIONAL_ONLY:
2687 assert all(positional_only_parameters)
2688 for p in parameters:
2689 p.right_bracket_count = abs(p.group)
2690 else:
2691 # don't put any right brackets around non-positional-only parameters, ever.
2692 for p in parameters:
2693 p.right_bracket_count = 0
2694
2695 right_bracket_count = 0
2696
2697 def fix_right_bracket_count(desired):
2698 nonlocal right_bracket_count
2699 s = ''
2700 while right_bracket_count < desired:
2701 s += '['
2702 right_bracket_count += 1
2703 while right_bracket_count > desired:
2704 s += ']'
2705 right_bracket_count -= 1
2706 return s
2707
2708 added_star = False
2709 add_comma = False
2710
2711 for p in parameters:
2712 assert p.name
2713
2714 if p.is_keyword_only() and not added_star:
2715 added_star = True
2716 if add_comma:
2717 add(', ')
2718 add('*')
2719
2720 a = [p.name]
2721 if p.converter.is_optional():
2722 a.append('=')
2723 value = p.converter.default
2724 a.append(p.converter.doc_default)
2725 s = fix_right_bracket_count(p.right_bracket_count)
2726 s += "".join(a)
2727 if add_comma:
2728 add(', ')
2729 add(s)
2730 add_comma = True
2731
2732 add(fix_right_bracket_count(0))
2733 add(')')
2734
Larry Hastings44e2eaa2013-11-23 15:37:55 -08002735 # if f.return_converter.doc_default:
2736 # add(' -> ')
2737 # add(f.return_converter.doc_default)
Larry Hastings31826802013-10-19 00:09:25 -07002738
2739 docstring_first_line = output()
2740
2741 # now fix up the places where the brackets look wrong
2742 docstring_first_line = docstring_first_line.replace(', ]', ',] ')
2743
Larry Hastings44e2eaa2013-11-23 15:37:55 -08002744 # okay. now we're officially building the "parameters" section.
Larry Hastings31826802013-10-19 00:09:25 -07002745 # create substitution text for {parameters}
Larry Hastings44e2eaa2013-11-23 15:37:55 -08002746 spacer_line = False
Larry Hastings31826802013-10-19 00:09:25 -07002747 for p in parameters:
2748 if not p.docstring.strip():
2749 continue
Larry Hastings44e2eaa2013-11-23 15:37:55 -08002750 if spacer_line:
2751 add('\n')
2752 else:
2753 spacer_line = True
Larry Hastings31826802013-10-19 00:09:25 -07002754 add(" ")
2755 add(p.name)
2756 add('\n')
2757 add(textwrap.indent(rstrip_lines(p.docstring.rstrip()), " "))
Larry Hastings44e2eaa2013-11-23 15:37:55 -08002758 parameters = output()
2759 if parameters:
2760 parameters += '\n'
Larry Hastings31826802013-10-19 00:09:25 -07002761
2762 ##
2763 ## docstring body
2764 ##
2765
2766 docstring = f.docstring.rstrip()
2767 lines = [line.rstrip() for line in docstring.split('\n')]
2768
2769 # Enforce the summary line!
2770 # The first line of a docstring should be a summary of the function.
2771 # It should fit on one line (80 columns? 79 maybe?) and be a paragraph
2772 # by itself.
2773 #
2774 # Argument Clinic enforces the following rule:
2775 # * either the docstring is empty,
2776 # * or it must have a summary line.
2777 #
2778 # Guido said Clinic should enforce this:
2779 # http://mail.python.org/pipermail/python-dev/2013-June/127110.html
2780
2781 if len(lines) >= 2:
2782 if lines[1]:
2783 fail("Docstring for " + f.full_name + " does not have a summary line!\n" +
2784 "Every non-blank function docstring must start with\n" +
2785 "a single line summary followed by an empty line.")
2786 elif len(lines) == 1:
2787 # the docstring is only one line right now--the summary line.
2788 # add an empty line after the summary line so we have space
Larry Hastings44e2eaa2013-11-23 15:37:55 -08002789 # between it and the {parameters} we're about to add.
Larry Hastings31826802013-10-19 00:09:25 -07002790 lines.append('')
2791
Larry Hastings44e2eaa2013-11-23 15:37:55 -08002792 parameters_marker_count = len(docstring.split('{parameters}')) - 1
2793 if parameters_marker_count > 1:
2794 fail('You may not specify {parameters} more than once in a docstring!')
2795
2796 if not parameters_marker_count:
2797 # insert after summary line
2798 lines.insert(2, '{parameters}')
2799
2800 # insert at front of docstring
2801 lines.insert(0, docstring_first_line)
Larry Hastings31826802013-10-19 00:09:25 -07002802
2803 docstring = "\n".join(lines)
2804
2805 add(docstring)
2806 docstring = output()
2807
Larry Hastings44e2eaa2013-11-23 15:37:55 -08002808 docstring = linear_format(docstring, parameters=parameters)
Larry Hastings31826802013-10-19 00:09:25 -07002809 docstring = docstring.rstrip()
2810
2811 return docstring
2812
2813 def state_terminal(self, line):
2814 """
2815 Called when processing the block is done.
2816 """
2817 assert not line
2818
2819 if not self.function:
2820 return
2821
Larry Hastings6d2ea212014-01-05 02:50:45 -08002822 if not self.function.self_converter:
2823 self.function.self_converter = self_converter("self", self.function)
2824
Larry Hastings31826802013-10-19 00:09:25 -07002825 if self.keyword_only:
2826 values = self.function.parameters.values()
2827 if not values:
2828 no_parameter_after_star = True
2829 else:
2830 last_parameter = next(reversed(list(values)))
2831 no_parameter_after_star = last_parameter.kind != inspect.Parameter.KEYWORD_ONLY
2832 if no_parameter_after_star:
2833 fail("Function " + self.function.name + " specifies '*' without any parameters afterwards.")
2834
2835 # remove trailing whitespace from all parameter docstrings
2836 for name, value in self.function.parameters.items():
2837 if not value:
2838 continue
2839 value.docstring = value.docstring.rstrip()
2840
2841 self.function.docstring = self.format_docstring()
2842
2843
2844# maps strings to callables.
2845# the callable should return an object
2846# that implements the clinic parser
2847# interface (__init__ and parse).
2848#
2849# example parsers:
2850# "clinic", handles the Clinic DSL
2851# "python", handles running Python code
2852#
2853parsers = {'clinic' : DSLParser, 'python': PythonParser}
2854
2855
2856clinic = None
2857
2858
2859def main(argv):
2860 import sys
2861
2862 if sys.version_info.major < 3 or sys.version_info.minor < 3:
2863 sys.exit("Error: clinic.py requires Python 3.3 or greater.")
2864
2865 import argparse
2866 cmdline = argparse.ArgumentParser()
2867 cmdline.add_argument("-f", "--force", action='store_true')
2868 cmdline.add_argument("-o", "--output", type=str)
2869 cmdline.add_argument("--converters", action='store_true')
Larry Hastingsdcd340e2013-11-23 14:58:45 -08002870 cmdline.add_argument("--make", action='store_true')
Larry Hastings31826802013-10-19 00:09:25 -07002871 cmdline.add_argument("filename", type=str, nargs="*")
2872 ns = cmdline.parse_args(argv)
2873
2874 if ns.converters:
2875 if ns.filename:
2876 print("Usage error: can't specify --converters and a filename at the same time.")
2877 print()
2878 cmdline.print_usage()
2879 sys.exit(-1)
2880 converters = []
2881 return_converters = []
2882 ignored = set("""
2883 add_c_converter
2884 add_c_return_converter
2885 add_default_legacy_c_converter
2886 add_legacy_c_converter
2887 """.strip().split())
2888 module = globals()
2889 for name in module:
2890 for suffix, ids in (
2891 ("_return_converter", return_converters),
2892 ("_converter", converters),
2893 ):
2894 if name in ignored:
2895 continue
2896 if name.endswith(suffix):
2897 ids.append((name, name[:-len(suffix)]))
2898 break
2899 print()
2900
2901 print("Legacy converters:")
2902 legacy = sorted(legacy_converters)
2903 print(' ' + ' '.join(c for c in legacy if c[0].isupper()))
2904 print(' ' + ' '.join(c for c in legacy if c[0].islower()))
2905 print()
2906
2907 for title, attribute, ids in (
2908 ("Converters", 'converter_init', converters),
2909 ("Return converters", 'return_converter_init', return_converters),
2910 ):
2911 print(title + ":")
2912 longest = -1
2913 for name, short_name in ids:
2914 longest = max(longest, len(short_name))
2915 for name, short_name in sorted(ids, key=lambda x: x[1].lower()):
2916 cls = module[name]
2917 callable = getattr(cls, attribute, None)
2918 if not callable:
2919 continue
2920 signature = inspect.signature(callable)
2921 parameters = []
2922 for parameter_name, parameter in signature.parameters.items():
2923 if parameter.kind == inspect.Parameter.KEYWORD_ONLY:
2924 if parameter.default != inspect.Parameter.empty:
2925 s = '{}={!r}'.format(parameter_name, parameter.default)
2926 else:
2927 s = parameter_name
2928 parameters.append(s)
2929 print(' {}({})'.format(short_name, ', '.join(parameters)))
2930 # add_comma = False
2931 # for parameter_name, parameter in signature.parameters.items():
2932 # if parameter.kind == inspect.Parameter.KEYWORD_ONLY:
2933 # if add_comma:
2934 # parameters.append(', ')
2935 # else:
2936 # add_comma = True
2937 # s = parameter_name
2938 # if parameter.default != inspect.Parameter.empty:
2939 # s += '=' + repr(parameter.default)
2940 # parameters.append(s)
2941 # parameters.append(')')
2942
2943 # print(" ", short_name + "".join(parameters))
2944 print()
Larry Hastings78cf85c2014-01-04 12:44:57 -08002945 print("All converters also accept (doc_default=None, required=False, annotation=None).")
Larry Hastings31826802013-10-19 00:09:25 -07002946 print("All return converters also accept (doc_default=None).")
2947 sys.exit(0)
2948
Larry Hastingsdcd340e2013-11-23 14:58:45 -08002949 if ns.make:
2950 if ns.output or ns.filename:
2951 print("Usage error: can't use -o or filenames with --make.")
2952 print()
2953 cmdline.print_usage()
2954 sys.exit(-1)
2955 for root, dirs, files in os.walk('.'):
2956 for rcs_dir in ('.svn', '.git', '.hg'):
2957 if rcs_dir in dirs:
2958 dirs.remove(rcs_dir)
2959 for filename in files:
2960 if not filename.endswith('.c'):
2961 continue
2962 path = os.path.join(root, filename)
2963 parse_file(path, verify=not ns.force)
2964 return
2965
Larry Hastings31826802013-10-19 00:09:25 -07002966 if not ns.filename:
2967 cmdline.print_usage()
2968 sys.exit(-1)
2969
2970 if ns.output and len(ns.filename) > 1:
2971 print("Usage error: can't use -o with multiple filenames.")
2972 print()
2973 cmdline.print_usage()
2974 sys.exit(-1)
2975
2976 for filename in ns.filename:
2977 parse_file(filename, output=ns.output, verify=not ns.force)
2978
2979
2980if __name__ == "__main__":
2981 sys.exit(main(sys.argv[1:]))