mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-25 15:06: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
|
||||
# be merged for now, but is to be grepped for and reverted or reworked later.
|
||||
BANNED_KEYWORDS = [
|
||||
'TO' + 'DO',
|
||||
'X' + 'XX',
|
||||
'W' + 'IP',
|
||||
"TO" + "DO",
|
||||
"X" + "XX",
|
||||
"W" + "IP",
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Check a range of commits to ensure they don’t contain '
|
||||
'banned keywords.')
|
||||
parser.add_argument('commits',
|
||||
help='SHA to diff from, or range of commits to diff')
|
||||
description="Check a range of commits to ensure they don’t contain "
|
||||
"banned keywords."
|
||||
)
|
||||
parser.add_argument("commits", help="SHA to diff from, or range of commits to diff")
|
||||
args = parser.parse_args()
|
||||
|
||||
banned_words_seen = set()
|
||||
@ -43,47 +43,55 @@ def main():
|
||||
|
||||
# Check the log messages for banned words.
|
||||
log_process = subprocess.run(
|
||||
['git', 'log', '--no-color', args.commits + '..HEAD'],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8',
|
||||
check=True)
|
||||
log_lines = log_process.stdout.strip().split('\n')
|
||||
["git", "log", "--no-color", args.commits + "..HEAD"],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
encoding="utf-8",
|
||||
check=True,
|
||||
)
|
||||
log_lines = log_process.stdout.strip().split("\n")
|
||||
|
||||
for line in log_lines:
|
||||
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)
|
||||
seen_in_log = True
|
||||
|
||||
# Check the diff for banned words.
|
||||
diff_process = subprocess.run(
|
||||
['git', 'diff', '-U0', '--no-color', args.commits],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8',
|
||||
check=True)
|
||||
diff_lines = diff_process.stdout.strip().split('\n')
|
||||
["git", "diff", "-U0", "--no-color", args.commits],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
encoding="utf-8",
|
||||
check=True,
|
||||
)
|
||||
diff_lines = diff_process.stdout.strip().split("\n")
|
||||
|
||||
for line in diff_lines:
|
||||
if not line.startswith('+ '):
|
||||
if not line.startswith("+ "):
|
||||
continue
|
||||
|
||||
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)
|
||||
seen_in_diff = True
|
||||
|
||||
if banned_words_seen:
|
||||
if seen_in_log and seen_in_diff:
|
||||
where = 'commit message and diff'
|
||||
where = "commit message and diff"
|
||||
elif seen_in_log:
|
||||
where = 'commit message'
|
||||
where = "commit message"
|
||||
elif seen_in_diff:
|
||||
where = 'commit diff'
|
||||
where = "commit diff"
|
||||
|
||||
print('Saw banned keywords in a {}: {}. '
|
||||
'This indicates the branch is a work in progress and should not '
|
||||
'be merged in its current '
|
||||
'form.'.format(where, ', '.join(banned_words_seen)))
|
||||
print(
|
||||
"Saw banned keywords in a {}: {}. "
|
||||
"This indicates the branch is a work in progress and should not "
|
||||
"be merged in its current "
|
||||
"form.".format(where, ", ".join(banned_words_seen))
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@ -11,105 +11,115 @@
|
||||
import argparse
|
||||
import datetime
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
aparser = argparse.ArgumentParser(description='Turns a Meson test log into a JUnit report')
|
||||
aparser.add_argument('--project-name', metavar='NAME',
|
||||
help='The project name',
|
||||
default='unknown')
|
||||
aparser.add_argument('--job-id', metavar='ID',
|
||||
help='The job ID for the report',
|
||||
default='Unknown')
|
||||
aparser.add_argument('--branch', metavar='NAME',
|
||||
help='Branch of the project being tested',
|
||||
default='master')
|
||||
aparser.add_argument('--output', 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)
|
||||
aparser = argparse.ArgumentParser(
|
||||
description="Turns a Meson test log into a JUnit report"
|
||||
)
|
||||
aparser.add_argument(
|
||||
"--project-name", metavar="NAME", help="The project name", default="unknown"
|
||||
)
|
||||
aparser.add_argument(
|
||||
"--job-id", metavar="ID", help="The job ID for the report", default="Unknown"
|
||||
)
|
||||
aparser.add_argument(
|
||||
"--branch",
|
||||
metavar="NAME",
|
||||
help="Branch of the project being tested",
|
||||
default="master",
|
||||
)
|
||||
aparser.add_argument(
|
||||
"--output",
|
||||
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()
|
||||
|
||||
outfile = args.output
|
||||
|
||||
testsuites = ET.Element('testsuites')
|
||||
testsuites.set('id', '{}/{}'.format(args.job_id, args.branch))
|
||||
testsuites.set('package', args.project_name)
|
||||
testsuites.set('timestamp', datetime.datetime.utcnow().isoformat())
|
||||
testsuites = ET.Element("testsuites")
|
||||
testsuites.set("id", "{}/{}".format(args.job_id, args.branch))
|
||||
testsuites.set("package", args.project_name)
|
||||
testsuites.set("timestamp", datetime.datetime.utcnow().isoformat())
|
||||
|
||||
suites = {}
|
||||
for line in args.infile:
|
||||
data = json.loads(line)
|
||||
(full_suite, unit_name) = data['name'].split(' / ')
|
||||
(full_suite, unit_name) = data["name"].split(" / ")
|
||||
try:
|
||||
(project_name, suite_name) = full_suite.split(':')
|
||||
(project_name, suite_name) = full_suite.split(":")
|
||||
except ValueError:
|
||||
project_name = full_suite
|
||||
suite_name = full_suite
|
||||
|
||||
duration = data['duration']
|
||||
return_code = data['returncode']
|
||||
log = data['stdout']
|
||||
log_stderr = data.get('stderr', '')
|
||||
duration = data["duration"]
|
||||
return_code = data["returncode"]
|
||||
log = data["stdout"]
|
||||
log_stderr = data.get("stderr", "")
|
||||
|
||||
unit = {
|
||||
'suite': suite_name,
|
||||
'name': unit_name,
|
||||
'duration': duration,
|
||||
'returncode': return_code,
|
||||
'stdout': log,
|
||||
'stderr': log_stderr,
|
||||
"suite": suite_name,
|
||||
"name": unit_name,
|
||||
"duration": duration,
|
||||
"returncode": return_code,
|
||||
"stdout": log,
|
||||
"stderr": log_stderr,
|
||||
}
|
||||
|
||||
units = suites.setdefault(suite_name, [])
|
||||
units.append(unit)
|
||||
|
||||
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):
|
||||
if unit['returncode'] != 0:
|
||||
if unit["returncode"] != 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
def if_succeded(unit):
|
||||
if unit['returncode'] == 0:
|
||||
if unit["returncode"] == 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
successes = list(filter(if_succeded, 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.set('name', '{}/{}'.format(args.project_name, name))
|
||||
testsuite.set('tests', str(len(units)))
|
||||
testsuite.set('errors', str(len(failures)))
|
||||
testsuite.set('failures', str(len(failures)))
|
||||
testsuite = ET.SubElement(testsuites, "testsuite")
|
||||
testsuite.set("name", "{}/{}".format(args.project_name, name))
|
||||
testsuite.set("tests", str(len(units)))
|
||||
testsuite.set("errors", str(len(failures)))
|
||||
testsuite.set("failures", str(len(failures)))
|
||||
|
||||
for unit in successes:
|
||||
testcase = ET.SubElement(testsuite, 'testcase')
|
||||
testcase.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
|
||||
testcase.set('name', unit['name'])
|
||||
testcase.set('time', str(unit['duration']))
|
||||
testcase = ET.SubElement(testsuite, "testcase")
|
||||
testcase.set("classname", "{}/{}".format(args.project_name, unit["suite"]))
|
||||
testcase.set("name", unit["name"])
|
||||
testcase.set("time", str(unit["duration"]))
|
||||
|
||||
for unit in failures:
|
||||
testcase = ET.SubElement(testsuite, 'testcase')
|
||||
testcase.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
|
||||
testcase.set('name', unit['name'])
|
||||
testcase.set('time', str(unit['duration']))
|
||||
testcase = ET.SubElement(testsuite, "testcase")
|
||||
testcase.set("classname", "{}/{}".format(args.project_name, unit["suite"]))
|
||||
testcase.set("name", unit["name"])
|
||||
testcase.set("time", str(unit["duration"]))
|
||||
|
||||
failure = ET.SubElement(testcase, 'failure')
|
||||
failure.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
|
||||
failure.set('name', unit['name'])
|
||||
failure.set('type', 'error')
|
||||
failure.text = unit['stdout'] + '\n' + unit['stderr']
|
||||
failure = ET.SubElement(testcase, "failure")
|
||||
failure.set("classname", "{}/{}".format(args.project_name, unit["suite"]))
|
||||
failure.set("name", unit["name"])
|
||||
failure.set("type", "error")
|
||||
failure.text = unit["stdout"] + "\n" + unit["stderr"]
|
||||
|
||||
output = ET.tostring(testsuites, encoding='unicode')
|
||||
output = ET.tostring(testsuites, encoding="unicode")
|
||||
outfile.write(output)
|
||||
|
@ -2,5 +2,8 @@
|
||||
|
||||
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
|
||||
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():
|
||||
parser = argparse.ArgumentParser(
|
||||
description=__doc__,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
parser.add_argument('-i', action='store_true', default=False,
|
||||
help='apply edits to files instead of displaying a '
|
||||
'diff')
|
||||
parser.add_argument('-p', metavar='NUM', default=0,
|
||||
help='strip the smallest prefix containing P slashes')
|
||||
parser.add_argument('-regex', metavar='PATTERN', default=None,
|
||||
help='custom pattern selecting file paths to reformat '
|
||||
'(case sensitive, overrides -iregex)')
|
||||
parser.add_argument('-iregex', 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')
|
||||
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
|
||||
)
|
||||
parser.add_argument(
|
||||
"-i",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="apply edits to files instead of displaying a " "diff",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-p",
|
||||
metavar="NUM",
|
||||
default=0,
|
||||
help="strip the smallest prefix containing P slashes",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-regex",
|
||||
metavar="PATTERN",
|
||||
default=None,
|
||||
help="custom pattern selecting file paths to reformat "
|
||||
"(case sensitive, overrides -iregex)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-iregex",
|
||||
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()
|
||||
|
||||
# Extract changed lines for each file.
|
||||
filename = None
|
||||
lines_by_file = {}
|
||||
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:
|
||||
filename = match.group(2)
|
||||
if filename is None:
|
||||
continue
|
||||
|
||||
if args.regex is not None:
|
||||
if not re.match('^%s$' % args.regex, filename):
|
||||
if not re.match("^%s$" % args.regex, filename):
|
||||
continue
|
||||
else:
|
||||
if not re.match('^%s$' % args.iregex, filename, re.IGNORECASE):
|
||||
if not re.match("^%s$" % args.iregex, filename, re.IGNORECASE):
|
||||
continue
|
||||
|
||||
match = re.search(r'^@@.*\+(\d+)(,(\d+))?', line)
|
||||
match = re.search(r"^@@.*\+(\d+)(,(\d+))?", line)
|
||||
if match:
|
||||
start_line = int(match.group(1))
|
||||
line_count = 1
|
||||
@ -86,7 +112,8 @@ def main():
|
||||
continue
|
||||
end_line = start_line + line_count - 1
|
||||
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.
|
||||
# We need to count amount of bytes generated in the output of
|
||||
@ -95,20 +122,22 @@ def main():
|
||||
format_line_counter = 0
|
||||
for filename, lines in lines_by_file.items():
|
||||
if args.i and args.verbose:
|
||||
print('Formatting {}'.format(filename))
|
||||
print("Formatting {}".format(filename))
|
||||
command = [args.binary, filename]
|
||||
if args.i:
|
||||
command.append('-i')
|
||||
command.append("-i")
|
||||
if args.sort_includes:
|
||||
command.append('-sort-includes')
|
||||
command.append("-sort-includes")
|
||||
command.extend(lines)
|
||||
if args.style:
|
||||
command.extend(['-style', args.style])
|
||||
p = subprocess.Popen(command,
|
||||
command.extend(["-style", args.style])
|
||||
p = subprocess.Popen(
|
||||
command,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=None,
|
||||
stdin=subprocess.PIPE,
|
||||
universal_newlines=True)
|
||||
universal_newlines=True,
|
||||
)
|
||||
stdout, _ = p.communicate()
|
||||
if p.returncode != 0:
|
||||
sys.exit(p.returncode)
|
||||
@ -117,11 +146,15 @@ def main():
|
||||
with open(filename) as f:
|
||||
code = f.readlines()
|
||||
formatted_code = StringIO(stdout).readlines()
|
||||
diff = difflib.unified_diff(code, formatted_code,
|
||||
filename, filename,
|
||||
'(before formatting)',
|
||||
'(after formatting)')
|
||||
diff_string = ''.join(diff)
|
||||
diff = difflib.unified_diff(
|
||||
code,
|
||||
formatted_code,
|
||||
filename,
|
||||
filename,
|
||||
"(before formatting)",
|
||||
"(after formatting)",
|
||||
)
|
||||
diff_string = "".join(diff)
|
||||
if diff_string:
|
||||
format_line_counter += sys.stdout.write(diff_string)
|
||||
|
||||
@ -129,5 +162,5 @@ def main():
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@ -18,13 +18,18 @@
|
||||
#
|
||||
# Author: Xavier Claessens <xavier.claessens@collabora.com>
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
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)
|
||||
|
||||
with open(sys.argv[1], 'w') as outfile:
|
||||
with open(sys.argv[1], "w") as outfile:
|
||||
for fname in sys.argv[2:]:
|
||||
with open(fname) as infile:
|
||||
for line in infile:
|
||||
|
@ -3,14 +3,14 @@
|
||||
import sys
|
||||
|
||||
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:
|
||||
in_data = f.read().decode('utf-8', 'backslashreplace')
|
||||
b = [r'\x{:02x}'.format(ord(c)) for c in in_data]
|
||||
with open(sys.argv[1], "rb") as f:
|
||||
in_data = f.read().decode("utf-8", "backslashreplace")
|
||||
b = [r"\x{:02x}".format(ord(c)) for c in in_data]
|
||||
|
||||
out_data = "const char {0}[] = \"".format(sys.argv[2])
|
||||
out_data += "".join(b) + "\";"
|
||||
out_data = 'const char {0}[] = "'.format(sys.argv[2])
|
||||
out_data += "".join(b) + '";'
|
||||
|
||||
with open(sys.argv[3], 'w') as f:
|
||||
with open(sys.argv[3], "w") as f:
|
||||
f.write(out_data)
|
||||
|
@ -21,7 +21,9 @@
|
||||
|
||||
import os
|
||||
|
||||
builddir = os.environ.get('UNINSTALLED_GLIB_BUILDDIR')
|
||||
builddir = os.environ.get("UNINSTALLED_GLIB_BUILDDIR")
|
||||
|
||||
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>
|
||||
|
||||
import sys
|
||||
import re
|
||||
from os import path
|
||||
|
||||
from . import config
|
||||
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:
|
||||
def __init__(self, ifaces):
|
||||
self.ifaces = ifaces
|
||||
@ -57,23 +59,36 @@ class DocbookCodeGenerator:
|
||||
max_signature_len = max(len(a.signature), max_signature_len)
|
||||
|
||||
if in_synopsis:
|
||||
self.out.write('<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), ''))
|
||||
self.out.write(
|
||||
'<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:
|
||||
self.out.write('%s%*s ('
|
||||
%(m.name, max_method_len - len(m.name), ''))
|
||||
self.out.write("%s%*s (" % (m.name, max_method_len - len(m.name), ""))
|
||||
count = 0
|
||||
for a in m.in_args:
|
||||
if (count > 0):
|
||||
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))
|
||||
if count > 0:
|
||||
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)
|
||||
)
|
||||
count = count + 1
|
||||
for a in m.out_args:
|
||||
if (count > 0):
|
||||
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))
|
||||
if count > 0:
|
||||
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)
|
||||
)
|
||||
count = count + 1
|
||||
self.out.write(');\n')
|
||||
self.out.write(");\n")
|
||||
|
||||
def print_signal_prototype(self, i, s, in_synopsis):
|
||||
max_signal_len = 0
|
||||
@ -93,18 +108,28 @@ class DocbookCodeGenerator:
|
||||
max_signature_len = max(len(a.signature), max_signature_len)
|
||||
|
||||
if in_synopsis:
|
||||
self.out.write('<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), ''))
|
||||
self.out.write(
|
||||
'<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:
|
||||
self.out.write('%s%*s ('
|
||||
%(s.name, max_signal_len - len(s.name), ''))
|
||||
self.out.write("%s%*s (" % (s.name, max_signal_len - len(s.name), ""))
|
||||
count = 0
|
||||
for a in s.args:
|
||||
if (count > 0):
|
||||
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))
|
||||
if count > 0:
|
||||
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)
|
||||
)
|
||||
count = count + 1
|
||||
self.out.write(');\n')
|
||||
self.out.write(");\n")
|
||||
|
||||
def print_property_prototype(self, i, p, in_synopsis):
|
||||
max_property_len = 0
|
||||
@ -122,109 +147,181 @@ class DocbookCodeGenerator:
|
||||
max_signature_len = max(len(p.signature), max_signature_len)
|
||||
|
||||
if in_synopsis:
|
||||
self.out.write('<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), ''))
|
||||
self.out.write(
|
||||
'<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:
|
||||
self.out.write('%s%*s'
|
||||
%(p.name, max_property_len - len(p.name), ''))
|
||||
self.out.write("%s%*s" % (p.name, max_property_len - len(p.name), ""))
|
||||
if p.readable and p.writable:
|
||||
access = 'readwrite'
|
||||
access = "readwrite"
|
||||
elif p.readable:
|
||||
access = 'readable '
|
||||
access = "readable "
|
||||
else:
|
||||
access = 'writable '
|
||||
self.out.write(' %s %s\n'%(access, p.signature))
|
||||
|
||||
access = "writable "
|
||||
self.out.write(" %s %s\n" % (access, p.signature))
|
||||
|
||||
def print_synopsis_methods(self, i):
|
||||
self.out.write(' <refsynopsisdiv role="synopsis">\n'%())
|
||||
self.out.write(' <title role="synopsis.title">Methods</title>\n'%())
|
||||
self.out.write(' <synopsis>\n'%())
|
||||
self.out.write(' <refsynopsisdiv role="synopsis">\n')
|
||||
self.out.write(' <title role="synopsis.title">Methods</title>\n')
|
||||
self.out.write(" <synopsis>\n")
|
||||
for m in i.methods:
|
||||
self.print_method_prototype(i, m, in_synopsis=True)
|
||||
self.out.write('</synopsis>\n'%())
|
||||
self.out.write(' </refsynopsisdiv>\n'%())
|
||||
self.out.write("</synopsis>\n")
|
||||
self.out.write(" </refsynopsisdiv>\n")
|
||||
|
||||
def print_synopsis_signals(self, i):
|
||||
self.out.write(' <refsect1 role="signal_proto">\n'%())
|
||||
self.out.write(' <title role="signal_proto.title">Signals</title>\n'%())
|
||||
self.out.write(' <synopsis>\n'%())
|
||||
self.out.write(' <refsect1 role="signal_proto">\n')
|
||||
self.out.write(' <title role="signal_proto.title">Signals</title>\n')
|
||||
self.out.write(" <synopsis>\n")
|
||||
for s in i.signals:
|
||||
self.print_signal_prototype(i, s, in_synopsis=True)
|
||||
self.out.write('</synopsis>\n'%())
|
||||
self.out.write(' </refsect1>\n'%())
|
||||
self.out.write("</synopsis>\n")
|
||||
self.out.write(" </refsect1>\n")
|
||||
|
||||
def print_synopsis_properties(self, i):
|
||||
self.out.write(' <refsect1 role="properties">\n'%())
|
||||
self.out.write(' <title role="properties.title">Properties</title>\n'%())
|
||||
self.out.write(' <synopsis>\n'%())
|
||||
self.out.write(' <refsect1 role="properties">\n')
|
||||
self.out.write(' <title role="properties.title">Properties</title>\n')
|
||||
self.out.write(" <synopsis>\n")
|
||||
for p in i.properties:
|
||||
self.print_property_prototype(i, p, in_synopsis=True)
|
||||
self.out.write('</synopsis>\n'%())
|
||||
self.out.write(' </refsect1>\n'%())
|
||||
self.out.write("</synopsis>\n")
|
||||
self.out.write(" </refsect1>\n")
|
||||
|
||||
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(' <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.out.write(
|
||||
'<refsect2 role="method" id="gdbus-method-%s.%s">\n'
|
||||
% (utils.dots_to_hyphens(i.name), m.name)
|
||||
)
|
||||
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.out.write('</programlisting>\n')
|
||||
self.out.write('%s\n'%(self.expand_paras(m.doc_string, True)))
|
||||
self.out.write("</programlisting>\n")
|
||||
self.out.write("%s\n" % (self.expand_paras(m.doc_string, True)))
|
||||
if m.in_args or m.out_args:
|
||||
self.out.write('<variablelist role="params">\n')
|
||||
for a in m.in_args:
|
||||
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(' <listitem>%s</listitem>\n'%(self.expand_paras(a.doc_string, True)))
|
||||
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(
|
||||
" <listitem>%s</listitem>\n"
|
||||
% (self.expand_paras(a.doc_string, True))
|
||||
)
|
||||
self.out.write("</varlistentry>\n")
|
||||
for a in m.out_args:
|
||||
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(' <listitem>%s</listitem>\n'%(self.expand_paras(a.doc_string, True)))
|
||||
self.out.write('</varlistentry>\n'%())
|
||||
self.out.write('</variablelist>\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(
|
||||
" <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:
|
||||
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:
|
||||
self.out.write('<warning><para>The %s() method is deprecated.</para></warning>'%(m.name))
|
||||
self.out.write('</refsect2>\n')
|
||||
self.out.write(
|
||||
"<warning><para>The %s() method is deprecated.</para></warning>"
|
||||
% (m.name)
|
||||
)
|
||||
self.out.write("</refsect2>\n")
|
||||
|
||||
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(' <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('<programlisting>\n')
|
||||
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(
|
||||
' <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.out.write('</programlisting>\n')
|
||||
self.out.write('%s\n'%(self.expand_paras(s.doc_string, True)))
|
||||
self.out.write("</programlisting>\n")
|
||||
self.out.write("%s\n" % (self.expand_paras(s.doc_string, True)))
|
||||
if s.args:
|
||||
self.out.write('<variablelist role="params">\n')
|
||||
for a in s.args:
|
||||
self.out.write('<varlistentry>\n'%())
|
||||
self.out.write(' <term><literal>%s <parameter>%s</parameter></literal>:</term>\n'%(a.signature, a.name))
|
||||
self.out.write(' <listitem>%s</listitem>\n'%(self.expand_paras(a.doc_string, True)))
|
||||
self.out.write('</varlistentry>\n'%())
|
||||
self.out.write('</variablelist>\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(
|
||||
" <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:
|
||||
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:
|
||||
self.out.write('<warning><para>The "%s" signal is deprecated.</para></warning>'%(s.name))
|
||||
self.out.write('</refsect2>\n')
|
||||
self.out.write(
|
||||
'<warning><para>The "%s" signal is deprecated.</para></warning>'
|
||||
% (s.name)
|
||||
)
|
||||
self.out.write("</refsect2>\n")
|
||||
|
||||
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(' <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('<programlisting>\n')
|
||||
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(
|
||||
' <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.out.write('</programlisting>\n')
|
||||
self.out.write('%s\n'%(self.expand_paras(p.doc_string, True)))
|
||||
self.out.write("</programlisting>\n")
|
||||
self.out.write("%s\n" % (self.expand_paras(p.doc_string, True)))
|
||||
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:
|
||||
self.out.write('<warning><para>The "%s" property is deprecated.</para></warning>'%(p.name))
|
||||
self.out.write('</refsect2>\n')
|
||||
self.out.write(
|
||||
'<warning><para>The "%s" property is deprecated.</para></warning>'
|
||||
% (p.name)
|
||||
)
|
||||
self.out.write("</refsect2>\n")
|
||||
|
||||
def expand(self, s, expandParamsAndConstants):
|
||||
for key in self.expand_member_dict_keys:
|
||||
@ -233,9 +330,17 @@ class DocbookCodeGenerator:
|
||||
s = s.replace(key, self.expand_iface_dict[key])
|
||||
if expandParamsAndConstants:
|
||||
# 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>
|
||||
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
|
||||
|
||||
def expand_paras(self, s, expandParamsAndConstants):
|
||||
@ -248,44 +353,73 @@ class DocbookCodeGenerator:
|
||||
self.expand_member_dict = {}
|
||||
self.expand_iface_dict = {}
|
||||
for i in self.ifaces:
|
||||
key = '#%s'%(i.name)
|
||||
value = '<link linkend="gdbus-interface-%s.top_of_page">%s</link>'%(utils.dots_to_hyphens(i.name), 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,
|
||||
)
|
||||
self.expand_iface_dict[key] = value
|
||||
for m in i.methods:
|
||||
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)
|
||||
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,
|
||||
)
|
||||
self.expand_member_dict[key] = value
|
||||
for s in i.signals:
|
||||
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)
|
||||
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,
|
||||
)
|
||||
self.expand_member_dict[key] = value
|
||||
for p in i.properties:
|
||||
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)
|
||||
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,
|
||||
)
|
||||
self.expand_member_dict[key] = value
|
||||
# Make sure to expand the keys in reverse order so e.g. #org.foo.Iface:MediaCompat
|
||||
# is evaluated before #org.foo.Iface:Media ...
|
||||
self.expand_member_dict_keys = sorted(self.expand_member_dict.keys(), reverse=True)
|
||||
self.expand_iface_dict_keys = sorted(self.expand_iface_dict.keys(), reverse=True)
|
||||
self.expand_member_dict_keys = sorted(
|
||||
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):
|
||||
for i in self.ifaces:
|
||||
self.out = open(path.join(outdir, '%s-%s.xml'%(docbook, i.name)), 'w')
|
||||
self.out.write(''%())
|
||||
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(' "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(' <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(' <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 = open(path.join(outdir, "%s-%s.xml" % (docbook, i.name)), "w")
|
||||
self.out.write("")
|
||||
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(
|
||||
' "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(" <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(
|
||||
' <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(' <refname>%s</refname>'%(i.name))
|
||||
self.out.write(' <refpurpose>%s</refpurpose>'%(i.doc_string_brief))
|
||||
self.out.write(' </refnamediv>'%())
|
||||
self.out.write(" <refnamediv>")
|
||||
self.out.write(" <refname>%s</refname>" % (i.name))
|
||||
self.out.write(" <refpurpose>%s</refpurpose>" % (i.doc_string_brief))
|
||||
self.out.write(" </refnamediv>")
|
||||
|
||||
if len(i.methods) > 0:
|
||||
self.print_synopsis_methods(i)
|
||||
@ -294,36 +428,49 @@ class DocbookCodeGenerator:
|
||||
if len(i.properties) > 0:
|
||||
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(' <title role="desc.title">Description</title>\n'%())
|
||||
self.out.write(' %s\n'%(self.expand_paras(i.doc_string, True)))
|
||||
self.out.write(
|
||||
'<refsect1 role="desc" id="gdbus-interface-%s">\n'
|
||||
% (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:
|
||||
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:
|
||||
self.out.write('<warning><para>The %s interface is deprecated.</para></warning>'%(i.name))
|
||||
self.out.write('</refsect1>\n'%())
|
||||
self.out.write(
|
||||
"<warning><para>The %s interface is deprecated.</para></warning>"
|
||||
% (i.name)
|
||||
)
|
||||
self.out.write("</refsect1>\n")
|
||||
|
||||
if len(i.methods) > 0:
|
||||
self.out.write('<refsect1 role="details" id="gdbus-methods-%s">\n'%(i.name))
|
||||
self.out.write(' <title role="details.title">Method Details</title>\n'%())
|
||||
self.out.write(
|
||||
'<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:
|
||||
self.print_method(i, m)
|
||||
self.out.write('</refsect1>\n'%())
|
||||
self.out.write("</refsect1>\n")
|
||||
|
||||
if len(i.signals) > 0:
|
||||
self.out.write('<refsect1 role="details" id="gdbus-signals-%s">\n'%(i.name))
|
||||
self.out.write(' <title role="details.title">Signal Details</title>\n'%())
|
||||
self.out.write(
|
||||
'<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:
|
||||
self.print_signal(i, s)
|
||||
self.out.write('</refsect1>\n'%())
|
||||
self.out.write("</refsect1>\n")
|
||||
|
||||
if len(i.properties) > 0:
|
||||
self.out.write('<refsect1 role="details" id="gdbus-properties-%s">\n'%(i.name))
|
||||
self.out.write(' <title role="details.title">Property Details</title>\n'%())
|
||||
self.out.write(
|
||||
'<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:
|
||||
self.print_property(i, s)
|
||||
self.out.write('</refsect1>\n'%())
|
||||
|
||||
self.out.write('</refentry>\n')
|
||||
self.out.write('\n')
|
||||
self.out.write("</refsect1>\n")
|
||||
|
||||
self.out.write("</refentry>\n")
|
||||
self.out.write("\n")
|
||||
|
@ -32,30 +32,35 @@ from . import codegen
|
||||
from . import codegen_docbook
|
||||
from .utils import print_error, print_warning
|
||||
|
||||
|
||||
def find_arg(arg_list, arg_name):
|
||||
for a in arg_list:
|
||||
if a.name == arg_name:
|
||||
return a
|
||||
return None
|
||||
|
||||
|
||||
def find_method(iface, method):
|
||||
for m in iface.methods:
|
||||
if m.name == method:
|
||||
return m
|
||||
return None
|
||||
|
||||
|
||||
def find_signal(iface, signal):
|
||||
for m in iface.signals:
|
||||
if m.name == signal:
|
||||
return m
|
||||
return None
|
||||
|
||||
|
||||
def find_prop(iface, prop):
|
||||
for m in iface.properties:
|
||||
if m.name == prop:
|
||||
return m
|
||||
return None
|
||||
|
||||
|
||||
def apply_annotation(iface_list, iface, method, signal, prop, arg, key, value):
|
||||
iface_obj = None
|
||||
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))
|
||||
if 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)
|
||||
if (arg_obj is None):
|
||||
print_error('No arg "{}" on method "{}" on interface "{}"'.format(arg, method, iface))
|
||||
if arg_obj is None:
|
||||
print_error(
|
||||
'No arg "{}" on method "{}" on interface "{}"'.format(
|
||||
arg, method, iface
|
||||
)
|
||||
)
|
||||
target_obj = arg_obj
|
||||
else:
|
||||
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))
|
||||
if arg:
|
||||
arg_obj = find_arg(signal_obj.args, arg)
|
||||
if (arg_obj is None):
|
||||
print_error('No arg "{}" on signal "{}" on interface "{}"'.format(arg, signal, iface))
|
||||
if arg_obj is None:
|
||||
print_error(
|
||||
'No arg "{}" on signal "{}" on interface "{}"'.format(
|
||||
arg, signal, iface
|
||||
)
|
||||
)
|
||||
target_obj = arg_obj
|
||||
else:
|
||||
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):
|
||||
# apply annotations given on the command line
|
||||
for (what, key, value) in annotation_list:
|
||||
pos = what.find('::')
|
||||
pos = what.find("::")
|
||||
if pos != -1:
|
||||
# signal
|
||||
iface = what[0:pos];
|
||||
signal = what[pos + 2:]
|
||||
pos = signal.find('[')
|
||||
iface = what[0:pos]
|
||||
signal = what[pos + 2 :]
|
||||
pos = signal.find("[")
|
||||
if pos != -1:
|
||||
arg = signal[pos + 1:]
|
||||
arg = signal[pos + 1 :]
|
||||
signal = signal[0:pos]
|
||||
pos = arg.find(']')
|
||||
pos = arg.find("]")
|
||||
arg = arg[0:pos]
|
||||
apply_annotation(iface_list, iface, None, signal, None, arg, key, value)
|
||||
else:
|
||||
apply_annotation(iface_list, iface, None, signal, None, None, key, value)
|
||||
apply_annotation(
|
||||
iface_list, iface, None, signal, None, None, key, value
|
||||
)
|
||||
else:
|
||||
pos = what.find(':')
|
||||
pos = what.find(":")
|
||||
if pos != -1:
|
||||
# property
|
||||
iface = what[0:pos];
|
||||
prop = what[pos + 1:]
|
||||
iface = what[0:pos]
|
||||
prop = what[pos + 1 :]
|
||||
apply_annotation(iface_list, iface, None, None, prop, None, key, value)
|
||||
else:
|
||||
pos = what.find('()')
|
||||
pos = what.find("()")
|
||||
if pos != -1:
|
||||
# method
|
||||
combined = what[0:pos]
|
||||
pos = combined.rfind('.')
|
||||
pos = combined.rfind(".")
|
||||
iface = combined[0:pos]
|
||||
method = combined[pos + 1:]
|
||||
pos = what.find('[')
|
||||
method = combined[pos + 1 :]
|
||||
pos = what.find("[")
|
||||
if pos != -1:
|
||||
arg = what[pos + 1:]
|
||||
pos = arg.find(']')
|
||||
arg = what[pos + 1 :]
|
||||
pos = arg.find("]")
|
||||
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:
|
||||
apply_annotation(iface_list, iface, method, None, None, None, key, value)
|
||||
apply_annotation(
|
||||
iface_list, iface, method, None, None, None, key, value
|
||||
)
|
||||
else:
|
||||
# must be an interface
|
||||
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():
|
||||
arg_parser = argparse.ArgumentParser(description='D-Bus code and documentation generator')
|
||||
arg_parser.add_argument('files', metavar='FILE', nargs='+',
|
||||
help='D-Bus introspection XML file')
|
||||
arg_parser.add_argument('--xml-files', metavar='FILE', action='append', default=[],
|
||||
help=argparse.SUPPRESS)
|
||||
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('--c-namespace', metavar='NAMESPACE', default='',
|
||||
help='The namespace to use for generated C code')
|
||||
arg_parser.add_argument('--c-generate-object-manager', action='store_true',
|
||||
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')
|
||||
arg_parser = argparse.ArgumentParser(
|
||||
description="D-Bus code and documentation generator"
|
||||
)
|
||||
arg_parser.add_argument(
|
||||
"files", metavar="FILE", nargs="+", help="D-Bus introspection XML file"
|
||||
)
|
||||
arg_parser.add_argument(
|
||||
"--xml-files",
|
||||
metavar="FILE",
|
||||
action="append",
|
||||
default=[],
|
||||
help=argparse.SUPPRESS,
|
||||
)
|
||||
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(
|
||||
"--c-namespace",
|
||||
metavar="NAMESPACE",
|
||||
default="",
|
||||
help="The namespace to use for generated C code",
|
||||
)
|
||||
arg_parser.add_argument(
|
||||
"--c-generate-object-manager",
|
||||
action="store_true",
|
||||
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.add_argument('--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('--body', action='store_true',
|
||||
help='Generate C code')
|
||||
group.add_argument('--interface-info-header', action='store_true',
|
||||
help='Generate GDBusInterfaceInfo C header')
|
||||
group.add_argument('--interface-info-body', action='store_true',
|
||||
help='Generate GDBusInterfaceInfo C code')
|
||||
group.add_argument(
|
||||
"--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("--body", action="store_true", help="Generate C code")
|
||||
group.add_argument(
|
||||
"--interface-info-header",
|
||||
action="store_true",
|
||||
help="Generate GDBusInterfaceInfo C header",
|
||||
)
|
||||
group.add_argument(
|
||||
"--interface-info-body",
|
||||
action="store_true",
|
||||
help="Generate GDBusInterfaceInfo C code",
|
||||
)
|
||||
|
||||
group = arg_parser.add_mutually_exclusive_group()
|
||||
group.add_argument('--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", metavar="FILE", help="Write output into the specified file"
|
||||
)
|
||||
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:
|
||||
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
|
||||
args.output is not None):
|
||||
print_error('Using --generate-c-code or --generate-docbook and '
|
||||
'--output at the same time is not allowed')
|
||||
if (
|
||||
args.generate_c_code is not None or args.generate_docbook is not None
|
||||
) and args.output is not None:
|
||||
print_error(
|
||||
"Using --generate-c-code or --generate-docbook and "
|
||||
"--output at the same time is not allowed"
|
||||
)
|
||||
|
||||
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)
|
||||
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
|
||||
elif args.header:
|
||||
if args.output is None:
|
||||
print_error('Using --header requires --output')
|
||||
print_error("Using --header requires --output")
|
||||
|
||||
h_file = args.output
|
||||
header_name = os.path.basename(h_file)
|
||||
elif args.body:
|
||||
if args.output is None:
|
||||
print_error('Using --body requires --output')
|
||||
print_error("Using --body requires --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:
|
||||
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:
|
||||
print_error('--c-generate-object-manager is incompatible with '
|
||||
'--interface-info-header')
|
||||
print_error(
|
||||
"--c-generate-object-manager is incompatible with "
|
||||
"--interface-info-header"
|
||||
)
|
||||
|
||||
h_file = args.output
|
||||
header_name = os.path.basename(h_file)
|
||||
elif args.interface_info_body:
|
||||
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:
|
||||
print_error('--c-generate-object-manager is incompatible with '
|
||||
'--interface-info-body')
|
||||
print_error(
|
||||
"--c-generate-object-manager is incompatible with "
|
||||
"--interface-info-body"
|
||||
)
|
||||
|
||||
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,
|
||||
# because that’s when gdbus-codegen was introduced. Support 1, 2 or 3
|
||||
# component versions, but ignore the micro component if it’s present.
|
||||
if args.glib_min_required:
|
||||
try:
|
||||
parts = args.glib_min_required.split('.', 3)
|
||||
glib_min_required = (int(parts[0]),
|
||||
int(parts[1] if len(parts) > 1 else 0))
|
||||
parts = args.glib_min_required.split(".", 3)
|
||||
glib_min_required = (int(parts[0]), int(parts[1] if len(parts) > 1 else 0))
|
||||
# Ignore micro component, but still validate it:
|
||||
_ = int(parts[2] if len(parts) > 2 else 0)
|
||||
except (ValueError, IndexError):
|
||||
print_error('Unrecognized --glib-min-required string ‘{}’'.format(
|
||||
args.glib_min_required))
|
||||
print_error(
|
||||
"Unrecognized --glib-min-required string ‘{}’".format(
|
||||
args.glib_min_required
|
||||
)
|
||||
)
|
||||
|
||||
if glib_min_required < (2, 30):
|
||||
print_error('Invalid --glib-min-required string ‘{}’: minimum '
|
||||
'version is 2.30'.format(args.glib_min_required))
|
||||
print_error(
|
||||
"Invalid --glib-min-required string ‘{}’: minimum "
|
||||
"version is 2.30".format(args.glib_min_required)
|
||||
)
|
||||
else:
|
||||
glib_min_required = (2, 30)
|
||||
|
||||
# And the maximum GLib version.
|
||||
if args.glib_max_allowed:
|
||||
try:
|
||||
parts = args.glib_max_allowed.split('.', 3)
|
||||
glib_max_allowed = (int(parts[0]),
|
||||
int(parts[1] if len(parts) > 1 else 0))
|
||||
parts = args.glib_max_allowed.split(".", 3)
|
||||
glib_max_allowed = (int(parts[0]), int(parts[1] if len(parts) > 1 else 0))
|
||||
# Ignore micro component, but still validate it:
|
||||
_ = int(parts[2] if len(parts) > 2 else 0)
|
||||
except (ValueError, IndexError):
|
||||
print_error('Unrecognized --glib-max-allowed string ‘{}’'.format(
|
||||
args.glib_max_allowed))
|
||||
print_error(
|
||||
"Unrecognized --glib-max-allowed string ‘{}’".format(
|
||||
args.glib_max_allowed
|
||||
)
|
||||
)
|
||||
else:
|
||||
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_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.
|
||||
glib_max_allowed = \
|
||||
(glib_max_allowed[0], glib_max_allowed[1] + (glib_max_allowed[1] % 2))
|
||||
glib_max_allowed = (
|
||||
glib_max_allowed[0],
|
||||
glib_max_allowed[1] + (glib_max_allowed[1] % 2),
|
||||
)
|
||||
|
||||
if glib_max_allowed < glib_min_required:
|
||||
print_error('Invalid versions: --glib-min-required ({}) must be '
|
||||
'less than or equal to --glib-max-allowed ({})'.format(glib_min_required, glib_max_allowed))
|
||||
print_error(
|
||||
"Invalid versions: --glib-min-required ({}) must be "
|
||||
"less than or equal to --glib-max-allowed ({})".format(
|
||||
glib_min_required, glib_max_allowed
|
||||
)
|
||||
)
|
||||
|
||||
all_ifaces = []
|
||||
input_files_basenames = []
|
||||
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()
|
||||
parsed_ifaces = parser.parse_dbus_xml(xml_data,
|
||||
h_type_implies_unix_fd=(glib_min_required >= (2, 64)))
|
||||
parsed_ifaces = parser.parse_dbus_xml(
|
||||
xml_data, h_type_implies_unix_fd=(glib_min_required >= (2, 64))
|
||||
)
|
||||
all_ifaces.extend(parsed_ifaces)
|
||||
input_files_basenames.append(os.path.basename(fname))
|
||||
|
||||
@ -307,13 +416,14 @@ def codegen_main():
|
||||
i.post_process(args.interface_prefix, args.c_namespace)
|
||||
|
||||
docbook = args.generate_docbook
|
||||
docbook_gen = codegen_docbook.DocbookCodeGenerator(all_ifaces);
|
||||
docbook_gen = codegen_docbook.DocbookCodeGenerator(all_ifaces)
|
||||
if docbook:
|
||||
ret = docbook_gen.generate(docbook, args.output_directory)
|
||||
docbook_gen.generate(docbook, args.output_directory)
|
||||
|
||||
if args.header:
|
||||
with open(h_file, 'w') as outfile:
|
||||
gen = codegen.HeaderCodeGenerator(all_ifaces,
|
||||
with open(h_file, "w") as outfile:
|
||||
gen = codegen.HeaderCodeGenerator(
|
||||
all_ifaces,
|
||||
args.c_namespace,
|
||||
args.c_generate_object_manager,
|
||||
args.c_generate_autocleanup,
|
||||
@ -323,12 +433,14 @@ def codegen_main():
|
||||
glib_min_required,
|
||||
args.symbol_decorator,
|
||||
args.symbol_decorator_header,
|
||||
outfile)
|
||||
outfile,
|
||||
)
|
||||
gen.generate()
|
||||
|
||||
if args.body:
|
||||
with open(c_file, 'w') as outfile:
|
||||
gen = codegen.CodeGenerator(all_ifaces,
|
||||
with open(c_file, "w") as outfile:
|
||||
gen = codegen.CodeGenerator(
|
||||
all_ifaces,
|
||||
args.c_namespace,
|
||||
args.c_generate_object_manager,
|
||||
header_name,
|
||||
@ -336,12 +448,14 @@ def codegen_main():
|
||||
docbook_gen,
|
||||
glib_min_required,
|
||||
args.symbol_decorator_define,
|
||||
outfile)
|
||||
outfile,
|
||||
)
|
||||
gen.generate()
|
||||
|
||||
if args.interface_info_header:
|
||||
with open(h_file, 'w') as outfile:
|
||||
gen = codegen.InterfaceInfoHeaderCodeGenerator(all_ifaces,
|
||||
with open(h_file, "w") as outfile:
|
||||
gen = codegen.InterfaceInfoHeaderCodeGenerator(
|
||||
all_ifaces,
|
||||
args.c_namespace,
|
||||
header_name,
|
||||
input_files_basenames,
|
||||
@ -349,21 +463,25 @@ def codegen_main():
|
||||
glib_min_required,
|
||||
args.symbol_decorator,
|
||||
args.symbol_decorator_header,
|
||||
outfile)
|
||||
outfile,
|
||||
)
|
||||
gen.generate()
|
||||
|
||||
if args.interface_info_body:
|
||||
with open(c_file, 'w') as outfile:
|
||||
gen = codegen.InterfaceInfoBodyCodeGenerator(all_ifaces,
|
||||
with open(c_file, "w") as outfile:
|
||||
gen = codegen.InterfaceInfoBodyCodeGenerator(
|
||||
all_ifaces,
|
||||
args.c_namespace,
|
||||
header_name,
|
||||
input_files_basenames,
|
||||
glib_min_required,
|
||||
args.symbol_decorator_define,
|
||||
outfile)
|
||||
outfile,
|
||||
)
|
||||
gen.generate()
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
codegen_main()
|
||||
|
@ -22,22 +22,30 @@
|
||||
from . import utils
|
||||
from .utils import print_error
|
||||
|
||||
|
||||
class Annotation:
|
||||
def __init__(self, key, value):
|
||||
self.key = key
|
||||
self.value = value
|
||||
self.annotations = []
|
||||
self.since = ''
|
||||
self.since = ""
|
||||
|
||||
def post_process(self, interface_prefix, cns, cns_upper, cns_lower, container):
|
||||
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):
|
||||
self.key_lower = overridden_key.lower()
|
||||
else:
|
||||
if 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:
|
||||
self.since = utils.lookup_since(self.annotations)
|
||||
@ -47,13 +55,14 @@ class Annotation:
|
||||
for a in self.annotations:
|
||||
a.post_process(interface_prefix, cns, cns_upper, cns_lower, self)
|
||||
|
||||
|
||||
class Arg:
|
||||
def __init__(self, name, signature):
|
||||
self.name = name
|
||||
self.signature = signature
|
||||
self.annotations = []
|
||||
self.doc_string = ''
|
||||
self.since = ''
|
||||
self.doc_string = ""
|
||||
self.since = ""
|
||||
|
||||
def post_process(self, interface_prefix, cns, cns_upper, cns_lower, arg_number):
|
||||
if len(self.doc_string) == 0:
|
||||
@ -62,195 +71,198 @@ class Arg:
|
||||
self.since = utils.lookup_since(self.annotations)
|
||||
|
||||
if self.name is None:
|
||||
self.name = 'unnamed_arg%d'%arg_number
|
||||
self.name = "unnamed_arg%d" % arg_number
|
||||
# default to GVariant
|
||||
self.ctype_in_g = 'GVariant *'
|
||||
self.ctype_in = 'GVariant *'
|
||||
self.ctype_in_dup = 'GVariant *'
|
||||
self.ctype_out = 'GVariant **'
|
||||
self.gtype = 'G_TYPE_VARIANT'
|
||||
self.free_func = 'g_variant_unref'
|
||||
self.format_in = '@' + self.signature
|
||||
self.format_out = '@' + self.signature
|
||||
self.gvariant_get = 'XXX'
|
||||
self.gvalue_get = 'g_value_get_variant'
|
||||
self.array_annotation = ''
|
||||
self.ctype_in_g = "GVariant *"
|
||||
self.ctype_in = "GVariant *"
|
||||
self.ctype_in_dup = "GVariant *"
|
||||
self.ctype_out = "GVariant **"
|
||||
self.gtype = "G_TYPE_VARIANT"
|
||||
self.free_func = "g_variant_unref"
|
||||
self.format_in = "@" + self.signature
|
||||
self.format_out = "@" + self.signature
|
||||
self.gvariant_get = "XXX"
|
||||
self.gvalue_get = "g_value_get_variant"
|
||||
self.array_annotation = ""
|
||||
|
||||
if not utils.lookup_annotation(self.annotations, 'org.gtk.GDBus.C.ForceGVariant'):
|
||||
if self.signature == 'b':
|
||||
self.ctype_in_g = 'gboolean '
|
||||
self.ctype_in = 'gboolean '
|
||||
self.ctype_out = 'gboolean *'
|
||||
self.gtype = 'G_TYPE_BOOLEAN'
|
||||
if not utils.lookup_annotation(
|
||||
self.annotations, "org.gtk.GDBus.C.ForceGVariant"
|
||||
):
|
||||
if self.signature == "b":
|
||||
self.ctype_in_g = "gboolean "
|
||||
self.ctype_in = "gboolean "
|
||||
self.ctype_out = "gboolean *"
|
||||
self.gtype = "G_TYPE_BOOLEAN"
|
||||
self.free_func = None
|
||||
self.format_in = 'b'
|
||||
self.format_out = 'b'
|
||||
self.gvariant_get = 'g_variant_get_boolean'
|
||||
self.gvalue_get = 'g_value_get_boolean'
|
||||
elif self.signature == 'y':
|
||||
self.ctype_in_g = 'guchar '
|
||||
self.ctype_in = 'guchar '
|
||||
self.ctype_out = 'guchar *'
|
||||
self.gtype = 'G_TYPE_UCHAR'
|
||||
self.format_in = "b"
|
||||
self.format_out = "b"
|
||||
self.gvariant_get = "g_variant_get_boolean"
|
||||
self.gvalue_get = "g_value_get_boolean"
|
||||
elif self.signature == "y":
|
||||
self.ctype_in_g = "guchar "
|
||||
self.ctype_in = "guchar "
|
||||
self.ctype_out = "guchar *"
|
||||
self.gtype = "G_TYPE_UCHAR"
|
||||
self.free_func = None
|
||||
self.format_in = 'y'
|
||||
self.format_out = 'y'
|
||||
self.gvariant_get = 'g_variant_get_byte'
|
||||
self.gvalue_get = 'g_value_get_uchar'
|
||||
elif self.signature == 'n':
|
||||
self.ctype_in_g = 'gint '
|
||||
self.ctype_in = 'gint16 '
|
||||
self.ctype_out = 'gint16 *'
|
||||
self.gtype = 'G_TYPE_INT'
|
||||
self.format_in = "y"
|
||||
self.format_out = "y"
|
||||
self.gvariant_get = "g_variant_get_byte"
|
||||
self.gvalue_get = "g_value_get_uchar"
|
||||
elif self.signature == "n":
|
||||
self.ctype_in_g = "gint "
|
||||
self.ctype_in = "gint16 "
|
||||
self.ctype_out = "gint16 *"
|
||||
self.gtype = "G_TYPE_INT"
|
||||
self.free_func = None
|
||||
self.format_in = 'n'
|
||||
self.format_out = 'n'
|
||||
self.gvariant_get = 'g_variant_get_int16'
|
||||
self.gvalue_get = 'g_value_get_int'
|
||||
elif self.signature == 'q':
|
||||
self.ctype_in_g = 'guint '
|
||||
self.ctype_in = 'guint16 '
|
||||
self.ctype_out = 'guint16 *'
|
||||
self.gtype = 'G_TYPE_UINT'
|
||||
self.format_in = "n"
|
||||
self.format_out = "n"
|
||||
self.gvariant_get = "g_variant_get_int16"
|
||||
self.gvalue_get = "g_value_get_int"
|
||||
elif self.signature == "q":
|
||||
self.ctype_in_g = "guint "
|
||||
self.ctype_in = "guint16 "
|
||||
self.ctype_out = "guint16 *"
|
||||
self.gtype = "G_TYPE_UINT"
|
||||
self.free_func = None
|
||||
self.format_in = 'q'
|
||||
self.format_out = 'q'
|
||||
self.gvariant_get = 'g_variant_get_uint16'
|
||||
self.gvalue_get = 'g_value_get_uint'
|
||||
elif self.signature == 'i':
|
||||
self.ctype_in_g = 'gint '
|
||||
self.ctype_in = 'gint '
|
||||
self.ctype_out = 'gint *'
|
||||
self.gtype = 'G_TYPE_INT'
|
||||
self.format_in = "q"
|
||||
self.format_out = "q"
|
||||
self.gvariant_get = "g_variant_get_uint16"
|
||||
self.gvalue_get = "g_value_get_uint"
|
||||
elif self.signature == "i":
|
||||
self.ctype_in_g = "gint "
|
||||
self.ctype_in = "gint "
|
||||
self.ctype_out = "gint *"
|
||||
self.gtype = "G_TYPE_INT"
|
||||
self.free_func = None
|
||||
self.format_in = 'i'
|
||||
self.format_out = 'i'
|
||||
self.gvariant_get = 'g_variant_get_int32'
|
||||
self.gvalue_get = 'g_value_get_int'
|
||||
elif self.signature == 'u':
|
||||
self.ctype_in_g = 'guint '
|
||||
self.ctype_in = 'guint '
|
||||
self.ctype_out = 'guint *'
|
||||
self.gtype = 'G_TYPE_UINT'
|
||||
self.format_in = "i"
|
||||
self.format_out = "i"
|
||||
self.gvariant_get = "g_variant_get_int32"
|
||||
self.gvalue_get = "g_value_get_int"
|
||||
elif self.signature == "u":
|
||||
self.ctype_in_g = "guint "
|
||||
self.ctype_in = "guint "
|
||||
self.ctype_out = "guint *"
|
||||
self.gtype = "G_TYPE_UINT"
|
||||
self.free_func = None
|
||||
self.format_in = 'u'
|
||||
self.format_out = 'u'
|
||||
self.gvariant_get = 'g_variant_get_uint32'
|
||||
self.gvalue_get = 'g_value_get_uint'
|
||||
elif self.signature == 'x':
|
||||
self.ctype_in_g = 'gint64 '
|
||||
self.ctype_in = 'gint64 '
|
||||
self.ctype_out = 'gint64 *'
|
||||
self.gtype = 'G_TYPE_INT64'
|
||||
self.format_in = "u"
|
||||
self.format_out = "u"
|
||||
self.gvariant_get = "g_variant_get_uint32"
|
||||
self.gvalue_get = "g_value_get_uint"
|
||||
elif self.signature == "x":
|
||||
self.ctype_in_g = "gint64 "
|
||||
self.ctype_in = "gint64 "
|
||||
self.ctype_out = "gint64 *"
|
||||
self.gtype = "G_TYPE_INT64"
|
||||
self.free_func = None
|
||||
self.format_in = 'x'
|
||||
self.format_out = 'x'
|
||||
self.gvariant_get = 'g_variant_get_int64'
|
||||
self.gvalue_get = 'g_value_get_int64'
|
||||
elif self.signature == 't':
|
||||
self.ctype_in_g = 'guint64 '
|
||||
self.ctype_in = 'guint64 '
|
||||
self.ctype_out = 'guint64 *'
|
||||
self.gtype = 'G_TYPE_UINT64'
|
||||
self.format_in = "x"
|
||||
self.format_out = "x"
|
||||
self.gvariant_get = "g_variant_get_int64"
|
||||
self.gvalue_get = "g_value_get_int64"
|
||||
elif self.signature == "t":
|
||||
self.ctype_in_g = "guint64 "
|
||||
self.ctype_in = "guint64 "
|
||||
self.ctype_out = "guint64 *"
|
||||
self.gtype = "G_TYPE_UINT64"
|
||||
self.free_func = None
|
||||
self.format_in = 't'
|
||||
self.format_out = 't'
|
||||
self.gvariant_get = 'g_variant_get_uint64'
|
||||
self.gvalue_get = 'g_value_get_uint64'
|
||||
elif self.signature == 'd':
|
||||
self.ctype_in_g = 'gdouble '
|
||||
self.ctype_in = 'gdouble '
|
||||
self.ctype_out = 'gdouble *'
|
||||
self.gtype = 'G_TYPE_DOUBLE'
|
||||
self.format_in = "t"
|
||||
self.format_out = "t"
|
||||
self.gvariant_get = "g_variant_get_uint64"
|
||||
self.gvalue_get = "g_value_get_uint64"
|
||||
elif self.signature == "d":
|
||||
self.ctype_in_g = "gdouble "
|
||||
self.ctype_in = "gdouble "
|
||||
self.ctype_out = "gdouble *"
|
||||
self.gtype = "G_TYPE_DOUBLE"
|
||||
self.free_func = None
|
||||
self.format_in = 'd'
|
||||
self.format_out = 'd'
|
||||
self.gvariant_get = 'g_variant_get_double'
|
||||
self.gvalue_get = 'g_value_get_double'
|
||||
elif self.signature == 's':
|
||||
self.ctype_in_g = 'const gchar *'
|
||||
self.ctype_in = 'const gchar *'
|
||||
self.ctype_in_dup = 'gchar *'
|
||||
self.ctype_out = 'gchar **'
|
||||
self.gtype = 'G_TYPE_STRING'
|
||||
self.free_func = 'g_free'
|
||||
self.format_in = 's'
|
||||
self.format_out = 's'
|
||||
self.gvariant_get = 'g_variant_get_string'
|
||||
self.gvalue_get = 'g_value_get_string'
|
||||
elif self.signature == 'o':
|
||||
self.ctype_in_g = 'const gchar *'
|
||||
self.ctype_in = 'const gchar *'
|
||||
self.ctype_in_dup = 'gchar *'
|
||||
self.ctype_out = 'gchar **'
|
||||
self.gtype = 'G_TYPE_STRING'
|
||||
self.free_func = 'g_free'
|
||||
self.format_in = 'o'
|
||||
self.format_out = 'o'
|
||||
self.gvariant_get = 'g_variant_get_string'
|
||||
self.gvalue_get = 'g_value_get_string'
|
||||
elif self.signature == 'g':
|
||||
self.ctype_in_g = 'const gchar *'
|
||||
self.ctype_in = 'const gchar *'
|
||||
self.ctype_in_dup = 'gchar *'
|
||||
self.ctype_out = 'gchar **'
|
||||
self.gtype = 'G_TYPE_STRING'
|
||||
self.free_func = 'g_free'
|
||||
self.format_in = 'g'
|
||||
self.format_out = 'g'
|
||||
self.gvariant_get = 'g_variant_get_string'
|
||||
self.gvalue_get = 'g_value_get_string'
|
||||
elif self.signature == 'ay':
|
||||
self.ctype_in_g = 'const gchar *'
|
||||
self.ctype_in = 'const gchar *'
|
||||
self.ctype_in_dup = 'gchar *'
|
||||
self.ctype_out = 'gchar **'
|
||||
self.gtype = 'G_TYPE_STRING'
|
||||
self.free_func = 'g_free'
|
||||
self.format_in = '^ay'
|
||||
self.format_out = '^ay'
|
||||
self.gvariant_get = 'g_variant_get_bytestring'
|
||||
self.gvalue_get = 'g_value_get_string'
|
||||
elif self.signature == 'as':
|
||||
self.ctype_in_g = 'const gchar *const *'
|
||||
self.ctype_in = 'const gchar *const *'
|
||||
self.ctype_in_dup = 'gchar **'
|
||||
self.ctype_out = 'gchar ***'
|
||||
self.gtype = 'G_TYPE_STRV'
|
||||
self.free_func = 'g_strfreev'
|
||||
self.format_in = '^as'
|
||||
self.format_out = '^as'
|
||||
self.gvariant_get = 'g_variant_get_strv'
|
||||
self.gvalue_get = 'g_value_get_boxed'
|
||||
self.array_annotation = '(array zero-terminated=1)'
|
||||
elif self.signature == 'ao':
|
||||
self.ctype_in_g = 'const gchar *const *'
|
||||
self.ctype_in = 'const gchar *const *'
|
||||
self.ctype_in_dup = 'gchar **'
|
||||
self.ctype_out = 'gchar ***'
|
||||
self.gtype = 'G_TYPE_STRV'
|
||||
self.free_func = 'g_strfreev'
|
||||
self.format_in = '^ao'
|
||||
self.format_out = '^ao'
|
||||
self.gvariant_get = 'g_variant_get_objv'
|
||||
self.gvalue_get = 'g_value_get_boxed'
|
||||
self.array_annotation = '(array zero-terminated=1)'
|
||||
elif self.signature == 'aay':
|
||||
self.ctype_in_g = 'const gchar *const *'
|
||||
self.ctype_in = 'const gchar *const *'
|
||||
self.ctype_in_dup = 'gchar **'
|
||||
self.ctype_out = 'gchar ***'
|
||||
self.gtype = 'G_TYPE_STRV'
|
||||
self.free_func = 'g_strfreev'
|
||||
self.format_in = '^aay'
|
||||
self.format_out = '^aay'
|
||||
self.gvariant_get = 'g_variant_get_bytestring_array'
|
||||
self.gvalue_get = 'g_value_get_boxed'
|
||||
self.array_annotation = '(array zero-terminated=1)'
|
||||
self.format_in = "d"
|
||||
self.format_out = "d"
|
||||
self.gvariant_get = "g_variant_get_double"
|
||||
self.gvalue_get = "g_value_get_double"
|
||||
elif self.signature == "s":
|
||||
self.ctype_in_g = "const gchar *"
|
||||
self.ctype_in = "const gchar *"
|
||||
self.ctype_in_dup = "gchar *"
|
||||
self.ctype_out = "gchar **"
|
||||
self.gtype = "G_TYPE_STRING"
|
||||
self.free_func = "g_free"
|
||||
self.format_in = "s"
|
||||
self.format_out = "s"
|
||||
self.gvariant_get = "g_variant_get_string"
|
||||
self.gvalue_get = "g_value_get_string"
|
||||
elif self.signature == "o":
|
||||
self.ctype_in_g = "const gchar *"
|
||||
self.ctype_in = "const gchar *"
|
||||
self.ctype_in_dup = "gchar *"
|
||||
self.ctype_out = "gchar **"
|
||||
self.gtype = "G_TYPE_STRING"
|
||||
self.free_func = "g_free"
|
||||
self.format_in = "o"
|
||||
self.format_out = "o"
|
||||
self.gvariant_get = "g_variant_get_string"
|
||||
self.gvalue_get = "g_value_get_string"
|
||||
elif self.signature == "g":
|
||||
self.ctype_in_g = "const gchar *"
|
||||
self.ctype_in = "const gchar *"
|
||||
self.ctype_in_dup = "gchar *"
|
||||
self.ctype_out = "gchar **"
|
||||
self.gtype = "G_TYPE_STRING"
|
||||
self.free_func = "g_free"
|
||||
self.format_in = "g"
|
||||
self.format_out = "g"
|
||||
self.gvariant_get = "g_variant_get_string"
|
||||
self.gvalue_get = "g_value_get_string"
|
||||
elif self.signature == "ay":
|
||||
self.ctype_in_g = "const gchar *"
|
||||
self.ctype_in = "const gchar *"
|
||||
self.ctype_in_dup = "gchar *"
|
||||
self.ctype_out = "gchar **"
|
||||
self.gtype = "G_TYPE_STRING"
|
||||
self.free_func = "g_free"
|
||||
self.format_in = "^ay"
|
||||
self.format_out = "^ay"
|
||||
self.gvariant_get = "g_variant_get_bytestring"
|
||||
self.gvalue_get = "g_value_get_string"
|
||||
elif self.signature == "as":
|
||||
self.ctype_in_g = "const gchar *const *"
|
||||
self.ctype_in = "const gchar *const *"
|
||||
self.ctype_in_dup = "gchar **"
|
||||
self.ctype_out = "gchar ***"
|
||||
self.gtype = "G_TYPE_STRV"
|
||||
self.free_func = "g_strfreev"
|
||||
self.format_in = "^as"
|
||||
self.format_out = "^as"
|
||||
self.gvariant_get = "g_variant_get_strv"
|
||||
self.gvalue_get = "g_value_get_boxed"
|
||||
self.array_annotation = "(array zero-terminated=1)"
|
||||
elif self.signature == "ao":
|
||||
self.ctype_in_g = "const gchar *const *"
|
||||
self.ctype_in = "const gchar *const *"
|
||||
self.ctype_in_dup = "gchar **"
|
||||
self.ctype_out = "gchar ***"
|
||||
self.gtype = "G_TYPE_STRV"
|
||||
self.free_func = "g_strfreev"
|
||||
self.format_in = "^ao"
|
||||
self.format_out = "^ao"
|
||||
self.gvariant_get = "g_variant_get_objv"
|
||||
self.gvalue_get = "g_value_get_boxed"
|
||||
self.array_annotation = "(array zero-terminated=1)"
|
||||
elif self.signature == "aay":
|
||||
self.ctype_in_g = "const gchar *const *"
|
||||
self.ctype_in = "const gchar *const *"
|
||||
self.ctype_in_dup = "gchar **"
|
||||
self.ctype_out = "gchar ***"
|
||||
self.gtype = "G_TYPE_STRV"
|
||||
self.free_func = "g_strfreev"
|
||||
self.format_in = "^aay"
|
||||
self.format_out = "^aay"
|
||||
self.gvariant_get = "g_variant_get_bytestring_array"
|
||||
self.gvalue_get = "g_value_get_boxed"
|
||||
self.array_annotation = "(array zero-terminated=1)"
|
||||
|
||||
for a in self.annotations:
|
||||
a.post_process(interface_prefix, cns, cns_upper, cns_lower, self)
|
||||
|
||||
|
||||
class Method:
|
||||
def __init__(self, name, h_type_implies_unix_fd=True):
|
||||
self.name = name
|
||||
@ -258,12 +270,14 @@ class Method:
|
||||
self.in_args = []
|
||||
self.out_args = []
|
||||
self.annotations = []
|
||||
self.doc_string = ''
|
||||
self.since = ''
|
||||
self.doc_string = ""
|
||||
self.since = ""
|
||||
self.deprecated = 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:
|
||||
self.doc_string = utils.lookup_docs(self.annotations)
|
||||
if len(self.since) == 0:
|
||||
@ -272,47 +286,55 @@ class Method:
|
||||
self.since = containing_iface.since
|
||||
|
||||
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):
|
||||
self.name_lower = overridden_name.lower()
|
||||
else:
|
||||
if overridden_name:
|
||||
name = overridden_name
|
||||
self.name_lower = utils.camel_case_to_uscore(name).lower().replace('-', '_')
|
||||
self.name_hyphen = self.name_lower.replace('_', '-')
|
||||
self.name_lower = utils.camel_case_to_uscore(name).lower().replace("-", "_")
|
||||
self.name_hyphen = self.name_lower.replace("_", "-")
|
||||
|
||||
arg_count = 0
|
||||
for a in self.in_args:
|
||||
a.post_process(interface_prefix, cns, cns_upper, cns_lower, arg_count)
|
||||
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
|
||||
|
||||
for a in self.out_args:
|
||||
a.post_process(interface_prefix, cns, cns_upper, cns_lower, arg_count)
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
for a in self.annotations:
|
||||
a.post_process(interface_prefix, cns, cns_upper, cns_lower, self)
|
||||
|
||||
|
||||
class Signal:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.args = []
|
||||
self.annotations = []
|
||||
self.doc_string = ''
|
||||
self.since = ''
|
||||
self.doc_string = ""
|
||||
self.since = ""
|
||||
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:
|
||||
self.doc_string = utils.lookup_docs(self.annotations)
|
||||
if len(self.since) == 0:
|
||||
@ -321,51 +343,59 @@ class Signal:
|
||||
self.since = containing_iface.since
|
||||
|
||||
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):
|
||||
self.name_lower = overridden_name.lower()
|
||||
else:
|
||||
if overridden_name:
|
||||
name = overridden_name
|
||||
self.name_lower = utils.camel_case_to_uscore(name).lower().replace('-', '_')
|
||||
self.name_hyphen = self.name_lower.replace('_', '-')
|
||||
self.name_lower = utils.camel_case_to_uscore(name).lower().replace("-", "_")
|
||||
self.name_hyphen = self.name_lower.replace("_", "-")
|
||||
|
||||
arg_count = 0
|
||||
for a in self.args:
|
||||
a.post_process(interface_prefix, cns, cns_upper, cns_lower, arg_count)
|
||||
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
|
||||
|
||||
for a in self.annotations:
|
||||
a.post_process(interface_prefix, cns, cns_upper, cns_lower, self)
|
||||
|
||||
|
||||
class Property:
|
||||
def __init__(self, name, signature, access):
|
||||
self.name = name
|
||||
self.signature = signature
|
||||
self.access = access
|
||||
self.annotations = []
|
||||
self.arg = Arg('value', self.signature)
|
||||
self.arg = Arg("value", self.signature)
|
||||
self.arg.annotations = self.annotations
|
||||
self.readable = False
|
||||
self.writable = False
|
||||
if self.access == 'readwrite':
|
||||
if self.access == "readwrite":
|
||||
self.readable = True
|
||||
self.writable = True
|
||||
elif self.access == 'read':
|
||||
elif self.access == "read":
|
||||
self.readable = True
|
||||
elif self.access == 'write':
|
||||
elif self.access == "write":
|
||||
self.writable = True
|
||||
else:
|
||||
print_error('Invalid access type "{}"'.format(self.access))
|
||||
self.doc_string = ''
|
||||
self.since = ''
|
||||
self.doc_string = ""
|
||||
self.since = ""
|
||||
self.deprecated = False
|
||||
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:
|
||||
self.doc_string = utils.lookup_docs(self.annotations)
|
||||
if len(self.since) == 0:
|
||||
@ -374,34 +404,44 @@ class Property:
|
||||
self.since = containing_iface.since
|
||||
|
||||
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):
|
||||
self.name_lower = overridden_name.lower()
|
||||
else:
|
||||
if overridden_name:
|
||||
name = overridden_name
|
||||
self.name_lower = utils.camel_case_to_uscore(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
|
||||
if self.name_lower == 'type':
|
||||
self.name_lower = 'type_'
|
||||
self.name_lower = utils.camel_case_to_uscore(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
|
||||
if self.name_lower == "type":
|
||||
self.name_lower = "type_"
|
||||
|
||||
# recalculate arg
|
||||
self.arg.annotations = self.annotations
|
||||
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
|
||||
|
||||
for a in self.annotations:
|
||||
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
|
||||
# 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
|
||||
|
||||
|
||||
class Interface:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
@ -409,9 +449,9 @@ class Interface:
|
||||
self.signals = []
|
||||
self.properties = []
|
||||
self.annotations = []
|
||||
self.doc_string = ''
|
||||
self.doc_string_brief = ''
|
||||
self.since = ''
|
||||
self.doc_string = ""
|
||||
self.doc_string_brief = ""
|
||||
self.since = ""
|
||||
self.deprecated = False
|
||||
|
||||
def post_process(self, interface_prefix, c_namespace):
|
||||
@ -424,21 +464,23 @@ class Interface:
|
||||
|
||||
if len(c_namespace) > 0:
|
||||
if utils.is_ugly_case(c_namespace):
|
||||
cns = c_namespace.replace('_', '')
|
||||
cns_upper = c_namespace.upper() + '_'
|
||||
cns_lower = c_namespace.lower() + '_'
|
||||
cns = c_namespace.replace("_", "")
|
||||
cns_upper = c_namespace.upper() + "_"
|
||||
cns_lower = c_namespace.lower() + "_"
|
||||
else:
|
||||
cns = c_namespace
|
||||
cns_upper = utils.camel_case_to_uscore(c_namespace).upper() + '_'
|
||||
cns_lower = utils.camel_case_to_uscore(c_namespace).lower() + '_'
|
||||
cns_upper = utils.camel_case_to_uscore(c_namespace).upper() + "_"
|
||||
cns_lower = utils.camel_case_to_uscore(c_namespace).lower() + "_"
|
||||
else:
|
||||
cns = ''
|
||||
cns_upper = ''
|
||||
cns_lower = ''
|
||||
cns = ""
|
||||
cns_upper = ""
|
||||
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):
|
||||
name = overridden_name.replace('_', '')
|
||||
name = overridden_name.replace("_", "")
|
||||
name_with_ns = cns + name
|
||||
self.name_without_prefix = name
|
||||
self.camel_name = name_with_ns
|
||||
@ -446,25 +488,28 @@ class Interface:
|
||||
self.name_lower = cns_lower + overridden_name.lower()
|
||||
self.name_upper = overridden_name.upper()
|
||||
|
||||
#print_error('handle Ugly_Case "{}"'.format(overridden_name))
|
||||
# print_error('handle Ugly_Case "{}"'.format(overridden_name))
|
||||
else:
|
||||
if overridden_name:
|
||||
name = overridden_name
|
||||
else:
|
||||
name = self.name
|
||||
if name.startswith(interface_prefix):
|
||||
name = name[len(interface_prefix):]
|
||||
name = name[len(interface_prefix) :]
|
||||
self.name_without_prefix = 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.ns_upper = cns_upper
|
||||
self.name_lower = cns_lower + utils.camel_case_to_uscore(name)
|
||||
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
|
||||
|
||||
for m in self.methods:
|
||||
|
@ -19,22 +19,22 @@
|
||||
#
|
||||
# Author: David Zeuthen <davidz@redhat.com>
|
||||
|
||||
import sys
|
||||
import xml.parsers.expat
|
||||
|
||||
from . import dbustypes
|
||||
from .utils import print_error
|
||||
|
||||
|
||||
class DBusXMLParser:
|
||||
STATE_TOP = 'top'
|
||||
STATE_NODE = 'node'
|
||||
STATE_INTERFACE = 'interface'
|
||||
STATE_METHOD = 'method'
|
||||
STATE_SIGNAL = 'signal'
|
||||
STATE_PROPERTY = 'property'
|
||||
STATE_ARG = 'arg'
|
||||
STATE_ANNOTATION = 'annotation'
|
||||
STATE_IGNORED = 'ignored'
|
||||
STATE_TOP = "top"
|
||||
STATE_NODE = "node"
|
||||
STATE_INTERFACE = "interface"
|
||||
STATE_METHOD = "method"
|
||||
STATE_SIGNAL = "signal"
|
||||
STATE_PROPERTY = "property"
|
||||
STATE_ARG = "arg"
|
||||
STATE_ANNOTATION = "annotation"
|
||||
STATE_IGNORED = "ignored"
|
||||
|
||||
def __init__(self, xml_data, h_type_implies_unix_fd=True):
|
||||
self._parser = xml.parsers.expat.ParserCreate()
|
||||
@ -51,21 +51,22 @@ class DBusXMLParser:
|
||||
self._cur_object = None
|
||||
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._parser.Parse(xml_data)
|
||||
|
||||
COMMENT_STATE_BEGIN = 'begin'
|
||||
COMMENT_STATE_PARAMS = 'params'
|
||||
COMMENT_STATE_BODY = 'body'
|
||||
COMMENT_STATE_SKIP = 'skip'
|
||||
COMMENT_STATE_BEGIN = "begin"
|
||||
COMMENT_STATE_PARAMS = "params"
|
||||
COMMENT_STATE_BODY = "body"
|
||||
COMMENT_STATE_SKIP = "skip"
|
||||
|
||||
def handle_comment(self, data):
|
||||
comment_state = DBusXMLParser.COMMENT_STATE_BEGIN;
|
||||
lines = data.split('\n')
|
||||
symbol = ''
|
||||
body = ''
|
||||
comment_state = DBusXMLParser.COMMENT_STATE_BEGIN
|
||||
lines = data.split("\n")
|
||||
symbol = ""
|
||||
body = ""
|
||||
in_para = False
|
||||
params = {}
|
||||
for line in lines:
|
||||
@ -73,59 +74,59 @@ class DBusXMLParser:
|
||||
line = line.lstrip()
|
||||
if comment_state == DBusXMLParser.COMMENT_STATE_BEGIN:
|
||||
if len(line) > 0:
|
||||
colon_index = line.find(': ')
|
||||
colon_index = line.find(": ")
|
||||
if colon_index == -1:
|
||||
if line.endswith(':'):
|
||||
symbol = line[0:len(line)-1]
|
||||
if line.endswith(":"):
|
||||
symbol = line[0 : len(line) - 1]
|
||||
comment_state = DBusXMLParser.COMMENT_STATE_PARAMS
|
||||
else:
|
||||
comment_state = DBusXMLParser.COMMENT_STATE_SKIP
|
||||
else:
|
||||
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:
|
||||
body += '<para>' + rest_of_line + '</para>'
|
||||
body += "<para>" + rest_of_line + "</para>"
|
||||
comment_state = DBusXMLParser.COMMENT_STATE_PARAMS
|
||||
elif comment_state == DBusXMLParser.COMMENT_STATE_PARAMS:
|
||||
if line.startswith('@'):
|
||||
colon_index = line.find(': ')
|
||||
if line.startswith("@"):
|
||||
colon_index = line.find(": ")
|
||||
if colon_index == -1:
|
||||
comment_state = DBusXMLParser.COMMENT_STATE_BODY
|
||||
if not in_para:
|
||||
body += '<para>'
|
||||
body += "<para>"
|
||||
in_para = True
|
||||
body += orig_line + '\n'
|
||||
body += orig_line + "\n"
|
||||
else:
|
||||
param = line[1:colon_index]
|
||||
docs = line[colon_index + 2:]
|
||||
docs = line[colon_index + 2 :]
|
||||
params[param] = docs
|
||||
else:
|
||||
comment_state = DBusXMLParser.COMMENT_STATE_BODY
|
||||
if len(line) > 0:
|
||||
if not in_para:
|
||||
body += '<para>'
|
||||
body += "<para>"
|
||||
in_para = True
|
||||
body += orig_line + '\n'
|
||||
body += orig_line + "\n"
|
||||
elif comment_state == DBusXMLParser.COMMENT_STATE_BODY:
|
||||
if len(line) > 0:
|
||||
if not in_para:
|
||||
body += '<para>'
|
||||
body += "<para>"
|
||||
in_para = True
|
||||
body += orig_line + '\n'
|
||||
body += orig_line + "\n"
|
||||
else:
|
||||
if in_para:
|
||||
body += '</para>'
|
||||
body += "</para>"
|
||||
in_para = False
|
||||
if in_para:
|
||||
body += '</para>'
|
||||
body += "</para>"
|
||||
|
||||
if symbol != '':
|
||||
if symbol != "":
|
||||
self.doc_comment_last_symbol = symbol
|
||||
self.doc_comment_params = params
|
||||
self.doc_comment_body = body
|
||||
|
||||
def handle_char_data(self, data):
|
||||
#print 'char_data=%s'%data
|
||||
# print 'char_data=%s'%data
|
||||
pass
|
||||
|
||||
def handle_start_element(self, name, attrs):
|
||||
@ -141,77 +142,76 @@ class DBusXMLParser:
|
||||
elif self.state == DBusXMLParser.STATE_NODE:
|
||||
if name == DBusXMLParser.STATE_INTERFACE:
|
||||
self.state = DBusXMLParser.STATE_INTERFACE
|
||||
iface = dbustypes.Interface(attrs['name'])
|
||||
iface = dbustypes.Interface(attrs["name"])
|
||||
self._cur_object = iface
|
||||
self.parsed_interfaces.append(iface)
|
||||
elif name == 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 = anno
|
||||
else:
|
||||
self.state = DBusXMLParser.STATE_IGNORED
|
||||
|
||||
# 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
|
||||
if 'short_description' in self.doc_comment_params:
|
||||
short_description = self.doc_comment_params['short_description']
|
||||
if "short_description" in self.doc_comment_params:
|
||||
short_description = self.doc_comment_params["short_description"]
|
||||
self._cur_object.doc_string_brief = short_description
|
||||
if 'since' in self.doc_comment_params:
|
||||
self._cur_object.since = \
|
||||
self.doc_comment_params['since'].strip()
|
||||
if "since" in self.doc_comment_params:
|
||||
self._cur_object.since = self.doc_comment_params["since"].strip()
|
||||
|
||||
elif self.state == DBusXMLParser.STATE_INTERFACE:
|
||||
if name == DBusXMLParser.STATE_METHOD:
|
||||
self.state = DBusXMLParser.STATE_METHOD
|
||||
method = dbustypes.Method(attrs['name'],
|
||||
h_type_implies_unix_fd=self._h_type_implies_unix_fd)
|
||||
method = dbustypes.Method(
|
||||
attrs["name"], h_type_implies_unix_fd=self._h_type_implies_unix_fd
|
||||
)
|
||||
self._cur_object.methods.append(method)
|
||||
self._cur_object = method
|
||||
elif name == 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 = signal
|
||||
elif name == 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 = prop
|
||||
elif name == 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 = anno
|
||||
else:
|
||||
self.state = DBusXMLParser.STATE_IGNORED
|
||||
|
||||
# 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
|
||||
if 'since' in self.doc_comment_params:
|
||||
self._cur_object.since = \
|
||||
self.doc_comment_params['since'].strip()
|
||||
if "since" in self.doc_comment_params:
|
||||
self._cur_object.since = self.doc_comment_params["since"].strip()
|
||||
|
||||
elif self.state == DBusXMLParser.STATE_METHOD:
|
||||
if name == DBusXMLParser.STATE_ARG:
|
||||
self.state = DBusXMLParser.STATE_ARG
|
||||
arg_name = None
|
||||
if 'name' in attrs:
|
||||
arg_name = attrs['name']
|
||||
arg = dbustypes.Arg(arg_name, attrs['type'])
|
||||
direction = attrs.get('direction', 'in')
|
||||
if direction == 'in':
|
||||
if "name" in attrs:
|
||||
arg_name = attrs["name"]
|
||||
arg = dbustypes.Arg(arg_name, attrs["type"])
|
||||
direction = attrs.get("direction", "in")
|
||||
if direction == "in":
|
||||
self._cur_object.in_args.append(arg)
|
||||
elif direction == 'out':
|
||||
elif direction == "out":
|
||||
self._cur_object.out_args.append(arg)
|
||||
else:
|
||||
print_error('Invalid direction "{}"'.format(direction))
|
||||
self._cur_object = arg
|
||||
elif name == 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 = anno
|
||||
else:
|
||||
@ -219,26 +219,27 @@ class DBusXMLParser:
|
||||
|
||||
# assign docs, if any
|
||||
if self.doc_comment_last_symbol == old_cur_object.name:
|
||||
if 'name' in attrs and attrs['name'] in self.doc_comment_params:
|
||||
doc_string = self.doc_comment_params[attrs['name']]
|
||||
if doc_string != None:
|
||||
if "name" in attrs and attrs["name"] in self.doc_comment_params:
|
||||
doc_string = self.doc_comment_params[attrs["name"]]
|
||||
if doc_string is not None:
|
||||
self._cur_object.doc_string = doc_string
|
||||
if 'since' in self.doc_comment_params:
|
||||
self._cur_object.since = \
|
||||
self.doc_comment_params['since'].strip()
|
||||
if "since" in self.doc_comment_params:
|
||||
self._cur_object.since = self.doc_comment_params[
|
||||
"since"
|
||||
].strip()
|
||||
|
||||
elif self.state == DBusXMLParser.STATE_SIGNAL:
|
||||
if name == DBusXMLParser.STATE_ARG:
|
||||
self.state = DBusXMLParser.STATE_ARG
|
||||
arg_name = None
|
||||
if 'name' in attrs:
|
||||
arg_name = attrs['name']
|
||||
arg = dbustypes.Arg(arg_name, attrs['type'])
|
||||
if "name" in attrs:
|
||||
arg_name = attrs["name"]
|
||||
arg = dbustypes.Arg(arg_name, attrs["type"])
|
||||
self._cur_object.args.append(arg)
|
||||
self._cur_object = arg
|
||||
elif name == 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 = anno
|
||||
else:
|
||||
@ -246,18 +247,19 @@ class DBusXMLParser:
|
||||
|
||||
# assign docs, if any
|
||||
if self.doc_comment_last_symbol == old_cur_object.name:
|
||||
if 'name' in attrs and attrs['name'] in self.doc_comment_params:
|
||||
doc_string = self.doc_comment_params[attrs['name']]
|
||||
if doc_string != None:
|
||||
if "name" in attrs and attrs["name"] in self.doc_comment_params:
|
||||
doc_string = self.doc_comment_params[attrs["name"]]
|
||||
if doc_string is not None:
|
||||
self._cur_object.doc_string = doc_string
|
||||
if 'since' in self.doc_comment_params:
|
||||
self._cur_object.since = \
|
||||
self.doc_comment_params['since'].strip()
|
||||
if "since" in self.doc_comment_params:
|
||||
self._cur_object.since = self.doc_comment_params[
|
||||
"since"
|
||||
].strip()
|
||||
|
||||
elif self.state == DBusXMLParser.STATE_PROPERTY:
|
||||
if name == 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 = anno
|
||||
else:
|
||||
@ -266,7 +268,7 @@ class DBusXMLParser:
|
||||
elif self.state == DBusXMLParser.STATE_ARG:
|
||||
if name == 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 = anno
|
||||
else:
|
||||
@ -275,14 +277,18 @@ class DBusXMLParser:
|
||||
elif self.state == DBusXMLParser.STATE_ANNOTATION:
|
||||
if name == 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 = anno
|
||||
else:
|
||||
self.state = DBusXMLParser.STATE_IGNORED
|
||||
|
||||
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._cur_object_stack.append(old_cur_object)
|
||||
@ -291,6 +297,7 @@ class DBusXMLParser:
|
||||
self.state = self.state_stack.pop()
|
||||
self._cur_object = self._cur_object_stack.pop()
|
||||
|
||||
|
||||
def parse_dbus_xml(xml_data, h_type_implies_unix_fd):
|
||||
parser = DBusXMLParser(xml_data, h_type_implies_unix_fd)
|
||||
return parser.parsed_interfaces
|
||||
|
@ -23,49 +23,58 @@ import distutils.version
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
# pylint: disable=too-few-public-methods
|
||||
class Color:
|
||||
'''ANSI Terminal colors'''
|
||||
GREEN = '\033[1;32m'
|
||||
BLUE = '\033[1;34m'
|
||||
YELLOW = '\033[1;33m'
|
||||
RED = '\033[1;31m'
|
||||
END = '\033[0m'
|
||||
"""ANSI Terminal colors"""
|
||||
|
||||
def print_color(msg, color=Color.END, prefix='MESSAGE'):
|
||||
'''Print a string with a color prefix'''
|
||||
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"):
|
||||
"""Print a string with a color prefix"""
|
||||
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:
|
||||
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):
|
||||
'''Print an error, and terminate'''
|
||||
print_color(msg, color=Color.RED, prefix='ERROR')
|
||||
"""Print an error, and terminate"""
|
||||
print_color(msg, color=Color.RED, prefix="ERROR")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def print_warning(msg, fatal=False):
|
||||
'''Print a warning, and optionally terminate'''
|
||||
"""Print a warning, and optionally terminate"""
|
||||
if fatal:
|
||||
color = Color.RED
|
||||
prefix = 'ERROR'
|
||||
prefix = "ERROR"
|
||||
else:
|
||||
color = Color.YELLOW
|
||||
prefix = 'WARNING'
|
||||
prefix = "WARNING"
|
||||
print_color(msg, color, prefix)
|
||||
if fatal:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def print_info(msg):
|
||||
'''Print a message'''
|
||||
print_color(msg, color=Color.GREEN, prefix='INFO')
|
||||
"""Print a message"""
|
||||
print_color(msg, color=Color.GREEN, prefix="INFO")
|
||||
|
||||
|
||||
def strip_dots(s):
|
||||
ret = ''
|
||||
ret = ""
|
||||
force_upper = False
|
||||
for c in s:
|
||||
if c == '.':
|
||||
if c == ".":
|
||||
force_upper = True
|
||||
else:
|
||||
if force_upper:
|
||||
@ -75,19 +84,21 @@ def strip_dots(s):
|
||||
ret += c
|
||||
return ret
|
||||
|
||||
|
||||
def dots_to_hyphens(s):
|
||||
return s.replace('.', '-')
|
||||
return s.replace(".", "-")
|
||||
|
||||
|
||||
def camel_case_to_uscore(s):
|
||||
ret = ''
|
||||
ret = ""
|
||||
insert_uscore = False
|
||||
prev_was_lower = False
|
||||
initial = True;
|
||||
initial = True
|
||||
for c in s:
|
||||
# Keep initial underscores in camel case
|
||||
if initial and c == '_':
|
||||
ret += '_'
|
||||
continue;
|
||||
if initial and c == "_":
|
||||
ret += "_"
|
||||
continue
|
||||
initial = False
|
||||
|
||||
if c.isupper():
|
||||
@ -97,16 +108,18 @@ def camel_case_to_uscore(s):
|
||||
else:
|
||||
prev_was_lower = True
|
||||
if insert_uscore:
|
||||
ret += '_'
|
||||
ret += "_"
|
||||
ret += c.lower()
|
||||
insert_uscore = False
|
||||
return ret
|
||||
|
||||
|
||||
def is_ugly_case(s):
|
||||
if s and s.find('_') > 0:
|
||||
if s and s.find("_") > 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def lookup_annotation(annotations, key):
|
||||
if annotations:
|
||||
for a in annotations:
|
||||
@ -114,35 +127,39 @@ def lookup_annotation(annotations, key):
|
||||
return a.value
|
||||
return None
|
||||
|
||||
|
||||
def lookup_docs(annotations):
|
||||
s = lookup_annotation(annotations, 'org.gtk.GDBus.DocString')
|
||||
s = lookup_annotation(annotations, "org.gtk.GDBus.DocString")
|
||||
if s is None:
|
||||
return ''
|
||||
return ""
|
||||
else:
|
||||
return s
|
||||
|
||||
|
||||
def lookup_since(annotations):
|
||||
s = lookup_annotation(annotations, 'org.gtk.GDBus.Since')
|
||||
s = lookup_annotation(annotations, "org.gtk.GDBus.Since")
|
||||
if s is None:
|
||||
return ''
|
||||
return ""
|
||||
else:
|
||||
return s
|
||||
|
||||
|
||||
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:
|
||||
return ''
|
||||
return ""
|
||||
else:
|
||||
return s
|
||||
|
||||
|
||||
def version_cmp_key(key):
|
||||
# If the 'since' version is 'UNRELEASED', compare higher than anything else
|
||||
# If it is empty put a 0 in its place as this will
|
||||
# allow LooseVersion to work and will always compare lower.
|
||||
if key[0] == 'UNRELEASED':
|
||||
v = '9999'
|
||||
if key[0] == "UNRELEASED":
|
||||
v = "9999"
|
||||
elif key[0]:
|
||||
v = str(key[0])
|
||||
else:
|
||||
v = '0'
|
||||
v = "0"
|
||||
return (distutils.version.LooseVersion(v), key[1])
|
||||
|
@ -4,6 +4,6 @@ import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
if not os.environ.get('DESTDIR'):
|
||||
print('GIO module cache creation...')
|
||||
if not os.environ.get("DESTDIR"):
|
||||
print("GIO module cache creation...")
|
||||
subprocess.call([sys.argv[1], sys.argv[2]])
|
||||
|
@ -26,13 +26,16 @@ import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import textwrap
|
||||
import unittest
|
||||
|
||||
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):
|
||||
@ -47,22 +50,27 @@ class TestCodegen(unittest.TestCase):
|
||||
parsing and generation code of gdbus-codegen into separate unit tests, and
|
||||
just test command line behaviour in this integration test.
|
||||
"""
|
||||
|
||||
# Track the cwd, we want to back out to that to clean up our tempdir
|
||||
cwd = ''
|
||||
cwd = ""
|
||||
|
||||
def setUp(self):
|
||||
self.timeout_seconds = 10 # seconds per test
|
||||
self.tmpdir = tempfile.TemporaryDirectory()
|
||||
self.cwd = os.getcwd()
|
||||
os.chdir(self.tmpdir.name)
|
||||
print('tmpdir:', self.tmpdir.name)
|
||||
if 'G_TEST_BUILDDIR' in os.environ:
|
||||
self.__codegen = \
|
||||
os.path.join(os.environ['G_TEST_BUILDDIR'], '..',
|
||||
'gdbus-2.0', 'codegen', 'gdbus-codegen')
|
||||
print("tmpdir:", self.tmpdir.name)
|
||||
if "G_TEST_BUILDDIR" in os.environ:
|
||||
self.__codegen = os.path.join(
|
||||
os.environ["G_TEST_BUILDDIR"],
|
||||
"..",
|
||||
"gdbus-2.0",
|
||||
"codegen",
|
||||
"gdbus-codegen",
|
||||
)
|
||||
else:
|
||||
self.__codegen = shutil.which('gdbus-codegen')
|
||||
print('codegen:', self.__codegen)
|
||||
self.__codegen = shutil.which("gdbus-codegen")
|
||||
print("codegen:", self.__codegen)
|
||||
|
||||
def tearDown(self):
|
||||
os.chdir(self.cwd)
|
||||
@ -73,201 +81,200 @@ class TestCodegen(unittest.TestCase):
|
||||
|
||||
# shebang lines are not supported on native
|
||||
# Windows consoles
|
||||
if os.name == 'nt':
|
||||
if os.name == "nt":
|
||||
argv.insert(0, sys.executable)
|
||||
|
||||
argv.extend(args)
|
||||
print('Running:', argv)
|
||||
print("Running:", argv)
|
||||
|
||||
env = os.environ.copy()
|
||||
env['LC_ALL'] = 'C.UTF-8'
|
||||
print('Environment:', env)
|
||||
env["LC_ALL"] = "C.UTF-8"
|
||||
print("Environment:", env)
|
||||
|
||||
# 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,
|
||||
stderr=subprocess.PIPE,
|
||||
env=env,
|
||||
universal_newlines=True)
|
||||
universal_newlines=True,
|
||||
)
|
||||
info.check_returncode()
|
||||
out = info.stdout.strip()
|
||||
err = info.stderr.strip()
|
||||
|
||||
# Known substitutions for standard boilerplate
|
||||
subs = {
|
||||
'standard_top_comment':
|
||||
'/*\n'
|
||||
' * This file is generated by gdbus-codegen, do not modify it.\n'
|
||||
' *\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'
|
||||
' * LGPL linking clauses.\n'
|
||||
' */',
|
||||
'standard_config_h_include':
|
||||
'#ifdef HAVE_CONFIG_H\n'
|
||||
"standard_top_comment": "/*\n"
|
||||
" * This file is generated by gdbus-codegen, do not modify it.\n"
|
||||
" *\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"
|
||||
" * LGPL linking clauses.\n"
|
||||
" */",
|
||||
"standard_config_h_include": "#ifdef HAVE_CONFIG_H\n"
|
||||
'# include "config.h"\n'
|
||||
'#endif',
|
||||
'standard_header_includes':
|
||||
'#include <string.h>\n'
|
||||
'#ifdef G_OS_UNIX\n'
|
||||
'# include <gio/gunixfdlist.h>\n'
|
||||
'#endif',
|
||||
'standard_typedefs_and_helpers':
|
||||
'typedef struct\n'
|
||||
'{\n'
|
||||
' GDBusArgInfo parent_struct;\n'
|
||||
' gboolean use_gvariant;\n'
|
||||
'} _ExtendedGDBusArgInfo;\n'
|
||||
'\n'
|
||||
'typedef struct\n'
|
||||
'{\n'
|
||||
' GDBusMethodInfo parent_struct;\n'
|
||||
' const gchar *signal_name;\n'
|
||||
' gboolean pass_fdlist;\n'
|
||||
'} _ExtendedGDBusMethodInfo;\n'
|
||||
'\n'
|
||||
'typedef struct\n'
|
||||
'{\n'
|
||||
' GDBusSignalInfo parent_struct;\n'
|
||||
' const gchar *signal_name;\n'
|
||||
'} _ExtendedGDBusSignalInfo;\n'
|
||||
'\n'
|
||||
'typedef struct\n'
|
||||
'{\n'
|
||||
' GDBusPropertyInfo parent_struct;\n'
|
||||
' const gchar *hyphen_name;\n'
|
||||
' guint use_gvariant : 1;\n'
|
||||
' guint emits_changed_signal : 1;\n'
|
||||
'} _ExtendedGDBusPropertyInfo;\n'
|
||||
'\n'
|
||||
'typedef struct\n'
|
||||
'{\n'
|
||||
' GDBusInterfaceInfo parent_struct;\n'
|
||||
' const gchar *hyphen_name;\n'
|
||||
'} _ExtendedGDBusInterfaceInfo;\n'
|
||||
'\n'
|
||||
'typedef struct\n'
|
||||
'{\n'
|
||||
' const _ExtendedGDBusPropertyInfo *info;\n'
|
||||
' guint prop_id;\n'
|
||||
' GValue orig_value; /* the value before the change */\n'
|
||||
'} ChangedProperty;\n'
|
||||
'\n'
|
||||
'static void\n'
|
||||
'_changed_property_free (ChangedProperty *data)\n'
|
||||
'{\n'
|
||||
' g_value_unset (&data->orig_value);\n'
|
||||
' g_free (data);\n'
|
||||
'}\n'
|
||||
'\n'
|
||||
'static gboolean\n'
|
||||
'_g_strv_equal0 (gchar **a, gchar **b)\n'
|
||||
'{\n'
|
||||
' gboolean ret = FALSE;\n'
|
||||
' guint n;\n'
|
||||
' if (a == NULL && b == NULL)\n'
|
||||
' {\n'
|
||||
' ret = TRUE;\n'
|
||||
' goto out;\n'
|
||||
' }\n'
|
||||
' if (a == NULL || b == NULL)\n'
|
||||
' goto out;\n'
|
||||
' if (g_strv_length (a) != g_strv_length (b))\n'
|
||||
' goto out;\n'
|
||||
' for (n = 0; a[n] != NULL; n++)\n'
|
||||
' if (g_strcmp0 (a[n], b[n]) != 0)\n'
|
||||
' goto out;\n'
|
||||
' ret = TRUE;\n'
|
||||
'out:\n'
|
||||
' return ret;\n'
|
||||
'}\n'
|
||||
'\n'
|
||||
'static gboolean\n'
|
||||
'_g_variant_equal0 (GVariant *a, GVariant *b)\n'
|
||||
'{\n'
|
||||
' gboolean ret = FALSE;\n'
|
||||
' if (a == NULL && b == NULL)\n'
|
||||
' {\n'
|
||||
' ret = TRUE;\n'
|
||||
' goto out;\n'
|
||||
' }\n'
|
||||
' if (a == NULL || b == NULL)\n'
|
||||
' goto out;\n'
|
||||
' ret = g_variant_equal (a, b);\n'
|
||||
'out:\n'
|
||||
' return ret;\n'
|
||||
'}\n'
|
||||
'\n'
|
||||
'G_GNUC_UNUSED static gboolean\n'
|
||||
'_g_value_equal (const GValue *a, const GValue *b)\n'
|
||||
'{\n'
|
||||
' gboolean ret = FALSE;\n'
|
||||
' g_assert (G_VALUE_TYPE (a) == G_VALUE_TYPE (b));\n'
|
||||
' switch (G_VALUE_TYPE (a))\n'
|
||||
' {\n'
|
||||
' case G_TYPE_BOOLEAN:\n'
|
||||
' ret = (g_value_get_boolean (a) == g_value_get_boolean (b));\n'
|
||||
' break;\n'
|
||||
' case G_TYPE_UCHAR:\n'
|
||||
' ret = (g_value_get_uchar (a) == g_value_get_uchar (b));\n'
|
||||
' break;\n'
|
||||
' case G_TYPE_INT:\n'
|
||||
' ret = (g_value_get_int (a) == g_value_get_int (b));\n'
|
||||
' break;\n'
|
||||
' case G_TYPE_UINT:\n'
|
||||
' ret = (g_value_get_uint (a) == g_value_get_uint (b));\n'
|
||||
' break;\n'
|
||||
' case G_TYPE_INT64:\n'
|
||||
' ret = (g_value_get_int64 (a) == g_value_get_int64 (b));\n'
|
||||
' break;\n'
|
||||
' case G_TYPE_UINT64:\n'
|
||||
' ret = (g_value_get_uint64 (a) == g_value_get_uint64 (b));\n'
|
||||
' break;\n'
|
||||
' case G_TYPE_DOUBLE:\n'
|
||||
' {\n'
|
||||
' /* Avoid -Wfloat-equal warnings by doing a direct bit compare */\n'
|
||||
' gdouble da = g_value_get_double (a);\n'
|
||||
' gdouble db = g_value_get_double (b);\n'
|
||||
' ret = memcmp (&da, &db, sizeof (gdouble)) == 0;\n'
|
||||
' }\n'
|
||||
' break;\n'
|
||||
' case G_TYPE_STRING:\n'
|
||||
' ret = (g_strcmp0 (g_value_get_string (a), g_value_get_string (b)) == 0);\n'
|
||||
' break;\n'
|
||||
' case G_TYPE_VARIANT:\n'
|
||||
' ret = _g_variant_equal0 (g_value_get_variant (a), g_value_get_variant (b));\n'
|
||||
' break;\n'
|
||||
' default:\n'
|
||||
' if (G_VALUE_TYPE (a) == G_TYPE_STRV)\n'
|
||||
' ret = _g_strv_equal0 (g_value_get_boxed (a), g_value_get_boxed (b));\n'
|
||||
' else\n'
|
||||
"#endif",
|
||||
"standard_header_includes": "#include <string.h>\n"
|
||||
"#ifdef G_OS_UNIX\n"
|
||||
"# include <gio/gunixfdlist.h>\n"
|
||||
"#endif",
|
||||
"standard_typedefs_and_helpers": "typedef struct\n"
|
||||
"{\n"
|
||||
" GDBusArgInfo parent_struct;\n"
|
||||
" gboolean use_gvariant;\n"
|
||||
"} _ExtendedGDBusArgInfo;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" GDBusMethodInfo parent_struct;\n"
|
||||
" const gchar *signal_name;\n"
|
||||
" gboolean pass_fdlist;\n"
|
||||
"} _ExtendedGDBusMethodInfo;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" GDBusSignalInfo parent_struct;\n"
|
||||
" const gchar *signal_name;\n"
|
||||
"} _ExtendedGDBusSignalInfo;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" GDBusPropertyInfo parent_struct;\n"
|
||||
" const gchar *hyphen_name;\n"
|
||||
" guint use_gvariant : 1;\n"
|
||||
" guint emits_changed_signal : 1;\n"
|
||||
"} _ExtendedGDBusPropertyInfo;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" GDBusInterfaceInfo parent_struct;\n"
|
||||
" const gchar *hyphen_name;\n"
|
||||
"} _ExtendedGDBusInterfaceInfo;\n"
|
||||
"\n"
|
||||
"typedef struct\n"
|
||||
"{\n"
|
||||
" const _ExtendedGDBusPropertyInfo *info;\n"
|
||||
" guint prop_id;\n"
|
||||
" GValue orig_value; /* the value before the change */\n"
|
||||
"} ChangedProperty;\n"
|
||||
"\n"
|
||||
"static void\n"
|
||||
"_changed_property_free (ChangedProperty *data)\n"
|
||||
"{\n"
|
||||
" g_value_unset (&data->orig_value);\n"
|
||||
" g_free (data);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"static gboolean\n"
|
||||
"_g_strv_equal0 (gchar **a, gchar **b)\n"
|
||||
"{\n"
|
||||
" gboolean ret = FALSE;\n"
|
||||
" guint n;\n"
|
||||
" if (a == NULL && b == NULL)\n"
|
||||
" {\n"
|
||||
" ret = TRUE;\n"
|
||||
" goto out;\n"
|
||||
" }\n"
|
||||
" if (a == NULL || b == NULL)\n"
|
||||
" goto out;\n"
|
||||
" if (g_strv_length (a) != g_strv_length (b))\n"
|
||||
" goto out;\n"
|
||||
" for (n = 0; a[n] != NULL; n++)\n"
|
||||
" if (g_strcmp0 (a[n], b[n]) != 0)\n"
|
||||
" goto out;\n"
|
||||
" ret = TRUE;\n"
|
||||
"out:\n"
|
||||
" return ret;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"static gboolean\n"
|
||||
"_g_variant_equal0 (GVariant *a, GVariant *b)\n"
|
||||
"{\n"
|
||||
" gboolean ret = FALSE;\n"
|
||||
" if (a == NULL && b == NULL)\n"
|
||||
" {\n"
|
||||
" ret = TRUE;\n"
|
||||
" goto out;\n"
|
||||
" }\n"
|
||||
" if (a == NULL || b == NULL)\n"
|
||||
" goto out;\n"
|
||||
" ret = g_variant_equal (a, b);\n"
|
||||
"out:\n"
|
||||
" return ret;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"G_GNUC_UNUSED static gboolean\n"
|
||||
"_g_value_equal (const GValue *a, const GValue *b)\n"
|
||||
"{\n"
|
||||
" gboolean ret = FALSE;\n"
|
||||
" g_assert (G_VALUE_TYPE (a) == G_VALUE_TYPE (b));\n"
|
||||
" switch (G_VALUE_TYPE (a))\n"
|
||||
" {\n"
|
||||
" case G_TYPE_BOOLEAN:\n"
|
||||
" ret = (g_value_get_boolean (a) == g_value_get_boolean (b));\n"
|
||||
" break;\n"
|
||||
" case G_TYPE_UCHAR:\n"
|
||||
" ret = (g_value_get_uchar (a) == g_value_get_uchar (b));\n"
|
||||
" break;\n"
|
||||
" case G_TYPE_INT:\n"
|
||||
" ret = (g_value_get_int (a) == g_value_get_int (b));\n"
|
||||
" break;\n"
|
||||
" case G_TYPE_UINT:\n"
|
||||
" ret = (g_value_get_uint (a) == g_value_get_uint (b));\n"
|
||||
" break;\n"
|
||||
" case G_TYPE_INT64:\n"
|
||||
" ret = (g_value_get_int64 (a) == g_value_get_int64 (b));\n"
|
||||
" break;\n"
|
||||
" case G_TYPE_UINT64:\n"
|
||||
" ret = (g_value_get_uint64 (a) == g_value_get_uint64 (b));\n"
|
||||
" break;\n"
|
||||
" case G_TYPE_DOUBLE:\n"
|
||||
" {\n"
|
||||
" /* Avoid -Wfloat-equal warnings by doing a direct bit compare */\n"
|
||||
" gdouble da = g_value_get_double (a);\n"
|
||||
" gdouble db = g_value_get_double (b);\n"
|
||||
" ret = memcmp (&da, &db, sizeof (gdouble)) == 0;\n"
|
||||
" }\n"
|
||||
" break;\n"
|
||||
" case G_TYPE_STRING:\n"
|
||||
" ret = (g_strcmp0 (g_value_get_string (a), g_value_get_string (b)) == 0);\n"
|
||||
" break;\n"
|
||||
" case G_TYPE_VARIANT:\n"
|
||||
" ret = _g_variant_equal0 (g_value_get_variant (a), g_value_get_variant (b));\n"
|
||||
" break;\n"
|
||||
" default:\n"
|
||||
" if (G_VALUE_TYPE (a) == G_TYPE_STRV)\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'
|
||||
' break;\n'
|
||||
' }\n'
|
||||
' return ret;\n'
|
||||
'}',
|
||||
" break;\n"
|
||||
" }\n"
|
||||
" return ret;\n"
|
||||
"}",
|
||||
}
|
||||
|
||||
result = Result(info, out, err, subs)
|
||||
|
||||
print('Output:', result.out)
|
||||
print("Output:", result.out)
|
||||
return result
|
||||
|
||||
def runCodegenWithInterface(self, interface_contents, *args):
|
||||
with tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
|
||||
suffix='.xml',
|
||||
delete=False) as interface_file:
|
||||
with tempfile.NamedTemporaryFile(
|
||||
dir=self.tmpdir.name, suffix=".xml", delete=False
|
||||
) as interface_file:
|
||||
# Write out the interface.
|
||||
interface_file.write(interface_contents.encode('utf-8'))
|
||||
print(interface_file.name + ':', interface_contents)
|
||||
interface_file.write(interface_contents.encode("utf-8"))
|
||||
print(interface_file.name + ":", interface_contents)
|
||||
interface_file.flush()
|
||||
|
||||
return self.runCodegen(interface_file.name, *args)
|
||||
|
||||
def test_help(self):
|
||||
"""Test the --help argument."""
|
||||
result = self.runCodegen('--help')
|
||||
self.assertIn('usage: gdbus-codegen', result.out)
|
||||
result = self.runCodegen("--help")
|
||||
self.assertIn("usage: gdbus-codegen", result.out)
|
||||
|
||||
def test_no_args(self):
|
||||
"""Test running with no arguments at all."""
|
||||
@ -276,11 +283,10 @@ class TestCodegen(unittest.TestCase):
|
||||
|
||||
def test_empty_interface_header(self):
|
||||
"""Test generating a header with an empty interface file."""
|
||||
result = self.runCodegenWithInterface('',
|
||||
'--output', '/dev/stdout',
|
||||
'--header')
|
||||
self.assertEqual('', result.err)
|
||||
self.assertEqual('''{standard_top_comment}
|
||||
result = self.runCodegenWithInterface("", "--output", "/dev/stdout", "--header")
|
||||
self.assertEqual("", result.err)
|
||||
self.assertEqual(
|
||||
"""{standard_top_comment}
|
||||
|
||||
#ifndef __STDOUT__
|
||||
#define __STDOUT__
|
||||
@ -292,16 +298,18 @@ G_BEGIN_DECLS
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __STDOUT__ */'''.format(**result.subs),
|
||||
result.out.strip())
|
||||
#endif /* __STDOUT__ */""".format(
|
||||
**result.subs
|
||||
),
|
||||
result.out.strip(),
|
||||
)
|
||||
|
||||
def test_empty_interface_body(self):
|
||||
"""Test generating a body with an empty interface file."""
|
||||
result = self.runCodegenWithInterface('',
|
||||
'--output', '/dev/stdout',
|
||||
'--body')
|
||||
self.assertEqual('', result.err)
|
||||
self.assertEqual('''{standard_top_comment}
|
||||
result = self.runCodegenWithInterface("", "--output", "/dev/stdout", "--body")
|
||||
self.assertEqual("", result.err)
|
||||
self.assertEqual(
|
||||
"""{standard_top_comment}
|
||||
|
||||
{standard_config_h_include}
|
||||
|
||||
@ -309,12 +317,15 @@ G_END_DECLS
|
||||
|
||||
{standard_header_includes}
|
||||
|
||||
{standard_typedefs_and_helpers}'''.format(**result.subs),
|
||||
result.out.strip())
|
||||
{standard_typedefs_and_helpers}""".format(
|
||||
**result.subs
|
||||
),
|
||||
result.out.strip(),
|
||||
)
|
||||
|
||||
def test_reproducible(self):
|
||||
"""Test builds are reproducible regardless of file ordering."""
|
||||
xml_contents1 = '''
|
||||
xml_contents1 = """
|
||||
<node>
|
||||
<interface name="com.acme.Coyote">
|
||||
<method name="Run"/>
|
||||
@ -324,40 +335,49 @@ G_END_DECLS
|
||||
<property name="Mood" type="s" access="read"/>
|
||||
</interface>
|
||||
</node>
|
||||
'''
|
||||
"""
|
||||
|
||||
xml_contents2 = '''
|
||||
xml_contents2 = """
|
||||
<node>
|
||||
<interface name="org.project.Bar.Frobnicator">
|
||||
<method name="RandomMethod"/>
|
||||
</interface>
|
||||
</node>
|
||||
'''
|
||||
"""
|
||||
|
||||
with tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
|
||||
suffix='1.xml', delete=False) as xml_file1, \
|
||||
tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
|
||||
suffix='2.xml', delete=False) as xml_file2:
|
||||
with tempfile.NamedTemporaryFile(
|
||||
dir=self.tmpdir.name, suffix="1.xml", delete=False
|
||||
) as xml_file1, tempfile.NamedTemporaryFile(
|
||||
dir=self.tmpdir.name, suffix="2.xml", delete=False
|
||||
) as xml_file2:
|
||||
# Write out the interfaces.
|
||||
xml_file1.write(xml_contents1.encode('utf-8'))
|
||||
xml_file2.write(xml_contents2.encode('utf-8'))
|
||||
xml_file1.write(xml_contents1.encode("utf-8"))
|
||||
xml_file2.write(xml_contents2.encode("utf-8"))
|
||||
|
||||
xml_file1.flush()
|
||||
xml_file2.flush()
|
||||
|
||||
# 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
|
||||
# again in another order.
|
||||
result1 = self.runCodegen(xml_file1.name, xml_file2.name,
|
||||
'--output', '/dev/stdout',
|
||||
header_or_body)
|
||||
self.assertEqual('', result1.err)
|
||||
result1 = self.runCodegen(
|
||||
xml_file1.name,
|
||||
xml_file2.name,
|
||||
"--output",
|
||||
"/dev/stdout",
|
||||
header_or_body,
|
||||
)
|
||||
self.assertEqual("", result1.err)
|
||||
|
||||
result2 = self.runCodegen(xml_file2.name, xml_file1.name,
|
||||
'--output', '/dev/stdout',
|
||||
header_or_body)
|
||||
self.assertEqual('', result2.err)
|
||||
result2 = self.runCodegen(
|
||||
xml_file2.name,
|
||||
xml_file1.name,
|
||||
"--output",
|
||||
"/dev/stdout",
|
||||
header_or_body,
|
||||
)
|
||||
self.assertEqual("", result2.err)
|
||||
|
||||
# The output should be the same.
|
||||
self.assertEqual(result1.out, result2.out)
|
||||
@ -365,94 +385,108 @@ G_END_DECLS
|
||||
def test_glib_min_required_invalid(self):
|
||||
"""Test running with an invalid --glib-min-required."""
|
||||
with self.assertRaises(subprocess.CalledProcessError):
|
||||
self.runCodegenWithInterface('',
|
||||
'--output', '/dev/stdout',
|
||||
'--body',
|
||||
'--glib-min-required', 'hello mum')
|
||||
self.runCodegenWithInterface(
|
||||
"",
|
||||
"--output",
|
||||
"/dev/stdout",
|
||||
"--body",
|
||||
"--glib-min-required",
|
||||
"hello mum",
|
||||
)
|
||||
|
||||
def test_glib_min_required_too_low(self):
|
||||
"""Test running with a --glib-min-required which is too low (and hence
|
||||
probably a typo)."""
|
||||
with self.assertRaises(subprocess.CalledProcessError):
|
||||
self.runCodegenWithInterface('',
|
||||
'--output', '/dev/stdout',
|
||||
'--body',
|
||||
'--glib-min-required', '2.6')
|
||||
self.runCodegenWithInterface(
|
||||
"", "--output", "/dev/stdout", "--body", "--glib-min-required", "2.6"
|
||||
)
|
||||
|
||||
def test_glib_min_required_major_only(self):
|
||||
"""Test running with a --glib-min-required which contains only a major version."""
|
||||
result = self.runCodegenWithInterface('',
|
||||
'--output', '/dev/stdout',
|
||||
'--header',
|
||||
'--glib-min-required', '3',
|
||||
'--glib-max-allowed', '3.2')
|
||||
self.assertEqual('', result.err)
|
||||
self.assertNotEqual('', result.out.strip())
|
||||
result = self.runCodegenWithInterface(
|
||||
"",
|
||||
"--output",
|
||||
"/dev/stdout",
|
||||
"--header",
|
||||
"--glib-min-required",
|
||||
"3",
|
||||
"--glib-max-allowed",
|
||||
"3.2",
|
||||
)
|
||||
self.assertEqual("", result.err)
|
||||
self.assertNotEqual("", result.out.strip())
|
||||
|
||||
def test_glib_min_required_with_micro(self):
|
||||
"""Test running with a --glib-min-required which contains a micro version."""
|
||||
result = self.runCodegenWithInterface('',
|
||||
'--output', '/dev/stdout',
|
||||
'--header',
|
||||
'--glib-min-required', '2.46.2')
|
||||
self.assertEqual('', result.err)
|
||||
self.assertNotEqual('', result.out.strip())
|
||||
result = self.runCodegenWithInterface(
|
||||
"", "--output", "/dev/stdout", "--header", "--glib-min-required", "2.46.2"
|
||||
)
|
||||
self.assertEqual("", result.err)
|
||||
self.assertNotEqual("", result.out.strip())
|
||||
|
||||
def test_glib_max_allowed_too_low(self):
|
||||
"""Test running with a --glib-max-allowed which is too low (and hence
|
||||
probably a typo)."""
|
||||
with self.assertRaises(subprocess.CalledProcessError):
|
||||
self.runCodegenWithInterface('',
|
||||
'--output', '/dev/stdout',
|
||||
'--body',
|
||||
'--glib-max-allowed', '2.6')
|
||||
self.runCodegenWithInterface(
|
||||
"", "--output", "/dev/stdout", "--body", "--glib-max-allowed", "2.6"
|
||||
)
|
||||
|
||||
def test_glib_max_allowed_major_only(self):
|
||||
"""Test running with a --glib-max-allowed which contains only a major version."""
|
||||
result = self.runCodegenWithInterface('',
|
||||
'--output', '/dev/stdout',
|
||||
'--header',
|
||||
'--glib-max-allowed', '3')
|
||||
self.assertEqual('', result.err)
|
||||
self.assertNotEqual('', result.out.strip())
|
||||
result = self.runCodegenWithInterface(
|
||||
"", "--output", "/dev/stdout", "--header", "--glib-max-allowed", "3"
|
||||
)
|
||||
self.assertEqual("", result.err)
|
||||
self.assertNotEqual("", result.out.strip())
|
||||
|
||||
def test_glib_max_allowed_with_micro(self):
|
||||
"""Test running with a --glib-max-allowed which contains a micro version."""
|
||||
result = self.runCodegenWithInterface('',
|
||||
'--output', '/dev/stdout',
|
||||
'--header',
|
||||
'--glib-max-allowed', '2.46.2')
|
||||
self.assertEqual('', result.err)
|
||||
self.assertNotEqual('', result.out.strip())
|
||||
result = self.runCodegenWithInterface(
|
||||
"", "--output", "/dev/stdout", "--header", "--glib-max-allowed", "2.46.2"
|
||||
)
|
||||
self.assertEqual("", result.err)
|
||||
self.assertNotEqual("", result.out.strip())
|
||||
|
||||
def test_glib_max_allowed_unstable(self):
|
||||
"""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
|
||||
end up less than --glib-min-required."""
|
||||
result = self.runCodegenWithInterface('',
|
||||
'--output', '/dev/stdout',
|
||||
'--header',
|
||||
'--glib-max-allowed', '2.63',
|
||||
'--glib-min-required', '2.64')
|
||||
self.assertEqual('', result.err)
|
||||
self.assertNotEqual('', result.out.strip())
|
||||
result = self.runCodegenWithInterface(
|
||||
"",
|
||||
"--output",
|
||||
"/dev/stdout",
|
||||
"--header",
|
||||
"--glib-max-allowed",
|
||||
"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):
|
||||
"""Test running with a --glib-max-allowed which is less than
|
||||
--glib-min-required."""
|
||||
with self.assertRaises(subprocess.CalledProcessError):
|
||||
self.runCodegenWithInterface('',
|
||||
'--output', '/dev/stdout',
|
||||
'--body',
|
||||
'--glib-max-allowed', '2.62',
|
||||
'--glib-min-required', '2.64')
|
||||
self.runCodegenWithInterface(
|
||||
"",
|
||||
"--output",
|
||||
"/dev/stdout",
|
||||
"--body",
|
||||
"--glib-max-allowed",
|
||||
"2.62",
|
||||
"--glib-min-required",
|
||||
"2.64",
|
||||
)
|
||||
|
||||
def test_unix_fd_types_and_annotations(self):
|
||||
"""Test an interface with `h` arguments, no annotation, and GLib < 2.64.
|
||||
|
||||
See issue #1726.
|
||||
"""
|
||||
interface_xml = '''
|
||||
interface_xml = """
|
||||
<node>
|
||||
<interface name="FDPassing">
|
||||
<method name="HelloFD">
|
||||
@ -470,71 +504,87 @@ G_END_DECLS
|
||||
<arg name="files" type="a{sh}" direction="in"/>
|
||||
</method>
|
||||
</interface>
|
||||
</node>'''
|
||||
</node>"""
|
||||
|
||||
# Try without specifying --glib-min-required.
|
||||
result = self.runCodegenWithInterface(interface_xml,
|
||||
'--output', '/dev/stdout',
|
||||
'--header')
|
||||
self.assertEqual('', result.err)
|
||||
self.assertEqual(result.out.strip().count('GUnixFDList'), 6)
|
||||
result = self.runCodegenWithInterface(
|
||||
interface_xml, "--output", "/dev/stdout", "--header"
|
||||
)
|
||||
self.assertEqual("", result.err)
|
||||
self.assertEqual(result.out.strip().count("GUnixFDList"), 6)
|
||||
|
||||
# Specify an old --glib-min-required.
|
||||
result = self.runCodegenWithInterface(interface_xml,
|
||||
'--output', '/dev/stdout',
|
||||
'--header',
|
||||
'--glib-min-required', '2.32')
|
||||
self.assertEqual('', result.err)
|
||||
self.assertEqual(result.out.strip().count('GUnixFDList'), 6)
|
||||
result = self.runCodegenWithInterface(
|
||||
interface_xml,
|
||||
"--output",
|
||||
"/dev/stdout",
|
||||
"--header",
|
||||
"--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
|
||||
# mentions of `GUnixFDList` now, since the annotation is not needed to
|
||||
# trigger its use.
|
||||
result = self.runCodegenWithInterface(interface_xml,
|
||||
'--output', '/dev/stdout',
|
||||
'--header',
|
||||
'--glib-min-required', '2.64')
|
||||
self.assertEqual('', result.err)
|
||||
self.assertEqual(result.out.strip().count('GUnixFDList'), 18)
|
||||
result = self.runCodegenWithInterface(
|
||||
interface_xml,
|
||||
"--output",
|
||||
"/dev/stdout",
|
||||
"--header",
|
||||
"--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):
|
||||
"""Test that generated method call functions have @call_flags and
|
||||
@timeout_msec args if and only if GLib >= 2.64.
|
||||
"""
|
||||
interface_xml = '''
|
||||
interface_xml = """
|
||||
<node>
|
||||
<interface name="org.project.UsefulInterface">
|
||||
<method name="UsefulMethod"/>
|
||||
</interface>
|
||||
</node>'''
|
||||
</node>"""
|
||||
|
||||
# Try without specifying --glib-min-required.
|
||||
result = self.runCodegenWithInterface(interface_xml,
|
||||
'--output', '/dev/stdout',
|
||||
'--header')
|
||||
self.assertEqual('', result.err)
|
||||
self.assertEqual(result.out.strip().count('GDBusCallFlags call_flags,'), 0)
|
||||
self.assertEqual(result.out.strip().count('gint timeout_msec,'), 0)
|
||||
result = self.runCodegenWithInterface(
|
||||
interface_xml, "--output", "/dev/stdout", "--header"
|
||||
)
|
||||
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 an old --glib-min-required.
|
||||
result = self.runCodegenWithInterface(interface_xml,
|
||||
'--output', '/dev/stdout',
|
||||
'--header',
|
||||
'--glib-min-required', '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)
|
||||
result = self.runCodegenWithInterface(
|
||||
interface_xml,
|
||||
"--output",
|
||||
"/dev/stdout",
|
||||
"--header",
|
||||
"--glib-min-required",
|
||||
"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
|
||||
# present for both the async and sync method call functions.
|
||||
result = self.runCodegenWithInterface(interface_xml,
|
||||
'--output', '/dev/stdout',
|
||||
'--header',
|
||||
'--glib-min-required', '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)
|
||||
result = self.runCodegenWithInterface(
|
||||
interface_xml,
|
||||
"--output",
|
||||
"/dev/stdout",
|
||||
"--header",
|
||||
"--glib-min-required",
|
||||
"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())
|
||||
|
@ -8,14 +8,13 @@
|
||||
#
|
||||
# See issue #1580
|
||||
|
||||
import io
|
||||
import string
|
||||
import sys
|
||||
|
||||
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 c in string.ascii_lowercase:
|
||||
f.write("%s\n" % (c * 100))
|
||||
|
@ -5,7 +5,7 @@ import sys
|
||||
import re
|
||||
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]
|
||||
in_files = sys.argv[2:]
|
||||
@ -13,32 +13,37 @@ in_files = sys.argv[2:]
|
||||
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:
|
||||
if debug: print ('Input file: ', filename)
|
||||
with open(filename, 'rb') as f:
|
||||
if debug:
|
||||
print("Input file: ", filename)
|
||||
with open(filename, "rb") as f:
|
||||
for line in f:
|
||||
line = line.rstrip(b'\n').rstrip(b'\r')
|
||||
line = line.rstrip(b"\n").rstrip(b"\r")
|
||||
# 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:
|
||||
func = match.group(0)
|
||||
if not func in funcs:
|
||||
if func not in funcs:
|
||||
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)
|
||||
|
||||
for f in funcs:
|
||||
if f not in ['g_io_extension_get_type', 'g_settings_backend_get_type']:
|
||||
file_output += '*tp++ = {0} ();\n'.format(f)
|
||||
if f not in ["g_io_extension_get_type", "g_settings_backend_get_type"]:
|
||||
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.write(file_output)
|
||||
|
@ -23,29 +23,33 @@ import sys
|
||||
import tempfile
|
||||
import subprocess
|
||||
|
||||
if not 'GLIB_TEST_COMPILATION' in os.environ:
|
||||
print('''Test disabled because GLIB_TEST_COMPILATION is not set in the env.
|
||||
if "GLIB_TEST_COMPILATION" not in os.environ:
|
||||
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,
|
||||
and make sure you have glib build dependencies installed, including
|
||||
meson.''')
|
||||
meson."""
|
||||
)
|
||||
sys.exit(77)
|
||||
|
||||
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)
|
||||
|
||||
test_dir = os.path.dirname(sys.argv[0])
|
||||
|
||||
with tempfile.TemporaryDirectory() as builddir:
|
||||
env = os.environ.copy()
|
||||
env['PKG_CONFIG_PATH'] = sys.argv[1]
|
||||
sourcedir = os.path.join(test_dir, 'static-link')
|
||||
env["PKG_CONFIG_PATH"] = sys.argv[1]
|
||||
sourcedir = os.path.join(test_dir, "static-link")
|
||||
|
||||
# Ensure we can static link and run a test app
|
||||
subprocess.check_call(['meson', sourcedir, builddir], env=env)
|
||||
subprocess.check_call(['ninja', '-C', builddir, 'test'], env=env)
|
||||
subprocess.check_call(["meson", sourcedir, builddir], env=env)
|
||||
subprocess.check_call(["ninja", "-C", builddir, "test"], env=env)
|
||||
# FIXME: This probably only works on Linux
|
||||
out = subprocess.check_output(['ldd', os.path.join(builddir, 'test-static-link')], env=env).decode()
|
||||
if 'libgio' in out:
|
||||
print('test-static-link is dynamically linked on libgio')
|
||||
out = subprocess.check_output(
|
||||
["ldd", os.path.join(builddir, "test-static-link")], env=env
|
||||
).decode()
|
||||
if "libgio" in out:
|
||||
print("test-static-link is dynamically linked on libgio")
|
||||
exit(1)
|
||||
|
@ -30,8 +30,9 @@ import sys
|
||||
import base64
|
||||
from io import StringIO
|
||||
|
||||
|
||||
# Log modes
|
||||
class LogMode(object) :
|
||||
class LogMode(object):
|
||||
LogToError, LogToDiagnostics, LogToYAML, LogToAttachment = range(4)
|
||||
|
||||
|
||||
@ -73,19 +74,18 @@ class TAPTestResult(unittest.TestResult):
|
||||
sys.stdout = self.orig_stdout
|
||||
sys.stderr = self.orig_stderr
|
||||
|
||||
|
||||
def print_raw(self, text):
|
||||
self.output_stream.write(text)
|
||||
self.output_stream.flush()
|
||||
|
||||
def print_result(self, result, test, directive = None):
|
||||
def print_result(self, result, test, directive=None):
|
||||
self.output_stream.write("%s %d %s" % (result, self.testsRun, test.id()))
|
||||
if directive:
|
||||
self.output_stream.write(" # " + directive)
|
||||
self.output_stream.write("\n")
|
||||
self.output_stream.flush()
|
||||
|
||||
def ok(self, test, directive = None):
|
||||
def ok(self, test, directive=None):
|
||||
self.print_result("ok", test, directive)
|
||||
|
||||
def not_ok(self, test):
|
||||
@ -101,7 +101,7 @@ class TAPTestResult(unittest.TestResult):
|
||||
else:
|
||||
logs = [
|
||||
(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:
|
||||
if log_mode != LogMode.LogToError:
|
||||
@ -110,17 +110,23 @@ class TAPTestResult(unittest.TestResult):
|
||||
if log_mode == LogMode.LogToYAML:
|
||||
self.print_raw(" ---\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")
|
||||
elif log_mode == LogMode.LogToAttachment:
|
||||
self.print_raw(" ---\n")
|
||||
self.print_raw(" " + log_name + ":\n")
|
||||
self.print_raw(" File-Name: " + log_name + ".txt\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")
|
||||
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.
|
||||
# Seek to the beginning to avoid extensions on subsequent writes.
|
||||
log.seek(0)
|
||||
@ -155,10 +161,13 @@ class TAPTestResult(unittest.TestResult):
|
||||
|
||||
|
||||
class TAPTestRunner(object):
|
||||
def __init__(self,
|
||||
message_log = LogMode.LogToYAML,
|
||||
test_output_log = LogMode.LogToDiagnostics,
|
||||
output_stream = sys.stdout, error_stream = sys.stderr):
|
||||
def __init__(
|
||||
self,
|
||||
message_log=LogMode.LogToYAML,
|
||||
test_output_log=LogMode.LogToDiagnostics,
|
||||
output_stream=sys.stdout,
|
||||
error_stream=sys.stderr,
|
||||
):
|
||||
self.output_stream = output_stream
|
||||
self.error_stream = error_stream
|
||||
self.message_log = message_log
|
||||
@ -169,7 +178,8 @@ class TAPTestRunner(object):
|
||||
self.output_stream,
|
||||
self.error_stream,
|
||||
self.message_log,
|
||||
self.test_output_log)
|
||||
self.test_output_log,
|
||||
)
|
||||
test(result)
|
||||
result.printErrors()
|
||||
|
||||
|
156
glib/glib_gdb.py
156
glib/glib_gdb.py
@ -4,48 +4,57 @@ import sys
|
||||
if sys.version_info[0] >= 3:
|
||||
long = int
|
||||
|
||||
|
||||
# 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)
|
||||
|
||||
def g_quark_to_string (quark):
|
||||
|
||||
def g_quark_to_string(quark):
|
||||
if quark is None:
|
||||
return None
|
||||
quark = long(quark)
|
||||
if quark == 0:
|
||||
return None
|
||||
try:
|
||||
val = read_global_var ("quarks")
|
||||
max_q = long(read_global_var ("quark_seq_id"))
|
||||
except:
|
||||
val = read_global_var("quarks")
|
||||
max_q = long(read_global_var("quark_seq_id"))
|
||||
except Exception:
|
||||
try:
|
||||
val = read_global_var ("g_quarks")
|
||||
max_q = long(read_global_var ("g_quark_seq_id"))
|
||||
except:
|
||||
return None;
|
||||
val = read_global_var("g_quarks")
|
||||
max_q = long(read_global_var("g_quark_seq_id"))
|
||||
except Exception:
|
||||
return None
|
||||
if quark < max_q:
|
||||
return val[quark].string()
|
||||
return None
|
||||
|
||||
|
||||
# We override the node printers too, so that node->next is not expanded
|
||||
class GListNodePrinter:
|
||||
"Prints a GList node"
|
||||
|
||||
def __init__ (self, val):
|
||||
def __init__(self, val):
|
||||
self.val = val
|
||||
|
||||
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"]))
|
||||
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"]),
|
||||
)
|
||||
|
||||
|
||||
class GSListNodePrinter:
|
||||
"Prints a GSList node"
|
||||
|
||||
def __init__ (self, val):
|
||||
def __init__(self, val):
|
||||
self.val = val
|
||||
|
||||
def to_string (self):
|
||||
def to_string(self):
|
||||
return "{data=%s, next=0x%x}" % (str(self.val["data"]), long(self.val["next"]))
|
||||
|
||||
|
||||
class GListPrinter:
|
||||
"Prints a GList"
|
||||
|
||||
@ -61,27 +70,28 @@ class GListPrinter:
|
||||
def next(self):
|
||||
if self.link == 0:
|
||||
raise StopIteration
|
||||
data = self.link['data']
|
||||
self.link = self.link['next']
|
||||
data = self.link["data"]
|
||||
self.link = self.link["next"]
|
||||
count = self.count
|
||||
self.count = self.count + 1
|
||||
return ('[%d]' % count, data)
|
||||
return ("[%d]" % count, data)
|
||||
|
||||
__next__ = next
|
||||
|
||||
def __init__ (self, val, listtype):
|
||||
def __init__(self, val, listtype):
|
||||
self.val = val
|
||||
self.listtype = listtype
|
||||
|
||||
def children(self):
|
||||
return self._iterator(self.val, self.listtype)
|
||||
|
||||
def to_string (self):
|
||||
def to_string(self):
|
||||
return "0x%x" % (long(self.val))
|
||||
|
||||
def display_hint (self):
|
||||
def display_hint(self):
|
||||
return "array"
|
||||
|
||||
|
||||
class GHashPrinter:
|
||||
"Prints a GHashTable"
|
||||
|
||||
@ -90,7 +100,9 @@ class GHashPrinter:
|
||||
def __init__(self, ptr, big_items):
|
||||
self._big_items = big_items
|
||||
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())
|
||||
|
||||
@ -119,23 +131,23 @@ class GHashPrinter:
|
||||
def next(self):
|
||||
if self.ht == 0:
|
||||
raise StopIteration
|
||||
if self.value != None:
|
||||
if self.value is not None:
|
||||
v = self.value
|
||||
self.value = None
|
||||
return v
|
||||
while long(self.pos) < long(self.size):
|
||||
if long (self.hashes[self.pos]) >= 2:
|
||||
if long(self.hashes[self.pos]) >= 2:
|
||||
key = self.keys[self.pos]
|
||||
val = self.values[self.pos]
|
||||
|
||||
if self.keys_are_strings:
|
||||
key = key.cast (gdb.lookup_type("char").pointer())
|
||||
key = key.cast(gdb.lookup_type("char").pointer())
|
||||
|
||||
# Queue value for next result
|
||||
self.value = ('[%dv]'% (self.pos), val)
|
||||
self.value = ("[%dv]" % (self.pos), val)
|
||||
|
||||
# Increment pos and return key
|
||||
key = ('[%dk]'% (self.pos), key)
|
||||
key = ("[%dk]" % (self.pos), key)
|
||||
self.pos += 1
|
||||
return key
|
||||
|
||||
@ -144,33 +156,38 @@ class GHashPrinter:
|
||||
|
||||
__next__ = next
|
||||
|
||||
def __init__ (self, val):
|
||||
def __init__(self, val):
|
||||
self.val = val
|
||||
self.keys_are_strings = False
|
||||
try:
|
||||
string_hash = read_global_var ("g_str_hash")
|
||||
except:
|
||||
string_hash = read_global_var("g_str_hash")
|
||||
except Exception:
|
||||
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
|
||||
|
||||
def children(self):
|
||||
return self._iterator(self.val, self.keys_are_strings)
|
||||
|
||||
def to_string (self):
|
||||
def to_string(self):
|
||||
return "0x%x" % (long(self.val))
|
||||
|
||||
def display_hint (self):
|
||||
def display_hint(self):
|
||||
return "map"
|
||||
|
||||
def pretty_printer_lookup (val):
|
||||
|
||||
def pretty_printer_lookup(val):
|
||||
# None yet, want things like hash table and list
|
||||
|
||||
type = val.type.unqualified()
|
||||
|
||||
# If it points to a reference, get the reference.
|
||||
if type.code == gdb.TYPE_CODE_REF:
|
||||
type = type.target ()
|
||||
type = type.target()
|
||||
|
||||
if type.code == gdb.TYPE_CODE_PTR:
|
||||
type = type.target().unqualified()
|
||||
@ -189,52 +206,54 @@ def pretty_printer_lookup (val):
|
||||
return GListPrinter(val, "GSList")
|
||||
return None
|
||||
|
||||
def register (obj):
|
||||
|
||||
def register(obj):
|
||||
if obj is None:
|
||||
obj = gdb
|
||||
|
||||
obj.pretty_printers.append(pretty_printer_lookup)
|
||||
|
||||
class ForeachCommand (gdb.Command):
|
||||
|
||||
class ForeachCommand(gdb.Command):
|
||||
"""Foreach on list"""
|
||||
|
||||
def __init__ (self):
|
||||
super (ForeachCommand, self).__init__ ("gforeach",
|
||||
gdb.COMMAND_DATA,
|
||||
gdb.COMPLETE_SYMBOL)
|
||||
def __init__(self):
|
||||
super(ForeachCommand, self).__init__(
|
||||
"gforeach", gdb.COMMAND_DATA, gdb.COMPLETE_SYMBOL
|
||||
)
|
||||
|
||||
def valid_name (self, name):
|
||||
def valid_name(self, name):
|
||||
if not name[0].isalpha():
|
||||
return False
|
||||
return True
|
||||
|
||||
def parse_args (self, arg):
|
||||
def parse_args(self, arg):
|
||||
i = arg.find(" ")
|
||||
if i <= 0:
|
||||
raise Exception ("No var specified")
|
||||
raise Exception("No var specified")
|
||||
var = arg[:i]
|
||||
if not self.valid_name(var):
|
||||
raise Exception ("Invalid variable name")
|
||||
raise Exception("Invalid variable name")
|
||||
|
||||
while i < len (arg) and arg[i].isspace():
|
||||
while i < len(arg) and arg[i].isspace():
|
||||
i = i + 1
|
||||
|
||||
if arg[i:i+2] != "in":
|
||||
raise Exception ("Invalid syntax, missing in")
|
||||
if arg[i : i + 2] != "in":
|
||||
raise Exception("Invalid syntax, missing in")
|
||||
|
||||
i = i + 2
|
||||
|
||||
while i < len (arg) and arg[i].isspace():
|
||||
while i < len(arg) and arg[i].isspace():
|
||||
i = i + 1
|
||||
|
||||
colon = arg.find (":", i)
|
||||
colon = arg.find(":", i)
|
||||
if colon == -1:
|
||||
raise Exception ("Invalid syntax, missing colon")
|
||||
raise Exception("Invalid syntax, missing colon")
|
||||
|
||||
val = arg[i:colon]
|
||||
|
||||
colon = colon + 1
|
||||
while colon < len (arg) and arg[colon].isspace():
|
||||
while colon < len(arg) and arg[colon].isspace():
|
||||
colon = colon + 1
|
||||
|
||||
command = arg[colon:]
|
||||
@ -242,25 +261,25 @@ class ForeachCommand (gdb.Command):
|
||||
return (var, val, command)
|
||||
|
||||
def do_iter(self, arg, item, command):
|
||||
item = item.cast (gdb.lookup_type("void").pointer())
|
||||
item = item.cast(gdb.lookup_type("void").pointer())
|
||||
item = long(item)
|
||||
to_eval = "set $%s = (void *)0x%x\n"%(arg, item)
|
||||
to_eval = "set $%s = (void *)0x%x\n" % (arg, item)
|
||||
gdb.execute(to_eval)
|
||||
gdb.execute(command)
|
||||
|
||||
def slist_iterator (self, arg, container, command):
|
||||
l = container.cast (gdb.lookup_type("GSList").pointer())
|
||||
while long(l) != 0:
|
||||
self.do_iter (arg, l["data"], command)
|
||||
l = l["next"]
|
||||
def slist_iterator(self, arg, container, command):
|
||||
list_element = container.cast(gdb.lookup_type("GSList").pointer())
|
||||
while long(list_element) != 0:
|
||||
self.do_iter(arg, list_element["data"], command)
|
||||
list_element = list_element["next"]
|
||||
|
||||
def list_iterator (self, arg, container, command):
|
||||
l = container.cast (gdb.lookup_type("GList").pointer())
|
||||
while long(l) != 0:
|
||||
self.do_iter (arg, l["data"], command)
|
||||
l = l["next"]
|
||||
def list_iterator(self, arg, container, command):
|
||||
list_element = container.cast(gdb.lookup_type("GList").pointer())
|
||||
while long(list_element) != 0:
|
||||
self.do_iter(arg, list_element["data"], command)
|
||||
list_element = list_element["next"]
|
||||
|
||||
def pick_iterator (self, container):
|
||||
def pick_iterator(self, container):
|
||||
t = container.type.unqualified()
|
||||
if t.code == gdb.TYPE_CODE_PTR:
|
||||
t = t.target().unqualified()
|
||||
@ -269,12 +288,13 @@ class ForeachCommand (gdb.Command):
|
||||
return self.slist_iterator
|
||||
if t == "GList":
|
||||
return self.list_iterator
|
||||
raise Exception("Invalid container type %s"%(str(container.type)))
|
||||
raise Exception("Invalid container type %s" % (str(container.type)))
|
||||
|
||||
def invoke (self, arg, from_tty):
|
||||
def invoke(self, arg, from_tty):
|
||||
(var, container, command) = self.parse_args(arg)
|
||||
container = gdb.parse_and_eval (container)
|
||||
container = gdb.parse_and_eval(container)
|
||||
func = self.pick_iterator(container)
|
||||
func(var, container, command)
|
||||
|
||||
ForeachCommand ()
|
||||
|
||||
ForeachCommand()
|
||||
|
@ -4,21 +4,25 @@
|
||||
#
|
||||
# ./update-gtranslit.py /path/to/glibc/localedata/locales > gtranslit-data.h
|
||||
|
||||
import sys, os
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
localedir = sys.argv[1]
|
||||
|
||||
|
||||
# returns true if the name looks like a POSIX 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
|
||||
|
||||
lang, _, land = name.partition('_')
|
||||
lang, _, land = name.partition("_")
|
||||
|
||||
return len(lang) == 2 or len(lang) == 3 and len(land) == 2
|
||||
|
||||
|
||||
# handles <U1234> style escapes
|
||||
def unescape(string):
|
||||
chunks = []
|
||||
@ -27,27 +31,29 @@ def unescape(string):
|
||||
i = 0
|
||||
|
||||
while i < n:
|
||||
start_escape = string.find('<', i)
|
||||
start_escape = string.find("<", i)
|
||||
|
||||
if start_escape == -1:
|
||||
chunks.append(string[i:])
|
||||
break
|
||||
|
||||
assert string[start_escape:start_escape + 2] == '<U'
|
||||
assert string[start_escape : (start_escape + 2)] == "<U"
|
||||
start_escape += 2
|
||||
|
||||
end_escape = string.find('>', start_escape)
|
||||
end_escape = string.find(">", start_escape)
|
||||
assert end_escape != -1
|
||||
|
||||
chunks.append(chr(int(string[start_escape:end_escape], 16)))
|
||||
i = end_escape + 1
|
||||
|
||||
return ''.join(chunks)
|
||||
return "".join(chunks)
|
||||
|
||||
|
||||
# Checks if a string is ascii
|
||||
def is_ascii(string):
|
||||
return all(ord(c) < 0x80 for c in string)
|
||||
|
||||
|
||||
# A Mapping is a map from non-ascii strings to ascii strings.
|
||||
#
|
||||
# It corresponds to a sequence of one or more mapping lines:
|
||||
@ -62,31 +68,32 @@ class Mapping:
|
||||
|
||||
# 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
|
||||
# dictionary, with the origin string as the key. In the case of
|
||||
# IGNORE, stores the empty string.
|
||||
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)
|
||||
|
||||
for alternative in value.split(';'):
|
||||
for alternative in value.split(";"):
|
||||
if alternative[0] == '"' and alternative[-1] == '"':
|
||||
unescaped = unescape(alternative[1:-1])
|
||||
if is_ascii(unescaped):
|
||||
self.mapping[key] = unescaped
|
||||
break
|
||||
|
||||
elif alternative[0] == '<' and alternative[-1] == '>':
|
||||
elif alternative[0] == "<" and alternative[-1] == ">":
|
||||
unescaped = unescape(alternative)
|
||||
if is_ascii(unescaped):
|
||||
self.mapping[key] = unescaped
|
||||
break
|
||||
|
||||
elif alternative == 'IGNORE':
|
||||
self.mapping[key] = ''
|
||||
elif alternative == "IGNORE":
|
||||
self.mapping[key] = ""
|
||||
break
|
||||
|
||||
# Performs a normal dictionary merge, but ensures that there are no
|
||||
@ -109,6 +116,7 @@ class Mapping:
|
||||
|
||||
return self.serialised
|
||||
|
||||
|
||||
# A Chain is a sequence of mappings and chains.
|
||||
#
|
||||
# A chain contains another chain whenever "copy" or "include" is
|
||||
@ -135,16 +143,16 @@ class Chain:
|
||||
in_lc_ctype = False
|
||||
in_translit = False
|
||||
|
||||
fp = open(filename, encoding='ascii', errors='surrogateescape')
|
||||
fp = open(filename, encoding="ascii", errors="surrogateescape")
|
||||
|
||||
for line in fp:
|
||||
line = line.strip()
|
||||
|
||||
if in_lc_ctype:
|
||||
if line == 'END LC_CTYPE':
|
||||
if line == "END LC_CTYPE":
|
||||
break
|
||||
|
||||
if line.startswith('copy') or line.startswith('include'):
|
||||
if line.startswith("copy") or line.startswith("include"):
|
||||
if current_mapping:
|
||||
self.chain.append(current_mapping)
|
||||
|
||||
@ -155,29 +163,29 @@ class Chain:
|
||||
|
||||
current_mapping = None
|
||||
|
||||
elif line == 'translit_start':
|
||||
elif line == "translit_start":
|
||||
in_translit = True
|
||||
|
||||
elif line == 'translit_end':
|
||||
elif line == "translit_end":
|
||||
in_translit = False
|
||||
|
||||
elif in_translit and line.startswith('<U'):
|
||||
elif in_translit and line.startswith("<U"):
|
||||
if not current_mapping:
|
||||
current_mapping = Mapping()
|
||||
|
||||
current_mapping.consider_mapping_line(line)
|
||||
|
||||
elif line == '' or line.startswith('%'):
|
||||
elif line == "" or line.startswith("%"):
|
||||
pass
|
||||
|
||||
elif 'default_missing <U003F>':
|
||||
elif "default_missing <U003F>":
|
||||
pass
|
||||
|
||||
elif in_translit:
|
||||
print('unknown line:', line)
|
||||
print("unknown line:", line)
|
||||
assert False
|
||||
|
||||
elif line == 'LC_CTYPE':
|
||||
elif line == "LC_CTYPE":
|
||||
in_lc_ctype = True
|
||||
|
||||
if current_mapping:
|
||||
@ -199,7 +207,9 @@ class Chain:
|
||||
|
||||
i = 0
|
||||
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.
|
||||
self.chain[i].merge_mapping(self.chain[i + 1])
|
||||
del self.chain[i + 1]
|
||||
@ -215,10 +225,13 @@ class Chain:
|
||||
|
||||
return self.serialised
|
||||
|
||||
|
||||
# Chain cache -- allows sharing of common chains
|
||||
chains = {}
|
||||
|
||||
|
||||
def get_chain(name):
|
||||
if not name in chains:
|
||||
if name not in chains:
|
||||
chains[name] = Chain(name)
|
||||
|
||||
return chains[name]
|
||||
@ -227,10 +240,11 @@ def get_chain(name):
|
||||
# Remove the country name from a locale, preserving variant
|
||||
# eg: 'sr_RS@latin' -> 'sr@latin'
|
||||
def remove_country(string):
|
||||
base, at, variant = string.partition('@')
|
||||
lang, _, land = base.partition('_')
|
||||
base, at, variant = string.partition("@")
|
||||
lang, _, land = base.partition("_")
|
||||
return lang + at + variant
|
||||
|
||||
|
||||
def encode_range(start, end):
|
||||
assert start <= end
|
||||
length = end - start
|
||||
@ -244,8 +258,10 @@ def encode_range(start, end):
|
||||
|
||||
return result
|
||||
|
||||
|
||||
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:
|
||||
def __init__(self):
|
||||
@ -284,7 +300,9 @@ class Serialiser:
|
||||
languages = list(set(remove_country(locale) for locale in self.locales))
|
||||
|
||||
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]]
|
||||
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
|
||||
# eg: 'de@euro' and 'de'
|
||||
for variant in list(locale for locale in self.locales if '@' in locale):
|
||||
base, _, _ = variant.partition('@')
|
||||
for variant in list(locale for locale in self.locales if "@" in locale):
|
||||
base, _, _ = variant.partition("@")
|
||||
if base in self.locales and self.locales[base] == self.locales[variant]:
|
||||
del self.locales[variant]
|
||||
|
||||
@ -305,19 +323,19 @@ class Serialiser:
|
||||
del self.locales[locale]
|
||||
|
||||
def to_c(self):
|
||||
src_table = ''
|
||||
ascii_table = ''
|
||||
src_table = ""
|
||||
ascii_table = ""
|
||||
mappings_table = []
|
||||
mapping_ranges = []
|
||||
chains_table = []
|
||||
chain_starts = []
|
||||
locale_names = ''
|
||||
locale_names = ""
|
||||
locale_index = []
|
||||
max_lookup = 0
|
||||
max_localename = 0
|
||||
|
||||
for mapping in self.mappings:
|
||||
mapping_ranges.append ((len(mappings_table), len(mapping)))
|
||||
mapping_ranges.append((len(mappings_table), len(mapping)))
|
||||
|
||||
for key in sorted(mapping):
|
||||
if len(key) == 1 and ord(key[0]) < 0x8000:
|
||||
@ -326,7 +344,7 @@ class Serialiser:
|
||||
existing = src_table.find(key)
|
||||
if existing == -1:
|
||||
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_range = encode_range(start, len(src_table))
|
||||
max_lookup = max(max_lookup, len(key))
|
||||
@ -346,23 +364,21 @@ class Serialiser:
|
||||
else:
|
||||
ascii_range = encode_range(existing, existing + len(value))
|
||||
|
||||
mappings_table.append ((src_range, ascii_range))
|
||||
|
||||
mapping_end = len(mappings_table)
|
||||
mappings_table.append((src_range, ascii_range))
|
||||
|
||||
for chain in self.chains:
|
||||
chain_starts.append(len(chains_table))
|
||||
|
||||
for item_id in reversed(chain):
|
||||
assert item_id < 0xff
|
||||
assert item_id < 0xFF
|
||||
chains_table.append(item_id)
|
||||
chains_table.append(0xff)
|
||||
chains_table.append(0xFF)
|
||||
|
||||
for locale in sorted(self.locales):
|
||||
max_localename = max(max_localename, len(locale))
|
||||
name_offset = len(locale_names)
|
||||
assert all(ord(c) <= 0x7f for c in locale)
|
||||
locale_names += (locale + '\0')
|
||||
assert all(ord(c) <= 0x7F for c in locale)
|
||||
locale_names += locale + "\0"
|
||||
|
||||
item_id = self.locales[locale]
|
||||
|
||||
@ -370,30 +386,60 @@ class Serialiser:
|
||||
assert item_id < 256
|
||||
locale_index.append((name_offset, item_id))
|
||||
|
||||
print('/* Generated by update-gtranslit.py */')
|
||||
print('#define MAX_KEY_SIZE', max_lookup)
|
||||
print('#define MAX_LOCALE_NAME', max_localename)
|
||||
print('static const gunichar src_table[] = {', ', '.join(str(ord(c)) for c in src_table), '};')
|
||||
print("/* Generated by update-gtranslit.py */")
|
||||
print("#define MAX_KEY_SIZE", max_lookup)
|
||||
print("#define MAX_LOCALE_NAME", max_localename)
|
||||
print(
|
||||
"static const gunichar src_table[] = {",
|
||||
", ".join(str(ord(c)) for c in src_table),
|
||||
"};",
|
||||
)
|
||||
# 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('static const struct mapping_entry mappings_table[] =', 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,))
|
||||
print(
|
||||
"static const gchar ascii_table[] = {",
|
||||
", ".join(str(ord(c)) for c in ascii_table),
|
||||
"};",
|
||||
)
|
||||
print(
|
||||
"static const struct mapping_entry mappings_table[] =",
|
||||
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):
|
||||
print(self.mappings)
|
||||
print(self.chains)
|
||||
print(self.locales)
|
||||
|
||||
|
||||
locales = []
|
||||
for name in os.listdir(localedir):
|
||||
if looks_like_locale(name):
|
||||
chain = get_chain(name)
|
||||
locales.append (chain)
|
||||
locales.append(chain)
|
||||
chain.links += 1
|
||||
|
||||
serialiser = Serialiser()
|
||||
@ -401,8 +447,8 @@ serialiser = Serialiser()
|
||||
for locale in locales:
|
||||
serialiser.add_locale(locale.name, locale.serialise(serialiser))
|
||||
|
||||
i18n = get_chain('i18n').serialise(serialiser)
|
||||
combining = get_chain('translit_combining').serialise(serialiser)
|
||||
i18n = get_chain("i18n").serialise(serialiser)
|
||||
combining = get_chain("translit_combining").serialise(serialiser)
|
||||
serialiser.add_default(serialiser.add_chain([i18n, combining]))
|
||||
|
||||
serialiser.optimise_locales()
|
||||
|
@ -1,4 +1,3 @@
|
||||
import os.path
|
||||
import gdb
|
||||
import glib_gdb
|
||||
import sys
|
||||
@ -7,25 +6,29 @@ if sys.version_info[0] >= 3:
|
||||
long = int
|
||||
else:
|
||||
import itertools
|
||||
|
||||
map = itertools.imap
|
||||
|
||||
# FrameDecorator is new in gdb 7.7, so we adapt to its absence.
|
||||
try:
|
||||
import gdb.FrameDecorator
|
||||
|
||||
HAVE_GDB_FRAMEDECORATOR = True
|
||||
FrameDecorator = gdb.FrameDecorator.FrameDecorator
|
||||
except ImportError:
|
||||
HAVE_GDB_FRAMEDECORATOR = False
|
||||
|
||||
|
||||
# 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)
|
||||
|
||||
def g_type_to_typenode (gtype):
|
||||
def lookup_fundamental_type (typenode):
|
||||
|
||||
def g_type_to_typenode(gtype):
|
||||
def lookup_fundamental_type(typenode):
|
||||
if typenode == 0:
|
||||
return None
|
||||
val = read_global_var ("static_fundamental_type_nodes")
|
||||
val = read_global_var("static_fundamental_type_nodes")
|
||||
if val is None:
|
||||
return None
|
||||
return val[typenode >> 2].address
|
||||
@ -33,19 +36,21 @@ def g_type_to_typenode (gtype):
|
||||
gtype = long(gtype)
|
||||
typenode = gtype - gtype % 4
|
||||
if typenode > (255 << 2):
|
||||
typenode = gdb.Value(typenode).cast (gdb.lookup_type("TypeNode").pointer())
|
||||
typenode = gdb.Value(typenode).cast(gdb.lookup_type("TypeNode").pointer())
|
||||
else:
|
||||
typenode = lookup_fundamental_type (typenode)
|
||||
typenode = lookup_fundamental_type(typenode)
|
||||
return typenode
|
||||
|
||||
def g_type_to_name (gtype):
|
||||
|
||||
def g_type_to_name(gtype):
|
||||
typenode = g_type_to_typenode(gtype)
|
||||
if typenode != None:
|
||||
return glib_gdb.g_quark_to_string (typenode["qname"])
|
||||
if typenode is not None:
|
||||
return glib_gdb.g_quark_to_string(typenode["qname"])
|
||||
return None
|
||||
|
||||
def is_g_type_instance (val):
|
||||
def is_g_type_instance_helper (type):
|
||||
|
||||
def is_g_type_instance(val):
|
||||
def is_g_type_instance_helper(type):
|
||||
if str(type) == "GTypeInstance":
|
||||
return True
|
||||
|
||||
@ -56,7 +61,7 @@ def is_g_type_instance (val):
|
||||
return False
|
||||
|
||||
fields = type.fields()
|
||||
if len (fields) < 1:
|
||||
if len(fields) < 1:
|
||||
return False
|
||||
|
||||
first_field = fields[0]
|
||||
@ -66,51 +71,55 @@ def is_g_type_instance (val):
|
||||
if type.code != gdb.TYPE_CODE_PTR:
|
||||
return False
|
||||
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:
|
||||
try:
|
||||
inst = instance.cast (gdb.lookup_type("GTypeInstance").pointer())
|
||||
inst = instance.cast(gdb.lookup_type("GTypeInstance").pointer())
|
||||
klass = inst["g_class"]
|
||||
gtype = klass["g_type"]
|
||||
name = g_type_to_name (gtype)
|
||||
name = g_type_to_name(gtype)
|
||||
return name
|
||||
except RuntimeError:
|
||||
pass
|
||||
return None
|
||||
|
||||
|
||||
class GTypePrettyPrinter:
|
||||
"Prints a GType instance pointer"
|
||||
|
||||
def __init__ (self, val):
|
||||
def __init__(self, val):
|
||||
self.val = val
|
||||
|
||||
def to_string (self):
|
||||
name = g_type_name_from_instance (self.val)
|
||||
def to_string(self):
|
||||
name = g_type_name_from_instance(self.val)
|
||||
if name:
|
||||
return ("0x%x [%s]")% (long(self.val), name)
|
||||
return ("0x%x [%s]") % (long(self.val), name)
|
||||
return ("0x%x") % (long(self.val))
|
||||
|
||||
def is_g_type_class_instance (val):
|
||||
|
||||
def is_g_type_class_instance(val):
|
||||
type = val.type
|
||||
if type.code != gdb.TYPE_CODE_PTR:
|
||||
return False
|
||||
return str(type.target()) == "GTypeClass"
|
||||
|
||||
|
||||
class GTypeHandlePrettyPrinter:
|
||||
"Prints a GType instance"
|
||||
|
||||
def __init__ (self, val, hint = ""):
|
||||
def __init__(self, val, hint=""):
|
||||
self.val = val
|
||||
self.hint = hint
|
||||
|
||||
def to_string (self):
|
||||
def to_string(self):
|
||||
typenode = g_type_to_typenode(self.val)
|
||||
if typenode != None:
|
||||
name = glib_gdb.g_quark_to_string (typenode["qname"])
|
||||
s = ("0x%x [%s%s")% (long(self.val), self.hint, name)
|
||||
for i in range (1, int(typenode["n_supers"])):
|
||||
if typenode is not None:
|
||||
name = glib_gdb.g_quark_to_string(typenode["qname"])
|
||||
s = ("0x%x [%s%s") % (long(self.val), self.hint, name)
|
||||
for i in range(1, int(typenode["n_supers"])):
|
||||
node = g_type_to_typenode(typenode["supers"][i])
|
||||
if node:
|
||||
name = glib_gdb.g_quark_to_string(node["qname"])
|
||||
@ -121,161 +130,168 @@ class GTypeHandlePrettyPrinter:
|
||||
else:
|
||||
return ("0x%x") % (long(self.val))
|
||||
|
||||
def pretty_printer_lookup (val):
|
||||
if is_g_type_instance (val):
|
||||
return GTypePrettyPrinter (val)
|
||||
|
||||
def pretty_printer_lookup(val):
|
||||
if is_g_type_instance(val):
|
||||
return GTypePrettyPrinter(val)
|
||||
if str(val.type) == "GType":
|
||||
return GTypeHandlePrettyPrinter (val)
|
||||
if is_g_type_class_instance (val):
|
||||
return GTypeHandlePrettyPrinter (val["g_type"], "g_type: ")
|
||||
return GTypeHandlePrettyPrinter(val)
|
||||
if is_g_type_class_instance(val):
|
||||
return GTypeHandlePrettyPrinter(val["g_type"], "g_type: ")
|
||||
|
||||
return None
|
||||
|
||||
def get_signal_name (id):
|
||||
|
||||
def get_signal_name(id):
|
||||
if id is None:
|
||||
return None
|
||||
id = long(id)
|
||||
if id == 0:
|
||||
return None
|
||||
val = read_global_var ("g_signal_nodes")
|
||||
max_s = read_global_var ("g_n_signal_nodes")
|
||||
val = read_global_var("g_signal_nodes")
|
||||
max_s = read_global_var("g_n_signal_nodes")
|
||||
max_s = long(max_s)
|
||||
if id < max_s:
|
||||
return val[id]["name"].string()
|
||||
return None
|
||||
|
||||
|
||||
def frame_name(frame):
|
||||
return str(frame.function())
|
||||
|
||||
|
||||
def frame_var(frame, var):
|
||||
return frame.inferior_frame().read_var(var)
|
||||
|
||||
|
||||
class SignalFrame(FrameDecorator):
|
||||
def __init__ (self, frames):
|
||||
def __init__(self, frames):
|
||||
FrameDecorator.__init__(self, frames[-1])
|
||||
self.frame = frames[-1]
|
||||
self.frames = frames
|
||||
|
||||
def name (self):
|
||||
def name(self):
|
||||
return "signal-emission"
|
||||
|
||||
def read_var (self, frame, name, array = None):
|
||||
def read_var(self, frame, name, array=None):
|
||||
try:
|
||||
v = frame_var (frame, name)
|
||||
v = frame_var(frame, name)
|
||||
if v is None or v.is_optimized_out:
|
||||
return None
|
||||
if array != None:
|
||||
array.append (v)
|
||||
if array is not None:
|
||||
array.append(v)
|
||||
return v
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
def read_object (self, frame, name, array = None):
|
||||
def read_object(self, frame, name, array=None):
|
||||
try:
|
||||
v = frame_var (frame, name)
|
||||
v = frame_var(frame, name)
|
||||
if v is None or v.is_optimized_out:
|
||||
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
|
||||
if v != None and g_type_name_from_instance (v):
|
||||
if array != None:
|
||||
array.append (v)
|
||||
if v is not None and g_type_name_from_instance(v):
|
||||
if array is not None:
|
||||
array.append(v)
|
||||
return v
|
||||
return None
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
def append (self, array, obj):
|
||||
if obj != None:
|
||||
array.append (obj)
|
||||
def append(self, array, obj):
|
||||
if obj is not None:
|
||||
array.append(obj)
|
||||
|
||||
def or_join_array (self, array):
|
||||
def or_join_array(self, array):
|
||||
if len(array) == 0:
|
||||
return "???"
|
||||
else:
|
||||
return ' or '.join(set(map(str, array)))
|
||||
return " or ".join(set(map(str, array)))
|
||||
|
||||
def get_detailed_signal_from_frame(self, frame, signal):
|
||||
detail = self.read_var (frame, "detail")
|
||||
detail = glib_gdb.g_quark_to_string (detail)
|
||||
detail = self.read_var(frame, "detail")
|
||||
detail = glib_gdb.g_quark_to_string(detail)
|
||||
if detail is not None:
|
||||
return signal + ":" + detail
|
||||
else:
|
||||
return detail
|
||||
|
||||
def function (self):
|
||||
def function(self):
|
||||
instances = []
|
||||
signals = []
|
||||
|
||||
for frame in self.frames:
|
||||
name = frame_name(frame)
|
||||
if name == "signal_emit_unlocked_R":
|
||||
self.read_object (frame, "instance", instances)
|
||||
node = self.read_var (frame, "node")
|
||||
self.read_object(frame, "instance", instances)
|
||||
node = self.read_var(frame, "node")
|
||||
if node:
|
||||
signal = node["name"].string()
|
||||
signal = self.get_detailed_signal_from_frame(frame, signal)
|
||||
self.append(signals, signal)
|
||||
|
||||
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:
|
||||
instance = instance_and_params[0]["v_pointer"].cast (gdb.Type("GObject").pointer())
|
||||
self.append (instances, instance)
|
||||
id = self.read_var (frame, "signal_id")
|
||||
signal = get_signal_name (id)
|
||||
instance = instance_and_params[0]["v_pointer"].cast(
|
||||
gdb.Type("GObject").pointer()
|
||||
)
|
||||
self.append(instances, instance)
|
||||
id = self.read_var(frame, "signal_id")
|
||||
signal = get_signal_name(id)
|
||||
if signal:
|
||||
signal = self.get_detailed_signal_from_frame(frame, signal)
|
||||
self.append (signals, signal)
|
||||
self.append(signals, signal)
|
||||
|
||||
if name == "g_signal_emit_valist" or name == "g_signal_emit":
|
||||
self.read_object (frame, "instance", instances)
|
||||
id = self.read_var (frame, "signal_id")
|
||||
signal = get_signal_name (id)
|
||||
self.read_object(frame, "instance", instances)
|
||||
id = self.read_var(frame, "signal_id")
|
||||
signal = get_signal_name(id)
|
||||
if signal:
|
||||
signal = self.get_detailed_signal_from_frame(frame, signal)
|
||||
self.append (signals, signal)
|
||||
self.append(signals, signal)
|
||||
|
||||
if name == "g_signal_emit_by_name":
|
||||
self.read_object (frame, "instance", instances)
|
||||
self.read_var (frame, "detailed_signal", signals)
|
||||
self.read_object(frame, "instance", instances)
|
||||
self.read_var(frame, "detailed_signal", signals)
|
||||
break
|
||||
|
||||
instance = self.or_join_array (instances)
|
||||
signal = self.or_join_array (signals)
|
||||
instance = self.or_join_array(instances)
|
||||
signal = self.or_join_array(signals)
|
||||
|
||||
return "<emit signal %s on instance %s>" % (signal, instance)
|
||||
|
||||
def elided (self):
|
||||
def elided(self):
|
||||
return self.frames[0:-1]
|
||||
|
||||
def describe (self, stream, full):
|
||||
stream.write (" " + self.function () + "\n")
|
||||
def describe(self, stream, full):
|
||||
stream.write(" " + self.function() + "\n")
|
||||
|
||||
|
||||
class GFrameDecorator:
|
||||
def __init__ (self, iter):
|
||||
def __init__(self, iter):
|
||||
self.queue = []
|
||||
self.iter = iter
|
||||
|
||||
def __iter__ (self):
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def fill (self):
|
||||
def fill(self):
|
||||
while len(self.queue) <= 8:
|
||||
try:
|
||||
f = next(self.iter)
|
||||
self.queue.append (f)
|
||||
self.queue.append(f)
|
||||
except StopIteration:
|
||||
return
|
||||
|
||||
def find_signal_emission (self):
|
||||
for i in range (min (len(self.queue), 3)):
|
||||
def find_signal_emission(self):
|
||||
for i in range(min(len(self.queue), 3)):
|
||||
if frame_name(self.queue[i]) == "signal_emit_unlocked_R":
|
||||
return i
|
||||
return -1
|
||||
|
||||
def next (self):
|
||||
def next(self):
|
||||
# Ensure we have enough frames for a full signal emission
|
||||
self.fill()
|
||||
|
||||
@ -283,24 +299,26 @@ class GFrameDecorator:
|
||||
if len(self.queue) == 0:
|
||||
raise StopIteration
|
||||
|
||||
emission = self.find_signal_emission ()
|
||||
emission = self.find_signal_emission()
|
||||
if emission > 0:
|
||||
start = emission
|
||||
while True:
|
||||
if start == 0:
|
||||
break
|
||||
prev_name = frame_name(self.queue[start-1])
|
||||
prev_name = frame_name(self.queue[start - 1])
|
||||
if prev_name.find("_marshal_") >= 0 or prev_name == "g_closure_invoke":
|
||||
start = start - 1
|
||||
else:
|
||||
break
|
||||
end = emission + 1
|
||||
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",
|
||||
"g_signal_emit_by_name",
|
||||
"_g_closure_invoke_va"]:
|
||||
"_g_closure_invoke_va",
|
||||
]:
|
||||
end = end + 1
|
||||
else:
|
||||
break
|
||||
@ -311,18 +329,20 @@ class GFrameDecorator:
|
||||
|
||||
return self.queue.pop(0)
|
||||
|
||||
def __next__ (self):
|
||||
def __next__(self):
|
||||
return self.next()
|
||||
|
||||
|
||||
class GFrameFilter(object):
|
||||
name = 'glib'
|
||||
name = "glib"
|
||||
enabled = True
|
||||
priority = 100
|
||||
|
||||
def filter(self, iterator):
|
||||
return GFrameDecorator(iterator)
|
||||
|
||||
def register (obj):
|
||||
|
||||
def register(obj):
|
||||
if obj is None:
|
||||
obj = gdb
|
||||
|
||||
|
@ -32,7 +32,11 @@ import unittest
|
||||
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):
|
||||
@ -47,22 +51,23 @@ class TestGenmarshal(unittest.TestCase):
|
||||
parsing and generation code out into a library and unit test that, and
|
||||
convert this test to just check command line behaviour.
|
||||
"""
|
||||
|
||||
# Track the cwd, we want to back out to that to clean up our tempdir
|
||||
cwd = ''
|
||||
cwd = ""
|
||||
|
||||
def setUp(self):
|
||||
self.timeout_seconds = 10 # seconds per test
|
||||
self.tmpdir = tempfile.TemporaryDirectory()
|
||||
self.cwd = os.getcwd()
|
||||
os.chdir(self.tmpdir.name)
|
||||
print('tmpdir:', self.tmpdir.name)
|
||||
if 'G_TEST_BUILDDIR' in os.environ:
|
||||
self.__genmarshal = \
|
||||
os.path.join(os.environ['G_TEST_BUILDDIR'], '..',
|
||||
'glib-genmarshal')
|
||||
print("tmpdir:", self.tmpdir.name)
|
||||
if "G_TEST_BUILDDIR" in os.environ:
|
||||
self.__genmarshal = os.path.join(
|
||||
os.environ["G_TEST_BUILDDIR"], "..", "glib-genmarshal"
|
||||
)
|
||||
else:
|
||||
self.__genmarshal = shutil.which('glib-genmarshal')
|
||||
print('genmarshal:', self.__genmarshal)
|
||||
self.__genmarshal = shutil.which("glib-genmarshal")
|
||||
print("genmarshal:", self.__genmarshal)
|
||||
|
||||
def tearDown(self):
|
||||
os.chdir(self.cwd)
|
||||
@ -73,48 +78,53 @@ class TestGenmarshal(unittest.TestCase):
|
||||
|
||||
# shebang lines are not supported on native
|
||||
# Windows consoles
|
||||
if os.name == 'nt':
|
||||
if os.name == "nt":
|
||||
argv.insert(0, sys.executable)
|
||||
|
||||
argv.extend(args)
|
||||
print('Running:', argv)
|
||||
print("Running:", argv)
|
||||
|
||||
env = os.environ.copy()
|
||||
env['LC_ALL'] = 'C.UTF-8'
|
||||
print('Environment:', env)
|
||||
env["LC_ALL"] = "C.UTF-8"
|
||||
print("Environment:", env)
|
||||
|
||||
# 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,
|
||||
stderr=subprocess.PIPE,
|
||||
env=env,
|
||||
universal_newlines=True)
|
||||
universal_newlines=True,
|
||||
)
|
||||
info.check_returncode()
|
||||
out = info.stdout.strip()
|
||||
err = info.stderr.strip()
|
||||
|
||||
# Known substitutions for standard boilerplate
|
||||
subs = {
|
||||
'standard_top_comment':
|
||||
'This file is generated by glib-genmarshal, do not modify '
|
||||
'it. This code is licensed under the same license as the '
|
||||
'containing project. Note that it links to GLib, so must '
|
||||
'comply with the LGPL linking clauses.',
|
||||
'standard_top_pragma': dedent(
|
||||
'''
|
||||
"standard_top_comment": "This file is generated by glib-genmarshal, do not modify "
|
||||
"it. This code is licensed under the same license as the "
|
||||
"containing project. Note that it links to GLib, so must "
|
||||
"comply with the LGPL linking clauses.",
|
||||
"standard_top_pragma": dedent(
|
||||
"""
|
||||
#ifndef __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__ */
|
||||
''').strip(),
|
||||
'standard_includes': dedent(
|
||||
'''
|
||||
"""
|
||||
).strip(),
|
||||
"standard_includes": dedent(
|
||||
"""
|
||||
#include <glib-object.h>
|
||||
''').strip(),
|
||||
'standard_marshal_peek_defines': dedent(
|
||||
'''
|
||||
"""
|
||||
).strip(),
|
||||
"standard_marshal_peek_defines": dedent(
|
||||
"""
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
#define g_marshal_value_peek_boolean(v) g_value_get_boolean (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_variant(v) (v)->data[0].v_pointer
|
||||
#endif /* !G_ENABLE_DEBUG */
|
||||
''').strip(),
|
||||
"""
|
||||
).strip(),
|
||||
}
|
||||
|
||||
result = Result(info, out, err, subs)
|
||||
|
||||
print('Output:', result.out)
|
||||
print("Output:", result.out)
|
||||
return result
|
||||
|
||||
def runGenmarshalWithList(self, list_contents, *args):
|
||||
with tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
|
||||
suffix='.list',
|
||||
delete=False) as list_file:
|
||||
with tempfile.NamedTemporaryFile(
|
||||
dir=self.tmpdir.name, suffix=".list", delete=False
|
||||
) as list_file:
|
||||
# Write out the list.
|
||||
list_file.write(list_contents.encode('utf-8'))
|
||||
print(list_file.name + ':', list_contents)
|
||||
list_file.write(list_contents.encode("utf-8"))
|
||||
print(list_file.name + ":", list_contents)
|
||||
list_file.flush()
|
||||
|
||||
header_result = self.runGenmarshal(list_file.name,
|
||||
'--header', *args)
|
||||
body_result = self.runGenmarshal(list_file.name,
|
||||
'--body', *args)
|
||||
header_result = self.runGenmarshal(list_file.name, "--header", *args)
|
||||
body_result = self.runGenmarshal(list_file.name, "--body", *args)
|
||||
|
||||
header_result.subs['list_path'] = list_file.name
|
||||
body_result.subs['list_path'] = list_file.name
|
||||
header_result.subs["list_path"] = list_file.name
|
||||
body_result.subs["list_path"] = list_file.name
|
||||
|
||||
return (header_result, body_result)
|
||||
|
||||
def test_help(self):
|
||||
"""Test the --help argument."""
|
||||
result = self.runGenmarshal('--help')
|
||||
self.assertIn('usage: glib-genmarshal', result.out)
|
||||
result = self.runGenmarshal("--help")
|
||||
self.assertIn("usage: glib-genmarshal", result.out)
|
||||
|
||||
def test_no_args(self):
|
||||
"""Test running with no arguments at all."""
|
||||
result = self.runGenmarshal()
|
||||
self.assertEqual('', result.err)
|
||||
self.assertEqual('', result.out)
|
||||
self.assertEqual("", result.err)
|
||||
self.assertEqual("", result.out)
|
||||
|
||||
def test_empty_list(self):
|
||||
"""Test running with an empty list."""
|
||||
(header_result, body_result) = \
|
||||
self.runGenmarshalWithList('', '--quiet')
|
||||
(header_result, body_result) = self.runGenmarshalWithList("", "--quiet")
|
||||
|
||||
self.assertEqual('', header_result.err)
|
||||
self.assertEqual('', body_result.err)
|
||||
self.assertEqual("", header_result.err)
|
||||
self.assertEqual("", body_result.err)
|
||||
|
||||
self.assertEqual(dedent(
|
||||
'''
|
||||
self.assertEqual(
|
||||
dedent(
|
||||
"""
|
||||
/* {standard_top_comment} */
|
||||
{standard_top_pragma}
|
||||
|
||||
@ -219,28 +228,39 @@ class TestGenmarshal(unittest.TestCase):
|
||||
G_END_DECLS
|
||||
|
||||
{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_includes}
|
||||
|
||||
{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):
|
||||
"""Test running with a basic VOID:BOOLEAN list."""
|
||||
(header_result, body_result) = \
|
||||
self.runGenmarshalWithList('VOID:BOOLEAN', '--quiet')
|
||||
(header_result, body_result) = self.runGenmarshalWithList(
|
||||
"VOID:BOOLEAN", "--quiet"
|
||||
)
|
||||
|
||||
self.assertEqual('', header_result.err)
|
||||
self.assertEqual('', body_result.err)
|
||||
self.assertEqual("", header_result.err)
|
||||
self.assertEqual("", body_result.err)
|
||||
|
||||
self.assertEqual(dedent(
|
||||
'''
|
||||
self.assertEqual(
|
||||
dedent(
|
||||
"""
|
||||
/* {standard_top_comment} */
|
||||
{standard_top_pragma}
|
||||
|
||||
@ -255,28 +275,39 @@ class TestGenmarshal(unittest.TestCase):
|
||||
G_END_DECLS
|
||||
|
||||
{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_includes}
|
||||
|
||||
{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):
|
||||
"""Test running with a non-trivial VOID:BOOLEAN,INT64 list."""
|
||||
(header_result, body_result) = \
|
||||
self.runGenmarshalWithList('VOID:BOOLEAN,INT64', '--quiet')
|
||||
(header_result, body_result) = self.runGenmarshalWithList(
|
||||
"VOID:BOOLEAN,INT64", "--quiet"
|
||||
)
|
||||
|
||||
self.assertEqual('', header_result.err)
|
||||
self.assertEqual('', body_result.err)
|
||||
self.assertEqual("", header_result.err)
|
||||
self.assertEqual("", body_result.err)
|
||||
|
||||
self.assertEqual(dedent(
|
||||
'''
|
||||
self.assertEqual(
|
||||
dedent(
|
||||
"""
|
||||
/* {standard_top_comment} */
|
||||
{standard_top_pragma}
|
||||
|
||||
@ -297,11 +328,16 @@ class TestGenmarshal(unittest.TestCase):
|
||||
G_END_DECLS
|
||||
|
||||
{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_includes}
|
||||
|
||||
@ -343,8 +379,12 @@ class TestGenmarshal(unittest.TestCase):
|
||||
g_marshal_value_peek_int64 (param_values + 2),
|
||||
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):
|
||||
"""Test running with a basic VOID:VARIANT list, but without the
|
||||
@ -353,15 +393,16 @@ class TestGenmarshal(unittest.TestCase):
|
||||
|
||||
See issue #1793.
|
||||
"""
|
||||
(header_result, body_result) = \
|
||||
self.runGenmarshalWithList('VOID:VARIANT', '--quiet', '--nostdinc',
|
||||
'--valist-marshaller')
|
||||
(header_result, body_result) = self.runGenmarshalWithList(
|
||||
"VOID:VARIANT", "--quiet", "--nostdinc", "--valist-marshaller"
|
||||
)
|
||||
|
||||
self.assertEqual('', header_result.err)
|
||||
self.assertEqual('', body_result.err)
|
||||
self.assertEqual("", header_result.err)
|
||||
self.assertEqual("", body_result.err)
|
||||
|
||||
self.assertEqual(dedent(
|
||||
'''
|
||||
self.assertEqual(
|
||||
dedent(
|
||||
"""
|
||||
/* {standard_top_comment} */
|
||||
{standard_top_pragma}
|
||||
|
||||
@ -388,11 +429,16 @@ class TestGenmarshal(unittest.TestCase):
|
||||
G_END_DECLS
|
||||
|
||||
{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_marshal_peek_defines}
|
||||
|
||||
@ -474,8 +520,12 @@ class TestGenmarshal(unittest.TestCase):
|
||||
if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
|
||||
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):
|
||||
"""Test running with a basic VOID:STRING list, but without the
|
||||
@ -485,15 +535,16 @@ class TestGenmarshal(unittest.TestCase):
|
||||
|
||||
See issue #1792.
|
||||
"""
|
||||
(header_result, body_result) = \
|
||||
self.runGenmarshalWithList('VOID:STRING', '--quiet', '--nostdinc',
|
||||
'--valist-marshaller')
|
||||
(header_result, body_result) = self.runGenmarshalWithList(
|
||||
"VOID:STRING", "--quiet", "--nostdinc", "--valist-marshaller"
|
||||
)
|
||||
|
||||
self.assertEqual('', header_result.err)
|
||||
self.assertEqual('', body_result.err)
|
||||
self.assertEqual("", header_result.err)
|
||||
self.assertEqual("", body_result.err)
|
||||
|
||||
self.assertEqual(dedent(
|
||||
'''
|
||||
self.assertEqual(
|
||||
dedent(
|
||||
"""
|
||||
/* {standard_top_comment} */
|
||||
{standard_top_pragma}
|
||||
|
||||
@ -520,11 +571,16 @@ class TestGenmarshal(unittest.TestCase):
|
||||
G_END_DECLS
|
||||
|
||||
{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_marshal_peek_defines}
|
||||
|
||||
@ -606,8 +662,12 @@ class TestGenmarshal(unittest.TestCase):
|
||||
if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
|
||||
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):
|
||||
"""Test running with a basic VOID:PARAM list, but without the
|
||||
@ -618,15 +678,16 @@ class TestGenmarshal(unittest.TestCase):
|
||||
See issue #1792.
|
||||
"""
|
||||
self.maxDiff = None # TODO
|
||||
(header_result, body_result) = \
|
||||
self.runGenmarshalWithList('VOID:PARAM', '--quiet', '--nostdinc',
|
||||
'--valist-marshaller')
|
||||
(header_result, body_result) = self.runGenmarshalWithList(
|
||||
"VOID:PARAM", "--quiet", "--nostdinc", "--valist-marshaller"
|
||||
)
|
||||
|
||||
self.assertEqual('', header_result.err)
|
||||
self.assertEqual('', body_result.err)
|
||||
self.assertEqual("", header_result.err)
|
||||
self.assertEqual("", body_result.err)
|
||||
|
||||
self.assertEqual(dedent(
|
||||
'''
|
||||
self.assertEqual(
|
||||
dedent(
|
||||
"""
|
||||
/* {standard_top_comment} */
|
||||
{standard_top_pragma}
|
||||
|
||||
@ -653,11 +714,16 @@ class TestGenmarshal(unittest.TestCase):
|
||||
G_END_DECLS
|
||||
|
||||
{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_marshal_peek_defines}
|
||||
|
||||
@ -739,9 +805,13 @@ class TestGenmarshal(unittest.TestCase):
|
||||
if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
|
||||
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())
|
||||
|
@ -32,7 +32,7 @@ import unittest
|
||||
import taptestrunner
|
||||
|
||||
|
||||
Result = collections.namedtuple('Result', ('info', 'out', 'err', 'subs'))
|
||||
Result = collections.namedtuple("Result", ("info", "out", "err", "subs"))
|
||||
|
||||
|
||||
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
|
||||
convert this test to just check command line behaviour.
|
||||
"""
|
||||
|
||||
# Track the cwd, we want to back out to that to clean up our tempdir
|
||||
cwd = ''
|
||||
cwd = ""
|
||||
rspfile = False
|
||||
|
||||
def setUp(self):
|
||||
@ -56,14 +57,14 @@ class TestMkenums(unittest.TestCase):
|
||||
self.tmpdir = tempfile.TemporaryDirectory()
|
||||
self.cwd = os.getcwd()
|
||||
os.chdir(self.tmpdir.name)
|
||||
print('tmpdir:', self.tmpdir.name)
|
||||
if 'G_TEST_BUILDDIR' in os.environ:
|
||||
self.__mkenums = \
|
||||
os.path.join(os.environ['G_TEST_BUILDDIR'], '..',
|
||||
'glib-mkenums')
|
||||
print("tmpdir:", self.tmpdir.name)
|
||||
if "G_TEST_BUILDDIR" in os.environ:
|
||||
self.__mkenums = os.path.join(
|
||||
os.environ["G_TEST_BUILDDIR"], "..", "glib-mkenums"
|
||||
)
|
||||
else:
|
||||
self.__mkenums = shutil.which('glib-mkenums')
|
||||
print('rspfile: {}, mkenums:'.format(self.rspfile), self.__mkenums)
|
||||
self.__mkenums = shutil.which("glib-mkenums")
|
||||
print("rspfile: {}, mkenums:".format(self.rspfile), self.__mkenums)
|
||||
|
||||
def tearDown(self):
|
||||
os.chdir(self.cwd)
|
||||
@ -71,10 +72,12 @@ class TestMkenums(unittest.TestCase):
|
||||
|
||||
def _write_rspfile(self, argv):
|
||||
import shlex
|
||||
with tempfile.NamedTemporaryFile(dir=self.tmpdir.name, mode='w',
|
||||
delete=False) as f:
|
||||
contents = ' '.join([shlex.quote(arg) for arg in argv])
|
||||
print('Response file contains:', contents)
|
||||
|
||||
with tempfile.NamedTemporaryFile(
|
||||
dir=self.tmpdir.name, mode="w", delete=False
|
||||
) as f:
|
||||
contents = " ".join([shlex.quote(arg) for arg in argv])
|
||||
print("Response file contains:", contents)
|
||||
f.write(contents)
|
||||
f.flush()
|
||||
return f.name
|
||||
@ -82,60 +85,62 @@ class TestMkenums(unittest.TestCase):
|
||||
def runMkenums(self, *args):
|
||||
if self.rspfile:
|
||||
rspfile = self._write_rspfile(args)
|
||||
args = ['@' + rspfile]
|
||||
args = ["@" + rspfile]
|
||||
argv = [self.__mkenums]
|
||||
|
||||
# shebang lines are not supported on native
|
||||
# Windows consoles
|
||||
if os.name == 'nt':
|
||||
if os.name == "nt":
|
||||
argv.insert(0, sys.executable)
|
||||
|
||||
argv.extend(args)
|
||||
print('Running:', argv)
|
||||
print("Running:", argv)
|
||||
|
||||
env = os.environ.copy()
|
||||
env['LC_ALL'] = 'C.UTF-8'
|
||||
print('Environment:', env)
|
||||
env["LC_ALL"] = "C.UTF-8"
|
||||
print("Environment:", env)
|
||||
|
||||
# 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,
|
||||
stderr=subprocess.PIPE,
|
||||
env=env,
|
||||
universal_newlines=True)
|
||||
universal_newlines=True,
|
||||
)
|
||||
info.check_returncode()
|
||||
out = info.stdout.strip()
|
||||
err = info.stderr.strip()
|
||||
|
||||
# Known substitutions for standard boilerplate
|
||||
subs = {
|
||||
'standard_top_comment':
|
||||
'This file is generated by glib-mkenums, do not modify '
|
||||
'it. This code is licensed under the same license as the '
|
||||
'containing project. Note that it links to GLib, so must '
|
||||
'comply with the LGPL linking clauses.',
|
||||
'standard_bottom_comment': 'Generated data ends here'
|
||||
"standard_top_comment": "This file is generated by glib-mkenums, do not modify "
|
||||
"it. This code is licensed under the same license as the "
|
||||
"containing project. Note that it links to GLib, so must "
|
||||
"comply with the LGPL linking clauses.",
|
||||
"standard_bottom_comment": "Generated data ends here",
|
||||
}
|
||||
|
||||
result = Result(info, out, err, subs)
|
||||
|
||||
print('Output:', result.out)
|
||||
print("Output:", result.out)
|
||||
return result
|
||||
|
||||
def runMkenumsWithTemplate(self, template_contents, *args):
|
||||
with tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
|
||||
suffix='.template',
|
||||
delete=False) as template_file:
|
||||
with tempfile.NamedTemporaryFile(
|
||||
dir=self.tmpdir.name, suffix=".template", delete=False
|
||||
) as template_file:
|
||||
# Write out the template.
|
||||
template_file.write(template_contents.encode('utf-8'))
|
||||
print(template_file.name + ':', template_contents)
|
||||
template_file.write(template_contents.encode("utf-8"))
|
||||
print(template_file.name + ":", template_contents)
|
||||
template_file.flush()
|
||||
|
||||
return self.runMkenums('--template', template_file.name, *args)
|
||||
return self.runMkenums("--template", template_file.name, *args)
|
||||
|
||||
def runMkenumsWithAllSubstitutions(self, *args):
|
||||
'''Run glib-mkenums with a template which outputs all substitutions.'''
|
||||
template_contents = '''
|
||||
"""Run glib-mkenums with a template which outputs all substitutions."""
|
||||
template_contents = """
|
||||
/*** BEGIN file-header ***/
|
||||
file-header
|
||||
/*** END file-header ***/
|
||||
@ -203,51 +208,66 @@ comment: @comment@
|
||||
/*** BEGIN file-tail ***/
|
||||
file-tail
|
||||
/*** END file-tail ***/
|
||||
'''
|
||||
"""
|
||||
return self.runMkenumsWithTemplate(template_contents, *args)
|
||||
|
||||
def runMkenumsWithHeader(self, h_contents, encoding='utf-8'):
|
||||
with tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
|
||||
suffix='.h',
|
||||
delete=False) as h_file:
|
||||
def runMkenumsWithHeader(self, h_contents, encoding="utf-8"):
|
||||
with tempfile.NamedTemporaryFile(
|
||||
dir=self.tmpdir.name, suffix=".h", delete=False
|
||||
) as h_file:
|
||||
# Write out the header to be scanned.
|
||||
h_file.write(h_contents.encode(encoding))
|
||||
print(h_file.name + ':', h_contents)
|
||||
print(h_file.name + ":", h_contents)
|
||||
h_file.flush()
|
||||
|
||||
# Run glib-mkenums with a template which outputs all substitutions.
|
||||
result = self.runMkenumsWithAllSubstitutions(h_file.name)
|
||||
|
||||
# Known substitutions for generated filenames.
|
||||
result.subs.update({
|
||||
'filename': h_file.name,
|
||||
'basename': os.path.basename(h_file.name),
|
||||
})
|
||||
result.subs.update(
|
||||
{"filename": h_file.name, "basename": os.path.basename(h_file.name),}
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
def assertSingleEnum(self, result, 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):
|
||||
def assertSingleEnum(
|
||||
self,
|
||||
result,
|
||||
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
|
||||
enum and value matching the given arguments."""
|
||||
subs = dict({
|
||||
'enum_name_camel': enum_name_camel,
|
||||
'enum_name_lower': enum_name_lower,
|
||||
'enum_name_upper': enum_name_upper,
|
||||
'enum_name_short': enum_name_short,
|
||||
'enum_prefix': enum_prefix,
|
||||
'enum_since': enum_since,
|
||||
'type_lower': type_lower,
|
||||
'type_camel': type_camel,
|
||||
'type_upper': type_upper,
|
||||
'value_name': value_name,
|
||||
'value_nick': value_nick,
|
||||
'value_num': value_num,
|
||||
}, **result.subs)
|
||||
subs = dict(
|
||||
{
|
||||
"enum_name_camel": enum_name_camel,
|
||||
"enum_name_lower": enum_name_lower,
|
||||
"enum_name_upper": enum_name_upper,
|
||||
"enum_name_short": enum_name_short,
|
||||
"enum_prefix": enum_prefix,
|
||||
"enum_since": enum_since,
|
||||
"type_lower": type_lower,
|
||||
"type_camel": type_camel,
|
||||
"type_upper": type_upper,
|
||||
"value_name": value_name,
|
||||
"value_nick": value_nick,
|
||||
"value_num": value_num,
|
||||
},
|
||||
**result.subs
|
||||
)
|
||||
|
||||
self.assertEqual('''
|
||||
self.assertEqual(
|
||||
"""
|
||||
comment
|
||||
comment: {standard_top_comment}
|
||||
|
||||
@ -297,38 +317,51 @@ file-tail
|
||||
|
||||
comment
|
||||
comment: {standard_bottom_comment}
|
||||
'''.format(**subs).strip(), result.out)
|
||||
""".format(
|
||||
**subs
|
||||
).strip(),
|
||||
result.out,
|
||||
)
|
||||
|
||||
def test_help(self):
|
||||
"""Test the --help argument."""
|
||||
result = self.runMkenums('--help')
|
||||
self.assertIn('usage: glib-mkenums', result.out)
|
||||
result = self.runMkenums("--help")
|
||||
self.assertIn("usage: glib-mkenums", result.out)
|
||||
|
||||
def test_no_args(self):
|
||||
"""Test running with no arguments at all."""
|
||||
result = self.runMkenums()
|
||||
self.assertEqual('', result.err)
|
||||
self.assertEqual('''/* {standard_top_comment} */
|
||||
self.assertEqual("", result.err)
|
||||
self.assertEqual(
|
||||
"""/* {standard_top_comment} */
|
||||
|
||||
|
||||
/* {standard_bottom_comment} */'''.format(**result.subs),
|
||||
result.out.strip())
|
||||
/* {standard_bottom_comment} */""".format(
|
||||
**result.subs
|
||||
),
|
||||
result.out.strip(),
|
||||
)
|
||||
|
||||
def test_empty_template(self):
|
||||
"""Test running with an empty template and no header files."""
|
||||
result = self.runMkenumsWithTemplate('')
|
||||
self.assertEqual('', result.err)
|
||||
self.assertEqual('''/* {standard_top_comment} */
|
||||
result = self.runMkenumsWithTemplate("")
|
||||
self.assertEqual("", result.err)
|
||||
self.assertEqual(
|
||||
"""/* {standard_top_comment} */
|
||||
|
||||
|
||||
/* {standard_bottom_comment} */'''.format(**result.subs),
|
||||
result.out.strip())
|
||||
/* {standard_bottom_comment} */""".format(
|
||||
**result.subs
|
||||
),
|
||||
result.out.strip(),
|
||||
)
|
||||
|
||||
def test_no_headers(self):
|
||||
"""Test running with a complete template, but no header files."""
|
||||
result = self.runMkenumsWithAllSubstitutions()
|
||||
self.assertEqual('', result.err)
|
||||
self.assertEqual('''
|
||||
self.assertEqual("", result.err)
|
||||
self.assertEqual(
|
||||
"""
|
||||
comment
|
||||
comment: {standard_top_comment}
|
||||
|
||||
@ -338,13 +371,18 @@ file-tail
|
||||
|
||||
comment
|
||||
comment: {standard_bottom_comment}
|
||||
'''.format(**result.subs).strip(), result.out)
|
||||
""".format(
|
||||
**result.subs
|
||||
).strip(),
|
||||
result.out,
|
||||
)
|
||||
|
||||
def test_empty_header(self):
|
||||
"""Test an empty header."""
|
||||
result = self.runMkenumsWithHeader('')
|
||||
self.assertEqual('', result.err)
|
||||
self.assertEqual('''
|
||||
result = self.runMkenumsWithHeader("")
|
||||
self.assertEqual("", result.err)
|
||||
self.assertEqual(
|
||||
"""
|
||||
comment
|
||||
comment: {standard_top_comment}
|
||||
|
||||
@ -354,94 +392,134 @@ file-tail
|
||||
|
||||
comment
|
||||
comment: {standard_bottom_comment}
|
||||
'''.format(**result.subs).strip(), result.out)
|
||||
""".format(
|
||||
**result.subs
|
||||
).strip(),
|
||||
result.out,
|
||||
)
|
||||
|
||||
def test_enum_name(self):
|
||||
"""Test typedefs with an enum and a typedef name. Bug #794506."""
|
||||
h_contents = '''
|
||||
h_contents = """
|
||||
typedef enum _SomeEnumIdentifier {
|
||||
ENUM_VALUE
|
||||
} SomeEnumIdentifier;
|
||||
'''
|
||||
"""
|
||||
result = self.runMkenumsWithHeader(h_contents)
|
||||
self.assertEqual('', result.err)
|
||||
self.assertSingleEnum(result, 'SomeEnumIdentifier',
|
||||
'some_enum_identifier', 'SOME_ENUM_IDENTIFIER',
|
||||
'ENUM_IDENTIFIER', 'SOME', '', 'enum', 'Enum',
|
||||
'ENUM', 'ENUM_VALUE', 'value', '0')
|
||||
self.assertEqual("", result.err)
|
||||
self.assertSingleEnum(
|
||||
result,
|
||||
"SomeEnumIdentifier",
|
||||
"some_enum_identifier",
|
||||
"SOME_ENUM_IDENTIFIER",
|
||||
"ENUM_IDENTIFIER",
|
||||
"SOME",
|
||||
"",
|
||||
"enum",
|
||||
"Enum",
|
||||
"ENUM",
|
||||
"ENUM_VALUE",
|
||||
"value",
|
||||
"0",
|
||||
)
|
||||
|
||||
def test_non_utf8_encoding(self):
|
||||
"""Test source files with non-UTF-8 encoding. Bug #785113."""
|
||||
h_contents = '''
|
||||
h_contents = """
|
||||
/* Copyright © La Peña */
|
||||
typedef enum {
|
||||
ENUM_VALUE
|
||||
} SomeEnumIdentifier;
|
||||
'''
|
||||
result = self.runMkenumsWithHeader(h_contents, encoding='iso-8859-1')
|
||||
self.assertIn('WARNING: UnicodeWarning: ', result.err)
|
||||
self.assertSingleEnum(result, 'SomeEnumIdentifier',
|
||||
'some_enum_identifier', 'SOME_ENUM_IDENTIFIER',
|
||||
'ENUM_IDENTIFIER', 'SOME', '', 'enum', 'Enum',
|
||||
'ENUM', 'ENUM_VALUE', 'value', '0')
|
||||
"""
|
||||
result = self.runMkenumsWithHeader(h_contents, encoding="iso-8859-1")
|
||||
self.assertIn("WARNING: UnicodeWarning: ", result.err)
|
||||
self.assertSingleEnum(
|
||||
result,
|
||||
"SomeEnumIdentifier",
|
||||
"some_enum_identifier",
|
||||
"SOME_ENUM_IDENTIFIER",
|
||||
"ENUM_IDENTIFIER",
|
||||
"SOME",
|
||||
"",
|
||||
"enum",
|
||||
"Enum",
|
||||
"ENUM",
|
||||
"ENUM_VALUE",
|
||||
"value",
|
||||
"0",
|
||||
)
|
||||
|
||||
def test_reproducible(self):
|
||||
"""Test builds are reproducible regardless of file ordering.
|
||||
Bug #691436."""
|
||||
template_contents = 'template'
|
||||
template_contents = "template"
|
||||
|
||||
h_contents1 = '''
|
||||
h_contents1 = """
|
||||
typedef enum {
|
||||
FIRST,
|
||||
} Header1;
|
||||
'''
|
||||
"""
|
||||
|
||||
h_contents2 = '''
|
||||
h_contents2 = """
|
||||
typedef enum {
|
||||
SECOND,
|
||||
} Header2;
|
||||
'''
|
||||
"""
|
||||
|
||||
with tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
|
||||
suffix='1.h', delete=False) as h_file1, \
|
||||
tempfile.NamedTemporaryFile(dir=self.tmpdir.name,
|
||||
suffix='2.h', delete=False) as h_file2:
|
||||
with tempfile.NamedTemporaryFile(
|
||||
dir=self.tmpdir.name, suffix="1.h", delete=False
|
||||
) as h_file1, tempfile.NamedTemporaryFile(
|
||||
dir=self.tmpdir.name, suffix="2.h", delete=False
|
||||
) as h_file2:
|
||||
# Write out the headers.
|
||||
h_file1.write(h_contents1.encode('utf-8'))
|
||||
h_file2.write(h_contents2.encode('utf-8'))
|
||||
h_file1.write(h_contents1.encode("utf-8"))
|
||||
h_file2.write(h_contents2.encode("utf-8"))
|
||||
|
||||
h_file1.flush()
|
||||
h_file2.flush()
|
||||
|
||||
# Run glib-mkenums with the headers in one order, and then again
|
||||
# in another order.
|
||||
result1 = self.runMkenumsWithTemplate(template_contents,
|
||||
h_file1.name, h_file2.name)
|
||||
self.assertEqual('', result1.err)
|
||||
result1 = self.runMkenumsWithTemplate(
|
||||
template_contents, h_file1.name, h_file2.name
|
||||
)
|
||||
self.assertEqual("", result1.err)
|
||||
|
||||
result2 = self.runMkenumsWithTemplate(template_contents,
|
||||
h_file2.name, h_file1.name)
|
||||
self.assertEqual('', result2.err)
|
||||
result2 = self.runMkenumsWithTemplate(
|
||||
template_contents, h_file2.name, h_file1.name
|
||||
)
|
||||
self.assertEqual("", result2.err)
|
||||
|
||||
# The output should be the same.
|
||||
self.assertEqual(result1.out, result2.out)
|
||||
|
||||
def test_no_nick(self):
|
||||
"""Test trigraphs with a desc but no nick. Issue #1360."""
|
||||
h_contents = '''
|
||||
h_contents = """
|
||||
typedef enum {
|
||||
GEGL_SAMPLER_NEAREST = 0, /*< desc="nearest" >*/
|
||||
} GeglSamplerType;
|
||||
'''
|
||||
"""
|
||||
result = self.runMkenumsWithHeader(h_contents)
|
||||
self.assertEqual('', result.err)
|
||||
self.assertSingleEnum(result, 'GeglSamplerType',
|
||||
'gegl_sampler_type', 'GEGL_SAMPLER_TYPE',
|
||||
'SAMPLER_TYPE', 'GEGL', '', 'enum', 'Enum',
|
||||
'ENUM', 'GEGL_SAMPLER_NEAREST', 'nearest', '0')
|
||||
self.assertEqual("", result.err)
|
||||
self.assertSingleEnum(
|
||||
result,
|
||||
"GeglSamplerType",
|
||||
"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):
|
||||
template_contents = '''
|
||||
template_contents = """
|
||||
/*** BEGIN file-header ***/
|
||||
file-header
|
||||
filename: @filename@
|
||||
@ -457,18 +535,21 @@ comment: @comment@
|
||||
file-tail
|
||||
filename: @filename@
|
||||
basename: @basename@
|
||||
/*** END file-tail ***/'''
|
||||
/*** END file-tail ***/"""
|
||||
result = self.runMkenumsWithTemplate(template_contents)
|
||||
self.assertEqual(
|
||||
textwrap.dedent(
|
||||
'''
|
||||
"""
|
||||
WARNING: @filename@ used in file-header section.
|
||||
WARNING: @basename@ used in file-header section.
|
||||
WARNING: @filename@ used in file-tail section.
|
||||
WARNING: @basename@ used in file-tail section.
|
||||
''').strip(),
|
||||
result.err)
|
||||
self.assertEqual('''
|
||||
"""
|
||||
).strip(),
|
||||
result.err,
|
||||
)
|
||||
self.assertEqual(
|
||||
"""
|
||||
comment
|
||||
comment: {standard_top_comment}
|
||||
|
||||
@ -482,27 +563,44 @@ basename: @basename@
|
||||
|
||||
comment
|
||||
comment: {standard_bottom_comment}
|
||||
'''.format(**result.subs).strip(), result.out)
|
||||
""".format(
|
||||
**result.subs
|
||||
).strip(),
|
||||
result.out,
|
||||
)
|
||||
|
||||
def test_since(self):
|
||||
"""Test user-provided 'since' version handling
|
||||
https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1492"""
|
||||
h_contents = '''
|
||||
h_contents = """
|
||||
typedef enum { /*< since=1.0 >*/
|
||||
QMI_WMS_MESSAGE_PROTOCOL_CDMA = 0,
|
||||
} QmiWmsMessageProtocol;
|
||||
'''
|
||||
"""
|
||||
result = self.runMkenumsWithHeader(h_contents)
|
||||
self.assertEqual('', result.err)
|
||||
self.assertSingleEnum(result, 'QmiWmsMessageProtocol',
|
||||
'qmi_wms_message_protocol', 'QMI_WMS_MESSAGE_PROTOCOL',
|
||||
'WMS_MESSAGE_PROTOCOL', 'QMI', '1.0', 'enum', 'Enum',
|
||||
'ENUM', 'QMI_WMS_MESSAGE_PROTOCOL_CDMA', 'cdma', '0')
|
||||
self.assertEqual("", result.err)
|
||||
self.assertSingleEnum(
|
||||
result,
|
||||
"QmiWmsMessageProtocol",
|
||||
"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):
|
||||
'''Run all tests again in @rspfile mode'''
|
||||
"""Run all tests again in @rspfile mode"""
|
||||
|
||||
rspfile = True
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
unittest.main(testRunner=taptestrunner.TAPTestRunner())
|
||||
|
@ -30,8 +30,9 @@ import sys
|
||||
import base64
|
||||
from io import StringIO
|
||||
|
||||
|
||||
# Log modes
|
||||
class LogMode(object) :
|
||||
class LogMode(object):
|
||||
LogToError, LogToDiagnostics, LogToYAML, LogToAttachment = range(4)
|
||||
|
||||
|
||||
@ -73,19 +74,18 @@ class TAPTestResult(unittest.TestResult):
|
||||
sys.stdout = self.orig_stdout
|
||||
sys.stderr = self.orig_stderr
|
||||
|
||||
|
||||
def print_raw(self, text):
|
||||
self.output_stream.write(text)
|
||||
self.output_stream.flush()
|
||||
|
||||
def print_result(self, result, test, directive = None):
|
||||
def print_result(self, result, test, directive=None):
|
||||
self.output_stream.write("%s %d %s" % (result, self.testsRun, test.id()))
|
||||
if directive:
|
||||
self.output_stream.write(" # " + directive)
|
||||
self.output_stream.write("\n")
|
||||
self.output_stream.flush()
|
||||
|
||||
def ok(self, test, directive = None):
|
||||
def ok(self, test, directive=None):
|
||||
self.print_result("ok", test, directive)
|
||||
|
||||
def not_ok(self, test):
|
||||
@ -101,7 +101,7 @@ class TAPTestResult(unittest.TestResult):
|
||||
else:
|
||||
logs = [
|
||||
(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:
|
||||
if log_mode != LogMode.LogToError:
|
||||
@ -110,17 +110,23 @@ class TAPTestResult(unittest.TestResult):
|
||||
if log_mode == LogMode.LogToYAML:
|
||||
self.print_raw(" ---\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")
|
||||
elif log_mode == LogMode.LogToAttachment:
|
||||
self.print_raw(" ---\n")
|
||||
self.print_raw(" " + log_name + ":\n")
|
||||
self.print_raw(" File-Name: " + log_name + ".txt\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")
|
||||
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.
|
||||
# Seek to the beginning to avoid extensions on subsequent writes.
|
||||
log.seek(0)
|
||||
@ -155,10 +161,13 @@ class TAPTestResult(unittest.TestResult):
|
||||
|
||||
|
||||
class TAPTestRunner(object):
|
||||
def __init__(self,
|
||||
message_log = LogMode.LogToYAML,
|
||||
test_output_log = LogMode.LogToDiagnostics,
|
||||
output_stream = sys.stdout, error_stream = sys.stderr):
|
||||
def __init__(
|
||||
self,
|
||||
message_log=LogMode.LogToYAML,
|
||||
test_output_log=LogMode.LogToDiagnostics,
|
||||
output_stream=sys.stdout,
|
||||
error_stream=sys.stderr,
|
||||
):
|
||||
self.output_stream = output_stream
|
||||
self.error_stream = error_stream
|
||||
self.message_log = message_log
|
||||
@ -169,7 +178,8 @@ class TAPTestRunner(object):
|
||||
self.output_stream,
|
||||
self.error_stream,
|
||||
self.message_log,
|
||||
self.test_output_log)
|
||||
self.test_output_log,
|
||||
)
|
||||
test(result)
|
||||
result.printErrors()
|
||||
|
||||
|
@ -29,14 +29,16 @@ import argparse
|
||||
|
||||
def main(argv):
|
||||
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("CaseFolding.txt")
|
||||
args = parser.parse_args(argv[1:])
|
||||
version = getattr(args, "UNICODE-VERSION")
|
||||
filename = getattr(args, "CaseFolding.txt")
|
||||
|
||||
print("""\
|
||||
print(
|
||||
"""\
|
||||
# Test cases generated from Unicode {} data
|
||||
# by gen-casefold-txt.py. Do not edit.
|
||||
#
|
||||
@ -45,7 +47,10 @@ def main(argv):
|
||||
AaBbCc@@\taabbcc@@
|
||||
#
|
||||
# Now the automatic tests
|
||||
#""".format(version))
|
||||
#""".format(
|
||||
version
|
||||
)
|
||||
)
|
||||
|
||||
# Names of fields in the CaseFolding table
|
||||
CODE, STATUS, MAPPING = range(3)
|
||||
@ -60,8 +65,9 @@ AaBbCc@@\taabbcc@@
|
||||
fields = [f.strip() for f in line.split(";", 3)[:3]]
|
||||
if len(fields) != 3:
|
||||
raise SystemExit(
|
||||
"Entry for %s has wrong number of fields (%d)" % (
|
||||
fields[CODE], len(fields)))
|
||||
"Entry for %s has wrong number of fields (%d)"
|
||||
% (fields[CODE], len(fields))
|
||||
)
|
||||
|
||||
status = fields[STATUS]
|
||||
# skip simple and Turkic mappings
|
||||
@ -69,8 +75,7 @@ AaBbCc@@\taabbcc@@
|
||||
continue
|
||||
|
||||
code = chr(int(fields[CODE], 16))
|
||||
values = "".join(
|
||||
[chr(int(v, 16)) for v in fields[MAPPING].split()])
|
||||
values = "".join([chr(int(v, 16)) for v in fields[MAPPING].split()])
|
||||
print("{}\t{}".format(code, values))
|
||||
|
||||
|
||||
|
@ -27,9 +27,14 @@ import sys
|
||||
import argparse
|
||||
|
||||
|
||||
# Disable line length warnings as wrapping the test templates would be hard
|
||||
# flake8: noqa: E501
|
||||
|
||||
|
||||
def main(argv):
|
||||
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("UnicodeData.txt")
|
||||
parser.add_argument("SpecialCasing.txt")
|
||||
@ -39,9 +44,23 @@ def main(argv):
|
||||
filename_casing = getattr(args, "SpecialCasing.txt")
|
||||
|
||||
# Names of fields in Unicode data table.
|
||||
CODE, NAME, CATEGORY, COMBINING_CLASSES, BIDI_CATEGORY, DECOMPOSITION, \
|
||||
DECIMAL_VALUE, DIGIT_VALUE, NUMERIC_VALUE, MIRRORED, OLD_NAME, \
|
||||
COMMENT, UPPER, LOWER, TITLE = range(15)
|
||||
(
|
||||
CODE,
|
||||
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
|
||||
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(";")]
|
||||
if len(fields) != 15:
|
||||
raise SystemExit(
|
||||
"Entry for %s has wrong number of fields (%d)" % (
|
||||
fields[CODE], len(fields)))
|
||||
"Entry for %s has wrong number of fields (%d)"
|
||||
% (fields[CODE], len(fields))
|
||||
)
|
||||
|
||||
code = int(fields[CODE], 16)
|
||||
|
||||
@ -92,8 +112,23 @@ def main(argv):
|
||||
else:
|
||||
# The gap represents undefined characters. Only the type
|
||||
# matters.
|
||||
gfields = ['', '', 'Cn', '0', '', '', '', '', '', '', '',
|
||||
'', '', '', '']
|
||||
gfields = [
|
||||
"",
|
||||
"",
|
||||
"Cn",
|
||||
"0",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
]
|
||||
|
||||
last_code += 1
|
||||
while last_code < code:
|
||||
@ -117,8 +152,9 @@ def main(argv):
|
||||
fields = [f.strip() for f in line.split(";")]
|
||||
if len(fields) not in (4, 5):
|
||||
raise SystemExit(
|
||||
"Entry for %s has wrong number of fields (%d)" % (
|
||||
fields[CASE_CODE], len(fields)))
|
||||
"Entry for %s has wrong number of fields (%d)"
|
||||
% (fields[CASE_CODE], len(fields))
|
||||
)
|
||||
|
||||
if len(fields) == 5:
|
||||
# Ignore conditional special cases - we'll handle them manually
|
||||
@ -134,7 +170,8 @@ def main(argv):
|
||||
|
||||
|
||||
def print_tests(version, upper, title, lower):
|
||||
print("""\
|
||||
print(
|
||||
"""\
|
||||
# Test cases generated from Unicode {} data
|
||||
# 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\u0314\u0345\t\u03b1\u0314\u0345\t\u0391\u0314\u0345\t\u0391\u0314\u0399\t
|
||||
# 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
|
||||
# about the titlecase part here
|
||||
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
|
||||
#
|
||||
# Now the automatic tests
|
||||
#""".format(version))
|
||||
#""".format(
|
||||
version
|
||||
)
|
||||
)
|
||||
|
||||
for i in range(0x10ffff):
|
||||
for i in range(0x10FFFF):
|
||||
if i == 0x3A3:
|
||||
# Greek sigma needs special tests
|
||||
continue
|
||||
|
Loading…
Reference in New Issue
Block a user