Python queue, 2018-02-05

-----BEGIN PGP SIGNATURE-----
 
 iQIcBAABCAAGBQJaeOPNAAoJECgHk2+YTcWmW18QAIYVEuiOGgQY6iBcdYWe5Gaq
 u+XUogPN/eNVYXGuxPY/kKQ7xcnYGPgGpDVSg27mW4OGdyA10upaW+jWxRCHcPoK
 6kuLqCucFc7ptuwDZAeF8AFTvK3jhraNPBh6ApFjhTODr0X+ymGkCe+ELgVEGSTD
 7S5VOnw6BfR5zhp6HVgRma4H0SG5vhseXiDIJxEydoYp7DemFtFts3WDtj9f7VRm
 0Dac4/NWSWGIJpaS+zMrS3OvtswI9D66nC5tRHCVFOUEEj/likGyjFuPWa/eyGYz
 vtZyn0v+b2IcQxTPAMIlFkxqEXsKdlf4A4KCs0Wf0pIWU0qSAen7xffXaW6FGAWB
 uOClOY4+302sArBjtqfOAQP3TlRC+bonABkV6bJx9bObesfx9zQH/9fRgkLfVFHb
 /sSiDhwqRRJ43B1/1VhG7Fj152+qYWDWBZ1WnyEHXObAKGEkmlAiMVeZmBiNr9w6
 YTDCuOiZ9Rsv1IQRClCEUzDUyZ7XGpBpjJMCyUaW1PQFgu0j1cvaZLoG3MUuatKC
 PBGRW2beTQBlhJ1zzk2+uxWJ438P7fcxbsc8nf3wWQlKEixwsiQ3JT1cLBkvDwfX
 /ob+Sk1f/kVdjUI5z/Ydm5bfb1nAQBNdQges1xDfLuou3f8gS95qUu+De8BV6erA
 9c1/g8yZeokDs9gw5/IH
 =wKYf
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/ehabkost/tags/python-next-pull-request' into staging

Python queue, 2018-02-05

# gpg: Signature made Mon 05 Feb 2018 23:07:57 GMT
# gpg:                using RSA key 2807936F984DC5A6
# gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>"
# Primary key fingerprint: 5A32 2FD5 ABC4 D3DB ACCF  D1AA 2807 936F 984D C5A6

* remotes/ehabkost/tags/python-next-pull-request: (21 commits)
  docker: change Fedora images to run with python3
  travis: improve python version test coverage
  ui: update keycodemapdb to get py3 fixes
  input: add missing JIS keys to virtio input
  qemu.py: don't launch again before shutdown()
  qemu.py: cleanup redundant calls in launch()
  qemu.py: use poll() instead of 'returncode'
  qemu.py: always cleanup on shutdown()
  qemu.py: refactor launch()
  qemu.py: better control of created files
  qemu.py: remove unused import
  configure: allow use of python 3
  scripts: ensure signrom treats data as bytes
  qapi: force a UTF-8 locale for running Python
  qapi: ensure stable sort ordering when checking QAPI entities
  qapi: remove '-q' arg to diff when comparing QAPI output
  qapi: Adapt to moved location of 'maketrans' function in py3
  qapi: adapt to moved location of StringIO module in py3
  qapi: Use OrderedDict from standard library if available
  qapi: use items()/values() intead of iteritems()/itervalues()
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2018-02-06 19:28:08 +00:00
commit bc2943d6ca
12 changed files with 151 additions and 101 deletions

View File

