mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-26 15:36:14 +01:00
Merge branch 'py-fixes' into 'master'
Python formatting improvements See merge request GNOME/glib!1757
This commit is contained in:
commit
fa8a39c6c6
@ -23,18 +23,18 @@ import sys
|
|||||||
# that’s conventionally used as a way of marking a workaround which needs to
|
# that’s conventionally used as a way of marking a workaround which needs to
|
||||||
# be merged for now, but is to be grepped for and reverted or reworked later.
|
# be merged for now, but is to be grepped for and reverted or reworked later.
|
||||||
BANNED_KEYWORDS = [
|
BANNED_KEYWORDS = [
|
||||||
'TO' + 'DO',
|
"TO" + "DO",
|
||||||
'X' + 'XX',
|
"X" + "XX",
|
||||||
'W' + 'IP',
|
"W" + "IP",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description='Check a range of commits to ensure they don’t contain '
|
description="Check a range of commits to ensure they don’t contain "
|
||||||
'banned keywords.')
|
"banned keywords."
|
||||||
parser.add_argument('commits',
|
)
|
||||||
help='SHA to diff from, or range of commits to diff')
|
parser.add_argument("commits", help="SHA to diff from, or range of commits to diff")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
banned_words_seen = set()
|
banned_words_seen = set()
|
||||||
@ -43,47 +43,55 @@ def main():
|
|||||||
|
|
||||||
# Check the log messages for banned words.
|
# Check the log messages for banned words.
|
||||||
log_process = subprocess.run(
|
log_process = subprocess.run(
|
||||||
['git', 'log', '--no-color', args.commits + '..HEAD'],
|
["git", "log", "--no-color", args.commits + "..HEAD"],
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8',
|
stdout=subprocess.PIPE,
|
||||||
check=True)
|
stderr=subprocess.PIPE,
|
||||||
log_lines = log_process.stdout.strip().split('\n')
|
encoding="utf-8",
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
log_lines = log_process.stdout.strip().split("\n")
|
||||||
|
|
||||||
for line in log_lines:
|
for line in log_lines:
|
||||||
for keyword in BANNED_KEYWORDS:
|
for keyword in BANNED_KEYWORDS:
|
||||||
if re.search('(^|\W+){}(\W+|$)'.format(keyword), line):
|
if re.search(r"(^|\W+){}(\W+|$)".format(keyword), line):
|
||||||
banned_words_seen.add(keyword)
|
banned_words_seen.add(keyword)
|
||||||
seen_in_log = True
|
seen_in_log = True
|
||||||
|
|
||||||
# Check the diff for banned words.
|
# Check the diff for banned words.
|
||||||
diff_process = subprocess.run(
|
diff_process = subprocess.run(
|
||||||
['git', 'diff', '-U0', '--no-color', args.commits],
|
["git", "diff", "-U0", "--no-color", args.commits],
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8',
|
stdout=subprocess.PIPE,
|
||||||
check=True)
|
stderr=subprocess.PIPE,
|
||||||
diff_lines = diff_process.stdout.strip().split('\n')
|
encoding="utf-8",
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
diff_lines = diff_process.stdout.strip().split("\n")
|
||||||
|
|
||||||
for line in diff_lines:
|
for line in diff_lines:
|
||||||
if not line.startswith('+ '):
|
if not line.startswith("+ "):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for keyword in BANNED_KEYWORDS:
|
for keyword in BANNED_KEYWORDS:
|
||||||
if re.search('(^|\W+){}(\W+|$)'.format(keyword), line):
|
if re.search(r"(^|\W+){}(\W+|$)".format(keyword), line):
|
||||||
banned_words_seen.add(keyword)
|
banned_words_seen.add(keyword)
|
||||||
seen_in_diff = True
|
seen_in_diff = True
|
||||||
|
|
||||||
if banned_words_seen:
|
if banned_words_seen:
|
||||||
if seen_in_log and seen_in_diff:
|
if seen_in_log and seen_in_diff:
|
||||||
where = 'commit message and diff'
|
where = "commit message and diff"
|
||||||
elif seen_in_log:
|
elif seen_in_log:
|
||||||
where = 'commit message'
|
where = "commit message"
|
||||||
elif seen_in_diff:
|
elif seen_in_diff:
|
||||||
where = 'commit diff'
|
where = "commit diff"
|
||||||
|
|
||||||
print('Saw banned keywords in a {}: {}. '
|
print(
|
||||||
'This indicates the branch is a work in progress and should not '
|
"Saw banned keywords in a {}: {}. "
|
||||||
'be merged in its current '
|
"This indicates the branch is a work in progress and should not "
|
||||||
'form.'.format(where, ', '.join(banned_words_seen)))
|
"be merged in its current "
|
||||||
|
"form.".format(where, ", ".join(banned_words_seen))
|
||||||
|
)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
@ -11,105 +11,115 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import datetime
|
import datetime
|
||||||
import json
|
import json
|
||||||
import os
|
|
||||||
import sys
|
import sys
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
aparser = argparse.ArgumentParser(description='Turns a Meson test log into a JUnit report')
|
aparser = argparse.ArgumentParser(
|
||||||
aparser.add_argument('--project-name', metavar='NAME',
|
description="Turns a Meson test log into a JUnit report"
|
||||||
help='The project name',
|
)
|
||||||
default='unknown')
|
aparser.add_argument(
|
||||||
aparser.add_argument('--job-id', metavar='ID',
|
"--project-name", metavar="NAME", help="The project name", default="unknown"
|
||||||
help='The job ID for the report',
|
)
|
||||||
default='Unknown')
|
aparser.add_argument(
|
||||||
aparser.add_argument('--branch', metavar='NAME',
|
"--job-id", metavar="ID", help="The job ID for the report", default="Unknown"
|
||||||
help='Branch of the project being tested',
|
)
|
||||||
default='master')
|
aparser.add_argument(
|
||||||
aparser.add_argument('--output', metavar='FILE',
|
"--branch",
|
||||||
help='The output file, stdout by default',
|
metavar="NAME",
|
||||||
type=argparse.FileType('w', encoding='UTF-8'),
|
help="Branch of the project being tested",
|
||||||
default=sys.stdout)
|
default="master",
|
||||||
aparser.add_argument('infile', metavar='FILE',
|
)
|
||||||
help='The input testlog.json, stdin by default',
|
aparser.add_argument(
|
||||||
type=argparse.FileType('r', encoding='UTF-8'),
|
"--output",
|
||||||
default=sys.stdin)
|
metavar="FILE",
|
||||||
|
help="The output file, stdout by default",
|
||||||
|
type=argparse.FileType("w", encoding="UTF-8"),
|
||||||
|
default=sys.stdout,
|
||||||
|
)
|
||||||
|
aparser.add_argument(
|
||||||
|
"infile",
|
||||||
|
metavar="FILE",
|
||||||
|
help="The input testlog.json, stdin by default",
|
||||||
|
type=argparse.FileType("r", encoding="UTF-8"),
|
||||||
|
default=sys.stdin,
|
||||||
|
)
|
||||||
|
|
||||||
args = aparser.parse_args()
|
args = aparser.parse_args()
|
||||||
|
|
||||||
outfile = args.output
|
outfile = args.output
|
||||||
|
|
||||||
testsuites = ET.Element('testsuites')
|
testsuites = ET.Element("testsuites")
|
||||||
testsuites.set('id', '{}/{}'.format(args.job_id, args.branch))
|
testsuites.set("id", "{}/{}".format(args.job_id, args.branch))
|
||||||
testsuites.set('package', args.project_name)
|
testsuites.set("package", args.project_name)
|
||||||
testsuites.set('timestamp', datetime.datetime.utcnow().isoformat())
|
testsuites.set("timestamp", datetime.datetime.utcnow().isoformat())
|
||||||
|
|
||||||
suites = {}
|
suites = {}
|
||||||
for line in args.infile:
|
for line in args.infile:
|
||||||
data = json.loads(line)
|
data = json.loads(line)
|
||||||
(full_suite, unit_name) = data['name'].split(' / ')
|
(full_suite, unit_name) = data["name"].split(" / ")
|
||||||
try:
|
try:
|
||||||
(project_name, suite_name) = full_suite.split(':')
|
(project_name, suite_name) = full_suite.split(":")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
project_name = full_suite
|
project_name = full_suite
|
||||||
suite_name = full_suite
|
suite_name = full_suite
|
||||||
|
|
||||||
duration = data['duration']
|
duration = data["duration"]
|
||||||
return_code = data['returncode']
|
return_code = data["returncode"]
|
||||||
log = data['stdout']
|
log = data["stdout"]
|
||||||
log_stderr = data.get('stderr', '')
|
log_stderr = data.get("stderr", "")
|
||||||
|
|
||||||
unit = {
|
unit = {
|
||||||
'suite': suite_name,
|
"suite": suite_name,
|
||||||
'name': unit_name,
|
"name": unit_name,
|
||||||
'duration': duration,
|
"duration": duration,
|
||||||
'returncode': return_code,
|
"returncode": return_code,
|
||||||
'stdout': log,
|
"stdout": log,
|
||||||
'stderr': log_stderr,
|
"stderr": log_stderr,
|
||||||
}
|
}
|
||||||
|
|
||||||
units = suites.setdefault(suite_name, [])
|
units = suites.setdefault(suite_name, [])
|
||||||
units.append(unit)
|
units.append(unit)
|
||||||
|
|
||||||
for name, units in suites.items():
|
for name, units in suites.items():
|
||||||
print('Processing suite {} (units: {})'.format(name, len(units)))
|
print("Processing suite {} (units: {})".format(name, len(units)))
|
||||||
|
|
||||||
def if_failed(unit):
|
def if_failed(unit):
|
||||||
if unit['returncode'] != 0:
|
if unit["returncode"] != 0:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def if_succeded(unit):
|
def if_succeded(unit):
|
||||||
if unit['returncode'] == 0:
|
if unit["returncode"] == 0:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
successes = list(filter(if_succeded, units))
|
successes = list(filter(if_succeded, units))
|
||||||
failures = list(filter(if_failed, units))
|
failures = list(filter(if_failed, units))
|
||||||
print(' - {}: {} pass, {} fail'.format(name, len(successes), len(failures)))
|
print(" - {}: {} pass, {} fail".format(name, len(successes), len(failures)))
|
||||||
|
|
||||||
testsuite = ET.SubElement(testsuites, 'testsuite')
|
testsuite = ET.SubElement(testsuites, "testsuite")
|
||||||
testsuite.set('name', '{}/{}'.format(args.project_name, name))
|
testsuite.set("name", "{}/{}".format(args.project_name, name))
|
||||||
testsuite.set('tests', str(len(units)))
|
testsuite.set("tests", str(len(units)))
|
||||||
testsuite.set('errors', str(len(failures)))
|
testsuite.set("errors", str(len(failures)))
|
||||||
testsuite.set('failures', str(len(failures)))
|
testsuite.set("failures", str(len(failures)))
|
||||||
|
|
||||||
for unit in successes:
|
for unit in successes:
|
||||||
testcase = ET.SubElement(testsuite, 'testcase')
|
testcase = ET.SubElement(testsuite, "testcase")
|
||||||
testcase.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
|
testcase.set("classname", "{}/{}".format(args.project_name, unit["suite"]))
|
||||||
testcase.set('name', unit['name'])
|
testcase.set("name", unit["name"])
|
||||||
testcase.set('time', str(unit['duration']))
|
testcase.set("time", str(unit["duration"]))
|
||||||
|
|
||||||
for unit in failures:
|
for unit in failures:
|
||||||
testcase = ET.SubElement(testsuite, 'testcase')
|
testcase = ET.SubElement(testsuite, "testcase")
|
||||||
testcase.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
|
testcase.set("classname", "{}/{}".format(args.project_name, unit["suite"]))
|
||||||
testcase.set('name', unit['name'])
|
testcase.set("name", unit["name"])
|
||||||
testcase.set('time', str(unit['duration']))
|
testcase.set("time", str(unit["duration"]))
|
||||||
|
|
||||||
failure = ET.SubElement(testcase, 'failure')
|
failure = ET.SubElement(testcase, "failure")
|
||||||
failure.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
|
failure.set("classname", "{}/{}".format(args.project_name, unit["suite"]))
|
||||||
failure.set('name', unit['name'])
|
failure.set("name", unit["name"])
|
||||||
failure.set('type', 'error')
|
failure.set("type", "error")
|
||||||
failure.text = unit['stdout'] + '\n' + unit['stderr']
|
failure.text = unit["stdout"] + "\n" + unit["stderr"]
|
||||||
|
|
||||||
output = ET.tostring(testsuites, encoding='unicode')
|
output = ET.tostring(testsuites, encoding="unicode")
|
||||||
outfile.write(output)
|
outfile.write(output)
|
||||||
|
@ -2,5 +2,8 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
# Disable formatting warnings in flake8, as we use `black` to handle that.
|
||||||
|
formatting_warnings=E101,E111,E114,E115,E116,E117,E12,E13,E2,E3,E401,E5,E70,W1,W2,W3,W5
|
||||||
|
|
||||||
# shellcheck disable=SC2046
|
# shellcheck disable=SC2046
|
||||||
flake8 --max-line-length=88 $(git ls-files '*.py')
|
flake8 --max-line-length=88 --ignore="$formatting_warnings" $(git ls-files '*.py')
|
||||||
|
@ -33,50 +33,76 @@ else:
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description=__doc__,
|
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
|
||||||
formatter_class=argparse.RawDescriptionHelpFormatter)
|
)
|
||||||
parser.add_argument('-i', action='store_true', default=False,
|
parser.add_argument(
|
||||||
help='apply edits to files instead of displaying a '
|
"-i",
|
||||||
'diff')
|
action="store_true",
|
||||||
parser.add_argument('-p', metavar='NUM', default=0,
|
default=False,
|
||||||
help='strip the smallest prefix containing P slashes')
|
help="apply edits to files instead of displaying a " "diff",
|
||||||
parser.add_argument('-regex', metavar='PATTERN', default=None,
|
)
|
||||||
help='custom pattern selecting file paths to reformat '
|
parser.add_argument(
|
||||||
'(case sensitive, overrides -iregex)')
|
"-p",
|
||||||
parser.add_argument('-iregex', metavar='PATTERN',
|
metavar="NUM",
|
||||||
default=r'.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hh|hpp|m|mm|inc'
|
default=0,
|
||||||
r'|js|ts|proto|protodevel|java|cs)',
|
help="strip the smallest prefix containing P slashes",
|
||||||
help='custom pattern selecting file paths to reformat '
|
)
|
||||||
'(case insensitive, overridden by -regex)')
|
parser.add_argument(
|
||||||
parser.add_argument('-sort-includes', action='store_true', default=False,
|
"-regex",
|
||||||
help='let clang-format sort include blocks')
|
metavar="PATTERN",
|
||||||
parser.add_argument('-v', '--verbose', action='store_true',
|
default=None,
|
||||||
help='be more verbose, ineffective without -i')
|
help="custom pattern selecting file paths to reformat "
|
||||||
parser.add_argument('-style',
|
"(case sensitive, overrides -iregex)",
|
||||||
help='formatting style to apply (LLVM, Google, '
|
)
|
||||||
'Chromium, Mozilla, WebKit)')
|
parser.add_argument(
|
||||||
parser.add_argument('-binary', default='clang-format',
|
"-iregex",
|
||||||
help='location of binary to use for clang-format')
|
metavar="PATTERN",
|
||||||
|
default=r".*\.(cpp|cc|c\+\+|cxx|c|cl|h|hh|hpp|m|mm|inc"
|
||||||
|
r"|js|ts|proto|protodevel|java|cs)",
|
||||||
|
help="custom pattern selecting file paths to reformat "
|
||||||
|
"(case insensitive, overridden by -regex)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-sort-includes",
|
||||||
|
action="store_true",
|
||||||
|
default=False,
|
||||||
|
help="let clang-format sort include blocks",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-v",
|
||||||
|
"--verbose",
|
||||||
|
action="store_true",
|
||||||
|
help="be more verbose, ineffective without -i",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-style",
|
||||||
|
help="formatting style to apply (LLVM, Google, " "Chromium, Mozilla, WebKit)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-binary",
|
||||||
|
default="clang-format",
|
||||||
|
help="location of binary to use for clang-format",
|
||||||
|
)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
# Extract changed lines for each file.
|
# Extract changed lines for each file.
|
||||||
filename = None
|
filename = None
|
||||||
lines_by_file = {}
|
lines_by_file = {}
|
||||||
for line in sys.stdin:
|
for line in sys.stdin:
|
||||||
match = re.search(r'^\+\+\+\ (.*?/){%s}(\S*)' % args.p, line)
|
match = re.search(r"^\+\+\+\ (.*?/){%s}(\S*)" % args.p, line)
|
||||||
if match:
|
if match:
|
||||||
filename = match.group(2)
|
filename = match.group(2)
|
||||||
if filename is None:
|
if filename is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if args.regex is not None:
|
if args.regex is not None:
|
||||||
if not re.match('^%s$' % args.regex, filename):
|
if not re.match("^%s$" % args.regex, filename):
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
if not re.match('^%s$' % args.iregex, filename, re.IGNORECASE):
|
if not re.match("^%s$" % args.iregex, filename, re.IGNORECASE):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
match = re.search(r'^@@.*\+(\d+)(,(\d+))?', line)
|
match = re.search(r"^@@.*\+(\d+)(,(\d+))?", line)
|
||||||
if match:
|
if match:
|
||||||
start_line = int(match.group(1))
|
start_line = int(match.group(1))
|
||||||
line_count = 1
|
line_count = 1
|
||||||
@ -86,7 +112,8 @@ def main():
|
|||||||
continue
|
continue
|
||||||
end_line = start_line + line_count - 1
|
end_line = start_line + line_count - 1
|
||||||
lines_by_file.setdefault(filename, []).extend(
|
lines_by_file.setdefault(filename, []).extend(
|
||||||
['-lines', str(start_line) + ':' + str(end_line)])
|
["-lines", str(start_line) + ":" + str(end_line)]
|
||||||
|
)
|
||||||
|
|
||||||
# Reformat files containing changes in place.
|
# Reformat files containing changes in place.
|
||||||
# We need to count amount of bytes generated in the output of
|
# We need to count amount of bytes generated in the output of
|
||||||
@ -95,20 +122,22 @@ def main():
|
|||||||
format_line_counter = 0
|
format_line_counter = 0
|
||||||
for filename, lines in lines_by_file.items():
|
for filename, lines in lines_by_file.items():
|
||||||
if args.i and args.verbose:
|
if args.i and args.verbose:
|
||||||
print('Formatting {}'.format(filename))
|
print("Formatting {}".format(filename))
|
||||||
command = [args.binary, filename]
|
command = [args.binary, filename]
|
||||||
if args.i:
|
if args.i:
|
||||||
command.append('-i')
|
command.append("-i")
|
||||||
if args.sort_includes:
|
if args.sort_includes:
|
||||||
command.append('-sort-includes')
|
command.append("-sort-includes")
|
||||||
command.extend(lines)
|
command.extend(lines)
|
||||||
if args.style:
|
if args.style:
|
||||||
command.extend(['-style', args.style])
|
command.extend(["-style", args.style])
|
||||||
p = subprocess.Popen(command,
|
p = subprocess.Popen(
|
||||||
|
command,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=None,
|
stderr=None,
|
||||||
stdin=subprocess.PIPE,
|
stdin=subprocess.PIPE,
|
||||||
universal_newlines=True)
|
universal_newlines=True,
|
||||||
|
)
|
||||||
stdout, _ = p.communicate()
|
stdout, _ = p.communicate()
|
||||||
if p.returncode != 0:
|
if p.returncode != 0:
|
||||||
sys.exit(p.returncode)
|
sys.exit(p.returncode)
|
||||||
@ -117,11 +146,15 @@ def main():
|
|||||||
with open(filename) as f:
|
with open(filename) as f:
|
||||||
code = f.readlines()
|
code = f.readlines()
|
||||||
formatted_code = StringIO(stdout).readlines()
|
formatted_code = StringIO(stdout).readlines()
|
||||||
diff = difflib.unified_diff(code, formatted_code,
|
diff = difflib.unified_diff(
|
||||||
filename, filename,
|
code,
|
||||||
'(before formatting)',
|
formatted_code,
|
||||||
'(after formatting)')
|
filename,
|
||||||
diff_string = ''.join(diff)
|
filename,
|
||||||
|
"(before formatting)",
|
||||||
|
"(after formatting)",
|
||||||
|
)
|
||||||
|
diff_string = "".join(diff)
|
||||||
if diff_string:
|
if diff_string:
|
||||||
format_line_counter += sys.stdout.write(diff_string)
|
format_line_counter += sys.stdout.write(diff_string)
|
||||||
|
|
||||||
@ -129,5 +162,5 @@ def main():
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
@ -18,13 +18,18 @@
|
|||||||
#
|
#
|
||||||
# Author: Xavier Claessens <xavier.claessens@collabora.com>
|
# Author: Xavier Claessens <xavier.claessens@collabora.com>
|
||||||
|
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
if len(sys.argv) < 3:
|
if len(sys.argv) < 3:
|
||||||
print('Usage: {} <output file> <input file 1> ...'.format(os.path.basename(sys.argv[0])))
|
print(
|
||||||
|
"Usage: {} <output file> <input file 1> ...".format(
|
||||||
|
os.path.basename(sys.argv[0])
|
||||||
|
)
|
||||||
|
)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
with open(sys.argv[1], 'w') as outfile:
|
with open(sys.argv[1], "w") as outfile:
|
||||||
for fname in sys.argv[2:]:
|
for fname in sys.argv[2:]:
|
||||||
with open(fname) as infile:
|
with open(fname) as infile:
|
||||||
for line in infile:
|
for line in infile:
|
||||||
|
@ -3,14 +3,14 @@
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
if len(sys.argv) < 4:
|
if len(sys.argv) < 4:
|
||||||
print('Usage: {0} <filename> <variable> <output>')
|
print("Usage: {0} <filename> <variable> <output>")
|
||||||
|
|
||||||
with open(sys.argv[1], 'rb') as f:
|
with open(sys.argv[1], "rb") as f:
|
||||||
in_data = f.read().decode('utf-8', 'backslashreplace')
|
in_data = f.read().decode("utf-8", "backslashreplace")
|
||||||
b = [r'\x{:02x}'.format(ord(c)) for c in in_data]
|
b = [r"\x{:02x}".format(ord(c)) for c in in_data]
|
||||||
|
|
||||||
out_data = "const char {0}[] = \"".format(sys.argv[2])
|
out_data = 'const char {0}[] = "'.format(sys.argv[2])
|
||||||
out_data += "".join(b) + "\";"
|
out_data += "".join(b) + '";'
|
||||||
|
|
||||||
with open(sys.argv[3], 'w') as f:
|
with open(sys.argv[3], "w") as f:
|
||||||
f.write(out_data)
|
f.write(out_data)
|
||||||
|
@ -21,7 +21,9 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
builddir = os.environ.get('UNINSTALLED_GLIB_BUILDDIR')
|
builddir = os.environ.get("UNINSTALLED_GLIB_BUILDDIR")
|
||||||
|
|
||||||
if builddir is not None:
|
if builddir is not None:
|
||||||
__path__.append(os.path.abspath(os.path.join(builddir, 'gio', 'gdbus-2.0', 'codegen')))
|
__path__.append(
|
||||||
|
os.path.abspath(os.path.join(builddir, "gio", "gdbus-2.0", "codegen"))
|
||||||
|
)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -19,17 +19,19 @@
|
|||||||
#
|
#
|
||||||
# Author: David Zeuthen <davidz@redhat.com>
|
# Author: David Zeuthen <davidz@redhat.com>
|
||||||
|
|
||||||
import sys
|
|
||||||
import re
|
import re
|
||||||
from os import path
|
from os import path
|
||||||
|
|
||||||
from . import config
|
|
||||||
from . import utils
|
from . import utils
|
||||||
from . import dbustypes
|
|
||||||
from . import parser
|
|
||||||
|
# Disable line length warnings as wrapping the Docbook templates would be hard
|
||||||
|
# flake8: noqa: E501
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
class DocbookCodeGenerator:
|
class DocbookCodeGenerator:
|
||||||
def __init__(self, ifaces):
|
def __init__(self, ifaces):
|
||||||
self.ifaces = ifaces
|
self.ifaces = ifaces
|
||||||
@ -57,23 +59,36 @@ class DocbookCodeGenerator:
|
|||||||
max_signature_len = max(len(a.signature), max_signature_len)
|
max_signature_len = max(len(a.signature), max_signature_len)
|
||||||
|
|
||||||
if in_synopsis:
|
if in_synopsis:
|
||||||
self.out.write('<link linkend="gdbus-method-%s.%s">%s</link>%*s ('
|
self.out.write(
|
||||||
%(utils.dots_to_hyphens(i.name), m.name, m.name, max_method_len - len(m.name), ''))
|
'<link linkend="gdbus-method-%s.%s">%s</link>%*s ('
|
||||||
|
% (
|
||||||
|
utils.dots_to_hyphens(i.name),
|
||||||
|
m.name,
|
||||||
|
m.name,
|
||||||
|
max_method_len - len(m.name),
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.out.write('%s%*s ('
|
self.out.write("%s%*s (" % (m.name, max_method_len - len(m.name), ""))
|
||||||
%(m.name, max_method_len - len(m.name), ''))
|
|
||||||
count = 0
|
count = 0
|
||||||
for a in m.in_args:
|
for a in m.in_args:
|
||||||
if (count > 0):
|
if count > 0:
|
||||||
self.out.write(',\n%*s'%(max_method_len + 2, ''))
|
self.out.write(",\n%*s" % (max_method_len + 2, ""))
|
||||||
self.out.write('IN %s%*s %s'%(a.signature, max_signature_len - len(a.signature), '', a.name))
|
self.out.write(
|
||||||
|
"IN %s%*s %s"
|
||||||
|
% (a.signature, max_signature_len - len(a.signature), "", a.name)
|
||||||
|
)
|
||||||
count = count + 1
|
count = count + 1
|
||||||
for a in m.out_args:
|
for a in m.out_args:
|
||||||
if (count > 0):
|
if count > 0:
|
||||||
self.out.write(',\n%*s'%(max_method_len + 2, ''))
|
self.out.write(",\n%*s" % (max_method_len + 2, ""))
|
||||||
self.out.write('OUT %s%*s %s'%(a.signature, max_signature_len - len(a.signature), '', a.name))
|
self.out.write(
|
||||||
|
"OUT %s%*s %s"
|
||||||
|
% (a.signature, max_signature_len - len(a.signature), "", a.name)
|
||||||
|
)
|
||||||
count = count + 1
|
count = count + 1
|
||||||
self.out.write(');\n')
|
self.out.write(");\n")
|
||||||
|
|
||||||
def print_signal_prototype(self, i, s, in_synopsis):
|
def print_signal_prototype(self, i, s, in_synopsis):
|
||||||
max_signal_len = 0
|
max_signal_len = 0
|
||||||
@ -93,18 +108,28 @@ class DocbookCodeGenerator:
|
|||||||
max_signature_len = max(len(a.signature), max_signature_len)
|
max_signature_len = max(len(a.signature), max_signature_len)
|
||||||
|
|
||||||
if in_synopsis:
|
if in_synopsis:
|
||||||
self.out.write('<link linkend="gdbus-signal-%s.%s">%s</link>%*s ('
|
self.out.write(
|
||||||
%(utils.dots_to_hyphens(i.name), s.name, s.name, max_signal_len - len(s.name), ''))
|
'<link linkend="gdbus-signal-%s.%s">%s</link>%*s ('
|
||||||
|
% (
|
||||||
|
utils.dots_to_hyphens(i.name),
|
||||||
|
s.name,
|
||||||
|
s.name,
|
||||||
|
max_signal_len - len(s.name),
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.out.write('%s%*s ('
|
self.out.write("%s%*s (" % (s.name, max_signal_len - len(s.name), ""))
|
||||||
%(s.name, max_signal_len - len(s.name), ''))
|
|
||||||
count = 0
|
count = 0
|
||||||
for a in s.args:
|
for a in s.args:
|
||||||
if (count > 0):
|
if count > 0:
|
||||||
self.out.write(',\n%*s'%(max_signal_len + 2, ''))
|
self.out.write(",\n%*s" % (max_signal_len + 2, ""))
|
||||||
self.out.write('%s%*s %s'%(a.signature, max_signature_len - len(a.signature), '', a.name))
|
self.out.write(
|
||||||
|
"%s%*s %s"
|
||||||
|
% (a.signature, max_signature_len - len(a.signature), "", a.name)
|
||||||
|
)
|
||||||
count = count + 1
|
count = count + 1
|
||||||
self.out.write(');\n')
|
self.out.write(");\n")
|
||||||
|
|
||||||
def print_property_prototype(self, i, p, in_synopsis):
|
def print_property_prototype(self, i, p, in_synopsis):
|
||||||
max_property_len = 0
|
max_property_len = 0
|
||||||
@ -122,109 +147,181 @@ class DocbookCodeGenerator:
|
|||||||
max_signature_len = max(len(p.signature), max_signature_len)
|
max_signature_len = max(len(p.signature), max_signature_len)
|
||||||
|
|
||||||
if in_synopsis:
|
if in_synopsis:
|
||||||
self.out.write('<link linkend="gdbus-property-%s.%s">%s</link>%*s'
|
self.out.write(
|
||||||
%(utils.dots_to_hyphens(i.name), p.name, p.name, max_property_len - len(p.name), ''))
|
'<link linkend="gdbus-property-%s.%s">%s</link>%*s'
|
||||||
|
% (
|
||||||
|
utils.dots_to_hyphens(i.name),
|
||||||
|
p.name,
|
||||||
|
p.name,
|
||||||
|
max_property_len - len(p.name),
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.out.write('%s%*s'
|
self.out.write("%s%*s" % (p.name, max_property_len - len(p.name), ""))
|
||||||
%(p.name, max_property_len - len(p.name), ''))
|
|
||||||
if p.readable and p.writable:
|
if p.readable and p.writable:
|
||||||
access = 'readwrite'
|
access = "readwrite"
|
||||||
elif p.readable:
|
elif p.readable:
|
||||||
access = 'readable '
|
access = "readable "
|
||||||
else:
|
else:
|
||||||
access = 'writable '
|
access = "writable "
|
||||||
self.out.write(' %s %s\n'%(access, p.signature))
|
self.out.write(" %s %s\n" % (access, p.signature))
|
||||||
|
|
||||||
|
|
||||||
def print_synopsis_methods(self, i):
|
def print_synopsis_methods(self, i):
|
||||||
self.out.write(' <refsynopsisdiv role="synopsis">\n'%())
|
self.out.write(' <refsynopsisdiv role="synopsis">\n')
|
||||||
self.out.write(' <title role="synopsis.title">Methods</title>\n'%())
|
self.out.write(' <title role="synopsis.title">Methods</title>\n')
|
||||||
self.out.write(' <synopsis>\n'%())
|
self.out.write(" <synopsis>\n")
|
||||||
for m in i.methods:
|
for m in i.methods:
|
||||||
self.print_method_prototype(i, m, in_synopsis=True)
|
self.print_method_prototype(i, m, in_synopsis=True)
|
||||||
self.out.write('</synopsis>\n'%())
|
self.out.write("</synopsis>\n")
|
||||||
self.out.write(' </refsynopsisdiv>\n'%())
|
self.out.write(" </refsynopsisdiv>\n")
|
||||||
|
|
||||||
def print_synopsis_signals(self, i):
|
def print_synopsis_signals(self, i):
|
||||||
self.out.write(' <refsect1 role="signal_proto">\n'%())
|
self.out.write(' <refsect1 role="signal_proto">\n')
|
||||||
self.out.write(' <title role="signal_proto.title">Signals</title>\n'%())
|
self.out.write(' <title role="signal_proto.title">Signals</title>\n')
|
||||||
self.out.write(' <synopsis>\n'%())
|
self.out.write(" <synopsis>\n")
|
||||||
for s in i.signals:
|
for s in i.signals:
|
||||||
self.print_signal_prototype(i, s, in_synopsis=True)
|
self.print_signal_prototype(i, s, in_synopsis=True)
|
||||||
self.out.write('</synopsis>\n'%())
|
self.out.write("</synopsis>\n")
|
||||||
self.out.write(' </refsect1>\n'%())
|
self.out.write(" </refsect1>\n")
|
||||||
|
|
||||||
def print_synopsis_properties(self, i):
|
def print_synopsis_properties(self, i):
|
||||||
self.out.write(' <refsect1 role="properties">\n'%())
|
self.out.write(' <refsect1 role="properties">\n')
|
||||||
self.out.write(' <title role="properties.title">Properties</title>\n'%())
|
self.out.write(' <title role="properties.title">Properties</title>\n')
|
||||||
self.out.write(' <synopsis>\n'%())
|
self.out.write(" <synopsis>\n")
|
||||||
for p in i.properties:
|
for p in i.properties:
|
||||||
self.print_property_prototype(i, p, in_synopsis=True)
|
self.print_property_prototype(i, p, in_synopsis=True)
|
||||||
self.out.write('</synopsis>\n'%())
|
self.out.write("</synopsis>\n")
|
||||||
self.out.write(' </refsect1>\n'%())
|
self.out.write(" </refsect1>\n")
|
||||||
|
|
||||||
def print_method(self, i, m):
|
def print_method(self, i, m):
|
||||||
self.out.write('<refsect2 role="method" id="gdbus-method-%s.%s">\n'%(utils.dots_to_hyphens(i.name), m.name))
|
self.out.write(
|
||||||
self.out.write(' <title>The %s() method</title>\n'%(m.name))
|
'<refsect2 role="method" id="gdbus-method-%s.%s">\n'
|
||||||
self.out.write(' <indexterm zone="gdbus-method-%s.%s"><primary sortas="%s.%s">%s.%s()</primary></indexterm>\n'%(utils.dots_to_hyphens(i.name), m.name, i.name_without_prefix, m.name, i.name, m.name))
|
% (utils.dots_to_hyphens(i.name), m.name)
|
||||||
self.out.write('<programlisting>\n')
|
)
|
||||||
|
self.out.write(" <title>The %s() method</title>\n" % (m.name))
|
||||||
|
self.out.write(
|
||||||
|
' <indexterm zone="gdbus-method-%s.%s"><primary sortas="%s.%s">%s.%s()</primary></indexterm>\n'
|
||||||
|
% (
|
||||||
|
utils.dots_to_hyphens(i.name),
|
||||||
|
m.name,
|
||||||
|
i.name_without_prefix,
|
||||||
|
m.name,
|
||||||
|
i.name,
|
||||||
|
m.name,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.out.write("<programlisting>\n")
|
||||||
self.print_method_prototype(i, m, in_synopsis=False)
|
self.print_method_prototype(i, m, in_synopsis=False)
|
||||||
self.out.write('</programlisting>\n')
|
self.out.write("</programlisting>\n")
|
||||||
self.out.write('%s\n'%(self.expand_paras(m.doc_string, True)))
|
self.out.write("%s\n" % (self.expand_paras(m.doc_string, True)))
|
||||||
if m.in_args or m.out_args:
|
if m.in_args or m.out_args:
|
||||||
self.out.write('<variablelist role="params">\n')
|
self.out.write('<variablelist role="params">\n')
|
||||||
for a in m.in_args:
|
for a in m.in_args:
|
||||||
self.out.write('<varlistentry>\n'%())
|
self.out.write("<varlistentry>\n")
|
||||||
self.out.write(' <term><literal>IN %s <parameter>%s</parameter></literal>:</term>\n'%(a.signature, a.name))
|
self.out.write(
|
||||||
self.out.write(' <listitem>%s</listitem>\n'%(self.expand_paras(a.doc_string, True)))
|
" <term><literal>IN %s <parameter>%s</parameter></literal>:</term>\n"
|
||||||
self.out.write('</varlistentry>\n'%())
|
% (a.signature, a.name)
|
||||||
|
)
|
||||||
|
self.out.write(
|
||||||
|
" <listitem>%s</listitem>\n"
|
||||||
|
% (self.expand_paras(a.doc_string, True))
|
||||||
|
)
|
||||||
|
self.out.write("</varlistentry>\n")
|
||||||
for a in m.out_args:
|
for a in m.out_args:
|
||||||
self.out.write('<varlistentry>\n'%())
|
self.out.write("<varlistentry>\n")
|
||||||
self.out.write(' <term><literal>OUT %s <parameter>%s</parameter></literal>:</term>\n'%(a.signature, a.name))
|
self.out.write(
|
||||||
self.out.write(' <listitem>%s</listitem>\n'%(self.expand_paras(a.doc_string, True)))
|
" <term><literal>OUT %s <parameter>%s</parameter></literal>:</term>\n"
|
||||||
self.out.write('</varlistentry>\n'%())
|
% (a.signature, a.name)
|
||||||
self.out.write('</variablelist>\n')
|
)
|
||||||
|
self.out.write(
|
||||||
|
" <listitem>%s</listitem>\n"
|
||||||
|
% (self.expand_paras(a.doc_string, True))
|
||||||
|
)
|
||||||
|
self.out.write("</varlistentry>\n")
|
||||||
|
self.out.write("</variablelist>\n")
|
||||||
if len(m.since) > 0:
|
if len(m.since) > 0:
|
||||||
self.out.write('<para role="since">Since %s</para>\n' % (m.since))
|
self.out.write('<para role="since">Since %s</para>\n' % (m.since))
|
||||||
if m.deprecated:
|
if m.deprecated:
|
||||||
self.out.write('<warning><para>The %s() method is deprecated.</para></warning>'%(m.name))
|
self.out.write(
|
||||||
self.out.write('</refsect2>\n')
|
"<warning><para>The %s() method is deprecated.</para></warning>"
|
||||||
|
% (m.name)
|
||||||
|
)
|
||||||
|
self.out.write("</refsect2>\n")
|
||||||
|
|
||||||
def print_signal(self, i, s):
|
def print_signal(self, i, s):
|
||||||
self.out.write('<refsect2 role="signal" id="gdbus-signal-%s.%s">\n'%(utils.dots_to_hyphens(i.name), s.name))
|
self.out.write(
|
||||||
|
'<refsect2 role="signal" id="gdbus-signal-%s.%s">\n'
|
||||||
|
% (utils.dots_to_hyphens(i.name), s.name)
|
||||||
|
)
|
||||||
self.out.write(' <title>The "%s" signal</title>\n' % (s.name))
|
self.out.write(' <title>The "%s" signal</title>\n' % (s.name))
|
||||||
self.out.write(' <indexterm zone="gdbus-signal-%s.%s"><primary sortas="%s::%s">%s::%s</primary></indexterm>\n'%(utils.dots_to_hyphens(i.name), s.name, i.name_without_prefix, s.name, i.name, s.name))
|
self.out.write(
|
||||||
self.out.write('<programlisting>\n')
|
' <indexterm zone="gdbus-signal-%s.%s"><primary sortas="%s::%s">%s::%s</primary></indexterm>\n'
|
||||||
|
% (
|
||||||
|
utils.dots_to_hyphens(i.name),
|
||||||
|
s.name,
|
||||||
|
i.name_without_prefix,
|
||||||
|
s.name,
|
||||||
|
i.name,
|
||||||
|
s.name,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.out.write("<programlisting>\n")
|
||||||
self.print_signal_prototype(i, s, in_synopsis=False)
|
self.print_signal_prototype(i, s, in_synopsis=False)
|
||||||
self.out.write('</programlisting>\n')
|
self.out.write("</programlisting>\n")
|
||||||
self.out.write('%s\n'%(self.expand_paras(s.doc_string, True)))
|
self.out.write("%s\n" % (self.expand_paras(s.doc_string, True)))
|
||||||
if s.args:
|
if s.args:
|
||||||
self.out.write('<variablelist role="params">\n')
|
self.out.write('<variablelist role="params">\n')
|
||||||
for a in s.args:
|
for a in s.args:
|
||||||
self.out.write('<varlistentry>\n'%())
|
self.out.write("<varlistentry>\n")
|
||||||
self.out.write(' <term><literal>%s <parameter>%s</parameter></literal>:</term>\n'%(a.signature, a.name))
|
self.out.write(
|
||||||
self.out.write(' <listitem>%s</listitem>\n'%(self.expand_paras(a.doc_string, True)))
|
" <term><literal>%s <parameter>%s</parameter></literal>:</term>\n"
|
||||||
self.out.write('</varlistentry>\n'%())
|
% (a.signature, a.name)
|
||||||
self.out.write('</variablelist>\n')
|
)
|
||||||
|
self.out.write(
|
||||||
|
" <listitem>%s</listitem>\n"
|
||||||
|
% (self.expand_paras(a.doc_string, True))
|
||||||
|
)
|
||||||
|
self.out.write("</varlistentry>\n")
|
||||||
|
self.out.write("</variablelist>\n")
|
||||||
if len(s.since) > 0:
|
if len(s.since) > 0:
|
||||||
self.out.write('<para role="since">Since %s</para>\n' % (s.since))
|
self.out.write('<para role="since">Since %s</para>\n' % (s.since))
|
||||||
if s.deprecated:
|
if s.deprecated:
|
||||||
self.out.write('<warning><para>The "%s" signal is deprecated.</para></warning>'%(s.name))
|
self.out.write(
|
||||||
self.out.write('</refsect2>\n')
|
'<warning><para>The "%s" signal is deprecated.</para></warning>'
|
||||||
|
% (s.name)
|
||||||
|
)
|
||||||
|
self.out.write("</refsect2>\n")
|
||||||
|
|
||||||
def print_property(self, i, p):
|
def print_property(self, i, p):
|
||||||
self.out.write('<refsect2 role="property" id="gdbus-property-%s.%s">\n'%(utils.dots_to_hyphens(i.name), p.name))
|
self.out.write(
|
||||||
|
'<refsect2 role="property" id="gdbus-property-%s.%s">\n'
|
||||||
|
% (utils.dots_to_hyphens(i.name), p.name)
|
||||||
|
)
|
||||||
self.out.write(' <title>The "%s" property</title>\n' % (p.name))
|
self.out.write(' <title>The "%s" property</title>\n' % (p.name))
|
||||||
self.out.write(' <indexterm zone="gdbus-property-%s.%s"><primary sortas="%s:%s">%s:%s</primary></indexterm>\n'%(utils.dots_to_hyphens(i.name), p.name, i.name_without_prefix, p.name, i.name, p.name))
|
self.out.write(
|
||||||
self.out.write('<programlisting>\n')
|
' <indexterm zone="gdbus-property-%s.%s"><primary sortas="%s:%s">%s:%s</primary></indexterm>\n'
|
||||||
|
% (
|
||||||
|
utils.dots_to_hyphens(i.name),
|
||||||
|
p.name,
|
||||||
|
i.name_without_prefix,
|
||||||
|
p.name,
|
||||||
|
i.name,
|
||||||
|
p.name,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.out.write("<programlisting>\n")
|
||||||
self.print_property_prototype(i, p, in_synopsis=False)
|
self.print_property_prototype(i, p, in_synopsis=False)
|
||||||
self.out.write('</programlisting>\n')
|
self.out.write("</programlisting>\n")
|
||||||
self.out.write('%s\n'%(self.expand_paras(p.doc_string, True)))
|
self.out.write("%s\n" % (self.expand_paras(p.doc_string, True)))
|
||||||
if len(p.since) > 0:
|
if len(p.since) > 0:
|
||||||
self.out.write('<para role="since">Since %s</para>\n' % (p.since))
|
self.out.write('<para role="since">Since %s</para>\n' % (p.since))
|
||||||
if p.deprecated:
|
if p.deprecated:
|
||||||
self.out.write('<warning><para>The "%s" property is deprecated.</para></warning>'%(p.name))
|
self.out.write(
|
||||||
self.out.write('</refsect2>\n')
|
'<warning><para>The "%s" property is deprecated.</para></warning>'
|
||||||
|
% (p.name)
|
||||||
|
)
|
||||||
|
self.out.write("</refsect2>\n")
|
||||||
|
|
||||||
def expand(self, s, expandParamsAndConstants):
|
def expand(self, s, expandParamsAndConstants):
|
||||||
for key in self.expand_member_dict_keys:
|
for key in self.expand_member_dict_keys:
|
||||||
@ -233,9 +330,17 @@ class DocbookCodeGenerator:
|
|||||||
s = s.replace(key, self.expand_iface_dict[key])
|
s = s.replace(key, self.expand_iface_dict[key])
|
||||||
if expandParamsAndConstants:
|
if expandParamsAndConstants:
|
||||||
# replace @foo with <parameter>foo</parameter>
|
# replace @foo with <parameter>foo</parameter>
|
||||||
s = re.sub('@[a-zA-Z0-9_]*', lambda m: '<parameter>' + m.group(0)[1:] + '</parameter>', s)
|
s = re.sub(
|
||||||
|
"@[a-zA-Z0-9_]*",
|
||||||
|
lambda m: "<parameter>" + m.group(0)[1:] + "</parameter>",
|
||||||
|
s,
|
||||||
|
)
|
||||||
# replace e.g. %TRUE with <constant>TRUE</constant>
|
# replace e.g. %TRUE with <constant>TRUE</constant>
|
||||||
s = re.sub('%[a-zA-Z0-9_]*', lambda m: '<constant>' + m.group(0)[1:] + '</constant>', s)
|
s = re.sub(
|
||||||
|
"%[a-zA-Z0-9_]*",
|
||||||
|
lambda m: "<constant>" + m.group(0)[1:] + "</constant>",
|
||||||
|
s,
|
||||||
|
)
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def expand_paras(self, s, expandParamsAndConstants):
|
def expand_paras(self, s, expandParamsAndConstants):
|
||||||
@ -248,44 +353,73 @@ class DocbookCodeGenerator:
|
|||||||
self.expand_member_dict = {}
|
self.expand_member_dict = {}
|
||||||
self.expand_iface_dict = {}
|
self.expand_iface_dict = {}
|
||||||
for i in self.ifaces:
|
for i in self.ifaces:
|
||||||
key = '#%s'%(i.name)
|
key = "#%s" % (i.name)
|
||||||
value = '<link linkend="gdbus-interface-%s.top_of_page">%s</link>'%(utils.dots_to_hyphens(i.name), i.name)
|
value = '<link linkend="gdbus-interface-%s.top_of_page">%s</link>' % (
|
||||||
|
utils.dots_to_hyphens(i.name),
|
||||||
|
i.name,
|
||||||
|
)
|
||||||
self.expand_iface_dict[key] = value
|
self.expand_iface_dict[key] = value
|
||||||
for m in i.methods:
|
for m in i.methods:
|
||||||
key = '%s.%s()'%(i.name, m.name)
|
key = "%s.%s()" % (i.name, m.name)
|
||||||
value = '<link linkend="gdbus-method-%s.%s">%s()</link>'%(utils.dots_to_hyphens(i.name), m.name, m.name)
|
value = '<link linkend="gdbus-method-%s.%s">%s()</link>' % (
|
||||||
|
utils.dots_to_hyphens(i.name),
|
||||||
|
m.name,
|
||||||
|
m.name,
|
||||||
|
)
|
||||||
self.expand_member_dict[key] = value
|
self.expand_member_dict[key] = value
|
||||||
for s in i.signals:
|
for s in i.signals:
|
||||||
key = '#%s::%s'%(i.name, s.name)
|
key = "#%s::%s" % (i.name, s.name)
|
||||||
value = '<link linkend="gdbus-signal-%s.%s">"%s"</link>'%(utils.dots_to_hyphens(i.name), s.name, s.name)
|
value = '<link linkend="gdbus-signal-%s.%s">"%s"</link>' % (
|
||||||
|
utils.dots_to_hyphens(i.name),
|
||||||
|
s.name,
|
||||||
|
s.name,
|
||||||
|
)
|
||||||
self.expand_member_dict[key] = value
|
self.expand_member_dict[key] = value
|
||||||
for p in i.properties:
|
for p in i.properties:
|
||||||
key = '#%s:%s'%(i.name, p.name)
|
key = "#%s:%s" % (i.name, p.name)
|
||||||
value = '<link linkend="gdbus-property-%s.%s">"%s"</link>'%(utils.dots_to_hyphens(i.name), p.name, p.name)
|
value = '<link linkend="gdbus-property-%s.%s">"%s"</link>' % (
|
||||||
|
utils.dots_to_hyphens(i.name),
|
||||||
|
p.name,
|
||||||
|
p.name,
|
||||||
|
)
|
||||||
self.expand_member_dict[key] = value
|
self.expand_member_dict[key] = value
|
||||||
# Make sure to expand the keys in reverse order so e.g. #org.foo.Iface:MediaCompat
|
# Make sure to expand the keys in reverse order so e.g. #org.foo.Iface:MediaCompat
|
||||||
# is evaluated before #org.foo.Iface:Media ...
|
# is evaluated before #org.foo.Iface:Media ...
|
||||||
self.expand_member_dict_keys = sorted(self.expand_member_dict.keys(), reverse=True)
|
self.expand_member_dict_keys = sorted(
|
||||||
self.expand_iface_dict_keys = sorted(self.expand_iface_dict.keys(), reverse=True)
|
self.expand_member_dict.keys(), reverse=True
|
||||||
|
)
|
||||||
|
self.expand_iface_dict_keys = sorted(
|
||||||
|
self.expand_iface_dict.keys(), reverse=True
|
||||||
|
)
|
||||||
|
|
||||||
def generate(self, docbook, outdir):
|
def generate(self, docbook, outdir):
|
||||||
for i in self.ifaces:
|
for i in self.ifaces:
|
||||||
self.out = open(path.join(outdir, '%s-%s.xml'%(docbook, i.name)), 'w')
|
self.out = open(path.join(outdir, "%s-%s.xml" % (docbook, i.name)), "w")
|
||||||
self.out.write(''%())
|
self.out.write("")
|
||||||
self.out.write('<?xml version="1.0" encoding="utf-8"?>\n'%())
|
self.out.write('<?xml version="1.0" encoding="utf-8"?>\n')
|
||||||
self.out.write('<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"\n'%())
|
self.out.write(
|
||||||
self.out.write(' "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [\n'%())
|
'<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"\n'
|
||||||
self.out.write(']>\n'%())
|
)
|
||||||
|
self.out.write(
|
||||||
|
' "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [\n'
|
||||||
|
)
|
||||||
|
self.out.write("]>\n")
|
||||||
self.out.write('<refentry id="gdbus-%s">\n' % (i.name))
|
self.out.write('<refentry id="gdbus-%s">\n' % (i.name))
|
||||||
self.out.write(' <refmeta>'%())
|
self.out.write(" <refmeta>")
|
||||||
self.out.write(' <refentrytitle role="top_of_page" id="gdbus-interface-%s.top_of_page">%s</refentrytitle>\n'%(utils.dots_to_hyphens(i.name), i.name))
|
self.out.write(
|
||||||
self.out.write(' <indexterm zone="gdbus-interface-%s.top_of_page"><primary sortas="%s">%s</primary></indexterm>\n'%(utils.dots_to_hyphens(i.name), i.name_without_prefix, i.name))
|
' <refentrytitle role="top_of_page" id="gdbus-interface-%s.top_of_page">%s</refentrytitle>\n'
|
||||||
self.out.write(' </refmeta>'%())
|
% (utils.dots_to_hyphens(i.name), i.name)
|
||||||
|
)
|
||||||
|
self.out.write(
|
||||||
|
' <indexterm zone="gdbus-interface-%s.top_of_page"><primary sortas="%s">%s</primary></indexterm>\n'
|
||||||
|
% (utils.dots_to_hyphens(i.name), i.name_without_prefix, i.name)
|
||||||
|
)
|
||||||
|
self.out.write(" </refmeta>")
|
||||||
|
|
||||||
self.out.write(' <refnamediv>'%())
|
self.out.write(" <refnamediv>")
|
||||||
self.out.write(' <refname>%s</refname>'%(i.name))
|
self.out.write(" <refname>%s</refname>" % (i.name))
|
||||||
self.out.write(' <refpurpose>%s</refpurpose>'%(i.doc_string_brief))
|
self.out.write(" <refpurpose>%s</refpurpose>" % (i.doc_string_brief))
|
||||||
self.out.write(' </refnamediv>'%())
|
self.out.write(" </refnamediv>")
|
||||||
|
|
||||||
if len(i.methods) > 0:
|
if len(i.methods) > 0:
|
||||||
self.print_synopsis_methods(i)
|
self.print_synopsis_methods(i)
|
||||||
@ -294,36 +428,49 @@ class DocbookCodeGenerator:
|
|||||||
if len(i.properties) > 0:
|
if len(i.properties) > 0:
|
||||||
self.print_synopsis_properties(i)
|
self.print_synopsis_properties(i)
|
||||||
|
|
||||||
self.out.write('<refsect1 role="desc" id="gdbus-interface-%s">\n'%(utils.dots_to_hyphens(i.name)))
|
self.out.write(
|
||||||
self.out.write(' <title role="desc.title">Description</title>\n'%())
|
'<refsect1 role="desc" id="gdbus-interface-%s">\n'
|
||||||
self.out.write(' %s\n'%(self.expand_paras(i.doc_string, True)))
|
% (utils.dots_to_hyphens(i.name))
|
||||||
|
)
|
||||||
|
self.out.write(' <title role="desc.title">Description</title>\n')
|
||||||
|
self.out.write(" %s\n" % (self.expand_paras(i.doc_string, True)))
|
||||||
if len(i.since) > 0:
|
if len(i.since) > 0:
|
||||||
self.out.write(' <para role="since">Since %s</para>\n' % (i.since))
|
self.out.write(' <para role="since">Since %s</para>\n' % (i.since))
|
||||||
if i.deprecated:
|
if i.deprecated:
|
||||||
self.out.write('<warning><para>The %s interface is deprecated.</para></warning>'%(i.name))
|
self.out.write(
|
||||||
self.out.write('</refsect1>\n'%())
|
"<warning><para>The %s interface is deprecated.</para></warning>"
|
||||||
|
% (i.name)
|
||||||
|
)
|
||||||
|
self.out.write("</refsect1>\n")
|
||||||
|
|
||||||
if len(i.methods) > 0:
|
if len(i.methods) > 0:
|
||||||
self.out.write('<refsect1 role="details" id="gdbus-methods-%s">\n'%(i.name))
|
self.out.write(
|
||||||
self.out.write(' <title role="details.title">Method Details</title>\n'%())
|
'<refsect1 role="details" id="gdbus-methods-%s">\n' % (i.name)
|
||||||
|
)
|
||||||
|
self.out.write(' <title role="details.title">Method Details</title>\n')
|
||||||
for m in i.methods:
|
for m in i.methods:
|
||||||
self.print_method(i, m)
|
self.print_method(i, m)
|
||||||
self.out.write('</refsect1>\n'%())
|
self.out.write("</refsect1>\n")
|
||||||
|
|
||||||
if len(i.signals) > 0:
|
if len(i.signals) > 0:
|
||||||
self.out.write('<refsect1 role="details" id="gdbus-signals-%s">\n'%(i.name))
|
self.out.write(
|
||||||
self.out.write(' <title role="details.title">Signal Details</title>\n'%())
|
'<refsect1 role="details" id="gdbus-signals-%s">\n' % (i.name)
|
||||||
|
)
|
||||||
|
self.out.write(' <title role="details.title">Signal Details</title>\n')
|
||||||
for s in i.signals:
|
for s in i.signals:
|
||||||
self.print_signal(i, s)
|
self.print_signal(i, s)
|
||||||
self.out.write('</refsect1>\n'%())
|
self.out.write("</refsect1>\n")
|
||||||
|
|
||||||
if len(i.properties) > 0:
|
if len(i.properties) > 0:
|
||||||
self.out.write('<refsect1 role="details" id="gdbus-properties-%s">\n'%(i.name))
|
self.out.write(
|
||||||
self.out.write(' <title role="details.title">Property Details</title>\n'%())
|
'<refsect1 role="details" id="gdbus-properties-%s">\n' % (i.name)
|
||||||
|
)
|
||||||
|
self.out.write(
|
||||||
|
' <title role="details.title">Property Details</title>\n'
|
||||||
|
)
|
||||||
for s in i.properties:
|
for s in i.properties:
|
||||||
self.print_property(i, s)
|
self.print_property(i, s)
|
||||||
self.out.write('</refsect1>\n'%())
|
self.out.write("</refsect1>\n")
|
||||||
|
|
||||||
self.out.write('</refentry>\n')
|
|
||||||
self.out.write('\n')
|
|
||||||
|
|
||||||
|
self.out.write("</refentry>\n")
|
||||||
|
self.out.write("\n")
|
||||||
|
@ -32,30 +32,35 @@ from . import codegen
|
|||||||
from . import codegen_docbook
|
from . import codegen_docbook
|
||||||
from .utils import print_error, print_warning
|
from .utils import print_error, print_warning
|
||||||
|
|
||||||
|
|
||||||
def find_arg(arg_list, arg_name):
|
def find_arg(arg_list, arg_name):
|
||||||
for a in arg_list:
|
for a in arg_list:
|
||||||
if a.name == arg_name:
|
if a.name == arg_name:
|
||||||
return a
|
return a
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def find_method(iface, method):
|
def find_method(iface, method):
|
||||||
for m in iface.methods:
|
for m in iface.methods:
|
||||||
if m.name == method:
|
if m.name == method:
|
||||||
return m
|
return m
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def find_signal(iface, signal):
|
def find_signal(iface, signal):
|
||||||
for m in iface.signals:
|
for m in iface.signals:
|
||||||
if m.name == signal:
|
if m.name == signal:
|
||||||
return m
|
return m
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def find_prop(iface, prop):
|
def find_prop(iface, prop):
|
||||||
for m in iface.properties:
|
for m in iface.properties:
|
||||||
if m.name == prop:
|
if m.name == prop:
|
||||||
return m
|
return m
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def apply_annotation(iface_list, iface, method, signal, prop, arg, key, value):
|
def apply_annotation(iface_list, iface, method, signal, prop, arg, key, value):
|
||||||
iface_obj = None
|
iface_obj = None
|
||||||
for i in iface_list:
|
for i in iface_list:
|
||||||
@ -74,10 +79,14 @@ def apply_annotation(iface_list, iface, method, signal, prop, arg, key, value):
|
|||||||
print_error('No method "{}" on interface "{}"'.format(method, iface))
|
print_error('No method "{}" on interface "{}"'.format(method, iface))
|
||||||
if arg:
|
if arg:
|
||||||
arg_obj = find_arg(method_obj.in_args, arg)
|
arg_obj = find_arg(method_obj.in_args, arg)
|
||||||
if (arg_obj is None):
|
if arg_obj is None:
|
||||||
arg_obj = find_arg(method_obj.out_args, arg)
|
arg_obj = find_arg(method_obj.out_args, arg)
|
||||||
if (arg_obj is None):
|
if arg_obj is None:
|
||||||
print_error('No arg "{}" on method "{}" on interface "{}"'.format(arg, method, iface))
|
print_error(
|
||||||
|
'No arg "{}" on method "{}" on interface "{}"'.format(
|
||||||
|
arg, method, iface
|
||||||
|
)
|
||||||
|
)
|
||||||
target_obj = arg_obj
|
target_obj = arg_obj
|
||||||
else:
|
else:
|
||||||
target_obj = method_obj
|
target_obj = method_obj
|
||||||
@ -87,8 +96,12 @@ def apply_annotation(iface_list, iface, method, signal, prop, arg, key, value):
|
|||||||
print_error('No signal "{}" on interface "{}"'.format(signal, iface))
|
print_error('No signal "{}" on interface "{}"'.format(signal, iface))
|
||||||
if arg:
|
if arg:
|
||||||
arg_obj = find_arg(signal_obj.args, arg)
|
arg_obj = find_arg(signal_obj.args, arg)
|
||||||
if (arg_obj is None):
|
if arg_obj is None:
|
||||||
print_error('No arg "{}" on signal "{}" on interface "{}"'.format(arg, signal, iface))
|
print_error(
|
||||||
|
'No arg "{}" on signal "{}" on interface "{}"'.format(
|
||||||
|
arg, signal, iface
|
||||||
|
)
|
||||||
|
)
|
||||||
target_obj = arg_obj
|
target_obj = arg_obj
|
||||||
else:
|
else:
|
||||||
target_obj = signal_obj
|
target_obj = signal_obj
|
||||||
@ -105,198 +118,294 @@ def apply_annotation(iface_list, iface, method, signal, prop, arg, key, value):
|
|||||||
def apply_annotations(iface_list, annotation_list):
|
def apply_annotations(iface_list, annotation_list):
|
||||||
# apply annotations given on the command line
|
# apply annotations given on the command line
|
||||||
for (what, key, value) in annotation_list:
|
for (what, key, value) in annotation_list:
|
||||||
pos = what.find('::')
|
pos = what.find("::")
|
||||||
if pos != -1:
|
if pos != -1:
|
||||||
# signal
|
# signal
|
||||||
iface = what[0:pos];
|
iface = what[0:pos]
|
||||||
signal = what[pos + 2 :]
|
signal = what[pos + 2 :]
|
||||||
pos = signal.find('[')
|
pos = signal.find("[")
|
||||||
if pos != -1:
|
if pos != -1:
|
||||||
arg = signal[pos + 1 :]
|
arg = signal[pos + 1 :]
|
||||||
signal = signal[0:pos]
|
signal = signal[0:pos]
|
||||||
pos = arg.find(']')
|
pos = arg.find("]")
|
||||||
arg = arg[0:pos]
|
arg = arg[0:pos]
|
||||||
apply_annotation(iface_list, iface, None, signal, None, arg, key, value)
|
apply_annotation(iface_list, iface, None, signal, None, arg, key, value)
|
||||||
else:
|
else:
|
||||||
apply_annotation(iface_list, iface, None, signal, None, None, key, value)
|
apply_annotation(
|
||||||
|
iface_list, iface, None, signal, None, None, key, value
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
pos = what.find(':')
|
pos = what.find(":")
|
||||||
if pos != -1:
|
if pos != -1:
|
||||||
# property
|
# property
|
||||||
iface = what[0:pos];
|
iface = what[0:pos]
|
||||||
prop = what[pos + 1 :]
|
prop = what[pos + 1 :]
|
||||||
apply_annotation(iface_list, iface, None, None, prop, None, key, value)
|
apply_annotation(iface_list, iface, None, None, prop, None, key, value)
|
||||||
else:
|
else:
|
||||||
pos = what.find('()')
|
pos = what.find("()")
|
||||||
if pos != -1:
|
if pos != -1:
|
||||||
# method
|
# method
|
||||||
combined = what[0:pos]
|
combined = what[0:pos]
|
||||||
pos = combined.rfind('.')
|
pos = combined.rfind(".")
|
||||||
iface = combined[0:pos]
|
iface = combined[0:pos]
|
||||||
method = combined[pos + 1 :]
|
method = combined[pos + 1 :]
|
||||||
pos = what.find('[')
|
pos = what.find("[")
|
||||||
if pos != -1:
|
if pos != -1:
|
||||||
arg = what[pos + 1 :]
|
arg = what[pos + 1 :]
|
||||||
pos = arg.find(']')
|
pos = arg.find("]")
|
||||||
arg = arg[0:pos]
|
arg = arg[0:pos]
|
||||||
apply_annotation(iface_list, iface, method, None, None, arg, key, value)
|
apply_annotation(
|
||||||
|
iface_list, iface, method, None, None, arg, key, value
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
apply_annotation(iface_list, iface, method, None, None, None, key, value)
|
apply_annotation(
|
||||||
|
iface_list, iface, method, None, None, None, key, value
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
# must be an interface
|
# must be an interface
|
||||||
iface = what
|
iface = what
|
||||||
apply_annotation(iface_list, iface, None, None, None, None, key, value)
|
apply_annotation(
|
||||||
|
iface_list, iface, None, None, None, None, key, value
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def codegen_main():
|
def codegen_main():
|
||||||
arg_parser = argparse.ArgumentParser(description='D-Bus code and documentation generator')
|
arg_parser = argparse.ArgumentParser(
|
||||||
arg_parser.add_argument('files', metavar='FILE', nargs='+',
|
description="D-Bus code and documentation generator"
|
||||||
help='D-Bus introspection XML file')
|
)
|
||||||
arg_parser.add_argument('--xml-files', metavar='FILE', action='append', default=[],
|
arg_parser.add_argument(
|
||||||
help=argparse.SUPPRESS)
|
"files", metavar="FILE", nargs="+", help="D-Bus introspection XML file"
|
||||||
arg_parser.add_argument('--interface-prefix', metavar='PREFIX', default='',
|
)
|
||||||
help='String to strip from D-Bus interface names for code and docs')
|
arg_parser.add_argument(
|
||||||
arg_parser.add_argument('--c-namespace', metavar='NAMESPACE', default='',
|
"--xml-files",
|
||||||
help='The namespace to use for generated C code')
|
metavar="FILE",
|
||||||
arg_parser.add_argument('--c-generate-object-manager', action='store_true',
|
action="append",
|
||||||
help='Generate a GDBusObjectManagerClient subclass when generating C code')
|
default=[],
|
||||||
arg_parser.add_argument('--c-generate-autocleanup', choices=['none', 'objects', 'all'], default='objects',
|
help=argparse.SUPPRESS,
|
||||||
help='Generate autocleanup support')
|
)
|
||||||
arg_parser.add_argument('--generate-docbook', metavar='OUTFILES',
|
arg_parser.add_argument(
|
||||||
help='Generate Docbook in OUTFILES-org.Project.IFace.xml')
|
"--interface-prefix",
|
||||||
arg_parser.add_argument('--pragma-once', action='store_true',
|
metavar="PREFIX",
|
||||||
help='Use "pragma once" as the inclusion guard')
|
default="",
|
||||||
arg_parser.add_argument('--annotate', nargs=3, action='append', metavar='WHAT KEY VALUE',
|
help="String to strip from D-Bus interface names for code and docs",
|
||||||
help='Add annotation (may be used several times)')
|
)
|
||||||
arg_parser.add_argument('--glib-min-required', metavar='VERSION',
|
arg_parser.add_argument(
|
||||||
help='Minimum version of GLib to be supported by the outputted code (default: 2.30)')
|
"--c-namespace",
|
||||||
arg_parser.add_argument('--glib-max-allowed', metavar='VERSION',
|
metavar="NAMESPACE",
|
||||||
help='Maximum version of GLib to be used by the outputted code (default: current GLib version)')
|
default="",
|
||||||
arg_parser.add_argument('--symbol-decorator',
|
help="The namespace to use for generated C code",
|
||||||
help='Macro used to decorate a symbol in the outputted header, possibly to export symbols')
|
)
|
||||||
arg_parser.add_argument('--symbol-decorator-header',
|
arg_parser.add_argument(
|
||||||
help='Additional header required for decorator specified by --symbol-decorator')
|
"--c-generate-object-manager",
|
||||||
arg_parser.add_argument('--symbol-decorator-define',
|
action="store_true",
|
||||||
help='Additional define required for decorator specified by --symbol-decorator')
|
help="Generate a GDBusObjectManagerClient subclass when generating C code",
|
||||||
|
)
|
||||||
|
arg_parser.add_argument(
|
||||||
|
"--c-generate-autocleanup",
|
||||||
|
choices=["none", "objects", "all"],
|
||||||
|
default="objects",
|
||||||
|
help="Generate autocleanup support",
|
||||||
|
)
|
||||||
|
arg_parser.add_argument(
|
||||||
|
"--generate-docbook",
|
||||||
|
metavar="OUTFILES",
|
||||||
|
help="Generate Docbook in OUTFILES-org.Project.IFace.xml",
|
||||||
|
)
|
||||||
|
arg_parser.add_argument(
|
||||||
|
"--pragma-once",
|
||||||
|
action="store_true",
|
||||||
|
help='Use "pragma once" as the inclusion guard',
|
||||||
|
)
|
||||||
|
arg_parser.add_argument(
|
||||||
|
"--annotate",
|
||||||
|
nargs=3,
|
||||||
|
action="append",
|
||||||
|
metavar="WHAT KEY VALUE",
|
||||||
|
help="Add annotation (may be used several times)",
|
||||||
|
)
|
||||||
|
arg_parser.add_argument(
|
||||||
|
"--glib-min-required",
|
||||||
|
metavar="VERSION",
|
||||||
|
help="Minimum version of GLib to be supported by the outputted code "
|
||||||
|
"(default: 2.30)",
|
||||||
|
)
|
||||||
|
arg_parser.add_argument(
|
||||||
|
"--glib-max-allowed",
|
||||||
|
metavar="VERSION",
|
||||||
|
help="Maximum version of GLib to be used by the outputted code "
|
||||||
|
"(default: current GLib version)",
|
||||||
|
)
|
||||||
|
arg_parser.add_argument(
|
||||||
|
"--symbol-decorator",
|
||||||
|
help="Macro used to decorate a symbol in the outputted header, "
|
||||||
|
"possibly to export symbols",
|
||||||
|
)
|
||||||
|
arg_parser.add_argument(
|
||||||
|
"--symbol-decorator-header",
|
||||||
|
help="Additional header required for decorator specified by "
|
||||||
|
"--symbol-decorator",
|
||||||
|
)
|
||||||
|
arg_parser.add_argument(
|
||||||
|
"--symbol-decorator-define",
|
||||||
|
help="Additional define required for decorator specified by "
|
||||||
|
"--symbol-decorator",
|
||||||
|
)
|
||||||
|
|
||||||
group = arg_parser.add_mutually_exclusive_group()
|
group = arg_parser.add_mutually_exclusive_group()
|
||||||
group.add_argument('--generate-c-code', metavar='OUTFILES',
|
group.add_argument(
|
||||||
help='Generate C code in OUTFILES.[ch]')
|
"--generate-c-code", metavar="OUTFILES", help="Generate C code in OUTFILES.[ch]"
|
||||||
group.add_argument('--header', action='store_true',
|
)
|
||||||
help='Generate C headers')
|
group.add_argument("--header", action="store_true", help="Generate C headers")
|
||||||
group.add_argument('--body', action='store_true',
|
group.add_argument("--body", action="store_true", help="Generate C code")
|
||||||
help='Generate C code')
|
group.add_argument(
|
||||||
group.add_argument('--interface-info-header', action='store_true',
|
"--interface-info-header",
|
||||||
help='Generate GDBusInterfaceInfo C header')
|
action="store_true",
|
||||||
group.add_argument('--interface-info-body', action='store_true',
|
help="Generate GDBusInterfaceInfo C header",
|
||||||
help='Generate GDBusInterfaceInfo C code')
|
)
|
||||||
|
group.add_argument(
|
||||||
|
"--interface-info-body",
|
||||||
|
action="store_true",
|
||||||
|
help="Generate GDBusInterfaceInfo C code",
|
||||||
|
)
|
||||||
|
|
||||||
group = arg_parser.add_mutually_exclusive_group()
|
group = arg_parser.add_mutually_exclusive_group()
|
||||||
group.add_argument('--output', metavar='FILE',
|
group.add_argument(
|
||||||
help='Write output into the specified file')
|
"--output", metavar="FILE", help="Write output into the specified file"
|
||||||
group.add_argument('--output-directory', metavar='OUTDIR', default='',
|
)
|
||||||
help='Location to output generated files')
|
group.add_argument(
|
||||||
|
"--output-directory",
|
||||||
|
metavar="OUTDIR",
|
||||||
|
default="",
|
||||||
|
help="Location to output generated files",
|
||||||
|
)
|
||||||
|
|
||||||
args = arg_parser.parse_args();
|
args = arg_parser.parse_args()
|
||||||
|
|
||||||
if len(args.xml_files) > 0:
|
if len(args.xml_files) > 0:
|
||||||
print_warning('The "--xml-files" option is deprecated; use positional arguments instead')
|
print_warning(
|
||||||
|
'The "--xml-files" option is deprecated; use positional arguments instead'
|
||||||
|
)
|
||||||
|
|
||||||
if ((args.generate_c_code is not None or args.generate_docbook is not None) and
|
if (
|
||||||
args.output is not None):
|
args.generate_c_code is not None or args.generate_docbook is not None
|
||||||
print_error('Using --generate-c-code or --generate-docbook and '
|
) and args.output is not None:
|
||||||
'--output at the same time is not allowed')
|
print_error(
|
||||||
|
"Using --generate-c-code or --generate-docbook and "
|
||||||
|
"--output at the same time is not allowed"
|
||||||
|
)
|
||||||
|
|
||||||
if args.generate_c_code:
|
if args.generate_c_code:
|
||||||
header_name = args.generate_c_code + '.h'
|
header_name = args.generate_c_code + ".h"
|
||||||
h_file = os.path.join(args.output_directory, header_name)
|
h_file = os.path.join(args.output_directory, header_name)
|
||||||
args.header = True
|
args.header = True
|
||||||
c_file = os.path.join(args.output_directory, args.generate_c_code + '.c')
|
c_file = os.path.join(args.output_directory, args.generate_c_code + ".c")
|
||||||
args.body = True
|
args.body = True
|
||||||
elif args.header:
|
elif args.header:
|
||||||
if args.output is None:
|
if args.output is None:
|
||||||
print_error('Using --header requires --output')
|
print_error("Using --header requires --output")
|
||||||
|
|
||||||
h_file = args.output
|
h_file = args.output
|
||||||
header_name = os.path.basename(h_file)
|
header_name = os.path.basename(h_file)
|
||||||
elif args.body:
|
elif args.body:
|
||||||
if args.output is None:
|
if args.output is None:
|
||||||
print_error('Using --body requires --output')
|
print_error("Using --body requires --output")
|
||||||
|
|
||||||
c_file = args.output
|
c_file = args.output
|
||||||
header_name = os.path.splitext(os.path.basename(c_file))[0] + '.h'
|
header_name = os.path.splitext(os.path.basename(c_file))[0] + ".h"
|
||||||
elif args.interface_info_header:
|
elif args.interface_info_header:
|
||||||
if args.output is None:
|
if args.output is None:
|
||||||
print_error('Using --interface-info-header requires --output')
|
print_error("Using --interface-info-header requires --output")
|
||||||
if args.c_generate_object_manager:
|
if args.c_generate_object_manager:
|
||||||
print_error('--c-generate-object-manager is incompatible with '
|
print_error(
|
||||||
'--interface-info-header')
|
"--c-generate-object-manager is incompatible with "
|
||||||
|
"--interface-info-header"
|
||||||
|
)
|
||||||
|
|
||||||
h_file = args.output
|
h_file = args.output
|
||||||
header_name = os.path.basename(h_file)
|
header_name = os.path.basename(h_file)
|
||||||
elif args.interface_info_body:
|
elif args.interface_info_body:
|
||||||
if args.output is None:
|
if args.output is None:
|
||||||
print_error('Using --interface-info-body requires --output')
|
print_error("Using --interface-info-body requires --output")
|
||||||
if args.c_generate_object_manager:
|
if args.c_generate_object_manager:
|
||||||
print_error('--c-generate-object-manager is incompatible with '
|
print_error(
|
||||||
'--interface-info-body')
|
"--c-generate-object-manager is incompatible with "
|
||||||
|
"--interface-info-body"
|
||||||
|
)
|
||||||
|
|
||||||
c_file = args.output
|
c_file = args.output
|
||||||
header_name = os.path.splitext(os.path.basename(c_file))[0] + '.h'
|
header_name = os.path.splitext(os.path.basename(c_file))[0] + ".h"
|
||||||
|
|
||||||
# Check the minimum GLib version. The minimum --glib-min-required is 2.30,
|
# Check the minimum GLib version. The minimum --glib-min-required is 2.30,
|
||||||
# because that’s when gdbus-codegen was introduced. Support 1, 2 or 3
|
# because that’s when gdbus-codegen was introduced. Support 1, 2 or 3
|
||||||
# component versions, but ignore the micro component if it’s present.
|
# component versions, but ignore the micro component if it’s present.
|
||||||
if args.glib_min_required:
|
if args.glib_min_required:
|
||||||
try:
|
try:
|
||||||
parts = args.glib_min_required.split('.', 3)
|
parts = args.glib_min_required.split(".", 3)
|
||||||
glib_min_required = (int(parts[0]),
|
glib_min_required = (int(parts[0]), int(parts[1] if len(parts) > 1 else 0))
|
||||||
int(parts[1] if len(parts) > 1 else 0))
|
|
||||||
# Ignore micro component, but still validate it:
|
# Ignore micro component, but still validate it:
|
||||||
_ = int(parts[2] if len(parts) > 2 else 0)
|
_ = int(parts[2] if len(parts) > 2 else 0)
|
||||||
except (ValueError, IndexError):
|
except (ValueError, IndexError):
|
||||||
print_error('Unrecognized --glib-min-required string ‘{}’'.format(
|
print_error(
|
||||||
args.glib_min_required))
|
"Unrecognized --glib-min-required string ‘{}’".format(
|
||||||
|
args.glib_min_required
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if glib_min_required < (2, 30):
|
if glib_min_required < (2, 30):
|
||||||
print_error('Invalid --glib-min-required string ‘{}’: minimum '
|
print_error(
|
||||||
'version is 2.30'.format(args.glib_min_required))
|
"Invalid --glib-min-required string ‘{}’: minimum "
|
||||||
|
"version is 2.30".format(args.glib_min_required)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
glib_min_required = (2, 30)
|
glib_min_required = (2, 30)
|
||||||
|
|
||||||
# And the maximum GLib version.
|
# And the maximum GLib version.
|
||||||
if args.glib_max_allowed:
|
if args.glib_max_allowed:
|
||||||
try:
|
try:
|
||||||
parts = args.glib_max_allowed.split('.', 3)
|
parts = args.glib_max_allowed.split(".", 3)
|
||||||
glib_max_allowed = (int(parts[0]),
|
glib_max_allowed = (int(parts[0]), int(parts[1] if len(parts) > 1 else 0))
|
||||||
int(parts[1] if len(parts) > 1 else 0))
|
|
||||||
# Ignore micro component, but still validate it:
|
# Ignore micro component, but still validate it:
|
||||||
_ = int(parts[2] if len(parts) > 2 else 0)
|
_ = int(parts[2] if len(parts) > 2 else 0)
|
||||||
except (ValueError, IndexError):
|
except (ValueError, IndexError):
|
||||||
print_error('Unrecognized --glib-max-allowed string ‘{}’'.format(
|
print_error(
|
||||||
args.glib_max_allowed))
|
"Unrecognized --glib-max-allowed string ‘{}’".format(
|
||||||
|
args.glib_max_allowed
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
glib_max_allowed = (config.MAJOR_VERSION, config.MINOR_VERSION)
|
glib_max_allowed = (config.MAJOR_VERSION, config.MINOR_VERSION)
|
||||||
|
|
||||||
# Only allow --symbol-decorator-define and --symbol-decorator-header if --symbol-decorator is used
|
# Only allow --symbol-decorator-define and --symbol-decorator-header if
|
||||||
|
# --symbol-decorator is used
|
||||||
if args.symbol_decorator is None:
|
if args.symbol_decorator is None:
|
||||||
if args.symbol_decorator_header or args.symbol_decorator_define:
|
if args.symbol_decorator_header or args.symbol_decorator_define:
|
||||||
print_error('--symbol-decorator-define and --symbol-decorator-header must be used with --symbol-decorator')
|
print_error(
|
||||||
|
"--symbol-decorator-define and --symbol-decorator-header must "
|
||||||
|
"be used with --symbol-decorator"
|
||||||
|
)
|
||||||
|
|
||||||
# Round --glib-max-allowed up to the next stable release.
|
# Round --glib-max-allowed up to the next stable release.
|
||||||
glib_max_allowed = \
|
glib_max_allowed = (
|
||||||
(glib_max_allowed[0], glib_max_allowed[1] + (glib_max_allowed[1] % 2))
|
glib_max_allowed[0],
|
||||||
|
glib_max_allowed[1] + (glib_max_allowed[1] % 2),
|
||||||
|
)
|
||||||
|
|
||||||
if glib_max_allowed < glib_min_required:
|
if glib_max_allowed < glib_min_required:
|
||||||
print_error('Invalid versions: --glib-min-required ({}) must be '
|
print_error(
|
||||||
'less than or equal to --glib-max-allowed ({})'.format(glib_min_required, glib_max_allowed))
|
"Invalid versions: --glib-min-required ({}) must be "
|
||||||
|
"less than or equal to --glib-max-allowed ({})".format(
|
||||||
|
glib_min_required, glib_max_allowed
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
all_ifaces = []
|
all_ifaces = []
|
||||||
input_files_basenames = []
|
input_files_basenames = []
|
||||||
for fname in sorted(args.files + args.xml_files):
|
for fname in sorted(args.files + args.xml_files):
|
||||||
with open(fname, 'rb') as f:
|
with open(fname, "rb") as f:
|
||||||
xml_data = f.read()
|
xml_data = f.read()
|
||||||
parsed_ifaces = parser.parse_dbus_xml(xml_data,
|
parsed_ifaces = parser.parse_dbus_xml(
|
||||||
h_type_implies_unix_fd=(glib_min_required >= (2, 64)))
|
xml_data, h_type_implies_unix_fd=(glib_min_required >= (2, 64))
|
||||||
|
)
|
||||||
all_ifaces.extend(parsed_ifaces)
|
all_ifaces.extend(parsed_ifaces)
|
||||||
input_files_basenames.append(os.path.basename(fname))
|
input_files_basenames.append(os.path.basename(fname))
|
||||||
|
|
||||||
@ -307,13 +416,14 @@ def codegen_main():
|
|||||||
i.post_process(args.interface_prefix, args.c_namespace)
|
i.post_process(args.interface_prefix, args.c_namespace)
|
||||||
|
|
||||||
docbook = args.generate_docbook
|
docbook = args.generate_docbook
|
||||||
docbook_gen = codegen_docbook.DocbookCodeGenerator(all_ifaces);
|
docbook_gen = codegen_docbook.DocbookCodeGenerator(all_ifaces)
|
||||||
if docbook:
|
if docbook:
|
||||||
ret = docbook_gen.generate(docbook, args.output_directory)
|
docbook_gen.generate(docbook, args.output_directory)
|
||||||
|
|
||||||
if args.header:
|
if args.header:
|
||||||
with open(h_file, 'w') as outfile:
|
with open(h_file, "w") as outfile:
|
||||||
gen = codegen.HeaderCodeGenerator(all_ifaces,
|
gen = codegen.HeaderCodeGenerator(
|
||||||
|
all_ifaces,
|
||||||
args.c_namespace,
|
args.c_namespace,
|
||||||
args.c_generate_object_manager,
|
args.c_generate_object_manager,
|
||||||
args.c_generate_autocleanup,
|
args.c_generate_autocleanup,
|
||||||
@ -323,12 +433,14 @@ def codegen_main():
|
|||||||
glib_min_required,
|
glib_min_required,
|
||||||
args.symbol_decorator,
|
args.symbol_decorator,
|
||||||
args.symbol_decorator_header,
|
args.symbol_decorator_header,
|
||||||
outfile)
|
outfile,
|
||||||
|
)
|
||||||
gen.generate()
|
gen.generate()
|
||||||
|
|
||||||
if args.body:
|
if args.body:
|
||||||
with open(c_file, 'w') as outfile:
|
with open(c_file, "w") as outfile:
|
||||||
gen = codegen.CodeGenerator(all_ifaces,
|
gen = codegen.CodeGenerator(
|
||||||
|
all_ifaces,
|
||||||
args.c_namespace,
|
args.c_namespace,
|
||||||
args.c_generate_object_manager,
|
args.c_generate_object_manager,
|
||||||
header_name,
|
header_name,
|
||||||
@ -336,12 +448,14 @@ def codegen_main():
|
|||||||
docbook_gen,
|
docbook_gen,
|
||||||
glib_min_required,
|
glib_min_required,
|
||||||
args.symbol_decorator_define,
|
args.symbol_decorator_define,
|
||||||
outfile)
|
outfile,
|
||||||
|
)
|
||||||
gen.generate()
|
gen.generate()
|
||||||
|
|
||||||
if args.interface_info_header:
|
if args.interface_info_header:
|
||||||
with open(h_file, 'w') as outfile:
|
with open(h_file, "w") as outfile:
|
||||||
gen = codegen.InterfaceInfoHeaderCodeGenerator(all_ifaces,
|
gen = codegen.InterfaceInfoHeaderCodeGenerator(
|
||||||
|
all_ifaces,
|
||||||
args.c_namespace,
|
args.c_namespace,
|
||||||
header_name,
|
header_name,
|
||||||
input_files_basenames,
|
input_files_basenames,
|
||||||
@ -349,21 +463,25 @@ def codegen_main():
|
|||||||
glib_min_required,
|
glib_min_required,
|
||||||
args.symbol_decorator,
|
args.symbol_decorator,
|
||||||
args.symbol_decorator_header,
|
args.symbol_decorator_header,
|
||||||
outfile)
|
outfile,
|
||||||
|
)
|
||||||
gen.generate()
|
gen.generate()
|
||||||
|
|
||||||
if args.interface_info_body:
|
if args.interface_info_body:
|
||||||
with open(c_file, 'w') as outfile:
|
with open(c_file, "w") as outfile:
|
||||||
gen = codegen.InterfaceInfoBodyCodeGenerator(all_ifaces,
|
gen = codegen.InterfaceInfoBodyCodeGenerator(
|
||||||
|
all_ifaces,
|
||||||
args.c_namespace,
|
args.c_namespace,
|
||||||
header_name,
|
header_name,
|
||||||
input_files_basenames,
|
input_files_basenames,
|
||||||
glib_min_required,
|
glib_min_required,
|
||||||
args.symbol_decorator_define,
|
args.symbol_decorator_define,
|
||||||
outfile)
|
outfile,
|
||||||
|
)
|
||||||
gen.generate()
|
gen.generate()
|
||||||
|
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
codegen_main()
|
codegen_main()
|
||||||
|
@ -22,22 +22,30 @@
|
|||||||
from . import utils
|
from . import utils
|
||||||
from .utils import print_error
|
from .utils import print_error
|
||||||
|
|
||||||
|
|
||||||
class Annotation:
|
class Annotation:
|
||||||
def __init__(self, key, value):
|
def __init__(self, key, value):
|
||||||
self.key = key
|
self.key = key
|
||||||
self.value = value
|
self.value = value
|
||||||
self.annotations = []
|
self.annotations = []
|
||||||
self.since = ''
|
self.since = ""
|
||||||
|
|
||||||
def post_process(self, interface_prefix, cns, cns_upper, cns_lower, container):
|
def post_process(self, interface_prefix, cns, cns_upper, cns_lower, container):
|
||||||
key = self.key
|
key = self.key
|
||||||
overridden_key = utils.lookup_annotation(self.annotations, 'org.gtk.GDBus.C.Name')
|
overridden_key = utils.lookup_annotation(
|
||||||
|
self.annotations, "org.gtk.GDBus.C.Name"
|
||||||
|
)
|
||||||
if utils.is_ugly_case(overridden_key):
|
if utils.is_ugly_case(overridden_key):
|
||||||
self.key_lower = overridden_key.lower()
|
self.key_lower = overridden_key.lower()
|
||||||
else:
|
else:
|
||||||
if overridden_key:
|
if overridden_key:
|
||||||
key = overridden_key
|
key = overridden_key
|
||||||
self.key_lower = utils.camel_case_to_uscore(key).lower().replace('-', '_').replace('.', '_')
|
self.key_lower = (
|
||||||
|
utils.camel_case_to_uscore(key)
|
||||||
|
.lower()
|
||||||
|
.replace("-", "_")
|
||||||
|
.replace(".", "_")
|
||||||
|
)
|
||||||
|
|
||||||
if len(self.since) == 0:
|
if len(self.since) == 0:
|
||||||
self.since = utils.lookup_since(self.annotations)
|
self.since = utils.lookup_since(self.annotations)
|
||||||
@ -47,13 +55,14 @@ class Annotation:
|
|||||||
for a in self.annotations:
|
for a in self.annotations:
|
||||||
a.post_process(interface_prefix, cns, cns_upper, cns_lower, self)
|
a.post_process(interface_prefix, cns, cns_upper, cns_lower, self)
|
||||||
|
|
||||||
|
|
||||||
class Arg:
|
class Arg:
|
||||||
def __init__(self, name, signature):
|
def __init__(self, name, signature):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.signature = signature
|
self.signature = signature
|
||||||
self.annotations = []
|
self.annotations = []
|
||||||
self.doc_string = ''
|
self.doc_string = ""
|
||||||
self.since = ''
|
self.since = ""
|
||||||
|
|
||||||
def post_process(self, interface_prefix, cns, cns_upper, cns_lower, arg_number):
|
def post_process(self, interface_prefix, cns, cns_upper, cns_lower, arg_number):
|
||||||
if len(self.doc_string) == 0:
|
if len(self.doc_string) == 0:
|
||||||
@ -62,195 +71,198 @@ class Arg:
|
|||||||
self.since = utils.lookup_since(self.annotations)
|
self.since = utils.lookup_since(self.annotations)
|
||||||
|
|
||||||
if self.name is None:
|
if self.name is None:
|
||||||
self.name = 'unnamed_arg%d'%arg_number
|
self.name = "unnamed_arg%d" % arg_number
|
||||||
# default to GVariant
|
# default to GVariant
|
||||||
self.ctype_in_g = 'GVariant *'
|
self.ctype_in_g = "GVariant *"
|
||||||
self.ctype_in = 'GVariant *'
|
self.ctype_in = "GVariant *"
|
||||||
self.ctype_in_dup = 'GVariant *'
|
self.ctype_in_dup = "GVariant *"
|
||||||
self.ctype_out = 'GVariant **'
|
self.ctype_out = "GVariant **"
|
||||||
self.gtype = 'G_TYPE_VARIANT'
|
self.gtype = "G_TYPE_VARIANT"
|
||||||
self.free_func = 'g_variant_unref'
|
self.free_func = "g_variant_unref"
|
||||||
self.format_in = '@' + self.signature
|
self.format_in = "@" + self.signature
|
||||||
self.format_out = '@' + self.signature
|
self.format_out = "@" + self.signature
|
||||||
self.gvariant_get = 'XXX'
|
self.gvariant_get = "XXX"
|
||||||
self.gvalue_get = 'g_value_get_variant'
|
self.gvalue_get = "g_value_get_variant"
|
||||||
self.array_annotation = ''
|
self.array_annotation = ""
|
||||||
|
|
||||||
if not utils.lookup_annotation(self.annotations, 'org.gtk.GDBus.C.ForceGVariant'):
|
if not utils.lookup_annotation(
|
||||||
if self.signature == 'b':
|
self.annotations, "org.gtk.GDBus.C.ForceGVariant"
|
||||||
self.ctype_in_g = 'gboolean '
|
):
|
||||||
self.ctype_in = 'gboolean '
|
if self.signature == "b":
|
||||||
self.ctype_out = 'gboolean *'
|
self.ctype_in_g = "gboolean "
|
||||||
self.gtype = 'G_TYPE_BOOLEAN'
|
self.ctype_in = "gboolean "
|
||||||
|
self.ctype_out = "gboolean *"
|
||||||
|
self.gtype = "G_TYPE_BOOLEAN"
|
||||||
self.free_func = None
|
self.free_func = None
|
||||||
self.format_in = 'b'
|
self.format_in = "b"
|
||||||
self.format_out = 'b'
|
self.format_out = "b"
|
||||||
self.gvariant_get = 'g_variant_get_boolean'
|
self.gvariant_get = "g_variant_get_boolean"
|
||||||
self.gvalue_get = 'g_value_get_boolean'
|
self.gvalue_get = "g_value_get_boolean"
|
||||||
elif self.signature == 'y':
|
elif self.signature == "y":
|
||||||
self.ctype_in_g = 'guchar '
|
self.ctype_in_g = "guchar "
|
||||||
self.ctype_in = 'guchar '
|
self.ctype_in = "guchar "
|
||||||
self.ctype_out = 'guchar *'
|
self.ctype_out = "guchar *"
|
||||||
self.gtype = 'G_TYPE_UCHAR'
|
self.gtype = "G_TYPE_UCHAR"
|
||||||
self.free_func = None
|
self.free_func = None
|
||||||
self.format_in = 'y'
|
self.format_in = "y"
|
||||||
self.format_out = 'y'
|
self.format_out = "y"
|
||||||
self.gvariant_get = 'g_variant_get_byte'
|
self.gvariant_get = "g_variant_get_byte"
|
||||||
self.gvalue_get = 'g_value_get_uchar'
|
self.gvalue_get = "g_value_get_uchar"
|
||||||
elif self.signature == 'n':
|
elif self.signature == "n":
|
||||||
self.ctype_in_g = 'gint '
|
self.ctype_in_g = "gint "
|
||||||
self.ctype_in = 'gint16 '
|
self.ctype_in = "gint16 "
|
||||||
self.ctype_out = 'gint16 *'
|
self.ctype_out = "gint16 *"
|
||||||
self.gtype = 'G_TYPE_INT'
|
self.gtype = "G_TYPE_INT"
|
||||||
self.free_func = None
|
self.free_func = None
|
||||||
self.format_in = 'n'
|
self.format_in = "n"
|
||||||
self.format_out = 'n'
|
self.format_out = "n"
|
||||||
self.gvariant_get = 'g_variant_get_int16'
|
self.gvariant_get = "g_variant_get_int16"
|
||||||
self.gvalue_get = 'g_value_get_int'
|
self.gvalue_get = "g_value_get_int"
|
||||||
elif self.signature == 'q':
|
elif self.signature == "q":
|
||||||
self.ctype_in_g = 'guint '
|
self.ctype_in_g = "guint "
|
||||||
self.ctype_in = 'guint16 '
|
self.ctype_in = "guint16 "
|
||||||
self.ctype_out = 'guint16 *'
|
self.ctype_out = "guint16 *"
|
||||||
self.gtype = 'G_TYPE_UINT'
|
self.gtype = "G_TYPE_UINT"
|
||||||
self.free_func = None
|
self.free_func = None
|
||||||
self.format_in = 'q'
|
self.format_in = "q"
|
||||||
self.format_out = 'q'
|
self.format_out = "q"
|
||||||
self.gvariant_get = 'g_variant_get_uint16'
|
self.gvariant_get = "g_variant_get_uint16"
|
||||||
self.gvalue_get = 'g_value_get_uint'
|
self.gvalue_get = "g_value_get_uint"
|
||||||
elif self.signature == 'i':
|
elif self.signature == "i":
|
||||||
self.ctype_in_g = 'gint '
|
self.ctype_in_g = "gint "
|
||||||
self.ctype_in = 'gint '
|
self.ctype_in = "gint "
|
||||||
self.ctype_out = 'gint *'
|
self.ctype_out = "gint *"
|
||||||
self.gtype = 'G_TYPE_INT'
|
self.gtype = "G_TYPE_INT"
|
||||||
self.free_func = None
|
self.free_func = None
|
||||||
self.format_in = 'i'
|
self.format_in = "i"
|
||||||
self.format_out = 'i'
|
self.format_out = "i"
|
||||||
self.gvariant_get = 'g_variant_get_int32'
|
self.gvariant_get = "g_variant_get_int32"
|
||||||
self.gvalue_get = 'g_value_get_int'
|
self.gvalue_get = "g_value_get_int"
|
||||||
elif self.signature == 'u':
|
elif self.signature == "u":
|
||||||
self.ctype_in_g = 'guint '
|
self.ctype_in_g = "guint "
|
||||||
self.ctype_in = 'guint '
|
self.ctype_in = "guint "
|
||||||
self.ctype_out = 'guint *'
|
self.ctype_out = "guint *"
|
||||||
self.gtype = 'G_TYPE_UINT'
|
self.gtype = "G_TYPE_UINT"
|
||||||
self.free_func = None
|
self.free_func = None
|
||||||
self.format_in = 'u'
|
self.format_in = "u"
|
||||||
self.format_out = 'u'
|
self.format_out = "u"
|
||||||
self.gvariant_get = 'g_variant_get_uint32'
|
self.gvariant_get = "g_variant_get_uint32"
|
||||||
self.gvalue_get = 'g_value_get_uint'
|
self.gvalue_get = "g_value_get_uint"
|
||||||
elif self.signature == 'x':
|
elif self.signature == "x":
|
||||||
self.ctype_in_g = 'gint64 '
|
self.ctype_in_g = "gint64 "
|
||||||
self.ctype_in = 'gint64 '
|
self.ctype_in = "gint64 "
|
||||||
self.ctype_out = 'gint64 *'
|
self.ctype_out = "gint64 *"
|
||||||
self.gtype = 'G_TYPE_INT64'
|
self.gtype = "G_TYPE_INT64"
|
||||||
self.free_func = None
|
self.free_func = None
|
||||||
self.format_in = 'x'
|
self.format_in = "x"
|
||||||
self.format_out = 'x'
|
self.format_out = "x"
|
||||||
self.gvariant_get = 'g_variant_get_int64'
|
self.gvariant_get = "g_variant_get_int64"
|
||||||
self.gvalue_get = 'g_value_get_int64'
|
self.gvalue_get = "g_value_get_int64"
|
||||||
elif self.signature == 't':
|
elif self.signature == "t":
|
||||||
self.ctype_in_g = 'guint64 '
|
self.ctype_in_g = "guint64 "
|
||||||
self.ctype_in = 'guint64 '
|
self.ctype_in = "guint64 "
|
||||||
self.ctype_out = 'guint64 *'
|
self.ctype_out = "guint64 *"
|
||||||
self.gtype = 'G_TYPE_UINT64'
|
self.gtype = "G_TYPE_UINT64"
|
||||||
self.free_func = None
|
self.free_func = None
|
||||||
self.format_in = 't'
|
self.format_in = "t"
|
||||||
self.format_out = 't'
|
self.format_out = "t"
|
||||||
self.gvariant_get = 'g_variant_get_uint64'
|
self.gvariant_get = "g_variant_get_uint64"
|
||||||
self.gvalue_get = 'g_value_get_uint64'
|
self.gvalue_get = "g_value_get_uint64"
|
||||||
elif self.signature == 'd':
|
elif self.signature == "d":
|
||||||
self.ctype_in_g = 'gdouble '
|
self.ctype_in_g = "gdouble "
|
||||||
self.ctype_in = 'gdouble '
|
self.ctype_in = "gdouble "
|
||||||
self.ctype_out = 'gdouble *'
|
self.ctype_out = "gdouble *"
|
||||||
self.gtype = 'G_TYPE_DOUBLE'
|
self.gtype = "G_TYPE_DOUBLE"
|
||||||
self.free_func = None
|
self.free_func = None
|
||||||
self.format_in = 'd'
|
self.format_in = "d"
|
||||||
self.format_out = 'd'
|
self.format_out = "d"
|
||||||
self.gvariant_get = 'g_variant_get_double'
|
self.gvariant_get = "g_variant_get_double"
|
||||||
self.gvalue_get = 'g_value_get_double'
|
self.gvalue_get = "g_value_get_double"
|
||||||
elif self.signature == 's':
|
elif self.signature == "s":
|
||||||
self.ctype_in_g = 'const gchar *'
|
self.ctype_in_g = "const gchar *"
|
||||||
self.ctype_in = 'const gchar *'
|
self.ctype_in = "const gchar *"
|
||||||
self.ctype_in_dup = 'gchar *'
|
self.ctype_in_dup = "gchar *"
|
||||||
self.ctype_out = 'gchar **'
|
self.ctype_out = "gchar **"
|
||||||
self.gtype = 'G_TYPE_STRING'
|
self.gtype = "G_TYPE_STRING"
|
||||||
self.free_func = 'g_free'
|
self.free_func = "g_free"
|
||||||
self.format_in = 's'
|
self.format_in = "s"
|
||||||
self.format_out = 's'
|
self.format_out = "s"
|
||||||
self.gvariant_get = 'g_variant_get_string'
|
self.gvariant_get = "g_variant_get_string"
|
||||||
self.gvalue_get = 'g_value_get_string'
|
self.gvalue_get = "g_value_get_string"
|
||||||
elif self.signature == 'o':
|
elif self.signature == "o":
|
||||||
self.ctype_in_g = 'const gchar *'
|
self.ctype_in_g = "const gchar *"
|
||||||
self.ctype_in = 'const gchar *'
|
self.ctype_in = "const gchar *"
|
||||||
self.ctype_in_dup = 'gchar *'
|
self.ctype_in_dup = "gchar *"
|
||||||
self.ctype_out = 'gchar **'
|
self.ctype_out = "gchar **"
|
||||||
self.gtype = 'G_TYPE_STRING'
|
self.gtype = "G_TYPE_STRING"
|
||||||
self.free_func = 'g_free'
|
self.free_func = "g_free"
|
||||||
self.format_in = 'o'
|
self.format_in = "o"
|
||||||
self.format_out = 'o'
|
self.format_out = "o"
|
||||||
self.gvariant_get = 'g_variant_get_string'
|
self.gvariant_get = "g_variant_get_string"
|
||||||
self.gvalue_get = 'g_value_get_string'
|
self.gvalue_get = "g_value_get_string"
|
||||||
elif self.signature == 'g':
|
elif self.signature == "g":
|
||||||
self.ctype_in_g = 'const gchar *'
|
self.ctype_in_g = "const gchar *"
|
||||||
self.ctype_in = 'const gchar *'
|
self.ctype_in = "const gchar *"
|
||||||
self.ctype_in_dup = 'gchar *'
|
self.ctype_in_dup = "gchar *"
|
||||||
self.ctype_out = 'gchar **'
|
self.ctype_out = "gchar **"
|
||||||
self.gtype = 'G_TYPE_STRING'
|
self.gtype = "G_TYPE_STRING"
|
||||||
self.free_func = 'g_free'
|
self.free_func = "g_free"
|
||||||
self.format_in = 'g'
|
self.format_in = "g"
|
||||||
self.format_out = 'g'
|
self.format_out = "g"
|
||||||
self.gvariant_get = 'g_variant_get_string'
|
self.gvariant_get = "g_variant_get_string"
|
||||||
self.gvalue_get = 'g_value_get_string'
|
self.gvalue_get = "g_value_get_string"
|
||||||
elif self.signature == 'ay':
|
elif self.signature == "ay":
|
||||||
self.ctype_in_g = 'const gchar *'
|
self.ctype_in_g = "const gchar *"
|
||||||
self.ctype_in = 'const gchar *'
|
self.ctype_in = "const gchar *"
|
||||||
self.ctype_in_dup = 'gchar *'
|
self.ctype_in_dup = "gchar *"
|
||||||
self.ctype_out = 'gchar **'
|
self.ctype_out = "gchar **"
|
||||||
self.gtype = 'G_TYPE_STRING'
|
self.gtype = "G_TYPE_STRING"
|
||||||
self.free_func = 'g_free'
|
self.free_func = "g_free"
|
||||||
self.format_in = '^ay'
|
self.format_in = "^ay"
|
||||||
self.format_out = '^ay'
|
self.format_out = "^ay"
|
||||||
self.gvariant_get = 'g_variant_get_bytestring'
|
self.gvariant_get = "g_variant_get_bytestring"
|
||||||
self.gvalue_get = 'g_value_get_string'
|
self.gvalue_get = "g_value_get_string"
|
||||||
elif self.signature == 'as':
|
elif self.signature == "as":
|
||||||
self.ctype_in_g = 'const gchar *const *'
|
self.ctype_in_g = "const gchar *const *"
|
||||||
self.ctype_in = 'const gchar *const *'
|
self.ctype_in = "const gchar *const *"
|
||||||
self.ctype_in_dup = 'gchar **'
|
self.ctype_in_dup = "gchar **"
|
||||||
self.ctype_out = 'gchar ***'
|
self.ctype_out = "gchar ***"
|
||||||
self.gtype = 'G_TYPE_STRV'
|
self.gtype = "G_TYPE_STRV"
|
||||||
self.free_func = 'g_strfreev'
|
self.free_func = "g_strfreev"
|
||||||
self.format_in = '^as'
|
self.format_in = "^as"
|
||||||
self.format_out = '^as'
|
self.format_out = "^as"
|
||||||
self.gvariant_get = 'g_variant_get_strv'
|
self.gvariant_get = "g_variant_get_strv"
|
||||||
self.gvalue_get = 'g_value_get_boxed'
|
self.gvalue_get = "g_value_get_boxed"
|
||||||
self.array_annotation = '(array zero-terminated=1)'
|
self.array_annotation = "(array zero-terminated=1)"
|
||||||
elif self.signature == 'ao':
|
elif self.signature == "ao":
|
||||||
self.ctype_in_g = 'const gchar *const *'
|
self.ctype_in_g = "const gchar *const *"
|
||||||
self.ctype_in = 'const gchar *const *'
|
self.ctype_in = "const gchar *const *"
|
||||||
self.ctype_in_dup = 'gchar **'
|
self.ctype_in_dup = "gchar **"
|
||||||
self.ctype_out = 'gchar ***'
|
self.ctype_out = "gchar ***"
|
||||||
self.gtype = 'G_TYPE_STRV'
|
self.gtype = "G_TYPE_STRV"
|
||||||
self.free_func = 'g_strfreev'
|
self.free_func = "g_strfreev"
|
||||||
self.format_in = '^ao'
|
self.format_in = "^ao"
|
||||||
self.format_out = '^ao'
|
self.format_out = "^ao"
|
||||||
self.gvariant_get = 'g_variant_get_objv'
|
self.gvariant_get = "g_variant_get_objv"
|
||||||
self.gvalue_get = 'g_value_get_boxed'
|
self.gvalue_get = "g_value_get_boxed"
|
||||||
self.array_annotation = '(array zero-terminated=1)'
|
self.array_annotation = "(array zero-terminated=1)"
|
||||||
elif self.signature == 'aay':
|
elif self.signature == "aay":
|
||||||
self.ctype_in_g = 'const gchar *const *'
|
self.ctype_in_g = "const gchar *const *"
|
||||||
self.ctype_in = 'const gchar *const *'
|
self.ctype_in = "const gchar *const *"
|
||||||
self.ctype_in_dup = 'gchar **'
|
self.ctype_in_dup = "gchar **"
|
||||||
self.ctype_out = 'gchar ***'
|
self.ctype_out = "gchar ***"
|
||||||
self.gtype = 'G_TYPE_STRV'
|
self.gtype = "G_TYPE_STRV"
|
||||||
self.free_func = 'g_strfreev'
|
self.free_func = "g_strfreev"
|
||||||
self.format_in = '^aay'
|
self.format_in = "^aay"
|
||||||
self.format_out = '^aay'
|
self.format_out = "^aay"
|
||||||
self.gvariant_get = 'g_variant_get_bytestring_array'
|
self.gvariant_get = "g_variant_get_bytestring_array"
|
||||||
self.gvalue_get = 'g_value_get_boxed'
|
self.gvalue_get = "g_value_get_boxed"
|
||||||
self.array_annotation = '(array zero-terminated=1)'
|
self.array_annotation = "(array zero-terminated=1)"
|
||||||
|
|
||||||
for a in self.annotations:
|
for a in self.annotations:
|
||||||
a.post_process(interface_prefix, cns, cns_upper, cns_lower, self)
|
a.post_process(interface_prefix, cns, cns_upper, cns_lower, self)
|
||||||
|
|
||||||
|
|
||||||
class Method:
|
class Method:
|
||||||
def __init__(self, name, h_type_implies_unix_fd=True):
|
def __init__(self, name, h_type_implies_unix_fd=True):
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -258,12 +270,14 @@ class Method:
|
|||||||
self.in_args = []
|
self.in_args = []
|
||||||
self.out_args = []
|
self.out_args = []
|
||||||
self.annotations = []
|
self.annotations = []
|
||||||
self.doc_string = ''
|
self.doc_string = ""
|
||||||
self.since = ''
|
self.since = ""
|
||||||
self.deprecated = False
|
self.deprecated = False
|
||||||
self.unix_fd = False
|
self.unix_fd = False
|
||||||
|
|
||||||
def post_process(self, interface_prefix, cns, cns_upper, cns_lower, containing_iface):
|
def post_process(
|
||||||
|
self, interface_prefix, cns, cns_upper, cns_lower, containing_iface
|
||||||
|
):
|
||||||
if len(self.doc_string) == 0:
|
if len(self.doc_string) == 0:
|
||||||
self.doc_string = utils.lookup_docs(self.annotations)
|
self.doc_string = utils.lookup_docs(self.annotations)
|
||||||
if len(self.since) == 0:
|
if len(self.since) == 0:
|
||||||
@ -272,47 +286,55 @@ class Method:
|
|||||||
self.since = containing_iface.since
|
self.since = containing_iface.since
|
||||||
|
|
||||||
name = self.name
|
name = self.name
|
||||||
overridden_name = utils.lookup_annotation(self.annotations, 'org.gtk.GDBus.C.Name')
|
overridden_name = utils.lookup_annotation(
|
||||||
|
self.annotations, "org.gtk.GDBus.C.Name"
|
||||||
|
)
|
||||||
if utils.is_ugly_case(overridden_name):
|
if utils.is_ugly_case(overridden_name):
|
||||||
self.name_lower = overridden_name.lower()
|
self.name_lower = overridden_name.lower()
|
||||||
else:
|
else:
|
||||||
if overridden_name:
|
if overridden_name:
|
||||||
name = overridden_name
|
name = overridden_name
|
||||||
self.name_lower = utils.camel_case_to_uscore(name).lower().replace('-', '_')
|
self.name_lower = utils.camel_case_to_uscore(name).lower().replace("-", "_")
|
||||||
self.name_hyphen = self.name_lower.replace('_', '-')
|
self.name_hyphen = self.name_lower.replace("_", "-")
|
||||||
|
|
||||||
arg_count = 0
|
arg_count = 0
|
||||||
for a in self.in_args:
|
for a in self.in_args:
|
||||||
a.post_process(interface_prefix, cns, cns_upper, cns_lower, arg_count)
|
a.post_process(interface_prefix, cns, cns_upper, cns_lower, arg_count)
|
||||||
arg_count += 1
|
arg_count += 1
|
||||||
if self.h_type_implies_unix_fd and 'h' in a.signature:
|
if self.h_type_implies_unix_fd and "h" in a.signature:
|
||||||
self.unix_fd = True
|
self.unix_fd = True
|
||||||
|
|
||||||
for a in self.out_args:
|
for a in self.out_args:
|
||||||
a.post_process(interface_prefix, cns, cns_upper, cns_lower, arg_count)
|
a.post_process(interface_prefix, cns, cns_upper, cns_lower, arg_count)
|
||||||
arg_count += 1
|
arg_count += 1
|
||||||
if self.h_type_implies_unix_fd and 'h' in a.signature:
|
if self.h_type_implies_unix_fd and "h" in a.signature:
|
||||||
self.unix_fd = True
|
self.unix_fd = True
|
||||||
|
|
||||||
if utils.lookup_annotation(self.annotations, 'org.freedesktop.DBus.Deprecated') == 'true':
|
if (
|
||||||
|
utils.lookup_annotation(self.annotations, "org.freedesktop.DBus.Deprecated")
|
||||||
|
== "true"
|
||||||
|
):
|
||||||
self.deprecated = True
|
self.deprecated = True
|
||||||
|
|
||||||
if utils.lookup_annotation(self.annotations, 'org.gtk.GDBus.C.UnixFD'):
|
if utils.lookup_annotation(self.annotations, "org.gtk.GDBus.C.UnixFD"):
|
||||||
self.unix_fd = True
|
self.unix_fd = True
|
||||||
|
|
||||||
for a in self.annotations:
|
for a in self.annotations:
|
||||||
a.post_process(interface_prefix, cns, cns_upper, cns_lower, self)
|
a.post_process(interface_prefix, cns, cns_upper, cns_lower, self)
|
||||||
|
|
||||||
|
|
||||||
class Signal:
|
class Signal:
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.args = []
|
self.args = []
|
||||||
self.annotations = []
|
self.annotations = []
|
||||||
self.doc_string = ''
|
self.doc_string = ""
|
||||||
self.since = ''
|
self.since = ""
|
||||||
self.deprecated = False
|
self.deprecated = False
|
||||||
|
|
||||||
def post_process(self, interface_prefix, cns, cns_upper, cns_lower, containing_iface):
|
def post_process(
|
||||||
|
self, interface_prefix, cns, cns_upper, cns_lower, containing_iface
|
||||||
|
):
|
||||||
if len(self.doc_string) == 0:
|
if len(self.doc_string) == 0:
|
||||||
self.doc_string = utils.lookup_docs(self.annotations)
|
self.doc_string = utils.lookup_docs(self.annotations)
|
||||||
if len(self.since) == 0:
|
if len(self.since) == 0:
|
||||||
@ -321,51 +343,59 @@ class Signal:
|
|||||||
self.since = containing_iface.since
|
self.since = containing_iface.since
|
||||||
|
|
||||||
name = self.name
|
name = self.name
|
||||||
overridden_name = utils.lookup_annotation(self.annotations, 'org.gtk.GDBus.C.Name')
|
overridden_name = utils.lookup_annotation(
|
||||||
|
self.annotations, "org.gtk.GDBus.C.Name"
|
||||||
|
)
|
||||||
if utils.is_ugly_case(overridden_name):
|
if utils.is_ugly_case(overridden_name):
|
||||||
self.name_lower = overridden_name.lower()
|
self.name_lower = overridden_name.lower()
|
||||||
else:
|
else:
|
||||||
if overridden_name:
|
if overridden_name:
|
||||||
name = overridden_name
|
name = overridden_name
|
||||||
self.name_lower = utils.camel_case_to_uscore(name).lower().replace('-', '_')
|
self.name_lower = utils.camel_case_to_uscore(name).lower().replace("-", "_")
|
||||||
self.name_hyphen = self.name_lower.replace('_', '-')
|
self.name_hyphen = self.name_lower.replace("_", "-")
|
||||||
|
|
||||||
arg_count = 0
|
arg_count = 0
|
||||||
for a in self.args:
|
for a in self.args:
|
||||||
a.post_process(interface_prefix, cns, cns_upper, cns_lower, arg_count)
|
a.post_process(interface_prefix, cns, cns_upper, cns_lower, arg_count)
|
||||||
arg_count += 1
|
arg_count += 1
|
||||||
|
|
||||||
if utils.lookup_annotation(self.annotations, 'org.freedesktop.DBus.Deprecated') == 'true':
|
if (
|
||||||
|
utils.lookup_annotation(self.annotations, "org.freedesktop.DBus.Deprecated")
|
||||||
|
== "true"
|
||||||
|
):
|
||||||
self.deprecated = True
|
self.deprecated = True
|
||||||
|
|
||||||
for a in self.annotations:
|
for a in self.annotations:
|
||||||
a.post_process(interface_prefix, cns, cns_upper, cns_lower, self)
|
a.post_process(interface_prefix, cns, cns_upper, cns_lower, self)
|
||||||
|
|
||||||
|
|
||||||
class Property:
|
class Property:
|
||||||
def __init__(self, name, signature, access):
|
def __init__(self, name, signature, access):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.signature = signature
|
self.signature = signature
|
||||||
self.access = access
|
self.access = access
|
||||||
self.annotations = []
|
self.annotations = []
|
||||||
self.arg = Arg('value', self.signature)
|
self.arg = Arg("value", self.signature)
|
||||||
self.arg.annotations = self.annotations
|
self.arg.annotations = self.annotations
|
||||||
self.readable = False
|
self.readable = False
|
||||||
self.writable = False
|
self.writable = False
|
||||||
if self.access == 'readwrite':
|
if self.access == "readwrite":
|
||||||
self.readable = True
|
self.readable = True
|
||||||
self.writable = True
|
self.writable = True
|
||||||
elif self.access == 'read':
|
elif self.access == "read":
|
||||||
self.readable = True
|
self.readable = True
|
||||||
elif self.access == 'write':
|
elif self.access == "write":
|
||||||
self.writable = True
|
self.writable = True
|
||||||
else:
|
else:
|
||||||
print_error('Invalid access type "{}"'.format(self.access))
|
print_error('Invalid access type "{}"'.format(self.access))
|
||||||
self.doc_string = ''
|
self.doc_string = ""
|
||||||
self.since = ''
|
self.since = ""
|
||||||
self.deprecated = False
|
self.deprecated = False
|
||||||
self.emits_changed_signal = True
|
self.emits_changed_signal = True
|
||||||
|
|
||||||
def post_process(self, interface_prefix, cns, cns_upper, cns_lower, containing_iface):
|
def post_process(
|
||||||
|
self, interface_prefix, cns, cns_upper, cns_lower, containing_iface
|
||||||
|
):
|
||||||
if len(self.doc_string) == 0:
|
if len(self.doc_string) == 0:
|
||||||
self.doc_string = utils.lookup_docs(self.annotations)
|
self.doc_string = utils.lookup_docs(self.annotations)
|
||||||
if len(self.since) == 0:
|
if len(self.since) == 0:
|
||||||
@ -374,34 +404,44 @@ class Property:
|
|||||||
self.since = containing_iface.since
|
self.since = containing_iface.since
|
||||||
|
|
||||||
name = self.name
|
name = self.name
|
||||||
overridden_name = utils.lookup_annotation(self.annotations, 'org.gtk.GDBus.C.Name')
|
overridden_name = utils.lookup_annotation(
|
||||||
|
self.annotations, "org.gtk.GDBus.C.Name"
|
||||||
|
)
|
||||||
if utils.is_ugly_case(overridden_name):
|
if utils.is_ugly_case(overridden_name):
|
||||||
self.name_lower = overridden_name.lower()
|
self.name_lower = overridden_name.lower()
|
||||||
else:
|
else:
|
||||||
if overridden_name:
|
if overridden_name:
|
||||||
name = overridden_name
|
name = overridden_name
|
||||||
self.name_lower = utils.camel_case_to_uscore(name).lower().replace('-', '_')
|
self.name_lower = utils.camel_case_to_uscore(name).lower().replace("-", "_")
|
||||||
self.name_hyphen = self.name_lower.replace('_', '-')
|
self.name_hyphen = self.name_lower.replace("_", "-")
|
||||||
# don't clash with the GType getter, e.g.: GType foo_bar_get_type (void); G_GNUC_CONST
|
# don't clash with the GType getter, e.g.:
|
||||||
if self.name_lower == 'type':
|
# GType foo_bar_get_type (void); G_GNUC_CONST
|
||||||
self.name_lower = 'type_'
|
if self.name_lower == "type":
|
||||||
|
self.name_lower = "type_"
|
||||||
|
|
||||||
# recalculate arg
|
# recalculate arg
|
||||||
self.arg.annotations = self.annotations
|
self.arg.annotations = self.annotations
|
||||||
self.arg.post_process(interface_prefix, cns, cns_upper, cns_lower, 0)
|
self.arg.post_process(interface_prefix, cns, cns_upper, cns_lower, 0)
|
||||||
|
|
||||||
if utils.lookup_annotation(self.annotations, 'org.freedesktop.DBus.Deprecated') == 'true':
|
if (
|
||||||
|
utils.lookup_annotation(self.annotations, "org.freedesktop.DBus.Deprecated")
|
||||||
|
== "true"
|
||||||
|
):
|
||||||
self.deprecated = True
|
self.deprecated = True
|
||||||
|
|
||||||
for a in self.annotations:
|
for a in self.annotations:
|
||||||
a.post_process(interface_prefix, cns, cns_upper, cns_lower, self)
|
a.post_process(interface_prefix, cns, cns_upper, cns_lower, self)
|
||||||
|
|
||||||
# FIXME: for now we only support 'false' and 'const' on the signal itself, see #674913 and
|
# FIXME: for now we only support 'false' and 'const' on the signal itself,
|
||||||
|
# see #674913 and
|
||||||
# http://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format
|
# http://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format
|
||||||
# for details
|
# for details
|
||||||
if utils.lookup_annotation(self.annotations, 'org.freedesktop.DBus.Property.EmitsChangedSignal') in ('false', 'const'):
|
if utils.lookup_annotation(
|
||||||
|
self.annotations, "org.freedesktop.DBus.Property.EmitsChangedSignal"
|
||||||
|
) in ("false", "const"):
|
||||||
self.emits_changed_signal = False
|
self.emits_changed_signal = False
|
||||||
|
|
||||||
|
|
||||||
class Interface:
|
class Interface:
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -409,9 +449,9 @@ class Interface:
|
|||||||
self.signals = []
|
self.signals = []
|
||||||
self.properties = []
|
self.properties = []
|
||||||
self.annotations = []
|
self.annotations = []
|
||||||
self.doc_string = ''
|
self.doc_string = ""
|
||||||
self.doc_string_brief = ''
|
self.doc_string_brief = ""
|
||||||
self.since = ''
|
self.since = ""
|
||||||
self.deprecated = False
|
self.deprecated = False
|
||||||
|
|
||||||
def post_process(self, interface_prefix, c_namespace):
|
def post_process(self, interface_prefix, c_namespace):
|
||||||
@ -424,21 +464,23 @@ class Interface:
|
|||||||
|
|
||||||
if len(c_namespace) > 0:
|
if len(c_namespace) > 0:
|
||||||
if utils.is_ugly_case(c_namespace):
|
if utils.is_ugly_case(c_namespace):
|
||||||
cns = c_namespace.replace('_', '')
|
cns = c_namespace.replace("_", "")
|
||||||
cns_upper = c_namespace.upper() + '_'
|
cns_upper = c_namespace.upper() + "_"
|
||||||
cns_lower = c_namespace.lower() + '_'
|
cns_lower = c_namespace.lower() + "_"
|
||||||
else:
|
else:
|
||||||
cns = c_namespace
|
cns = c_namespace
|
||||||
cns_upper = utils.camel_case_to_uscore(c_namespace).upper() + '_'
|
cns_upper = utils.camel_case_to_uscore(c_namespace).upper() + "_"
|
||||||
cns_lower = utils.camel_case_to_uscore(c_namespace).lower() + '_'
|
cns_lower = utils.camel_case_to_uscore(c_namespace).lower() + "_"
|
||||||
else:
|
else:
|
||||||
cns = ''
|
cns = ""
|
||||||
cns_upper = ''
|
cns_upper = ""
|
||||||
cns_lower = ''
|
cns_lower = ""
|
||||||
|
|
||||||
overridden_name = utils.lookup_annotation(self.annotations, 'org.gtk.GDBus.C.Name')
|
overridden_name = utils.lookup_annotation(
|
||||||
|
self.annotations, "org.gtk.GDBus.C.Name"
|
||||||
|
)
|
||||||
if utils.is_ugly_case(overridden_name):
|
if utils.is_ugly_case(overridden_name):
|
||||||
name = overridden_name.replace('_', '')
|
name = overridden_name.replace("_", "")
|
||||||
name_with_ns = cns + name
|
name_with_ns = cns + name
|
||||||
self.name_without_prefix = name
|
self.name_without_prefix = name
|
||||||
self.camel_name = name_with_ns
|
self.camel_name = name_with_ns
|
||||||
@ -456,15 +498,18 @@ class Interface:
|
|||||||
name = name[len(interface_prefix) :]
|
name = name[len(interface_prefix) :]
|
||||||
self.name_without_prefix = name
|
self.name_without_prefix = name
|
||||||
name = utils.strip_dots(name)
|
name = utils.strip_dots(name)
|
||||||
name_with_ns = utils.strip_dots(cns + '.' + name)
|
name_with_ns = utils.strip_dots(cns + "." + name)
|
||||||
self.camel_name = name_with_ns
|
self.camel_name = name_with_ns
|
||||||
self.ns_upper = cns_upper
|
self.ns_upper = cns_upper
|
||||||
self.name_lower = cns_lower + utils.camel_case_to_uscore(name)
|
self.name_lower = cns_lower + utils.camel_case_to_uscore(name)
|
||||||
self.name_upper = utils.camel_case_to_uscore(name).upper()
|
self.name_upper = utils.camel_case_to_uscore(name).upper()
|
||||||
|
|
||||||
self.name_hyphen = self.name_upper.lower().replace('_', '-')
|
self.name_hyphen = self.name_upper.lower().replace("_", "-")
|
||||||
|
|
||||||
if utils.lookup_annotation(self.annotations, 'org.freedesktop.DBus.Deprecated') == 'true':
|
if (
|
||||||
|
utils.lookup_annotation(self.annotations, "org.freedesktop.DBus.Deprecated")
|
||||||
|
== "true"
|
||||||
|
):
|
||||||
self.deprecated = True
|
self.deprecated = True
|
||||||
|
|
||||||
for m in self.methods:
|
for m in self.methods:
|
||||||
|
@ -19,22 +19,22 @@
|
|||||||
#
|
#
|
||||||
# Author: David Zeuthen <davidz@redhat.com>
|
# Author: David Zeuthen <davidz@redhat.com>
|
||||||
|
|
||||||
import sys
|
|
||||||
import xml.parsers.expat
|
import xml.parsers.expat
|
||||||
|
|
||||||
from . import dbustypes
|
from . import dbustypes
|
||||||
from .utils import print_error
|
from .utils import print_error
|
||||||
|
|
||||||
|
|
||||||
class DBusXMLParser:
|
class DBusXMLParser:
|
||||||
STATE_TOP = 'top'
|
STATE_TOP = "top"
|
||||||
STATE_NODE = 'node'
|
STATE_NODE = "node"
|
||||||
STATE_INTERFACE = 'interface'
|
STATE_INTERFACE = "interface"
|
||||||
STATE_METHOD = 'method'
|
STATE_METHOD = "method"
|
||||||
STATE_SIGNAL = 'signal'
|
STATE_SIGNAL = "signal"
|
||||||
STATE_PROPERTY = 'property'
|
STATE_PROPERTY = "property"
|
||||||
STATE_ARG = 'arg'
|
STATE_ARG = "arg"
|
||||||
STATE_ANNOTATION = 'annotation'
|
STATE_ANNOTATION = "annotation"
|
||||||
STATE_IGNORED = 'ignored'
|
STATE_IGNORED = "ignored"
|
||||||
|
|
||||||
def __init__(self, xml_data, h_type_implies_unix_fd=True):
|
def __init__(self, xml_data, h_type_implies_unix_fd=True):
|
||||||
self._parser = xml.parsers.expat.ParserCreate()
|
self._parser = xml.parsers.expat.ParserCreate()
|
||||||
@ -51,21 +51,22 @@ class DBusXMLParser:
|
|||||||
self._cur_object = None
|
self._cur_object = None
|
||||||
self._cur_object_stack = []
|
self._cur_object_stack = []
|
||||||
|
|
||||||
self.doc_comment_last_symbol = ''
|
self.doc_comment_last_symbol = ""
|
||||||
|
|
||||||
self._h_type_implies_unix_fd = h_type_implies_unix_fd
|
self._h_type_implies_unix_fd = h_type_implies_unix_fd
|
||||||
|
|
||||||
self._parser.Parse(xml_data)
|
self._parser.Parse(xml_data)
|
||||||
|
|
||||||
COMMENT_STATE_BEGIN = 'begin'
|
COMMENT_STATE_BEGIN = "begin"
|
||||||
COMMENT_STATE_PARAMS = 'params'
|
COMMENT_STATE_PARAMS = "params"
|
||||||
COMMENT_STATE_BODY = 'body'
|
COMMENT_STATE_BODY = "body"
|
||||||
COMMENT_STATE_SKIP = 'skip'
|
COMMENT_STATE_SKIP = "skip"
|
||||||
|
|
||||||
def handle_comment(self, data):
|
def handle_comment(self, data):
|
||||||
comment_state = DBusXMLParser.COMMENT_STATE_BEGIN;
|
comment_state = DBusXMLParser.COMMENT_STATE_BEGIN
|
||||||
lines = data.split('\n')
|
lines = data.split("\n")
|
||||||
symbol = ''
|
symbol = ""
|
||||||
body = ''
|
body = ""
|
||||||
in_para = False
|
in_para = False
|
||||||
params = {}
|
params = {}
|
||||||
for line in lines:
|
for line in lines:
|
||||||
@ -73,9 +74,9 @@ class DBusXMLParser:
|
|||||||
line = line.lstrip()
|
line = line.lstrip()
|
||||||
if comment_state == DBusXMLParser.COMMENT_STATE_BEGIN:
|
if comment_state == DBusXMLParser.COMMENT_STATE_BEGIN:
|
||||||
if len(line) > 0:
|
if len(line) > 0:
|
||||||
colon_index = line.find(': ')
|
colon_index = line.find(": ")
|
||||||
if colon_index == -1:
|
if colon_index == -1:
|
||||||
if line.endswith(':'):
|
if line.endswith(":"):
|
||||||
symbol = line[0 : len(line) - 1]
|
symbol = line[0 : len(line) - 1]
|
||||||
comment_state = DBusXMLParser.COMMENT_STATE_PARAMS
|
comment_state = DBusXMLParser.COMMENT_STATE_PARAMS
|
||||||
else:
|
else:
|
||||||
@ -84,17 +85,17 @@ class DBusXMLParser:
|
|||||||
symbol = line[0:colon_index]
|
symbol = line[0:colon_index]
|
||||||
rest_of_line = line[colon_index + 2 :].strip()
|
rest_of_line = line[colon_index + 2 :].strip()
|
||||||
if len(rest_of_line) > 0:
|
if len(rest_of_line) > 0:
|
||||||
body += '<para>' + rest_of_line + '</para>'
|
body += "<para>" + rest_of_line + "</para>"
|
||||||
comment_state = DBusXMLParser.COMMENT_STATE_PARAMS
|
comment_state = DBusXMLParser.COMMENT_STATE_PARAMS
|
||||||
elif comment_state == DBusXMLParser.COMMENT_STATE_PARAMS:
|
elif comment_state == DBusXMLParser.COMMENT_STATE_PARAMS:
|
||||||
if line.startswith('@'):
|
if line.startswith("@"):
|
||||||
colon_index = line.find(': ')
|
colon_index = line.find(": ")
|
||||||
if colon_index == -1:
|
if colon_index == -1:
|
||||||
comment_state = DBusXMLParser.COMMENT_STATE_BODY
|
comment_state = DBusXMLParser.COMMENT_STATE_BODY
|
||||||
if not in_para:
|
if not in_para:
|
||||||
body += '<para>'
|
body += "<para>"
|
||||||
in_para = True
|
in_para = True
|
||||||
body += orig_line + '\n'
|
body += orig_line + "\n"
|
||||||
else:
|
else:
|
||||||
param = line[1:colon_index]
|
param = line[1:colon_index]
|
||||||
docs = line[colon_index + 2 :]
|
docs = line[colon_index + 2 :]
|
||||||
@ -103,23 +104,23 @@ class DBusXMLParser:
|
|||||||
comment_state = DBusXMLParser.COMMENT_STATE_BODY
|
comment_state = DBusXMLParser.COMMENT_STATE_BODY
|
||||||
if len(line) > 0:
|
if len(line) > 0:
|
||||||
if not in_para:
|
if not in_para:
|
||||||
body += '<para>'
|
body += "<para>"
|
||||||
in_para = True
|
in_para = True
|
||||||
body += orig_line + '\n'
|
body += orig_line + "\n"
|
||||||
elif comment_state == DBusXMLParser.COMMENT_STATE_BODY:
|
elif comment_state == DBusXMLParser.COMMENT_STATE_BODY:
|
||||||
if len(line) > 0:
|
if len(line) > 0:
|
||||||
if not in_para:
|
if not in_para:
|
||||||
body += '<para>'
|
body += "<para>"
|
||||||
in_para = True
|
in_para = True
|
||||||
body += orig_line + '\n'
|
body += orig_line + "\n"
|
||||||
else:
|
else:
|
||||||
if in_para:
|
if in_para:
|
||||||
body += '</para>'
|
body += "</para>"
|
||||||
in_para = False
|
in_para = False
|
||||||
if in_para:
|
if in_para:
|
||||||
body += '</para>'
|
body += "</para>"
|
||||||
|
|
||||||
if symbol != '':
|
if symbol != "":
|
||||||
self.doc_comment_last_symbol = symbol
|
self.doc_comment_last_symbol = symbol
|
||||||
self.doc_comment_params = params
|
self.doc_comment_params = params
|
||||||
self.doc_comment_body = body
|
self.doc_comment_body = body
|
||||||
@ -141,77 +142,76 @@ class DBusXMLParser:
|
|||||||
elif self.state == DBusXMLParser.STATE_NODE:
|
elif self.state == DBusXMLParser.STATE_NODE:
|
||||||
if name == DBusXMLParser.STATE_INTERFACE:
|
if name == DBusXMLParser.STATE_INTERFACE:
|
||||||
self.state = DBusXMLParser.STATE_INTERFACE
|
self.state = DBusXMLParser.STATE_INTERFACE
|
||||||
iface = dbustypes.Interface(attrs['name'])
|
iface = dbustypes.Interface(attrs["name"])
|
||||||
self._cur_object = iface
|
self._cur_object = iface
|
||||||
self.parsed_interfaces.append(iface)
|
self.parsed_interfaces.append(iface)
|
||||||
elif name == DBusXMLParser.STATE_ANNOTATION:
|
elif name == DBusXMLParser.STATE_ANNOTATION:
|
||||||
self.state = DBusXMLParser.STATE_ANNOTATION
|
self.state = DBusXMLParser.STATE_ANNOTATION
|
||||||
anno = dbustypes.Annotation(attrs['name'], attrs['value'])
|
anno = dbustypes.Annotation(attrs["name"], attrs["value"])
|
||||||
self._cur_object.annotations.append(anno)
|
self._cur_object.annotations.append(anno)
|
||||||
self._cur_object = anno
|
self._cur_object = anno
|
||||||
else:
|
else:
|
||||||
self.state = DBusXMLParser.STATE_IGNORED
|
self.state = DBusXMLParser.STATE_IGNORED
|
||||||
|
|
||||||
# assign docs, if any
|
# assign docs, if any
|
||||||
if 'name' in attrs and self.doc_comment_last_symbol == attrs['name']:
|
if "name" in attrs and self.doc_comment_last_symbol == attrs["name"]:
|
||||||
self._cur_object.doc_string = self.doc_comment_body
|
self._cur_object.doc_string = self.doc_comment_body
|
||||||
if 'short_description' in self.doc_comment_params:
|
if "short_description" in self.doc_comment_params:
|
||||||
short_description = self.doc_comment_params['short_description']
|
short_description = self.doc_comment_params["short_description"]
|
||||||
self._cur_object.doc_string_brief = short_description
|
self._cur_object.doc_string_brief = short_description
|
||||||
if 'since' in self.doc_comment_params:
|
if "since" in self.doc_comment_params:
|
||||||
self._cur_object.since = \
|
self._cur_object.since = self.doc_comment_params["since"].strip()
|
||||||
self.doc_comment_params['since'].strip()
|
|
||||||
|
|
||||||
elif self.state == DBusXMLParser.STATE_INTERFACE:
|
elif self.state == DBusXMLParser.STATE_INTERFACE:
|
||||||
if name == DBusXMLParser.STATE_METHOD:
|
if name == DBusXMLParser.STATE_METHOD:
|
||||||
self.state = DBusXMLParser.STATE_METHOD
|
self.state = DBusXMLParser.STATE_METHOD
|
||||||
method = dbustypes.Method(attrs['name'],
|
method = dbustypes.Method(
|
||||||
h_type_implies_unix_fd=self._h_type_implies_unix_fd)
|
attrs["name"], h_type_implies_unix_fd=self._h_type_implies_unix_fd
|
||||||
|
)
|
||||||
self._cur_object.methods.append(method)
|
self._cur_object.methods.append(method)
|
||||||
self._cur_object = method
|
self._cur_object = method
|
||||||
elif name == DBusXMLParser.STATE_SIGNAL:
|
elif name == DBusXMLParser.STATE_SIGNAL:
|
||||||
self.state = DBusXMLParser.STATE_SIGNAL
|
self.state = DBusXMLParser.STATE_SIGNAL
|
||||||
signal = dbustypes.Signal(attrs['name'])
|
signal = dbustypes.Signal(attrs["name"])
|
||||||
self._cur_object.signals.append(signal)
|
self._cur_object.signals.append(signal)
|
||||||
self._cur_object = signal
|
self._cur_object = signal
|
||||||
elif name == DBusXMLParser.STATE_PROPERTY:
|
elif name == DBusXMLParser.STATE_PROPERTY:
|
||||||
self.state = DBusXMLParser.STATE_PROPERTY
|
self.state = DBusXMLParser.STATE_PROPERTY
|
||||||
prop = dbustypes.Property(attrs['name'], attrs['type'], attrs['access'])
|
prop = dbustypes.Property(attrs["name"], attrs["type"], attrs["access"])
|
||||||
self._cur_object.properties.append(prop)
|
self._cur_object.properties.append(prop)
|
||||||
self._cur_object = prop
|
self._cur_object = prop
|
||||||
elif name == DBusXMLParser.STATE_ANNOTATION:
|
elif name == DBusXMLParser.STATE_ANNOTATION:
|
||||||
self.state = DBusXMLParser.STATE_ANNOTATION
|
self.state = DBusXMLParser.STATE_ANNOTATION
|
||||||
anno = dbustypes.Annotation(attrs['name'], attrs['value'])
|
anno = dbustypes.Annotation(attrs["name"], attrs["value"])
|
||||||
self._cur_object.annotations.append(anno)
|
self._cur_object.annotations.append(anno)
|
||||||
self._cur_object = anno
|
self._cur_object = anno
|
||||||
else:
|
else:
|
||||||
self.state = DBusXMLParser.STATE_IGNORED
|
self.state = DBusXMLParser.STATE_IGNORED
|
||||||
|
|
||||||
# assign docs, if any
|
# assign docs, if any
|
||||||
if 'name' in attrs and self.doc_comment_last_symbol == attrs['name']:
|
if "name" in attrs and self.doc_comment_last_symbol == attrs["name"]:
|
||||||
self._cur_object.doc_string = self.doc_comment_body
|
self._cur_object.doc_string = self.doc_comment_body
|
||||||
if 'since' in self.doc_comment_params:
|
if "since" in self.doc_comment_params:
|
||||||
self._cur_object.since = \
|
self._cur_object.since = self.doc_comment_params["since"].strip()
|
||||||
self.doc_comment_params['since'].strip()
|
|
||||||
|
|
||||||
elif self.state == DBusXMLParser.STATE_METHOD:
|
elif self.state == DBusXMLParser.STATE_METHOD:
|
||||||
if name == DBusXMLParser.STATE_ARG:
|
if name == DBusXMLParser.STATE_ARG:
|
||||||
self.state = DBusXMLParser.STATE_ARG
|
self.state = DBusXMLParser.STATE_ARG
|
||||||
arg_name = None
|
arg_name = None
|
||||||
if 'name' in attrs:
|
if "name" in attrs:
|
||||||
arg_name = attrs['name']
|
arg_name = attrs["name"]
|
||||||
arg = dbustypes.Arg(arg_name, attrs['type'])
|
arg = dbustypes.Arg(arg_name, attrs["type"])
|
||||||
direction = attrs.get('direction', 'in')
|
direction = attrs.get("direction", "in")
|
||||||
if direction == 'in':
|
if direction == "in":
|
||||||
self._cur_object.in_args.append(arg)
|
self._cur_object.in_args.append(arg)
|
||||||
elif direction == 'out':
|
elif direction == "out":
|
||||||
self._cur_object.out_args.append(arg)
|
self._cur_object.out_args.append(arg)
|
||||||
else:
|
else:
|
||||||
print_error('Invalid direction "{}"'.format(direction))
|
print_error('Invalid direction "{}"'.format(direction))
|
||||||
self._cur_object = arg
|
self._cur_object = arg
|
||||||
elif name == DBusXMLParser.STATE_ANNOTATION:
|
elif name == DBusXMLParser.STATE_ANNOTATION:
|
||||||
self.state = DBusXMLParser.STATE_ANNOTATION
|
self.state = DBusXMLParser.STATE_ANNOTATION
|
||||||
anno = dbustypes.Annotation(attrs['name'], attrs['value'])
|
anno = dbustypes.Annotation(attrs["name"], attrs["value"])
|
||||||
self._cur_object.annotations.append(anno)
|
self._cur_object.annotations.append(anno)
|
||||||
self._cur_object = anno
|
self._cur_object = anno
|
||||||
else:
|
else:
|
||||||
@ -219,26 +219,27 @@ class DBusXMLParser:
|
|||||||
|
|
||||||
# assign docs, if any
|
# assign docs, if any
|
||||||
if self.doc_comment_last_symbol == old_cur_object.name:
|
if self.doc_comment_last_symbol == old_cur_object.name:
|
||||||
if 'name' in attrs and attrs['name'] in self.doc_comment_params:
|
if "name" in attrs and attrs["name"] in self.doc_comment_params:
|
||||||
doc_string = self.doc_comment_params[attrs['name']]
|
doc_string = self.doc_comment_params[attrs["name"]]
|
||||||
if doc_string != None:
|
if doc_string is not None:
|
||||||
self._cur_object.doc_string = doc_string
|
self._cur_object.doc_string = doc_string
|
||||||
if 'since' in self.doc_comment_params:
|
if "since" in self.doc_comment_params:
|
||||||
self._cur_object.since = \
|
self._cur_object.since = self.doc_comment_params[
|
||||||
self.doc_comment_params['since'].strip()
|
"since"
|
||||||
|
].strip()
|
||||||
|
|
||||||
elif self.state == DBusXMLParser.STATE_SIGNAL:
|
elif self.state == DBusXMLParser.STATE_SIGNAL:
|
||||||
if name == DBusXMLParser.STATE_ARG:
|
if name == DBusXMLParser.STATE_ARG:
|
||||||
self.state = DBusXMLParser.STATE_ARG
|
self.state = DBusXMLParser.STATE_ARG
|
||||||
arg_name = None
|
arg_name = None
|
||||||
if 'name' in attrs:
|
if "name" in attrs:
|
||||||
arg_name = attrs['name']
|
arg_name = attrs["name"]
|
||||||
arg = dbustypes.Arg(arg_name, attrs['type'])
|
arg = dbustypes.Arg(arg_name, attrs["type"])
|
||||||
self._cur_object.args.append(arg)
|
self._cur_object.args.append(arg)
|
||||||
self._cur_object = arg
|
self._cur_object = arg
|
||||||
elif name == DBusXMLParser.STATE_ANNOTATION:
|
elif name == DBusXMLParser.STATE_ANNOTATION:
|
||||||
self.state = DBusXMLParser.STATE_ANNOTATION
|
self.state = DBusXMLParser.STATE_ANNOTATION
|
||||||
anno = dbustypes.Annotation(attrs['name'], attrs['value'])
|
anno = dbustypes.Annotation(attrs["name"], attrs["value"])
|
||||||
self._cur_object.annotations.append(anno)
|
self._cur_object.annotations.append(anno)
|
||||||
self._cur_object = anno
|
self._cur_object = anno
|
||||||
else:
|
else:
|
||||||
@ -246,18 +247,19 @@ class DBusXMLParser:
|
|||||||
|
|
||||||
# assign docs, if any
|
# assign docs, if any
|
||||||
if self.doc_comment_last_symbol == old_cur_object.name:
|
if self.doc_comment_last_symbol == old_cur_object.name:
|
||||||
if 'name' in attrs and attrs['name'] in self.doc_comment_params:
|
if "name" in attrs and attrs["name"] in self.doc_comment_params:
|
||||||
doc_string = self.doc_comment_params[attrs['name']]
|
doc_string = self.doc_comment_params[attrs["name"]]
|
||||||
if doc_string != None:
|
if doc_string is not None:
|
||||||
self._cur_object.doc_string = doc_string
|
self._cur_object.doc_string = doc_string
|
||||||
if 'since' in self.doc_comment_params:
|
if "since" in self.doc_comment_params:
|
||||||
self._cur_object.since = \
|
self._cur_object.since = self.doc_comment_params[
|
||||||
self.doc_comment_params['since'].strip()
|
"since"
|
||||||
|
].strip()
|
||||||
|
|
||||||
elif self.state == DBusXMLParser.STATE_PROPERTY:
|
elif self.state == DBusXMLParser.STATE_PROPERTY:
|
||||||
if name == DBusXMLParser.STATE_ANNOTATION:
|
if name == DBusXMLParser.STATE_ANNOTATION:
|
||||||
self.state = DBusXMLParser.STATE_ANNOTATION
|
self.state = DBusXMLParser.STATE_ANNOTATION
|
||||||
anno = dbustypes.Annotation(attrs['name'], attrs['value'])
|
anno = dbustypes.Annotation(attrs["name"], attrs["value"])
|
||||||
self._cur_object.annotations.append(anno)
|
self._cur_object.annotations.append(anno)
|
||||||
self._cur_object = anno
|
self._cur_object = anno
|
||||||
else:
|
else:
|
||||||
@ -266,7 +268,7 @@ class DBusXMLParser:
|
|||||||
elif self.state == DBusXMLParser.STATE_ARG:
|
elif self.state == DBusXMLParser.STATE_ARG:
|
||||||
if name == DBusXMLParser.STATE_ANNOTATION:
|
if name == DBusXMLParser.STATE_ANNOTATION:
|
||||||
self.state = DBusXMLParser.STATE_ANNOTATION
|
self.state = DBusXMLParser.STATE_ANNOTATION
|
||||||
anno = dbustypes.Annotation(attrs['name'], attrs['value'])
|
anno = dbustypes.Annotation(attrs["name"], attrs["value"])
|
||||||
self._cur_object.annotations.append(anno)
|
self._cur_object.annotations.append(anno)
|
||||||
self._cur_object = anno
|
self._cur_object = anno
|
||||||
else:
|
else:
|
||||||
@ -275,14 +277,18 @@ class DBusXMLParser:
|
|||||||
elif self.state == DBusXMLParser.STATE_ANNOTATION:
|
elif self.state == DBusXMLParser.STATE_ANNOTATION:
|
||||||
if name == DBusXMLParser.STATE_ANNOTATION:
|
if name == DBusXMLParser.STATE_ANNOTATION:
|
||||||
self.state = DBusXMLParser.STATE_ANNOTATION
|
self.state = DBusXMLParser.STATE_ANNOTATION
|
||||||
anno = dbustypes.Annotation(attrs['name'], attrs['value'])
|
anno = dbustypes.Annotation(attrs["name"], attrs["value"])
|
||||||
self._cur_object.annotations.append(anno)
|
self._cur_object.annotations.append(anno)
|
||||||
self._cur_object = anno
|
self._cur_object = anno
|
||||||
else:
|
else:
|
||||||
self.state = DBusXMLParser.STATE_IGNORED
|
self.state = DBusXMLParser.STATE_IGNORED
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print_error('Unhandled state "{}" while entering element with name "{}"'.format(self.state, name))
|
print_error(
|
||||||
|
'Unhandled state "{}" while entering element with name "{}"'.format(
|
||||||
|
self.state, name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
self.state_stack.append(old_state)
|
self.state_stack.append(old_state)
|
||||||
self._cur_object_stack.append(old_cur_object)
|
self._cur_object_stack.append(old_cur_object)
|
||||||
@ -291,6 +297,7 @@ class DBusXMLParser:
|
|||||||
self.state = self.state_stack.pop()
|
self.state = self.state_stack.pop()
|
||||||
self._cur_object = self._cur_object_stack.pop()
|
self._cur_object = self._cur_object_stack.pop()
|
||||||
|
|
||||||
|
|
||||||
def parse_dbus_xml(xml_data, h_type_implies_unix_fd):
|
def parse_dbus_xml(xml_data, h_type_implies_unix_fd):
|
||||||
parser = DBusXMLParser(xml_data, h_type_implies_unix_fd)
|
parser = DBusXMLParser(xml_data, h_type_implies_unix_fd)
|
||||||
return parser.parsed_interfaces
|
return parser.parsed_interfaces
|
||||||
|
@ -23,49 +23,58 @@ import distutils.version
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
class Color:
|
class Color:
|
||||||
'''ANSI Terminal colors'''
|
"""ANSI Terminal colors"""
|
||||||
GREEN = '\033[1;32m'
|
|
||||||
BLUE = '\033[1;34m'
|
|
||||||
YELLOW = '\033[1;33m'
|
|
||||||
RED = '\033[1;31m'
|
|
||||||
END = '\033[0m'
|
|
||||||
|
|
||||||
def print_color(msg, color=Color.END, prefix='MESSAGE'):
|
GREEN = "\033[1;32m"
|
||||||
'''Print a string with a color prefix'''
|
BLUE = "\033[1;34m"
|
||||||
|
YELLOW = "\033[1;33m"
|
||||||
|
RED = "\033[1;31m"
|
||||||
|
END = "\033[0m"
|
||||||
|
|
||||||
|
|
||||||
|
def print_color(msg, color=Color.END, prefix="MESSAGE"):
|
||||||
|
"""Print a string with a color prefix"""
|
||||||
if os.isatty(sys.stderr.fileno()):
|
if os.isatty(sys.stderr.fileno()):
|
||||||
real_prefix = '{start}{prefix}{end}'.format(start=color, prefix=prefix, end=Color.END)
|
real_prefix = "{start}{prefix}{end}".format(
|
||||||
|
start=color, prefix=prefix, end=Color.END
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
real_prefix = prefix
|
real_prefix = prefix
|
||||||
sys.stderr.write('{prefix}: {msg}\n'.format(prefix=real_prefix, msg=msg))
|
sys.stderr.write("{prefix}: {msg}\n".format(prefix=real_prefix, msg=msg))
|
||||||
|
|
||||||
|
|
||||||
def print_error(msg):
|
def print_error(msg):
|
||||||
'''Print an error, and terminate'''
|
"""Print an error, and terminate"""
|
||||||
print_color(msg, color=Color.RED, prefix='ERROR')
|
print_color(msg, color=Color.RED, prefix="ERROR")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
def print_warning(msg, fatal=False):
|
def print_warning(msg, fatal=False):
|
||||||
'''Print a warning, and optionally terminate'''
|
"""Print a warning, and optionally terminate"""
|
||||||
if fatal:
|
if fatal:
|
||||||
color = Color.RED
|
color = Color.RED
|
||||||
prefix = 'ERROR'
|
prefix = "ERROR"
|
||||||
else:
|
else:
|
||||||
color = Color.YELLOW
|
color = Color.YELLOW
|
||||||
prefix = 'WARNING'
|
prefix = "WARNING"
|
||||||
print_color(msg, color, prefix)
|
print_color(msg, color, prefix)
|
||||||
if fatal:
|
if fatal:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
def print_info(msg):
|
def print_info(msg):
|
||||||
'''Print a message'''
|
"""Print a message"""
|
||||||
print_color(msg, color=Color.GREEN, prefix='INFO')
|
print_color(msg, color=Color.GREEN, prefix="INFO")
|
||||||
|
|
||||||
|
|
||||||
def strip_dots(s):
|
def strip_dots(s):
|
||||||
ret = ''
|
ret = ""
|
||||||
force_upper = False
|
force_upper = False
|
||||||
for c in s:
|
for c in s:
|
||||||
if c == '.':
|
if c == ".":
|
||||||
force_upper = True
|
force_upper = True
|
||||||
else:
|
else:
|
||||||
if force_upper:
|
if force_upper:
|
||||||
@ -75,19 +84,21 @@ def strip_dots(s):
|
|||||||
ret += c
|
ret += c
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def dots_to_hyphens(s):
|
def dots_to_hyphens(s):
|
||||||
return s.replace('.', '-')
|
return s.replace(".", "-")
|
||||||
|
|
||||||
|
|
||||||
def camel_case_to_uscore(s):
|
def camel_case_to_uscore(s):
|
||||||
ret = ''
|
ret = ""
|
||||||
insert_uscore = False
|
insert_uscore = False
|
||||||
prev_was_lower = False
|
prev_was_lower = False
|
||||||
initial = True;
|
initial = True
|
||||||
for c in s:
|
for c in s:
|
||||||
# Keep initial underscores in camel case
|
# Keep initial underscores in camel case
|
||||||
if initial and c == '_':
|
if initial and c == "_":
|
||||||
ret += '_'
|
ret += "_"
|
||||||
continue;
|
continue
|
||||||
initial = False
|
initial = False
|
||||||
|
|
||||||
if c.isupper():
|
if c.isupper():
|
||||||
@ -97,16 +108,18 @@ def camel_case_to_uscore(s):
|
|||||||
else:
|
else:
|
||||||
prev_was_lower = True
|
prev_was_lower = True
|
||||||
if insert_uscore:
|
if insert_uscore:
|
||||||
ret += '_'
|
ret += "_"
|
||||||
ret += c.lower()
|
ret += c.lower()
|
||||||
insert_uscore = False
|
insert_uscore = False
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def is_ugly_case(s):
|
def is_ugly_case(s):
|
||||||
if s and s.find('_') > 0:
|
if s and s.find("_") > 0:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def lookup_annotation(annotations, key):
|
def lookup_annotation(annotations, key):
|
||||||
if annotations:
|
if annotations:
|
||||||
for a in annotations:
|
for a in annotations:
|
||||||
@ -114,35 +127,39 @@ def lookup_annotation(annotations, key):
|
|||||||
return a.value
|
return a.value
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def lookup_docs(annotations):
|
def lookup_docs(annotations):
|
||||||
s = lookup_annotation(annotations, 'org.gtk.GDBus.DocString')
|
s = lookup_annotation(annotations, "org.gtk.GDBus.DocString")
|
||||||
if s is None:
|
if s is None:
|
||||||
return ''
|
return ""
|
||||||
else:
|
else:
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
def lookup_since(annotations):
|
def lookup_since(annotations):
|
||||||
s = lookup_annotation(annotations, 'org.gtk.GDBus.Since')
|
s = lookup_annotation(annotations, "org.gtk.GDBus.Since")
|
||||||
if s is None:
|
if s is None:
|
||||||
return ''
|
return ""
|
||||||
else:
|
else:
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
def lookup_brief_docs(annotations):
|
def lookup_brief_docs(annotations):
|
||||||
s = lookup_annotation(annotations, 'org.gtk.GDBus.DocString.Short')
|
s = lookup_annotation(annotations, "org.gtk.GDBus.DocString.Short")
|
||||||
if s is None:
|
if s is None:
|
||||||
return ''
|
return ""
|
||||||
else:
|
else:
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
def version_cmp_key(key):
|
def version_cmp_key(key):
|
||||||
# If the 'since' version is 'UNRELEASED', compare higher than anything else
|
# If the 'since' version is 'UNRELEASED', compare higher than anything else
|
||||||
# If it is empty put a 0 in its place as this will
|
# If it is empty put a 0 in its place as this will
|
||||||
# allow LooseVersion to work and will always compare lower.
|
# allow LooseVersion to work and will always compare lower.
|
||||||
if key[0] == 'UNRELEASED':
|
if key[0] == "UNRELEASED":
|
||||||
v = '9999'
|
v = "9999"
|
||||||
elif key[0]:
|
elif key[0]:
|
||||||
v = str(key[0])
|
v = str(key[0])
|
||||||
else:
|
else:
|
||||||
v = '0'
|
v = "0"
|
||||||
return (distutils.version.LooseVersion(v), key[1])
|
return (distutils.version.LooseVersion(v), key[1])
|
||||||
|
@ -4,6 +4,6 @@ import os
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
if not os.environ.get('DESTDIR'):
|
if not os.environ.get("DESTDIR"):
|
||||||
print('GIO module cache creation...')
|
print("GIO module cache creation...")
|
||||||
subprocess.call([sys.argv[1], sys.argv[2]])
|
subprocess.call([sys.argv[1], sys.argv[2]])
|
||||||
|
@ -26,13 +26,16 @@ import shutil
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import textwrap
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
import taptestrunner
|
import taptestrunner
|
||||||
|
|
||||||
|
|
||||||
Result = collections.namedtuple('Result', ('info', 'out', 'err', 'subs'))
|
# Disable line length warnings as wrapping the C code templates would be hard
|
||||||
|
# flake8: noqa: E501
|
||||||
|
|
||||||
|
|
||||||
|
Result = collections.namedtuple("Result", ("info", "out", "err", "subs"))
|
||||||
|
|
||||||
|
|
||||||
class TestCodegen(unittest.TestCase):
|
class TestCodegen(unittest.TestCase):
|
||||||
@ -47,22 +50,27 @@ class TestCodegen(unittest.TestCase):
|
|||||||
parsing and generation code of gdbus-codegen into separate unit tests, and
|
parsing and generation code of gdbus-codegen into separate unit tests, and
|
||||||
just test command line behaviour in this integration test.
|
just test command line behaviour in this integration test.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Track the cwd, we want to back out to that to clean up our tempdir
|
# Track the cwd, we want to back out to that to clean up our tempdir
|
||||||
cwd = ''
|
cwd = ""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.timeout_seconds = 10 # seconds per test
|
self.timeout_seconds = 10 # seconds per test
|
||||||
self.tmpdir = tempfile.TemporaryDirectory()
|
self.tmpdir = tempfile.TemporaryDirectory()
|
||||||
self.cwd = os.getcwd()
|
self.cwd = os.getcwd()
|
||||||
os.chdir(self.tmpdir.name)
|
os.chdir(self.tmpdir.name)
|
||||||
print('tmpdir:', self.tmpdir.name)
|
print("tmpdir:", self.tmpdir.name)
|
||||||
if 'G_TEST_BUILDDIR' in os.environ:
|
if "G_TEST_BUILDDIR" in os.environ:
|
||||||
self.__codegen = \
|
self.__codegen = os.path.join(
|
||||||
os.path.join(os.environ['G_TEST_BUILDDIR'], '..',
|
os.environ["G_TEST_BUILDDIR"],
|
||||||
'gdbus-2.0', 'codegen', 'gdbus-codegen')
|
"..",
|
||||||
|
"gdbus-2.0",
|
||||||
|
"codegen",
|
||||||
|
"gdbus-codegen",
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.__codegen = shutil.which('gdbus-codegen')
|
self.__codegen = shutil.which("gdbus-codegen")
|
||||||
print('codegen:', self.__codegen)
|
print("codegen:", self.__codegen)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
os.chdir(self.cwd)
|
os.chdir(self.cwd)
|
||||||
@ -73,201 +81,200 @@ class TestCodegen(unittest.TestCase):
|
|||||||
|
|
||||||
# shebang lines are not supported on native
|
# shebang lines are not supported on native
|
||||||
# Windows consoles
|
# Windows consoles
|
||||||
if os.name == 'nt':
|
if os.name == "nt":
|
||||||
argv.insert(0, sys.executable)
|
argv.insert(0, sys.executable)
|
||||||
|
|
||||||
argv.extend(args)
|
argv.extend(args)
|
||||||
print('Running:', argv)
|
print("Running:", argv)
|
||||||
|
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
env['LC_ALL'] = 'C.UTF-8'
|
env["LC_ALL"] = "C.UTF-8"
|
||||||
print('Environment:', env)
|
print("Environment:", env)
|
||||||
|
|
||||||
# We want to ensure consistent line endings...
|
# We want to ensure consistent line endings...
|
||||||
info = subprocess.run(argv, timeout=self.timeout_seconds,
|
info = subprocess.run(
|
||||||
|
argv,
|
||||||
|
timeout=self.timeout_seconds,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
env=env,
|
env=env,
|
||||||
universal_newlines=True)
|
universal_newlines=True,
|
||||||
|
)
|
||||||
info.check_returncode()
|
info.check_returncode()
|
||||||
out = info.stdout.strip()
|
out = info.stdout.strip()
|
||||||
err = info.stderr.strip()
|
err = info.stderr.strip()
|
||||||
|
|
||||||
# Known substitutions for standard boilerplate
|
# Known substitutions for standard boilerplate
|
||||||
subs = {
|
subs = {
|
||||||
'standard_top_comment':
|
"standard_top_comment": "/*\n"
|
||||||
'/*\n'
|
" * This file is generated by gdbus-codegen, do not modify it.\n"
|
||||||
' * This file is generated by gdbus-codegen, do not modify it.\n'
|
" *\n"
|
||||||
' *\n'
|
" * The license of this code is the same as for the D-Bus interface description\n"
|
||||||
' * The license of this code is the same as for the D-Bus interface description\n'
|
" * it was derived from. Note that it links to GLib, so must comply with the\n"
|
||||||
' * it was derived from. Note that it links to GLib, so must comply with the\n'
|
" * LGPL linking clauses.\n"
|
||||||
' * LGPL linking clauses.\n'
|
" */",
|
||||||
' */',
|
"standard_config_h_include": "#ifdef HAVE_CONFIG_H\n"
|
||||||
'standard_config_h_include':
|
|
||||||
'#ifdef HAVE_CONFIG_H\n'
|
|
||||||
'# include "config.h"\n'
|
'# include "config.h"\n'
|
||||||
'#endif',
|
"#endif",
|
||||||
'standard_header_includes':
|
"standard_header_includes": "#include <string.h>\n"
|
||||||
'#include <string.h>\n'
|
"#ifdef G_OS_UNIX\n"
|
||||||
'#ifdef G_OS_UNIX\n'
|
"# include <gio/gunixfdlist.h>\n"
|
||||||
'# include <gio/gunixfdlist.h>\n'
|
"#endif",
|
||||||
'#endif',
|
"standard_typedefs_and_helpers": "typedef struct\n"
|
||||||
'standard_typedefs_and_helpers':
|
"{\n"
|
||||||
'typedef struct\n'
|
" GDBusArgInfo parent_struct;\n"
|
||||||
'{\n'
|
" gboolean use_gvariant;\n"
|
||||||
' GDBusArgInfo parent_struct;\n'
|
"} _ExtendedGDBusArgInfo;\n"
|
||||||
' gboolean use_gvariant;\n'
|
"\n"
|
||||||
'} _ExtendedGDBusArgInfo;\n'
|
"typedef struct\n"
|
||||||
'\n'
|
"{\n"
|
||||||
'typedef struct\n'
|
" GDBusMethodInfo parent_struct;\n"
|
||||||
'{\n'
|
" const gchar *signal_name;\n"
|
||||||
' GDBusMethodInfo parent_struct;\n'
|
" gboolean pass_fdlist;\n"
|
||||||
' const gchar *signal_name;\n'
|
"} _ExtendedGDBusMethodInfo;\n"
|
||||||
' gboolean pass_fdlist;\n'
|
"\n"
|
||||||
'} _ExtendedGDBusMethodInfo;\n'
|
"typedef struct\n"
|
||||||
'\n'
|
"{\n"
|
||||||
'typedef struct\n'
|
" GDBusSignalInfo parent_struct;\n"
|
||||||
'{\n'
|
" const gchar *signal_name;\n"
|
||||||
' GDBusSignalInfo parent_struct;\n'
|
"} _ExtendedGDBusSignalInfo;\n"
|
||||||
' const gchar *signal_name;\n'
|
"\n"
|
||||||
'} _ExtendedGDBusSignalInfo;\n'
|
"typedef struct\n"
|
||||||
'\n'
|
"{\n"
|
||||||
'typedef struct\n'
|
" GDBusPropertyInfo parent_struct;\n"
|
||||||
'{\n'
|
" const gchar *hyphen_name;\n"
|
||||||
' GDBusPropertyInfo parent_struct;\n'
|
" guint use_gvariant : 1;\n"
|
||||||
' const gchar *hyphen_name;\n'
|
" guint emits_changed_signal : 1;\n"
|
||||||
' guint use_gvariant : 1;\n'
|
"} _ExtendedGDBusPropertyInfo;\n"
|
||||||
' guint emits_changed_signal : 1;\n'
|
"\n"
|
||||||
'} _ExtendedGDBusPropertyInfo;\n'
|
"typedef struct\n"
|
||||||
'\n'
|
"{\n"
|
||||||
'typedef struct\n'
|
" GDBusInterfaceInfo parent_struct;\n"
|
||||||
'{\n'
|
" const gchar *hyphen_name;\n"
|
||||||
' GDBusInterfaceInfo parent_struct;\n'
|
"} _ExtendedGDBusInterfaceInfo;\n"
|
||||||
' const gchar *hyphen_name;\n'
|
"\n"
|
||||||
'} _ExtendedGDBusInterfaceInfo;\n'
|
"typedef struct\n"
|
||||||
'\n'
|
"{\n"
|
||||||
'typedef struct\n'
|
" const _ExtendedGDBusPropertyInfo *info;\n"
|
||||||
'{\n'
|
" guint prop_id;\n"
|
||||||
' const _ExtendedGDBusPropertyInfo *info;\n'
|
" GValue orig_value; /* the value before the change */\n"
|
||||||
' guint prop_id;\n'
|
"} ChangedProperty;\n"
|
||||||
' GValue orig_value; /* the value before the change */\n'
|
"\n"
|
||||||
'} ChangedProperty;\n'
|
"static void\n"
|
||||||
'\n'
|
"_changed_property_free (ChangedProperty *data)\n"
|
||||||
'static void\n'
|
"{\n"
|
||||||
'_changed_property_free (ChangedProperty *data)\n'
|
" g_value_unset (&data->orig_value);\n"
|
||||||
'{\n'
|
" g_free (data);\n"
|
||||||
' g_value_unset (&data->orig_value);\n'
|
"}\n"
|
||||||
' g_free (data);\n'
|
"\n"
|
||||||
'}\n'
|
"static gboolean\n"
|
||||||
'\n'
|
"_g_strv_equal0 (gchar **a, gchar **b)\n"
|
||||||
'static gboolean\n'
|
"{\n"
|
||||||
'_g_strv_equal0 (gchar **a, gchar **b)\n'
|
" gboolean ret = FALSE;\n"
|
||||||
'{\n'
|
" guint n;\n"
|
||||||
' gboolean ret = FALSE;\n'
|
" if (a == NULL && b == NULL)\n"
|
||||||
' guint n;\n'
|
" {\n"
|
||||||
' if (a == NULL && b == NULL)\n'
|
" ret = TRUE;\n"
|
||||||
' {\n'
|
" goto out;\n"
|
||||||
' ret = TRUE;\n'
|
" }\n"
|
||||||
' goto out;\n'
|
" if (a == NULL || b == NULL)\n"
|
||||||
' }\n'
|
" goto out;\n"
|
||||||
' if (a == NULL || b == NULL)\n'
|
" if (g_strv_length (a) != g_strv_length (b))\n"
|
||||||
' goto out;\n'
|
" goto out;\n"
|
||||||
' if (g_strv_length (a) != g_strv_length (b))\n'
|
" for (n = 0; a[n] != NULL; n++)\n"
|
||||||
' goto out;\n'
|
" if (g_strcmp0 (a[n], b[n]) != 0)\n"
|
||||||
' for (n = 0; a[n] != NULL; n++)\n'
|
" goto out;\n"
|
||||||
' if (g_strcmp0 (a[n], b[n]) != 0)\n'
|
" ret = TRUE;\n"
|
||||||
' goto out;\n'
|
"out:\n"
|
||||||
' ret = TRUE;\n'
|
" return ret;\n"
|
||||||
'out:\n'
|
"}\n"
|
||||||
' return ret;\n'
|
"\n"
|
||||||
'}\n'
|
"static gboolean\n"
|
||||||
'\n'
|
"_g_variant_equal0 (GVariant *a, GVariant *b)\n"
|
||||||
'static gboolean\n'
|
"{\n"
|
||||||
'_g_variant_equal0 (GVariant *a, GVariant *b)\n'
|
" gboolean ret = FALSE;\n"
|
||||||
'{\n'
|
" if (a == NULL && b == NULL)\n"
|
||||||
' gboolean ret = FALSE;\n'
|
" {\n"
|
||||||
' if (a == NULL && b == NULL)\n'
|
" ret = TRUE;\n"
|
||||||
' {\n'
|
" goto out;\n"
|
||||||
' ret = TRUE;\n'
|
" }\n"
|
||||||
' goto out;\n'
|
" if (a == NULL || b == NULL)\n"
|
||||||
' }\n'
|
" goto out;\n"
|
||||||
' if (a == NULL || b == NULL)\n'
|
" ret = g_variant_equal (a, b);\n"
|
||||||
' goto out;\n'
|
"out:\n"
|
||||||
' ret = g_variant_equal (a, b);\n'
|
" return ret;\n"
|
||||||
'out:\n'
|
"}\n"
|
||||||
' return ret;\n'
|
"\n"
|
||||||
'}\n'
|
"G_GNUC_UNUSED static gboolean\n"
|
||||||
'\n'
|
"_g_value_equal (const GValue *a, const GValue *b)\n"
|
||||||
'G_GNUC_UNUSED static gboolean\n'
|
"{\n"
|
||||||
'_g_value_equal (const GValue *a, const GValue *b)\n'
|
" gboolean ret = FALSE;\n"
|
||||||
'{\n'
|
" g_assert (G_VALUE_TYPE (a) == G_VALUE_TYPE (b));\n"
|
||||||
' gboolean ret = FALSE;\n'
|
" switch (G_VALUE_TYPE (a))\n"
|
||||||
' g_assert (G_VALUE_TYPE (a) == G_VALUE_TYPE (b));\n'
|
" {\n"
|
||||||
' switch (G_VALUE_TYPE (a))\n'
|
" case G_TYPE_BOOLEAN:\n"
|
||||||
' {\n'
|
" ret = (g_value_get_boolean (a) == g_value_get_boolean (b));\n"
|
||||||
' case G_TYPE_BOOLEAN:\n'
|
" break;\n"
|
||||||
' ret = (g_value_get_boolean (a) == g_value_get_boolean (b));\n'
|
" case G_TYPE_UCHAR:\n"
|
||||||
' break;\n'
|
" ret = (g_value_get_uchar (a) == g_value_get_uchar (b));\n"
|
||||||
' case G_TYPE_UCHAR:\n'
|
" break;\n"
|
||||||
' ret = (g_value_get_uchar (a) == g_value_get_uchar (b));\n'
|
" case G_TYPE_INT:\n"
|
||||||
' break;\n'
|
" ret = (g_value_get_int (a) == g_value_get_int (b));\n"
|
||||||
' case G_TYPE_INT:\n'
|
" break;\n"
|
||||||
' ret = (g_value_get_int (a) == g_value_get_int (b));\n'
|
" case G_TYPE_UINT:\n"
|
||||||
' break;\n'
|
" ret = (g_value_get_uint (a) == g_value_get_uint (b));\n"
|
||||||
' case G_TYPE_UINT:\n'
|
" break;\n"
|
||||||
' ret = (g_value_get_uint (a) == g_value_get_uint (b));\n'
|
" case G_TYPE_INT64:\n"
|
||||||
' break;\n'
|
" ret = (g_value_get_int64 (a) == g_value_get_int64 (b));\n"
|
||||||
' case G_TYPE_INT64:\n'
|
" break;\n"
|
||||||
' ret = (g_value_get_int64 (a) == g_value_get_int64 (b));\n'
|
" case G_TYPE_UINT64:\n"
|
||||||
' break;\n'
|
" ret = (g_value_get_uint64 (a) == g_value_get_uint64 (b));\n"
|
||||||
' case G_TYPE_UINT64:\n'
|
" break;\n"
|
||||||
' ret = (g_value_get_uint64 (a) == g_value_get_uint64 (b));\n'
|
" case G_TYPE_DOUBLE:\n"
|
||||||
' break;\n'
|
" {\n"
|
||||||
' case G_TYPE_DOUBLE:\n'
|
" /* Avoid -Wfloat-equal warnings by doing a direct bit compare */\n"
|
||||||
' {\n'
|
" gdouble da = g_value_get_double (a);\n"
|
||||||
' /* Avoid -Wfloat-equal warnings by doing a direct bit compare */\n'
|
" gdouble db = g_value_get_double (b);\n"
|
||||||
' gdouble da = g_value_get_double (a);\n'
|
" ret = memcmp (&da, &db, sizeof (gdouble)) == 0;\n"
|
||||||
' gdouble db = g_value_get_double (b);\n'
|
" }\n"
|
||||||
' ret = memcmp (&da, &db, sizeof (gdouble)) == 0;\n'
|
" break;\n"
|
||||||
' }\n'
|
" case G_TYPE_STRING:\n"
|
||||||
' break;\n'
|
" ret = (g_strcmp0 (g_value_get_string (a), g_value_get_string (b)) == 0);\n"
|
||||||
' case G_TYPE_STRING:\n'
|
" break;\n"
|
||||||
' ret = (g_strcmp0 (g_value_get_string (a), g_value_get_string (b)) == 0);\n'
|
" case G_TYPE_VARIANT:\n"
|
||||||
' break;\n'
|
" ret = _g_variant_equal0 (g_value_get_variant (a), g_value_get_variant (b));\n"
|
||||||
' case G_TYPE_VARIANT:\n'
|
" break;\n"
|
||||||
' ret = _g_variant_equal0 (g_value_get_variant (a), g_value_get_variant (b));\n'
|
" default:\n"
|
||||||
' break;\n'
|
" if (G_VALUE_TYPE (a) == G_TYPE_STRV)\n"
|
||||||
' default:\n'
|
" ret = _g_strv_equal0 (g_value_get_boxed (a), g_value_get_boxed (b));\n"
|
||||||
' if (G_VALUE_TYPE (a) == G_TYPE_STRV)\n'
|
" else\n"
|
||||||
' ret = _g_strv_equal0 (g_value_get_boxed (a), g_value_get_boxed (b));\n'
|
|
||||||
' else\n'
|
|
||||||
' g_critical ("_g_value_equal() does not handle type %s", g_type_name (G_VALUE_TYPE (a)));\n'
|
' g_critical ("_g_value_equal() does not handle type %s", g_type_name (G_VALUE_TYPE (a)));\n'
|
||||||
' break;\n'
|
" break;\n"
|
||||||
' }\n'
|
" }\n"
|
||||||
' return ret;\n'
|
" return ret;\n"
|
||||||
'}',
|
"}",
|
||||||
}
|
}
|
||||||
|
|
||||||
result = Result(info, out, err, subs)
|
result = Result(info, out, err, subs)
|
||||||
|
|
||||||
print('Output:', result.out)
|
print("Output:", result.out)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def runCodegenWithInterface(self, interface_contents, *args):
|
def runCodegenWithInterface(self, interface_contents, *args):
|
||||||
with tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
|
with tempfile.NamedTemporaryFile(
|
||||||
suffix='.xml',
|
dir=self.tmpdir.name, suffix=".xml", delete=False
|
||||||
delete=False) as interface_file:
|
) as interface_file:
|
||||||
# Write out the interface.
|
# Write out the interface.
|
||||||
interface_file.write(interface_contents.encode('utf-8'))
|
interface_file.write(interface_contents.encode("utf-8"))
|
||||||
print(interface_file.name + ':', interface_contents)
|
print(interface_file.name + ":", interface_contents)
|
||||||
interface_file.flush()
|
interface_file.flush()
|
||||||
|
|
||||||
return self.runCodegen(interface_file.name, *args)
|
return self.runCodegen(interface_file.name, *args)
|
||||||
|
|
||||||
def test_help(self):
|
def test_help(self):
|
||||||
"""Test the --help argument."""
|
"""Test the --help argument."""
|
||||||
result = self.runCodegen('--help')
|
result = self.runCodegen("--help")
|
||||||
self.assertIn('usage: gdbus-codegen', result.out)
|
self.assertIn("usage: gdbus-codegen", result.out)
|
||||||
|
|
||||||
def test_no_args(self):
|
def test_no_args(self):
|
||||||
"""Test running with no arguments at all."""
|
"""Test running with no arguments at all."""
|
||||||
@ -276,11 +283,10 @@ class TestCodegen(unittest.TestCase):
|
|||||||
|
|
||||||
def test_empty_interface_header(self):
|
def test_empty_interface_header(self):
|
||||||
"""Test generating a header with an empty interface file."""
|
"""Test generating a header with an empty interface file."""
|
||||||
result = self.runCodegenWithInterface('',
|
result = self.runCodegenWithInterface("", "--output", "/dev/stdout", "--header")
|
||||||
'--output', '/dev/stdout',
|
self.assertEqual("", result.err)
|
||||||
'--header')
|
self.assertEqual(
|
||||||
self.assertEqual('', result.err)
|
"""{standard_top_comment}
|
||||||
self.assertEqual('''{standard_top_comment}
|
|
||||||
|
|
||||||
#ifndef __STDOUT__
|
#ifndef __STDOUT__
|
||||||
#define __STDOUT__
|
#define __STDOUT__
|
||||||
@ -292,16 +298,18 @@ G_BEGIN_DECLS
|
|||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __STDOUT__ */'''.format(**result.subs),
|
#endif /* __STDOUT__ */""".format(
|
||||||
result.out.strip())
|
**result.subs
|
||||||
|
),
|
||||||
|
result.out.strip(),
|
||||||
|
)
|
||||||
|
|
||||||
def test_empty_interface_body(self):
|
def test_empty_interface_body(self):
|
||||||
"""Test generating a body with an empty interface file."""
|
"""Test generating a body with an empty interface file."""
|
||||||
result = self.runCodegenWithInterface('',
|
result = self.runCodegenWithInterface("", "--output", "/dev/stdout", "--body")
|
||||||
'--output', '/dev/stdout',
|
self.assertEqual("", result.err)
|
||||||
'--body')
|
self.assertEqual(
|
||||||
self.assertEqual('', result.err)
|
"""{standard_top_comment}
|
||||||
self.assertEqual('''{standard_top_comment}
|
|
||||||
|
|
||||||
{standard_config_h_include}
|
{standard_config_h_include}
|
||||||
|
|
||||||
@ -309,12 +317,15 @@ G_END_DECLS
|
|||||||
|
|
||||||
{standard_header_includes}
|
{standard_header_includes}
|
||||||
|
|
||||||
{standard_typedefs_and_helpers}'''.format(**result.subs),
|
{standard_typedefs_and_helpers}""".format(
|
||||||
result.out.strip())
|
**result.subs
|
||||||
|
),
|
||||||
|
result.out.strip(),
|
||||||
|
)
|
||||||
|
|
||||||
def test_reproducible(self):
|
def test_reproducible(self):
|
||||||
"""Test builds are reproducible regardless of file ordering."""
|
"""Test builds are reproducible regardless of file ordering."""
|
||||||
xml_contents1 = '''
|
xml_contents1 = """
|
||||||
<node>
|
<node>
|
||||||
<interface name="com.acme.Coyote">
|
<interface name="com.acme.Coyote">
|
||||||
<method name="Run"/>
|
<method name="Run"/>
|
||||||
@ -324,40 +335,49 @@ G_END_DECLS
|
|||||||
<property name="Mood" type="s" access="read"/>
|
<property name="Mood" type="s" access="read"/>
|
||||||
</interface>
|
</interface>
|
||||||
</node>
|
</node>
|
||||||
'''
|
"""
|
||||||
|
|
||||||
xml_contents2 = '''
|
xml_contents2 = """
|
||||||
<node>
|
<node>
|
||||||
<interface name="org.project.Bar.Frobnicator">
|
<interface name="org.project.Bar.Frobnicator">
|
||||||
<method name="RandomMethod"/>
|
<method name="RandomMethod"/>
|
||||||
</interface>
|
</interface>
|
||||||
</node>
|
</node>
|
||||||
'''
|
"""
|
||||||
|
|
||||||
with tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
|
with tempfile.NamedTemporaryFile(
|
||||||
suffix='1.xml', delete=False) as xml_file1, \
|
dir=self.tmpdir.name, suffix="1.xml", delete=False
|
||||||
tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
|
) as xml_file1, tempfile.NamedTemporaryFile(
|
||||||
suffix='2.xml', delete=False) as xml_file2:
|
dir=self.tmpdir.name, suffix="2.xml", delete=False
|
||||||
|
) as xml_file2:
|
||||||
# Write out the interfaces.
|
# Write out the interfaces.
|
||||||
xml_file1.write(xml_contents1.encode('utf-8'))
|
xml_file1.write(xml_contents1.encode("utf-8"))
|
||||||
xml_file2.write(xml_contents2.encode('utf-8'))
|
xml_file2.write(xml_contents2.encode("utf-8"))
|
||||||
|
|
||||||
xml_file1.flush()
|
xml_file1.flush()
|
||||||
xml_file2.flush()
|
xml_file2.flush()
|
||||||
|
|
||||||
# Repeat this for headers and bodies.
|
# Repeat this for headers and bodies.
|
||||||
for header_or_body in ['--header', '--body']:
|
for header_or_body in ["--header", "--body"]:
|
||||||
# Run gdbus-codegen with the interfaces in one order, and then
|
# Run gdbus-codegen with the interfaces in one order, and then
|
||||||
# again in another order.
|
# again in another order.
|
||||||
result1 = self.runCodegen(xml_file1.name, xml_file2.name,
|
result1 = self.runCodegen(
|
||||||
'--output', '/dev/stdout',
|
xml_file1.name,
|
||||||
header_or_body)
|
xml_file2.name,
|
||||||
self.assertEqual('', result1.err)
|
"--output",
|
||||||
|
"/dev/stdout",
|
||||||
|
header_or_body,
|
||||||
|
)
|
||||||
|
self.assertEqual("", result1.err)
|
||||||
|
|
||||||
result2 = self.runCodegen(xml_file2.name, xml_file1.name,
|
result2 = self.runCodegen(
|
||||||
'--output', '/dev/stdout',
|
xml_file2.name,
|
||||||
header_or_body)
|
xml_file1.name,
|
||||||
self.assertEqual('', result2.err)
|
"--output",
|
||||||
|
"/dev/stdout",
|
||||||
|
header_or_body,
|
||||||
|
)
|
||||||
|
self.assertEqual("", result2.err)
|
||||||
|
|
||||||
# The output should be the same.
|
# The output should be the same.
|
||||||
self.assertEqual(result1.out, result2.out)
|
self.assertEqual(result1.out, result2.out)
|
||||||
@ -365,94 +385,108 @@ G_END_DECLS
|
|||||||
def test_glib_min_required_invalid(self):
|
def test_glib_min_required_invalid(self):
|
||||||
"""Test running with an invalid --glib-min-required."""
|
"""Test running with an invalid --glib-min-required."""
|
||||||
with self.assertRaises(subprocess.CalledProcessError):
|
with self.assertRaises(subprocess.CalledProcessError):
|
||||||
self.runCodegenWithInterface('',
|
self.runCodegenWithInterface(
|
||||||
'--output', '/dev/stdout',
|
"",
|
||||||
'--body',
|
"--output",
|
||||||
'--glib-min-required', 'hello mum')
|
"/dev/stdout",
|
||||||
|
"--body",
|
||||||
|
"--glib-min-required",
|
||||||
|
"hello mum",
|
||||||
|
)
|
||||||
|
|
||||||
def test_glib_min_required_too_low(self):
|
def test_glib_min_required_too_low(self):
|
||||||
"""Test running with a --glib-min-required which is too low (and hence
|
"""Test running with a --glib-min-required which is too low (and hence
|
||||||
probably a typo)."""
|
probably a typo)."""
|
||||||
with self.assertRaises(subprocess.CalledProcessError):
|
with self.assertRaises(subprocess.CalledProcessError):
|
||||||
self.runCodegenWithInterface('',
|
self.runCodegenWithInterface(
|
||||||
'--output', '/dev/stdout',
|
"", "--output", "/dev/stdout", "--body", "--glib-min-required", "2.6"
|
||||||
'--body',
|
)
|
||||||
'--glib-min-required', '2.6')
|
|
||||||
|
|
||||||
def test_glib_min_required_major_only(self):
|
def test_glib_min_required_major_only(self):
|
||||||
"""Test running with a --glib-min-required which contains only a major version."""
|
"""Test running with a --glib-min-required which contains only a major version."""
|
||||||
result = self.runCodegenWithInterface('',
|
result = self.runCodegenWithInterface(
|
||||||
'--output', '/dev/stdout',
|
"",
|
||||||
'--header',
|
"--output",
|
||||||
'--glib-min-required', '3',
|
"/dev/stdout",
|
||||||
'--glib-max-allowed', '3.2')
|
"--header",
|
||||||
self.assertEqual('', result.err)
|
"--glib-min-required",
|
||||||
self.assertNotEqual('', result.out.strip())
|
"3",
|
||||||
|
"--glib-max-allowed",
|
||||||
|
"3.2",
|
||||||
|
)
|
||||||
|
self.assertEqual("", result.err)
|
||||||
|
self.assertNotEqual("", result.out.strip())
|
||||||
|
|
||||||
def test_glib_min_required_with_micro(self):
|
def test_glib_min_required_with_micro(self):
|
||||||
"""Test running with a --glib-min-required which contains a micro version."""
|
"""Test running with a --glib-min-required which contains a micro version."""
|
||||||
result = self.runCodegenWithInterface('',
|
result = self.runCodegenWithInterface(
|
||||||
'--output', '/dev/stdout',
|
"", "--output", "/dev/stdout", "--header", "--glib-min-required", "2.46.2"
|
||||||
'--header',
|
)
|
||||||
'--glib-min-required', '2.46.2')
|
self.assertEqual("", result.err)
|
||||||
self.assertEqual('', result.err)
|
self.assertNotEqual("", result.out.strip())
|
||||||
self.assertNotEqual('', result.out.strip())
|
|
||||||
|
|
||||||
def test_glib_max_allowed_too_low(self):
|
def test_glib_max_allowed_too_low(self):
|
||||||
"""Test running with a --glib-max-allowed which is too low (and hence
|
"""Test running with a --glib-max-allowed which is too low (and hence
|
||||||
probably a typo)."""
|
probably a typo)."""
|
||||||
with self.assertRaises(subprocess.CalledProcessError):
|
with self.assertRaises(subprocess.CalledProcessError):
|
||||||
self.runCodegenWithInterface('',
|
self.runCodegenWithInterface(
|
||||||
'--output', '/dev/stdout',
|
"", "--output", "/dev/stdout", "--body", "--glib-max-allowed", "2.6"
|
||||||
'--body',
|
)
|
||||||
'--glib-max-allowed', '2.6')
|
|
||||||
|
|
||||||
def test_glib_max_allowed_major_only(self):
|
def test_glib_max_allowed_major_only(self):
|
||||||
"""Test running with a --glib-max-allowed which contains only a major version."""
|
"""Test running with a --glib-max-allowed which contains only a major version."""
|
||||||
result = self.runCodegenWithInterface('',
|
result = self.runCodegenWithInterface(
|
||||||
'--output', '/dev/stdout',
|
"", "--output", "/dev/stdout", "--header", "--glib-max-allowed", "3"
|
||||||
'--header',
|
)
|
||||||
'--glib-max-allowed', '3')
|
self.assertEqual("", result.err)
|
||||||
self.assertEqual('', result.err)
|
self.assertNotEqual("", result.out.strip())
|
||||||
self.assertNotEqual('', result.out.strip())
|
|
||||||
|
|
||||||
def test_glib_max_allowed_with_micro(self):
|
def test_glib_max_allowed_with_micro(self):
|
||||||
"""Test running with a --glib-max-allowed which contains a micro version."""
|
"""Test running with a --glib-max-allowed which contains a micro version."""
|
||||||
result = self.runCodegenWithInterface('',
|
result = self.runCodegenWithInterface(
|
||||||
'--output', '/dev/stdout',
|
"", "--output", "/dev/stdout", "--header", "--glib-max-allowed", "2.46.2"
|
||||||
'--header',
|
)
|
||||||
'--glib-max-allowed', '2.46.2')
|
self.assertEqual("", result.err)
|
||||||
self.assertEqual('', result.err)
|
self.assertNotEqual("", result.out.strip())
|
||||||
self.assertNotEqual('', result.out.strip())
|
|
||||||
|
|
||||||
def test_glib_max_allowed_unstable(self):
|
def test_glib_max_allowed_unstable(self):
|
||||||
"""Test running with a --glib-max-allowed which is unstable. It should
|
"""Test running with a --glib-max-allowed which is unstable. It should
|
||||||
be rounded up to the next stable version number, and hence should not
|
be rounded up to the next stable version number, and hence should not
|
||||||
end up less than --glib-min-required."""
|
end up less than --glib-min-required."""
|
||||||
result = self.runCodegenWithInterface('',
|
result = self.runCodegenWithInterface(
|
||||||
'--output', '/dev/stdout',
|
"",
|
||||||
'--header',
|
"--output",
|
||||||
'--glib-max-allowed', '2.63',
|
"/dev/stdout",
|
||||||
'--glib-min-required', '2.64')
|
"--header",
|
||||||
self.assertEqual('', result.err)
|
"--glib-max-allowed",
|
||||||
self.assertNotEqual('', result.out.strip())
|
"2.63",
|
||||||
|
"--glib-min-required",
|
||||||
|
"2.64",
|
||||||
|
)
|
||||||
|
self.assertEqual("", result.err)
|
||||||
|
self.assertNotEqual("", result.out.strip())
|
||||||
|
|
||||||
def test_glib_max_allowed_less_than_min_required(self):
|
def test_glib_max_allowed_less_than_min_required(self):
|
||||||
"""Test running with a --glib-max-allowed which is less than
|
"""Test running with a --glib-max-allowed which is less than
|
||||||
--glib-min-required."""
|
--glib-min-required."""
|
||||||
with self.assertRaises(subprocess.CalledProcessError):
|
with self.assertRaises(subprocess.CalledProcessError):
|
||||||
self.runCodegenWithInterface('',
|
self.runCodegenWithInterface(
|
||||||
'--output', '/dev/stdout',
|
"",
|
||||||
'--body',
|
"--output",
|
||||||
'--glib-max-allowed', '2.62',
|
"/dev/stdout",
|
||||||
'--glib-min-required', '2.64')
|
"--body",
|
||||||
|
"--glib-max-allowed",
|
||||||
|
"2.62",
|
||||||
|
"--glib-min-required",
|
||||||
|
"2.64",
|
||||||
|
)
|
||||||
|
|
||||||
def test_unix_fd_types_and_annotations(self):
|
def test_unix_fd_types_and_annotations(self):
|
||||||
"""Test an interface with `h` arguments, no annotation, and GLib < 2.64.
|
"""Test an interface with `h` arguments, no annotation, and GLib < 2.64.
|
||||||
|
|
||||||
See issue #1726.
|
See issue #1726.
|
||||||
"""
|
"""
|
||||||
interface_xml = '''
|
interface_xml = """
|
||||||
<node>
|
<node>
|
||||||
<interface name="FDPassing">
|
<interface name="FDPassing">
|
||||||
<method name="HelloFD">
|
<method name="HelloFD">
|
||||||
@ -470,71 +504,87 @@ G_END_DECLS
|
|||||||
<arg name="files" type="a{sh}" direction="in"/>
|
<arg name="files" type="a{sh}" direction="in"/>
|
||||||
</method>
|
</method>
|
||||||
</interface>
|
</interface>
|
||||||
</node>'''
|
</node>"""
|
||||||
|
|
||||||
# Try without specifying --glib-min-required.
|
# Try without specifying --glib-min-required.
|
||||||
result = self.runCodegenWithInterface(interface_xml,
|
result = self.runCodegenWithInterface(
|
||||||
'--output', '/dev/stdout',
|
interface_xml, "--output", "/dev/stdout", "--header"
|
||||||
'--header')
|
)
|
||||||
self.assertEqual('', result.err)
|
self.assertEqual("", result.err)
|
||||||
self.assertEqual(result.out.strip().count('GUnixFDList'), 6)
|
self.assertEqual(result.out.strip().count("GUnixFDList"), 6)
|
||||||
|
|
||||||
# Specify an old --glib-min-required.
|
# Specify an old --glib-min-required.
|
||||||
result = self.runCodegenWithInterface(interface_xml,
|
result = self.runCodegenWithInterface(
|
||||||
'--output', '/dev/stdout',
|
interface_xml,
|
||||||
'--header',
|
"--output",
|
||||||
'--glib-min-required', '2.32')
|
"/dev/stdout",
|
||||||
self.assertEqual('', result.err)
|
"--header",
|
||||||
self.assertEqual(result.out.strip().count('GUnixFDList'), 6)
|
"--glib-min-required",
|
||||||
|
"2.32",
|
||||||
|
)
|
||||||
|
self.assertEqual("", result.err)
|
||||||
|
self.assertEqual(result.out.strip().count("GUnixFDList"), 6)
|
||||||
|
|
||||||
# Specify a --glib-min-required ≥ 2.64. There should be more
|
# Specify a --glib-min-required ≥ 2.64. There should be more
|
||||||
# mentions of `GUnixFDList` now, since the annotation is not needed to
|
# mentions of `GUnixFDList` now, since the annotation is not needed to
|
||||||
# trigger its use.
|
# trigger its use.
|
||||||
result = self.runCodegenWithInterface(interface_xml,
|
result = self.runCodegenWithInterface(
|
||||||
'--output', '/dev/stdout',
|
interface_xml,
|
||||||
'--header',
|
"--output",
|
||||||
'--glib-min-required', '2.64')
|
"/dev/stdout",
|
||||||
self.assertEqual('', result.err)
|
"--header",
|
||||||
self.assertEqual(result.out.strip().count('GUnixFDList'), 18)
|
"--glib-min-required",
|
||||||
|
"2.64",
|
||||||
|
)
|
||||||
|
self.assertEqual("", result.err)
|
||||||
|
self.assertEqual(result.out.strip().count("GUnixFDList"), 18)
|
||||||
|
|
||||||
def test_call_flags_and_timeout_method_args(self):
|
def test_call_flags_and_timeout_method_args(self):
|
||||||
"""Test that generated method call functions have @call_flags and
|
"""Test that generated method call functions have @call_flags and
|
||||||
@timeout_msec args if and only if GLib >= 2.64.
|
@timeout_msec args if and only if GLib >= 2.64.
|
||||||
"""
|
"""
|
||||||
interface_xml = '''
|
interface_xml = """
|
||||||
<node>
|
<node>
|
||||||
<interface name="org.project.UsefulInterface">
|
<interface name="org.project.UsefulInterface">
|
||||||
<method name="UsefulMethod"/>
|
<method name="UsefulMethod"/>
|
||||||
</interface>
|
</interface>
|
||||||
</node>'''
|
</node>"""
|
||||||
|
|
||||||
# Try without specifying --glib-min-required.
|
# Try without specifying --glib-min-required.
|
||||||
result = self.runCodegenWithInterface(interface_xml,
|
result = self.runCodegenWithInterface(
|
||||||
'--output', '/dev/stdout',
|
interface_xml, "--output", "/dev/stdout", "--header"
|
||||||
'--header')
|
)
|
||||||
self.assertEqual('', result.err)
|
self.assertEqual("", result.err)
|
||||||
self.assertEqual(result.out.strip().count('GDBusCallFlags call_flags,'), 0)
|
self.assertEqual(result.out.strip().count("GDBusCallFlags call_flags,"), 0)
|
||||||
self.assertEqual(result.out.strip().count('gint timeout_msec,'), 0)
|
self.assertEqual(result.out.strip().count("gint timeout_msec,"), 0)
|
||||||
|
|
||||||
# Specify an old --glib-min-required.
|
# Specify an old --glib-min-required.
|
||||||
result = self.runCodegenWithInterface(interface_xml,
|
result = self.runCodegenWithInterface(
|
||||||
'--output', '/dev/stdout',
|
interface_xml,
|
||||||
'--header',
|
"--output",
|
||||||
'--glib-min-required', '2.32')
|
"/dev/stdout",
|
||||||
self.assertEqual('', result.err)
|
"--header",
|
||||||
self.assertEqual(result.out.strip().count('GDBusCallFlags call_flags,'), 0)
|
"--glib-min-required",
|
||||||
self.assertEqual(result.out.strip().count('gint timeout_msec,'), 0)
|
"2.32",
|
||||||
|
)
|
||||||
|
self.assertEqual("", result.err)
|
||||||
|
self.assertEqual(result.out.strip().count("GDBusCallFlags call_flags,"), 0)
|
||||||
|
self.assertEqual(result.out.strip().count("gint timeout_msec,"), 0)
|
||||||
|
|
||||||
# Specify a --glib-min-required ≥ 2.64. The two arguments should be
|
# Specify a --glib-min-required ≥ 2.64. The two arguments should be
|
||||||
# present for both the async and sync method call functions.
|
# present for both the async and sync method call functions.
|
||||||
result = self.runCodegenWithInterface(interface_xml,
|
result = self.runCodegenWithInterface(
|
||||||
'--output', '/dev/stdout',
|
interface_xml,
|
||||||
'--header',
|
"--output",
|
||||||
'--glib-min-required', '2.64')
|
"/dev/stdout",
|
||||||
self.assertEqual('', result.err)
|
"--header",
|
||||||
self.assertEqual(result.out.strip().count('GDBusCallFlags call_flags,'), 2)
|
"--glib-min-required",
|
||||||
self.assertEqual(result.out.strip().count('gint timeout_msec,'), 2)
|
"2.64",
|
||||||
|
)
|
||||||
|
self.assertEqual("", result.err)
|
||||||
|
self.assertEqual(result.out.strip().count("GDBusCallFlags call_flags,"), 2)
|
||||||
|
self.assertEqual(result.out.strip().count("gint timeout_msec,"), 2)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
unittest.main(testRunner=taptestrunner.TAPTestRunner())
|
unittest.main(testRunner=taptestrunner.TAPTestRunner())
|
||||||
|
@ -8,14 +8,13 @@
|
|||||||
#
|
#
|
||||||
# See issue #1580
|
# See issue #1580
|
||||||
|
|
||||||
import io
|
|
||||||
import string
|
import string
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
if len(sys.argv) != 2:
|
if len(sys.argv) != 2:
|
||||||
raise SystemExit('Usage: %s <output-file>' % sys.argv[0])
|
raise SystemExit("Usage: %s <output-file>" % sys.argv[0])
|
||||||
|
|
||||||
with open(sys.argv[1], 'w', newline='\n') as f:
|
with open(sys.argv[1], "w", newline="\n") as f:
|
||||||
for count in range(12):
|
for count in range(12):
|
||||||
for c in string.ascii_lowercase:
|
for c in string.ascii_lowercase:
|
||||||
f.write("%s\n" % (c * 100))
|
f.write("%s\n" % (c * 100))
|
||||||
|
@ -5,7 +5,7 @@ import sys
|
|||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
|
|
||||||
debug = os.getenv('GIO_GENTYPEFUNCS_DEBUG') is not None
|
debug = os.getenv("GIO_GENTYPEFUNCS_DEBUG") is not None
|
||||||
|
|
||||||
out_file = sys.argv[1]
|
out_file = sys.argv[1]
|
||||||
in_files = sys.argv[2:]
|
in_files = sys.argv[2:]
|
||||||
@ -13,32 +13,37 @@ in_files = sys.argv[2:]
|
|||||||
funcs = []
|
funcs = []
|
||||||
|
|
||||||
|
|
||||||
if debug: print ('Output file: ', out_file)
|
if debug:
|
||||||
|
print("Output file: ", out_file)
|
||||||
|
|
||||||
if debug: print (len(in_files), 'input files')
|
if debug:
|
||||||
|
print(len(in_files), "input files")
|
||||||
|
|
||||||
for filename in in_files:
|
for filename in in_files:
|
||||||
if debug: print ('Input file: ', filename)
|
if debug:
|
||||||
with open(filename, 'rb') as f:
|
print("Input file: ", filename)
|
||||||
|
with open(filename, "rb") as f:
|
||||||
for line in f:
|
for line in f:
|
||||||
line = line.rstrip(b'\n').rstrip(b'\r')
|
line = line.rstrip(b"\n").rstrip(b"\r")
|
||||||
# print line
|
# print line
|
||||||
match = re.search(b'\bg_[a-zA-Z0-9_]*_get_type\b', line)
|
match = re.search(b"\bg_[a-zA-Z0-9_]*_get_type\b", line)
|
||||||
if match:
|
if match:
|
||||||
func = match.group(0)
|
func = match.group(0)
|
||||||
if not func in funcs:
|
if func not in funcs:
|
||||||
funcs.append(func)
|
funcs.append(func)
|
||||||
if debug: print ('Found ', func)
|
if debug:
|
||||||
|
print("Found ", func)
|
||||||
|
|
||||||
file_output = 'G_GNUC_BEGIN_IGNORE_DEPRECATIONS\n'
|
file_output = "G_GNUC_BEGIN_IGNORE_DEPRECATIONS\n"
|
||||||
|
|
||||||
funcs = sorted(funcs)
|
funcs = sorted(funcs)
|
||||||
|
|
||||||
for f in funcs:
|
for f in funcs:
|
||||||
if f not in ['g_io_extension_get_type', 'g_settings_backend_get_type']:
|
if f not in ["g_io_extension_get_type", "g_settings_backend_get_type"]:
|
||||||
file_output += '*tp++ = {0} ();\n'.format(f)
|
file_output += "*tp++ = {0} ();\n".format(f)
|
||||||
|
|
||||||
if debug: print (len(funcs), 'functions')
|
if debug:
|
||||||
|
print(len(funcs), "functions")
|
||||||
|
|
||||||
ofile = open(out_file, "w")
|
ofile = open(out_file, "w")
|
||||||
ofile.write(file_output)
|
ofile.write(file_output)
|
||||||
|
@ -23,29 +23,33 @@ import sys
|
|||||||
import tempfile
|
import tempfile
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
if not 'GLIB_TEST_COMPILATION' in os.environ:
|
if "GLIB_TEST_COMPILATION" not in os.environ:
|
||||||
print('''Test disabled because GLIB_TEST_COMPILATION is not set in the env.
|
print(
|
||||||
|
"""Test disabled because GLIB_TEST_COMPILATION is not set in the env.
|
||||||
If you wish to run this test, set GLIB_TEST_COMPILATION=1 in the env,
|
If you wish to run this test, set GLIB_TEST_COMPILATION=1 in the env,
|
||||||
and make sure you have glib build dependencies installed, including
|
and make sure you have glib build dependencies installed, including
|
||||||
meson.''')
|
meson."""
|
||||||
|
)
|
||||||
sys.exit(77)
|
sys.exit(77)
|
||||||
|
|
||||||
if len(sys.argv) != 2:
|
if len(sys.argv) != 2:
|
||||||
print('Usage: {} <gio-2.0.pc dir>'.format(os.path.basename(sys.argv[0])))
|
print("Usage: {} <gio-2.0.pc dir>".format(os.path.basename(sys.argv[0])))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
test_dir = os.path.dirname(sys.argv[0])
|
test_dir = os.path.dirname(sys.argv[0])
|
||||||
|
|
||||||
with tempfile.TemporaryDirectory() as builddir:
|
with tempfile.TemporaryDirectory() as builddir:
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
env['PKG_CONFIG_PATH'] = sys.argv[1]
|
env["PKG_CONFIG_PATH"] = sys.argv[1]
|
||||||
sourcedir = os.path.join(test_dir, 'static-link')
|
sourcedir = os.path.join(test_dir, "static-link")
|
||||||
|
|
||||||
# Ensure we can static link and run a test app
|
# Ensure we can static link and run a test app
|
||||||
subprocess.check_call(['meson', sourcedir, builddir], env=env)
|
subprocess.check_call(["meson", sourcedir, builddir], env=env)
|
||||||
subprocess.check_call(['ninja', '-C', builddir, 'test'], env=env)
|
subprocess.check_call(["ninja", "-C", builddir, "test"], env=env)
|
||||||
# FIXME: This probably only works on Linux
|
# FIXME: This probably only works on Linux
|
||||||
out = subprocess.check_output(['ldd', os.path.join(builddir, 'test-static-link')], env=env).decode()
|
out = subprocess.check_output(
|
||||||
if 'libgio' in out:
|
["ldd", os.path.join(builddir, "test-static-link")], env=env
|
||||||
print('test-static-link is dynamically linked on libgio')
|
).decode()
|
||||||
|
if "libgio" in out:
|
||||||
|
print("test-static-link is dynamically linked on libgio")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
@ -30,6 +30,7 @@ import sys
|
|||||||
import base64
|
import base64
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
|
|
||||||
# Log modes
|
# Log modes
|
||||||
class LogMode(object):
|
class LogMode(object):
|
||||||
LogToError, LogToDiagnostics, LogToYAML, LogToAttachment = range(4)
|
LogToError, LogToDiagnostics, LogToYAML, LogToAttachment = range(4)
|
||||||
@ -73,7 +74,6 @@ class TAPTestResult(unittest.TestResult):
|
|||||||
sys.stdout = self.orig_stdout
|
sys.stdout = self.orig_stdout
|
||||||
sys.stderr = self.orig_stderr
|
sys.stderr = self.orig_stderr
|
||||||
|
|
||||||
|
|
||||||
def print_raw(self, text):
|
def print_raw(self, text):
|
||||||
self.output_stream.write(text)
|
self.output_stream.write(text)
|
||||||
self.output_stream.flush()
|
self.output_stream.flush()
|
||||||
@ -101,7 +101,7 @@ class TAPTestResult(unittest.TestResult):
|
|||||||
else:
|
else:
|
||||||
logs = [
|
logs = [
|
||||||
(self.test_output_log, self.test_output, "test_output"),
|
(self.test_output_log, self.test_output, "test_output"),
|
||||||
(self.message_log, self.message, "message")
|
(self.message_log, self.message, "message"),
|
||||||
]
|
]
|
||||||
for log_mode, log, log_name in logs:
|
for log_mode, log, log_name in logs:
|
||||||
if log_mode != LogMode.LogToError:
|
if log_mode != LogMode.LogToError:
|
||||||
@ -110,17 +110,23 @@ class TAPTestResult(unittest.TestResult):
|
|||||||
if log_mode == LogMode.LogToYAML:
|
if log_mode == LogMode.LogToYAML:
|
||||||
self.print_raw(" ---\n")
|
self.print_raw(" ---\n")
|
||||||
self.print_raw(" " + log_name + ": |\n")
|
self.print_raw(" " + log_name + ": |\n")
|
||||||
self.print_raw(" " + output.rstrip().replace("\n", "\n ") + "\n")
|
self.print_raw(
|
||||||
|
" " + output.rstrip().replace("\n", "\n ") + "\n"
|
||||||
|
)
|
||||||
self.print_raw(" ...\n")
|
self.print_raw(" ...\n")
|
||||||
elif log_mode == LogMode.LogToAttachment:
|
elif log_mode == LogMode.LogToAttachment:
|
||||||
self.print_raw(" ---\n")
|
self.print_raw(" ---\n")
|
||||||
self.print_raw(" " + log_name + ":\n")
|
self.print_raw(" " + log_name + ":\n")
|
||||||
self.print_raw(" File-Name: " + log_name + ".txt\n")
|
self.print_raw(" File-Name: " + log_name + ".txt\n")
|
||||||
self.print_raw(" File-Type: text/plain\n")
|
self.print_raw(" File-Type: text/plain\n")
|
||||||
self.print_raw(" File-Content: " + base64.b64encode(output) + "\n")
|
self.print_raw(
|
||||||
|
" File-Content: " + base64.b64encode(output) + "\n"
|
||||||
|
)
|
||||||
self.print_raw(" ...\n")
|
self.print_raw(" ...\n")
|
||||||
else:
|
else:
|
||||||
self.print_raw("# " + output.rstrip().replace("\n", "\n# ") + "\n")
|
self.print_raw(
|
||||||
|
"# " + output.rstrip().replace("\n", "\n# ") + "\n"
|
||||||
|
)
|
||||||
# Truncate doesn't change the current stream position.
|
# Truncate doesn't change the current stream position.
|
||||||
# Seek to the beginning to avoid extensions on subsequent writes.
|
# Seek to the beginning to avoid extensions on subsequent writes.
|
||||||
log.seek(0)
|
log.seek(0)
|
||||||
@ -155,10 +161,13 @@ class TAPTestResult(unittest.TestResult):
|
|||||||
|
|
||||||
|
|
||||||
class TAPTestRunner(object):
|
class TAPTestRunner(object):
|
||||||
def __init__(self,
|
def __init__(
|
||||||
|
self,
|
||||||
message_log=LogMode.LogToYAML,
|
message_log=LogMode.LogToYAML,
|
||||||
test_output_log=LogMode.LogToDiagnostics,
|
test_output_log=LogMode.LogToDiagnostics,
|
||||||
output_stream = sys.stdout, error_stream = sys.stderr):
|
output_stream=sys.stdout,
|
||||||
|
error_stream=sys.stderr,
|
||||||
|
):
|
||||||
self.output_stream = output_stream
|
self.output_stream = output_stream
|
||||||
self.error_stream = error_stream
|
self.error_stream = error_stream
|
||||||
self.message_log = message_log
|
self.message_log = message_log
|
||||||
@ -169,7 +178,8 @@ class TAPTestRunner(object):
|
|||||||
self.output_stream,
|
self.output_stream,
|
||||||
self.error_stream,
|
self.error_stream,
|
||||||
self.message_log,
|
self.message_log,
|
||||||
self.test_output_log)
|
self.test_output_log,
|
||||||
|
)
|
||||||
test(result)
|
test(result)
|
||||||
result.printErrors()
|
result.printErrors()
|
||||||
|
|
||||||
|
@ -4,10 +4,12 @@ import sys
|
|||||||
if sys.version_info[0] >= 3:
|
if sys.version_info[0] >= 3:
|
||||||
long = int
|
long = int
|
||||||
|
|
||||||
|
|
||||||
# This is not quite right, as local vars may override symname
|
# This is not quite right, as local vars may override symname
|
||||||
def read_global_var(symname):
|
def read_global_var(symname):
|
||||||
return gdb.selected_frame().read_var(symname)
|
return gdb.selected_frame().read_var(symname)
|
||||||
|
|
||||||
|
|
||||||
def g_quark_to_string(quark):
|
def g_quark_to_string(quark):
|
||||||
if quark is None:
|
if quark is None:
|
||||||
return None
|
return None
|
||||||
@ -17,16 +19,17 @@ def g_quark_to_string (quark):
|
|||||||
try:
|
try:
|
||||||
val = read_global_var("quarks")
|
val = read_global_var("quarks")
|
||||||
max_q = long(read_global_var("quark_seq_id"))
|
max_q = long(read_global_var("quark_seq_id"))
|
||||||
except:
|
except Exception:
|
||||||
try:
|
try:
|
||||||
val = read_global_var("g_quarks")
|
val = read_global_var("g_quarks")
|
||||||
max_q = long(read_global_var("g_quark_seq_id"))
|
max_q = long(read_global_var("g_quark_seq_id"))
|
||||||
except:
|
except Exception:
|
||||||
return None;
|
return None
|
||||||
if quark < max_q:
|
if quark < max_q:
|
||||||
return val[quark].string()
|
return val[quark].string()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
# We override the node printers too, so that node->next is not expanded
|
# We override the node printers too, so that node->next is not expanded
|
||||||
class GListNodePrinter:
|
class GListNodePrinter:
|
||||||
"Prints a GList node"
|
"Prints a GList node"
|
||||||
@ -35,7 +38,12 @@ class GListNodePrinter:
|
|||||||
self.val = val
|
self.val = val
|
||||||
|
|
||||||
def to_string(self):
|
def to_string(self):
|
||||||
return "{data=%s, next=0x%x, prev=0x%x}" % (str(self.val["data"]), long(self.val["next"]), long(self.val["prev"]))
|
return "{data=%s, next=0x%x, prev=0x%x}" % (
|
||||||
|
str(self.val["data"]),
|
||||||
|
long(self.val["next"]),
|
||||||
|
long(self.val["prev"]),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class GSListNodePrinter:
|
class GSListNodePrinter:
|
||||||
"Prints a GSList node"
|
"Prints a GSList node"
|
||||||
@ -46,6 +54,7 @@ class GSListNodePrinter:
|
|||||||
def to_string(self):
|
def to_string(self):
|
||||||
return "{data=%s, next=0x%x}" % (str(self.val["data"]), long(self.val["next"]))
|
return "{data=%s, next=0x%x}" % (str(self.val["data"]), long(self.val["next"]))
|
||||||
|
|
||||||
|
|
||||||
class GListPrinter:
|
class GListPrinter:
|
||||||
"Prints a GList"
|
"Prints a GList"
|
||||||
|
|
||||||
@ -61,11 +70,11 @@ class GListPrinter:
|
|||||||
def next(self):
|
def next(self):
|
||||||
if self.link == 0:
|
if self.link == 0:
|
||||||
raise StopIteration
|
raise StopIteration
|
||||||
data = self.link['data']
|
data = self.link["data"]
|
||||||
self.link = self.link['next']
|
self.link = self.link["next"]
|
||||||
count = self.count
|
count = self.count
|
||||||
self.count = self.count + 1
|
self.count = self.count + 1
|
||||||
return ('[%d]' % count, data)
|
return ("[%d]" % count, data)
|
||||||
|
|
||||||
__next__ = next
|
__next__ = next
|
||||||
|
|
||||||
@ -82,6 +91,7 @@ class GListPrinter:
|
|||||||
def display_hint(self):
|
def display_hint(self):
|
||||||
return "array"
|
return "array"
|
||||||
|
|
||||||
|
|
||||||
class GHashPrinter:
|
class GHashPrinter:
|
||||||
"Prints a GHashTable"
|
"Prints a GHashTable"
|
||||||
|
|
||||||
@ -90,7 +100,9 @@ class GHashPrinter:
|
|||||||
def __init__(self, ptr, big_items):
|
def __init__(self, ptr, big_items):
|
||||||
self._big_items = big_items
|
self._big_items = big_items
|
||||||
self._gpointer_type = gdb.lookup_type("gpointer")
|
self._gpointer_type = gdb.lookup_type("gpointer")
|
||||||
item_type = self._gpointer_type if self._big_items else gdb.lookup_type("guint")
|
item_type = (
|
||||||
|
self._gpointer_type if self._big_items else gdb.lookup_type("guint")
|
||||||
|
)
|
||||||
|
|
||||||
self._items = ptr.cast(item_type.pointer())
|
self._items = ptr.cast(item_type.pointer())
|
||||||
|
|
||||||
@ -119,7 +131,7 @@ class GHashPrinter:
|
|||||||
def next(self):
|
def next(self):
|
||||||
if self.ht == 0:
|
if self.ht == 0:
|
||||||
raise StopIteration
|
raise StopIteration
|
||||||
if self.value != None:
|
if self.value is not None:
|
||||||
v = self.value
|
v = self.value
|
||||||
self.value = None
|
self.value = None
|
||||||
return v
|
return v
|
||||||
@ -132,10 +144,10 @@ class GHashPrinter:
|
|||||||
key = key.cast(gdb.lookup_type("char").pointer())
|
key = key.cast(gdb.lookup_type("char").pointer())
|
||||||
|
|
||||||
# Queue value for next result
|
# Queue value for next result
|
||||||
self.value = ('[%dv]'% (self.pos), val)
|
self.value = ("[%dv]" % (self.pos), val)
|
||||||
|
|
||||||
# Increment pos and return key
|
# Increment pos and return key
|
||||||
key = ('[%dk]'% (self.pos), key)
|
key = ("[%dk]" % (self.pos), key)
|
||||||
self.pos += 1
|
self.pos += 1
|
||||||
return key
|
return key
|
||||||
|
|
||||||
@ -149,9 +161,13 @@ class GHashPrinter:
|
|||||||
self.keys_are_strings = False
|
self.keys_are_strings = False
|
||||||
try:
|
try:
|
||||||
string_hash = read_global_var("g_str_hash")
|
string_hash = read_global_var("g_str_hash")
|
||||||
except:
|
except Exception:
|
||||||
string_hash = None
|
string_hash = None
|
||||||
if self.val != 0 and string_hash != None and self.val["hash_func"] == string_hash:
|
if (
|
||||||
|
self.val != 0
|
||||||
|
and string_hash is not None
|
||||||
|
and self.val["hash_func"] == string_hash
|
||||||
|
):
|
||||||
self.keys_are_strings = True
|
self.keys_are_strings = True
|
||||||
|
|
||||||
def children(self):
|
def children(self):
|
||||||
@ -163,6 +179,7 @@ class GHashPrinter:
|
|||||||
def display_hint(self):
|
def display_hint(self):
|
||||||
return "map"
|
return "map"
|
||||||
|
|
||||||
|
|
||||||
def pretty_printer_lookup(val):
|
def pretty_printer_lookup(val):
|
||||||
# None yet, want things like hash table and list
|
# None yet, want things like hash table and list
|
||||||
|
|
||||||
@ -189,19 +206,21 @@ def pretty_printer_lookup (val):
|
|||||||
return GListPrinter(val, "GSList")
|
return GListPrinter(val, "GSList")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def register(obj):
|
def register(obj):
|
||||||
if obj is None:
|
if obj is None:
|
||||||
obj = gdb
|
obj = gdb
|
||||||
|
|
||||||
obj.pretty_printers.append(pretty_printer_lookup)
|
obj.pretty_printers.append(pretty_printer_lookup)
|
||||||
|
|
||||||
|
|
||||||
class ForeachCommand(gdb.Command):
|
class ForeachCommand(gdb.Command):
|
||||||
"""Foreach on list"""
|
"""Foreach on list"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super (ForeachCommand, self).__init__ ("gforeach",
|
super(ForeachCommand, self).__init__(
|
||||||
gdb.COMMAND_DATA,
|
"gforeach", gdb.COMMAND_DATA, gdb.COMPLETE_SYMBOL
|
||||||
gdb.COMPLETE_SYMBOL)
|
)
|
||||||
|
|
||||||
def valid_name(self, name):
|
def valid_name(self, name):
|
||||||
if not name[0].isalpha():
|
if not name[0].isalpha():
|
||||||
@ -249,16 +268,16 @@ class ForeachCommand (gdb.Command):
|
|||||||
gdb.execute(command)
|
gdb.execute(command)
|
||||||
|
|
||||||
def slist_iterator(self, arg, container, command):
|
def slist_iterator(self, arg, container, command):
|
||||||
l = container.cast (gdb.lookup_type("GSList").pointer())
|
list_element = container.cast(gdb.lookup_type("GSList").pointer())
|
||||||
while long(l) != 0:
|
while long(list_element) != 0:
|
||||||
self.do_iter (arg, l["data"], command)
|
self.do_iter(arg, list_element["data"], command)
|
||||||
l = l["next"]
|
list_element = list_element["next"]
|
||||||
|
|
||||||
def list_iterator(self, arg, container, command):
|
def list_iterator(self, arg, container, command):
|
||||||
l = container.cast (gdb.lookup_type("GList").pointer())
|
list_element = container.cast(gdb.lookup_type("GList").pointer())
|
||||||
while long(l) != 0:
|
while long(list_element) != 0:
|
||||||
self.do_iter (arg, l["data"], command)
|
self.do_iter(arg, list_element["data"], command)
|
||||||
l = l["next"]
|
list_element = list_element["next"]
|
||||||
|
|
||||||
def pick_iterator(self, container):
|
def pick_iterator(self, container):
|
||||||
t = container.type.unqualified()
|
t = container.type.unqualified()
|
||||||
@ -277,4 +296,5 @@ class ForeachCommand (gdb.Command):
|
|||||||
func = self.pick_iterator(container)
|
func = self.pick_iterator(container)
|
||||||
func(var, container, command)
|
func(var, container, command)
|
||||||
|
|
||||||
|
|
||||||
ForeachCommand()
|
ForeachCommand()
|
||||||
|
@ -4,21 +4,25 @@
|
|||||||
#
|
#
|
||||||
# ./update-gtranslit.py /path/to/glibc/localedata/locales > gtranslit-data.h
|
# ./update-gtranslit.py /path/to/glibc/localedata/locales > gtranslit-data.h
|
||||||
|
|
||||||
import sys, os
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
localedir = sys.argv[1]
|
localedir = sys.argv[1]
|
||||||
|
|
||||||
|
|
||||||
# returns true if the name looks like a POSIX locale name
|
# returns true if the name looks like a POSIX locale name
|
||||||
def looks_like_locale(name):
|
def looks_like_locale(name):
|
||||||
name, _, variant = name.partition('@')
|
name, _, variant = name.partition("@")
|
||||||
|
|
||||||
if '_' not in name:
|
if "_" not in name:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
lang, _, land = name.partition('_')
|
lang, _, land = name.partition("_")
|
||||||
|
|
||||||
return len(lang) == 2 or len(lang) == 3 and len(land) == 2
|
return len(lang) == 2 or len(lang) == 3 and len(land) == 2
|
||||||
|
|
||||||
|
|
||||||
# handles <U1234> style escapes
|
# handles <U1234> style escapes
|
||||||
def unescape(string):
|
def unescape(string):
|
||||||
chunks = []
|
chunks = []
|
||||||
@ -27,27 +31,29 @@ def unescape(string):
|
|||||||
i = 0
|
i = 0
|
||||||
|
|
||||||
while i < n:
|
while i < n:
|
||||||
start_escape = string.find('<', i)
|
start_escape = string.find("<", i)
|
||||||
|
|
||||||
if start_escape == -1:
|
if start_escape == -1:
|
||||||
chunks.append(string[i:])
|
chunks.append(string[i:])
|
||||||
break
|
break
|
||||||
|
|
||||||
assert string[start_escape:start_escape + 2] == '<U'
|
assert string[start_escape : (start_escape + 2)] == "<U"
|
||||||
start_escape += 2
|
start_escape += 2
|
||||||
|
|
||||||
end_escape = string.find('>', start_escape)
|
end_escape = string.find(">", start_escape)
|
||||||
assert end_escape != -1
|
assert end_escape != -1
|
||||||
|
|
||||||
chunks.append(chr(int(string[start_escape:end_escape], 16)))
|
chunks.append(chr(int(string[start_escape:end_escape], 16)))
|
||||||
i = end_escape + 1
|
i = end_escape + 1
|
||||||
|
|
||||||
return ''.join(chunks)
|
return "".join(chunks)
|
||||||
|
|
||||||
|
|
||||||
# Checks if a string is ascii
|
# Checks if a string is ascii
|
||||||
def is_ascii(string):
|
def is_ascii(string):
|
||||||
return all(ord(c) < 0x80 for c in string)
|
return all(ord(c) < 0x80 for c in string)
|
||||||
|
|
||||||
|
|
||||||
# A Mapping is a map from non-ascii strings to ascii strings.
|
# A Mapping is a map from non-ascii strings to ascii strings.
|
||||||
#
|
#
|
||||||
# It corresponds to a sequence of one or more mapping lines:
|
# It corresponds to a sequence of one or more mapping lines:
|
||||||
@ -62,31 +68,32 @@ class Mapping:
|
|||||||
|
|
||||||
# Scans a string like
|
# Scans a string like
|
||||||
#
|
#
|
||||||
# <U00C4> "<U0041><U0308>";"<U0041><U0045>" % LATIN CAPITAL LETTER A WITH DIAERESIS.
|
# <U00C4> "<U0041><U0308>";"<U0041><U0045>" % \
|
||||||
|
# LATIN CAPITAL LETTER A WITH DIAERESIS.
|
||||||
#
|
#
|
||||||
# and adds the first all-ascii choice (or IGNORE) to the mapping
|
# and adds the first all-ascii choice (or IGNORE) to the mapping
|
||||||
# dictionary, with the origin string as the key. In the case of
|
# dictionary, with the origin string as the key. In the case of
|
||||||
# IGNORE, stores the empty string.
|
# IGNORE, stores the empty string.
|
||||||
def consider_mapping_line(self, line):
|
def consider_mapping_line(self, line):
|
||||||
key, value, rest = (line + ' % comment').split(maxsplit=2)
|
key, value, rest = (line + " % comment").split(maxsplit=2)
|
||||||
|
|
||||||
key = unescape(key)
|
key = unescape(key)
|
||||||
|
|
||||||
for alternative in value.split(';'):
|
for alternative in value.split(";"):
|
||||||
if alternative[0] == '"' and alternative[-1] == '"':
|
if alternative[0] == '"' and alternative[-1] == '"':
|
||||||
unescaped = unescape(alternative[1:-1])
|
unescaped = unescape(alternative[1:-1])
|
||||||
if is_ascii(unescaped):
|
if is_ascii(unescaped):
|
||||||
self.mapping[key] = unescaped
|
self.mapping[key] = unescaped
|
||||||
break
|
break
|
||||||
|
|
||||||
elif alternative[0] == '<' and alternative[-1] == '>':
|
elif alternative[0] == "<" and alternative[-1] == ">":
|
||||||
unescaped = unescape(alternative)
|
unescaped = unescape(alternative)
|
||||||
if is_ascii(unescaped):
|
if is_ascii(unescaped):
|
||||||
self.mapping[key] = unescaped
|
self.mapping[key] = unescaped
|
||||||
break
|
break
|
||||||
|
|
||||||
elif alternative == 'IGNORE':
|
elif alternative == "IGNORE":
|
||||||
self.mapping[key] = ''
|
self.mapping[key] = ""
|
||||||
break
|
break
|
||||||
|
|
||||||
# Performs a normal dictionary merge, but ensures that there are no
|
# Performs a normal dictionary merge, but ensures that there are no
|
||||||
@ -109,6 +116,7 @@ class Mapping:
|
|||||||
|
|
||||||
return self.serialised
|
return self.serialised
|
||||||
|
|
||||||
|
|
||||||
# A Chain is a sequence of mappings and chains.
|
# A Chain is a sequence of mappings and chains.
|
||||||
#
|
#
|
||||||
# A chain contains another chain whenever "copy" or "include" is
|
# A chain contains another chain whenever "copy" or "include" is
|
||||||
@ -135,16 +143,16 @@ class Chain:
|
|||||||
in_lc_ctype = False
|
in_lc_ctype = False
|
||||||
in_translit = False
|
in_translit = False
|
||||||
|
|
||||||
fp = open(filename, encoding='ascii', errors='surrogateescape')
|
fp = open(filename, encoding="ascii", errors="surrogateescape")
|
||||||
|
|
||||||
for line in fp:
|
for line in fp:
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
|
|
||||||
if in_lc_ctype:
|
if in_lc_ctype:
|
||||||
if line == 'END LC_CTYPE':
|
if line == "END LC_CTYPE":
|
||||||
break
|
break
|
||||||
|
|
||||||
if line.startswith('copy') or line.startswith('include'):
|
if line.startswith("copy") or line.startswith("include"):
|
||||||
if current_mapping:
|
if current_mapping:
|
||||||
self.chain.append(current_mapping)
|
self.chain.append(current_mapping)
|
||||||
|
|
||||||
@ -155,29 +163,29 @@ class Chain:
|
|||||||
|
|
||||||
current_mapping = None
|
current_mapping = None
|
||||||
|
|
||||||
elif line == 'translit_start':
|
elif line == "translit_start":
|
||||||
in_translit = True
|
in_translit = True
|
||||||
|
|
||||||
elif line == 'translit_end':
|
elif line == "translit_end":
|
||||||
in_translit = False
|
in_translit = False
|
||||||
|
|
||||||
elif in_translit and line.startswith('<U'):
|
elif in_translit and line.startswith("<U"):
|
||||||
if not current_mapping:
|
if not current_mapping:
|
||||||
current_mapping = Mapping()
|
current_mapping = Mapping()
|
||||||
|
|
||||||
current_mapping.consider_mapping_line(line)
|
current_mapping.consider_mapping_line(line)
|
||||||
|
|
||||||
elif line == '' or line.startswith('%'):
|
elif line == "" or line.startswith("%"):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
elif 'default_missing <U003F>':
|
elif "default_missing <U003F>":
|
||||||
pass
|
pass
|
||||||
|
|
||||||
elif in_translit:
|
elif in_translit:
|
||||||
print('unknown line:', line)
|
print("unknown line:", line)
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
elif line == 'LC_CTYPE':
|
elif line == "LC_CTYPE":
|
||||||
in_lc_ctype = True
|
in_lc_ctype = True
|
||||||
|
|
||||||
if current_mapping:
|
if current_mapping:
|
||||||
@ -199,7 +207,9 @@ class Chain:
|
|||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
while i < len(self.chain) - 1:
|
while i < len(self.chain) - 1:
|
||||||
if isinstance(self.chain[i], Mapping) and isinstance(self.chain[i + 1], Mapping):
|
if isinstance(self.chain[i], Mapping) and isinstance(
|
||||||
|
self.chain[i + 1], Mapping
|
||||||
|
):
|
||||||
# We have two mappings in a row. Try to merge them.
|
# We have two mappings in a row. Try to merge them.
|
||||||
self.chain[i].merge_mapping(self.chain[i + 1])
|
self.chain[i].merge_mapping(self.chain[i + 1])
|
||||||
del self.chain[i + 1]
|
del self.chain[i + 1]
|
||||||
@ -215,10 +225,13 @@ class Chain:
|
|||||||
|
|
||||||
return self.serialised
|
return self.serialised
|
||||||
|
|
||||||
|
|
||||||
# Chain cache -- allows sharing of common chains
|
# Chain cache -- allows sharing of common chains
|
||||||
chains = {}
|
chains = {}
|
||||||
|
|
||||||
|
|
||||||
def get_chain(name):
|
def get_chain(name):
|
||||||
if not name in chains:
|
if name not in chains:
|
||||||
chains[name] = Chain(name)
|
chains[name] = Chain(name)
|
||||||
|
|
||||||
return chains[name]
|
return chains[name]
|
||||||
@ -227,10 +240,11 @@ def get_chain(name):
|
|||||||
# Remove the country name from a locale, preserving variant
|
# Remove the country name from a locale, preserving variant
|
||||||
# eg: 'sr_RS@latin' -> 'sr@latin'
|
# eg: 'sr_RS@latin' -> 'sr@latin'
|
||||||
def remove_country(string):
|
def remove_country(string):
|
||||||
base, at, variant = string.partition('@')
|
base, at, variant = string.partition("@")
|
||||||
lang, _, land = base.partition('_')
|
lang, _, land = base.partition("_")
|
||||||
return lang + at + variant
|
return lang + at + variant
|
||||||
|
|
||||||
|
|
||||||
def encode_range(start, end):
|
def encode_range(start, end):
|
||||||
assert start <= end
|
assert start <= end
|
||||||
length = end - start
|
length = end - start
|
||||||
@ -244,8 +258,10 @@ def encode_range(start, end):
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def c_pair_array(array):
|
def c_pair_array(array):
|
||||||
return '{ ' + ', '.join ('{ %u, %u }' % pair for pair in array) + ' };'
|
return "{ " + ", ".join("{ %u, %u }" % pair for pair in array) + " };"
|
||||||
|
|
||||||
|
|
||||||
class Serialiser:
|
class Serialiser:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -284,7 +300,9 @@ class Serialiser:
|
|||||||
languages = list(set(remove_country(locale) for locale in self.locales))
|
languages = list(set(remove_country(locale) for locale in self.locales))
|
||||||
|
|
||||||
for language in languages:
|
for language in languages:
|
||||||
locales = [locale for locale in self.locales if remove_country(locale) == language]
|
locales = [
|
||||||
|
locale for locale in self.locales if remove_country(locale) == language
|
||||||
|
]
|
||||||
|
|
||||||
item_id = self.locales[locales[0]]
|
item_id = self.locales[locales[0]]
|
||||||
if all(self.locales[locale] == item_id for locale in locales):
|
if all(self.locales[locale] == item_id for locale in locales):
|
||||||
@ -294,8 +312,8 @@ class Serialiser:
|
|||||||
|
|
||||||
# Check if a variant is the same as the non-variant form
|
# Check if a variant is the same as the non-variant form
|
||||||
# eg: 'de@euro' and 'de'
|
# eg: 'de@euro' and 'de'
|
||||||
for variant in list(locale for locale in self.locales if '@' in locale):
|
for variant in list(locale for locale in self.locales if "@" in locale):
|
||||||
base, _, _ = variant.partition('@')
|
base, _, _ = variant.partition("@")
|
||||||
if base in self.locales and self.locales[base] == self.locales[variant]:
|
if base in self.locales and self.locales[base] == self.locales[variant]:
|
||||||
del self.locales[variant]
|
del self.locales[variant]
|
||||||
|
|
||||||
@ -305,13 +323,13 @@ class Serialiser:
|
|||||||
del self.locales[locale]
|
del self.locales[locale]
|
||||||
|
|
||||||
def to_c(self):
|
def to_c(self):
|
||||||
src_table = ''
|
src_table = ""
|
||||||
ascii_table = ''
|
ascii_table = ""
|
||||||
mappings_table = []
|
mappings_table = []
|
||||||
mapping_ranges = []
|
mapping_ranges = []
|
||||||
chains_table = []
|
chains_table = []
|
||||||
chain_starts = []
|
chain_starts = []
|
||||||
locale_names = ''
|
locale_names = ""
|
||||||
locale_index = []
|
locale_index = []
|
||||||
max_lookup = 0
|
max_lookup = 0
|
||||||
max_localename = 0
|
max_localename = 0
|
||||||
@ -326,7 +344,7 @@ class Serialiser:
|
|||||||
existing = src_table.find(key)
|
existing = src_table.find(key)
|
||||||
if existing == -1:
|
if existing == -1:
|
||||||
start = len(src_table)
|
start = len(src_table)
|
||||||
assert all(ord(c) <= 0x10ffff for c in key)
|
assert all(ord(c) <= 0x10FFFF for c in key)
|
||||||
src_table += key
|
src_table += key
|
||||||
src_range = encode_range(start, len(src_table))
|
src_range = encode_range(start, len(src_table))
|
||||||
max_lookup = max(max_lookup, len(key))
|
max_lookup = max(max_lookup, len(key))
|
||||||
@ -348,21 +366,19 @@ class Serialiser:
|
|||||||
|
|
||||||
mappings_table.append((src_range, ascii_range))
|
mappings_table.append((src_range, ascii_range))
|
||||||
|
|
||||||
mapping_end = len(mappings_table)
|
|
||||||
|
|
||||||
for chain in self.chains:
|
for chain in self.chains:
|
||||||
chain_starts.append(len(chains_table))
|
chain_starts.append(len(chains_table))
|
||||||
|
|
||||||
for item_id in reversed(chain):
|
for item_id in reversed(chain):
|
||||||
assert item_id < 0xff
|
assert item_id < 0xFF
|
||||||
chains_table.append(item_id)
|
chains_table.append(item_id)
|
||||||
chains_table.append(0xff)
|
chains_table.append(0xFF)
|
||||||
|
|
||||||
for locale in sorted(self.locales):
|
for locale in sorted(self.locales):
|
||||||
max_localename = max(max_localename, len(locale))
|
max_localename = max(max_localename, len(locale))
|
||||||
name_offset = len(locale_names)
|
name_offset = len(locale_names)
|
||||||
assert all(ord(c) <= 0x7f for c in locale)
|
assert all(ord(c) <= 0x7F for c in locale)
|
||||||
locale_names += (locale + '\0')
|
locale_names += locale + "\0"
|
||||||
|
|
||||||
item_id = self.locales[locale]
|
item_id = self.locales[locale]
|
||||||
|
|
||||||
@ -370,25 +386,55 @@ class Serialiser:
|
|||||||
assert item_id < 256
|
assert item_id < 256
|
||||||
locale_index.append((name_offset, item_id))
|
locale_index.append((name_offset, item_id))
|
||||||
|
|
||||||
print('/* Generated by update-gtranslit.py */')
|
print("/* Generated by update-gtranslit.py */")
|
||||||
print('#define MAX_KEY_SIZE', max_lookup)
|
print("#define MAX_KEY_SIZE", max_lookup)
|
||||||
print('#define MAX_LOCALE_NAME', max_localename)
|
print("#define MAX_LOCALE_NAME", max_localename)
|
||||||
print('static const gunichar src_table[] = {', ', '.join(str(ord(c)) for c in src_table), '};')
|
print(
|
||||||
|
"static const gunichar src_table[] = {",
|
||||||
|
", ".join(str(ord(c)) for c in src_table),
|
||||||
|
"};",
|
||||||
|
)
|
||||||
# cannot do this in plain ascii because of trigraphs... :(
|
# cannot do this in plain ascii because of trigraphs... :(
|
||||||
print('static const gchar ascii_table[] = {', ', '.join(str(ord(c)) for c in ascii_table), '};')
|
print(
|
||||||
print('static const struct mapping_entry mappings_table[] =', c_pair_array (mappings_table))
|
"static const gchar ascii_table[] = {",
|
||||||
print('static const struct mapping_range mapping_ranges[] =', c_pair_array (mapping_ranges))
|
", ".join(str(ord(c)) for c in ascii_table),
|
||||||
print('static const guint8 chains_table[] = {', ', '.join(str(i) for i in chains_table), '};')
|
"};",
|
||||||
print('static const guint8 chain_starts[] = {', ', '.join(str(i) for i in chain_starts), '};')
|
)
|
||||||
print('static const gchar locale_names[] = "' + locale_names.replace('\0', '\\0') + '";')
|
print(
|
||||||
print('static const struct locale_entry locale_index[] = ', c_pair_array (locale_index))
|
"static const struct mapping_entry mappings_table[] =",
|
||||||
print('static const guint8 default_item_id = %u;' % (self.default,))
|
c_pair_array(mappings_table),
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
"static const struct mapping_range mapping_ranges[] =",
|
||||||
|
c_pair_array(mapping_ranges),
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
"static const guint8 chains_table[] = {",
|
||||||
|
", ".join(str(i) for i in chains_table),
|
||||||
|
"};",
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
"static const guint8 chain_starts[] = {",
|
||||||
|
", ".join(str(i) for i in chain_starts),
|
||||||
|
"};",
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
'static const gchar locale_names[] = "'
|
||||||
|
+ locale_names.replace("\0", "\\0")
|
||||||
|
+ '";'
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
"static const struct locale_entry locale_index[] = ",
|
||||||
|
c_pair_array(locale_index),
|
||||||
|
)
|
||||||
|
print("static const guint8 default_item_id = %u;" % (self.default,))
|
||||||
|
|
||||||
def dump(self):
|
def dump(self):
|
||||||
print(self.mappings)
|
print(self.mappings)
|
||||||
print(self.chains)
|
print(self.chains)
|
||||||
print(self.locales)
|
print(self.locales)
|
||||||
|
|
||||||
|
|
||||||
locales = []
|
locales = []
|
||||||
for name in os.listdir(localedir):
|
for name in os.listdir(localedir):
|
||||||
if looks_like_locale(name):
|
if looks_like_locale(name):
|
||||||
@ -401,8 +447,8 @@ serialiser = Serialiser()
|
|||||||
for locale in locales:
|
for locale in locales:
|
||||||
serialiser.add_locale(locale.name, locale.serialise(serialiser))
|
serialiser.add_locale(locale.name, locale.serialise(serialiser))
|
||||||
|
|
||||||
i18n = get_chain('i18n').serialise(serialiser)
|
i18n = get_chain("i18n").serialise(serialiser)
|
||||||
combining = get_chain('translit_combining').serialise(serialiser)
|
combining = get_chain("translit_combining").serialise(serialiser)
|
||||||
serialiser.add_default(serialiser.add_chain([i18n, combining]))
|
serialiser.add_default(serialiser.add_chain([i18n, combining]))
|
||||||
|
|
||||||
serialiser.optimise_locales()
|
serialiser.optimise_locales()
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import os.path
|
|
||||||
import gdb
|
import gdb
|
||||||
import glib_gdb
|
import glib_gdb
|
||||||
import sys
|
import sys
|
||||||
@ -7,20 +6,24 @@ if sys.version_info[0] >= 3:
|
|||||||
long = int
|
long = int
|
||||||
else:
|
else:
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
map = itertools.imap
|
map = itertools.imap
|
||||||
|
|
||||||
# FrameDecorator is new in gdb 7.7, so we adapt to its absence.
|
# FrameDecorator is new in gdb 7.7, so we adapt to its absence.
|
||||||
try:
|
try:
|
||||||
import gdb.FrameDecorator
|
import gdb.FrameDecorator
|
||||||
|
|
||||||
HAVE_GDB_FRAMEDECORATOR = True
|
HAVE_GDB_FRAMEDECORATOR = True
|
||||||
FrameDecorator = gdb.FrameDecorator.FrameDecorator
|
FrameDecorator = gdb.FrameDecorator.FrameDecorator
|
||||||
except ImportError:
|
except ImportError:
|
||||||
HAVE_GDB_FRAMEDECORATOR = False
|
HAVE_GDB_FRAMEDECORATOR = False
|
||||||
|
|
||||||
|
|
||||||
# This is not quite right, as local vars may override symname
|
# This is not quite right, as local vars may override symname
|
||||||
def read_global_var(symname):
|
def read_global_var(symname):
|
||||||
return gdb.selected_frame().read_var(symname)
|
return gdb.selected_frame().read_var(symname)
|
||||||
|
|
||||||
|
|
||||||
def g_type_to_typenode(gtype):
|
def g_type_to_typenode(gtype):
|
||||||
def lookup_fundamental_type(typenode):
|
def lookup_fundamental_type(typenode):
|
||||||
if typenode == 0:
|
if typenode == 0:
|
||||||
@ -38,12 +41,14 @@ def g_type_to_typenode (gtype):
|
|||||||
typenode = lookup_fundamental_type(typenode)
|
typenode = lookup_fundamental_type(typenode)
|
||||||
return typenode
|
return typenode
|
||||||
|
|
||||||
|
|
||||||
def g_type_to_name(gtype):
|
def g_type_to_name(gtype):
|
||||||
typenode = g_type_to_typenode(gtype)
|
typenode = g_type_to_typenode(gtype)
|
||||||
if typenode != None:
|
if typenode is not None:
|
||||||
return glib_gdb.g_quark_to_string(typenode["qname"])
|
return glib_gdb.g_quark_to_string(typenode["qname"])
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def is_g_type_instance(val):
|
def is_g_type_instance(val):
|
||||||
def is_g_type_instance_helper(type):
|
def is_g_type_instance_helper(type):
|
||||||
if str(type) == "GTypeInstance":
|
if str(type) == "GTypeInstance":
|
||||||
@ -68,6 +73,7 @@ def is_g_type_instance (val):
|
|||||||
type = type.target()
|
type = type.target()
|
||||||
return is_g_type_instance_helper(type)
|
return is_g_type_instance_helper(type)
|
||||||
|
|
||||||
|
|
||||||
def g_type_name_from_instance(instance):
|
def g_type_name_from_instance(instance):
|
||||||
if long(instance) != 0:
|
if long(instance) != 0:
|
||||||
try:
|
try:
|
||||||
@ -80,6 +86,7 @@ def g_type_name_from_instance (instance):
|
|||||||
pass
|
pass
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class GTypePrettyPrinter:
|
class GTypePrettyPrinter:
|
||||||
"Prints a GType instance pointer"
|
"Prints a GType instance pointer"
|
||||||
|
|
||||||
@ -92,12 +99,14 @@ class GTypePrettyPrinter:
|
|||||||
return ("0x%x [%s]") % (long(self.val), name)
|
return ("0x%x [%s]") % (long(self.val), name)
|
||||||
return ("0x%x") % (long(self.val))
|
return ("0x%x") % (long(self.val))
|
||||||
|
|
||||||
|
|
||||||
def is_g_type_class_instance(val):
|
def is_g_type_class_instance(val):
|
||||||
type = val.type
|
type = val.type
|
||||||
if type.code != gdb.TYPE_CODE_PTR:
|
if type.code != gdb.TYPE_CODE_PTR:
|
||||||
return False
|
return False
|
||||||
return str(type.target()) == "GTypeClass"
|
return str(type.target()) == "GTypeClass"
|
||||||
|
|
||||||
|
|
||||||
class GTypeHandlePrettyPrinter:
|
class GTypeHandlePrettyPrinter:
|
||||||
"Prints a GType instance"
|
"Prints a GType instance"
|
||||||
|
|
||||||
@ -107,7 +116,7 @@ class GTypeHandlePrettyPrinter:
|
|||||||
|
|
||||||
def to_string(self):
|
def to_string(self):
|
||||||
typenode = g_type_to_typenode(self.val)
|
typenode = g_type_to_typenode(self.val)
|
||||||
if typenode != None:
|
if typenode is not None:
|
||||||
name = glib_gdb.g_quark_to_string(typenode["qname"])
|
name = glib_gdb.g_quark_to_string(typenode["qname"])
|
||||||
s = ("0x%x [%s%s") % (long(self.val), self.hint, name)
|
s = ("0x%x [%s%s") % (long(self.val), self.hint, name)
|
||||||
for i in range(1, int(typenode["n_supers"])):
|
for i in range(1, int(typenode["n_supers"])):
|
||||||
@ -121,6 +130,7 @@ class GTypeHandlePrettyPrinter:
|
|||||||
else:
|
else:
|
||||||
return ("0x%x") % (long(self.val))
|
return ("0x%x") % (long(self.val))
|
||||||
|
|
||||||
|
|
||||||
def pretty_printer_lookup(val):
|
def pretty_printer_lookup(val):
|
||||||
if is_g_type_instance(val):
|
if is_g_type_instance(val):
|
||||||
return GTypePrettyPrinter(val)
|
return GTypePrettyPrinter(val)
|
||||||
@ -131,6 +141,7 @@ def pretty_printer_lookup (val):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_signal_name(id):
|
def get_signal_name(id):
|
||||||
if id is None:
|
if id is None:
|
||||||
return None
|
return None
|
||||||
@ -144,9 +155,11 @@ def get_signal_name (id):
|
|||||||
return val[id]["name"].string()
|
return val[id]["name"].string()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def frame_name(frame):
|
def frame_name(frame):
|
||||||
return str(frame.function())
|
return str(frame.function())
|
||||||
|
|
||||||
|
|
||||||
def frame_var(frame, var):
|
def frame_var(frame, var):
|
||||||
return frame.inferior_frame().read_var(var)
|
return frame.inferior_frame().read_var(var)
|
||||||
|
|
||||||
@ -165,7 +178,7 @@ class SignalFrame(FrameDecorator):
|
|||||||
v = frame_var(frame, name)
|
v = frame_var(frame, name)
|
||||||
if v is None or v.is_optimized_out:
|
if v is None or v.is_optimized_out:
|
||||||
return None
|
return None
|
||||||
if array != None:
|
if array is not None:
|
||||||
array.append(v)
|
array.append(v)
|
||||||
return v
|
return v
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@ -178,8 +191,8 @@ class SignalFrame(FrameDecorator):
|
|||||||
return None
|
return None
|
||||||
v = v.cast(gdb.lookup_type("GObject").pointer())
|
v = v.cast(gdb.lookup_type("GObject").pointer())
|
||||||
# Ensure this is a somewhat correct object pointer
|
# Ensure this is a somewhat correct object pointer
|
||||||
if v != None and g_type_name_from_instance (v):
|
if v is not None and g_type_name_from_instance(v):
|
||||||
if array != None:
|
if array is not None:
|
||||||
array.append(v)
|
array.append(v)
|
||||||
return v
|
return v
|
||||||
return None
|
return None
|
||||||
@ -187,14 +200,14 @@ class SignalFrame(FrameDecorator):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def append(self, array, obj):
|
def append(self, array, obj):
|
||||||
if obj != None:
|
if obj is not None:
|
||||||
array.append(obj)
|
array.append(obj)
|
||||||
|
|
||||||
def or_join_array(self, array):
|
def or_join_array(self, array):
|
||||||
if len(array) == 0:
|
if len(array) == 0:
|
||||||
return "???"
|
return "???"
|
||||||
else:
|
else:
|
||||||
return ' or '.join(set(map(str, array)))
|
return " or ".join(set(map(str, array)))
|
||||||
|
|
||||||
def get_detailed_signal_from_frame(self, frame, signal):
|
def get_detailed_signal_from_frame(self, frame, signal):
|
||||||
detail = self.read_var(frame, "detail")
|
detail = self.read_var(frame, "detail")
|
||||||
@ -221,7 +234,9 @@ class SignalFrame(FrameDecorator):
|
|||||||
if name == "g_signal_emitv":
|
if name == "g_signal_emitv":
|
||||||
instance_and_params = self.read_var(frame, "instance_and_params")
|
instance_and_params = self.read_var(frame, "instance_and_params")
|
||||||
if instance_and_params:
|
if instance_and_params:
|
||||||
instance = instance_and_params[0]["v_pointer"].cast (gdb.Type("GObject").pointer())
|
instance = instance_and_params[0]["v_pointer"].cast(
|
||||||
|
gdb.Type("GObject").pointer()
|
||||||
|
)
|
||||||
self.append(instances, instance)
|
self.append(instances, instance)
|
||||||
id = self.read_var(frame, "signal_id")
|
id = self.read_var(frame, "signal_id")
|
||||||
signal = get_signal_name(id)
|
signal = get_signal_name(id)
|
||||||
@ -253,6 +268,7 @@ class SignalFrame(FrameDecorator):
|
|||||||
def describe(self, stream, full):
|
def describe(self, stream, full):
|
||||||
stream.write(" " + self.function() + "\n")
|
stream.write(" " + self.function() + "\n")
|
||||||
|
|
||||||
|
|
||||||
class GFrameDecorator:
|
class GFrameDecorator:
|
||||||
def __init__(self, iter):
|
def __init__(self, iter):
|
||||||
self.queue = []
|
self.queue = []
|
||||||
@ -296,11 +312,13 @@ class GFrameDecorator:
|
|||||||
break
|
break
|
||||||
end = emission + 1
|
end = emission + 1
|
||||||
while end < len(self.queue):
|
while end < len(self.queue):
|
||||||
if frame_name(self.queue[end]) in ["g_signal_emitv",
|
if frame_name(self.queue[end]) in [
|
||||||
|
"g_signal_emitv",
|
||||||
"g_signal_emit_valist",
|
"g_signal_emit_valist",
|
||||||
"g_signal_emit",
|
"g_signal_emit",
|
||||||
"g_signal_emit_by_name",
|
"g_signal_emit_by_name",
|
||||||
"_g_closure_invoke_va"]:
|
"_g_closure_invoke_va",
|
||||||
|
]:
|
||||||
end = end + 1
|
end = end + 1
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
@ -314,14 +332,16 @@ class GFrameDecorator:
|
|||||||
def __next__(self):
|
def __next__(self):
|
||||||
return self.next()
|
return self.next()
|
||||||
|
|
||||||
|
|
||||||
class GFrameFilter(object):
|
class GFrameFilter(object):
|
||||||
name = 'glib'
|
name = "glib"
|
||||||
enabled = True
|
enabled = True
|
||||||
priority = 100
|
priority = 100
|
||||||
|
|
||||||
def filter(self, iterator):
|
def filter(self, iterator):
|
||||||
return GFrameDecorator(iterator)
|
return GFrameDecorator(iterator)
|
||||||
|
|
||||||
|
|
||||||
def register(obj):
|
def register(obj):
|
||||||
if obj is None:
|
if obj is None:
|
||||||
obj = gdb
|
obj = gdb
|
||||||
|
@ -32,7 +32,11 @@ import unittest
|
|||||||
import taptestrunner
|
import taptestrunner
|
||||||
|
|
||||||
|
|
||||||
Result = collections.namedtuple('Result', ('info', 'out', 'err', 'subs'))
|
# Disable line length warnings as wrapping the C code templates would be hard
|
||||||
|
# flake8: noqa: E501
|
||||||
|
|
||||||
|
|
||||||
|
Result = collections.namedtuple("Result", ("info", "out", "err", "subs"))
|
||||||
|
|
||||||
|
|
||||||
class TestGenmarshal(unittest.TestCase):
|
class TestGenmarshal(unittest.TestCase):
|
||||||
@ -47,22 +51,23 @@ class TestGenmarshal(unittest.TestCase):
|
|||||||
parsing and generation code out into a library and unit test that, and
|
parsing and generation code out into a library and unit test that, and
|
||||||
convert this test to just check command line behaviour.
|
convert this test to just check command line behaviour.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Track the cwd, we want to back out to that to clean up our tempdir
|
# Track the cwd, we want to back out to that to clean up our tempdir
|
||||||
cwd = ''
|
cwd = ""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.timeout_seconds = 10 # seconds per test
|
self.timeout_seconds = 10 # seconds per test
|
||||||
self.tmpdir = tempfile.TemporaryDirectory()
|
self.tmpdir = tempfile.TemporaryDirectory()
|
||||||
self.cwd = os.getcwd()
|
self.cwd = os.getcwd()
|
||||||
os.chdir(self.tmpdir.name)
|
os.chdir(self.tmpdir.name)
|
||||||
print('tmpdir:', self.tmpdir.name)
|
print("tmpdir:", self.tmpdir.name)
|
||||||
if 'G_TEST_BUILDDIR' in os.environ:
|
if "G_TEST_BUILDDIR" in os.environ:
|
||||||
self.__genmarshal = \
|
self.__genmarshal = os.path.join(
|
||||||
os.path.join(os.environ['G_TEST_BUILDDIR'], '..',
|
os.environ["G_TEST_BUILDDIR"], "..", "glib-genmarshal"
|
||||||
'glib-genmarshal')
|
)
|
||||||
else:
|
else:
|
||||||
self.__genmarshal = shutil.which('glib-genmarshal')
|
self.__genmarshal = shutil.which("glib-genmarshal")
|
||||||
print('genmarshal:', self.__genmarshal)
|
print("genmarshal:", self.__genmarshal)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
os.chdir(self.cwd)
|
os.chdir(self.cwd)
|
||||||
@ -73,48 +78,53 @@ class TestGenmarshal(unittest.TestCase):
|
|||||||
|
|
||||||
# shebang lines are not supported on native
|
# shebang lines are not supported on native
|
||||||
# Windows consoles
|
# Windows consoles
|
||||||
if os.name == 'nt':
|
if os.name == "nt":
|
||||||
argv.insert(0, sys.executable)
|
argv.insert(0, sys.executable)
|
||||||
|
|
||||||
argv.extend(args)
|
argv.extend(args)
|
||||||
print('Running:', argv)
|
print("Running:", argv)
|
||||||
|
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
env['LC_ALL'] = 'C.UTF-8'
|
env["LC_ALL"] = "C.UTF-8"
|
||||||
print('Environment:', env)
|
print("Environment:", env)
|
||||||
|
|
||||||
# We want to ensure consistent line endings...
|
# We want to ensure consistent line endings...
|
||||||
info = subprocess.run(argv, timeout=self.timeout_seconds,
|
info = subprocess.run(
|
||||||
|
argv,
|
||||||
|
timeout=self.timeout_seconds,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
env=env,
|
env=env,
|
||||||
universal_newlines=True)
|
universal_newlines=True,
|
||||||
|
)
|
||||||
info.check_returncode()
|
info.check_returncode()
|
||||||
out = info.stdout.strip()
|
out = info.stdout.strip()
|
||||||
err = info.stderr.strip()
|
err = info.stderr.strip()
|
||||||
|
|
||||||
# Known substitutions for standard boilerplate
|
# Known substitutions for standard boilerplate
|
||||||
subs = {
|
subs = {
|
||||||
'standard_top_comment':
|
"standard_top_comment": "This file is generated by glib-genmarshal, do not modify "
|
||||||
'This file is generated by glib-genmarshal, do not modify '
|
"it. This code is licensed under the same license as the "
|
||||||
'it. This code is licensed under the same license as the '
|
"containing project. Note that it links to GLib, so must "
|
||||||
'containing project. Note that it links to GLib, so must '
|
"comply with the LGPL linking clauses.",
|
||||||
'comply with the LGPL linking clauses.',
|
"standard_top_pragma": dedent(
|
||||||
'standard_top_pragma': dedent(
|
"""
|
||||||
'''
|
|
||||||
#ifndef __G_CCLOSURE_USER_MARSHAL_MARSHAL_H__
|
#ifndef __G_CCLOSURE_USER_MARSHAL_MARSHAL_H__
|
||||||
#define __G_CCLOSURE_USER_MARSHAL_MARSHAL_H__
|
#define __G_CCLOSURE_USER_MARSHAL_MARSHAL_H__
|
||||||
''').strip(),
|
"""
|
||||||
'standard_bottom_pragma': dedent(
|
).strip(),
|
||||||
'''
|
"standard_bottom_pragma": dedent(
|
||||||
|
"""
|
||||||
#endif /* __G_CCLOSURE_USER_MARSHAL_MARSHAL_H__ */
|
#endif /* __G_CCLOSURE_USER_MARSHAL_MARSHAL_H__ */
|
||||||
''').strip(),
|
"""
|
||||||
'standard_includes': dedent(
|
).strip(),
|
||||||
'''
|
"standard_includes": dedent(
|
||||||
|
"""
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
''').strip(),
|
"""
|
||||||
'standard_marshal_peek_defines': dedent(
|
).strip(),
|
||||||
'''
|
"standard_marshal_peek_defines": dedent(
|
||||||
|
"""
|
||||||
#ifdef G_ENABLE_DEBUG
|
#ifdef G_ENABLE_DEBUG
|
||||||
#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
|
#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
|
||||||
#define g_marshal_value_peek_char(v) g_value_get_schar (v)
|
#define g_marshal_value_peek_char(v) g_value_get_schar (v)
|
||||||
@ -160,54 +170,53 @@ class TestGenmarshal(unittest.TestCase):
|
|||||||
#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
|
#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
|
||||||
#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer
|
#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer
|
||||||
#endif /* !G_ENABLE_DEBUG */
|
#endif /* !G_ENABLE_DEBUG */
|
||||||
''').strip(),
|
"""
|
||||||
|
).strip(),
|
||||||
}
|
}
|
||||||
|
|
||||||
result = Result(info, out, err, subs)
|
result = Result(info, out, err, subs)
|
||||||
|
|
||||||
print('Output:', result.out)
|
print("Output:", result.out)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def runGenmarshalWithList(self, list_contents, *args):
|
def runGenmarshalWithList(self, list_contents, *args):
|
||||||
with tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
|
with tempfile.NamedTemporaryFile(
|
||||||
suffix='.list',
|
dir=self.tmpdir.name, suffix=".list", delete=False
|
||||||
delete=False) as list_file:
|
) as list_file:
|
||||||
# Write out the list.
|
# Write out the list.
|
||||||
list_file.write(list_contents.encode('utf-8'))
|
list_file.write(list_contents.encode("utf-8"))
|
||||||
print(list_file.name + ':', list_contents)
|
print(list_file.name + ":", list_contents)
|
||||||
list_file.flush()
|
list_file.flush()
|
||||||
|
|
||||||
header_result = self.runGenmarshal(list_file.name,
|
header_result = self.runGenmarshal(list_file.name, "--header", *args)
|
||||||
'--header', *args)
|
body_result = self.runGenmarshal(list_file.name, "--body", *args)
|
||||||
body_result = self.runGenmarshal(list_file.name,
|
|
||||||
'--body', *args)
|
|
||||||
|
|
||||||
header_result.subs['list_path'] = list_file.name
|
header_result.subs["list_path"] = list_file.name
|
||||||
body_result.subs['list_path'] = list_file.name
|
body_result.subs["list_path"] = list_file.name
|
||||||
|
|
||||||
return (header_result, body_result)
|
return (header_result, body_result)
|
||||||
|
|
||||||
def test_help(self):
|
def test_help(self):
|
||||||
"""Test the --help argument."""
|
"""Test the --help argument."""
|
||||||
result = self.runGenmarshal('--help')
|
result = self.runGenmarshal("--help")
|
||||||
self.assertIn('usage: glib-genmarshal', result.out)
|
self.assertIn("usage: glib-genmarshal", result.out)
|
||||||
|
|
||||||
def test_no_args(self):
|
def test_no_args(self):
|
||||||
"""Test running with no arguments at all."""
|
"""Test running with no arguments at all."""
|
||||||
result = self.runGenmarshal()
|
result = self.runGenmarshal()
|
||||||
self.assertEqual('', result.err)
|
self.assertEqual("", result.err)
|
||||||
self.assertEqual('', result.out)
|
self.assertEqual("", result.out)
|
||||||
|
|
||||||
def test_empty_list(self):
|
def test_empty_list(self):
|
||||||
"""Test running with an empty list."""
|
"""Test running with an empty list."""
|
||||||
(header_result, body_result) = \
|
(header_result, body_result) = self.runGenmarshalWithList("", "--quiet")
|
||||||
self.runGenmarshalWithList('', '--quiet')
|
|
||||||
|
|
||||||
self.assertEqual('', header_result.err)
|
self.assertEqual("", header_result.err)
|
||||||
self.assertEqual('', body_result.err)
|
self.assertEqual("", body_result.err)
|
||||||
|
|
||||||
self.assertEqual(dedent(
|
self.assertEqual(
|
||||||
'''
|
dedent(
|
||||||
|
"""
|
||||||
/* {standard_top_comment} */
|
/* {standard_top_comment} */
|
||||||
{standard_top_pragma}
|
{standard_top_pragma}
|
||||||
|
|
||||||
@ -219,28 +228,39 @@ class TestGenmarshal(unittest.TestCase):
|
|||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
{standard_bottom_pragma}
|
{standard_bottom_pragma}
|
||||||
''').strip().format(**header_result.subs),
|
"""
|
||||||
header_result.out.strip())
|
)
|
||||||
|
.strip()
|
||||||
|
.format(**header_result.subs),
|
||||||
|
header_result.out.strip(),
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual(dedent(
|
self.assertEqual(
|
||||||
'''
|
dedent(
|
||||||
|
"""
|
||||||
/* {standard_top_comment} */
|
/* {standard_top_comment} */
|
||||||
{standard_includes}
|
{standard_includes}
|
||||||
|
|
||||||
{standard_marshal_peek_defines}
|
{standard_marshal_peek_defines}
|
||||||
''').strip().format(**body_result.subs),
|
"""
|
||||||
body_result.out.strip())
|
)
|
||||||
|
.strip()
|
||||||
|
.format(**body_result.subs),
|
||||||
|
body_result.out.strip(),
|
||||||
|
)
|
||||||
|
|
||||||
def test_void_boolean(self):
|
def test_void_boolean(self):
|
||||||
"""Test running with a basic VOID:BOOLEAN list."""
|
"""Test running with a basic VOID:BOOLEAN list."""
|
||||||
(header_result, body_result) = \
|
(header_result, body_result) = self.runGenmarshalWithList(
|
||||||
self.runGenmarshalWithList('VOID:BOOLEAN', '--quiet')
|
"VOID:BOOLEAN", "--quiet"
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual('', header_result.err)
|
self.assertEqual("", header_result.err)
|
||||||
self.assertEqual('', body_result.err)
|
self.assertEqual("", body_result.err)
|
||||||
|
|
||||||
self.assertEqual(dedent(
|
self.assertEqual(
|
||||||
'''
|
dedent(
|
||||||
|
"""
|
||||||
/* {standard_top_comment} */
|
/* {standard_top_comment} */
|
||||||
{standard_top_pragma}
|
{standard_top_pragma}
|
||||||
|
|
||||||
@ -255,28 +275,39 @@ class TestGenmarshal(unittest.TestCase):
|
|||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
{standard_bottom_pragma}
|
{standard_bottom_pragma}
|
||||||
''').strip().format(**header_result.subs),
|
"""
|
||||||
header_result.out.strip())
|
)
|
||||||
|
.strip()
|
||||||
|
.format(**header_result.subs),
|
||||||
|
header_result.out.strip(),
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual(dedent(
|
self.assertEqual(
|
||||||
'''
|
dedent(
|
||||||
|
"""
|
||||||
/* {standard_top_comment} */
|
/* {standard_top_comment} */
|
||||||
{standard_includes}
|
{standard_includes}
|
||||||
|
|
||||||
{standard_marshal_peek_defines}
|
{standard_marshal_peek_defines}
|
||||||
''').strip().format(**body_result.subs),
|
"""
|
||||||
body_result.out.strip())
|
)
|
||||||
|
.strip()
|
||||||
|
.format(**body_result.subs),
|
||||||
|
body_result.out.strip(),
|
||||||
|
)
|
||||||
|
|
||||||
def test_void_boolean_int64(self):
|
def test_void_boolean_int64(self):
|
||||||
"""Test running with a non-trivial VOID:BOOLEAN,INT64 list."""
|
"""Test running with a non-trivial VOID:BOOLEAN,INT64 list."""
|
||||||
(header_result, body_result) = \
|
(header_result, body_result) = self.runGenmarshalWithList(
|
||||||
self.runGenmarshalWithList('VOID:BOOLEAN,INT64', '--quiet')
|
"VOID:BOOLEAN,INT64", "--quiet"
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual('', header_result.err)
|
self.assertEqual("", header_result.err)
|
||||||
self.assertEqual('', body_result.err)
|
self.assertEqual("", body_result.err)
|
||||||
|
|
||||||
self.assertEqual(dedent(
|
self.assertEqual(
|
||||||
'''
|
dedent(
|
||||||
|
"""
|
||||||
/* {standard_top_comment} */
|
/* {standard_top_comment} */
|
||||||
{standard_top_pragma}
|
{standard_top_pragma}
|
||||||
|
|
||||||
@ -297,11 +328,16 @@ class TestGenmarshal(unittest.TestCase):
|
|||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
{standard_bottom_pragma}
|
{standard_bottom_pragma}
|
||||||
''').strip().format(**header_result.subs),
|
"""
|
||||||
header_result.out.strip())
|
)
|
||||||
|
.strip()
|
||||||
|
.format(**header_result.subs),
|
||||||
|
header_result.out.strip(),
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual(dedent(
|
self.assertEqual(
|
||||||
'''
|
dedent(
|
||||||
|
"""
|
||||||
/* {standard_top_comment} */
|
/* {standard_top_comment} */
|
||||||
{standard_includes}
|
{standard_includes}
|
||||||
|
|
||||||
@ -343,8 +379,12 @@ class TestGenmarshal(unittest.TestCase):
|
|||||||
g_marshal_value_peek_int64 (param_values + 2),
|
g_marshal_value_peek_int64 (param_values + 2),
|
||||||
data2);
|
data2);
|
||||||
}}
|
}}
|
||||||
''').strip().format(**body_result.subs),
|
"""
|
||||||
body_result.out.strip())
|
)
|
||||||
|
.strip()
|
||||||
|
.format(**body_result.subs),
|
||||||
|
body_result.out.strip(),
|
||||||
|
)
|
||||||
|
|
||||||
def test_void_variant_nostdinc_valist_marshaller(self):
|
def test_void_variant_nostdinc_valist_marshaller(self):
|
||||||
"""Test running with a basic VOID:VARIANT list, but without the
|
"""Test running with a basic VOID:VARIANT list, but without the
|
||||||
@ -353,15 +393,16 @@ class TestGenmarshal(unittest.TestCase):
|
|||||||
|
|
||||||
See issue #1793.
|
See issue #1793.
|
||||||
"""
|
"""
|
||||||
(header_result, body_result) = \
|
(header_result, body_result) = self.runGenmarshalWithList(
|
||||||
self.runGenmarshalWithList('VOID:VARIANT', '--quiet', '--nostdinc',
|
"VOID:VARIANT", "--quiet", "--nostdinc", "--valist-marshaller"
|
||||||
'--valist-marshaller')
|
)
|
||||||
|
|
||||||
self.assertEqual('', header_result.err)
|
self.assertEqual("", header_result.err)
|
||||||
self.assertEqual('', body_result.err)
|
self.assertEqual("", body_result.err)
|
||||||
|
|
||||||
self.assertEqual(dedent(
|
self.assertEqual(
|
||||||
'''
|
dedent(
|
||||||
|
"""
|
||||||
/* {standard_top_comment} */
|
/* {standard_top_comment} */
|
||||||
{standard_top_pragma}
|
{standard_top_pragma}
|
||||||
|
|
||||||
@ -388,11 +429,16 @@ class TestGenmarshal(unittest.TestCase):
|
|||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
{standard_bottom_pragma}
|
{standard_bottom_pragma}
|
||||||
''').strip().format(**header_result.subs),
|
"""
|
||||||
header_result.out.strip())
|
)
|
||||||
|
.strip()
|
||||||
|
.format(**header_result.subs),
|
||||||
|
header_result.out.strip(),
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual(dedent(
|
self.assertEqual(
|
||||||
'''
|
dedent(
|
||||||
|
"""
|
||||||
/* {standard_top_comment} */
|
/* {standard_top_comment} */
|
||||||
{standard_marshal_peek_defines}
|
{standard_marshal_peek_defines}
|
||||||
|
|
||||||
@ -474,8 +520,12 @@ class TestGenmarshal(unittest.TestCase):
|
|||||||
if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
|
if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
|
||||||
g_variant_unref (arg0);
|
g_variant_unref (arg0);
|
||||||
}}
|
}}
|
||||||
''').strip().format(**body_result.subs),
|
"""
|
||||||
body_result.out.strip())
|
)
|
||||||
|
.strip()
|
||||||
|
.format(**body_result.subs),
|
||||||
|
body_result.out.strip(),
|
||||||
|
)
|
||||||
|
|
||||||
def test_void_string_nostdinc(self):
|
def test_void_string_nostdinc(self):
|
||||||
"""Test running with a basic VOID:STRING list, but without the
|
"""Test running with a basic VOID:STRING list, but without the
|
||||||
@ -485,15 +535,16 @@ class TestGenmarshal(unittest.TestCase):
|
|||||||
|
|
||||||
See issue #1792.
|
See issue #1792.
|
||||||
"""
|
"""
|
||||||
(header_result, body_result) = \
|
(header_result, body_result) = self.runGenmarshalWithList(
|
||||||
self.runGenmarshalWithList('VOID:STRING', '--quiet', '--nostdinc',
|
"VOID:STRING", "--quiet", "--nostdinc", "--valist-marshaller"
|
||||||
'--valist-marshaller')
|
)
|
||||||
|
|
||||||
self.assertEqual('', header_result.err)
|
self.assertEqual("", header_result.err)
|
||||||
self.assertEqual('', body_result.err)
|
self.assertEqual("", body_result.err)
|
||||||
|
|
||||||
self.assertEqual(dedent(
|
self.assertEqual(
|
||||||
'''
|
dedent(
|
||||||
|
"""
|
||||||
/* {standard_top_comment} */
|
/* {standard_top_comment} */
|
||||||
{standard_top_pragma}
|
{standard_top_pragma}
|
||||||
|
|
||||||
@ -520,11 +571,16 @@ class TestGenmarshal(unittest.TestCase):
|
|||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
{standard_bottom_pragma}
|
{standard_bottom_pragma}
|
||||||
''').strip().format(**header_result.subs),
|
"""
|
||||||
header_result.out.strip())
|
)
|
||||||
|
.strip()
|
||||||
|
.format(**header_result.subs),
|
||||||
|
header_result.out.strip(),
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual(dedent(
|
self.assertEqual(
|
||||||
'''
|
dedent(
|
||||||
|
"""
|
||||||
/* {standard_top_comment} */
|
/* {standard_top_comment} */
|
||||||
{standard_marshal_peek_defines}
|
{standard_marshal_peek_defines}
|
||||||
|
|
||||||
@ -606,8 +662,12 @@ class TestGenmarshal(unittest.TestCase):
|
|||||||
if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
|
if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
|
||||||
g_free (arg0);
|
g_free (arg0);
|
||||||
}}
|
}}
|
||||||
''').strip().format(**body_result.subs),
|
"""
|
||||||
body_result.out.strip())
|
)
|
||||||
|
.strip()
|
||||||
|
.format(**body_result.subs),
|
||||||
|
body_result.out.strip(),
|
||||||
|
)
|
||||||
|
|
||||||
def test_void_param_nostdinc(self):
|
def test_void_param_nostdinc(self):
|
||||||
"""Test running with a basic VOID:PARAM list, but without the
|
"""Test running with a basic VOID:PARAM list, but without the
|
||||||
@ -618,15 +678,16 @@ class TestGenmarshal(unittest.TestCase):
|
|||||||
See issue #1792.
|
See issue #1792.
|
||||||
"""
|
"""
|
||||||
self.maxDiff = None # TODO
|
self.maxDiff = None # TODO
|
||||||
(header_result, body_result) = \
|
(header_result, body_result) = self.runGenmarshalWithList(
|
||||||
self.runGenmarshalWithList('VOID:PARAM', '--quiet', '--nostdinc',
|
"VOID:PARAM", "--quiet", "--nostdinc", "--valist-marshaller"
|
||||||
'--valist-marshaller')
|
)
|
||||||
|
|
||||||
self.assertEqual('', header_result.err)
|
self.assertEqual("", header_result.err)
|
||||||
self.assertEqual('', body_result.err)
|
self.assertEqual("", body_result.err)
|
||||||
|
|
||||||
self.assertEqual(dedent(
|
self.assertEqual(
|
||||||
'''
|
dedent(
|
||||||
|
"""
|
||||||
/* {standard_top_comment} */
|
/* {standard_top_comment} */
|
||||||
{standard_top_pragma}
|
{standard_top_pragma}
|
||||||
|
|
||||||
@ -653,11 +714,16 @@ class TestGenmarshal(unittest.TestCase):
|
|||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
{standard_bottom_pragma}
|
{standard_bottom_pragma}
|
||||||
''').strip().format(**header_result.subs),
|
"""
|
||||||
header_result.out.strip())
|
)
|
||||||
|
.strip()
|
||||||
|
.format(**header_result.subs),
|
||||||
|
header_result.out.strip(),
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual(dedent(
|
self.assertEqual(
|
||||||
'''
|
dedent(
|
||||||
|
"""
|
||||||
/* {standard_top_comment} */
|
/* {standard_top_comment} */
|
||||||
{standard_marshal_peek_defines}
|
{standard_marshal_peek_defines}
|
||||||
|
|
||||||
@ -739,9 +805,13 @@ class TestGenmarshal(unittest.TestCase):
|
|||||||
if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
|
if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
|
||||||
g_param_spec_unref (arg0);
|
g_param_spec_unref (arg0);
|
||||||
}}
|
}}
|
||||||
''').strip().format(**body_result.subs),
|
"""
|
||||||
body_result.out.strip())
|
)
|
||||||
|
.strip()
|
||||||
|
.format(**body_result.subs),
|
||||||
|
body_result.out.strip(),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
unittest.main(testRunner=taptestrunner.TAPTestRunner())
|
unittest.main(testRunner=taptestrunner.TAPTestRunner())
|
||||||
|
@ -32,7 +32,7 @@ import unittest
|
|||||||
import taptestrunner
|
import taptestrunner
|
||||||
|
|
||||||
|
|
||||||
Result = collections.namedtuple('Result', ('info', 'out', 'err', 'subs'))
|
Result = collections.namedtuple("Result", ("info", "out", "err", "subs"))
|
||||||
|
|
||||||
|
|
||||||
class TestMkenums(unittest.TestCase):
|
class TestMkenums(unittest.TestCase):
|
||||||
@ -47,8 +47,9 @@ class TestMkenums(unittest.TestCase):
|
|||||||
parsing and generation code out into a library and unit test that, and
|
parsing and generation code out into a library and unit test that, and
|
||||||
convert this test to just check command line behaviour.
|
convert this test to just check command line behaviour.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Track the cwd, we want to back out to that to clean up our tempdir
|
# Track the cwd, we want to back out to that to clean up our tempdir
|
||||||
cwd = ''
|
cwd = ""
|
||||||
rspfile = False
|
rspfile = False
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -56,14 +57,14 @@ class TestMkenums(unittest.TestCase):
|
|||||||
self.tmpdir = tempfile.TemporaryDirectory()
|
self.tmpdir = tempfile.TemporaryDirectory()
|
||||||
self.cwd = os.getcwd()
|
self.cwd = os.getcwd()
|
||||||
os.chdir(self.tmpdir.name)
|
os.chdir(self.tmpdir.name)
|
||||||
print('tmpdir:', self.tmpdir.name)
|
print("tmpdir:", self.tmpdir.name)
|
||||||
if 'G_TEST_BUILDDIR' in os.environ:
|
if "G_TEST_BUILDDIR" in os.environ:
|
||||||
self.__mkenums = \
|
self.__mkenums = os.path.join(
|
||||||
os.path.join(os.environ['G_TEST_BUILDDIR'], '..',
|
os.environ["G_TEST_BUILDDIR"], "..", "glib-mkenums"
|
||||||
'glib-mkenums')
|
)
|
||||||
else:
|
else:
|
||||||
self.__mkenums = shutil.which('glib-mkenums')
|
self.__mkenums = shutil.which("glib-mkenums")
|
||||||
print('rspfile: {}, mkenums:'.format(self.rspfile), self.__mkenums)
|
print("rspfile: {}, mkenums:".format(self.rspfile), self.__mkenums)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
os.chdir(self.cwd)
|
os.chdir(self.cwd)
|
||||||
@ -71,10 +72,12 @@ class TestMkenums(unittest.TestCase):
|
|||||||
|
|
||||||
def _write_rspfile(self, argv):
|
def _write_rspfile(self, argv):
|
||||||
import shlex
|
import shlex
|
||||||
with tempfile.NamedTemporaryFile(dir=self.tmpdir.name, mode='w',
|
|
||||||
delete=False) as f:
|
with tempfile.NamedTemporaryFile(
|
||||||
contents = ' '.join([shlex.quote(arg) for arg in argv])
|
dir=self.tmpdir.name, mode="w", delete=False
|
||||||
print('Response file contains:', contents)
|
) as f:
|
||||||
|
contents = " ".join([shlex.quote(arg) for arg in argv])
|
||||||
|
print("Response file contains:", contents)
|
||||||
f.write(contents)
|
f.write(contents)
|
||||||
f.flush()
|
f.flush()
|
||||||
return f.name
|
return f.name
|
||||||
@ -82,60 +85,62 @@ class TestMkenums(unittest.TestCase):
|
|||||||
def runMkenums(self, *args):
|
def runMkenums(self, *args):
|
||||||
if self.rspfile:
|
if self.rspfile:
|
||||||
rspfile = self._write_rspfile(args)
|
rspfile = self._write_rspfile(args)
|
||||||
args = ['@' + rspfile]
|
args = ["@" + rspfile]
|
||||||
argv = [self.__mkenums]
|
argv = [self.__mkenums]
|
||||||
|
|
||||||
# shebang lines are not supported on native
|
# shebang lines are not supported on native
|
||||||
# Windows consoles
|
# Windows consoles
|
||||||
if os.name == 'nt':
|
if os.name == "nt":
|
||||||
argv.insert(0, sys.executable)
|
argv.insert(0, sys.executable)
|
||||||
|
|
||||||
argv.extend(args)
|
argv.extend(args)
|
||||||
print('Running:', argv)
|
print("Running:", argv)
|
||||||
|
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
env['LC_ALL'] = 'C.UTF-8'
|
env["LC_ALL"] = "C.UTF-8"
|
||||||
print('Environment:', env)
|
print("Environment:", env)
|
||||||
|
|
||||||
# We want to ensure consistent line endings...
|
# We want to ensure consistent line endings...
|
||||||
info = subprocess.run(argv, timeout=self.timeout_seconds,
|
info = subprocess.run(
|
||||||
|
argv,
|
||||||
|
timeout=self.timeout_seconds,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
env=env,
|
env=env,
|
||||||
universal_newlines=True)
|
universal_newlines=True,
|
||||||
|
)
|
||||||
info.check_returncode()
|
info.check_returncode()
|
||||||
out = info.stdout.strip()
|
out = info.stdout.strip()
|
||||||
err = info.stderr.strip()
|
err = info.stderr.strip()
|
||||||
|
|
||||||
# Known substitutions for standard boilerplate
|
# Known substitutions for standard boilerplate
|
||||||
subs = {
|
subs = {
|
||||||
'standard_top_comment':
|
"standard_top_comment": "This file is generated by glib-mkenums, do not modify "
|
||||||
'This file is generated by glib-mkenums, do not modify '
|
"it. This code is licensed under the same license as the "
|
||||||
'it. This code is licensed under the same license as the '
|
"containing project. Note that it links to GLib, so must "
|
||||||
'containing project. Note that it links to GLib, so must '
|
"comply with the LGPL linking clauses.",
|
||||||
'comply with the LGPL linking clauses.',
|
"standard_bottom_comment": "Generated data ends here",
|
||||||
'standard_bottom_comment': 'Generated data ends here'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = Result(info, out, err, subs)
|
result = Result(info, out, err, subs)
|
||||||
|
|
||||||
print('Output:', result.out)
|
print("Output:", result.out)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def runMkenumsWithTemplate(self, template_contents, *args):
|
def runMkenumsWithTemplate(self, template_contents, *args):
|
||||||
with tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
|
with tempfile.NamedTemporaryFile(
|
||||||
suffix='.template',
|
dir=self.tmpdir.name, suffix=".template", delete=False
|
||||||
delete=False) as template_file:
|
) as template_file:
|
||||||
# Write out the template.
|
# Write out the template.
|
||||||
template_file.write(template_contents.encode('utf-8'))
|
template_file.write(template_contents.encode("utf-8"))
|
||||||
print(template_file.name + ':', template_contents)
|
print(template_file.name + ":", template_contents)
|
||||||
template_file.flush()
|
template_file.flush()
|
||||||
|
|
||||||
return self.runMkenums('--template', template_file.name, *args)
|
return self.runMkenums("--template", template_file.name, *args)
|
||||||
|
|
||||||
def runMkenumsWithAllSubstitutions(self, *args):
|
def runMkenumsWithAllSubstitutions(self, *args):
|
||||||
'''Run glib-mkenums with a template which outputs all substitutions.'''
|
"""Run glib-mkenums with a template which outputs all substitutions."""
|
||||||
template_contents = '''
|
template_contents = """
|
||||||
/*** BEGIN file-header ***/
|
/*** BEGIN file-header ***/
|
||||||
file-header
|
file-header
|
||||||
/*** END file-header ***/
|
/*** END file-header ***/
|
||||||
@ -203,51 +208,66 @@ comment: @comment@
|
|||||||
/*** BEGIN file-tail ***/
|
/*** BEGIN file-tail ***/
|
||||||
file-tail
|
file-tail
|
||||||
/*** END file-tail ***/
|
/*** END file-tail ***/
|
||||||
'''
|
"""
|
||||||
return self.runMkenumsWithTemplate(template_contents, *args)
|
return self.runMkenumsWithTemplate(template_contents, *args)
|
||||||
|
|
||||||
def runMkenumsWithHeader(self, h_contents, encoding='utf-8'):
|
def runMkenumsWithHeader(self, h_contents, encoding="utf-8"):
|
||||||
with tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
|
with tempfile.NamedTemporaryFile(
|
||||||
suffix='.h',
|
dir=self.tmpdir.name, suffix=".h", delete=False
|
||||||
delete=False) as h_file:
|
) as h_file:
|
||||||
# Write out the header to be scanned.
|
# Write out the header to be scanned.
|
||||||
h_file.write(h_contents.encode(encoding))
|
h_file.write(h_contents.encode(encoding))
|
||||||
print(h_file.name + ':', h_contents)
|
print(h_file.name + ":", h_contents)
|
||||||
h_file.flush()
|
h_file.flush()
|
||||||
|
|
||||||
# Run glib-mkenums with a template which outputs all substitutions.
|
# Run glib-mkenums with a template which outputs all substitutions.
|
||||||
result = self.runMkenumsWithAllSubstitutions(h_file.name)
|
result = self.runMkenumsWithAllSubstitutions(h_file.name)
|
||||||
|
|
||||||
# Known substitutions for generated filenames.
|
# Known substitutions for generated filenames.
|
||||||
result.subs.update({
|
result.subs.update(
|
||||||
'filename': h_file.name,
|
{"filename": h_file.name, "basename": os.path.basename(h_file.name),}
|
||||||
'basename': os.path.basename(h_file.name),
|
)
|
||||||
})
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def assertSingleEnum(self, result, enum_name_camel, enum_name_lower,
|
def assertSingleEnum(
|
||||||
enum_name_upper, enum_name_short, enum_prefix,
|
self,
|
||||||
enum_since, type_lower, type_camel, type_upper,
|
result,
|
||||||
value_name, value_nick, value_num):
|
enum_name_camel,
|
||||||
|
enum_name_lower,
|
||||||
|
enum_name_upper,
|
||||||
|
enum_name_short,
|
||||||
|
enum_prefix,
|
||||||
|
enum_since,
|
||||||
|
type_lower,
|
||||||
|
type_camel,
|
||||||
|
type_upper,
|
||||||
|
value_name,
|
||||||
|
value_nick,
|
||||||
|
value_num,
|
||||||
|
):
|
||||||
"""Assert that out (from runMkenumsWithHeader()) contains a single
|
"""Assert that out (from runMkenumsWithHeader()) contains a single
|
||||||
enum and value matching the given arguments."""
|
enum and value matching the given arguments."""
|
||||||
subs = dict({
|
subs = dict(
|
||||||
'enum_name_camel': enum_name_camel,
|
{
|
||||||
'enum_name_lower': enum_name_lower,
|
"enum_name_camel": enum_name_camel,
|
||||||
'enum_name_upper': enum_name_upper,
|
"enum_name_lower": enum_name_lower,
|
||||||
'enum_name_short': enum_name_short,
|
"enum_name_upper": enum_name_upper,
|
||||||
'enum_prefix': enum_prefix,
|
"enum_name_short": enum_name_short,
|
||||||
'enum_since': enum_since,
|
"enum_prefix": enum_prefix,
|
||||||
'type_lower': type_lower,
|
"enum_since": enum_since,
|
||||||
'type_camel': type_camel,
|
"type_lower": type_lower,
|
||||||
'type_upper': type_upper,
|
"type_camel": type_camel,
|
||||||
'value_name': value_name,
|
"type_upper": type_upper,
|
||||||
'value_nick': value_nick,
|
"value_name": value_name,
|
||||||
'value_num': value_num,
|
"value_nick": value_nick,
|
||||||
}, **result.subs)
|
"value_num": value_num,
|
||||||
|
},
|
||||||
|
**result.subs
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual('''
|
self.assertEqual(
|
||||||
|
"""
|
||||||
comment
|
comment
|
||||||
comment: {standard_top_comment}
|
comment: {standard_top_comment}
|
||||||
|
|
||||||
@ -297,38 +317,51 @@ file-tail
|
|||||||
|
|
||||||
comment
|
comment
|
||||||
comment: {standard_bottom_comment}
|
comment: {standard_bottom_comment}
|
||||||
'''.format(**subs).strip(), result.out)
|
""".format(
|
||||||
|
**subs
|
||||||
|
).strip(),
|
||||||
|
result.out,
|
||||||
|
)
|
||||||
|
|
||||||
def test_help(self):
|
def test_help(self):
|
||||||
"""Test the --help argument."""
|
"""Test the --help argument."""
|
||||||
result = self.runMkenums('--help')
|
result = self.runMkenums("--help")
|
||||||
self.assertIn('usage: glib-mkenums', result.out)
|
self.assertIn("usage: glib-mkenums", result.out)
|
||||||
|
|
||||||
def test_no_args(self):
|
def test_no_args(self):
|
||||||
"""Test running with no arguments at all."""
|
"""Test running with no arguments at all."""
|
||||||
result = self.runMkenums()
|
result = self.runMkenums()
|
||||||
self.assertEqual('', result.err)
|
self.assertEqual("", result.err)
|
||||||
self.assertEqual('''/* {standard_top_comment} */
|
self.assertEqual(
|
||||||
|
"""/* {standard_top_comment} */
|
||||||
|
|
||||||
|
|
||||||
/* {standard_bottom_comment} */'''.format(**result.subs),
|
/* {standard_bottom_comment} */""".format(
|
||||||
result.out.strip())
|
**result.subs
|
||||||
|
),
|
||||||
|
result.out.strip(),
|
||||||
|
)
|
||||||
|
|
||||||
def test_empty_template(self):
|
def test_empty_template(self):
|
||||||
"""Test running with an empty template and no header files."""
|
"""Test running with an empty template and no header files."""
|
||||||
result = self.runMkenumsWithTemplate('')
|
result = self.runMkenumsWithTemplate("")
|
||||||
self.assertEqual('', result.err)
|
self.assertEqual("", result.err)
|
||||||
self.assertEqual('''/* {standard_top_comment} */
|
self.assertEqual(
|
||||||
|
"""/* {standard_top_comment} */
|
||||||
|
|
||||||
|
|
||||||
/* {standard_bottom_comment} */'''.format(**result.subs),
|
/* {standard_bottom_comment} */""".format(
|
||||||
result.out.strip())
|
**result.subs
|
||||||
|
),
|
||||||
|
result.out.strip(),
|
||||||
|
)
|
||||||
|
|
||||||
def test_no_headers(self):
|
def test_no_headers(self):
|
||||||
"""Test running with a complete template, but no header files."""
|
"""Test running with a complete template, but no header files."""
|
||||||
result = self.runMkenumsWithAllSubstitutions()
|
result = self.runMkenumsWithAllSubstitutions()
|
||||||
self.assertEqual('', result.err)
|
self.assertEqual("", result.err)
|
||||||
self.assertEqual('''
|
self.assertEqual(
|
||||||
|
"""
|
||||||
comment
|
comment
|
||||||
comment: {standard_top_comment}
|
comment: {standard_top_comment}
|
||||||
|
|
||||||
@ -338,13 +371,18 @@ file-tail
|
|||||||
|
|
||||||
comment
|
comment
|
||||||
comment: {standard_bottom_comment}
|
comment: {standard_bottom_comment}
|
||||||
'''.format(**result.subs).strip(), result.out)
|
""".format(
|
||||||
|
**result.subs
|
||||||
|
).strip(),
|
||||||
|
result.out,
|
||||||
|
)
|
||||||
|
|
||||||
def test_empty_header(self):
|
def test_empty_header(self):
|
||||||
"""Test an empty header."""
|
"""Test an empty header."""
|
||||||
result = self.runMkenumsWithHeader('')
|
result = self.runMkenumsWithHeader("")
|
||||||
self.assertEqual('', result.err)
|
self.assertEqual("", result.err)
|
||||||
self.assertEqual('''
|
self.assertEqual(
|
||||||
|
"""
|
||||||
comment
|
comment
|
||||||
comment: {standard_top_comment}
|
comment: {standard_top_comment}
|
||||||
|
|
||||||
@ -354,94 +392,134 @@ file-tail
|
|||||||
|
|
||||||
comment
|
comment
|
||||||
comment: {standard_bottom_comment}
|
comment: {standard_bottom_comment}
|
||||||
'''.format(**result.subs).strip(), result.out)
|
""".format(
|
||||||
|
**result.subs
|
||||||
|
).strip(),
|
||||||
|
result.out,
|
||||||
|
)
|
||||||
|
|
||||||
def test_enum_name(self):
|
def test_enum_name(self):
|
||||||
"""Test typedefs with an enum and a typedef name. Bug #794506."""
|
"""Test typedefs with an enum and a typedef name. Bug #794506."""
|
||||||
h_contents = '''
|
h_contents = """
|
||||||
typedef enum _SomeEnumIdentifier {
|
typedef enum _SomeEnumIdentifier {
|
||||||
ENUM_VALUE
|
ENUM_VALUE
|
||||||
} SomeEnumIdentifier;
|
} SomeEnumIdentifier;
|
||||||
'''
|
"""
|
||||||
result = self.runMkenumsWithHeader(h_contents)
|
result = self.runMkenumsWithHeader(h_contents)
|
||||||
self.assertEqual('', result.err)
|
self.assertEqual("", result.err)
|
||||||
self.assertSingleEnum(result, 'SomeEnumIdentifier',
|
self.assertSingleEnum(
|
||||||
'some_enum_identifier', 'SOME_ENUM_IDENTIFIER',
|
result,
|
||||||
'ENUM_IDENTIFIER', 'SOME', '', 'enum', 'Enum',
|
"SomeEnumIdentifier",
|
||||||
'ENUM', 'ENUM_VALUE', 'value', '0')
|
"some_enum_identifier",
|
||||||
|
"SOME_ENUM_IDENTIFIER",
|
||||||
|
"ENUM_IDENTIFIER",
|
||||||
|
"SOME",
|
||||||
|
"",
|
||||||
|
"enum",
|
||||||
|
"Enum",
|
||||||
|
"ENUM",
|
||||||
|
"ENUM_VALUE",
|
||||||
|
"value",
|
||||||
|
"0",
|
||||||
|
)
|
||||||
|
|
||||||
def test_non_utf8_encoding(self):
|
def test_non_utf8_encoding(self):
|
||||||
"""Test source files with non-UTF-8 encoding. Bug #785113."""
|
"""Test source files with non-UTF-8 encoding. Bug #785113."""
|
||||||
h_contents = '''
|
h_contents = """
|
||||||
/* Copyright © La Peña */
|
/* Copyright © La Peña */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ENUM_VALUE
|
ENUM_VALUE
|
||||||
} SomeEnumIdentifier;
|
} SomeEnumIdentifier;
|
||||||
'''
|
"""
|
||||||
result = self.runMkenumsWithHeader(h_contents, encoding='iso-8859-1')
|
result = self.runMkenumsWithHeader(h_contents, encoding="iso-8859-1")
|
||||||
self.assertIn('WARNING: UnicodeWarning: ', result.err)
|
self.assertIn("WARNING: UnicodeWarning: ", result.err)
|
||||||
self.assertSingleEnum(result, 'SomeEnumIdentifier',
|
self.assertSingleEnum(
|
||||||
'some_enum_identifier', 'SOME_ENUM_IDENTIFIER',
|
result,
|
||||||
'ENUM_IDENTIFIER', 'SOME', '', 'enum', 'Enum',
|
"SomeEnumIdentifier",
|
||||||
'ENUM', 'ENUM_VALUE', 'value', '0')
|
"some_enum_identifier",
|
||||||
|
"SOME_ENUM_IDENTIFIER",
|
||||||
|
"ENUM_IDENTIFIER",
|
||||||
|
"SOME",
|
||||||
|
"",
|
||||||
|
"enum",
|
||||||
|
"Enum",
|
||||||
|
"ENUM",
|
||||||
|
"ENUM_VALUE",
|
||||||
|
"value",
|
||||||
|
"0",
|
||||||
|
)
|
||||||
|
|
||||||
def test_reproducible(self):
|
def test_reproducible(self):
|
||||||
"""Test builds are reproducible regardless of file ordering.
|
"""Test builds are reproducible regardless of file ordering.
|
||||||
Bug #691436."""
|
Bug #691436."""
|
||||||
template_contents = 'template'
|
template_contents = "template"
|
||||||
|
|
||||||
h_contents1 = '''
|
h_contents1 = """
|
||||||
typedef enum {
|
typedef enum {
|
||||||
FIRST,
|
FIRST,
|
||||||
} Header1;
|
} Header1;
|
||||||
'''
|
"""
|
||||||
|
|
||||||
h_contents2 = '''
|
h_contents2 = """
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SECOND,
|
SECOND,
|
||||||
} Header2;
|
} Header2;
|
||||||
'''
|
"""
|
||||||
|
|
||||||
with tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
|
with tempfile.NamedTemporaryFile(
|
||||||
suffix='1.h', delete=False) as h_file1, \
|
dir=self.tmpdir.name, suffix="1.h", delete=False
|
||||||
tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
|
) as h_file1, tempfile.NamedTemporaryFile(
|
||||||
suffix='2.h', delete=False) as h_file2:
|
dir=self.tmpdir.name, suffix="2.h", delete=False
|
||||||
|
) as h_file2:
|
||||||
# Write out the headers.
|
# Write out the headers.
|
||||||
h_file1.write(h_contents1.encode('utf-8'))
|
h_file1.write(h_contents1.encode("utf-8"))
|
||||||
h_file2.write(h_contents2.encode('utf-8'))
|
h_file2.write(h_contents2.encode("utf-8"))
|
||||||
|
|
||||||
h_file1.flush()
|
h_file1.flush()
|
||||||
h_file2.flush()
|
h_file2.flush()
|
||||||
|
|
||||||
# Run glib-mkenums with the headers in one order, and then again
|
# Run glib-mkenums with the headers in one order, and then again
|
||||||
# in another order.
|
# in another order.
|
||||||
result1 = self.runMkenumsWithTemplate(template_contents,
|
result1 = self.runMkenumsWithTemplate(
|
||||||
h_file1.name, h_file2.name)
|
template_contents, h_file1.name, h_file2.name
|
||||||
self.assertEqual('', result1.err)
|
)
|
||||||
|
self.assertEqual("", result1.err)
|
||||||
|
|
||||||
result2 = self.runMkenumsWithTemplate(template_contents,
|
result2 = self.runMkenumsWithTemplate(
|
||||||
h_file2.name, h_file1.name)
|
template_contents, h_file2.name, h_file1.name
|
||||||
self.assertEqual('', result2.err)
|
)
|
||||||
|
self.assertEqual("", result2.err)
|
||||||
|
|
||||||
# The output should be the same.
|
# The output should be the same.
|
||||||
self.assertEqual(result1.out, result2.out)
|
self.assertEqual(result1.out, result2.out)
|
||||||
|
|
||||||
def test_no_nick(self):
|
def test_no_nick(self):
|
||||||
"""Test trigraphs with a desc but no nick. Issue #1360."""
|
"""Test trigraphs with a desc but no nick. Issue #1360."""
|
||||||
h_contents = '''
|
h_contents = """
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GEGL_SAMPLER_NEAREST = 0, /*< desc="nearest" >*/
|
GEGL_SAMPLER_NEAREST = 0, /*< desc="nearest" >*/
|
||||||
} GeglSamplerType;
|
} GeglSamplerType;
|
||||||
'''
|
"""
|
||||||
result = self.runMkenumsWithHeader(h_contents)
|
result = self.runMkenumsWithHeader(h_contents)
|
||||||
self.assertEqual('', result.err)
|
self.assertEqual("", result.err)
|
||||||
self.assertSingleEnum(result, 'GeglSamplerType',
|
self.assertSingleEnum(
|
||||||
'gegl_sampler_type', 'GEGL_SAMPLER_TYPE',
|
result,
|
||||||
'SAMPLER_TYPE', 'GEGL', '', 'enum', 'Enum',
|
"GeglSamplerType",
|
||||||
'ENUM', 'GEGL_SAMPLER_NEAREST', 'nearest', '0')
|
"gegl_sampler_type",
|
||||||
|
"GEGL_SAMPLER_TYPE",
|
||||||
|
"SAMPLER_TYPE",
|
||||||
|
"GEGL",
|
||||||
|
"",
|
||||||
|
"enum",
|
||||||
|
"Enum",
|
||||||
|
"ENUM",
|
||||||
|
"GEGL_SAMPLER_NEAREST",
|
||||||
|
"nearest",
|
||||||
|
"0",
|
||||||
|
)
|
||||||
|
|
||||||
def test_filename_basename_in_fhead_ftail(self):
|
def test_filename_basename_in_fhead_ftail(self):
|
||||||
template_contents = '''
|
template_contents = """
|
||||||
/*** BEGIN file-header ***/
|
/*** BEGIN file-header ***/
|
||||||
file-header
|
file-header
|
||||||
filename: @filename@
|
filename: @filename@
|
||||||
@ -457,18 +535,21 @@ comment: @comment@
|
|||||||
file-tail
|
file-tail
|
||||||
filename: @filename@
|
filename: @filename@
|
||||||
basename: @basename@
|
basename: @basename@
|
||||||
/*** END file-tail ***/'''
|
/*** END file-tail ***/"""
|
||||||
result = self.runMkenumsWithTemplate(template_contents)
|
result = self.runMkenumsWithTemplate(template_contents)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
textwrap.dedent(
|
textwrap.dedent(
|
||||||
'''
|
"""
|
||||||
WARNING: @filename@ used in file-header section.
|
WARNING: @filename@ used in file-header section.
|
||||||
WARNING: @basename@ used in file-header section.
|
WARNING: @basename@ used in file-header section.
|
||||||
WARNING: @filename@ used in file-tail section.
|
WARNING: @filename@ used in file-tail section.
|
||||||
WARNING: @basename@ used in file-tail section.
|
WARNING: @basename@ used in file-tail section.
|
||||||
''').strip(),
|
"""
|
||||||
result.err)
|
).strip(),
|
||||||
self.assertEqual('''
|
result.err,
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
"""
|
||||||
comment
|
comment
|
||||||
comment: {standard_top_comment}
|
comment: {standard_top_comment}
|
||||||
|
|
||||||
@ -482,27 +563,44 @@ basename: @basename@
|
|||||||
|
|
||||||
comment
|
comment
|
||||||
comment: {standard_bottom_comment}
|
comment: {standard_bottom_comment}
|
||||||
'''.format(**result.subs).strip(), result.out)
|
""".format(
|
||||||
|
**result.subs
|
||||||
|
).strip(),
|
||||||
|
result.out,
|
||||||
|
)
|
||||||
|
|
||||||
def test_since(self):
|
def test_since(self):
|
||||||
"""Test user-provided 'since' version handling
|
"""Test user-provided 'since' version handling
|
||||||
https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1492"""
|
https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1492"""
|
||||||
h_contents = '''
|
h_contents = """
|
||||||
typedef enum { /*< since=1.0 >*/
|
typedef enum { /*< since=1.0 >*/
|
||||||
QMI_WMS_MESSAGE_PROTOCOL_CDMA = 0,
|
QMI_WMS_MESSAGE_PROTOCOL_CDMA = 0,
|
||||||
} QmiWmsMessageProtocol;
|
} QmiWmsMessageProtocol;
|
||||||
'''
|
"""
|
||||||
result = self.runMkenumsWithHeader(h_contents)
|
result = self.runMkenumsWithHeader(h_contents)
|
||||||
self.assertEqual('', result.err)
|
self.assertEqual("", result.err)
|
||||||
self.assertSingleEnum(result, 'QmiWmsMessageProtocol',
|
self.assertSingleEnum(
|
||||||
'qmi_wms_message_protocol', 'QMI_WMS_MESSAGE_PROTOCOL',
|
result,
|
||||||
'WMS_MESSAGE_PROTOCOL', 'QMI', '1.0', 'enum', 'Enum',
|
"QmiWmsMessageProtocol",
|
||||||
'ENUM', 'QMI_WMS_MESSAGE_PROTOCOL_CDMA', 'cdma', '0')
|
"qmi_wms_message_protocol",
|
||||||
|
"QMI_WMS_MESSAGE_PROTOCOL",
|
||||||
|
"WMS_MESSAGE_PROTOCOL",
|
||||||
|
"QMI",
|
||||||
|
"1.0",
|
||||||
|
"enum",
|
||||||
|
"Enum",
|
||||||
|
"ENUM",
|
||||||
|
"QMI_WMS_MESSAGE_PROTOCOL_CDMA",
|
||||||
|
"cdma",
|
||||||
|
"0",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestRspMkenums(TestMkenums):
|
class TestRspMkenums(TestMkenums):
|
||||||
'''Run all tests again in @rspfile mode'''
|
"""Run all tests again in @rspfile mode"""
|
||||||
|
|
||||||
rspfile = True
|
rspfile = True
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
unittest.main(testRunner=taptestrunner.TAPTestRunner())
|
unittest.main(testRunner=taptestrunner.TAPTestRunner())
|
||||||
|
@ -30,6 +30,7 @@ import sys
|
|||||||
import base64
|
import base64
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
|
|
||||||
# Log modes
|
# Log modes
|
||||||
class LogMode(object):
|
class LogMode(object):
|
||||||
LogToError, LogToDiagnostics, LogToYAML, LogToAttachment = range(4)
|
LogToError, LogToDiagnostics, LogToYAML, LogToAttachment = range(4)
|
||||||
@ -73,7 +74,6 @@ class TAPTestResult(unittest.TestResult):
|
|||||||
sys.stdout = self.orig_stdout
|
sys.stdout = self.orig_stdout
|
||||||
sys.stderr = self.orig_stderr
|
sys.stderr = self.orig_stderr
|
||||||
|
|
||||||
|
|
||||||
def print_raw(self, text):
|
def print_raw(self, text):
|
||||||
self.output_stream.write(text)
|
self.output_stream.write(text)
|
||||||
self.output_stream.flush()
|
self.output_stream.flush()
|
||||||
@ -101,7 +101,7 @@ class TAPTestResult(unittest.TestResult):
|
|||||||
else:
|
else:
|
||||||
logs = [
|
logs = [
|
||||||
(self.test_output_log, self.test_output, "test_output"),
|
(self.test_output_log, self.test_output, "test_output"),
|
||||||
(self.message_log, self.message, "message")
|
(self.message_log, self.message, "message"),
|
||||||
]
|
]
|
||||||
for log_mode, log, log_name in logs:
|
for log_mode, log, log_name in logs:
|
||||||
if log_mode != LogMode.LogToError:
|
if log_mode != LogMode.LogToError:
|
||||||
@ -110,17 +110,23 @@ class TAPTestResult(unittest.TestResult):
|
|||||||
if log_mode == LogMode.LogToYAML:
|
if log_mode == LogMode.LogToYAML:
|
||||||
self.print_raw(" ---\n")
|
self.print_raw(" ---\n")
|
||||||
self.print_raw(" " + log_name + ": |\n")
|
self.print_raw(" " + log_name + ": |\n")
|
||||||
self.print_raw(" " + output.rstrip().replace("\n", "\n ") + "\n")
|
self.print_raw(
|
||||||
|
" " + output.rstrip().replace("\n", "\n ") + "\n"
|
||||||
|
)
|
||||||
self.print_raw(" ...\n")
|
self.print_raw(" ...\n")
|
||||||
elif log_mode == LogMode.LogToAttachment:
|
elif log_mode == LogMode.LogToAttachment:
|
||||||
self.print_raw(" ---\n")
|
self.print_raw(" ---\n")
|
||||||
self.print_raw(" " + log_name + ":\n")
|
self.print_raw(" " + log_name + ":\n")
|
||||||
self.print_raw(" File-Name: " + log_name + ".txt\n")
|
self.print_raw(" File-Name: " + log_name + ".txt\n")
|
||||||
self.print_raw(" File-Type: text/plain\n")
|
self.print_raw(" File-Type: text/plain\n")
|
||||||
self.print_raw(" File-Content: " + base64.b64encode(output) + "\n")
|
self.print_raw(
|
||||||
|
" File-Content: " + base64.b64encode(output) + "\n"
|
||||||
|
)
|
||||||
self.print_raw(" ...\n")
|
self.print_raw(" ...\n")
|
||||||
else:
|
else:
|
||||||
self.print_raw("# " + output.rstrip().replace("\n", "\n# ") + "\n")
|
self.print_raw(
|
||||||
|
"# " + output.rstrip().replace("\n", "\n# ") + "\n"
|
||||||
|
)
|
||||||
# Truncate doesn't change the current stream position.
|
# Truncate doesn't change the current stream position.
|
||||||
# Seek to the beginning to avoid extensions on subsequent writes.
|
# Seek to the beginning to avoid extensions on subsequent writes.
|
||||||
log.seek(0)
|
log.seek(0)
|
||||||
@ -155,10 +161,13 @@ class TAPTestResult(unittest.TestResult):
|
|||||||
|
|
||||||
|
|
||||||
class TAPTestRunner(object):
|
class TAPTestRunner(object):
|
||||||
def __init__(self,
|
def __init__(
|
||||||
|
self,
|
||||||
message_log=LogMode.LogToYAML,
|
message_log=LogMode.LogToYAML,
|
||||||
test_output_log=LogMode.LogToDiagnostics,
|
test_output_log=LogMode.LogToDiagnostics,
|
||||||
output_stream = sys.stdout, error_stream = sys.stderr):
|
output_stream=sys.stdout,
|
||||||
|
error_stream=sys.stderr,
|
||||||
|
):
|
||||||
self.output_stream = output_stream
|
self.output_stream = output_stream
|
||||||
self.error_stream = error_stream
|
self.error_stream = error_stream
|
||||||
self.message_log = message_log
|
self.message_log = message_log
|
||||||
@ -169,7 +178,8 @@ class TAPTestRunner(object):
|
|||||||
self.output_stream,
|
self.output_stream,
|
||||||
self.error_stream,
|
self.error_stream,
|
||||||
self.message_log,
|
self.message_log,
|
||||||
self.test_output_log)
|
self.test_output_log,
|
||||||
|
)
|
||||||
test(result)
|
test(result)
|
||||||
result.printErrors()
|
result.printErrors()
|
||||||
|
|
||||||
|
@ -29,14 +29,16 @@ import argparse
|
|||||||
|
|
||||||
def main(argv):
|
def main(argv):
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description="Generate test cases for casefolding from Unicode data")
|
description="Generate test cases for casefolding from Unicode data"
|
||||||
|
)
|
||||||
parser.add_argument("UNICODE-VERSION")
|
parser.add_argument("UNICODE-VERSION")
|
||||||
parser.add_argument("CaseFolding.txt")
|
parser.add_argument("CaseFolding.txt")
|
||||||
args = parser.parse_args(argv[1:])
|
args = parser.parse_args(argv[1:])
|
||||||
version = getattr(args, "UNICODE-VERSION")
|
version = getattr(args, "UNICODE-VERSION")
|
||||||
filename = getattr(args, "CaseFolding.txt")
|
filename = getattr(args, "CaseFolding.txt")
|
||||||
|
|
||||||
print("""\
|
print(
|
||||||
|
"""\
|
||||||
# Test cases generated from Unicode {} data
|
# Test cases generated from Unicode {} data
|
||||||
# by gen-casefold-txt.py. Do not edit.
|
# by gen-casefold-txt.py. Do not edit.
|
||||||
#
|
#
|
||||||
@ -45,7 +47,10 @@ def main(argv):
|
|||||||
AaBbCc@@\taabbcc@@
|
AaBbCc@@\taabbcc@@
|
||||||
#
|
#
|
||||||
# Now the automatic tests
|
# Now the automatic tests
|
||||||
#""".format(version))
|
#""".format(
|
||||||
|
version
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# Names of fields in the CaseFolding table
|
# Names of fields in the CaseFolding table
|
||||||
CODE, STATUS, MAPPING = range(3)
|
CODE, STATUS, MAPPING = range(3)
|
||||||
@ -60,8 +65,9 @@ AaBbCc@@\taabbcc@@
|
|||||||
fields = [f.strip() for f in line.split(";", 3)[:3]]
|
fields = [f.strip() for f in line.split(";", 3)[:3]]
|
||||||
if len(fields) != 3:
|
if len(fields) != 3:
|
||||||
raise SystemExit(
|
raise SystemExit(
|
||||||
"Entry for %s has wrong number of fields (%d)" % (
|
"Entry for %s has wrong number of fields (%d)"
|
||||||
fields[CODE], len(fields)))
|
% (fields[CODE], len(fields))
|
||||||
|
)
|
||||||
|
|
||||||
status = fields[STATUS]
|
status = fields[STATUS]
|
||||||
# skip simple and Turkic mappings
|
# skip simple and Turkic mappings
|
||||||
@ -69,8 +75,7 @@ AaBbCc@@\taabbcc@@
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
code = chr(int(fields[CODE], 16))
|
code = chr(int(fields[CODE], 16))
|
||||||
values = "".join(
|
values = "".join([chr(int(v, 16)) for v in fields[MAPPING].split()])
|
||||||
[chr(int(v, 16)) for v in fields[MAPPING].split()])
|
|
||||||
print("{}\t{}".format(code, values))
|
print("{}\t{}".format(code, values))
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,9 +27,14 @@ import sys
|
|||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
|
|
||||||
|
# Disable line length warnings as wrapping the test templates would be hard
|
||||||
|
# flake8: noqa: E501
|
||||||
|
|
||||||
|
|
||||||
def main(argv):
|
def main(argv):
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description="Generate test cases for case mapping from Unicode data")
|
description="Generate test cases for case mapping from Unicode data"
|
||||||
|
)
|
||||||
parser.add_argument("UNICODE-VERSION")
|
parser.add_argument("UNICODE-VERSION")
|
||||||
parser.add_argument("UnicodeData.txt")
|
parser.add_argument("UnicodeData.txt")
|
||||||
parser.add_argument("SpecialCasing.txt")
|
parser.add_argument("SpecialCasing.txt")
|
||||||
@ -39,9 +44,23 @@ def main(argv):
|
|||||||
filename_casing = getattr(args, "SpecialCasing.txt")
|
filename_casing = getattr(args, "SpecialCasing.txt")
|
||||||
|
|
||||||
# Names of fields in Unicode data table.
|
# Names of fields in Unicode data table.
|
||||||
CODE, NAME, CATEGORY, COMBINING_CLASSES, BIDI_CATEGORY, DECOMPOSITION, \
|
(
|
||||||
DECIMAL_VALUE, DIGIT_VALUE, NUMERIC_VALUE, MIRRORED, OLD_NAME, \
|
CODE,
|
||||||
COMMENT, UPPER, LOWER, TITLE = range(15)
|
NAME,
|
||||||
|
CATEGORY,
|
||||||
|
COMBINING_CLASSES,
|
||||||
|
BIDI_CATEGORY,
|
||||||
|
DECOMPOSITION,
|
||||||
|
DECIMAL_VALUE,
|
||||||
|
DIGIT_VALUE,
|
||||||
|
NUMERIC_VALUE,
|
||||||
|
MIRRORED,
|
||||||
|
OLD_NAME,
|
||||||
|
COMMENT,
|
||||||
|
UPPER,
|
||||||
|
LOWER,
|
||||||
|
TITLE,
|
||||||
|
) = range(15)
|
||||||
|
|
||||||
# Names of fields in the SpecialCasing table
|
# Names of fields in the SpecialCasing table
|
||||||
CASE_CODE, CASE_LOWER, CASE_TITLE, CASE_UPPER, CASE_CONDITION = range(5)
|
CASE_CODE, CASE_LOWER, CASE_TITLE, CASE_UPPER, CASE_CONDITION = range(5)
|
||||||
@ -78,8 +97,9 @@ def main(argv):
|
|||||||
fields = [f.strip() for f in line.split(";")]
|
fields = [f.strip() for f in line.split(";")]
|
||||||
if len(fields) != 15:
|
if len(fields) != 15:
|
||||||
raise SystemExit(
|
raise SystemExit(
|
||||||
"Entry for %s has wrong number of fields (%d)" % (
|
"Entry for %s has wrong number of fields (%d)"
|
||||||
fields[CODE], len(fields)))
|
% (fields[CODE], len(fields))
|
||||||
|
)
|
||||||
|
|
||||||
code = int(fields[CODE], 16)
|
code = int(fields[CODE], 16)
|
||||||
|
|
||||||
@ -92,8 +112,23 @@ def main(argv):
|
|||||||
else:
|
else:
|
||||||
# The gap represents undefined characters. Only the type
|
# The gap represents undefined characters. Only the type
|
||||||
# matters.
|
# matters.
|
||||||
gfields = ['', '', 'Cn', '0', '', '', '', '', '', '', '',
|
gfields = [
|
||||||
'', '', '', '']
|
"",
|
||||||
|
"",
|
||||||
|
"Cn",
|
||||||
|
"0",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
]
|
||||||
|
|
||||||
last_code += 1
|
last_code += 1
|
||||||
while last_code < code:
|
while last_code < code:
|
||||||
@ -117,8 +152,9 @@ def main(argv):
|
|||||||
fields = [f.strip() for f in line.split(";")]
|
fields = [f.strip() for f in line.split(";")]
|
||||||
if len(fields) not in (4, 5):
|
if len(fields) not in (4, 5):
|
||||||
raise SystemExit(
|
raise SystemExit(
|
||||||
"Entry for %s has wrong number of fields (%d)" % (
|
"Entry for %s has wrong number of fields (%d)"
|
||||||
fields[CASE_CODE], len(fields)))
|
% (fields[CASE_CODE], len(fields))
|
||||||
|
)
|
||||||
|
|
||||||
if len(fields) == 5:
|
if len(fields) == 5:
|
||||||
# Ignore conditional special cases - we'll handle them manually
|
# Ignore conditional special cases - we'll handle them manually
|
||||||
@ -134,7 +170,8 @@ def main(argv):
|
|||||||
|
|
||||||
|
|
||||||
def print_tests(version, upper, title, lower):
|
def print_tests(version, upper, title, lower):
|
||||||
print("""\
|
print(
|
||||||
|
"""\
|
||||||
# Test cases generated from Unicode {} data
|
# Test cases generated from Unicode {} data
|
||||||
# by gen-casemap-txt.py. Do not edit.
|
# by gen-casemap-txt.py. Do not edit.
|
||||||
#
|
#
|
||||||
@ -150,9 +187,9 @@ tr_TR.UTF-8\tI\u0307\ti\tI\u0307\tI\u0307\t# I => LATIN SMALL LETTER DOTLESS I
|
|||||||
\t\u03b1\u0345\u0314\t\u03b1\u0345\u0314\t\u0391\u0345\u0314\t\u0391\u0314\u0399\t
|
\t\u03b1\u0345\u0314\t\u03b1\u0345\u0314\t\u0391\u0345\u0314\t\u0391\u0314\u0399\t
|
||||||
\t\u03b1\u0314\u0345\t\u03b1\u0314\u0345\t\u0391\u0314\u0345\t\u0391\u0314\u0399\t
|
\t\u03b1\u0314\u0345\t\u03b1\u0314\u0345\t\u0391\u0314\u0345\t\u0391\u0314\u0399\t
|
||||||
# Handling of final and nonfinal sigma
|
# Handling of final and nonfinal sigma
|
||||||
\tΜΆΙΟΣ μάιος Μάιος ΜΆΙΟΣ
|
\tΜΆΙΟΣ μάιος Μάιος ΜΆΙΟΣ \t
|
||||||
\tΜΆΙΟΣ μάιος Μάιος ΜΆΙΟΣ
|
\tΜΆΙΟΣ μάιος Μάιος ΜΆΙΟΣ\t
|
||||||
\tΣΙΓΜΑ σιγμα Σιγμα ΣΙΓΜΑ
|
\tΣΙΓΜΑ σιγμα Σιγμα ΣΙΓΜΑ\t
|
||||||
# Lithuanian rule of i followed by letter with dot. Not at all sure
|
# Lithuanian rule of i followed by letter with dot. Not at all sure
|
||||||
# about the titlecase part here
|
# about the titlecase part here
|
||||||
lt_LT\ti\u0117\ti\u0117\tIe\tIE\t
|
lt_LT\ti\u0117\ti\u0117\tIe\tIE\t
|
||||||
@ -181,9 +218,12 @@ lt_LT.UTF-8\t\u012e\u0301\t\u012f\u0307\u0301\t\u012e\u0301\t\u012e\u0301\t # LA
|
|||||||
\ta\ufb04\ta\ufb04\tAffl\tAFFL\t# FB04
|
\ta\ufb04\ta\ufb04\tAffl\tAFFL\t# FB04
|
||||||
#
|
#
|
||||||
# Now the automatic tests
|
# Now the automatic tests
|
||||||
#""".format(version))
|
#""".format(
|
||||||
|
version
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
for i in range(0x10ffff):
|
for i in range(0x10FFFF):
|
||||||
if i == 0x3A3:
|
if i == 0x3A3:
|
||||||
# Greek sigma needs special tests
|
# Greek sigma needs special tests
|
||||||
continue
|
continue
|
||||||
|
Loading…
Reference in New Issue
Block a user