<p>Jenkins2 <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/8641">View Change</a></p><div style="white-space:pre-wrap">Approvals:
George Joseph: Looks good to me, but someone else must approve
Kevin Harwell: Looks good to me, approved
Jenkins2: Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Build System: Enable python3 compatibility.<br><br>* Consistently use spaces in rest-api-templates/asterisk_processor.py.<br>* Exclude third-party from docs/full-en_US.xml.<br>* Add docs/full-en_US.xml to .gitignore.<br>* Use list() to convert python3 view.<br>* Use python3 print function.<br>* Replace cmp() with equivalent equation.<br>* Replace reference to out of scope subtype variable with name<br> parameter.<br>* Use unescaping triple bracket notation in mustache templates where<br> needed. This causes behavior of Python2 to be maintained when using<br> Python3.<br>* Fix references to has_websocket / is_websocket in<br> res_ari_resource.c.mustache.<br>* Update calculation of has_websocket to use any().<br>* Use unicode mode for writing output file in transform.py.<br>* Replace 'from swagger_model import *' with explicit import of required<br> symbols.<br><br>I have not tested spandspflow2pcap.py or voicemailpwcheck.py, only the<br>print syntax has been fixed.<br><br>Change-Id: If5c5b556a2800d41a3e2cfef080ac2e151178c33<br>---<br>M Makefile<br>M contrib/scripts/refcounter.py<br>M contrib/scripts/spandspflow2pcap.py<br>M contrib/scripts/voicemailpwcheck.py<br>M doc/.gitignore<br>M rest-api-templates/api.wiki.mustache<br>M rest-api-templates/ari_resource.h.mustache<br>M rest-api-templates/asterisk_processor.py<br>M rest-api-templates/make_ari_stubs.py<br>M rest-api-templates/res_ari_resource.c.mustache<br>M rest-api-templates/swagger_model.py<br>M rest-api-templates/transform.py<br>12 files changed, 49 insertions(+), 44 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/Makefile b/Makefile<br>index 2c10dc4..1cd9665 100644<br>--- a/Makefile<br>+++ b/Makefile<br>@@ -511,7 +511,7 @@<br> @echo "<!DOCTYPE docs SYSTEM \"appdocsxml.dtd\">" >> $@<br> @echo "<?xml-stylesheet type=\"text/xsl\" href=\"appdocsxml.xslt\"?>" >> $@<br> @echo "<docs xmlns:xi=\"http://www.w3.org/2001/XInclude\">" >> $@<br>- @for x in $(MOD_SUBDIRS); do \<br>+ @for x in $(filter-out third-party,$(MOD_SUBDIRS)); do \<br> printf "$$x " ; \<br> for i in `find $$x -name '*.c'`; do \<br> $(PYTHON) build_tools/get_documentation.py < $$i >> $@ ; \<br>diff --git a/contrib/scripts/refcounter.py b/contrib/scripts/refcounter.py<br>index 1f4b375..de3cda0 100755<br>--- a/contrib/scripts/refcounter.py<br>+++ b/contrib/scripts/refcounter.py<br>@@ -18,6 +18,7 @@<br> Matt Jordan <mjordan@digium.com><br> """<br> <br>+from __future__ import print_function<br> import sys<br> import os<br> <br>@@ -35,8 +36,8 @@<br> """<br> tokens = line.strip().split(',', 7)<br> if len(tokens) < 8:<br>- print "ERROR: ref debug line '%s' contains fewer tokens than " \<br>- "expected: %d" % (line.strip(), len(tokens))<br>+ print("ERROR: ref debug line '%s' contains fewer tokens than "<br>+ "expected: %d" % (line.strip(), len(tokens)))<br> return None<br> <br> processed_line = {'addr': tokens[0],<br>@@ -142,7 +143,7 @@<br> del current_objects[obj]<br> <br> if options.leaks:<br>- for key, lines in current_objects.iteritems():<br>+ for (key, lines) in current_objects.items():<br> leaked_objects.append((key, lines))<br> return (finished_objects, invalid_objects, leaked_objects, skewed_objects)<br> <br>@@ -156,13 +157,13 @@<br> this object<br> """<br> <br>- print "======== %s Objects ========" % prefix<br>- print "\n"<br>+ print("======== %s Objects ========" % prefix)<br>+ print("\n")<br> for obj in objects:<br>- print "==== %s Object %s history ====" % (prefix, obj[0])<br>+ print("==== %s Object %s history ====" % (prefix, obj[0]))<br> for line in obj[1]['log']:<br>- print line<br>- print "\n"<br>+ print(line)<br>+ print("\n")<br> <br> <br> def main(argv=None):<br>@@ -198,11 +199,11 @@<br> <br> if not options.invalid and not options.leaks and not options.normal \<br> and not options.skewed:<br>- print >>sys.stderr, "All options disabled"<br>+ print("All options disabled", file=sys.stderr)<br> return -1<br> <br> if not os.path.isfile(options.filepath):<br>- print >>sys.stderr, "File not found: %s" % options.filepath<br>+ print("File not found: %s" % options.filepath, file=sys.stderr)<br> return -1<br> <br> try:<br>@@ -227,7 +228,7 @@<br> print_objects(finished_objects, "Finalized")<br> <br> except (KeyboardInterrupt, SystemExit, IOError):<br>- print >>sys.stderr, "File processing cancelled"<br>+ print("File processing cancelled", file=sys.stderr)<br> return -1<br> <br> return ret_code<br>diff --git a/contrib/scripts/spandspflow2pcap.py b/contrib/scripts/spandspflow2pcap.py<br>index a6546b6..7c403f1 100755<br>--- a/contrib/scripts/spandspflow2pcap.py<br>+++ b/contrib/scripts/spandspflow2pcap.py<br>@@ -119,7 +119,7 @@<br> else:<br> self.date += timedelta(microseconds=9000)<br> <br>- print seqno, '\t', self.date + self.dateoff<br>+ print(seqno, '\t', self.date + self.dateoff)<br> <br> # Make packet.<br> packet, prev_data = self.data2packet(self.date + self.dateoff,<br>diff --git a/contrib/scripts/voicemailpwcheck.py b/contrib/scripts/voicemailpwcheck.py<br>index d7a66d4..452255c 100755<br>--- a/contrib/scripts/voicemailpwcheck.py<br>+++ b/contrib/scripts/voicemailpwcheck.py<br>@@ -46,20 +46,20 @@<br> <br> # Enforce a password length of at least 6 characters<br> if len(new_pw) < REQUIRED_LENGTH:<br>- print "INVALID: Password is too short (%d) - must be at least %d" % \<br>- (len(new_pw), REQUIRED_LENGTH)<br>+ print("INVALID: Password is too short (%d) - must be at least %d" % \<br>+ (len(new_pw), REQUIRED_LENGTH))<br> sys.exit(0)<br> <br> for regex, error in REGEX_BLACKLIST:<br> if re.search(regex, new_pw):<br>- print "INVALID: %s" % error<br>+ print("INVALID: %s" % error)<br> sys.exit(0)<br> <br> for pw in PW_BLACKLIST:<br> if new_pw.find(pw) != -1:<br>- print "INVALID: %s is forbidden in a password" % pw<br>+ print("INVALID: %s is forbidden in a password" % pw)<br> sys.exit(0)<br> <br>-print "VALID"<br>+print("VALID")<br> <br> sys.exit(0)<br>diff --git a/doc/.gitignore b/doc/.gitignore<br>index 3461c58..49bfe42 100644<br>--- a/doc/.gitignore<br>+++ b/doc/.gitignore<br>@@ -1,4 +1,5 @@<br> core-en_US.xml<br>+full-en_US.xml<br> rest-api<br> api<br> asterisk-ng-doxygen<br>diff --git a/rest-api-templates/api.wiki.mustache b/rest-api-templates/api.wiki.mustache<br>index ad12bb6..a51c3e6 100644<br>--- a/rest-api-templates/api.wiki.mustache<br>+++ b/rest-api-templates/api.wiki.mustache<br>@@ -5,7 +5,7 @@<br> <br> {{#apis}}<br> {{#operations}}<br>-| {{http_method}} | [{{wiki_path}}|#{{nickname}}] | {{#response_class}}{{#is_primitive}}{{name}}{{/is_primitive}}{{^is_primitive}}[{{wiki_name}}|{{wiki_prefix}} REST Data Models#{{singular_name}}]{{/is_primitive}}{{/response_class}} | {{summary}} |<br>+| {{http_method}} | [{{wiki_path}}|#{{nickname}}] | {{#response_class}}{{#is_primitive}}{{name}}{{/is_primitive}}{{^is_primitive}}[{{wiki_name}}|{{wiki_prefix}} REST Data Models#{{singular_name}}]{{/is_primitive}}{{/response_class}} | {{{summary}}} |<br> {{/operations}}<br> {{/apis}}<br> {{#apis}}<br>diff --git a/rest-api-templates/ari_resource.h.mustache b/rest-api-templates/ari_resource.h.mustache<br>index df075af..c1d880d 100644<br>--- a/rest-api-templates/ari_resource.h.mustache<br>+++ b/rest-api-templates/ari_resource.h.mustache<br>@@ -76,7 +76,7 @@<br> <br> {{/parse_body}}<br> /*!<br>- * \brief {{summary}}<br>+ * \brief {{{summary}}}<br> {{#notes}}<br> *<br> * {{{notes}}}<br>@@ -99,7 +99,7 @@<br> {{#is_websocket}}<br> <br> /*!<br>- * \brief {{summary}}<br>+ * \brief {{{summary}}}<br> {{#notes}}<br> *<br> * {{{notes}}}<br>@@ -111,7 +111,7 @@<br> int ast_ari_websocket_{{c_name}}_{{c_nickname}}_init(void);<br> <br> /*!<br>- * \brief {{summary}}<br>+ * \brief {{{summary}}}<br> {{#notes}}<br> *<br> * {{{notes}}}<br>diff --git a/rest-api-templates/asterisk_processor.py b/rest-api-templates/asterisk_processor.py<br>index 9812946..5f8dbb5 100644<br>--- a/rest-api-templates/asterisk_processor.py<br>+++ b/rest-api-templates/asterisk_processor.py<br>@@ -23,7 +23,7 @@<br> import os<br> import re<br> <br>-from swagger_model import *<br>+from swagger_model import Stringify, SwaggerError, SwaggerPostProcessor<br> <br> try:<br> from collections import OrderedDict<br>@@ -183,7 +183,7 @@<br> raise SwaggerError(<br> "Should not mix resources in one API declaration", context)<br> # root_path isn't needed any more<br>- resource_api.root_path = resource_api.root_path.children()[0]<br>+ resource_api.root_path = list(resource_api.root_path.children())[0]<br> if resource_api.name != resource_api.root_path.name:<br> raise SwaggerError(<br> "API declaration name should match", context)<br>@@ -206,10 +206,10 @@<br> <br> def process_parameter(self, parameter, context):<br> if parameter.param_type == 'body':<br>- parameter.is_body_parameter = True;<br>+ parameter.is_body_parameter = True;<br> parameter.c_data_type = 'struct ast_json *'<br> else:<br>- parameter.is_body_parameter = False;<br>+ parameter.is_body_parameter = False;<br> if not parameter.data_type in self.type_mapping:<br> raise SwaggerError(<br> "Invalid parameter type %s" % parameter.data_type, context)<br>diff --git a/rest-api-templates/make_ari_stubs.py b/rest-api-templates/make_ari_stubs.py<br>index 0aba06d..a25773d 100755<br>--- a/rest-api-templates/make_ari_stubs.py<br>+++ b/rest-api-templates/make_ari_stubs.py<br>@@ -16,19 +16,20 @@<br> # at the top of the source tree.<br> #<br> <br>+from __future__ import print_function<br> import sys<br> <br> try:<br> import pystache<br> except ImportError:<br>- print >> sys.stderr, "Pystache required. Please sudo pip install pystache."<br>+ print("Pystache required. Please sudo pip install pystache.", file=sys.stderr)<br> sys.exit(1)<br> <br> import os.path<br> <br> from asterisk_processor import AsteriskProcessor<br> from optparse import OptionParser<br>-from swagger_model import *<br>+from swagger_model import ResourceListing<br> from transform import Transform<br> <br> TOPDIR = os.path.dirname(os.path.abspath(__file__))<br>diff --git a/rest-api-templates/res_ari_resource.c.mustache b/rest-api-templates/res_ari_resource.c.mustache<br>index 67a04d8..85948fb 100644<br>--- a/rest-api-templates/res_ari_resource.c.mustache<br>+++ b/rest-api-templates/res_ari_resource.c.mustache<br>@@ -55,7 +55,7 @@<br> #if defined(AST_DEVMODE)<br> #include "ari/ari_model_validators.h"<br> #endif<br>-{{^has_websocket}}<br>+{{#has_websocket}}<br> {{! Only include http_websocket if necessary. Otherwise we'll do a lot of<br> * unnecessary optional_api intialization, which makes optional_api harder<br> * to debug<br>@@ -278,7 +278,7 @@<br> <br> {{#apis}}<br> {{#operations}}<br>-{{#has_websocket}}<br>+{{#is_websocket}}<br> struct ast_websocket_protocol *protocol;<br> <br> if (ast_ari_websocket_{{c_name}}_{{c_nickname}}_init() == -1) {<br>@@ -300,8 +300,6 @@<br> }<br> protocol->session_attempted = ast_ari_{{c_name}}_{{c_nickname}}_ws_attempted_cb;<br> protocol->session_established = ast_ari_{{c_name}}_{{c_nickname}}_ws_established_cb;<br>-{{/has_websocket}}<br>-{{#is_websocket}}<br> res |= ast_websocket_server_add_protocol2({{full_name}}.ws_server, protocol);<br> {{/is_websocket}}<br> {{/operations}}<br>diff --git a/rest-api-templates/swagger_model.py b/rest-api-templates/swagger_model.py<br>index 3f729d8..50c5fb0 100644<br>--- a/rest-api-templates/swagger_model.py<br>+++ b/rest-api-templates/swagger_model.py<br>@@ -26,6 +26,7 @@<br> See https://github.com/wordnik/swagger-core/wiki/API-Declaration for the spec.<br> """<br> <br>+from __future__ import print_function<br> import json<br> import os.path<br> import pprint<br>@@ -75,7 +76,7 @@<br> '''<br> lhs = [int(v) for v in lhs.split('.')]<br> rhs = [int(v) for v in rhs.split('.')]<br>- return cmp(lhs, rhs)<br>+ return (lhs > rhs) - (lhs < rhs)<br> <br> <br> class ParsingContext(object):<br>@@ -444,8 +445,7 @@<br> op_json = api_json.get('operations')<br> self.operations = [<br> Operation().load(j, processor, context) for j in op_json]<br>- self.has_websocket = \<br>- filter(lambda op: op.is_websocket, self.operations) != []<br>+ self.has_websocket = any(op.is_websocket for op in self.operations)<br> processor.process_api(self, context)<br> return self<br> <br>@@ -611,7 +611,7 @@<br> except SwaggerError:<br> raise<br> except Exception as e:<br>- print >> sys.stderr, "Error: ", traceback.format_exc()<br>+ print("Error: ", traceback.format_exc(), file=sys.stderr)<br> raise SwaggerError(<br> "Error loading %s" % api_declaration_file, context, e)<br> <br>@@ -624,8 +624,8 @@<br> .replace(".json", ".{format}")<br> <br> if self.resource_path != expected_resource_path:<br>- print >> sys.stderr, \<br>- "%s != %s" % (self.resource_path, expected_resource_path)<br>+ print("%s != %s" % (self.resource_path, expected_resource_path),<br>+ file=sys.stderr)<br> raise SwaggerError("resourcePath has incorrect value", context)<br> <br> return self<br>@@ -656,8 +656,7 @@<br> if api.path in paths:<br> raise SwaggerError("API with duplicated path: %s" % api.path, context)<br> paths.add(api.path)<br>- self.has_websocket = filter(lambda api: api.has_websocket,<br>- self.apis) == []<br>+ self.has_websocket = any(api.has_websocket for api in self.apis)<br> models = api_decl_json.get('models').items() or []<br> self.models = [Model().load(id, json, processor, context)<br> for (id, json) in models]<br>@@ -666,7 +665,7 @@<br> model_dict = dict((m.id, m) for m in self.models)<br> for m in self.models:<br> def link_subtype(name):<br>- res = model_dict.get(subtype)<br>+ res = model_dict.get(name)<br> if not res:<br> raise SwaggerError("%s has non-existing subtype %s",<br> m.id, name)<br>@@ -725,7 +724,7 @@<br> except SwaggerError:<br> raise<br> except Exception as e:<br>- print >> sys.stderr, "Error: ", traceback.format_exc()<br>+ print("Error: ", traceback.format_exc(), file=sys.stderr)<br> raise SwaggerError(<br> "Error loading %s" % resource_file, context, e)<br> <br>diff --git a/rest-api-templates/transform.py b/rest-api-templates/transform.py<br>index c3a0300..88f7d2e 100644<br>--- a/rest-api-templates/transform.py<br>+++ b/rest-api-templates/transform.py<br>@@ -21,6 +21,11 @@<br> import pystache<br> import shutil<br> import tempfile<br>+import sys<br>+<br>+if sys.version_info[0] == 3:<br>+ def unicode(v):<br>+ return str(v)<br> <br> <br> class Transform(object):<br>@@ -52,10 +57,10 @@<br> dest_exists = os.path.exists(dest_file)<br> if dest_exists and not self.overwrite:<br> return<br>- with tempfile.NamedTemporaryFile() as out:<br>+ with tempfile.NamedTemporaryFile(mode='w+') as out:<br> out.write(renderer.render(self.template, model))<br> out.flush()<br> <br> if not dest_exists or not filecmp.cmp(out.name, dest_file):<br>- print "Writing %s" % dest_file<br>+ print("Writing %s" % dest_file)<br> shutil.copyfile(out.name, dest_file)<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/8641">change 8641</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/8641"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: If5c5b556a2800d41a3e2cfef080ac2e151178c33 </div>
<div style="display:none"> Gerrit-Change-Number: 8641 </div>
<div style="display:none"> Gerrit-PatchSet: 4 </div>
<div style="display:none"> Gerrit-Owner: Corey Farrell <git@cfware.com> </div>
<div style="display:none"> Gerrit-Reviewer: Alexander Traud <pabstraud@compuserve.com> </div>
<div style="display:none"> Gerrit-Reviewer: Corey Farrell <git@cfware.com> </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins2 </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Tzafrir Cohen <tzafrir.cohen@xorcom.com> </div>