@ -1,7 +1,7 @@
sudo: false sudo: false
language: c language: c
python: python:
- "2.4" - "2.6"
compiler: compiler:
- gcc - gcc
cache: ccache cache: ccache
@ -115,15 +115,17 @@ matrix:
- sudo apt-get build-dep -qq qemu - sudo apt-get build-dep -qq qemu
- wget -O - http://people.linaro.org/~alex.bennee/qemu-submodule-git-seed.tar.xz | tar -xvJ - wget -O - http://people.linaro.org/~alex.bennee/qemu-submodule-git-seed.tar.xz | tar -xvJ
- git submodule update --init --recursive - git submodule update --init --recursive
# Trusty System build with latest stable clang # Trusty System build with latest stable clang & python 3.0
- sudo: required - sudo: required
addons: addons:
dist: trusty dist: trusty
language: generic language: generic
compiler: none compiler: none
python:
- "3.0"
env: env:
- COMPILER_NAME=clang CXX=clang++-3.9 CC=clang-3.9 - COMPILER_NAME=clang CXX=clang++-3.9 CC=clang-3.9
- CONFIG="--disable-linux-user --cc=clang-3.9 --cxx=clang++-3.9" - CONFIG="--disable-linux-user --cc=clang-3.9 --cxx=clang++-3.9 --python=/usr/bin/python3"
before_install: before_install:
- wget -nv -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add - - wget -nv -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add -
- sudo apt-add-repository -y 'deb http://llvm.org/apt/trusty llvm-toolchain-trusty-3.9 main' - sudo apt-add-repository -y 'deb http://llvm.org/apt/trusty llvm-toolchain-trusty-3.9 main'
@ -134,15 +136,17 @@ matrix:
- git submodule update --init --recursive - git submodule update --init --recursive
before_script: before_script:
- ./configure ${CONFIG} || cat config.log - ./configure ${CONFIG} || cat config.log
# Trusty Linux User build with latest stable clang # Trusty Linux User build with latest stable clang & python 3.6
- sudo: required - sudo: required
addons: addons:
dist: trusty dist: trusty
language: generic language: generic
compiler: none compiler: none
python:
- "3.6"
env: env:
- COMPILER_NAME=clang CXX=clang++-3.9 CC=clang-3.9 - COMPILER_NAME=clang CXX=clang++-3.9 CC=clang-3.9
- CONFIG="--disable-system --cc=clang-3.9 --cxx=clang++-3.9" - CONFIG="--disable-system --cc=clang-3.9 --cxx=clang++-3.9 --python=/usr/bin/python3"
before_install: before_install:
- wget -nv -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add - - wget -nv -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add -
- sudo apt-add-repository -y 'deb http://llvm.org/apt/trusty llvm-toolchain-trusty-3.9 main' - sudo apt-add-repository -y 'deb http://llvm.org/apt/trusty llvm-toolchain-trusty-3.9 main'

View File

@ -20,6 +20,8 @@ ifneq ($(wildcard config-host.mak),)
all: all:
include config-host.mak include config-host.mak
PYTHON_UTF8 = LC_ALL= LANG=C LC_CTYPE=en_US.UTF-8 $(PYTHON)
git-submodule-update: git-submodule-update:
.PHONY: git-submodule-update .PHONY: git-submodule-update
@ -487,17 +489,17 @@ qapi-py = $(SRC_PATH)/scripts/qapi.py $(SRC_PATH)/scripts/ordereddict.py
qga/qapi-generated/qga-qapi-types.c qga/qapi-generated/qga-qapi-types.h :\ qga/qapi-generated/qga-qapi-types.c qga/qapi-generated/qga-qapi-types.h :\
$(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py) $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py \ $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-types.py \
$(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \ $(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \
"GEN","$@") "GEN","$@")
qga/qapi-generated/qga-qapi-visit.c qga/qapi-generated/qga-qapi-visit.h :\ qga/qapi-generated/qga-qapi-visit.c qga/qapi-generated/qga-qapi-visit.h :\
$(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py) $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py \ $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-visit.py \
$(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \ $(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \
"GEN","$@") "GEN","$@")
qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-marshal.c :\ qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-marshal.c :\
$(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \ $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-commands.py \
$(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \ $(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \
"GEN","$@") "GEN","$@")
@ -518,27 +520,27 @@ qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
qapi-types.c qapi-types.h :\ qapi-types.c qapi-types.h :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-types.py $(qapi-py) $(qapi-modules) $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py \ $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-types.py \
$(gen-out-type) -o "." -b $<, \ $(gen-out-type) -o "." -b $<, \
"GEN","$@") "GEN","$@")
qapi-visit.c qapi-visit.h :\ qapi-visit.c qapi-visit.h :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py) $(qapi-modules) $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py \ $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-visit.py \
$(gen-out-type) -o "." -b $<, \ $(gen-out-type) -o "." -b $<, \
"GEN","$@") "GEN","$@")
qapi-event.c qapi-event.h :\ qapi-event.c qapi-event.h :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-event.py $(qapi-py) $(qapi-modules) $(SRC_PATH)/scripts/qapi-event.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-event.py \ $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-event.py \
$(gen-out-type) -o "." $<, \ $(gen-out-type) -o "." $<, \
"GEN","$@") "GEN","$@")
qmp-commands.h qmp-marshal.c :\ qmp-commands.h qmp-marshal.c :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) $(qapi-modules) $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \ $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-commands.py \
$(gen-out-type) -o "." $<, \ $(gen-out-type) -o "." $<, \
"GEN","$@") "GEN","$@")
qmp-introspect.h qmp-introspect.c :\ qmp-introspect.h qmp-introspect.c :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-introspect.py $(qapi-py) $(qapi-modules) $(SRC_PATH)/scripts/qapi-introspect.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-introspect.py \ $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-introspect.py \
$(gen-out-type) -o "." $<, \ $(gen-out-type) -o "." $<, \
"GEN","$@") "GEN","$@")
@ -811,10 +813,10 @@ qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx $(SRC_PATH)/scripts/hxtool
docs/interop/qemu-qmp-qapi.texi docs/interop/qemu-ga-qapi.texi: $(SRC_PATH)/scripts/qapi2texi.py $(qapi-py) docs/interop/qemu-qmp-qapi.texi docs/interop/qemu-ga-qapi.texi: $(SRC_PATH)/scripts/qapi2texi.py $(qapi-py)
docs/interop/qemu-qmp-qapi.texi: $(qapi-modules) docs/interop/qemu-qmp-qapi.texi: $(qapi-modules)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi2texi.py $< > $@,"GEN","$@") $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi2texi.py $< > $@,"GEN","$@")
docs/interop/qemu-ga-qapi.texi: $(SRC_PATH)/qga/qapi-schema.json docs/interop/qemu-ga-qapi.texi: $(SRC_PATH)/qga/qapi-schema.json
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi2texi.py $< > $@,"GEN","$@") $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi2texi.py $< > $@,"GEN","$@")
qemu.1: qemu-doc.texi qemu-options.texi qemu-monitor.texi qemu-monitor-info.texi qemu.1: qemu-doc.texi qemu-options.texi qemu-monitor.texi qemu-monitor-info.texi
qemu.1: qemu-option-trace.texi qemu.1: qemu-option-trace.texi

