FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

gh-107603: Argument Clinic can emit includes by vstinner · Pull Request #108486 · python/cpython · GitHub

Repository navigation

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .py  (1) All 1 file type selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
58 changes: 41 additions & 17 deletions Tools/clinic/clinic.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -1075,6 +1075,11 @@ def output_templates(
del parameters[0]
converters = [p.converter for p in parameters]

# Copy includes from parameters to Clinic
for converter in converters:
if converter.include:
clinic.add_include(*converter.include)

has_option_groups = parameters and (parameters[0].group or parameters[-1].group)
default_return_converter = f.return_converter.type == 'PyObject *'
new_or_init = f.kind.new_or_init
Expand Down Expand Up @@ -2126,8 +2131,8 @@ def print_block(
self,
block: Block,
*,
clinic: Clinic,
core_includes: bool = False,
clinic: Clinic | None = None,
) -> None:
input = block.input
output = block.output
Expand Down Expand Up @@ -2156,18 +2161,22 @@ def print_block(
write("\n")

output = ''
if clinic:
limited_capi = clinic.limited_capi
else:
limited_capi = DEFAULT_LIMITED_CAPI
if core_includes and not limited_capi:
output += textwrap.dedent("""
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
# include "pycore_gc.h" // PyGC_Head
# include "pycore_runtime.h" // _Py_ID()
#endif

""")
if core_includes:
if not clinic.limited_capi:
output += textwrap.dedent("""
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
# include "pycore_gc.h" // PyGC_Head
# include "pycore_runtime.h" // _Py_ID()
#endif

""")

if clinic is not None:
# Emit optional includes
for include, reason in sorted(clinic.includes.items()):
line = f'#include "{include}"'
line = line.ljust(35) + f'// {reason}\n'
Comment on lines +2177 to +2178

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Should we add a comment to explain the indent amount?

Suggested change
line = f'#include "{include}"'
line = line.ljust(35) + f'// {reason}\n'
include = f'"{include}"'
line = f'#include {include: <25} // {reason}\n'

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

35 is my arbitrary convention that I'm using in Python. I prefer to keep ljust(35) since it reminds me the 35th column :-)

output += line

input = ''.join(block.input)
output += ''.join(block.output)
Expand Down Expand Up @@ -2311,7 +2320,7 @@ def __init__(self, clinic: Clinic) -> None: ...
def parse(self, block: Block) -> None: ...


clinic = None
clinic: Clinic | None = None
class Clinic:

presets_text = """
Expand Down Expand Up @@ -2379,6 +2388,9 @@ def __init__(
self.modules: ModuleDict = {}
self.classes: ClassDict = {}
self.functions: list[Function] = []
# dict: include name => reason
# Example: 'pycore_long.h' => '_PyLong_UnsignedShort_Converter()'
self.includes: dict[str, str] = {}

self.line_prefix = self.line_suffix = ''

Expand Down Expand Up @@ -2437,6 +2449,12 @@ def __init__(
global clinic
clinic = self

def add_include(self, name: str, reason: str) -> None:
if name in self.includes:
# Mention a single reason is enough, no need to list all of them
Comment on lines +2453 to +2454

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

For generated code we could list all the known reasons?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I don't see the point. It would generate giant lines for little value.

For #include, I like to show at least one imported symbol to explain why the include was needed. In manually written code, I use it to remove unused imports time to time. IMO here it's interesting to repeat this habit to explain why an include is needed.

return
self.includes[name] = reason

def add_destination(
self,
name: str,
Expand Down Expand Up @@ -3066,6 +3084,10 @@ class CConverter(metaclass=CConverterAutoRegister):
# Only set by self_converter.
signature_name: str | None = None

# Optional (name, reason) include which generate a line like:
# "#include "name" // reason"
include: tuple[str, str] | None = None

# keep in sync with self_converter.__init__!
def __init__(self,
# Positional args:
Expand Down Expand Up @@ -3370,6 +3392,11 @@ def parser_name(self) -> str:
else:
return self.name

def add_include(self, name: str, reason: str) -> None:
if self.include is not None:
raise ValueError("a converter only supports a single include")
self.include = (name, reason)

type_checks = {
'&PyLong_Type': ('PyLong_Check', 'int'),
'&PyTuple_Type': ('PyTuple_Check', 'tuple'),
Expand Down Expand Up @@ -5989,9 +6016,6 @@ def do_post_block_processing_cleanup(self, lineno: int) -> None:
}


clinic = None


def create_cli() -> argparse.ArgumentParser:
cmdline = argparse.ArgumentParser(
prog="clinic.py",
Expand Down

Back | FazBrowse Home | New Git URL