Skip to content

Commit

Permalink
feat(Deprecated): Add message to SIP deprecated annotation
Browse files Browse the repository at this point in the history
Works only with SIP 6.9.0
  • Loading branch information
troopa81 committed Dec 11, 2024
1 parent 0e804d1 commit ce0a6a5
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 8 deletions.
31 changes: 26 additions & 5 deletions scripts/sipify.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -79,7 +80,7 @@ def __init__(self):
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
Expand Down Expand Up @@ -127,6 +128,7 @@ def __init__(self):
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(
Expand All @@ -145,6 +147,7 @@ def current_fully_qualified_struct_name(self) -> str:
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)
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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"))
Expand Down Expand Up @@ -1157,14 +1169,18 @@ 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/",
r"\bSIP_ABSTRACT\b": "/Abstract/",
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/",
Expand All @@ -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
Expand Down
24 changes: 21 additions & 3 deletions scripts/sipify_all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit ce0a6a5

Please sign in to comment.