5
configure vendored
View File

@ -1604,9 +1604,8 @@ fi
# Note that if the Python conditional here evaluates True we will exit # Note that if the Python conditional here evaluates True we will exit
# with status 1 which is a shell 'false' value. # with status 1 which is a shell 'false' value.
if ! $python -c 'import sys; sys.exit(sys.version_info < (2,6) or sys.version_info >= (3,))'; then if ! $python -c 'import sys; sys.exit(sys.version_info < (2,6))'; then
error_exit "Cannot use '$python', Python 2.6 or later is required." \ error_exit "Cannot use '$python', Python 2 >= 2.6 or Python 3 is required." \
"Note that Python 3 or later is not yet supported." \
"Use --python=/path/to/python to specify a supported Python." "Use --python=/path/to/python to specify a supported Python."
fi fi

View File

@ -748,6 +748,9 @@
# @ac_bookmarks: since 2.10 # @ac_bookmarks: since 2.10
# altgr, altgr_r: dropped in 2.10 # altgr, altgr_r: dropped in 2.10
# #
# @muhenkan: since 2.12
# @katakanahiragana: since 2.12
#
# 'sysrq' was mistakenly added to hack around the fact that # 'sysrq' was mistakenly added to hack around the fact that
# the ps2 driver was not generating correct scancodes sequences # the ps2 driver was not generating correct scancodes sequences
# when 'alt+print' was pressed. This flaw is now fixed and the # when 'alt+print' was pressed. This flaw is now fixed and the
@ -775,7 +778,7 @@
'left', 'up', 'down', 'right', 'insert', 'delete', 'stop', 'again', 'left', 'up', 'down', 'right', 'insert', 'delete', 'stop', 'again',
'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', 'cut', 'props', 'undo', 'front', 'copy', 'open', 'paste', 'find', 'cut',
'lf', 'help', 'meta_l', 'meta_r', 'compose', 'pause', 'lf', 'help', 'meta_l', 'meta_r', 'compose', 'pause',
'ro', 'hiragana', 'henkan', 'yen', 'ro', 'hiragana', 'henkan', 'yen', 'muhenkan', 'katakanahiragana',
'kp_comma', 'kp_equals', 'power', 'sleep', 'wake', 'kp_comma', 'kp_equals', 'power', 'sleep', 'wake',
'audionext', 'audioprev', 'audiostop', 'audioplay', 'audiomute', 'audionext', 'audioprev', 'audiostop', 'audioplay', 'audiomute',
'volumeup', 'volumedown', 'mediaselect', 'volumeup', 'volumedown', 'mediaselect',

View File

