feat(Deprecated): Add message to SIP deprecated annotation

Works only with SIP 6.9.0
This commit is contained in:
Julien Cabieces 2024-12-11 17:34:24 +01:00
parent 398f00bc26
commit 92db5c2d82
2 changed files with 47 additions and 8 deletions

View File

@ -42,6 +42,7 @@ class MultiLineType(Enum):
parser = argparse.ArgumentParser(description="Convert header file to SIP and Python")
parser.add_argument("-debug", action="store_true", help="Enable debug mode")
parser.add_argument("-qt6", action="store_true", help="Enable Qt6 mode")
parser.add_argument("-generate_deprecated_message", action="store_true", help="Generate sip files with deprecated messages (supported only in SIP > 6.9.0)")
parser.add_argument("-sip_output", help="SIP output file")
parser.add_argument("-python_output", help="Python output file")
parser.add_argument("-class_map", help="Class map file")
@ -79,7 +80,7 @@ class Context:
self.debug: bool = False
self.is_qt6: bool = False
self.header_file: str = ""
self.generate_deprecated_message = False
self.current_line: str = ""
self.sip_run: bool = False
self.header_code: bool = False
@ -127,6 +128,7 @@ class Context:
self.static_methods = defaultdict(dict)
self.current_signal_args = []
self.signal_arguments = defaultdict(dict)
self.deprecated_message = None
def current_fully_qualified_class_name(self) -> str:
return ".".join(
@ -145,6 +147,7 @@ class Context:
CONTEXT = Context()
CONTEXT.debug = args.debug
CONTEXT.is_qt6 = args.qt6
CONTEXT.generate_deprecated_message = args.generate_deprecated_message
CONTEXT.header_file = args.headerfile
CONTEXT.input_lines = input_lines
CONTEXT.line_count = len(input_lines)
@ -715,6 +718,14 @@ def create_class_links(line):
return line
def process_deprecated_message(message: str) -> str:
"""
Remove all doxygen specific command from deprecated message
"""
# SIP issue with ':' , see https://github.com/Python-SIP/sip/issues/59
return message.replace("\\see", "").replace(":", "")
def process_doxygen_line(line: str) -> str:
global CONTEXT
@ -880,6 +891,7 @@ def process_doxygen_line(line: str) -> str:
version = version[:-1]
depr_line = f"\n.. deprecated:: {version}"
message = deprecated_match.group("DEPR_MESSAGE")
CONTEXT.deprecated_message = f"Since {version}. {process_deprecated_message(message)}"
if message:
depr_line += "\n"
depr_line += "\n".join(f"\n {_m}" for _m in message.split("\n"))
@ -1157,6 +1169,11 @@ def fix_annotations(line):
CONTEXT.skipped_params_out.append(param)
dbg_info(f"caught removed param: {CONTEXT.skipped_params_out[-1]}")
if "SIP_DEPRECATED" in line:
if CONTEXT.deprecated_message is None:
exit_with_error(f"Error in file {CONTEXT.header_file}: missing deprecated message for SIP_DEPRECATED instruction on line {CONTEXT.line_idx}. Please add \\deprecated instruction")
# Printed annotations
replacements = {
r"//\s*SIP_ABSTRACT\b": "/Abstract/",
@ -1164,7 +1181,6 @@ def fix_annotations(line):
r"\bSIP_ALLOWNONE\b": "/AllowNone/",
r"\bSIP_ARRAY\b": "/Array/",
r"\bSIP_ARRAYSIZE\b": "/ArraySize/",
r"\bSIP_DEPRECATED\b": "/Deprecated/",
r"\bSIP_CONSTRAINED\b": "/Constrained/",
r"\bSIP_EXTERNAL\b": "/External/",
r"\bSIP_FACTORY\b": "/Factory/",
@ -1190,16 +1206,21 @@ def fix_annotations(line):
# these have no effect (and aren't required) on sip >= 6
replacements[r"SIP_THROW\(\s*([\w\s,]+?)\s*\)"] = ""
if CONTEXT.generate_deprecated_message:
# check deprecated message is not empty
replacements[r"\bSIP_DEPRECATED\b"] = f'/Deprecated="{CONTEXT.deprecated_message}"/'
else:
replacements[r"\bSIP_DEPRECATED\b"] = f"/Deprecated/"
for _pattern, replacement in replacements.items():
line = re.sub(_pattern, replacement, line)
# Combine multiple annotations
while True:
new_line = re.sub(
r'/([\w,]+(="?[\w, \[\]]+"?)?)/\s*/([\w,]+(="?[\w, \[\]]+"?)?]?)/',
r'/([\w,]+(="?[^"]+"?)?)/\s*/([\w,]+(="?[^"]+"?)?]?)/',
r"/\1,\3/",
line,
)
line)
if new_line == line:
break
line = new_line

View File

@ -16,11 +16,15 @@
set -e
CLASS_MAP=0
while getopts "m" opt; do
DEPRECATED_MESSAGE=0
while getopts "md" opt; do
case $opt in
m)
CLASS_MAP=1
;;
d)
DEPRECATED_MESSAGE=1
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
@ -47,6 +51,14 @@ else
modules=(core gui analysis server 3d)
fi
pids=()
iPid=0
GENERATE_DEPRECATED_MESSAGE=""
if [[ ${DEPRECATED_MESSAGE} -eq 1 ]]; then
GENERATE_DEPRECATED_MESSAGE="-generate_deprecated_message"
fi
for root_dir in python python/PyQt6; do
if [[ $root_dir == "python/PyQt6" ]]; then
@ -83,13 +95,19 @@ It is not aimed to be manually edited
if [[ ${CLASS_MAP} -eq 1 ]]; then
CLASS_MAP_CALL="-c ${module_dir}/class_map.yaml"
fi
./scripts/sipify.py $IS_QT6 -s ${root_dir}/${sipfile}.in -p ${module_dir}/auto_additions/${pyfile} ${CLASS_MAP_CALL} ${header} &
./scripts/sipify.py $IS_QT6 $GENERATE_DEPRECATED_MESSAGE -s ${root_dir}/${sipfile}.in -p ${module_dir}/auto_additions/${pyfile} ${CLASS_MAP_CALL} ${header} &
pids[iPid]=$!
iPid=$((iPid+1))
fi
count=$((count+1))
done < <( ${GP}sed -n -r "s@^%Include auto_generated/(.*\.sip)@${module}/auto_generated/\1@p" python/${module}/${module}_auto.sip )
done
done
wait # wait for sipify processes to finish
for pid in "${pids[@]}"; do
wait $pid || ( echo "Errors while calling sipify!!!" && exit 1 )
done
if [[ ${CLASS_MAP} -eq 1 ]]; then
for root_dir in python python/PyQt6; do