return s + "_value"
return s
-def format_escape(s: str) -> str:
- # double up curly-braces, this string will be used
- # as part of a format_map() template later
- s = s.replace('{', '{{')
- s = s.replace('}', '}}')
- return s
def linear_format(s: str, **kwargs: str) -> str:
"""
return tuple(accumulator)
-def strip_leading_and_trailing_blank_lines(s: str) -> str:
- lines = s.rstrip().split('\n')
- while lines:
- line = lines[0]
- if line.strip():
- break
- del lines[0]
- return '\n'.join(lines)
-
-@functools.lru_cache()
-def normalize_snippet(
- s: str,
- *,
- indent: int = 0
-) -> str:
- """
- Reformats s:
- * removes leading and trailing blank lines
- * ensures that it does not end with a newline
- * dedents so the first nonwhite character on any line is at column "indent"
- """
- s = strip_leading_and_trailing_blank_lines(s)
- s = textwrap.dedent(s)
- if indent:
- s = textwrap.indent(s, ' ' * indent)
- return s
-
-
def declare_parser(
f: Function,
*,
}};
#undef KWTUPLE
""" % (format_ or fname)
- return normalize_snippet(declarations)
-
-
-def wrap_declarations(
- text: str,
- length: int = 78
-) -> str:
- """
- A simple-minded text wrapper for C function declarations.
-
- It views a declaration line as looking like this:
- xxxxxxxx(xxxxxxxxx,xxxxxxxxx)
- If called with length=30, it would wrap that line into
- xxxxxxxx(xxxxxxxxx,
- xxxxxxxxx)
- (If the declaration has zero or one parameters, this
- function won't wrap it.)
-
- If this doesn't work properly, it's probably better to
- start from scratch with a more sophisticated algorithm,
- rather than try and improve/debug this dumb little function.
- """
- lines = []
- for line in text.split('\n'):
- prefix, _, after_l_paren = line.partition('(')
- if not after_l_paren:
- lines.append(line)
- continue
- in_paren, _, after_r_paren = after_l_paren.partition(')')
- if not _:
- lines.append(line)
- continue
- if ',' not in in_paren:
- lines.append(line)
- continue
- parameters = [x.strip() + ", " for x in in_paren.split(',')]
- prefix += "("
- if len(prefix) < length:
- spaces = " " * len(prefix)
- else:
- spaces = " " * 4
-
- while parameters:
- line = prefix
- first = True
- while parameters:
- if (not first and
- (len(line) + len(parameters[0]) > length)):
- break
- line += parameters.pop(0)
- first = False
- if not parameters:
- line = line.rstrip(", ") + ")" + after_r_paren
- lines.append(line.rstrip())
- prefix = spaces
- return "\n".join(lines)
+ return libclinic.normalize_snippet(declarations)
class CLanguage(Language):
NO_VARARG: Final[str] = "PY_SSIZE_T_MAX"
- PARSER_PROTOTYPE_KEYWORD: Final[str] = normalize_snippet("""
+ PARSER_PROTOTYPE_KEYWORD: Final[str] = libclinic.normalize_snippet("""
static PyObject *
{c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
""")
- PARSER_PROTOTYPE_KEYWORD___INIT__: Final[str] = normalize_snippet("""
+ PARSER_PROTOTYPE_KEYWORD___INIT__: Final[str] = libclinic.normalize_snippet("""
static int
{c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
""")
- PARSER_PROTOTYPE_VARARGS: Final[str] = normalize_snippet("""
+ PARSER_PROTOTYPE_VARARGS: Final[str] = libclinic.normalize_snippet("""
static PyObject *
{c_basename}({self_type}{self_name}, PyObject *args)
""")
- PARSER_PROTOTYPE_FASTCALL: Final[str] = normalize_snippet("""
+ PARSER_PROTOTYPE_FASTCALL: Final[str] = libclinic.normalize_snippet("""
static PyObject *
{c_basename}({self_type}{self_name}, PyObject *const *args, Py_ssize_t nargs)
""")
- PARSER_PROTOTYPE_FASTCALL_KEYWORDS: Final[str] = normalize_snippet("""
+ PARSER_PROTOTYPE_FASTCALL_KEYWORDS: Final[str] = libclinic.normalize_snippet("""
static PyObject *
{c_basename}({self_type}{self_name}, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
""")
- PARSER_PROTOTYPE_DEF_CLASS: Final[str] = normalize_snippet("""
+ PARSER_PROTOTYPE_DEF_CLASS: Final[str] = libclinic.normalize_snippet("""
static PyObject *
{c_basename}({self_type}{self_name}, PyTypeObject *{defining_class_name}, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
""")
- PARSER_PROTOTYPE_NOARGS: Final[str] = normalize_snippet("""
+ PARSER_PROTOTYPE_NOARGS: Final[str] = libclinic.normalize_snippet("""
static PyObject *
{c_basename}({self_type}{self_name}, PyObject *Py_UNUSED(ignored))
""")
- PARSER_PROTOTYPE_GETTER: Final[str] = normalize_snippet("""
+ PARSER_PROTOTYPE_GETTER: Final[str] = libclinic.normalize_snippet("""
static PyObject *
{c_basename}({self_type}{self_name}, void *Py_UNUSED(context))
""")
- PARSER_PROTOTYPE_SETTER: Final[str] = normalize_snippet("""
+ PARSER_PROTOTYPE_SETTER: Final[str] = libclinic.normalize_snippet("""
static int
{c_basename}({self_type}{self_name}, PyObject *value, void *Py_UNUSED(context))
""")
- METH_O_PROTOTYPE: Final[str] = normalize_snippet("""
+ METH_O_PROTOTYPE: Final[str] = libclinic.normalize_snippet("""
static PyObject *
{c_basename}({impl_parameters})
""")
- DOCSTRING_PROTOTYPE_VAR: Final[str] = normalize_snippet("""
+ DOCSTRING_PROTOTYPE_VAR: Final[str] = libclinic.normalize_snippet("""
PyDoc_VAR({c_basename}__doc__);
""")
- DOCSTRING_PROTOTYPE_STRVAR: Final[str] = normalize_snippet("""
+ DOCSTRING_PROTOTYPE_STRVAR: Final[str] = libclinic.normalize_snippet("""
PyDoc_STRVAR({c_basename}__doc__,
{docstring});
""")
- GETSET_DOCSTRING_PROTOTYPE_STRVAR: Final[str] = normalize_snippet("""
+ GETSET_DOCSTRING_PROTOTYPE_STRVAR: Final[str] = libclinic.normalize_snippet("""
PyDoc_STRVAR({getset_basename}__doc__,
{docstring});
#define {getset_basename}_HAS_DOCSTR
""")
- IMPL_DEFINITION_PROTOTYPE: Final[str] = normalize_snippet("""
+ IMPL_DEFINITION_PROTOTYPE: Final[str] = libclinic.normalize_snippet("""
static {impl_return_type}
{c_basename}_impl({impl_parameters})
""")
- METHODDEF_PROTOTYPE_DEFINE: Final[str] = normalize_snippet(r"""
+ METHODDEF_PROTOTYPE_DEFINE: Final[str] = libclinic.normalize_snippet(r"""
#define {methoddef_name} \
{{"{name}", {methoddef_cast}{c_basename}{methoddef_cast_end}, {methoddef_flags}, {c_basename}__doc__}},
""")
- GETTERDEF_PROTOTYPE_DEFINE: Final[str] = normalize_snippet(r"""
+ GETTERDEF_PROTOTYPE_DEFINE: Final[str] = libclinic.normalize_snippet(r"""
#if defined({getset_basename}_HAS_DOCSTR)
# define {getset_basename}_DOCSTR {getset_basename}__doc__
#else
# define {getset_name}_GETSETDEF {{"{name}", (getter){getset_basename}_get, NULL, {getset_basename}_DOCSTR}},
#endif
""")
- SETTERDEF_PROTOTYPE_DEFINE: Final[str] = normalize_snippet(r"""
+ SETTERDEF_PROTOTYPE_DEFINE: Final[str] = libclinic.normalize_snippet(r"""
#if defined({getset_name}_HAS_DOCSTR)
# define {getset_basename}_DOCSTR {getset_basename}__doc__
#else
# define {getset_name}_GETSETDEF {{"{name}", NULL, (setter){getset_basename}_set, NULL}},
#endif
""")
- METHODDEF_PROTOTYPE_IFNDEF: Final[str] = normalize_snippet("""
+ METHODDEF_PROTOTYPE_IFNDEF: Final[str] = libclinic.normalize_snippet("""
#ifndef {methoddef_name}
#define {methoddef_name}
#endif /* !defined({methoddef_name}) */
minor=minversion[1],
message=libclinic.c_repr(message),
)
- return normalize_snippet(code)
+ return libclinic.normalize_snippet(code)
def deprecate_positional_use(
self,
message=libclinic.wrapped_c_string_literal(message, width=64,
subsequent_indent=20),
)
- return normalize_snippet(code, indent=4)
+ return libclinic.normalize_snippet(code, indent=4)
def deprecate_keyword_use(
self,
message=libclinic.wrapped_c_string_literal(message, width=64,
subsequent_indent=20),
)
- return normalize_snippet(code, indent=4)
+ return libclinic.normalize_snippet(code, indent=4)
def output_templates(
self,
lines.append(prototype)
parser_body_fields = fields
- preamble = normalize_snippet("""
+ preamble = libclinic.normalize_snippet("""
{{
{return_value_declaration}
{parser_declarations}
{declarations}
{initializers}
""") + "\n"
- finale = normalize_snippet("""
+ finale = libclinic.normalize_snippet("""
{modifications}
{lock}
{return_value} = {c_basename}_impl({impl_arguments});
parser_prototype = self.PARSER_PROTOTYPE_DEF_CLASS
return_error = ('return NULL;' if simple_return
else 'goto exit;')
- parser_code = [normalize_snippet("""
+ parser_code = [libclinic.normalize_snippet("""
if (nargs) {{
PyErr_SetString(PyExc_TypeError, "{name}() takes no arguments");
%s
argname = 'arg'
if parameters[0].name == argname:
argname += '_'
- parser_prototype = normalize_snippet("""
+ parser_prototype = libclinic.normalize_snippet("""
static PyObject *
{c_basename}({self_type}{self_name}, PyObject *%s)
""" % argname)
}}
""" % argname
parser_definition = parser_body(parser_prototype,
- normalize_snippet(parsearg, indent=4))
+ libclinic.normalize_snippet(parsearg, indent=4))
elif has_option_groups:
# positional parameters with option groups
if limited_capi:
parser_code = []
if nargs != 'nargs':
- parser_code.append(normalize_snippet(f'Py_ssize_t nargs = {nargs};', indent=4))
+ nargs_def = f'Py_ssize_t nargs = {nargs};'
+ parser_code.append(libclinic.normalize_snippet(nargs_def, indent=4))
nargs = 'nargs'
if min_pos == max_args:
pl = '' if min_pos == 1 else 's'
- parser_code.append(normalize_snippet(f"""
+ parser_code.append(libclinic.normalize_snippet(f"""
if ({nargs} != {min_pos}) {{{{
PyErr_Format(PyExc_TypeError, "{{name}} expected {min_pos} argument{pl}, got %zd", {nargs});
goto exit;
else:
if min_pos:
pl = '' if min_pos == 1 else 's'
- parser_code.append(normalize_snippet(f"""
+ parser_code.append(libclinic.normalize_snippet(f"""
if ({nargs} < {min_pos}) {{{{
PyErr_Format(PyExc_TypeError, "{{name}} expected at least {min_pos} argument{pl}, got %zd", {nargs});
goto exit;
indent=4))
if max_args != self.NO_VARARG:
pl = '' if max_args == 1 else 's'
- parser_code.append(normalize_snippet(f"""
+ parser_code.append(libclinic.normalize_snippet(f"""
if ({nargs} > {max_args}) {{{{
PyErr_Format(PyExc_TypeError, "{{name}} expected at most {max_args} argument{pl}, got %zd", {nargs});
goto exit;
else:
clinic.add_include('pycore_modsupport.h',
'_PyArg_CheckPositional()')
- parser_code = [normalize_snippet(f"""
+ parser_code = [libclinic.normalize_snippet(f"""
if (!_PyArg_CheckPositional("{{name}}", {nargs}, {min_pos}, {max_args})) {{{{
goto exit;
}}}}
for i, p in enumerate(parameters):
if p.is_vararg():
if fastcall:
- parser_code.append(normalize_snippet("""
+ parser_code.append(libclinic.normalize_snippet("""
%s = PyTuple_New(%s);
if (!%s) {{
goto exit;
max_pos
), indent=4))
else:
- parser_code.append(normalize_snippet("""
+ parser_code.append(libclinic.normalize_snippet("""
%s = PyTuple_GetSlice(%d, -1);
""" % (
p.converter.parser_name,
break
if has_optional or p.is_optional():
has_optional = True
- parser_code.append(normalize_snippet("""
+ parser_code.append(libclinic.normalize_snippet("""
if (%s < %d) {{
goto skip_optional;
}}
""", indent=4) % (nargs, i + 1))
- parser_code.append(normalize_snippet(parsearg, indent=4))
+ parser_code.append(libclinic.normalize_snippet(parsearg, indent=4))
if parser_code is not None:
if has_optional:
if fastcall:
clinic.add_include('pycore_modsupport.h',
'_PyArg_ParseStack()')
- parser_code = [normalize_snippet("""
+ parser_code = [libclinic.normalize_snippet("""
if (!_PyArg_ParseStack(args, nargs, "{format_units}:{name}",
{parse_arguments})) {{
goto exit;
else:
flags = "METH_VARARGS"
parser_prototype = self.PARSER_PROTOTYPE_VARARGS
- parser_code = [normalize_snippet("""
+ parser_code = [libclinic.normalize_snippet("""
if (!PyArg_ParseTuple(args, "{format_units}:{name}",
{parse_arguments})) {{
goto exit;
declarations += "\nPyObject *argsbuf[%s];" % len(converters)
if has_optional_kw:
declarations += "\nPy_ssize_t noptargs = %s + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - %d;" % (nargs, min_pos + min_kw_only)
- parser_code = [normalize_snippet("""
+ parser_code = [libclinic.normalize_snippet("""
args = %s(args, nargs, NULL, kwnames, &_parser, %s, argsbuf);
if (!args) {{
goto exit;
declarations += "\nPy_ssize_t nargs = PyTuple_GET_SIZE(args);"
if has_optional_kw:
declarations += "\nPy_ssize_t noptargs = %s + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - %d;" % (nargs, min_pos + min_kw_only)
- parser_code = [normalize_snippet("""
+ parser_code = [libclinic.normalize_snippet("""
fastargs = %s(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, %s, argsbuf);
if (!fastargs) {{
goto exit;
parser_code.append("%s:" % add_label)
add_label = None
if not p.is_optional():
- parser_code.append(normalize_snippet(parsearg, indent=4))
+ parser_code.append(libclinic.normalize_snippet(parsearg, indent=4))
elif i < pos_only:
add_label = 'skip_optional_posonly'
- parser_code.append(normalize_snippet("""
+ parser_code.append(libclinic.normalize_snippet("""
if (nargs < %d) {{
goto %s;
}}
""" % (i + 1, add_label), indent=4))
if has_optional_kw:
- parser_code.append(normalize_snippet("""
+ parser_code.append(libclinic.normalize_snippet("""
noptargs--;
""", indent=4))
- parser_code.append(normalize_snippet(parsearg, indent=4))
+ parser_code.append(libclinic.normalize_snippet(parsearg, indent=4))
else:
if i < max_pos:
label = 'skip_optional_pos'
first_opt += 1
if i == first_opt:
add_label = label
- parser_code.append(normalize_snippet("""
+ parser_code.append(libclinic.normalize_snippet("""
if (!noptargs) {{
goto %s;
}}
""" % add_label, indent=4))
if i + 1 == len(parameters):
- parser_code.append(normalize_snippet(parsearg, indent=4))
+ parser_code.append(libclinic.normalize_snippet(parsearg, indent=4))
else:
add_label = label
- parser_code.append(normalize_snippet("""
+ parser_code.append(libclinic.normalize_snippet("""
if (%s) {{
""" % (argname_fmt % i), indent=4))
- parser_code.append(normalize_snippet(parsearg, indent=8))
- parser_code.append(normalize_snippet("""
+ parser_code.append(libclinic.normalize_snippet(parsearg, indent=8))
+ parser_code.append(libclinic.normalize_snippet("""
if (!--noptargs) {{
goto %s;
}}
assert not fastcall
flags = "METH_VARARGS|METH_KEYWORDS"
parser_prototype = self.PARSER_PROTOTYPE_KEYWORD
- parser_code = [normalize_snippet("""
+ parser_code = [libclinic.normalize_snippet("""
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "{format_units}:{name}", _keywords,
{parse_arguments}))
goto exit;
elif fastcall:
clinic.add_include('pycore_modsupport.h',
'_PyArg_ParseStackAndKeywords()')
- parser_code = [normalize_snippet("""
+ parser_code = [libclinic.normalize_snippet("""
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser{parse_arguments_comma}
{parse_arguments})) {{
goto exit;
else:
clinic.add_include('pycore_modsupport.h',
'_PyArg_ParseTupleAndKeywordsFast()')
- parser_code = [normalize_snippet("""
+ parser_code = [libclinic.normalize_snippet("""
if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
{parse_arguments})) {{
goto exit;
declarations = '{base_type_ptr}'
clinic.add_include('pycore_modsupport.h',
'_PyArg_NoKeywords()')
- fields.insert(0, normalize_snippet("""
+ fields.insert(0, libclinic.normalize_snippet("""
if ({self_type_check}!_PyArg_NoKeywords("{name}", kwargs)) {{
goto exit;
}}
if not parses_positional:
clinic.add_include('pycore_modsupport.h',
'_PyArg_NoPositional()')
- fields.insert(0, normalize_snippet("""
+ fields.insert(0, libclinic.normalize_snippet("""
if ({self_type_check}!_PyArg_NoPositional("{name}", args)) {{
goto exit;
}}
out.append(' goto exit;\n')
out.append("}")
- template_dict['option_group_parsing'] = format_escape("".join(out))
+ template_dict['option_group_parsing'] = libclinic.format_escape("".join(out))
def render_function(
self,
else:
template_dict['impl_return_type'] = f.return_converter.type
- template_dict['declarations'] = format_escape("\n".join(data.declarations))
+ template_dict['declarations'] = libclinic.format_escape("\n".join(data.declarations))
template_dict['initializers'] = "\n\n".join(data.initializers)
template_dict['modifications'] = '\n\n'.join(data.modifications)
template_dict['keywords_c'] = ' '.join('"' + k + '",'
template_dict['parse_arguments_comma'] = '';
template_dict['impl_parameters'] = ", ".join(data.impl_parameters)
template_dict['impl_arguments'] = ", ".join(data.impl_arguments)
- template_dict['return_conversion'] = format_escape("".join(data.return_conversion).rstrip())
- template_dict['post_parsing'] = format_escape("".join(data.post_parsing).rstrip())
- template_dict['cleanup'] = format_escape("".join(data.cleanup))
+
+ template_dict['return_conversion'] = libclinic.format_escape("".join(data.return_conversion).rstrip())
+ template_dict['post_parsing'] = libclinic.format_escape("".join(data.post_parsing).rstrip())
+ template_dict['cleanup'] = libclinic.format_escape("".join(data.cleanup))
+
template_dict['return_value'] = data.return_value
template_dict['lock'] = "\n".join(data.lock)
template_dict['unlock'] = "\n".join(data.unlock)
# mild hack:
# reflow long impl declarations
if name in {"impl_prototype", "impl_definition"}:
- s = wrap_declarations(s)
+ s = libclinic.wrap_declarations(s)
if clinic.line_prefix:
s = libclinic.indent_all_lines(s, clinic.line_prefix)