@ -11,13 +11,21 @@
# This work is licensed under the terms of the GNU GPL, version 2. # This work is licensed under the terms of the GNU GPL, version 2.
# See the COPYING file in the top-level directory. # See the COPYING file in the top-level directory.
from __future__ import print_function
import errno import errno
import getopt import getopt
import os import os
import re import re
import string import string
import sys import sys
from ordereddict import OrderedDict try:
from collections import OrderedDict
except:
from ordereddict import OrderedDict
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
builtin_types = { builtin_types = {
'null': 'QTYPE_QNULL', 'null': 'QTYPE_QNULL',
@ -244,7 +252,7 @@ class QAPIDoc(object):
"'Returns:' is only valid for commands") "'Returns:' is only valid for commands")
def check(self): def check(self):
bogus = [name for name, section in self.args.iteritems() bogus = [name for name, section in self.args.items()
if not section.member] if not section.member]
if bogus: if bogus:
raise QAPISemError( raise QAPISemError(
@ -299,7 +307,7 @@ class QAPISchemaParser(object):
if not isinstance(pragma, dict): if not isinstance(pragma, dict):
raise QAPISemError( raise QAPISemError(
info, "Value of 'pragma' must be a dictionary") info, "Value of 'pragma' must be a dictionary")
for name, value in pragma.iteritems(): for name, value in pragma.items():
self._pragma(name, value, info) self._pragma(name, value, info)
else: else:
expr_elem = {'expr': expr, expr_elem = {'expr': expr,
@ -1467,7 +1475,7 @@ class QAPISchema(object):
self._def_exprs() self._def_exprs()
self.check() self.check()
except QAPIError as err: except QAPIError as err:
print >>sys.stderr, err print(err, file=sys.stderr)
exit(1) exit(1)
def _def_entity(self, ent): def _def_entity(self, ent):
@ -1565,7 +1573,7 @@ class QAPISchema(object):
def _make_members(self, data, info): def _make_members(self, data, info):
return [self._make_member(key, value, info) return [self._make_member(key, value, info)
for (key, value) in data.iteritems()] for (key, value) in data.items()]
def _def_struct_type(self, expr, info, doc): def _def_struct_type(self, expr, info, doc):
name = expr['struct'] name = expr['struct']
@ -1597,11 +1605,11 @@ class QAPISchema(object):
name, info, doc, 'base', self._make_members(base, info))) name, info, doc, 'base', self._make_members(base, info)))
if tag_name: if tag_name:
variants = [self._make_variant(key, value) variants = [self._make_variant(key, value)
for (key, value) in data.iteritems()] for (key, value) in data.items()]
members = [] members = []
else: else:
variants = [self._make_simple_variant(key, value, info) variants = [self._make_simple_variant(key, value, info)
for (key, value) in data.iteritems()] for (key, value) in data.items()]
typ = self._make_implicit_enum_type(name, info, typ = self._make_implicit_enum_type(name, info,
[v.name for v in variants]) [v.name for v in variants])
tag_member = QAPISchemaObjectTypeMember('type', typ, False) tag_member = QAPISchemaObjectTypeMember('type', typ, False)
@ -1616,7 +1624,7 @@ class QAPISchema(object):
name = expr['alternate'] name = expr['alternate']
data = expr['data'] data = expr['data']
variants = [self._make_variant(key, value) variants = [self._make_variant(key, value)
for (key, value) in data.iteritems()] for (key, value) in data.items()]
tag_member = QAPISchemaObjectTypeMember('type', 'QType', False) tag_member = QAPISchemaObjectTypeMember('type', 'QType', False)
self._def_entity( self._def_entity(
QAPISchemaAlternateType(name, info, doc, QAPISchemaAlternateType(name, info, doc,
@ -1670,7 +1678,7 @@ class QAPISchema(object):
assert False assert False
def check(self): def check(self):
for ent in self._entity_dict.values(): for (name, ent) in sorted(self._entity_dict.items()):
ent.check(self) ent.check(self)
def visit(self, visitor): def visit(self, visitor):
@ -1726,7 +1734,10 @@ def c_enum_const(type_name, const_name, prefix=None):
type_name = prefix type_name = prefix
return camel_to_upper(type_name) + '_' + c_name(const_name, False).upper() return camel_to_upper(type_name) + '_' + c_name(const_name, False).upper()
c_name_trans = string.maketrans('.-', '__') if hasattr(str, 'maketrans'):
c_name_trans = str.maketrans('.-', '__')
else:
c_name_trans = string.maketrans('.-', '__')
# Map @name to a valid C identifier. # Map @name to a valid C identifier.
@ -1931,7 +1942,7 @@ def parse_command_line(extra_options='', extra_long_options=[]):
['source', 'header', 'prefix=', ['source', 'header', 'prefix=',
'output-dir='] + extra_long_options) 'output-dir='] + extra_long_options)
except getopt.GetoptError as err: except getopt.GetoptError as err:
print >>sys.stderr, "%s: %s" % (sys.argv[0], str(err)) print("%s: %s" % (sys.argv[0], str(err)), file=sys.stderr)
sys.exit(1) sys.exit(1)
output_dir = '' output_dir = ''
@ -1945,9 +1956,8 @@ def parse_command_line(extra_options='', extra_long_options=[]):
if o in ('-p', '--prefix'): if o in ('-p', '--prefix'):
match = re.match(r'([A-Za-z_.-][A-Za-z0-9_.-]*)?', a) match = re.match(r'([A-Za-z_.-][A-Za-z0-9_.-]*)?', a)
if match.end() != len(a): if match.end() != len(a):
print >>sys.stderr, \ print("%s: 'funny character '%s' in argument of --prefix" \
"%s: 'funny character '%s' in argument of --prefix" \ % (sys.argv[0], a[match.end()]), file=sys.stderr)
% (sys.argv[0], a[match.end()])
sys.exit(1) sys.exit(1)
prefix = a prefix = a
elif o in ('-o', '--output-dir'): elif o in ('-o', '--output-dir'):
@ -1964,7 +1974,7 @@ def parse_command_line(extra_options='', extra_long_options=[]):
do_h = True do_h = True
if len(args) != 1: if len(args) != 1:
print >>sys.stderr, "%s: need exactly one argument" % sys.argv[0] print("%s: need exactly one argument" % sys.argv[0], file=sys.stderr)
sys.exit(1) sys.exit(1)
fname = args[0] fname = args[0]
@ -1992,8 +2002,7 @@ def open_output(output_dir, do_c, do_h, prefix, c_file, h_file,
if really: if really:
return open(name, opt) return open(name, opt)
else: else:
import StringIO return StringIO()
return StringIO.StringIO()
fdef = maybe_open(do_c, c_file, 'w') fdef = maybe_open(do_c, c_file, 'w')
fdecl = maybe_open(do_h, h_file, 'w') fdecl = maybe_open(do_h, h_file, 'w')

View File

@ -4,6 +4,7 @@
# This work is licensed under the terms of the GNU LGPL, version 2+. # This work is licensed under the terms of the GNU LGPL, version 2+.
# See the COPYING file in the top-level directory. # See the COPYING file in the top-level directory.
"""This script produces the documentation of a qapi schema in texinfo format""" """This script produces the documentation of a qapi schema in texinfo format"""
from __future__ import print_function
import re import re
import sys import sys
@ -145,7 +146,7 @@ def texi_member(member, suffix=''):
def texi_members(doc, what, base, variants, member_func): def texi_members(doc, what, base, variants, member_func):
"""Format the table of members""" """Format the table of members"""
items = '' items = ''
for section in doc.args.itervalues(): for section in doc.args.values():
# TODO Drop fallbacks when undocumented members are outlawed # TODO Drop fallbacks when undocumented members are outlawed
if section.text: if section.text:
desc = texi_format(section.text) desc = texi_format(section.text)
@ -274,15 +275,15 @@ def texi_schema(schema):
def main(argv): def main(argv):
"""Takes schema argument, prints result to stdout""" """Takes schema argument, prints result to stdout"""
if len(argv) != 2: if len(argv) != 2:
print >>sys.stderr, "%s: need exactly 1 argument: SCHEMA" % argv[0] print("%s: need exactly 1 argument: SCHEMA" % argv[0], file=sys.stderr)
sys.exit(1) sys.exit(1)
schema = qapi.QAPISchema(argv[1]) schema = qapi.QAPISchema(argv[1])
if not qapi.doc_required: if not qapi.doc_required:
print >>sys.stderr, ("%s: need pragma 'doc-required' " print("%s: need pragma 'doc-required' "
"to generate documentation" % argv[0]) "to generate documentation" % argv[0], file=sys.stderr)
sys.exit(1) sys.exit(1)
print texi_schema(schema) print(texi_schema(schema))
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -15,9 +15,10 @@
import errno import errno
import logging import logging
import os import os
import sys
import subprocess import subprocess
import qmp.qmp import qmp.qmp
import shutil
import tempfile
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -73,10 +74,11 @@ class QEMUMachine(object):
wrapper = [] wrapper = []
if name is None: if name is None:
name = "qemu-%d" % os.getpid() name = "qemu-%d" % os.getpid()
if monitor_address is None: self._name = name
monitor_address = os.path.join(test_dir, name + "-monitor.sock")
self._monitor_address = monitor_address self._monitor_address = monitor_address
self._qemu_log_path = os.path.join(test_dir, name + ".log") self._vm_monitor = None
self._qemu_log_path = None
self._qemu_log_file = None
self._popen = None self._popen = None
self._binary = binary self._binary = binary
self._args = list(args) # Force copy args in case we modify them self._args = list(args) # Force copy args in case we modify them
@ -86,6 +88,9 @@ class QEMUMachine(object):
self._socket_scm_helper = socket_scm_helper self._socket_scm_helper = socket_scm_helper
self._qmp = None self._qmp = None
self._qemu_full_args = None self._qemu_full_args = None
self._test_dir = test_dir
self._temp_dir = None
self._launched = False
# just in case logging wasn't configured by the main script: # just in case logging wasn't configured by the main script:
logging.basicConfig() logging.basicConfig()
@ -146,12 +151,12 @@ class QEMUMachine(object):
raise raise
def is_running(self): def is_running(self):
return self._popen is not None and self._popen.returncode is None return self._popen is not None and self._popen.poll() is None
def exitcode(self): def exitcode(self):
if self._popen is None: if self._popen is None:
return None return None
return self._popen.returncode return self._popen.poll()
def get_pid(self): def get_pid(self):
if not self.is_running(): if not self.is_running():
@ -159,8 +164,9 @@ class QEMUMachine(object):
return self._popen.pid return self._popen.pid
def _load_io_log(self): def _load_io_log(self):
with open(self._qemu_log_path, "r") as iolog: if self._qemu_log_path is not None:
self._iolog = iolog.read() with open(self._qemu_log_path, "r") as iolog:
self._iolog = iolog.read()
def _base_args(self): def _base_args(self):
if isinstance(self._monitor_address, tuple): if isinstance(self._monitor_address, tuple):
@ -168,45 +174,54 @@ class QEMUMachine(object):
self._monitor_address[0], self._monitor_address[0],
self._monitor_address[1]) self._monitor_address[1])
else: else:
moncdev = 'socket,id=mon,path=%s' % self._monitor_address moncdev = 'socket,id=mon,path=%s' % self._vm_monitor
return ['-chardev', moncdev, return ['-chardev', moncdev,
'-mon', 'chardev=mon,mode=control', '-mon', 'chardev=mon,mode=control',
'-display', 'none', '-vga', 'none'] '-display', 'none', '-vga', 'none']
def _pre_launch(self): def _pre_launch(self):
self._qmp = qmp.qmp.QEMUMonitorProtocol(self._monitor_address, self._temp_dir = tempfile.mkdtemp(dir=self._test_dir)
if self._monitor_address is not None:
self._vm_monitor = self._monitor_address
else:
self._vm_monitor = os.path.join(self._temp_dir,
self._name + "-monitor.sock")
self._qemu_log_path = os.path.join(self._temp_dir, self._name + ".log")
self._qemu_log_file = open(self._qemu_log_path, 'wb')
self._qmp = qmp.qmp.QEMUMonitorProtocol(self._vm_monitor,
server=True) server=True)
def _post_launch(self): def _post_launch(self):
self._qmp.accept() self._qmp.accept()
def _post_shutdown(self): def _post_shutdown(self):
if not isinstance(self._monitor_address, tuple): if self._qemu_log_file is not None:
self._remove_if_exists(self._monitor_address) self._qemu_log_file.close()
self._remove_if_exists(self._qemu_log_path) self._qemu_log_file = None
self._qemu_log_path = None
if self._temp_dir is not None:
shutil.rmtree(self._temp_dir)
self._temp_dir = None
def launch(self): def launch(self):
'''Launch the VM and establish a QMP connection''' """
Launch the VM and make sure we cleanup and expose the
command line/output in case of exception
"""
if self._launched:
raise QEMUMachineError('VM already launched')
self._iolog = None self._iolog = None
self._qemu_full_args = None self._qemu_full_args = None
devnull = open(os.path.devnull, 'rb')
qemulog = open(self._qemu_log_path, 'wb')
try: try:
self._pre_launch() self._launch()
self._qemu_full_args = (self._wrapper + [self._binary] + self._launched = True
self._base_args() + self._args)
self._popen = subprocess.Popen(self._qemu_full_args,
stdin=devnull,
stdout=qemulog,
stderr=subprocess.STDOUT,
shell=False)
self._post_launch()
except: except:
if self.is_running(): self.shutdown()
self._popen.kill()
self._popen.wait()
self._load_io_log()
self._post_shutdown()
LOG.debug('Error launching VM') LOG.debug('Error launching VM')
if self._qemu_full_args: if self._qemu_full_args:
@ -215,6 +230,19 @@ class QEMUMachine(object):
LOG.debug('Output: %r', self._iolog) LOG.debug('Output: %r', self._iolog)
raise raise
def _launch(self):
'''Launch the VM and establish a QMP connection'''
devnull = open(os.path.devnull, 'rb')
self._pre_launch()
self._qemu_full_args = (self._wrapper + [self._binary] +
self._base_args() + self._args)
self._popen = subprocess.Popen(self._qemu_full_args,
stdin=devnull,
stdout=self._qemu_log_file,
stderr=subprocess.STDOUT,
shell=False)
self._post_launch()
def wait(self): def wait(self):
'''Wait for the VM to power off''' '''Wait for the VM to power off'''
self._popen.wait() self._popen.wait()
@ -232,8 +260,8 @@ class QEMUMachine(object):
self._popen.kill() self._popen.kill()
self._popen.wait() self._popen.wait()
self._load_io_log() self._load_io_log()
self._post_shutdown() self._post_shutdown()
exitcode = self.exitcode() exitcode = self.exitcode()
if exitcode is not None and exitcode < 0: if exitcode is not None and exitcode < 0:
@ -244,6 +272,8 @@ class QEMUMachine(object):
command = '' command = ''
LOG.warn(msg, exitcode, command) LOG.warn(msg, exitcode, command)
self._launched = False
def qmp(self, cmd, conv_keys=True, **args): def qmp(self, cmd, conv_keys=True, **args):
'''Invoke a QMP command and return the response dict''' '''Invoke a QMP command and return the response dict'''
qmp_args = dict() qmp_args = dict()

View File

@ -18,7 +18,7 @@ fin = open(sys.argv[1], 'rb')
fout = open(sys.argv[2], 'wb') fout = open(sys.argv[2], 'wb')
magic = fin.read(2) magic = fin.read(2)
if magic != '\x55\xaa': if magic != b'\x55\xaa':
sys.exit("%s: option ROM does not begin with magic 55 aa" % sys.argv[1]) sys.exit("%s: option ROM does not begin with magic 55 aa" % sys.argv[1])
size_byte = ord(fin.read(1)) size_byte = ord(fin.read(1))
@ -33,7 +33,7 @@ elif len(data) < size:
# Add padding if necessary, rounding the whole input to a multiple of # Add padding if necessary, rounding the whole input to a multiple of
# 512 bytes according to the third byte of the input. # 512 bytes according to the third byte of the input.
# size-1 because a final byte is added below to store the checksum. # size-1 because a final byte is added below to store the checksum.
data = data.ljust(size-1, '\0') data = data.ljust(size-1, b'\0')
else: else:
if ord(data[-1:]) != 0: if ord(data[-1:]) != 0:
sys.stderr.write('WARNING: ROM includes nonzero checksum\n') sys.stderr.write('WARNING: ROM includes nonzero checksum\n')

View File

@ -919,10 +919,10 @@ $(patsubst %, check-%, $(check-qapi-schema-y)): check-%.json: $(SRC_PATH)/%.json
$^ >$*.test.out 2>$*.test.err; \ $^ >$*.test.out 2>$*.test.err; \
echo $$? >$*.test.exit, \ echo $$? >$*.test.exit, \
"TEST","$*.out") "TEST","$*.out")
@diff -q $(SRC_PATH)/$*.out $*.test.out @diff $(SRC_PATH)/$*.out $*.test.out
@# Sanitize error messages (make them independent of build directory) @# Sanitize error messages (make them independent of build directory)
@perl -p -e 's|\Q$(SRC_PATH)\E/||g' $*.test.err | diff -q $(SRC_PATH)/$*.err - @perl -p -e 's|\Q$(SRC_PATH)\E/||g' $*.test.err | diff $(SRC_PATH)/$*.err -
@diff -q $(SRC_PATH)/$*.exit $*.test.exit @diff $(SRC_PATH)/$*.exit $*.test.exit
.PHONY: check-tests/qapi-schema/doc-good.texi .PHONY: check-tests/qapi-schema/doc-good.texi
check-tests/qapi-schema/doc-good.texi: tests/qapi-schema/doc-good.test.texi check-tests/qapi-schema/doc-good.texi: tests/qapi-schema/doc-good.test.texi

