blob: 65bad5174cc09cd30d9c51915081aa003515f9ab [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
Larry Hastings7726ac92014-01-31 22:03:12 -080013import copy
14import cpp
Larry Hastings31826802013-10-19 00:09:25 -070015import functools
16import hashlib
17import inspect
18import io
19import itertools
20import os
Larry Hastingsbebf7352014-01-17 17:47:17 -080021import pprint
Larry Hastings31826802013-10-19 00:09:25 -070022import re
23import shlex
Larry Hastings581ee362014-01-28 05:00:08 -080024import string
Larry Hastings31826802013-10-19 00:09:25 -070025import sys
26import tempfile
27import textwrap
Georg Brandlaabebde2014-01-16 06:53:54 +010028import traceback
Larry Hastingsbebf7352014-01-17 17:47:17 -080029import uuid
Larry Hastings31826802013-10-19 00:09:25 -070030
Larry Hastings31826802013-10-19 00:09:25 -070031# TODO:
Larry Hastings31826802013-10-19 00:09:25 -070032#
33# soon:
34#
35# * allow mixing any two of {positional-only, positional-or-keyword,
36# keyword-only}
37# * dict constructor uses positional-only and keyword-only
38# * max and min use positional only with an optional group
39# and keyword-only
40#
Larry Hastings31826802013-10-19 00:09:25 -070041
Larry Hastingsebdcb502013-11-23 14:54:00 -080042version = '1'
43
Larry Hastings31826802013-10-19 00:09:25 -070044_empty = inspect._empty
45_void = inspect._void
46
Larry Hastings4a55fc52014-01-12 11:09:57 -080047NoneType = type(None)
Larry Hastings31826802013-10-19 00:09:25 -070048
49class Unspecified:
50 def __repr__(self):
51 return '<Unspecified>'
52
53unspecified = Unspecified()
54
55
56class Null:
57 def __repr__(self):
58 return '<Null>'
59
60NULL = Null()
61
62
Larry Hastings2a727912014-01-16 11:32:01 -080063class Unknown:
64 def __repr__(self):
65 return '<Unknown>'
66
67unknown = Unknown()
68
69
Larry Hastings31826802013-10-19 00:09:25 -070070def _text_accumulator():
71 text = []
72 def output():
73 s = ''.join(text)
74 text.clear()
75 return s
76 return text, text.append, output
77
78
79def text_accumulator():
80 """
81 Creates a simple text accumulator / joiner.
82
83 Returns a pair of callables:
84 append, output
85 "append" appends a string to the accumulator.
86 "output" returns the contents of the accumulator
87 joined together (''.join(accumulator)) and
88 empties the accumulator.
89 """
90 text, append, output = _text_accumulator()
91 return append, output
92
93
Larry Hastingsbebf7352014-01-17 17:47:17 -080094def warn_or_fail(fail=False, *args, filename=None, line_number=None):
Larry Hastings31826802013-10-19 00:09:25 -070095 joined = " ".join([str(a) for a in args])
96 add, output = text_accumulator()
Larry Hastingsbebf7352014-01-17 17:47:17 -080097 if fail:
98 add("Error")
99 else:
100 add("Warning")
Larry Hastings31826802013-10-19 00:09:25 -0700101 if clinic:
102 if filename is None:
103 filename = clinic.filename
Larry Hastings581ee362014-01-28 05:00:08 -0800104 if getattr(clinic, 'block_parser', None) and (line_number is None):
Larry Hastings31826802013-10-19 00:09:25 -0700105 line_number = clinic.block_parser.line_number
106 if filename is not None:
107 add(' in file "' + filename + '"')
108 if line_number is not None:
109 add(" on line " + str(line_number))
110 add(':\n')
111 add(joined)
112 print(output())
Larry Hastingsbebf7352014-01-17 17:47:17 -0800113 if fail:
114 sys.exit(-1)
Larry Hastings31826802013-10-19 00:09:25 -0700115
116
Larry Hastingsbebf7352014-01-17 17:47:17 -0800117def warn(*args, filename=None, line_number=None):
118 return warn_or_fail(False, *args, filename=filename, line_number=line_number)
119
120def fail(*args, filename=None, line_number=None):
121 return warn_or_fail(True, *args, filename=filename, line_number=line_number)
122
Larry Hastings31826802013-10-19 00:09:25 -0700123
124def quoted_for_c_string(s):
125 for old, new in (
Zachary Ware9d7849f2014-01-25 03:26:20 -0600126 ('\\', '\\\\'), # must be first!
Larry Hastings31826802013-10-19 00:09:25 -0700127 ('"', '\\"'),
128 ("'", "\\'"),
129 ):
130 s = s.replace(old, new)
131 return s
132
Larry Hastings4903e002014-01-18 00:26:16 -0800133def c_repr(s):
134 return '"' + s + '"'
135
136
Larry Hastingsdfcd4672013-10-27 02:49:39 -0700137is_legal_c_identifier = re.compile('^[A-Za-z_][A-Za-z0-9_]*$').match
138
139def is_legal_py_identifier(s):
140 return all(is_legal_c_identifier(field) for field in s.split('.'))
141
Larry Hastingsbebf7352014-01-17 17:47:17 -0800142# identifiers that are okay in Python but aren't a good idea in C.
143# so if they're used Argument Clinic will add "_value" to the end
144# of the name in C.
Larry Hastings31826802013-10-19 00:09:25 -0700145c_keywords = set("""
Larry Hastings5c661892014-01-24 06:17:25 -0800146asm auto break case char const continue default do double
147else enum extern float for goto if inline int long
148register return short signed sizeof static struct switch
Larry Hastingsbebf7352014-01-17 17:47:17 -0800149typedef typeof union unsigned void volatile while
Larry Hastings31826802013-10-19 00:09:25 -0700150""".strip().split())
151
Larry Hastingsdfcd4672013-10-27 02:49:39 -0700152def ensure_legal_c_identifier(s):
153 # for now, just complain if what we're given isn't legal
154 if not is_legal_c_identifier(s):
155 fail("Illegal C identifier: {}".format(s))
156 # but if we picked a C keyword, pick something else
Larry Hastings31826802013-10-19 00:09:25 -0700157 if s in c_keywords:
158 return s + "_value"
159 return s
160
161def rstrip_lines(s):
162 text, add, output = _text_accumulator()
163 for line in s.split('\n'):
164 add(line.rstrip())
165 add('\n')
166 text.pop()
167 return output()
168
169def linear_format(s, **kwargs):
170 """
171 Perform str.format-like substitution, except:
172 * The strings substituted must be on lines by
173 themselves. (This line is the "source line".)
174 * If the substitution text is empty, the source line
175 is removed in the output.
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800176 * If the field is not recognized, the original line
177 is passed unmodified through to the output.
Larry Hastings31826802013-10-19 00:09:25 -0700178 * If the substitution text is not empty:
179 * Each line of the substituted text is indented
180 by the indent of the source line.
181 * A newline will be added to the end.
182 """
183
184 add, output = text_accumulator()
185 for line in s.split('\n'):
186 indent, curly, trailing = line.partition('{')
187 if not curly:
188 add(line)
189 add('\n')
190 continue
191
192 name, curl, trailing = trailing.partition('}')
193 if not curly or name not in kwargs:
194 add(line)
195 add('\n')
196 continue
197
198 if trailing:
199 fail("Text found after {" + name + "} block marker! It must be on a line by itself.")
200 if indent.strip():
201 fail("Non-whitespace characters found before {" + name + "} block marker! It must be on a line by itself.")
202
203 value = kwargs[name]
204 if not value:
205 continue
206
207 value = textwrap.indent(rstrip_lines(value), indent)
208 add(value)
209 add('\n')
210
211 return output()[:-1]
212
Larry Hastingsbebf7352014-01-17 17:47:17 -0800213def indent_all_lines(s, prefix):
214 """
215 Returns 's', with 'prefix' prepended to all lines.
216
217 If the last line is empty, prefix is not prepended
218 to it. (If s is blank, returns s unchanged.)
219
220 (textwrap.indent only adds to non-blank lines.)
221 """
222 split = s.split('\n')
223 last = split.pop()
224 final = []
225 for line in split:
226 final.append(prefix)
227 final.append(line)
228 final.append('\n')
229 if last:
230 final.append(prefix)
231 final.append(last)
232 return ''.join(final)
233
234def suffix_all_lines(s, suffix):
235 """
236 Returns 's', with 'suffix' appended to all lines.
237
238 If the last line is empty, suffix is not appended
239 to it. (If s is blank, returns s unchanged.)
240 """
241 split = s.split('\n')
242 last = split.pop()
243 final = []
244 for line in split:
245 final.append(line)
246 final.append(suffix)
247 final.append('\n')
248 if last:
249 final.append(last)
250 final.append(suffix)
251 return ''.join(final)
252
253
Larry Hastingsebdcb502013-11-23 14:54:00 -0800254def version_splitter(s):
255 """Splits a version string into a tuple of integers.
256
257 The following ASCII characters are allowed, and employ
258 the following conversions:
259 a -> -3
260 b -> -2
261 c -> -1
262 (This permits Python-style version strings such as "1.4b3".)
263 """
264 version = []
265 accumulator = []
266 def flush():
267 if not accumulator:
Larry Hastings2a727912014-01-16 11:32:01 -0800268 raise ValueError('Unsupported version string: ' + repr(s))
Larry Hastingsebdcb502013-11-23 14:54:00 -0800269 version.append(int(''.join(accumulator)))
270 accumulator.clear()
271
272 for c in s:
273 if c.isdigit():
274 accumulator.append(c)
275 elif c == '.':
276 flush()
277 elif c in 'abc':
278 flush()
279 version.append('abc'.index(c) - 3)
280 else:
281 raise ValueError('Illegal character ' + repr(c) + ' in version string ' + repr(s))
282 flush()
283 return tuple(version)
284
285def version_comparitor(version1, version2):
286 iterator = itertools.zip_longest(version_splitter(version1), version_splitter(version2), fillvalue=0)
287 for i, (a, b) in enumerate(iterator):
288 if a < b:
289 return -1
290 if a > b:
291 return 1
292 return 0
293
Larry Hastings31826802013-10-19 00:09:25 -0700294
295class CRenderData:
296 def __init__(self):
297
298 # The C statements to declare variables.
299 # Should be full lines with \n eol characters.
300 self.declarations = []
301
302 # The C statements required to initialize the variables before the parse call.
303 # Should be full lines with \n eol characters.
304 self.initializers = []
305
Larry Hastingsc2047262014-01-25 20:43:29 -0800306 # The C statements needed to dynamically modify the values
307 # parsed by the parse call, before calling the impl.
308 self.modifications = []
309
Larry Hastings31826802013-10-19 00:09:25 -0700310 # The entries for the "keywords" array for PyArg_ParseTuple.
311 # Should be individual strings representing the names.
312 self.keywords = []
313
314 # The "format units" for PyArg_ParseTuple.
315 # Should be individual strings that will get
316 self.format_units = []
317
318 # The varargs arguments for PyArg_ParseTuple.
319 self.parse_arguments = []
320
321 # The parameter declarations for the impl function.
322 self.impl_parameters = []
323
324 # The arguments to the impl function at the time it's called.
325 self.impl_arguments = []
326
327 # For return converters: the name of the variable that
328 # should receive the value returned by the impl.
329 self.return_value = "return_value"
330
331 # For return converters: the code to convert the return
332 # value from the parse function. This is also where
333 # you should check the _return_value for errors, and
334 # "goto exit" if there are any.
335 self.return_conversion = []
336
337 # The C statements required to clean up after the impl call.
338 self.cleanup = []
339
340
Larry Hastings581ee362014-01-28 05:00:08 -0800341class FormatCounterFormatter(string.Formatter):
342 """
343 This counts how many instances of each formatter
344 "replacement string" appear in the format string.
345
346 e.g. after evaluating "string {a}, {b}, {c}, {a}"
347 the counts dict would now look like
348 {'a': 2, 'b': 1, 'c': 1}
349 """
350 def __init__(self):
351 self.counts = collections.Counter()
352
353 def get_value(self, key, args, kwargs):
354 self.counts[key] += 1
355 return ''
356
Larry Hastings31826802013-10-19 00:09:25 -0700357class Language(metaclass=abc.ABCMeta):
358
359 start_line = ""
360 body_prefix = ""
361 stop_line = ""
362 checksum_line = ""
363
Larry Hastings7726ac92014-01-31 22:03:12 -0800364 def __init__(self, filename):
365 pass
366
Larry Hastings31826802013-10-19 00:09:25 -0700367 @abc.abstractmethod
Larry Hastingsbebf7352014-01-17 17:47:17 -0800368 def render(self, clinic, signatures):
Larry Hastings31826802013-10-19 00:09:25 -0700369 pass
370
Larry Hastings7726ac92014-01-31 22:03:12 -0800371 def parse_line(self, line):
372 pass
373
Larry Hastings31826802013-10-19 00:09:25 -0700374 def validate(self):
Larry Hastings581ee362014-01-28 05:00:08 -0800375 def assert_only_one(attr, *additional_fields):
376 """
377 Ensures that the string found at getattr(self, attr)
378 contains exactly one formatter replacement string for
379 each valid field. The list of valid fields is
380 ['dsl_name'] extended by additional_fields.
381
382 e.g.
383 self.fmt = "{dsl_name} {a} {b}"
384
385 # this passes
386 self.assert_only_one('fmt', 'a', 'b')
387
388 # this fails, the format string has a {b} in it
389 self.assert_only_one('fmt', 'a')
390
391 # this fails, the format string doesn't have a {c} in it
392 self.assert_only_one('fmt', 'a', 'b', 'c')
393
394 # this fails, the format string has two {a}s in it,
395 # it must contain exactly one
396 self.fmt2 = '{dsl_name} {a} {a}'
397 self.assert_only_one('fmt2', 'a')
398
399 """
400 fields = ['dsl_name']
401 fields.extend(additional_fields)
402 line = getattr(self, attr)
403 fcf = FormatCounterFormatter()
404 fcf.format(line)
405 def local_fail(should_be_there_but_isnt):
406 if should_be_there_but_isnt:
407 fail("{} {} must contain {{{}}} exactly once!".format(
408 self.__class__.__name__, attr, name))
409 else:
410 fail("{} {} must not contain {{{}}}!".format(
411 self.__class__.__name__, attr, name))
412
413 for name, count in fcf.counts.items():
414 if name in fields:
415 if count > 1:
416 local_fail(True)
417 else:
418 local_fail(False)
419 for name in fields:
420 if fcf.counts.get(name) != 1:
421 local_fail(True)
422
Larry Hastings31826802013-10-19 00:09:25 -0700423 assert_only_one('start_line')
424 assert_only_one('stop_line')
Larry Hastings31826802013-10-19 00:09:25 -0700425
Larry Hastings581ee362014-01-28 05:00:08 -0800426 field = "arguments" if "{arguments}" in self.checksum_line else "checksum"
427 assert_only_one('checksum_line', field)
Larry Hastings31826802013-10-19 00:09:25 -0700428
429
430
431class PythonLanguage(Language):
432
433 language = 'Python'
Larry Hastings61272b72014-01-07 12:41:53 -0800434 start_line = "#/*[{dsl_name} input]"
Larry Hastings31826802013-10-19 00:09:25 -0700435 body_prefix = "#"
Larry Hastings61272b72014-01-07 12:41:53 -0800436 stop_line = "#[{dsl_name} start generated code]*/"
Larry Hastings581ee362014-01-28 05:00:08 -0800437 checksum_line = "#/*[{dsl_name} end generated code: {arguments}]*/"
Larry Hastings31826802013-10-19 00:09:25 -0700438
439
440def permute_left_option_groups(l):
441 """
442 Given [1, 2, 3], should yield:
443 ()
444 (3,)
445 (2, 3)
446 (1, 2, 3)
447 """
448 yield tuple()
449 accumulator = []
450 for group in reversed(l):
451 accumulator = list(group) + accumulator
452 yield tuple(accumulator)
453
454
455def permute_right_option_groups(l):
456 """
457 Given [1, 2, 3], should yield:
458 ()
459 (1,)
460 (1, 2)
461 (1, 2, 3)
462 """
463 yield tuple()
464 accumulator = []
465 for group in l:
466 accumulator.extend(group)
467 yield tuple(accumulator)
468
469
470def permute_optional_groups(left, required, right):
471 """
472 Generator function that computes the set of acceptable
473 argument lists for the provided iterables of
474 argument groups. (Actually it generates a tuple of tuples.)
475
476 Algorithm: prefer left options over right options.
477
478 If required is empty, left must also be empty.
479 """
480 required = tuple(required)
481 result = []
482
483 if not required:
484 assert not left
485
486 accumulator = []
487 counts = set()
488 for r in permute_right_option_groups(right):
489 for l in permute_left_option_groups(left):
490 t = l + required + r
491 if len(t) in counts:
492 continue
493 counts.add(len(t))
494 accumulator.append(t)
495
496 accumulator.sort(key=len)
497 return tuple(accumulator)
498
499
Larry Hastings7726ac92014-01-31 22:03:12 -0800500def strip_leading_and_trailing_blank_lines(s):
501 lines = s.rstrip().split('\n')
502 while lines:
503 line = lines[0]
504 if line.strip():
505 break
506 del lines[0]
507 return '\n'.join(lines)
508
509@functools.lru_cache()
510def normalize_snippet(s, *, indent=0):
511 """
512 Reformats s:
513 * removes leading and trailing blank lines
514 * ensures that it does not end with a newline
515 * dedents so the first nonwhite character on any line is at column "indent"
516 """
517 s = strip_leading_and_trailing_blank_lines(s)
518 s = textwrap.dedent(s)
519 if indent:
520 s = textwrap.indent(s, ' ' * indent)
521 return s
522
523
Larry Hastings31826802013-10-19 00:09:25 -0700524class CLanguage(Language):
525
Larry Hastings61272b72014-01-07 12:41:53 -0800526 body_prefix = "#"
Larry Hastings31826802013-10-19 00:09:25 -0700527 language = 'C'
Larry Hastings61272b72014-01-07 12:41:53 -0800528 start_line = "/*[{dsl_name} input]"
Larry Hastings31826802013-10-19 00:09:25 -0700529 body_prefix = ""
Larry Hastings61272b72014-01-07 12:41:53 -0800530 stop_line = "[{dsl_name} start generated code]*/"
Larry Hastings581ee362014-01-28 05:00:08 -0800531 checksum_line = "/*[{dsl_name} end generated code: {arguments}]*/"
Larry Hastings31826802013-10-19 00:09:25 -0700532
Larry Hastings7726ac92014-01-31 22:03:12 -0800533 def __init__(self, filename):
534 super().__init__(filename)
535 self.cpp = cpp.Monitor(filename)
536 self.cpp.fail = fail
537
538 def parse_line(self, line):
539 self.cpp.writeline(line)
540
Larry Hastingsbebf7352014-01-17 17:47:17 -0800541 def render(self, clinic, signatures):
Larry Hastings31826802013-10-19 00:09:25 -0700542 function = None
543 for o in signatures:
544 if isinstance(o, Function):
545 if function:
546 fail("You may specify at most one function per block.\nFound a block containing at least two:\n\t" + repr(function) + " and " + repr(o))
547 function = o
Larry Hastingsbebf7352014-01-17 17:47:17 -0800548 return self.render_function(clinic, function)
Larry Hastings31826802013-10-19 00:09:25 -0700549
550 def docstring_for_c_string(self, f):
551 text, add, output = _text_accumulator()
552 # turn docstring into a properly quoted C string
553 for line in f.docstring.split('\n'):
554 add('"')
555 add(quoted_for_c_string(line))
556 add('\\n"\n')
557
558 text.pop()
559 add('"')
560 return ''.join(text)
561
Larry Hastingsbebf7352014-01-17 17:47:17 -0800562 def output_templates(self, f):
563 parameters = list(f.parameters.values())
Larry Hastings5c661892014-01-24 06:17:25 -0800564 assert parameters
565 assert isinstance(parameters[0].converter, self_converter)
566 del parameters[0]
Larry Hastingsbebf7352014-01-17 17:47:17 -0800567 converters = [p.converter for p in parameters]
568
569 has_option_groups = parameters and (parameters[0].group or parameters[-1].group)
570 default_return_converter = (not f.return_converter or
571 f.return_converter.type == 'PyObject *')
572
573 positional = parameters and (parameters[-1].kind == inspect.Parameter.POSITIONAL_ONLY)
574 all_boring_objects = False # yes, this will be false if there are 0 parameters, it's fine
575 first_optional = len(parameters)
576 for i, p in enumerate(parameters):
577 c = p.converter
578 if type(c) != object_converter:
579 break
580 if c.format_unit != 'O':
581 break
582 if p.default is not unspecified:
583 first_optional = min(first_optional, i)
584 else:
585 all_boring_objects = True
586
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800587 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
588
Larry Hastingsbebf7352014-01-17 17:47:17 -0800589 meth_o = (len(parameters) == 1 and
590 parameters[0].kind == inspect.Parameter.POSITIONAL_ONLY and
591 not converters[0].is_optional() and
592 isinstance(converters[0], object_converter) and
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800593 converters[0].format_unit == 'O' and
594 not new_or_init)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800595
Larry Hastings7726ac92014-01-31 22:03:12 -0800596 # we have to set these things before we're done:
Larry Hastingsbebf7352014-01-17 17:47:17 -0800597 #
598 # docstring_prototype
599 # docstring_definition
600 # impl_prototype
601 # methoddef_define
602 # parser_prototype
603 # parser_definition
604 # impl_definition
Larry Hastings7726ac92014-01-31 22:03:12 -0800605 # cpp_if
606 # cpp_endif
607 # methoddef_ifndef
Larry Hastingsbebf7352014-01-17 17:47:17 -0800608
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800609 return_value_declaration = "PyObject *return_value = NULL;"
Larry Hastings31826802013-10-19 00:09:25 -0700610
Larry Hastings7726ac92014-01-31 22:03:12 -0800611 methoddef_define = normalize_snippet("""
612 #define {methoddef_name} \\
613 {{"{name}", (PyCFunction){c_basename}, {methoddef_flags}, {c_basename}__doc__}},
614 """)
Larry Hastings5c661892014-01-24 06:17:25 -0800615 if new_or_init and not f.docstring:
616 docstring_prototype = docstring_definition = ''
617 else:
Larry Hastings7726ac92014-01-31 22:03:12 -0800618 docstring_prototype = normalize_snippet("""
619 PyDoc_VAR({c_basename}__doc__);
620 """)
621 docstring_definition = normalize_snippet("""
622 PyDoc_STRVAR({c_basename}__doc__,
623 {docstring});
624 """)
625 impl_definition = normalize_snippet("""
626 static {impl_return_type}
627 {c_basename}_impl({impl_parameters})
628 """)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800629 impl_prototype = parser_prototype = parser_definition = None
630
Larry Hastings7726ac92014-01-31 22:03:12 -0800631 parser_prototype_keyword = normalize_snippet("""
632 static PyObject *
633 {c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
634 """)
635
636 parser_prototype_varargs = normalize_snippet("""
637 static PyObject *
638 {c_basename}({self_type}{self_name}, PyObject *args)
639 """)
640
641 # parser_body_fields remembers the fields passed in to the
642 # previous call to parser_body. this is used for an awful hack.
Larry Hastingsc2047262014-01-25 20:43:29 -0800643 parser_body_fields = ()
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800644 def parser_body(prototype, *fields):
645 nonlocal parser_body_fields
646 add, output = text_accumulator()
647 add(prototype)
648 parser_body_fields = fields
Larry Hastings7726ac92014-01-31 22:03:12 -0800649
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800650 fields = list(fields)
Larry Hastings7726ac92014-01-31 22:03:12 -0800651 fields.insert(0, normalize_snippet("""
652 {{
653 {return_value_declaration}
654 {declarations}
655 {initializers}
656 """) + "\n")
657 # just imagine--your code is here in the middle
658 fields.append(normalize_snippet("""
659 {modifications}
660 {return_value} = {c_basename}_impl({impl_arguments});
661 {return_conversion}
662
663 {exit_label}
664 {cleanup}
665 return return_value;
666 }}
667 """))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800668 for field in fields:
669 add('\n')
Larry Hastings7726ac92014-01-31 22:03:12 -0800670 add(field)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800671 return output()
Larry Hastingsbebf7352014-01-17 17:47:17 -0800672
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800673 def insert_keywords(s):
674 return linear_format(s, declarations="static char *_keywords[] = {{{keywords}, NULL}};\n{declarations}")
Larry Hastingsbebf7352014-01-17 17:47:17 -0800675
676 if not parameters:
677 # no parameters, METH_NOARGS
678
679 flags = "METH_NOARGS"
680
Larry Hastings7726ac92014-01-31 22:03:12 -0800681 parser_prototype = normalize_snippet("""
682 static PyObject *
683 {c_basename}({self_type}{self_name}, PyObject *Py_UNUSED(ignored))
684 """)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800685 parser_definition = parser_prototype
Larry Hastingsbebf7352014-01-17 17:47:17 -0800686
687 if default_return_converter:
Larry Hastings7726ac92014-01-31 22:03:12 -0800688 parser_definition = parser_prototype + '\n' + normalize_snippet("""
689 {{
690 return {c_basename}_impl({impl_arguments});
691 }}
692 """)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800693 else:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800694 parser_definition = parser_body(parser_prototype)
Larry Hastings31826802013-10-19 00:09:25 -0700695
Larry Hastingsbebf7352014-01-17 17:47:17 -0800696 elif meth_o:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800697 flags = "METH_O"
Larry Hastings7726ac92014-01-31 22:03:12 -0800698
699 meth_o_prototype = normalize_snippet("""
700 static PyObject *
701 {c_basename}({impl_parameters})
702 """)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800703
Larry Hastingsbebf7352014-01-17 17:47:17 -0800704 if default_return_converter:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800705 # maps perfectly to METH_O, doesn't need a return converter.
706 # so we skip making a parse function
707 # and call directly into the impl function.
Larry Hastingsbebf7352014-01-17 17:47:17 -0800708 impl_prototype = parser_prototype = parser_definition = ''
Larry Hastings7726ac92014-01-31 22:03:12 -0800709 impl_definition = meth_o_prototype
Larry Hastingsbebf7352014-01-17 17:47:17 -0800710 else:
Larry Hastings7726ac92014-01-31 22:03:12 -0800711 # SLIGHT HACK
712 # use impl_parameters for the parser here!
713 parser_prototype = meth_o_prototype
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800714 parser_definition = parser_body(parser_prototype)
Larry Hastings31826802013-10-19 00:09:25 -0700715
Larry Hastingsbebf7352014-01-17 17:47:17 -0800716 elif has_option_groups:
717 # positional parameters with option groups
718 # (we have to generate lots of PyArg_ParseTuple calls
719 # in a big switch statement)
Larry Hastings31826802013-10-19 00:09:25 -0700720
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800721 flags = "METH_VARARGS"
Larry Hastings7726ac92014-01-31 22:03:12 -0800722 parser_prototype = parser_prototype_varargs
Larry Hastings31826802013-10-19 00:09:25 -0700723
Larry Hastings7726ac92014-01-31 22:03:12 -0800724 parser_definition = parser_body(parser_prototype, ' {option_group_parsing}')
Larry Hastings31826802013-10-19 00:09:25 -0700725
Larry Hastingsbebf7352014-01-17 17:47:17 -0800726 elif positional and all_boring_objects:
727 # positional-only, but no option groups,
728 # and nothing but normal objects:
729 # PyArg_UnpackTuple!
Larry Hastings31826802013-10-19 00:09:25 -0700730
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800731 flags = "METH_VARARGS"
Larry Hastings7726ac92014-01-31 22:03:12 -0800732 parser_prototype = parser_prototype_varargs
Larry Hastings31826802013-10-19 00:09:25 -0700733
Larry Hastings7726ac92014-01-31 22:03:12 -0800734 parser_definition = parser_body(parser_prototype, normalize_snippet("""
735 if (!PyArg_UnpackTuple(args, "{name}",
736 {unpack_min}, {unpack_max},
737 {parse_arguments}))
738 goto exit;
739 """, indent=4))
Larry Hastingsbebf7352014-01-17 17:47:17 -0800740
741 elif positional:
742 # positional-only, but no option groups
743 # we only need one call to PyArg_ParseTuple
744
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800745 flags = "METH_VARARGS"
Larry Hastings7726ac92014-01-31 22:03:12 -0800746 parser_prototype = parser_prototype_varargs
Larry Hastingsbebf7352014-01-17 17:47:17 -0800747
Larry Hastings7726ac92014-01-31 22:03:12 -0800748 parser_definition = parser_body(parser_prototype, normalize_snippet("""
749 if (!PyArg_ParseTuple(args,
750 "{format_units}:{name}",
751 {parse_arguments}))
752 goto exit;
753 """, indent=4))
Larry Hastingsbebf7352014-01-17 17:47:17 -0800754
755 else:
756 # positional-or-keyword arguments
757 flags = "METH_VARARGS|METH_KEYWORDS"
758
Larry Hastings7726ac92014-01-31 22:03:12 -0800759 parser_prototype = parser_prototype_keyword
Larry Hastingsbebf7352014-01-17 17:47:17 -0800760
Larry Hastings7726ac92014-01-31 22:03:12 -0800761 body = normalize_snippet("""
762 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
763 "{format_units}:{name}", _keywords,
764 {parse_arguments}))
765 goto exit;
766 """, indent=4)
767 parser_definition = parser_body(parser_prototype, normalize_snippet("""
768 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
769 "{format_units}:{name}", _keywords,
770 {parse_arguments}))
771 goto exit;
772 """, indent=4))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800773 parser_definition = insert_keywords(parser_definition)
Larry Hastings31826802013-10-19 00:09:25 -0700774
Larry Hastings31826802013-10-19 00:09:25 -0700775
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800776 if new_or_init:
777 methoddef_define = ''
778
779 if f.kind == METHOD_NEW:
Larry Hastings7726ac92014-01-31 22:03:12 -0800780 parser_prototype = parser_prototype_keyword
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800781 else:
782 return_value_declaration = "int return_value = -1;"
Larry Hastings7726ac92014-01-31 22:03:12 -0800783 parser_prototype = normalize_snippet("""
784 static int
785 {c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
786 """)
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800787
788 fields = list(parser_body_fields)
789 parses_positional = 'METH_NOARGS' not in flags
790 parses_keywords = 'METH_KEYWORDS' in flags
791 if parses_keywords:
792 assert parses_positional
793
794 if not parses_keywords:
Larry Hastings7726ac92014-01-31 22:03:12 -0800795 fields.insert(0, normalize_snippet("""
796 if ({self_type_check}!_PyArg_NoKeywords("{name}", kwargs))
797 goto exit;
798 """, indent=4))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800799 if not parses_positional:
Larry Hastings7726ac92014-01-31 22:03:12 -0800800 fields.insert(0, normalize_snippet("""
801 if ({self_type_check}!_PyArg_NoPositional("{name}", args))
802 goto exit;
803 """, indent=4))
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800804
805 parser_definition = parser_body(parser_prototype, *fields)
806 if parses_keywords:
807 parser_definition = insert_keywords(parser_definition)
808
Larry Hastings31826802013-10-19 00:09:25 -0700809
Larry Hastingsbebf7352014-01-17 17:47:17 -0800810 if f.methoddef_flags:
Larry Hastingsbebf7352014-01-17 17:47:17 -0800811 flags += '|' + f.methoddef_flags
Larry Hastings31826802013-10-19 00:09:25 -0700812
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800813 methoddef_define = methoddef_define.replace('{methoddef_flags}', flags)
Larry Hastings31826802013-10-19 00:09:25 -0700814
Larry Hastings7726ac92014-01-31 22:03:12 -0800815 methoddef_ifndef = ''
816 conditional = self.cpp.condition()
817 if not conditional:
818 cpp_if = cpp_endif = ''
819 else:
820 cpp_if = "#if " + conditional
821 cpp_endif = "#endif /* " + conditional + " */"
822
823 if methoddef_define:
824 methoddef_ifndef = normalize_snippet("""
825 #ifndef {methoddef_name}
826 #define {methoddef_name}
827 #endif /* !defined({methoddef_name}) */
828 """)
829
830
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800831 # add ';' to the end of parser_prototype and impl_prototype
832 # (they mustn't be None, but they could be an empty string.)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800833 assert parser_prototype is not None
Larry Hastingsbebf7352014-01-17 17:47:17 -0800834 if parser_prototype:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800835 assert not parser_prototype.endswith(';')
Larry Hastingsbebf7352014-01-17 17:47:17 -0800836 parser_prototype += ';'
Larry Hastings31826802013-10-19 00:09:25 -0700837
Larry Hastingsbebf7352014-01-17 17:47:17 -0800838 if impl_prototype is None:
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800839 impl_prototype = impl_definition
840 if impl_prototype:
841 impl_prototype += ";"
Larry Hastings31826802013-10-19 00:09:25 -0700842
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800843 parser_definition = parser_definition.replace("{return_value_declaration}", return_value_declaration)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800844
845 d = {
846 "docstring_prototype" : docstring_prototype,
847 "docstring_definition" : docstring_definition,
848 "impl_prototype" : impl_prototype,
849 "methoddef_define" : methoddef_define,
850 "parser_prototype" : parser_prototype,
851 "parser_definition" : parser_definition,
852 "impl_definition" : impl_definition,
Larry Hastings7726ac92014-01-31 22:03:12 -0800853 "cpp_if" : cpp_if,
854 "cpp_endif" : cpp_endif,
855 "methoddef_ifndef" : methoddef_ifndef,
Larry Hastingsbebf7352014-01-17 17:47:17 -0800856 }
857
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800858 # make sure we didn't forget to assign something,
859 # and wrap each non-empty value in \n's
Larry Hastingsbebf7352014-01-17 17:47:17 -0800860 d2 = {}
861 for name, value in d.items():
Larry Hastingsb7ccb202014-01-18 23:50:21 -0800862 assert value is not None, "got a None value for template " + repr(name)
Larry Hastingsbebf7352014-01-17 17:47:17 -0800863 if value:
864 value = '\n' + value + '\n'
865 d2[name] = value
866 return d2
Larry Hastings31826802013-10-19 00:09:25 -0700867
868 @staticmethod
869 def group_to_variable_name(group):
870 adjective = "left_" if group < 0 else "right_"
871 return "group_" + adjective + str(abs(group))
872
873 def render_option_group_parsing(self, f, template_dict):
874 # positional only, grouped, optional arguments!
875 # can be optional on the left or right.
876 # here's an example:
877 #
878 # [ [ [ A1 A2 ] B1 B2 B3 ] C1 C2 ] D1 D2 D3 [ E1 E2 E3 [ F1 F2 F3 ] ]
879 #
880 # Here group D are required, and all other groups are optional.
881 # (Group D's "group" is actually None.)
882 # We can figure out which sets of arguments we have based on
883 # how many arguments are in the tuple.
884 #
885 # Note that you need to count up on both sides. For example,
886 # you could have groups C+D, or C+D+E, or C+D+E+F.
887 #
888 # What if the number of arguments leads us to an ambiguous result?
889 # Clinic prefers groups on the left. So in the above example,
890 # five arguments would map to B+C, not C+D.
891
892 add, output = text_accumulator()
893 parameters = list(f.parameters.values())
Larry Hastings5c661892014-01-24 06:17:25 -0800894 if isinstance(parameters[0].converter, self_converter):
895 del parameters[0]
Larry Hastings31826802013-10-19 00:09:25 -0700896
897 groups = []
898 group = None
899 left = []
900 right = []
901 required = []
902 last = unspecified
903
904 for p in parameters:
905 group_id = p.group
906 if group_id != last:
907 last = group_id
908 group = []
909 if group_id < 0:
910 left.append(group)
911 elif group_id == 0:
912 group = required
913 else:
914 right.append(group)
915 group.append(p)
916
917 count_min = sys.maxsize
918 count_max = -1
919
Larry Hastings2a727912014-01-16 11:32:01 -0800920 add("switch (PyTuple_GET_SIZE(args)) {{\n")
Larry Hastings31826802013-10-19 00:09:25 -0700921 for subset in permute_optional_groups(left, required, right):
922 count = len(subset)
923 count_min = min(count_min, count)
924 count_max = max(count_max, count)
925
Larry Hastings583baa82014-01-12 08:49:30 -0800926 if count == 0:
927 add(""" case 0:
928 break;
929""")
930 continue
931
Larry Hastings31826802013-10-19 00:09:25 -0700932 group_ids = {p.group for p in subset} # eliminate duplicates
933 d = {}
934 d['count'] = count
935 d['name'] = f.name
936 d['groups'] = sorted(group_ids)
937 d['format_units'] = "".join(p.converter.format_unit for p in subset)
938
939 parse_arguments = []
940 for p in subset:
941 p.converter.parse_argument(parse_arguments)
942 d['parse_arguments'] = ", ".join(parse_arguments)
943
944 group_ids.discard(0)
945 lines = [self.group_to_variable_name(g) + " = 1;" for g in group_ids]
946 lines = "\n".join(lines)
947
948 s = """
949 case {count}:
950 if (!PyArg_ParseTuple(args, "{format_units}:{name}", {parse_arguments}))
Larry Hastings46258262014-01-22 03:05:49 -0800951 goto exit;
Larry Hastings31826802013-10-19 00:09:25 -0700952 {group_booleans}
953 break;
954"""[1:]
955 s = linear_format(s, group_booleans=lines)
956 s = s.format_map(d)
957 add(s)
958
959 add(" default:\n")
960 s = ' PyErr_SetString(PyExc_TypeError, "{} requires {} to {} arguments");\n'
961 add(s.format(f.full_name, count_min, count_max))
Larry Hastings46258262014-01-22 03:05:49 -0800962 add(' goto exit;\n')
Larry Hastings31826802013-10-19 00:09:25 -0700963 add("}}")
964 template_dict['option_group_parsing'] = output()
965
Larry Hastingsbebf7352014-01-17 17:47:17 -0800966 def render_function(self, clinic, f):
Larry Hastings31826802013-10-19 00:09:25 -0700967 if not f:
968 return ""
969
970 add, output = text_accumulator()
971 data = CRenderData()
972
Larry Hastings7726ac92014-01-31 22:03:12 -0800973 assert f.parameters, "We should always have a 'self' at this point!"
974 parameters = f.render_parameters
Larry Hastings31826802013-10-19 00:09:25 -0700975 converters = [p.converter for p in parameters]
976
Larry Hastings5c661892014-01-24 06:17:25 -0800977 templates = self.output_templates(f)
978
979 f_self = parameters[0]
980 selfless = parameters[1:]
981 assert isinstance(f_self.converter, self_converter), "No self parameter in " + repr(f.full_name) + "!"
982
983 last_group = 0
984 first_optional = len(selfless)
985 positional = selfless and selfless[-1].kind == inspect.Parameter.POSITIONAL_ONLY
986 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
987 default_return_converter = (not f.return_converter or
988 f.return_converter.type == 'PyObject *')
989 has_option_groups = False
990
991 # offset i by -1 because first_optional needs to ignore self
992 for i, p in enumerate(parameters, -1):
993 c = p.converter
994
995 if (i != -1) and (p.default is not unspecified):
996 first_optional = min(first_optional, i)
997
998 # insert group variable
999 group = p.group
1000 if last_group != group:
1001 last_group = group
1002 if group:
1003 group_name = self.group_to_variable_name(group)
1004 data.impl_arguments.append(group_name)
1005 data.declarations.append("int " + group_name + " = 0;")
1006 data.impl_parameters.append("int " + group_name)
1007 has_option_groups = True
1008
1009 c.render(p, data)
1010
1011 if has_option_groups and (not positional):
1012 fail("You cannot use optional groups ('[' and ']')\nunless all parameters are positional-only ('/').")
1013
1014 # HACK
1015 # when we're METH_O, but have a custom return converter,
1016 # we use "impl_parameters" for the parsing function
1017 # because that works better. but that means we must
Berker Peksagf23530f2014-10-19 18:04:38 +03001018 # suppress actually declaring the impl's parameters
Larry Hastings5c661892014-01-24 06:17:25 -08001019 # as variables in the parsing function. but since it's
1020 # METH_O, we have exactly one anyway, so we know exactly
1021 # where it is.
1022 if ("METH_O" in templates['methoddef_define'] and
1023 not default_return_converter):
1024 data.declarations.pop(0)
1025
Larry Hastings31826802013-10-19 00:09:25 -07001026 template_dict = {}
1027
1028 full_name = f.full_name
1029 template_dict['full_name'] = full_name
1030
Larry Hastings5c661892014-01-24 06:17:25 -08001031 if new_or_init:
1032 name = f.cls.name
1033 else:
1034 name = f.name
1035
Larry Hastings31826802013-10-19 00:09:25 -07001036 template_dict['name'] = name
1037
Larry Hastings8666e652014-01-12 14:12:59 -08001038 if f.c_basename:
1039 c_basename = f.c_basename
1040 else:
1041 fields = full_name.split(".")
1042 if fields[-1] == '__new__':
1043 fields.pop()
1044 c_basename = "_".join(fields)
Larry Hastings5c661892014-01-24 06:17:25 -08001045
Larry Hastings31826802013-10-19 00:09:25 -07001046 template_dict['c_basename'] = c_basename
1047
1048 methoddef_name = "{}_METHODDEF".format(c_basename.upper())
1049 template_dict['methoddef_name'] = methoddef_name
1050
1051 template_dict['docstring'] = self.docstring_for_c_string(f)
1052
Larry Hastingsc2047262014-01-25 20:43:29 -08001053 template_dict['self_name'] = template_dict['self_type'] = template_dict['self_type_check'] = ''
Larry Hastings5c661892014-01-24 06:17:25 -08001054 f_self.converter.set_template_dict(template_dict)
Larry Hastingsebdcb502013-11-23 14:54:00 -08001055
Larry Hastings31826802013-10-19 00:09:25 -07001056 f.return_converter.render(f, data)
1057 template_dict['impl_return_type'] = f.return_converter.type
1058
1059 template_dict['declarations'] = "\n".join(data.declarations)
1060 template_dict['initializers'] = "\n\n".join(data.initializers)
Larry Hastingsc2047262014-01-25 20:43:29 -08001061 template_dict['modifications'] = '\n\n'.join(data.modifications)
Larry Hastings31826802013-10-19 00:09:25 -07001062 template_dict['keywords'] = '"' + '", "'.join(data.keywords) + '"'
1063 template_dict['format_units'] = ''.join(data.format_units)
1064 template_dict['parse_arguments'] = ', '.join(data.parse_arguments)
1065 template_dict['impl_parameters'] = ", ".join(data.impl_parameters)
1066 template_dict['impl_arguments'] = ", ".join(data.impl_arguments)
1067 template_dict['return_conversion'] = "".join(data.return_conversion).rstrip()
1068 template_dict['cleanup'] = "".join(data.cleanup)
1069 template_dict['return_value'] = data.return_value
1070
Larry Hastings5c661892014-01-24 06:17:25 -08001071 # used by unpack tuple code generator
1072 ignore_self = -1 if isinstance(converters[0], self_converter) else 0
1073 unpack_min = first_optional
1074 unpack_max = len(selfless)
1075 template_dict['unpack_min'] = str(unpack_min)
1076 template_dict['unpack_max'] = str(unpack_max)
Larry Hastingsb7ccb202014-01-18 23:50:21 -08001077
Larry Hastingsbebf7352014-01-17 17:47:17 -08001078 if has_option_groups:
Larry Hastings31826802013-10-19 00:09:25 -07001079 self.render_option_group_parsing(f, template_dict)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001080
Larry Hastingsbebf7352014-01-17 17:47:17 -08001081 for name, destination in clinic.field_destinations.items():
1082 template = templates[name]
1083 if has_option_groups:
1084 template = linear_format(template,
1085 option_group_parsing=template_dict['option_group_parsing'])
Larry Hastings31826802013-10-19 00:09:25 -07001086 template = linear_format(template,
Larry Hastingsbebf7352014-01-17 17:47:17 -08001087 declarations=template_dict['declarations'],
1088 return_conversion=template_dict['return_conversion'],
1089 initializers=template_dict['initializers'],
Larry Hastingsc2047262014-01-25 20:43:29 -08001090 modifications=template_dict['modifications'],
Larry Hastingsbebf7352014-01-17 17:47:17 -08001091 cleanup=template_dict['cleanup'],
1092 )
Larry Hastings31826802013-10-19 00:09:25 -07001093
Larry Hastingsbebf7352014-01-17 17:47:17 -08001094 # Only generate the "exit:" label
1095 # if we have any gotos
1096 need_exit_label = "goto exit;" in template
1097 template = linear_format(template,
1098 exit_label="exit:" if need_exit_label else ''
1099 )
Larry Hastings31826802013-10-19 00:09:25 -07001100
Larry Hastingsbebf7352014-01-17 17:47:17 -08001101 s = template.format_map(template_dict)
Larry Hastings31826802013-10-19 00:09:25 -07001102
Larry Hastingsbebf7352014-01-17 17:47:17 -08001103 if clinic.line_prefix:
1104 s = indent_all_lines(s, clinic.line_prefix)
1105 if clinic.line_suffix:
1106 s = suffix_all_lines(s, clinic.line_suffix)
1107
1108 destination.append(s)
1109
1110 return clinic.get_destination('block').dump()
1111
Larry Hastings31826802013-10-19 00:09:25 -07001112
1113
Larry Hastings5c661892014-01-24 06:17:25 -08001114
Larry Hastings31826802013-10-19 00:09:25 -07001115@contextlib.contextmanager
1116def OverrideStdioWith(stdout):
1117 saved_stdout = sys.stdout
1118 sys.stdout = stdout
1119 try:
1120 yield
1121 finally:
1122 assert sys.stdout is stdout
1123 sys.stdout = saved_stdout
1124
1125
Larry Hastings2623c8c2014-02-08 22:15:29 -08001126def create_regex(before, after, word=True, whole_line=True):
Larry Hastings31826802013-10-19 00:09:25 -07001127 """Create an re object for matching marker lines."""
Larry Hastings581ee362014-01-28 05:00:08 -08001128 group_re = "\w+" if word else ".+"
Larry Hastings2623c8c2014-02-08 22:15:29 -08001129 pattern = r'{}({}){}'
1130 if whole_line:
1131 pattern = '^' + pattern + '$'
Larry Hastings581ee362014-01-28 05:00:08 -08001132 pattern = pattern.format(re.escape(before), group_re, re.escape(after))
1133 return re.compile(pattern)
Larry Hastings31826802013-10-19 00:09:25 -07001134
1135
1136class Block:
1137 r"""
1138 Represents a single block of text embedded in
1139 another file. If dsl_name is None, the block represents
1140 verbatim text, raw original text from the file, in
1141 which case "input" will be the only non-false member.
1142 If dsl_name is not None, the block represents a Clinic
1143 block.
1144
1145 input is always str, with embedded \n characters.
1146 input represents the original text from the file;
1147 if it's a Clinic block, it is the original text with
1148 the body_prefix and redundant leading whitespace removed.
1149
1150 dsl_name is either str or None. If str, it's the text
1151 found on the start line of the block between the square
1152 brackets.
1153
1154 signatures is either list or None. If it's a list,
1155 it may only contain clinic.Module, clinic.Class, and
1156 clinic.Function objects. At the moment it should
1157 contain at most one of each.
1158
1159 output is either str or None. If str, it's the output
1160 from this block, with embedded '\n' characters.
1161
1162 indent is either str or None. It's the leading whitespace
1163 that was found on every line of input. (If body_prefix is
1164 not empty, this is the indent *after* removing the
1165 body_prefix.)
1166
1167 preindent is either str or None. It's the whitespace that
1168 was found in front of every line of input *before* the
1169 "body_prefix" (see the Language object). If body_prefix
1170 is empty, preindent must always be empty too.
1171
1172 To illustrate indent and preindent: Assume that '_'
1173 represents whitespace. If the block processed was in a
1174 Python file, and looked like this:
1175 ____#/*[python]
1176 ____#__for a in range(20):
1177 ____#____print(a)
1178 ____#[python]*/
1179 "preindent" would be "____" and "indent" would be "__".
1180
1181 """
1182 def __init__(self, input, dsl_name=None, signatures=None, output=None, indent='', preindent=''):
1183 assert isinstance(input, str)
1184 self.input = input
1185 self.dsl_name = dsl_name
1186 self.signatures = signatures or []
1187 self.output = output
1188 self.indent = indent
1189 self.preindent = preindent
1190
Larry Hastings581ee362014-01-28 05:00:08 -08001191 def __repr__(self):
1192 dsl_name = self.dsl_name or "text"
1193 def summarize(s):
1194 s = repr(s)
1195 if len(s) > 30:
1196 return s[:26] + "..." + s[0]
1197 return s
1198 return "".join((
1199 "<Block ", dsl_name, " input=", summarize(self.input), " output=", summarize(self.output), ">"))
1200
Larry Hastings31826802013-10-19 00:09:25 -07001201
1202class BlockParser:
1203 """
1204 Block-oriented parser for Argument Clinic.
1205 Iterator, yields Block objects.
1206 """
1207
1208 def __init__(self, input, language, *, verify=True):
1209 """
1210 "input" should be a str object
1211 with embedded \n characters.
1212
1213 "language" should be a Language object.
1214 """
1215 language.validate()
1216
1217 self.input = collections.deque(reversed(input.splitlines(keepends=True)))
1218 self.block_start_line_number = self.line_number = 0
1219
1220 self.language = language
1221 before, _, after = language.start_line.partition('{dsl_name}')
1222 assert _ == '{dsl_name}'
Larry Hastings2623c8c2014-02-08 22:15:29 -08001223 self.find_start_re = create_regex(before, after, whole_line=False)
Larry Hastings31826802013-10-19 00:09:25 -07001224 self.start_re = create_regex(before, after)
1225 self.verify = verify
1226 self.last_checksum_re = None
1227 self.last_dsl_name = None
1228 self.dsl_name = None
Larry Hastingsbebf7352014-01-17 17:47:17 -08001229 self.first_block = True
Larry Hastings31826802013-10-19 00:09:25 -07001230
1231 def __iter__(self):
1232 return self
1233
1234 def __next__(self):
Larry Hastingsbebf7352014-01-17 17:47:17 -08001235 while True:
1236 if not self.input:
1237 raise StopIteration
Larry Hastings31826802013-10-19 00:09:25 -07001238
Larry Hastingsbebf7352014-01-17 17:47:17 -08001239 if self.dsl_name:
1240 return_value = self.parse_clinic_block(self.dsl_name)
1241 self.dsl_name = None
1242 self.first_block = False
1243 return return_value
1244 block = self.parse_verbatim_block()
1245 if self.first_block and not block.input:
1246 continue
1247 self.first_block = False
1248 return block
1249
Larry Hastings31826802013-10-19 00:09:25 -07001250
1251 def is_start_line(self, line):
1252 match = self.start_re.match(line.lstrip())
1253 return match.group(1) if match else None
1254
1255 def _line(self):
1256 self.line_number += 1
Larry Hastings7726ac92014-01-31 22:03:12 -08001257 line = self.input.pop()
1258 self.language.parse_line(line)
1259 return line
Larry Hastings31826802013-10-19 00:09:25 -07001260
1261 def parse_verbatim_block(self):
1262 add, output = text_accumulator()
1263 self.block_start_line_number = self.line_number
1264
1265 while self.input:
1266 line = self._line()
1267 dsl_name = self.is_start_line(line)
1268 if dsl_name:
1269 self.dsl_name = dsl_name
1270 break
1271 add(line)
1272
1273 return Block(output())
1274
1275 def parse_clinic_block(self, dsl_name):
1276 input_add, input_output = text_accumulator()
1277 self.block_start_line_number = self.line_number + 1
Larry Hastings90261132014-01-07 12:21:08 -08001278 stop_line = self.language.stop_line.format(dsl_name=dsl_name)
Larry Hastings31826802013-10-19 00:09:25 -07001279 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1280
Larry Hastings90261132014-01-07 12:21:08 -08001281 def is_stop_line(line):
1282 # make sure to recognize stop line even if it
1283 # doesn't end with EOL (it could be the very end of the file)
1284 if not line.startswith(stop_line):
1285 return False
1286 remainder = line[len(stop_line):]
1287 return (not remainder) or remainder.isspace()
1288
Larry Hastings31826802013-10-19 00:09:25 -07001289 # consume body of program
1290 while self.input:
1291 line = self._line()
Larry Hastings90261132014-01-07 12:21:08 -08001292 if is_stop_line(line) or self.is_start_line(line):
Larry Hastings31826802013-10-19 00:09:25 -07001293 break
1294 if body_prefix:
1295 line = line.lstrip()
1296 assert line.startswith(body_prefix)
1297 line = line[len(body_prefix):]
1298 input_add(line)
1299
1300 # consume output and checksum line, if present.
1301 if self.last_dsl_name == dsl_name:
1302 checksum_re = self.last_checksum_re
1303 else:
Larry Hastings581ee362014-01-28 05:00:08 -08001304 before, _, after = self.language.checksum_line.format(dsl_name=dsl_name, arguments='{arguments}').partition('{arguments}')
1305 assert _ == '{arguments}'
1306 checksum_re = create_regex(before, after, word=False)
Larry Hastings31826802013-10-19 00:09:25 -07001307 self.last_dsl_name = dsl_name
1308 self.last_checksum_re = checksum_re
1309
1310 # scan forward for checksum line
1311 output_add, output_output = text_accumulator()
Larry Hastings581ee362014-01-28 05:00:08 -08001312 arguments = None
Larry Hastings31826802013-10-19 00:09:25 -07001313 while self.input:
1314 line = self._line()
1315 match = checksum_re.match(line.lstrip())
Larry Hastings581ee362014-01-28 05:00:08 -08001316 arguments = match.group(1) if match else None
1317 if arguments:
Larry Hastings31826802013-10-19 00:09:25 -07001318 break
1319 output_add(line)
1320 if self.is_start_line(line):
1321 break
1322
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07001323 output = output_output()
Larry Hastings581ee362014-01-28 05:00:08 -08001324 if arguments:
1325 d = {}
1326 for field in shlex.split(arguments):
1327 name, equals, value = field.partition('=')
1328 if not equals:
1329 fail("Mangled Argument Clinic marker line: {!r}".format(line))
1330 d[name.strip()] = value.strip()
1331
Larry Hastings31826802013-10-19 00:09:25 -07001332 if self.verify:
Larry Hastings581ee362014-01-28 05:00:08 -08001333 if 'input' in d:
1334 checksum = d['output']
1335 input_checksum = d['input']
1336 else:
1337 checksum = d['checksum']
1338 input_checksum = None
1339
1340 computed = compute_checksum(output, len(checksum))
Larry Hastings31826802013-10-19 00:09:25 -07001341 if checksum != computed:
Antoine Pitroucc1d31e2014-01-14 20:52:01 +01001342 fail("Checksum mismatch!\nExpected: {}\nComputed: {}\n"
1343 "Suggested fix: remove all generated code including "
Larry Hastingsbebf7352014-01-17 17:47:17 -08001344 "the end marker,\n"
1345 "or use the '-f' option."
Antoine Pitroucc1d31e2014-01-14 20:52:01 +01001346 .format(checksum, computed))
Larry Hastings31826802013-10-19 00:09:25 -07001347 else:
1348 # put back output
Larry Hastingseb31e9d2014-01-06 11:10:08 -08001349 output_lines = output.splitlines(keepends=True)
1350 self.line_number -= len(output_lines)
1351 self.input.extend(reversed(output_lines))
Larry Hastings31826802013-10-19 00:09:25 -07001352 output = None
1353
1354 return Block(input_output(), dsl_name, output=output)
1355
1356
1357class BlockPrinter:
1358
1359 def __init__(self, language, f=None):
1360 self.language = language
1361 self.f = f or io.StringIO()
1362
1363 def print_block(self, block):
1364 input = block.input
1365 output = block.output
1366 dsl_name = block.dsl_name
1367 write = self.f.write
1368
Larry Hastings31826802013-10-19 00:09:25 -07001369 assert not ((dsl_name == None) ^ (output == None)), "you must specify dsl_name and output together, dsl_name " + repr(dsl_name)
1370
1371 if not dsl_name:
1372 write(input)
1373 return
1374
1375 write(self.language.start_line.format(dsl_name=dsl_name))
1376 write("\n")
1377
1378 body_prefix = self.language.body_prefix.format(dsl_name=dsl_name)
1379 if not body_prefix:
1380 write(input)
1381 else:
1382 for line in input.split('\n'):
1383 write(body_prefix)
1384 write(line)
1385 write("\n")
1386
1387 write(self.language.stop_line.format(dsl_name=dsl_name))
1388 write("\n")
1389
Larry Hastings581ee362014-01-28 05:00:08 -08001390 input = ''.join(block.input)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001391 output = ''.join(block.output)
Larry Hastings31826802013-10-19 00:09:25 -07001392 if output:
Larry Hastings31826802013-10-19 00:09:25 -07001393 if not output.endswith('\n'):
Larry Hastingsbebf7352014-01-17 17:47:17 -08001394 output += '\n'
1395 write(output)
Larry Hastings31826802013-10-19 00:09:25 -07001396
Larry Hastings581ee362014-01-28 05:00:08 -08001397 arguments="output={} input={}".format(compute_checksum(output, 16), compute_checksum(input, 16))
1398 write(self.language.checksum_line.format(dsl_name=dsl_name, arguments=arguments))
Larry Hastings31826802013-10-19 00:09:25 -07001399 write("\n")
1400
Larry Hastingsbebf7352014-01-17 17:47:17 -08001401 def write(self, text):
1402 self.f.write(text)
1403
1404
1405class Destination:
1406 def __init__(self, name, type, clinic, *args):
1407 self.name = name
1408 self.type = type
1409 self.clinic = clinic
1410 valid_types = ('buffer', 'file', 'suppress', 'two-pass')
1411 if type not in valid_types:
1412 fail("Invalid destination type " + repr(type) + " for " + name + " , must be " + ', '.join(valid_types))
1413 extra_arguments = 1 if type == "file" else 0
1414 if len(args) < extra_arguments:
1415 fail("Not enough arguments for destination " + name + " new " + type)
1416 if len(args) > extra_arguments:
1417 fail("Too many arguments for destination " + name + " new " + type)
1418 if type =='file':
1419 d = {}
Larry Hastingsc2047262014-01-25 20:43:29 -08001420 filename = clinic.filename
1421 d['path'] = filename
1422 dirname, basename = os.path.split(filename)
1423 if not dirname:
1424 dirname = '.'
1425 d['dirname'] = dirname
1426 d['basename'] = basename
1427 d['basename_root'], d['basename_extension'] = os.path.splitext(filename)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001428 self.filename = args[0].format_map(d)
1429 if type == 'two-pass':
1430 self.id = None
1431
1432 self.text, self.append, self._dump = _text_accumulator()
1433
1434 def __repr__(self):
1435 if self.type == 'file':
1436 file_repr = " " + repr(self.filename)
1437 else:
1438 file_repr = ''
1439 return "".join(("<Destination ", self.name, " ", self.type, file_repr, ">"))
1440
1441 def clear(self):
1442 if self.type != 'buffer':
1443 fail("Can't clear destination" + self.name + " , it's not of type buffer")
1444 self.text.clear()
1445
1446 def dump(self):
1447 if self.type == 'two-pass':
1448 if self.id is None:
1449 self.id = str(uuid.uuid4())
1450 return self.id
1451 fail("You can only dump a two-pass buffer exactly once!")
1452 return self._dump()
1453
Larry Hastings31826802013-10-19 00:09:25 -07001454
1455# maps strings to Language objects.
1456# "languages" maps the name of the language ("C", "Python").
1457# "extensions" maps the file extension ("c", "py").
1458languages = { 'C': CLanguage, 'Python': PythonLanguage }
Larry Hastings6d2ea212014-01-05 02:50:45 -08001459extensions = { name: CLanguage for name in "c cc cpp cxx h hh hpp hxx".split() }
1460extensions['py'] = PythonLanguage
Larry Hastings31826802013-10-19 00:09:25 -07001461
1462
1463# maps strings to callables.
1464# these callables must be of the form:
1465# def foo(name, default, *, ...)
1466# The callable may have any number of keyword-only parameters.
1467# The callable must return a CConverter object.
1468# The callable should not call builtins.print.
1469converters = {}
1470
1471# maps strings to callables.
1472# these callables follow the same rules as those for "converters" above.
1473# note however that they will never be called with keyword-only parameters.
1474legacy_converters = {}
1475
1476
1477# maps strings to callables.
1478# these callables must be of the form:
1479# def foo(*, ...)
1480# The callable may have any number of keyword-only parameters.
1481# The callable must return a CConverter object.
1482# The callable should not call builtins.print.
1483return_converters = {}
1484
Larry Hastings7726ac92014-01-31 22:03:12 -08001485clinic = None
Larry Hastings31826802013-10-19 00:09:25 -07001486class Clinic:
Larry Hastingsbebf7352014-01-17 17:47:17 -08001487
1488 presets_text = """
Larry Hastings7726ac92014-01-31 22:03:12 -08001489preset block
1490everything block
1491docstring_prototype suppress
1492parser_prototype suppress
1493cpp_if suppress
1494cpp_endif suppress
1495methoddef_ifndef buffer
1496
Larry Hastingsbebf7352014-01-17 17:47:17 -08001497preset original
1498everything block
1499docstring_prototype suppress
1500parser_prototype suppress
Larry Hastings7726ac92014-01-31 22:03:12 -08001501cpp_if suppress
1502cpp_endif suppress
1503methoddef_ifndef buffer
Larry Hastingsbebf7352014-01-17 17:47:17 -08001504
1505preset file
1506everything file
1507docstring_prototype suppress
1508parser_prototype suppress
1509impl_definition block
1510
1511preset buffer
1512everything buffer
1513docstring_prototype suppress
1514impl_prototype suppress
1515parser_prototype suppress
1516impl_definition block
1517
1518preset partial-buffer
1519everything buffer
1520docstring_prototype block
1521impl_prototype suppress
1522methoddef_define block
1523parser_prototype block
1524impl_definition block
1525
1526preset two-pass
1527everything buffer
1528docstring_prototype two-pass
1529impl_prototype suppress
1530methoddef_define two-pass
1531parser_prototype two-pass
1532impl_definition block
1533
1534"""
1535
Larry Hastings581ee362014-01-28 05:00:08 -08001536 def __init__(self, language, printer=None, *, force=False, verify=True, filename=None):
Larry Hastings31826802013-10-19 00:09:25 -07001537 # maps strings to Parser objects.
1538 # (instantiated from the "parsers" global.)
1539 self.parsers = {}
1540 self.language = language
Larry Hastingsbebf7352014-01-17 17:47:17 -08001541 if printer:
1542 fail("Custom printers are broken right now")
Larry Hastings31826802013-10-19 00:09:25 -07001543 self.printer = printer or BlockPrinter(language)
1544 self.verify = verify
Larry Hastings581ee362014-01-28 05:00:08 -08001545 self.force = force
Larry Hastings31826802013-10-19 00:09:25 -07001546 self.filename = filename
1547 self.modules = collections.OrderedDict()
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001548 self.classes = collections.OrderedDict()
Larry Hastings2a727912014-01-16 11:32:01 -08001549 self.functions = []
Larry Hastings31826802013-10-19 00:09:25 -07001550
Larry Hastingsbebf7352014-01-17 17:47:17 -08001551 self.line_prefix = self.line_suffix = ''
1552
1553 self.destinations = {}
1554 self.add_destination("block", "buffer")
1555 self.add_destination("suppress", "suppress")
1556 self.add_destination("buffer", "buffer")
1557 self.add_destination("two-pass", "two-pass")
1558 if filename:
Larry Hastingsc2047262014-01-25 20:43:29 -08001559 self.add_destination("file", "file", "{dirname}/clinic/{basename}.h")
Larry Hastingsbebf7352014-01-17 17:47:17 -08001560
1561 d = self.destinations.get
1562 self.field_destinations = collections.OrderedDict((
Larry Hastings7726ac92014-01-31 22:03:12 -08001563 ('cpp_if', d('suppress')),
Larry Hastingsbebf7352014-01-17 17:47:17 -08001564 ('docstring_prototype', d('suppress')),
1565 ('docstring_definition', d('block')),
1566 ('methoddef_define', d('block')),
1567 ('impl_prototype', d('block')),
1568 ('parser_prototype', d('suppress')),
1569 ('parser_definition', d('block')),
Larry Hastings7726ac92014-01-31 22:03:12 -08001570 ('cpp_endif', d('suppress')),
1571 ('methoddef_ifndef', d('buffer')),
Larry Hastingsbebf7352014-01-17 17:47:17 -08001572 ('impl_definition', d('block')),
1573 ))
1574
1575 self.field_destinations_stack = []
1576
1577 self.presets = {}
1578 preset = None
1579 for line in self.presets_text.strip().split('\n'):
1580 line = line.strip()
1581 if not line:
1582 continue
1583 name, value = line.split()
1584 if name == 'preset':
1585 self.presets[value] = preset = collections.OrderedDict()
1586 continue
1587
1588 destination = self.get_destination(value)
1589
1590 if name == 'everything':
1591 for name in self.field_destinations:
1592 preset[name] = destination
1593 continue
1594
1595 assert name in self.field_destinations
1596 preset[name] = destination
1597
Larry Hastings31826802013-10-19 00:09:25 -07001598 global clinic
1599 clinic = self
1600
Larry Hastingsbebf7352014-01-17 17:47:17 -08001601 def get_destination(self, name, default=unspecified):
1602 d = self.destinations.get(name)
1603 if not d:
1604 if default is not unspecified:
1605 return default
1606 fail("Destination does not exist: " + repr(name))
1607 return d
1608
1609 def add_destination(self, name, type, *args):
1610 if name in self.destinations:
1611 fail("Destination already exists: " + repr(name))
1612 self.destinations[name] = Destination(name, type, self, *args)
1613
Larry Hastings31826802013-10-19 00:09:25 -07001614 def parse(self, input):
1615 printer = self.printer
1616 self.block_parser = BlockParser(input, self.language, verify=self.verify)
1617 for block in self.block_parser:
1618 dsl_name = block.dsl_name
1619 if dsl_name:
1620 if dsl_name not in self.parsers:
1621 assert dsl_name in parsers, "No parser to handle {!r} block.".format(dsl_name)
1622 self.parsers[dsl_name] = parsers[dsl_name](self)
1623 parser = self.parsers[dsl_name]
Georg Brandlaabebde2014-01-16 06:53:54 +01001624 try:
1625 parser.parse(block)
1626 except Exception:
1627 fail('Exception raised during parsing:\n' +
1628 traceback.format_exc().rstrip())
Larry Hastings31826802013-10-19 00:09:25 -07001629 printer.print_block(block)
Larry Hastingsbebf7352014-01-17 17:47:17 -08001630
1631 second_pass_replacements = {}
1632
1633 for name, destination in self.destinations.items():
1634 if destination.type == 'suppress':
1635 continue
1636 output = destination._dump()
1637
1638 if destination.type == 'two-pass':
1639 if destination.id:
1640 second_pass_replacements[destination.id] = output
1641 elif output:
1642 fail("Two-pass buffer " + repr(name) + " not empty at end of file!")
1643 continue
1644
1645 if output:
1646
1647 block = Block("", dsl_name="clinic", output=output)
1648
1649 if destination.type == 'buffer':
1650 block.input = "dump " + name + "\n"
1651 warn("Destination buffer " + repr(name) + " not empty at end of file, emptying.")
1652 printer.write("\n")
1653 printer.print_block(block)
1654 continue
1655
1656 if destination.type == 'file':
1657 try:
Larry Hastingsc2047262014-01-25 20:43:29 -08001658 dirname = os.path.dirname(destination.filename)
1659 try:
1660 os.makedirs(dirname)
1661 except FileExistsError:
1662 if not os.path.isdir(dirname):
1663 fail("Can't write to destination {}, "
1664 "can't make directory {}!".format(
1665 destination.filename, dirname))
Larry Hastings581ee362014-01-28 05:00:08 -08001666 if self.verify:
1667 with open(destination.filename, "rt") as f:
1668 parser_2 = BlockParser(f.read(), language=self.language)
1669 blocks = list(parser_2)
1670 if (len(blocks) != 1) or (blocks[0].input != 'preserve\n'):
1671 fail("Modified destination file " + repr(destination.filename) + ", not overwriting!")
Larry Hastingsbebf7352014-01-17 17:47:17 -08001672 except FileNotFoundError:
1673 pass
1674
1675 block.input = 'preserve\n'
1676 printer_2 = BlockPrinter(self.language)
1677 printer_2.print_block(block)
1678 with open(destination.filename, "wt") as f:
1679 f.write(printer_2.f.getvalue())
1680 continue
1681 text = printer.f.getvalue()
1682
1683 if second_pass_replacements:
1684 printer_2 = BlockPrinter(self.language)
1685 parser_2 = BlockParser(text, self.language)
1686 changed = False
1687 for block in parser_2:
1688 if block.dsl_name:
1689 for id, replacement in second_pass_replacements.items():
1690 if id in block.output:
1691 changed = True
1692 block.output = block.output.replace(id, replacement)
1693 printer_2.print_block(block)
1694 if changed:
1695 text = printer_2.f.getvalue()
1696
1697 return text
1698
Larry Hastings31826802013-10-19 00:09:25 -07001699
1700 def _module_and_class(self, fields):
1701 """
1702 fields should be an iterable of field names.
1703 returns a tuple of (module, class).
1704 the module object could actually be self (a clinic object).
1705 this function is only ever used to find the parent of where
1706 a new class/module should go.
1707 """
1708 in_classes = False
1709 parent = module = self
1710 cls = None
1711 so_far = []
1712
1713 for field in fields:
1714 so_far.append(field)
1715 if not in_classes:
1716 child = parent.modules.get(field)
1717 if child:
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001718 parent = module = child
Larry Hastings31826802013-10-19 00:09:25 -07001719 continue
1720 in_classes = True
1721 if not hasattr(parent, 'classes'):
1722 return module, cls
1723 child = parent.classes.get(field)
1724 if not child:
1725 fail('Parent class or module ' + '.'.join(so_far) + " does not exist.")
1726 cls = parent = child
1727
1728 return module, cls
1729
1730
Larry Hastings581ee362014-01-28 05:00:08 -08001731def parse_file(filename, *, force=False, verify=True, output=None, encoding='utf-8'):
Larry Hastings31826802013-10-19 00:09:25 -07001732 extension = os.path.splitext(filename)[1][1:]
1733 if not extension:
1734 fail("Can't extract file type for file " + repr(filename))
1735
1736 try:
Larry Hastings7726ac92014-01-31 22:03:12 -08001737 language = extensions[extension](filename)
Larry Hastings31826802013-10-19 00:09:25 -07001738 except KeyError:
1739 fail("Can't identify file type for file " + repr(filename))
1740
Larry Hastings31826802013-10-19 00:09:25 -07001741 with open(filename, 'r', encoding=encoding) as f:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001742 raw = f.read()
1743
Larry Hastings2623c8c2014-02-08 22:15:29 -08001744 # exit quickly if there are no clinic markers in the file
1745 find_start_re = BlockParser("", language).find_start_re
1746 if not find_start_re.search(raw):
1747 return
1748
1749 clinic = Clinic(language, force=force, verify=verify, filename=filename)
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001750 cooked = clinic.parse(raw)
Larry Hastings581ee362014-01-28 05:00:08 -08001751 if (cooked == raw) and not force:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001752 return
Larry Hastings31826802013-10-19 00:09:25 -07001753
1754 directory = os.path.dirname(filename) or '.'
1755
1756 with tempfile.TemporaryDirectory(prefix="clinic", dir=directory) as tmpdir:
Larry Hastingsdcd340e2013-11-23 14:58:45 -08001757 bytes = cooked.encode(encoding)
Larry Hastings31826802013-10-19 00:09:25 -07001758 tmpfilename = os.path.join(tmpdir, os.path.basename(filename))
1759 with open(tmpfilename, "wb") as f:
1760 f.write(bytes)
1761 os.replace(tmpfilename, output or filename)
1762
1763
Larry Hastings581ee362014-01-28 05:00:08 -08001764def compute_checksum(input, length=None):
Larry Hastings31826802013-10-19 00:09:25 -07001765 input = input or ''
Larry Hastings581ee362014-01-28 05:00:08 -08001766 s = hashlib.sha1(input.encode('utf-8')).hexdigest()
1767 if length:
1768 s = s[:length]
1769 return s
Larry Hastings31826802013-10-19 00:09:25 -07001770
1771
1772
1773
1774class PythonParser:
1775 def __init__(self, clinic):
1776 pass
1777
1778 def parse(self, block):
1779 s = io.StringIO()
1780 with OverrideStdioWith(s):
1781 exec(block.input)
1782 block.output = s.getvalue()
1783
1784
1785class Module:
1786 def __init__(self, name, module=None):
1787 self.name = name
1788 self.module = self.parent = module
1789
1790 self.modules = collections.OrderedDict()
1791 self.classes = collections.OrderedDict()
1792 self.functions = []
1793
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001794 def __repr__(self):
1795 return "<clinic.Module " + repr(self.name) + " at " + str(id(self)) + ">"
1796
Larry Hastings31826802013-10-19 00:09:25 -07001797class Class:
Larry Hastingsc2047262014-01-25 20:43:29 -08001798 def __init__(self, name, module=None, cls=None, typedef=None, type_object=None):
Larry Hastings31826802013-10-19 00:09:25 -07001799 self.name = name
1800 self.module = module
1801 self.cls = cls
Larry Hastingsc2047262014-01-25 20:43:29 -08001802 self.typedef = typedef
1803 self.type_object = type_object
Larry Hastings31826802013-10-19 00:09:25 -07001804 self.parent = cls or module
1805
1806 self.classes = collections.OrderedDict()
1807 self.functions = []
1808
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001809 def __repr__(self):
1810 return "<clinic.Class " + repr(self.name) + " at " + str(id(self)) + ">"
1811
Larry Hastings8666e652014-01-12 14:12:59 -08001812unsupported_special_methods = set("""
Larry Hastingsed4a1c52013-11-18 09:32:13 -08001813
Larry Hastings8666e652014-01-12 14:12:59 -08001814__abs__
1815__add__
1816__and__
1817__bytes__
1818__call__
1819__complex__
1820__delitem__
1821__divmod__
1822__eq__
1823__float__
1824__floordiv__
1825__ge__
1826__getattr__
1827__getattribute__
1828__getitem__
1829__gt__
1830__hash__
1831__iadd__
1832__iand__
1833__idivmod__
1834__ifloordiv__
1835__ilshift__
1836__imod__
1837__imul__
1838__index__
1839__int__
1840__invert__
1841__ior__
1842__ipow__
1843__irshift__
1844__isub__
1845__iter__
1846__itruediv__
1847__ixor__
1848__le__
1849__len__
1850__lshift__
1851__lt__
1852__mod__
1853__mul__
1854__neg__
1855__new__
1856__next__
1857__or__
1858__pos__
1859__pow__
1860__radd__
1861__rand__
1862__rdivmod__
1863__repr__
1864__rfloordiv__
1865__rlshift__
1866__rmod__
1867__rmul__
1868__ror__
1869__round__
1870__rpow__
1871__rrshift__
1872__rshift__
1873__rsub__
1874__rtruediv__
1875__rxor__
1876__setattr__
1877__setitem__
1878__str__
1879__sub__
1880__truediv__
1881__xor__
1882
1883""".strip().split())
1884
1885
Larry Hastings5c661892014-01-24 06:17:25 -08001886INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW = """
1887INVALID, CALLABLE, STATIC_METHOD, CLASS_METHOD, METHOD_INIT, METHOD_NEW
1888""".replace(",", "").strip().split()
Larry Hastings31826802013-10-19 00:09:25 -07001889
1890class Function:
1891 """
1892 Mutable duck type for inspect.Function.
1893
1894 docstring - a str containing
1895 * embedded line breaks
1896 * text outdented to the left margin
1897 * no trailing whitespace.
1898 It will always be true that
1899 (not docstring) or ((not docstring[0].isspace()) and (docstring.rstrip() == docstring))
1900 """
1901
1902 def __init__(self, parameters=None, *, name,
1903 module, cls=None, c_basename=None,
1904 full_name=None,
1905 return_converter, return_annotation=_empty,
Larry Hastings581ee362014-01-28 05:00:08 -08001906 docstring=None, kind=CALLABLE, coexist=False,
Larry Hastings2623c8c2014-02-08 22:15:29 -08001907 docstring_only=False):
Larry Hastings31826802013-10-19 00:09:25 -07001908 self.parameters = parameters or collections.OrderedDict()
1909 self.return_annotation = return_annotation
1910 self.name = name
1911 self.full_name = full_name
1912 self.module = module
1913 self.cls = cls
1914 self.parent = cls or module
1915 self.c_basename = c_basename
1916 self.return_converter = return_converter
1917 self.docstring = docstring or ''
1918 self.kind = kind
1919 self.coexist = coexist
Larry Hastingsebdcb502013-11-23 14:54:00 -08001920 self.self_converter = None
Larry Hastings2623c8c2014-02-08 22:15:29 -08001921 # docstring_only means "don't generate a machine-readable
1922 # signature, just a normal docstring". it's True for
1923 # functions with optional groups because we can't represent
1924 # those accurately with inspect.Signature in 3.4.
1925 self.docstring_only = docstring_only
Larry Hastingsebdcb502013-11-23 14:54:00 -08001926
Larry Hastings7726ac92014-01-31 22:03:12 -08001927 self.rendered_parameters = None
1928
1929 __render_parameters__ = None
1930 @property
1931 def render_parameters(self):
1932 if not self.__render_parameters__:
1933 self.__render_parameters__ = l = []
1934 for p in self.parameters.values():
1935 p = p.copy()
1936 p.converter.pre_render()
1937 l.append(p)
1938 return self.__render_parameters__
1939
Larry Hastingsebdcb502013-11-23 14:54:00 -08001940 @property
1941 def methoddef_flags(self):
Larry Hastings8666e652014-01-12 14:12:59 -08001942 if self.kind in (METHOD_INIT, METHOD_NEW):
1943 return None
Larry Hastingsebdcb502013-11-23 14:54:00 -08001944 flags = []
1945 if self.kind == CLASS_METHOD:
1946 flags.append('METH_CLASS')
1947 elif self.kind == STATIC_METHOD:
1948 flags.append('METH_STATIC')
1949 else:
1950 assert self.kind == CALLABLE, "unknown kind: " + repr(self.kind)
1951 if self.coexist:
1952 flags.append('METH_COEXIST')
1953 return '|'.join(flags)
Larry Hastings31826802013-10-19 00:09:25 -07001954
1955 def __repr__(self):
1956 return '<clinic.Function ' + self.name + '>'
1957
Larry Hastings7726ac92014-01-31 22:03:12 -08001958 def copy(self, **overrides):
1959 kwargs = {
1960 'name': self.name, 'module': self.module, 'parameters': self.parameters,
1961 'cls': self.cls, 'c_basename': self.c_basename,
1962 'full_name': self.full_name,
1963 'return_converter': self.return_converter, 'return_annotation': self.return_annotation,
1964 'docstring': self.docstring, 'kind': self.kind, 'coexist': self.coexist,
Larry Hastings2623c8c2014-02-08 22:15:29 -08001965 'docstring_only': self.docstring_only,
Larry Hastings7726ac92014-01-31 22:03:12 -08001966 }
1967 kwargs.update(overrides)
1968 f = Function(**kwargs)
1969
1970 parameters = collections.OrderedDict()
1971 for name, value in f.parameters.items():
1972 value = value.copy(function=f)
1973 parameters[name] = value
1974 f.parameters = parameters
1975 return f
1976
Larry Hastings31826802013-10-19 00:09:25 -07001977
1978class Parameter:
1979 """
1980 Mutable duck type of inspect.Parameter.
1981 """
1982
1983 def __init__(self, name, kind, *, default=_empty,
1984 function, converter, annotation=_empty,
1985 docstring=None, group=0):
1986 self.name = name
1987 self.kind = kind
1988 self.default = default
1989 self.function = function
1990 self.converter = converter
1991 self.annotation = annotation
1992 self.docstring = docstring or ''
1993 self.group = group
1994
1995 def __repr__(self):
1996 return '<clinic.Parameter ' + self.name + '>'
1997
1998 def is_keyword_only(self):
1999 return self.kind == inspect.Parameter.KEYWORD_ONLY
2000
Larry Hastings2623c8c2014-02-08 22:15:29 -08002001 def is_positional_only(self):
2002 return self.kind == inspect.Parameter.POSITIONAL_ONLY
2003
Larry Hastings7726ac92014-01-31 22:03:12 -08002004 def copy(self, **overrides):
2005 kwargs = {
2006 'name': self.name, 'kind': self.kind, 'default':self.default,
2007 'function': self.function, 'converter': self.converter, 'annotation': self.annotation,
2008 'docstring': self.docstring, 'group': self.group,
2009 }
2010 kwargs.update(overrides)
2011 if 'converter' not in overrides:
2012 converter = copy.copy(self.converter)
2013 converter.function = kwargs['function']
2014 kwargs['converter'] = converter
2015 return Parameter(**kwargs)
2016
2017
2018
2019class LandMine:
2020 # try to access any
2021 def __init__(self, message):
2022 self.__message__ = message
2023
2024 def __repr__(self):
2025 return '<LandMine ' + repr(self.__message__) + ">"
2026
2027 def __getattribute__(self, name):
2028 if name in ('__repr__', '__message__'):
2029 return super().__getattribute__(name)
2030 # raise RuntimeError(repr(name))
2031 fail("Stepped on a land mine, trying to access attribute " + repr(name) + ":\n" + self.__message__)
Larry Hastings31826802013-10-19 00:09:25 -07002032
Larry Hastings31826802013-10-19 00:09:25 -07002033
2034def add_c_converter(f, name=None):
2035 if not name:
2036 name = f.__name__
2037 if not name.endswith('_converter'):
2038 return f
2039 name = name[:-len('_converter')]
2040 converters[name] = f
2041 return f
2042
2043def add_default_legacy_c_converter(cls):
2044 # automatically add converter for default format unit
2045 # (but without stomping on the existing one if it's already
2046 # set, in case you subclass)
Larry Hastingsf1503782014-06-11 04:31:29 -07002047 if ((cls.format_unit not in ('O&', '')) and
Larry Hastings31826802013-10-19 00:09:25 -07002048 (cls.format_unit not in legacy_converters)):
2049 legacy_converters[cls.format_unit] = cls
2050 return cls
2051
2052def add_legacy_c_converter(format_unit, **kwargs):
2053 """
2054 Adds a legacy converter.
2055 """
2056 def closure(f):
2057 if not kwargs:
2058 added_f = f
2059 else:
2060 added_f = functools.partial(f, **kwargs)
Larry Hastings7726ac92014-01-31 22:03:12 -08002061 if format_unit:
2062 legacy_converters[format_unit] = added_f
Larry Hastings31826802013-10-19 00:09:25 -07002063 return f
2064 return closure
2065
2066class CConverterAutoRegister(type):
2067 def __init__(cls, name, bases, classdict):
2068 add_c_converter(cls)
2069 add_default_legacy_c_converter(cls)
2070
2071class CConverter(metaclass=CConverterAutoRegister):
2072 """
2073 For the init function, self, name, function, and default
2074 must be keyword-or-positional parameters. All other
Larry Hastings2a727912014-01-16 11:32:01 -08002075 parameters must be keyword-only.
Larry Hastings31826802013-10-19 00:09:25 -07002076 """
2077
Larry Hastings7726ac92014-01-31 22:03:12 -08002078 # The C name to use for this variable.
2079 name = None
2080
2081 # The Python name to use for this variable.
2082 py_name = None
2083
Larry Hastings78cf85c2014-01-04 12:44:57 -08002084 # The C type to use for this variable.
2085 # 'type' should be a Python string specifying the type, e.g. "int".
2086 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07002087 type = None
Larry Hastings31826802013-10-19 00:09:25 -07002088
2089 # The Python default value for this parameter, as a Python value.
Larry Hastings78cf85c2014-01-04 12:44:57 -08002090 # Or the magic value "unspecified" if there is no default.
Larry Hastings2a727912014-01-16 11:32:01 -08002091 # Or the magic value "unknown" if this value is a cannot be evaluated
2092 # at Argument-Clinic-preprocessing time (but is presumed to be valid
2093 # at runtime).
Larry Hastings31826802013-10-19 00:09:25 -07002094 default = unspecified
2095
Larry Hastings4a55fc52014-01-12 11:09:57 -08002096 # If not None, default must be isinstance() of this type.
2097 # (You can also specify a tuple of types.)
2098 default_type = None
2099
Larry Hastings31826802013-10-19 00:09:25 -07002100 # "default" converted into a C value, as a string.
2101 # Or None if there is no default.
2102 c_default = None
2103
Larry Hastings2a727912014-01-16 11:32:01 -08002104 # "default" converted into a Python value, as a string.
2105 # Or None if there is no default.
2106 py_default = None
2107
Larry Hastingsabc716b2013-11-20 09:13:52 -08002108 # The default value used to initialize the C variable when
2109 # there is no default, but not specifying a default may
2110 # result in an "uninitialized variable" warning. This can
2111 # easily happen when using option groups--although
2112 # properly-written code won't actually use the variable,
2113 # the variable does get passed in to the _impl. (Ah, if
2114 # only dataflow analysis could inline the static function!)
2115 #
2116 # This value is specified as a string.
2117 # Every non-abstract subclass should supply a valid value.
2118 c_ignored_default = 'NULL'
2119
Larry Hastings31826802013-10-19 00:09:25 -07002120 # The C converter *function* to be used, if any.
2121 # (If this is not None, format_unit must be 'O&'.)
2122 converter = None
Larry Hastingsebdcb502013-11-23 14:54:00 -08002123
Larry Hastings78cf85c2014-01-04 12:44:57 -08002124 # Should Argument Clinic add a '&' before the name of
2125 # the variable when passing it into the _impl function?
Larry Hastings31826802013-10-19 00:09:25 -07002126 impl_by_reference = False
Larry Hastings78cf85c2014-01-04 12:44:57 -08002127
2128 # Should Argument Clinic add a '&' before the name of
2129 # the variable when passing it into PyArg_ParseTuple (AndKeywords)?
Larry Hastings31826802013-10-19 00:09:25 -07002130 parse_by_reference = True
Larry Hastings78cf85c2014-01-04 12:44:57 -08002131
2132 #############################################################
2133 #############################################################
2134 ## You shouldn't need to read anything below this point to ##
2135 ## write your own converter functions. ##
2136 #############################################################
2137 #############################################################
2138
2139 # The "format unit" to specify for this variable when
2140 # parsing arguments using PyArg_ParseTuple (AndKeywords).
2141 # Custom converters should always use the default value of 'O&'.
2142 format_unit = 'O&'
2143
2144 # What encoding do we want for this variable? Only used
2145 # by format units starting with 'e'.
2146 encoding = None
2147
Larry Hastings77561cc2014-01-07 12:13:13 -08002148 # Should this object be required to be a subclass of a specific type?
2149 # If not None, should be a string representing a pointer to a
2150 # PyTypeObject (e.g. "&PyUnicode_Type").
2151 # Only used by the 'O!' format unit (and the "object" converter).
2152 subclass_of = None
2153
Larry Hastings78cf85c2014-01-04 12:44:57 -08002154 # Do we want an adjacent '_length' variable for this variable?
2155 # Only used by format units ending with '#'.
Larry Hastings31826802013-10-19 00:09:25 -07002156 length = False
2157
Larry Hastings5c661892014-01-24 06:17:25 -08002158 # Should we show this parameter in the generated
2159 # __text_signature__? This is *almost* always True.
Larry Hastingsc2047262014-01-25 20:43:29 -08002160 # (It's only False for __new__, __init__, and METH_STATIC functions.)
Larry Hastings5c661892014-01-24 06:17:25 -08002161 show_in_signature = True
2162
2163 # Overrides the name used in a text signature.
2164 # The name used for a "self" parameter must be one of
2165 # self, type, or module; however users can set their own.
2166 # This lets the self_converter overrule the user-settable
2167 # name, *just* for the text signature.
2168 # Only set by self_converter.
2169 signature_name = None
2170
2171 # keep in sync with self_converter.__init__!
Larry Hastings7726ac92014-01-31 22:03:12 -08002172 def __init__(self, name, py_name, function, default=unspecified, *, c_default=None, py_default=None, annotation=unspecified, **kwargs):
Larry Hastings31826802013-10-19 00:09:25 -07002173 self.name = name
Larry Hastings7726ac92014-01-31 22:03:12 -08002174 self.py_name = py_name
Larry Hastings31826802013-10-19 00:09:25 -07002175
2176 if default is not unspecified:
Larry Hastings2a727912014-01-16 11:32:01 -08002177 if self.default_type and not isinstance(default, (self.default_type, Unknown)):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002178 if isinstance(self.default_type, type):
2179 types_str = self.default_type.__name__
2180 else:
2181 types_str = ', '.join((cls.__name__ for cls in self.default_type))
2182 fail("{}: default value {!r} for field {} is not of type {}".format(
2183 self.__class__.__name__, default, name, types_str))
Larry Hastings31826802013-10-19 00:09:25 -07002184 self.default = default
Larry Hastings2a727912014-01-16 11:32:01 -08002185
Larry Hastingsb4705752014-01-18 21:54:15 -08002186 if c_default:
2187 self.c_default = c_default
2188 if py_default:
2189 self.py_default = py_default
Larry Hastings2a727912014-01-16 11:32:01 -08002190
Larry Hastings31826802013-10-19 00:09:25 -07002191 if annotation != unspecified:
2192 fail("The 'annotation' parameter is not currently permitted.")
Larry Hastings7726ac92014-01-31 22:03:12 -08002193
2194 # this is deliberate, to prevent you from caching information
2195 # about the function in the init.
2196 # (that breaks if we get cloned.)
2197 # so after this change we will noisily fail.
2198 self.function = LandMine("Don't access members of self.function inside converter_init!")
Larry Hastings31826802013-10-19 00:09:25 -07002199 self.converter_init(**kwargs)
Larry Hastings7726ac92014-01-31 22:03:12 -08002200 self.function = function
Larry Hastings31826802013-10-19 00:09:25 -07002201
2202 def converter_init(self):
2203 pass
2204
2205 def is_optional(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002206 return (self.default is not unspecified)
Larry Hastings31826802013-10-19 00:09:25 -07002207
Larry Hastings5c661892014-01-24 06:17:25 -08002208 def _render_self(self, parameter, data):
2209 self.parameter = parameter
2210 original_name = self.name
2211 name = ensure_legal_c_identifier(original_name)
2212
2213 # impl_arguments
2214 s = ("&" if self.impl_by_reference else "") + name
2215 data.impl_arguments.append(s)
2216 if self.length:
2217 data.impl_arguments.append(self.length_name())
2218
2219 # impl_parameters
2220 data.impl_parameters.append(self.simple_declaration(by_reference=self.impl_by_reference))
2221 if self.length:
2222 data.impl_parameters.append("Py_ssize_clean_t " + self.length_name())
2223
2224 def _render_non_self(self, parameter, data):
Larry Hastingsabc716b2013-11-20 09:13:52 -08002225 self.parameter = parameter
Larry Hastings90261132014-01-07 12:21:08 -08002226 original_name = self.name
2227 name = ensure_legal_c_identifier(original_name)
Larry Hastings31826802013-10-19 00:09:25 -07002228
2229 # declarations
2230 d = self.declaration()
2231 data.declarations.append(d)
2232
2233 # initializers
2234 initializers = self.initialize()
2235 if initializers:
2236 data.initializers.append('/* initializers for ' + name + ' */\n' + initializers.rstrip())
2237
Larry Hastingsc2047262014-01-25 20:43:29 -08002238 # modifications
2239 modifications = self.modify()
2240 if modifications:
2241 data.modifications.append('/* modifications for ' + name + ' */\n' + modifications.rstrip())
2242
Larry Hastings31826802013-10-19 00:09:25 -07002243 # keywords
Larry Hastings7726ac92014-01-31 22:03:12 -08002244 data.keywords.append(parameter.name)
Larry Hastings31826802013-10-19 00:09:25 -07002245
2246 # format_units
2247 if self.is_optional() and '|' not in data.format_units:
2248 data.format_units.append('|')
2249 if parameter.is_keyword_only() and '$' not in data.format_units:
2250 data.format_units.append('$')
2251 data.format_units.append(self.format_unit)
2252
2253 # parse_arguments
2254 self.parse_argument(data.parse_arguments)
2255
Larry Hastings31826802013-10-19 00:09:25 -07002256 # cleanup
2257 cleanup = self.cleanup()
2258 if cleanup:
2259 data.cleanup.append('/* Cleanup for ' + name + ' */\n' + cleanup.rstrip() + "\n")
2260
Larry Hastings5c661892014-01-24 06:17:25 -08002261 def render(self, parameter, data):
2262 """
2263 parameter is a clinic.Parameter instance.
2264 data is a CRenderData instance.
2265 """
2266 self._render_self(parameter, data)
2267 self._render_non_self(parameter, data)
2268
Larry Hastingsebdcb502013-11-23 14:54:00 -08002269 def length_name(self):
2270 """Computes the name of the associated "length" variable."""
2271 if not self.length:
2272 return None
2273 return ensure_legal_c_identifier(self.name) + "_length"
2274
Larry Hastings31826802013-10-19 00:09:25 -07002275 # Why is this one broken out separately?
2276 # For "positional-only" function parsing,
2277 # which generates a bunch of PyArg_ParseTuple calls.
2278 def parse_argument(self, list):
2279 assert not (self.converter and self.encoding)
2280 if self.format_unit == 'O&':
2281 assert self.converter
2282 list.append(self.converter)
2283
2284 if self.encoding:
Larry Hastings77561cc2014-01-07 12:13:13 -08002285 list.append(c_repr(self.encoding))
2286 elif self.subclass_of:
2287 list.append(self.subclass_of)
Larry Hastings31826802013-10-19 00:09:25 -07002288
Larry Hastingsebdcb502013-11-23 14:54:00 -08002289 legal_name = ensure_legal_c_identifier(self.name)
2290 s = ("&" if self.parse_by_reference else "") + legal_name
Larry Hastings31826802013-10-19 00:09:25 -07002291 list.append(s)
2292
Larry Hastingsebdcb502013-11-23 14:54:00 -08002293 if self.length:
2294 list.append("&" + self.length_name())
2295
Larry Hastings31826802013-10-19 00:09:25 -07002296 #
2297 # All the functions after here are intended as extension points.
2298 #
2299
2300 def simple_declaration(self, by_reference=False):
2301 """
2302 Computes the basic declaration of the variable.
2303 Used in computing the prototype declaration and the
2304 variable declaration.
2305 """
2306 prototype = [self.type]
2307 if by_reference or not self.type.endswith('*'):
2308 prototype.append(" ")
2309 if by_reference:
2310 prototype.append('*')
Larry Hastingsdfcd4672013-10-27 02:49:39 -07002311 prototype.append(ensure_legal_c_identifier(self.name))
Larry Hastings31826802013-10-19 00:09:25 -07002312 return "".join(prototype)
2313
2314 def declaration(self):
2315 """
2316 The C statement to declare this variable.
2317 """
2318 declaration = [self.simple_declaration()]
Larry Hastingsabc716b2013-11-20 09:13:52 -08002319 default = self.c_default
2320 if not default and self.parameter.group:
2321 default = self.c_ignored_default
2322 if default:
Larry Hastings31826802013-10-19 00:09:25 -07002323 declaration.append(" = ")
Larry Hastingsabc716b2013-11-20 09:13:52 -08002324 declaration.append(default)
Larry Hastings31826802013-10-19 00:09:25 -07002325 declaration.append(";")
Larry Hastingsebdcb502013-11-23 14:54:00 -08002326 if self.length:
2327 declaration.append('\nPy_ssize_clean_t ')
2328 declaration.append(self.length_name())
2329 declaration.append(';')
Larry Hastings3f144c22014-01-06 10:34:00 -08002330 s = "".join(declaration)
2331 # double up curly-braces, this string will be used
2332 # as part of a format_map() template later
2333 s = s.replace("{", "{{")
2334 s = s.replace("}", "}}")
2335 return s
Larry Hastings31826802013-10-19 00:09:25 -07002336
2337 def initialize(self):
2338 """
2339 The C statements required to set up this variable before parsing.
2340 Returns a string containing this code indented at column 0.
2341 If no initialization is necessary, returns an empty string.
2342 """
2343 return ""
2344
Larry Hastingsc2047262014-01-25 20:43:29 -08002345 def modify(self):
2346 """
2347 The C statements required to modify this variable after parsing.
2348 Returns a string containing this code indented at column 0.
2349 If no initialization is necessary, returns an empty string.
2350 """
2351 return ""
2352
Larry Hastings31826802013-10-19 00:09:25 -07002353 def cleanup(self):
2354 """
2355 The C statements required to clean up after this variable.
2356 Returns a string containing this code indented at column 0.
2357 If no cleanup is necessary, returns an empty string.
2358 """
2359 return ""
2360
Larry Hastings7726ac92014-01-31 22:03:12 -08002361 def pre_render(self):
2362 """
2363 A second initialization function, like converter_init,
2364 called just before rendering.
2365 You are permitted to examine self.function here.
2366 """
2367 pass
2368
Larry Hastings31826802013-10-19 00:09:25 -07002369
2370class bool_converter(CConverter):
2371 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002372 default_type = bool
Larry Hastings31826802013-10-19 00:09:25 -07002373 format_unit = 'p'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002374 c_ignored_default = '0'
Larry Hastings31826802013-10-19 00:09:25 -07002375
2376 def converter_init(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002377 if self.default is not unspecified:
2378 self.default = bool(self.default)
2379 self.c_default = str(int(self.default))
Larry Hastings31826802013-10-19 00:09:25 -07002380
2381class char_converter(CConverter):
2382 type = 'char'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002383 default_type = str
Larry Hastings31826802013-10-19 00:09:25 -07002384 format_unit = 'c'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002385 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002386
Larry Hastings4a55fc52014-01-12 11:09:57 -08002387 def converter_init(self):
Larry Hastings2a727912014-01-16 11:32:01 -08002388 if isinstance(self.default, str) and (len(self.default) != 1):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002389 fail("char_converter: illegal default value " + repr(self.default))
2390
2391
Larry Hastings31826802013-10-19 00:09:25 -07002392@add_legacy_c_converter('B', bitwise=True)
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002393class unsigned_char_converter(CConverter):
Serhiy Storchaka49776ef2014-01-19 00:38:36 +02002394 type = 'unsigned char'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002395 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002396 format_unit = 'b'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002397 c_ignored_default = "'\0'"
Larry Hastings31826802013-10-19 00:09:25 -07002398
2399 def converter_init(self, *, bitwise=False):
2400 if bitwise:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002401 self.format_unit = 'B'
Larry Hastings31826802013-10-19 00:09:25 -07002402
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002403class byte_converter(unsigned_char_converter): pass
2404
Larry Hastings31826802013-10-19 00:09:25 -07002405class short_converter(CConverter):
2406 type = 'short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002407 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002408 format_unit = 'h'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002409 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002410
2411class unsigned_short_converter(CConverter):
2412 type = 'unsigned short'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002413 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002414 format_unit = 'H'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002415 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002416
2417 def converter_init(self, *, bitwise=False):
2418 if not bitwise:
2419 fail("Unsigned shorts must be bitwise (for now).")
2420
Larry Hastingsebdcb502013-11-23 14:54:00 -08002421@add_legacy_c_converter('C', types='str')
Larry Hastings31826802013-10-19 00:09:25 -07002422class int_converter(CConverter):
2423 type = 'int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002424 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002425 format_unit = 'i'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002426 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002427
Larry Hastingsebdcb502013-11-23 14:54:00 -08002428 def converter_init(self, *, types='int'):
2429 if types == 'str':
2430 self.format_unit = 'C'
2431 elif types != 'int':
2432 fail("int_converter: illegal 'types' argument")
Larry Hastings31826802013-10-19 00:09:25 -07002433
2434class unsigned_int_converter(CConverter):
2435 type = 'unsigned int'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002436 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002437 format_unit = 'I'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002438 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002439
2440 def converter_init(self, *, bitwise=False):
2441 if not bitwise:
2442 fail("Unsigned ints must be bitwise (for now).")
2443
2444class long_converter(CConverter):
2445 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002446 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002447 format_unit = 'l'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002448 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002449
2450class unsigned_long_converter(CConverter):
2451 type = 'unsigned long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002452 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002453 format_unit = 'k'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002454 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002455
2456 def converter_init(self, *, bitwise=False):
2457 if not bitwise:
2458 fail("Unsigned longs must be bitwise (for now).")
2459
2460class PY_LONG_LONG_converter(CConverter):
2461 type = 'PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002462 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002463 format_unit = 'L'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002464 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002465
2466class unsigned_PY_LONG_LONG_converter(CConverter):
2467 type = 'unsigned PY_LONG_LONG'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002468 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002469 format_unit = 'K'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002470 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002471
2472 def converter_init(self, *, bitwise=False):
2473 if not bitwise:
2474 fail("Unsigned PY_LONG_LONGs must be bitwise (for now).")
2475
2476class Py_ssize_t_converter(CConverter):
2477 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002478 default_type = int
Larry Hastings31826802013-10-19 00:09:25 -07002479 format_unit = 'n'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002480 c_ignored_default = "0"
Larry Hastings31826802013-10-19 00:09:25 -07002481
2482
2483class float_converter(CConverter):
2484 type = 'float'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002485 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002486 format_unit = 'f'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002487 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002488
2489class double_converter(CConverter):
2490 type = 'double'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002491 default_type = float
Larry Hastings31826802013-10-19 00:09:25 -07002492 format_unit = 'd'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002493 c_ignored_default = "0.0"
Larry Hastings31826802013-10-19 00:09:25 -07002494
2495
2496class Py_complex_converter(CConverter):
2497 type = 'Py_complex'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002498 default_type = complex
Larry Hastings31826802013-10-19 00:09:25 -07002499 format_unit = 'D'
Larry Hastingsabc716b2013-11-20 09:13:52 -08002500 c_ignored_default = "{0.0, 0.0}"
Larry Hastings31826802013-10-19 00:09:25 -07002501
2502
2503class object_converter(CConverter):
2504 type = 'PyObject *'
2505 format_unit = 'O'
2506
Larry Hastings4a55fc52014-01-12 11:09:57 -08002507 def converter_init(self, *, converter=None, type=None, subclass_of=None):
2508 if converter:
2509 if subclass_of:
2510 fail("object: Cannot pass in both 'converter' and 'subclass_of'")
2511 self.format_unit = 'O&'
2512 self.converter = converter
2513 elif subclass_of:
Larry Hastings31826802013-10-19 00:09:25 -07002514 self.format_unit = 'O!'
Larry Hastings77561cc2014-01-07 12:13:13 -08002515 self.subclass_of = subclass_of
Larry Hastings4a55fc52014-01-12 11:09:57 -08002516
Larry Hastings77561cc2014-01-07 12:13:13 -08002517 if type is not None:
2518 self.type = type
Larry Hastings31826802013-10-19 00:09:25 -07002519
2520
Larry Hastingsebdcb502013-11-23 14:54:00 -08002521@add_legacy_c_converter('s#', length=True)
Larry Hastings2a727912014-01-16 11:32:01 -08002522@add_legacy_c_converter('y', types="bytes")
2523@add_legacy_c_converter('y#', types="bytes", length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002524@add_legacy_c_converter('z', nullable=True)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002525@add_legacy_c_converter('z#', nullable=True, length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002526class str_converter(CConverter):
2527 type = 'const char *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002528 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002529 format_unit = 's'
2530
Larry Hastingsebdcb502013-11-23 14:54:00 -08002531 def converter_init(self, *, encoding=None, types="str",
2532 length=False, nullable=False, zeroes=False):
2533
2534 types = set(types.strip().split())
2535 bytes_type = set(("bytes",))
2536 str_type = set(("str",))
2537 all_3_type = set(("bytearray",)) | bytes_type | str_type
2538 is_bytes = types == bytes_type
2539 is_str = types == str_type
2540 is_all_3 = types == all_3_type
2541
2542 self.length = bool(length)
2543 format_unit = None
2544
2545 if encoding:
2546 self.encoding = encoding
2547
2548 if is_str and not (length or zeroes or nullable):
2549 format_unit = 'es'
2550 elif is_all_3 and not (length or zeroes or nullable):
2551 format_unit = 'et'
2552 elif is_str and length and zeroes and not nullable:
2553 format_unit = 'es#'
2554 elif is_all_3 and length and not (nullable or zeroes):
2555 format_unit = 'et#'
2556
2557 if format_unit.endswith('#'):
Larry Hastings5c661892014-01-24 06:17:25 -08002558 fail("Sorry: code using format unit ", repr(format_unit), "probably doesn't work properly yet.\nGive Larry your test case and he'll it.")
Larry Hastingsebdcb502013-11-23 14:54:00 -08002559 # TODO set pointer to NULL
2560 # TODO add cleanup for buffer
2561 pass
2562
2563 else:
2564 if zeroes:
2565 fail("str_converter: illegal combination of arguments (zeroes is only legal with an encoding)")
2566
2567 if is_bytes and not (nullable or length):
2568 format_unit = 'y'
2569 elif is_bytes and length and not nullable:
2570 format_unit = 'y#'
2571 elif is_str and not (nullable or length):
2572 format_unit = 's'
2573 elif is_str and length and not nullable:
2574 format_unit = 's#'
2575 elif is_str and nullable and not length:
2576 format_unit = 'z'
2577 elif is_str and nullable and length:
2578 format_unit = 'z#'
2579
2580 if not format_unit:
2581 fail("str_converter: illegal combination of arguments")
2582 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002583
2584
2585class PyBytesObject_converter(CConverter):
2586 type = 'PyBytesObject *'
2587 format_unit = 'S'
2588
2589class PyByteArrayObject_converter(CConverter):
2590 type = 'PyByteArrayObject *'
2591 format_unit = 'Y'
2592
2593class unicode_converter(CConverter):
2594 type = 'PyObject *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002595 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002596 format_unit = 'U'
2597
Larry Hastingsebdcb502013-11-23 14:54:00 -08002598@add_legacy_c_converter('u#', length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002599@add_legacy_c_converter('Z', nullable=True)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002600@add_legacy_c_converter('Z#', nullable=True, length=True)
Larry Hastings31826802013-10-19 00:09:25 -07002601class Py_UNICODE_converter(CConverter):
2602 type = 'Py_UNICODE *'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002603 default_type = (str, Null, NoneType)
Larry Hastings31826802013-10-19 00:09:25 -07002604 format_unit = 'u'
2605
Larry Hastingsebdcb502013-11-23 14:54:00 -08002606 def converter_init(self, *, nullable=False, length=False):
2607 format_unit = 'Z' if nullable else 'u'
2608 if length:
2609 format_unit += '#'
2610 self.length = True
2611 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002612
Larry Hastingsebdcb502013-11-23 14:54:00 -08002613#
2614# We define three string conventions for buffer types in the 'types' argument:
2615# 'buffer' : any object supporting the buffer interface
2616# 'rwbuffer': any object supporting the buffer interface, but must be writeable
2617# 'robuffer': any object supporting the buffer interface, but must not be writeable
2618#
2619@add_legacy_c_converter('s*', types='str bytes bytearray buffer')
2620@add_legacy_c_converter('z*', types='str bytes bytearray buffer', nullable=True)
2621@add_legacy_c_converter('w*', types='bytearray rwbuffer')
Larry Hastings31826802013-10-19 00:09:25 -07002622class Py_buffer_converter(CConverter):
2623 type = 'Py_buffer'
2624 format_unit = 'y*'
2625 impl_by_reference = True
Larry Hastings4a55fc52014-01-12 11:09:57 -08002626 c_ignored_default = "{NULL, NULL}"
Larry Hastings31826802013-10-19 00:09:25 -07002627
Larry Hastingsebdcb502013-11-23 14:54:00 -08002628 def converter_init(self, *, types='bytes bytearray buffer', nullable=False):
Larry Hastings4a55fc52014-01-12 11:09:57 -08002629 if self.default not in (unspecified, None):
2630 fail("The only legal default value for Py_buffer is None.")
Larry Hastings3f144c22014-01-06 10:34:00 -08002631 self.c_default = self.c_ignored_default
Larry Hastingsebdcb502013-11-23 14:54:00 -08002632 types = set(types.strip().split())
2633 bytes_type = set(('bytes',))
2634 bytearray_type = set(('bytearray',))
2635 buffer_type = set(('buffer',))
2636 rwbuffer_type = set(('rwbuffer',))
2637 robuffer_type = set(('robuffer',))
2638 str_type = set(('str',))
2639 bytes_bytearray_buffer_type = bytes_type | bytearray_type | buffer_type
2640
2641 format_unit = None
2642 if types == (str_type | bytes_bytearray_buffer_type):
2643 format_unit = 's*' if not nullable else 'z*'
Larry Hastings31826802013-10-19 00:09:25 -07002644 else:
Larry Hastingsebdcb502013-11-23 14:54:00 -08002645 if nullable:
2646 fail('Py_buffer_converter: illegal combination of arguments (nullable=True)')
2647 elif types == (bytes_bytearray_buffer_type):
2648 format_unit = 'y*'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002649 elif types == (bytearray_type | rwbuffer_type):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002650 format_unit = 'w*'
2651 if not format_unit:
2652 fail("Py_buffer_converter: illegal combination of arguments")
2653
2654 self.format_unit = format_unit
Larry Hastings31826802013-10-19 00:09:25 -07002655
2656 def cleanup(self):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002657 name = ensure_legal_c_identifier(self.name)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002658 return "".join(["if (", name, ".obj)\n PyBuffer_Release(&", name, ");\n"])
Larry Hastingsebdcb502013-11-23 14:54:00 -08002659
2660
Larry Hastings5c661892014-01-24 06:17:25 -08002661def correct_name_for_self(f):
2662 if f.kind in (CALLABLE, METHOD_INIT):
2663 if f.cls:
2664 return "PyObject *", "self"
2665 return "PyModuleDef *", "module"
2666 if f.kind == STATIC_METHOD:
2667 return "void *", "null"
2668 if f.kind in (CLASS_METHOD, METHOD_NEW):
2669 return "PyTypeObject *", "type"
2670 raise RuntimeError("Unhandled type of function f: " + repr(f.kind))
2671
Larry Hastingsc2047262014-01-25 20:43:29 -08002672def required_type_for_self_for_parser(f):
2673 type, _ = correct_name_for_self(f)
2674 if f.kind in (METHOD_INIT, METHOD_NEW, STATIC_METHOD, CLASS_METHOD):
2675 return type
2676 return None
2677
Larry Hastings5c661892014-01-24 06:17:25 -08002678
Larry Hastingsebdcb502013-11-23 14:54:00 -08002679class self_converter(CConverter):
2680 """
2681 A special-case converter:
2682 this is the default converter used for "self".
2683 """
Larry Hastings5c661892014-01-24 06:17:25 -08002684 type = None
2685 format_unit = ''
2686
Larry Hastings78cf85c2014-01-04 12:44:57 -08002687 def converter_init(self, *, type=None):
Larry Hastings7726ac92014-01-31 22:03:12 -08002688 self.specified_type = type
2689
2690 def pre_render(self):
Larry Hastingsebdcb502013-11-23 14:54:00 -08002691 f = self.function
Larry Hastings5c661892014-01-24 06:17:25 -08002692 default_type, default_name = correct_name_for_self(f)
2693 self.signature_name = default_name
Larry Hastings7726ac92014-01-31 22:03:12 -08002694 self.type = self.specified_type or self.type or default_type
Larry Hastingsebdcb502013-11-23 14:54:00 -08002695
Larry Hastings5c661892014-01-24 06:17:25 -08002696 kind = self.function.kind
2697 new_or_init = kind in (METHOD_NEW, METHOD_INIT)
2698
2699 if (kind == STATIC_METHOD) or new_or_init:
2700 self.show_in_signature = False
2701
2702 # tp_new (METHOD_NEW) functions are of type newfunc:
2703 # typedef PyObject *(*newfunc)(struct _typeobject *, PyObject *, PyObject *);
2704 # PyTypeObject is a typedef for struct _typeobject.
2705 #
2706 # tp_init (METHOD_INIT) functions are of type initproc:
2707 # typedef int (*initproc)(PyObject *, PyObject *, PyObject *);
2708 #
2709 # All other functions generated by Argument Clinic are stored in
2710 # PyMethodDef structures, in the ml_meth slot, which is of type PyCFunction:
2711 # typedef PyObject *(*PyCFunction)(PyObject *, PyObject *);
2712 # However! We habitually cast these functions to PyCFunction,
2713 # since functions that accept keyword arguments don't fit this signature
2714 # but are stored there anyway. So strict type equality isn't important
2715 # for these functions.
2716 #
2717 # So:
2718 #
2719 # * The name of the first parameter to the impl and the parsing function will always
2720 # be self.name.
2721 #
2722 # * The type of the first parameter to the impl will always be of self.type.
2723 #
2724 # * If the function is neither tp_new (METHOD_NEW) nor tp_init (METHOD_INIT):
2725 # * The type of the first parameter to the parsing function is also self.type.
2726 # This means that if you step into the parsing function, your "self" parameter
2727 # is of the correct type, which may make debugging more pleasant.
2728 #
2729 # * Else if the function is tp_new (METHOD_NEW):
2730 # * The type of the first parameter to the parsing function is "PyTypeObject *",
2731 # so the type signature of the function call is an exact match.
2732 # * If self.type != "PyTypeObject *", we cast the first parameter to self.type
2733 # in the impl call.
2734 #
2735 # * Else if the function is tp_init (METHOD_INIT):
2736 # * The type of the first parameter to the parsing function is "PyObject *",
2737 # so the type signature of the function call is an exact match.
2738 # * If self.type != "PyObject *", we cast the first parameter to self.type
2739 # in the impl call.
2740
2741 @property
2742 def parser_type(self):
Larry Hastingsc2047262014-01-25 20:43:29 -08002743 return required_type_for_self_for_parser(self.function) or self.type
Larry Hastings78cf85c2014-01-04 12:44:57 -08002744
Larry Hastingsebdcb502013-11-23 14:54:00 -08002745 def render(self, parameter, data):
Larry Hastings5c661892014-01-24 06:17:25 -08002746 """
2747 parameter is a clinic.Parameter instance.
2748 data is a CRenderData instance.
2749 """
2750 if self.function.kind == STATIC_METHOD:
2751 return
2752
2753 self._render_self(parameter, data)
2754
2755 if self.type != self.parser_type:
2756 # insert cast to impl_argument[0], aka self.
2757 # we know we're in the first slot in all the CRenderData lists,
2758 # because we render parameters in order, and self is always first.
2759 assert len(data.impl_arguments) == 1
2760 assert data.impl_arguments[0] == self.name
2761 data.impl_arguments[0] = '(' + self.type + ")" + data.impl_arguments[0]
2762
2763 def set_template_dict(self, template_dict):
2764 template_dict['self_name'] = self.name
2765 template_dict['self_type'] = self.parser_type
Larry Hastingsf0537e82014-01-25 22:01:12 -08002766 kind = self.function.kind
2767 cls = self.function.cls
2768
2769 if ((kind in (METHOD_NEW, METHOD_INIT)) and cls and cls.typedef):
2770 if kind == METHOD_NEW:
2771 passed_in_type = self.name
2772 else:
2773 passed_in_type = 'Py_TYPE({})'.format(self.name)
2774
2775 line = '({passed_in_type} == {type_object}) &&\n '
2776 d = {
2777 'type_object': self.function.cls.type_object,
2778 'passed_in_type': passed_in_type
2779 }
2780 template_dict['self_type_check'] = line.format_map(d)
Larry Hastingsebdcb502013-11-23 14:54:00 -08002781
Larry Hastings31826802013-10-19 00:09:25 -07002782
2783
2784def add_c_return_converter(f, name=None):
2785 if not name:
2786 name = f.__name__
2787 if not name.endswith('_return_converter'):
2788 return f
2789 name = name[:-len('_return_converter')]
2790 return_converters[name] = f
2791 return f
2792
2793
2794class CReturnConverterAutoRegister(type):
2795 def __init__(cls, name, bases, classdict):
2796 add_c_return_converter(cls)
2797
2798class CReturnConverter(metaclass=CReturnConverterAutoRegister):
2799
Larry Hastings78cf85c2014-01-04 12:44:57 -08002800 # The C type to use for this variable.
2801 # 'type' should be a Python string specifying the type, e.g. "int".
2802 # If this is a pointer type, the type string should end with ' *'.
Larry Hastings31826802013-10-19 00:09:25 -07002803 type = 'PyObject *'
Larry Hastings78cf85c2014-01-04 12:44:57 -08002804
2805 # The Python default value for this parameter, as a Python value.
2806 # Or the magic value "unspecified" if there is no default.
Larry Hastings31826802013-10-19 00:09:25 -07002807 default = None
2808
Larry Hastings2a727912014-01-16 11:32:01 -08002809 def __init__(self, *, py_default=None, **kwargs):
2810 self.py_default = py_default
Larry Hastings31826802013-10-19 00:09:25 -07002811 try:
2812 self.return_converter_init(**kwargs)
2813 except TypeError as e:
2814 s = ', '.join(name + '=' + repr(value) for name, value in kwargs.items())
2815 sys.exit(self.__class__.__name__ + '(' + s + ')\n' + str(e))
2816
2817 def return_converter_init(self):
2818 pass
2819
2820 def declare(self, data, name="_return_value"):
2821 line = []
2822 add = line.append
2823 add(self.type)
2824 if not self.type.endswith('*'):
2825 add(' ')
2826 add(name + ';')
2827 data.declarations.append(''.join(line))
2828 data.return_value = name
2829
2830 def err_occurred_if(self, expr, data):
2831 data.return_conversion.append('if (({}) && PyErr_Occurred())\n goto exit;\n'.format(expr))
2832
2833 def err_occurred_if_null_pointer(self, variable, data):
2834 data.return_conversion.append('if ({} == NULL)\n goto exit;\n'.format(variable))
2835
2836 def render(self, function, data):
2837 """
2838 function is a clinic.Function instance.
2839 data is a CRenderData instance.
2840 """
2841 pass
2842
2843add_c_return_converter(CReturnConverter, 'object')
2844
Larry Hastings78cf85c2014-01-04 12:44:57 -08002845class NoneType_return_converter(CReturnConverter):
2846 def render(self, function, data):
2847 self.declare(data)
2848 data.return_conversion.append('''
2849if (_return_value != Py_None)
2850 goto exit;
2851return_value = Py_None;
2852Py_INCREF(Py_None);
2853'''.strip())
2854
Larry Hastings4a55fc52014-01-12 11:09:57 -08002855class bool_return_converter(CReturnConverter):
Larry Hastings31826802013-10-19 00:09:25 -07002856 type = 'int'
2857
2858 def render(self, function, data):
2859 self.declare(data)
2860 self.err_occurred_if("_return_value == -1", data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002861 data.return_conversion.append('return_value = PyBool_FromLong((long)_return_value);\n')
Larry Hastings31826802013-10-19 00:09:25 -07002862
2863class long_return_converter(CReturnConverter):
2864 type = 'long'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002865 conversion_fn = 'PyLong_FromLong'
2866 cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07002867
2868 def render(self, function, data):
2869 self.declare(data)
2870 self.err_occurred_if("_return_value == -1", data)
2871 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08002872 ''.join(('return_value = ', self.conversion_fn, '(', self.cast, '_return_value);\n')))
Larry Hastings31826802013-10-19 00:09:25 -07002873
Larry Hastings4a55fc52014-01-12 11:09:57 -08002874class int_return_converter(long_return_converter):
2875 type = 'int'
2876 cast = '(long)'
Larry Hastings31826802013-10-19 00:09:25 -07002877
Larry Hastingsb7ccb202014-01-18 23:50:21 -08002878class init_return_converter(long_return_converter):
2879 """
2880 Special return converter for __init__ functions.
2881 """
2882 type = 'int'
2883 cast = '(long)'
2884
2885 def render(self, function, data):
2886 pass
2887
Larry Hastings4a55fc52014-01-12 11:09:57 -08002888class unsigned_long_return_converter(long_return_converter):
2889 type = 'unsigned long'
2890 conversion_fn = 'PyLong_FromUnsignedLong'
2891
2892class unsigned_int_return_converter(unsigned_long_return_converter):
2893 type = 'unsigned int'
2894 cast = '(unsigned long)'
2895
2896class Py_ssize_t_return_converter(long_return_converter):
Larry Hastings31826802013-10-19 00:09:25 -07002897 type = 'Py_ssize_t'
Larry Hastings4a55fc52014-01-12 11:09:57 -08002898 conversion_fn = 'PyLong_FromSsize_t'
2899
2900class size_t_return_converter(long_return_converter):
2901 type = 'size_t'
2902 conversion_fn = 'PyLong_FromSize_t'
2903
2904
2905class double_return_converter(CReturnConverter):
2906 type = 'double'
2907 cast = ''
Larry Hastings31826802013-10-19 00:09:25 -07002908
2909 def render(self, function, data):
2910 self.declare(data)
Larry Hastings4a55fc52014-01-12 11:09:57 -08002911 self.err_occurred_if("_return_value == -1.0", data)
Larry Hastings31826802013-10-19 00:09:25 -07002912 data.return_conversion.append(
Larry Hastings4a55fc52014-01-12 11:09:57 -08002913 'return_value = PyFloat_FromDouble(' + self.cast + '_return_value);\n')
2914
2915class float_return_converter(double_return_converter):
2916 type = 'float'
2917 cast = '(double)'
Larry Hastings31826802013-10-19 00:09:25 -07002918
2919
2920class DecodeFSDefault_return_converter(CReturnConverter):
2921 type = 'char *'
2922
2923 def render(self, function, data):
2924 self.declare(data)
2925 self.err_occurred_if_null_pointer("_return_value", data)
2926 data.return_conversion.append(
2927 'return_value = PyUnicode_DecodeFSDefault(_return_value);\n')
2928
2929
2930class IndentStack:
2931 def __init__(self):
2932 self.indents = []
2933 self.margin = None
2934
2935 def _ensure(self):
2936 if not self.indents:
2937 fail('IndentStack expected indents, but none are defined.')
2938
2939 def measure(self, line):
2940 """
2941 Returns the length of the line's margin.
2942 """
2943 if '\t' in line:
Larry Hastings2623c8c2014-02-08 22:15:29 -08002944 fail('Tab characters are illegal in the Argument Clinic DSL.')
Larry Hastings31826802013-10-19 00:09:25 -07002945 stripped = line.lstrip()
2946 if not len(stripped):
2947 # we can't tell anything from an empty line
2948 # so just pretend it's indented like our current indent
2949 self._ensure()
2950 return self.indents[-1]
2951 return len(line) - len(stripped)
2952
2953 def infer(self, line):
2954 """
2955 Infer what is now the current margin based on this line.
2956 Returns:
2957 1 if we have indented (or this is the first margin)
2958 0 if the margin has not changed
2959 -N if we have dedented N times
2960 """
2961 indent = self.measure(line)
2962 margin = ' ' * indent
2963 if not self.indents:
2964 self.indents.append(indent)
2965 self.margin = margin
2966 return 1
2967 current = self.indents[-1]
2968 if indent == current:
2969 return 0
2970 if indent > current:
2971 self.indents.append(indent)
2972 self.margin = margin
2973 return 1
2974 # indent < current
2975 if indent not in self.indents:
2976 fail("Illegal outdent.")
2977 outdent_count = 0
2978 while indent != current:
2979 self.indents.pop()
2980 current = self.indents[-1]
2981 outdent_count -= 1
2982 self.margin = margin
2983 return outdent_count
2984
2985 @property
2986 def depth(self):
2987 """
2988 Returns how many margins are currently defined.
2989 """
2990 return len(self.indents)
2991
2992 def indent(self, line):
2993 """
2994 Indents a line by the currently defined margin.
2995 """
2996 return self.margin + line
2997
2998 def dedent(self, line):
2999 """
3000 Dedents a line by the currently defined margin.
3001 (The inverse of 'indent'.)
3002 """
3003 margin = self.margin
3004 indent = self.indents[-1]
3005 if not line.startswith(margin):
3006 fail('Cannot dedent, line does not start with the previous margin:')
3007 return line[indent:]
3008
3009
3010class DSLParser:
3011 def __init__(self, clinic):
3012 self.clinic = clinic
3013
3014 self.directives = {}
3015 for name in dir(self):
3016 # functions that start with directive_ are added to directives
3017 _, s, key = name.partition("directive_")
3018 if s:
3019 self.directives[key] = getattr(self, name)
3020
3021 # functions that start with at_ are too, with an @ in front
3022 _, s, key = name.partition("at_")
3023 if s:
3024 self.directives['@' + key] = getattr(self, name)
3025
3026 self.reset()
3027
3028 def reset(self):
3029 self.function = None
3030 self.state = self.state_dsl_start
3031 self.parameter_indent = None
3032 self.keyword_only = False
3033 self.group = 0
3034 self.parameter_state = self.ps_start
Larry Hastingsc2047262014-01-25 20:43:29 -08003035 self.seen_positional_with_default = False
Larry Hastings31826802013-10-19 00:09:25 -07003036 self.indent = IndentStack()
3037 self.kind = CALLABLE
3038 self.coexist = False
Larry Hastings2a727912014-01-16 11:32:01 -08003039 self.parameter_continuation = ''
Larry Hastingsbebf7352014-01-17 17:47:17 -08003040 self.preserve_output = False
Larry Hastings31826802013-10-19 00:09:25 -07003041
Larry Hastingsebdcb502013-11-23 14:54:00 -08003042 def directive_version(self, required):
3043 global version
3044 if version_comparitor(version, required) < 0:
3045 fail("Insufficient Clinic version!\n Version: " + version + "\n Required: " + required)
3046
Larry Hastings31826802013-10-19 00:09:25 -07003047 def directive_module(self, name):
3048 fields = name.split('.')
3049 new = fields.pop()
3050 module, cls = self.clinic._module_and_class(fields)
3051 if cls:
3052 fail("Can't nest a module inside a class!")
Larry Hastingsc2047262014-01-25 20:43:29 -08003053
3054 if name in module.classes:
3055 fail("Already defined module " + repr(name) + "!")
3056
Larry Hastings31826802013-10-19 00:09:25 -07003057 m = Module(name, module)
3058 module.modules[name] = m
3059 self.block.signatures.append(m)
3060
Larry Hastingsc2047262014-01-25 20:43:29 -08003061 def directive_class(self, name, typedef, type_object):
Larry Hastings31826802013-10-19 00:09:25 -07003062 fields = name.split('.')
3063 in_classes = False
3064 parent = self
3065 name = fields.pop()
3066 so_far = []
3067 module, cls = self.clinic._module_and_class(fields)
3068
Larry Hastingsc2047262014-01-25 20:43:29 -08003069 parent = cls or module
3070 if name in parent.classes:
3071 fail("Already defined class " + repr(name) + "!")
3072
3073 c = Class(name, module, cls, typedef, type_object)
3074 parent.classes[name] = c
Larry Hastings31826802013-10-19 00:09:25 -07003075 self.block.signatures.append(c)
3076
Larry Hastingsbebf7352014-01-17 17:47:17 -08003077 def directive_set(self, name, value):
3078 if name not in ("line_prefix", "line_suffix"):
3079 fail("unknown variable", repr(name))
3080
3081 value = value.format_map({
3082 'block comment start': '/*',
3083 'block comment end': '*/',
3084 })
3085
3086 self.clinic.__dict__[name] = value
3087
3088 def directive_destination(self, name, command, *args):
Zachary Ware071baa62014-01-21 23:07:12 -06003089 if command == 'new':
3090 self.clinic.add_destination(name, *args)
Larry Hastingsbebf7352014-01-17 17:47:17 -08003091 return
3092
Zachary Ware071baa62014-01-21 23:07:12 -06003093 if command == 'clear':
Larry Hastingsbebf7352014-01-17 17:47:17 -08003094 self.clinic.get_destination(name).clear()
3095 fail("unknown destination command", repr(command))
3096
3097
3098 def directive_output(self, field, destination=''):
3099 fd = self.clinic.field_destinations
3100
3101 if field == "preset":
3102 preset = self.clinic.presets.get(destination)
3103 if not preset:
3104 fail("Unknown preset " + repr(destination) + "!")
3105 fd.update(preset)
3106 return
3107
3108 if field == "push":
3109 self.clinic.field_destinations_stack.append(fd.copy())
3110 return
3111
3112 if field == "pop":
3113 if not self.clinic.field_destinations_stack:
3114 fail("Can't 'output pop', stack is empty!")
3115 previous_fd = self.clinic.field_destinations_stack.pop()
3116 fd.update(previous_fd)
3117 return
3118
3119 # secret command for debugging!
3120 if field == "print":
3121 self.block.output.append(pprint.pformat(fd))
3122 self.block.output.append('\n')
3123 return
3124
3125 d = self.clinic.get_destination(destination)
3126
3127 if field == "everything":
3128 for name in list(fd):
3129 fd[name] = d
3130 return
3131
3132 if field not in fd:
Larry Hastings7726ac92014-01-31 22:03:12 -08003133 fail("Invalid field " + repr(field) + ", must be one of:\n preset push pop print everything " + " ".join(fd))
Larry Hastingsbebf7352014-01-17 17:47:17 -08003134 fd[field] = d
3135
3136 def directive_dump(self, name):
3137 self.block.output.append(self.clinic.get_destination(name).dump())
3138
3139 def directive_print(self, *args):
3140 self.block.output.append(' '.join(args))
3141 self.block.output.append('\n')
3142
3143 def directive_preserve(self):
3144 if self.preserve_output:
3145 fail("Can't have preserve twice in one block!")
3146 self.preserve_output = True
3147
Larry Hastings31826802013-10-19 00:09:25 -07003148 def at_classmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003149 if self.kind is not CALLABLE:
3150 fail("Can't set @classmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07003151 self.kind = CLASS_METHOD
3152
3153 def at_staticmethod(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003154 if self.kind is not CALLABLE:
3155 fail("Can't set @staticmethod, function is not a normal callable")
Larry Hastings31826802013-10-19 00:09:25 -07003156 self.kind = STATIC_METHOD
3157
3158 def at_coexist(self):
Larry Hastings2a727912014-01-16 11:32:01 -08003159 if self.coexist:
3160 fail("Called @coexist twice!")
Larry Hastings31826802013-10-19 00:09:25 -07003161 self.coexist = True
3162
3163 def parse(self, block):
3164 self.reset()
3165 self.block = block
Larry Hastingsbebf7352014-01-17 17:47:17 -08003166 self.saved_output = self.block.output
3167 block.output = []
Larry Hastings31826802013-10-19 00:09:25 -07003168 block_start = self.clinic.block_parser.line_number
3169 lines = block.input.split('\n')
3170 for line_number, line in enumerate(lines, self.clinic.block_parser.block_start_line_number):
3171 if '\t' in line:
3172 fail('Tab characters are illegal in the Clinic DSL.\n\t' + repr(line), line_number=block_start)
3173 self.state(line)
3174
3175 self.next(self.state_terminal)
3176 self.state(None)
3177
Larry Hastingsbebf7352014-01-17 17:47:17 -08003178 block.output.extend(self.clinic.language.render(clinic, block.signatures))
3179
3180 if self.preserve_output:
3181 if block.output:
3182 fail("'preserve' only works for blocks that don't produce any output!")
3183 block.output = self.saved_output
Larry Hastings31826802013-10-19 00:09:25 -07003184
3185 @staticmethod
3186 def ignore_line(line):
3187 # ignore comment-only lines
3188 if line.lstrip().startswith('#'):
3189 return True
3190
3191 # Ignore empty lines too
3192 # (but not in docstring sections!)
3193 if not line.strip():
3194 return True
3195
3196 return False
3197
3198 @staticmethod
3199 def calculate_indent(line):
3200 return len(line) - len(line.strip())
3201
3202 def next(self, state, line=None):
3203 # real_print(self.state.__name__, "->", state.__name__, ", line=", line)
3204 self.state = state
3205 if line is not None:
3206 self.state(line)
3207
3208 def state_dsl_start(self, line):
3209 # self.block = self.ClinicOutputBlock(self)
3210 if self.ignore_line(line):
3211 return
Larry Hastings7726ac92014-01-31 22:03:12 -08003212
3213 # is it a directive?
3214 fields = shlex.split(line)
3215 directive_name = fields[0]
3216 directive = self.directives.get(directive_name, None)
3217 if directive:
3218 try:
3219 directive(*fields[1:])
3220 except TypeError as e:
3221 fail(str(e))
3222 return
3223
Larry Hastings31826802013-10-19 00:09:25 -07003224 self.next(self.state_modulename_name, line)
3225
3226 def state_modulename_name(self, line):
3227 # looking for declaration, which establishes the leftmost column
3228 # line should be
3229 # modulename.fnname [as c_basename] [-> return annotation]
3230 # square brackets denote optional syntax.
3231 #
Larry Hastings4a714d42014-01-14 22:22:41 -08003232 # alternatively:
3233 # modulename.fnname [as c_basename] = modulename.existing_fn_name
3234 # clones the parameters and return converter from that
3235 # function. you can't modify them. you must enter a
3236 # new docstring.
3237 #
Larry Hastings31826802013-10-19 00:09:25 -07003238 # (but we might find a directive first!)
3239 #
3240 # this line is permitted to start with whitespace.
3241 # we'll call this number of spaces F (for "function").
3242
3243 if not line.strip():
3244 return
3245
3246 self.indent.infer(line)
3247
Larry Hastings4a714d42014-01-14 22:22:41 -08003248 # are we cloning?
3249 before, equals, existing = line.rpartition('=')
3250 if equals:
3251 full_name, _, c_basename = before.partition(' as ')
3252 full_name = full_name.strip()
3253 c_basename = c_basename.strip()
3254 existing = existing.strip()
3255 if (is_legal_py_identifier(full_name) and
3256 (not c_basename or is_legal_c_identifier(c_basename)) and
3257 is_legal_py_identifier(existing)):
3258 # we're cloning!
3259 fields = [x.strip() for x in existing.split('.')]
3260 function_name = fields.pop()
3261 module, cls = self.clinic._module_and_class(fields)
3262
3263 for existing_function in (cls or module).functions:
3264 if existing_function.name == function_name:
3265 break
3266 else:
3267 existing_function = None
3268 if not existing_function:
Larry Hastings7726ac92014-01-31 22:03:12 -08003269 print("class", cls, "module", module, "existing", existing)
Larry Hastingsc2047262014-01-25 20:43:29 -08003270 print("cls. functions", cls.functions)
Larry Hastings4a714d42014-01-14 22:22:41 -08003271 fail("Couldn't find existing function " + repr(existing) + "!")
3272
3273 fields = [x.strip() for x in full_name.split('.')]
3274 function_name = fields.pop()
3275 module, cls = self.clinic._module_and_class(fields)
3276
3277 if not (existing_function.kind == self.kind and existing_function.coexist == self.coexist):
3278 fail("'kind' of function and cloned function don't match! (@classmethod/@staticmethod/@coexist)")
Larry Hastings7726ac92014-01-31 22:03:12 -08003279 self.function = existing_function.copy(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename, docstring='')
Larry Hastings4a714d42014-01-14 22:22:41 -08003280
3281 self.block.signatures.append(self.function)
3282 (cls or module).functions.append(self.function)
3283 self.next(self.state_function_docstring)
3284 return
3285
Larry Hastings31826802013-10-19 00:09:25 -07003286 line, _, returns = line.partition('->')
3287
3288 full_name, _, c_basename = line.partition(' as ')
3289 full_name = full_name.strip()
3290 c_basename = c_basename.strip() or None
3291
Larry Hastingsdfcd4672013-10-27 02:49:39 -07003292 if not is_legal_py_identifier(full_name):
3293 fail("Illegal function name: {}".format(full_name))
3294 if c_basename and not is_legal_c_identifier(c_basename):
3295 fail("Illegal C basename: {}".format(c_basename))
3296
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003297 return_converter = None
3298 if returns:
Larry Hastings31826802013-10-19 00:09:25 -07003299 ast_input = "def x() -> {}: pass".format(returns)
3300 module = None
3301 try:
3302 module = ast.parse(ast_input)
3303 except SyntaxError:
3304 pass
3305 if not module:
3306 fail("Badly-formed annotation for " + full_name + ": " + returns)
3307 try:
3308 name, legacy, kwargs = self.parse_converter(module.body[0].returns)
Antoine Pitroud7fb7912014-01-14 21:02:43 +01003309 if legacy:
3310 fail("Legacy converter {!r} not allowed as a return converter"
3311 .format(name))
Larry Hastings31826802013-10-19 00:09:25 -07003312 if name not in return_converters:
Antoine Pitroud7fb7912014-01-14 21:02:43 +01003313 fail("No available return converter called " + repr(name))
Larry Hastings31826802013-10-19 00:09:25 -07003314 return_converter = return_converters[name](**kwargs)
3315 except ValueError:
3316 fail("Badly-formed annotation for " + full_name + ": " + returns)
3317
3318 fields = [x.strip() for x in full_name.split('.')]
3319 function_name = fields.pop()
3320 module, cls = self.clinic._module_and_class(fields)
3321
Larry Hastings8666e652014-01-12 14:12:59 -08003322 fields = full_name.split('.')
3323 if fields[-1] == '__new__':
3324 if (self.kind != CLASS_METHOD) or (not cls):
3325 fail("__new__ must be a class method!")
3326 self.kind = METHOD_NEW
3327 elif fields[-1] == '__init__':
3328 if (self.kind != CALLABLE) or (not cls):
3329 fail("__init__ must be a normal method, not a class or static method!")
3330 self.kind = METHOD_INIT
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003331 if not return_converter:
3332 return_converter = init_return_converter()
Larry Hastings8666e652014-01-12 14:12:59 -08003333 elif fields[-1] in unsupported_special_methods:
Larry Hastings5c661892014-01-24 06:17:25 -08003334 fail(fields[-1] + " is a special method and cannot be converted to Argument Clinic! (Yet.)")
Larry Hastings8666e652014-01-12 14:12:59 -08003335
Larry Hastingsb7ccb202014-01-18 23:50:21 -08003336 if not return_converter:
3337 return_converter = CReturnConverter()
3338
Larry Hastings31826802013-10-19 00:09:25 -07003339 if not module:
3340 fail("Undefined module used in declaration of " + repr(full_name.strip()) + ".")
3341 self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename,
3342 return_converter=return_converter, kind=self.kind, coexist=self.coexist)
3343 self.block.signatures.append(self.function)
Larry Hastings5c661892014-01-24 06:17:25 -08003344
3345 # insert a self converter automatically
Larry Hastingsc2047262014-01-25 20:43:29 -08003346 type, name = correct_name_for_self(self.function)
3347 kwargs = {}
3348 if cls and type == "PyObject *":
3349 kwargs['type'] = cls.typedef
Larry Hastings7726ac92014-01-31 22:03:12 -08003350 sc = self.function.self_converter = self_converter(name, name, self.function, **kwargs)
Larry Hastings5c661892014-01-24 06:17:25 -08003351 p_self = Parameter(sc.name, inspect.Parameter.POSITIONAL_ONLY, function=self.function, converter=sc)
3352 self.function.parameters[sc.name] = p_self
3353
Larry Hastings4a714d42014-01-14 22:22:41 -08003354 (cls or module).functions.append(self.function)
Larry Hastings31826802013-10-19 00:09:25 -07003355 self.next(self.state_parameters_start)
3356
3357 # Now entering the parameters section. The rules, formally stated:
3358 #
3359 # * All lines must be indented with spaces only.
3360 # * The first line must be a parameter declaration.
3361 # * The first line must be indented.
3362 # * This first line establishes the indent for parameters.
3363 # * We'll call this number of spaces P (for "parameter").
3364 # * Thenceforth:
3365 # * Lines indented with P spaces specify a parameter.
3366 # * Lines indented with > P spaces are docstrings for the previous
3367 # parameter.
3368 # * We'll call this number of spaces D (for "docstring").
3369 # * All subsequent lines indented with >= D spaces are stored as
3370 # part of the per-parameter docstring.
3371 # * All lines will have the first D spaces of the indent stripped
3372 # before they are stored.
3373 # * It's illegal to have a line starting with a number of spaces X
3374 # such that P < X < D.
3375 # * A line with < P spaces is the first line of the function
3376 # docstring, which ends processing for parameters and per-parameter
3377 # docstrings.
3378 # * The first line of the function docstring must be at the same
3379 # indent as the function declaration.
3380 # * It's illegal to have any line in the parameters section starting
3381 # with X spaces such that F < X < P. (As before, F is the indent
3382 # of the function declaration.)
3383 #
Larry Hastings31826802013-10-19 00:09:25 -07003384 # Also, currently Argument Clinic places the following restrictions on groups:
3385 # * Each group must contain at least one parameter.
3386 # * Each group may contain at most one group, which must be the furthest
3387 # thing in the group from the required parameters. (The nested group
3388 # must be the first in the group when it's before the required
3389 # parameters, and the last thing in the group when after the required
3390 # parameters.)
3391 # * There may be at most one (top-level) group to the left or right of
3392 # the required parameters.
3393 # * You must specify a slash, and it must be after all parameters.
3394 # (In other words: either all parameters are positional-only,
3395 # or none are.)
3396 #
3397 # Said another way:
3398 # * Each group must contain at least one parameter.
3399 # * All left square brackets before the required parameters must be
3400 # consecutive. (You can't have a left square bracket followed
3401 # by a parameter, then another left square bracket. You can't
3402 # have a left square bracket, a parameter, a right square bracket,
3403 # and then a left square bracket.)
3404 # * All right square brackets after the required parameters must be
3405 # consecutive.
3406 #
3407 # These rules are enforced with a single state variable:
3408 # "parameter_state". (Previously the code was a miasma of ifs and
3409 # separate boolean state variables.) The states are:
3410 #
Larry Hastingsc2047262014-01-25 20:43:29 -08003411 # [ [ a, b, ] c, ] d, e, f=3, [ g, h, [ i ] ] / <- line
3412 # 01 2 3 4 5 6 7 <- state transitions
Larry Hastings31826802013-10-19 00:09:25 -07003413 #
3414 # 0: ps_start. before we've seen anything. legal transitions are to 1 or 3.
3415 # 1: ps_left_square_before. left square brackets before required parameters.
3416 # 2: ps_group_before. in a group, before required parameters.
Larry Hastingsc2047262014-01-25 20:43:29 -08003417 # 3: ps_required. required parameters, positional-or-keyword or positional-only
3418 # (we don't know yet). (renumber left groups!)
3419 # 4: ps_optional. positional-or-keyword or positional-only parameters that
3420 # now must have default values.
3421 # 5: ps_group_after. in a group, after required parameters.
3422 # 6: ps_right_square_after. right square brackets after required parameters.
3423 # 7: ps_seen_slash. seen slash.
Larry Hastings31826802013-10-19 00:09:25 -07003424 ps_start, ps_left_square_before, ps_group_before, ps_required, \
Larry Hastingsc2047262014-01-25 20:43:29 -08003425 ps_optional, ps_group_after, ps_right_square_after, ps_seen_slash = range(8)
Larry Hastings31826802013-10-19 00:09:25 -07003426
3427 def state_parameters_start(self, line):
3428 if self.ignore_line(line):
3429 return
3430
3431 # if this line is not indented, we have no parameters
3432 if not self.indent.infer(line):
3433 return self.next(self.state_function_docstring, line)
3434
Larry Hastings2a727912014-01-16 11:32:01 -08003435 self.parameter_continuation = ''
Larry Hastings31826802013-10-19 00:09:25 -07003436 return self.next(self.state_parameter, line)
3437
3438
3439 def to_required(self):
3440 """
3441 Transition to the "required" parameter state.
3442 """
3443 if self.parameter_state != self.ps_required:
3444 self.parameter_state = self.ps_required
3445 for p in self.function.parameters.values():
3446 p.group = -p.group
3447
3448 def state_parameter(self, line):
Larry Hastings2a727912014-01-16 11:32:01 -08003449 if self.parameter_continuation:
3450 line = self.parameter_continuation + ' ' + line.lstrip()
3451 self.parameter_continuation = ''
3452
Larry Hastings31826802013-10-19 00:09:25 -07003453 if self.ignore_line(line):
3454 return
3455
3456 assert self.indent.depth == 2
3457 indent = self.indent.infer(line)
3458 if indent == -1:
3459 # we outdented, must be to definition column
3460 return self.next(self.state_function_docstring, line)
3461
3462 if indent == 1:
3463 # we indented, must be to new parameter docstring column
3464 return self.next(self.state_parameter_docstring_start, line)
3465
Larry Hastings2a727912014-01-16 11:32:01 -08003466 line = line.rstrip()
3467 if line.endswith('\\'):
3468 self.parameter_continuation = line[:-1]
3469 return
3470
Larry Hastings31826802013-10-19 00:09:25 -07003471 line = line.lstrip()
3472
3473 if line in ('*', '/', '[', ']'):
3474 self.parse_special_symbol(line)
3475 return
3476
3477 if self.parameter_state in (self.ps_start, self.ps_required):
3478 self.to_required()
3479 elif self.parameter_state == self.ps_left_square_before:
3480 self.parameter_state = self.ps_group_before
3481 elif self.parameter_state == self.ps_group_before:
3482 if not self.group:
3483 self.to_required()
Larry Hastingsc2047262014-01-25 20:43:29 -08003484 elif self.parameter_state in (self.ps_group_after, self.ps_optional):
Larry Hastings31826802013-10-19 00:09:25 -07003485 pass
3486 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003487 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".a)")
Larry Hastings31826802013-10-19 00:09:25 -07003488
Larry Hastings7726ac92014-01-31 22:03:12 -08003489 # handle "as" for parameters too
3490 c_name = None
3491 name, have_as_token, trailing = line.partition(' as ')
3492 if have_as_token:
3493 name = name.strip()
3494 if ' ' not in name:
3495 fields = trailing.strip().split(' ')
3496 if not fields:
3497 fail("Invalid 'as' clause!")
3498 c_name = fields[0]
3499 if c_name.endswith(':'):
3500 name += ':'
3501 c_name = c_name[:-1]
3502 fields[0] = name
3503 line = ' '.join(fields)
3504
Larry Hastings2a727912014-01-16 11:32:01 -08003505 base, equals, default = line.rpartition('=')
3506 if not equals:
3507 base = default
3508 default = None
Larry Hastingsc2047262014-01-25 20:43:29 -08003509
Larry Hastings31826802013-10-19 00:09:25 -07003510 module = None
3511 try:
Larry Hastings2a727912014-01-16 11:32:01 -08003512 ast_input = "def x({}): pass".format(base)
Larry Hastings31826802013-10-19 00:09:25 -07003513 module = ast.parse(ast_input)
3514 except SyntaxError:
Larry Hastings2a727912014-01-16 11:32:01 -08003515 try:
Larry Hastingsc2047262014-01-25 20:43:29 -08003516 # the last = was probably inside a function call, like
3517 # i: int(nullable=True)
3518 # so assume there was no actual default value.
Larry Hastings2a727912014-01-16 11:32:01 -08003519 default = None
3520 ast_input = "def x({}): pass".format(line)
3521 module = ast.parse(ast_input)
3522 except SyntaxError:
3523 pass
Larry Hastings31826802013-10-19 00:09:25 -07003524 if not module:
Larry Hastingsef3b1fb2013-10-22 23:26:23 -07003525 fail("Function " + self.function.name + " has an invalid parameter declaration:\n\t" + line)
Larry Hastings31826802013-10-19 00:09:25 -07003526
3527 function_args = module.body[0].args
3528 parameter = function_args.args[0]
3529
Larry Hastings16c51912014-01-07 11:53:01 -08003530 parameter_name = parameter.arg
3531 name, legacy, kwargs = self.parse_converter(parameter.annotation)
3532
Larry Hastings2a727912014-01-16 11:32:01 -08003533 if not default:
Larry Hastingsc2047262014-01-25 20:43:29 -08003534 if self.parameter_state == self.ps_optional:
3535 fail("Can't have a parameter without a default (" + repr(parameter_name) + ")\nafter a parameter with a default!")
Larry Hastings2a727912014-01-16 11:32:01 -08003536 value = unspecified
3537 if 'py_default' in kwargs:
3538 fail("You can't specify py_default without specifying a default value!")
3539 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003540 if self.parameter_state == self.ps_required:
3541 self.parameter_state = self.ps_optional
Larry Hastings2a727912014-01-16 11:32:01 -08003542 default = default.strip()
Zachary Ware021bb872014-01-24 22:52:30 -06003543 bad = False
Larry Hastings2a727912014-01-16 11:32:01 -08003544 ast_input = "x = {}".format(default)
Larry Hastingsc2047262014-01-25 20:43:29 -08003545 bad = False
Larry Hastings2a727912014-01-16 11:32:01 -08003546 try:
3547 module = ast.parse(ast_input)
3548
Larry Hastings5c661892014-01-24 06:17:25 -08003549 if 'c_default' not in kwargs:
3550 # we can only represent very simple data values in C.
3551 # detect whether default is okay, via a blacklist
3552 # of disallowed ast nodes.
3553 class DetectBadNodes(ast.NodeVisitor):
3554 bad = False
3555 def bad_node(self, node):
3556 self.bad = True
Larry Hastings2a727912014-01-16 11:32:01 -08003557
Larry Hastings5c661892014-01-24 06:17:25 -08003558 # inline function call
3559 visit_Call = bad_node
3560 # inline if statement ("x = 3 if y else z")
3561 visit_IfExp = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003562
Larry Hastings5c661892014-01-24 06:17:25 -08003563 # comprehensions and generator expressions
3564 visit_ListComp = visit_SetComp = bad_node
3565 visit_DictComp = visit_GeneratorExp = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003566
Larry Hastings5c661892014-01-24 06:17:25 -08003567 # literals for advanced types
3568 visit_Dict = visit_Set = bad_node
3569 visit_List = visit_Tuple = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003570
Larry Hastings5c661892014-01-24 06:17:25 -08003571 # "starred": "a = [1, 2, 3]; *a"
3572 visit_Starred = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003573
Larry Hastings5c661892014-01-24 06:17:25 -08003574 # allow ellipsis, for now
3575 # visit_Ellipsis = bad_node
Larry Hastings2a727912014-01-16 11:32:01 -08003576
Larry Hastings5c661892014-01-24 06:17:25 -08003577 blacklist = DetectBadNodes()
3578 blacklist.visit(module)
3579 bad = blacklist.bad
3580 else:
3581 # if they specify a c_default, we can be more lenient about the default value.
Zachary Ware021bb872014-01-24 22:52:30 -06003582 # but at least make an attempt at ensuring it's a valid expression.
3583 try:
3584 value = eval(default)
3585 if value == unspecified:
3586 fail("'unspecified' is not a legal default value!")
3587 except NameError:
3588 pass # probably a named constant
3589 except Exception as e:
3590 fail("Malformed expression given as default value\n"
3591 "{!r} caused {!r}".format(default, e))
Larry Hastings5c661892014-01-24 06:17:25 -08003592 if bad:
Larry Hastings2a727912014-01-16 11:32:01 -08003593 fail("Unsupported expression as default value: " + repr(default))
3594
3595 expr = module.body[0].value
3596 # mild hack: explicitly support NULL as a default value
3597 if isinstance(expr, ast.Name) and expr.id == 'NULL':
3598 value = NULL
3599 py_default = 'None'
3600 c_default = "NULL"
3601 elif (isinstance(expr, ast.BinOp) or
3602 (isinstance(expr, ast.UnaryOp) and not isinstance(expr.operand, ast.Num))):
3603 c_default = kwargs.get("c_default")
3604 if not (isinstance(c_default, str) and c_default):
3605 fail("When you specify an expression (" + repr(default) + ") as your default value,\nyou MUST specify a valid c_default.")
3606 py_default = default
3607 value = unknown
3608 elif isinstance(expr, ast.Attribute):
3609 a = []
3610 n = expr
3611 while isinstance(n, ast.Attribute):
3612 a.append(n.attr)
3613 n = n.value
3614 if not isinstance(n, ast.Name):
3615 fail("Unsupported default value " + repr(default) + " (looked like a Python constant)")
3616 a.append(n.id)
3617 py_default = ".".join(reversed(a))
3618
3619 c_default = kwargs.get("c_default")
3620 if not (isinstance(c_default, str) and c_default):
3621 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3622
3623 try:
3624 value = eval(py_default)
3625 except NameError:
3626 value = unknown
3627 else:
3628 value = ast.literal_eval(expr)
3629 py_default = repr(value)
3630 if isinstance(value, (bool, None.__class__)):
3631 c_default = "Py_" + py_default
3632 elif isinstance(value, str):
Larry Hastings4903e002014-01-18 00:26:16 -08003633 c_default = c_repr(value)
Larry Hastings2a727912014-01-16 11:32:01 -08003634 else:
3635 c_default = py_default
3636
3637 except SyntaxError as e:
3638 fail("Syntax error: " + repr(e.text))
3639 except (ValueError, AttributeError):
3640 value = unknown
Larry Hastings4a55fc52014-01-12 11:09:57 -08003641 c_default = kwargs.get("c_default")
Larry Hastings2a727912014-01-16 11:32:01 -08003642 py_default = default
Larry Hastings4a55fc52014-01-12 11:09:57 -08003643 if not (isinstance(c_default, str) and c_default):
3644 fail("When you specify a named constant (" + repr(py_default) + ") as your default value,\nyou MUST specify a valid c_default.")
3645
Larry Hastings2a727912014-01-16 11:32:01 -08003646 kwargs.setdefault('c_default', c_default)
3647 kwargs.setdefault('py_default', py_default)
Larry Hastings31826802013-10-19 00:09:25 -07003648
Larry Hastings31826802013-10-19 00:09:25 -07003649 dict = legacy_converters if legacy else converters
3650 legacy_str = "legacy " if legacy else ""
3651 if name not in dict:
3652 fail('{} is not a valid {}converter'.format(name, legacy_str))
Larry Hastings7726ac92014-01-31 22:03:12 -08003653 # if you use a c_name for the parameter, we just give that name to the converter
3654 # but the parameter object gets the python name
3655 converter = dict[name](c_name or parameter_name, parameter_name, self.function, value, **kwargs)
Larry Hastings31826802013-10-19 00:09:25 -07003656
3657 kind = inspect.Parameter.KEYWORD_ONLY if self.keyword_only else inspect.Parameter.POSITIONAL_OR_KEYWORD
Larry Hastings5c661892014-01-24 06:17:25 -08003658
3659 if isinstance(converter, self_converter):
3660 if len(self.function.parameters) == 1:
3661 if (self.parameter_state != self.ps_required):
3662 fail("A 'self' parameter cannot be marked optional.")
3663 if value is not unspecified:
3664 fail("A 'self' parameter cannot have a default value.")
3665 if self.group:
3666 fail("A 'self' parameter cannot be in an optional group.")
3667 kind = inspect.Parameter.POSITIONAL_ONLY
3668 self.parameter_state = self.ps_start
3669 self.function.parameters.clear()
3670 else:
3671 fail("A 'self' parameter, if specified, must be the very first thing in the parameter block.")
3672
Larry Hastings31826802013-10-19 00:09:25 -07003673 p = Parameter(parameter_name, kind, function=self.function, converter=converter, default=value, group=self.group)
Larry Hastingsbebf7352014-01-17 17:47:17 -08003674
3675 if parameter_name in self.function.parameters:
3676 fail("You can't have two parameters named " + repr(parameter_name) + "!")
Larry Hastings31826802013-10-19 00:09:25 -07003677 self.function.parameters[parameter_name] = p
3678
3679 def parse_converter(self, annotation):
3680 if isinstance(annotation, ast.Str):
3681 return annotation.s, True, {}
3682
3683 if isinstance(annotation, ast.Name):
3684 return annotation.id, False, {}
3685
Larry Hastings4a55fc52014-01-12 11:09:57 -08003686 if not isinstance(annotation, ast.Call):
3687 fail("Annotations must be either a name, a function call, or a string.")
Larry Hastings31826802013-10-19 00:09:25 -07003688
3689 name = annotation.func.id
3690 kwargs = {node.arg: ast.literal_eval(node.value) for node in annotation.keywords}
3691 return name, False, kwargs
3692
3693 def parse_special_symbol(self, symbol):
3694 if self.parameter_state == self.ps_seen_slash:
3695 fail("Function " + self.function.name + " specifies " + symbol + " after /, which is unsupported.")
3696
3697 if symbol == '*':
3698 if self.keyword_only:
3699 fail("Function " + self.function.name + " uses '*' more than once.")
3700 self.keyword_only = True
3701 elif symbol == '[':
3702 if self.parameter_state in (self.ps_start, self.ps_left_square_before):
3703 self.parameter_state = self.ps_left_square_before
3704 elif self.parameter_state in (self.ps_required, self.ps_group_after):
3705 self.parameter_state = self.ps_group_after
3706 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003707 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".b)")
Larry Hastings31826802013-10-19 00:09:25 -07003708 self.group += 1
Larry Hastings2623c8c2014-02-08 22:15:29 -08003709 self.function.docstring_only = True
Larry Hastings31826802013-10-19 00:09:25 -07003710 elif symbol == ']':
3711 if not self.group:
3712 fail("Function " + self.function.name + " has a ] without a matching [.")
3713 if not any(p.group == self.group for p in self.function.parameters.values()):
3714 fail("Function " + self.function.name + " has an empty group.\nAll groups must contain at least one parameter.")
3715 self.group -= 1
3716 if self.parameter_state in (self.ps_left_square_before, self.ps_group_before):
3717 self.parameter_state = self.ps_group_before
3718 elif self.parameter_state in (self.ps_group_after, self.ps_right_square_after):
3719 self.parameter_state = self.ps_right_square_after
3720 else:
Larry Hastingsc2047262014-01-25 20:43:29 -08003721 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".c)")
Larry Hastings31826802013-10-19 00:09:25 -07003722 elif symbol == '/':
Larry Hastingsc2047262014-01-25 20:43:29 -08003723 # ps_required and ps_optional are allowed here, that allows positional-only without option groups
Larry Hastings31826802013-10-19 00:09:25 -07003724 # to work (and have default values!)
Larry Hastingsc2047262014-01-25 20:43:29 -08003725 if (self.parameter_state not in (self.ps_required, self.ps_optional, self.ps_right_square_after, self.ps_group_before)) or self.group:
3726 fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".d)")
Larry Hastings31826802013-10-19 00:09:25 -07003727 if self.keyword_only:
3728 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
3729 self.parameter_state = self.ps_seen_slash
Berker Peksagf23530f2014-10-19 18:04:38 +03003730 # fixup preceding parameters
Larry Hastings31826802013-10-19 00:09:25 -07003731 for p in self.function.parameters.values():
Larry Hastings5c661892014-01-24 06:17:25 -08003732 if (p.kind != inspect.Parameter.POSITIONAL_OR_KEYWORD and not isinstance(p.converter, self_converter)):
Larry Hastings31826802013-10-19 00:09:25 -07003733 fail("Function " + self.function.name + " mixes keyword-only and positional-only parameters, which is unsupported.")
3734 p.kind = inspect.Parameter.POSITIONAL_ONLY
3735
3736 def state_parameter_docstring_start(self, line):
3737 self.parameter_docstring_indent = len(self.indent.margin)
3738 assert self.indent.depth == 3
3739 return self.next(self.state_parameter_docstring, line)
3740
3741 # every line of the docstring must start with at least F spaces,
3742 # where F > P.
3743 # these F spaces will be stripped.
3744 def state_parameter_docstring(self, line):
3745 stripped = line.strip()
3746 if stripped.startswith('#'):
3747 return
3748
3749 indent = self.indent.measure(line)
3750 if indent < self.parameter_docstring_indent:
3751 self.indent.infer(line)
3752 assert self.indent.depth < 3
3753 if self.indent.depth == 2:
3754 # back to a parameter
3755 return self.next(self.state_parameter, line)
3756 assert self.indent.depth == 1
3757 return self.next(self.state_function_docstring, line)
3758
3759 assert self.function.parameters
3760 last_parameter = next(reversed(list(self.function.parameters.values())))
3761
3762 new_docstring = last_parameter.docstring
3763
3764 if new_docstring:
3765 new_docstring += '\n'
3766 if stripped:
3767 new_docstring += self.indent.dedent(line)
3768
3769 last_parameter.docstring = new_docstring
3770
3771 # the final stanza of the DSL is the docstring.
3772 def state_function_docstring(self, line):
Larry Hastings31826802013-10-19 00:09:25 -07003773 if self.group:
3774 fail("Function " + self.function.name + " has a ] without a matching [.")
3775
3776 stripped = line.strip()
3777 if stripped.startswith('#'):
3778 return
3779
3780 new_docstring = self.function.docstring
3781 if new_docstring:
3782 new_docstring += "\n"
3783 if stripped:
3784 line = self.indent.dedent(line).rstrip()
3785 else:
3786 line = ''
3787 new_docstring += line
3788 self.function.docstring = new_docstring
3789
3790 def format_docstring(self):
3791 f = self.function
3792
Larry Hastings5c661892014-01-24 06:17:25 -08003793 new_or_init = f.kind in (METHOD_NEW, METHOD_INIT)
3794 if new_or_init and not f.docstring:
3795 # don't render a docstring at all, no signature, nothing.
3796 return f.docstring
3797
Larry Hastings2623c8c2014-02-08 22:15:29 -08003798 text, add, output = _text_accumulator()
Larry Hastings7726ac92014-01-31 22:03:12 -08003799 parameters = f.render_parameters
Larry Hastings31826802013-10-19 00:09:25 -07003800
3801 ##
3802 ## docstring first line
3803 ##
3804
Larry Hastings2623c8c2014-02-08 22:15:29 -08003805 if new_or_init:
3806 # classes get *just* the name of the class
3807 # not __new__, not __init__, and not module.classname
3808 assert f.cls
3809 add(f.cls.name)
Larry Hastings46258262014-01-22 03:05:49 -08003810 else:
Larry Hastings2623c8c2014-02-08 22:15:29 -08003811 add(f.name)
Larry Hastings31826802013-10-19 00:09:25 -07003812 add('(')
3813
3814 # populate "right_bracket_count" field for every parameter
Larry Hastings5c661892014-01-24 06:17:25 -08003815 assert parameters, "We should always have a self parameter. " + repr(f)
3816 assert isinstance(parameters[0].converter, self_converter)
3817 parameters[0].right_bracket_count = 0
3818 parameters_after_self = parameters[1:]
3819 if parameters_after_self:
Larry Hastings31826802013-10-19 00:09:25 -07003820 # for now, the only way Clinic supports positional-only parameters
Larry Hastings5c661892014-01-24 06:17:25 -08003821 # is if all of them are positional-only...
3822 #
3823 # ... except for self! self is always positional-only.
3824
3825 positional_only_parameters = [p.kind == inspect.Parameter.POSITIONAL_ONLY for p in parameters_after_self]
3826 if parameters_after_self[0].kind == inspect.Parameter.POSITIONAL_ONLY:
Larry Hastings31826802013-10-19 00:09:25 -07003827 assert all(positional_only_parameters)
3828 for p in parameters:
3829 p.right_bracket_count = abs(p.group)
3830 else:
3831 # don't put any right brackets around non-positional-only parameters, ever.
Larry Hastings5c661892014-01-24 06:17:25 -08003832 for p in parameters_after_self:
Larry Hastings31826802013-10-19 00:09:25 -07003833 p.right_bracket_count = 0
3834
3835 right_bracket_count = 0
3836
3837 def fix_right_bracket_count(desired):
3838 nonlocal right_bracket_count
3839 s = ''
3840 while right_bracket_count < desired:
3841 s += '['
3842 right_bracket_count += 1
3843 while right_bracket_count > desired:
3844 s += ']'
3845 right_bracket_count -= 1
3846 return s
3847
Larry Hastings2623c8c2014-02-08 22:15:29 -08003848 need_slash = False
3849 added_slash = False
3850 need_a_trailing_slash = False
3851
3852 # we only need a trailing slash:
3853 # * if this is not a "docstring_only" signature
3854 # * and if the last *shown* parameter is
3855 # positional only
3856 if not f.docstring_only:
3857 for p in reversed(parameters):
3858 if not p.converter.show_in_signature:
3859 continue
3860 if p.is_positional_only():
3861 need_a_trailing_slash = True
3862 break
3863
3864
Larry Hastings31826802013-10-19 00:09:25 -07003865 added_star = False
Larry Hastings2623c8c2014-02-08 22:15:29 -08003866
3867 first_parameter = True
3868 last_p = parameters[-1]
3869 line_length = len(''.join(text))
3870 indent = " " * line_length
3871 def add_parameter(text):
3872 nonlocal line_length
3873 nonlocal first_parameter
3874 if first_parameter:
3875 s = text
3876 first_parameter = False
3877 else:
3878 s = ' ' + text
3879 if line_length + len(s) >= 72:
3880 add('\n')
3881 add(indent)
3882 line_length = len(indent)
3883 s = text
3884 line_length += len(s)
3885 add(s)
Larry Hastings31826802013-10-19 00:09:25 -07003886
3887 for p in parameters:
Larry Hastings5c661892014-01-24 06:17:25 -08003888 if not p.converter.show_in_signature:
3889 continue
Larry Hastings31826802013-10-19 00:09:25 -07003890 assert p.name
3891
Larry Hastings2623c8c2014-02-08 22:15:29 -08003892 is_self = isinstance(p.converter, self_converter)
3893 if is_self and f.docstring_only:
3894 # this isn't a real machine-parsable signature,
3895 # so let's not print the "self" parameter
3896 continue
3897
3898 if p.is_positional_only():
3899 need_slash = not f.docstring_only
3900 elif need_slash and not (added_slash or p.is_positional_only()):
3901 added_slash = True
3902 add_parameter('/,')
3903
Larry Hastings31826802013-10-19 00:09:25 -07003904 if p.is_keyword_only() and not added_star:
3905 added_star = True
Larry Hastings2623c8c2014-02-08 22:15:29 -08003906 add_parameter('*,')
3907
3908 p_add, p_output = text_accumulator()
3909 p_add(fix_right_bracket_count(p.right_bracket_count))
3910
3911 if isinstance(p.converter, self_converter):
3912 # annotate first parameter as being a "self".
3913 #
3914 # if inspect.Signature gets this function,
3915 # and it's already bound, the self parameter
3916 # will be stripped off.
3917 #
3918 # if it's not bound, it should be marked
3919 # as positional-only.
3920 #
3921 # note: we don't print "self" for __init__,
3922 # because this isn't actually the signature
3923 # for __init__. (it can't be, __init__ doesn't
3924 # have a docstring.) if this is an __init__
3925 # (or __new__), then this signature is for
Berker Peksagf23530f2014-10-19 18:04:38 +03003926 # calling the class to construct a new instance.
Larry Hastings2623c8c2014-02-08 22:15:29 -08003927 p_add('$')
Larry Hastings31826802013-10-19 00:09:25 -07003928
Larry Hastings5c661892014-01-24 06:17:25 -08003929 name = p.converter.signature_name or p.name
Larry Hastings2623c8c2014-02-08 22:15:29 -08003930 p_add(name)
Larry Hastings581ee362014-01-28 05:00:08 -08003931
Larry Hastings31826802013-10-19 00:09:25 -07003932 if p.converter.is_optional():
Larry Hastings2623c8c2014-02-08 22:15:29 -08003933 p_add('=')
Larry Hastingsc4fe0922014-01-19 02:27:34 -08003934 value = p.converter.py_default
3935 if not value:
Larry Hastings66575782014-01-19 03:01:23 -08003936 value = repr(p.converter.default)
Larry Hastings2623c8c2014-02-08 22:15:29 -08003937 p_add(value)
3938
3939 if (p != last_p) or need_a_trailing_slash:
3940 p_add(',')
3941
3942 add_parameter(p_output())
Larry Hastings31826802013-10-19 00:09:25 -07003943
3944 add(fix_right_bracket_count(0))
Larry Hastings2623c8c2014-02-08 22:15:29 -08003945 if need_a_trailing_slash:
3946 add_parameter('/')
Larry Hastings31826802013-10-19 00:09:25 -07003947 add(')')
3948
Larry Hastings2a727912014-01-16 11:32:01 -08003949 # PEP 8 says:
3950 #
3951 # The Python standard library will not use function annotations
3952 # as that would result in a premature commitment to a particular
3953 # annotation style. Instead, the annotations are left for users
3954 # to discover and experiment with useful annotation styles.
3955 #
3956 # therefore this is commented out:
3957 #
3958 # if f.return_converter.py_default:
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003959 # add(' -> ')
Larry Hastings2a727912014-01-16 11:32:01 -08003960 # add(f.return_converter.py_default)
Larry Hastings31826802013-10-19 00:09:25 -07003961
Larry Hastings2623c8c2014-02-08 22:15:29 -08003962 if not f.docstring_only:
3963 add("\n--\n")
3964
Larry Hastings31826802013-10-19 00:09:25 -07003965 docstring_first_line = output()
3966
3967 # now fix up the places where the brackets look wrong
3968 docstring_first_line = docstring_first_line.replace(', ]', ',] ')
3969
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003970 # okay. now we're officially building the "parameters" section.
Larry Hastings31826802013-10-19 00:09:25 -07003971 # create substitution text for {parameters}
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003972 spacer_line = False
Larry Hastings31826802013-10-19 00:09:25 -07003973 for p in parameters:
3974 if not p.docstring.strip():
3975 continue
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003976 if spacer_line:
3977 add('\n')
3978 else:
3979 spacer_line = True
Larry Hastings31826802013-10-19 00:09:25 -07003980 add(" ")
3981 add(p.name)
3982 add('\n')
3983 add(textwrap.indent(rstrip_lines(p.docstring.rstrip()), " "))
Larry Hastings44e2eaa2013-11-23 15:37:55 -08003984 parameters = output()
3985 if parameters:
3986 parameters += '\n'
Larry Hastings31826802013-10-19 00:09:25 -07003987
3988 ##
3989 ## docstring body
3990 ##
3991
3992 docstring = f.docstring.rstrip()
3993 lines = [line.rstrip() for line in docstring.split('\n')]
3994
3995 # Enforce the summary line!
3996 # The first line of a docstring should be a summary of the function.
3997 # It should fit on one line (80 columns? 79 maybe?) and be a paragraph
3998 # by itself.
3999 #
4000 # Argument Clinic enforces the following rule:
4001 # * either the docstring is empty,
4002 # * or it must have a summary line.
4003 #
4004 # Guido said Clinic should enforce this:
4005 # http://mail.python.org/pipermail/python-dev/2013-June/127110.html
4006
4007 if len(lines) >= 2:
4008 if lines[1]:
4009 fail("Docstring for " + f.full_name + " does not have a summary line!\n" +
4010 "Every non-blank function docstring must start with\n" +
4011 "a single line summary followed by an empty line.")
4012 elif len(lines) == 1:
4013 # the docstring is only one line right now--the summary line.
4014 # add an empty line after the summary line so we have space
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004015 # between it and the {parameters} we're about to add.
Larry Hastings31826802013-10-19 00:09:25 -07004016 lines.append('')
4017
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004018 parameters_marker_count = len(docstring.split('{parameters}')) - 1
4019 if parameters_marker_count > 1:
4020 fail('You may not specify {parameters} more than once in a docstring!')
4021
4022 if not parameters_marker_count:
4023 # insert after summary line
4024 lines.insert(2, '{parameters}')
4025
4026 # insert at front of docstring
4027 lines.insert(0, docstring_first_line)
Larry Hastings31826802013-10-19 00:09:25 -07004028
4029 docstring = "\n".join(lines)
4030
4031 add(docstring)
4032 docstring = output()
4033
Larry Hastings44e2eaa2013-11-23 15:37:55 -08004034 docstring = linear_format(docstring, parameters=parameters)
Larry Hastings31826802013-10-19 00:09:25 -07004035 docstring = docstring.rstrip()
4036
4037 return docstring
4038
4039 def state_terminal(self, line):
4040 """
4041 Called when processing the block is done.
4042 """
4043 assert not line
4044
4045 if not self.function:
4046 return
4047
4048 if self.keyword_only:
4049 values = self.function.parameters.values()
4050 if not values:
4051 no_parameter_after_star = True
4052 else:
4053 last_parameter = next(reversed(list(values)))
4054 no_parameter_after_star = last_parameter.kind != inspect.Parameter.KEYWORD_ONLY
4055 if no_parameter_after_star:
4056 fail("Function " + self.function.name + " specifies '*' without any parameters afterwards.")
4057
4058 # remove trailing whitespace from all parameter docstrings
4059 for name, value in self.function.parameters.items():
4060 if not value:
4061 continue
4062 value.docstring = value.docstring.rstrip()
4063
4064 self.function.docstring = self.format_docstring()
4065
4066
Larry Hastings5c661892014-01-24 06:17:25 -08004067
4068
Larry Hastings31826802013-10-19 00:09:25 -07004069# maps strings to callables.
4070# the callable should return an object
4071# that implements the clinic parser
4072# interface (__init__ and parse).
4073#
4074# example parsers:
4075# "clinic", handles the Clinic DSL
4076# "python", handles running Python code
4077#
4078parsers = {'clinic' : DSLParser, 'python': PythonParser}
4079
4080
4081clinic = None
4082
4083
4084def main(argv):
4085 import sys
4086
4087 if sys.version_info.major < 3 or sys.version_info.minor < 3:
4088 sys.exit("Error: clinic.py requires Python 3.3 or greater.")
4089
4090 import argparse
4091 cmdline = argparse.ArgumentParser()
4092 cmdline.add_argument("-f", "--force", action='store_true')
4093 cmdline.add_argument("-o", "--output", type=str)
Larry Hastings5c661892014-01-24 06:17:25 -08004094 cmdline.add_argument("-v", "--verbose", action='store_true')
Larry Hastings31826802013-10-19 00:09:25 -07004095 cmdline.add_argument("--converters", action='store_true')
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004096 cmdline.add_argument("--make", action='store_true')
Larry Hastings31826802013-10-19 00:09:25 -07004097 cmdline.add_argument("filename", type=str, nargs="*")
4098 ns = cmdline.parse_args(argv)
4099
4100 if ns.converters:
4101 if ns.filename:
4102 print("Usage error: can't specify --converters and a filename at the same time.")
4103 print()
4104 cmdline.print_usage()
4105 sys.exit(-1)
4106 converters = []
4107 return_converters = []
4108 ignored = set("""
4109 add_c_converter
4110 add_c_return_converter
4111 add_default_legacy_c_converter
4112 add_legacy_c_converter
4113 """.strip().split())
4114 module = globals()
4115 for name in module:
4116 for suffix, ids in (
4117 ("_return_converter", return_converters),
4118 ("_converter", converters),
4119 ):
4120 if name in ignored:
4121 continue
4122 if name.endswith(suffix):
4123 ids.append((name, name[:-len(suffix)]))
4124 break
4125 print()
4126
4127 print("Legacy converters:")
4128 legacy = sorted(legacy_converters)
4129 print(' ' + ' '.join(c for c in legacy if c[0].isupper()))
4130 print(' ' + ' '.join(c for c in legacy if c[0].islower()))
4131 print()
4132
4133 for title, attribute, ids in (
4134 ("Converters", 'converter_init', converters),
4135 ("Return converters", 'return_converter_init', return_converters),
4136 ):
4137 print(title + ":")
4138 longest = -1
4139 for name, short_name in ids:
4140 longest = max(longest, len(short_name))
4141 for name, short_name in sorted(ids, key=lambda x: x[1].lower()):
4142 cls = module[name]
4143 callable = getattr(cls, attribute, None)
4144 if not callable:
4145 continue
4146 signature = inspect.signature(callable)
4147 parameters = []
4148 for parameter_name, parameter in signature.parameters.items():
4149 if parameter.kind == inspect.Parameter.KEYWORD_ONLY:
4150 if parameter.default != inspect.Parameter.empty:
4151 s = '{}={!r}'.format(parameter_name, parameter.default)
4152 else:
4153 s = parameter_name
4154 parameters.append(s)
4155 print(' {}({})'.format(short_name, ', '.join(parameters)))
Larry Hastings31826802013-10-19 00:09:25 -07004156 print()
Larry Hastings2a727912014-01-16 11:32:01 -08004157 print("All converters also accept (c_default=None, py_default=None, annotation=None).")
4158 print("All return converters also accept (py_default=None).")
Larry Hastings31826802013-10-19 00:09:25 -07004159 sys.exit(0)
4160
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004161 if ns.make:
4162 if ns.output or ns.filename:
4163 print("Usage error: can't use -o or filenames with --make.")
4164 print()
4165 cmdline.print_usage()
4166 sys.exit(-1)
4167 for root, dirs, files in os.walk('.'):
Larry Hastings5c661892014-01-24 06:17:25 -08004168 for rcs_dir in ('.svn', '.git', '.hg', 'build'):
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004169 if rcs_dir in dirs:
4170 dirs.remove(rcs_dir)
4171 for filename in files:
Larry Hastings5c661892014-01-24 06:17:25 -08004172 if not (filename.endswith('.c') or filename.endswith('.h')):
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004173 continue
4174 path = os.path.join(root, filename)
Larry Hastings5c661892014-01-24 06:17:25 -08004175 if ns.verbose:
4176 print(path)
Larry Hastings581ee362014-01-28 05:00:08 -08004177 parse_file(path, force=ns.force, verify=not ns.force)
Larry Hastingsdcd340e2013-11-23 14:58:45 -08004178 return
4179
Larry Hastings31826802013-10-19 00:09:25 -07004180 if not ns.filename:
4181 cmdline.print_usage()
4182 sys.exit(-1)
4183
4184 if ns.output and len(ns.filename) > 1:
4185 print("Usage error: can't use -o with multiple filenames.")
4186 print()
4187 cmdline.print_usage()
4188 sys.exit(-1)
4189
4190 for filename in ns.filename:
Larry Hastings5c661892014-01-24 06:17:25 -08004191 if ns.verbose:
4192 print(filename)
Larry Hastings581ee362014-01-28 05:00:08 -08004193 parse_file(filename, output=ns.output, force=ns.force, verify=not ns.force)
Larry Hastings31826802013-10-19 00:09:25 -07004194
4195
4196if __name__ == "__main__":
4197 sys.exit(main(sys.argv[1:]))