View File

@ -1,6 +1,6 @@
FROM fedora:latest FROM fedora:latest
ENV PACKAGES \ ENV PACKAGES \
ccache gettext git tar PyYAML sparse flex bison python2 bzip2 hostname \ ccache gettext git tar PyYAML sparse flex bison python3 bzip2 hostname \
glib2-devel pixman-devel zlib-devel SDL-devel libfdt-devel \ glib2-devel pixman-devel zlib-devel SDL-devel libfdt-devel \
gcc gcc-c++ clang make perl which bc findutils libaio-devel \ gcc gcc-c++ clang make perl which bc findutils libaio-devel \
nettle-devel libasan libubsan \ nettle-devel libasan libubsan \
@ -12,6 +12,7 @@ ENV PACKAGES \
mingw64-gtk2 mingw64-gtk3 mingw64-gnutls mingw64-nettle mingw64-libtasn1 \ mingw64-gtk2 mingw64-gtk3 mingw64-gnutls mingw64-nettle mingw64-libtasn1 \
mingw64-libjpeg-turbo mingw64-libpng mingw64-curl mingw64-libssh2 \ mingw64-libjpeg-turbo mingw64-libpng mingw64-curl mingw64-libssh2 \
mingw64-bzip2 mingw64-bzip2
ENV QEMU_CONFIGURE_OPTS --python=/usr/bin/python3
RUN dnf install -y $PACKAGES RUN dnf install -y $PACKAGES
RUN rpm -q $PACKAGES | sort > /packages.txt RUN rpm -q $PACKAGES | sort > /packages.txt

View File

@ -10,6 +10,7 @@
# See the COPYING file in the top-level directory. # See the COPYING file in the top-level directory.
# #
from __future__ import print_function
from qapi import * from qapi import *
from pprint import pprint from pprint import pprint
import os import os
@ -18,51 +19,51 @@ import sys
class QAPISchemaTestVisitor(QAPISchemaVisitor): class QAPISchemaTestVisitor(QAPISchemaVisitor):
def visit_enum_type(self, name, info, values, prefix): def visit_enum_type(self, name, info, values, prefix):
print 'enum %s %s' % (name, values) print('enum %s %s' % (name, values))
if prefix: if prefix:
print ' prefix %s' % prefix print(' prefix %s' % prefix)
def visit_object_type(self, name, info, base, members, variants): def visit_object_type(self, name, info, base, members, variants):
print 'object %s' % name print('object %s' % name)
if base: if base:
print ' base %s' % base.name print(' base %s' % base.name)
for m in members: for m in members:
print ' member %s: %s optional=%s' % \ print(' member %s: %s optional=%s' % \
(m.name, m.type.name, m.optional) (m.name, m.type.name, m.optional))
self._print_variants(variants) self._print_variants(variants)
def visit_alternate_type(self, name, info, variants): def visit_alternate_type(self, name, info, variants):
print 'alternate %s' % name print('alternate %s' % name)
self._print_variants(variants) self._print_variants(variants)
def visit_command(self, name, info, arg_type, ret_type, def visit_command(self, name, info, arg_type, ret_type,
gen, success_response, boxed): gen, success_response, boxed):
print 'command %s %s -> %s' % \ print('command %s %s -> %s' % \
(name, arg_type and arg_type.name, ret_type and ret_type.name) (name, arg_type and arg_type.name, ret_type and ret_type.name))
print ' gen=%s success_response=%s boxed=%s' % \ print(' gen=%s success_response=%s boxed=%s' % \
(gen, success_response, boxed) (gen, success_response, boxed))
def visit_event(self, name, info, arg_type, boxed): def visit_event(self, name, info, arg_type, boxed):
print 'event %s %s' % (name, arg_type and arg_type.name) print('event %s %s' % (name, arg_type and arg_type.name))
print ' boxed=%s' % boxed print(' boxed=%s' % boxed)
@staticmethod @staticmethod
def _print_variants(variants): def _print_variants(variants):
if variants: if variants:
print ' tag %s' % variants.tag_member.name print(' tag %s' % variants.tag_member.name)
for v in variants.variants: for v in variants.variants:
print ' case %s: %s' % (v.name, v.type.name) print(' case %s: %s' % (v.name, v.type.name))
schema = QAPISchema(sys.argv[1]) schema = QAPISchema(sys.argv[1])
schema.visit(QAPISchemaTestVisitor()) schema.visit(QAPISchemaTestVisitor())
for doc in schema.docs: for doc in schema.docs:
if doc.symbol: if doc.symbol:
print 'doc symbol=%s' % doc.symbol print('doc symbol=%s' % doc.symbol)
else: else:
print 'doc freeform' print('doc freeform')
print ' body=\n%s' % doc.body.text print(' body=\n%s' % doc.body.text)
for arg, section in doc.args.iteritems(): for arg, section in doc.args.items():
print ' arg=%s\n%s' % (arg, section.text) print(' arg=%s\n%s' % (arg, section.text))
for section in doc.sections: for section in doc.sections:
print ' section=%s\n%s' % (section.name, section.text) print(' section=%s\n%s' % (section.name, section.text))

@ -1 +1 @@
Subproject commit 10739aa26051a5d49d88132604539d3ed085e72e Subproject commit 6b3d716e2b6472eb7189d3220552280ef3d832ce