<p>Joshua Colp <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/8805">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Corey Farrell: Looks good to me, but someone else must approve
  Kevin Harwell: Looks good to me, approved
  Joshua Colp: Approved for Submit

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">sip_to_pjsip: Enable python3 compatibility.<br><br>The script remains compatible with Python 2.7 but now also works with<br>Python 3.3 and newer; to ease the migration from chan_sip to chan_pjsip.<br><br>ASTERISK-27811<br><br>Change-Id: I59cc6b52a1a89777eebcf25b3023bdf93babf835<br>---<br>M contrib/scripts/sip_to_pjsip/astconfigparser.py<br>M contrib/scripts/sip_to_pjsip/astdicts.py<br>M contrib/scripts/sip_to_pjsip/sip_to_pjsip.py<br>M contrib/scripts/sip_to_pjsip/sip_to_pjsql.py<br>M contrib/scripts/sip_to_pjsip/sqlconfigparser.py<br>5 files changed, 69 insertions(+), 63 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/contrib/scripts/sip_to_pjsip/astconfigparser.py b/contrib/scripts/sip_to_pjsip/astconfigparser.py<br>index dc79e80..949acdb 100644<br>--- a/contrib/scripts/sip_to_pjsip/astconfigparser.py<br>+++ b/contrib/scripts/sip_to_pjsip/astconfigparser.py<br>@@ -49,7 +49,7 @@<br>         """<br>         Use self.id as means of determining equality<br>         """<br>-        return cmp(self.id, other.id)<br>+        return (self.id > other.id) - (self.id < other.id)<br> <br>     def __eq__(self, other):<br>         """<br>@@ -445,7 +445,7 @@<br>             with open(filename, 'rt') as config_file:<br>                 self._read(config_file, sect)<br>         except IOError:<br>-            print "Could not open file ", filename, " for reading"<br>+            print("Could not open file " + filename + " for reading")<br> <br>     def _read(self, config_file, sect):<br>         """Parse configuration information from the config_file"""<br>@@ -490,4 +490,4 @@<br>                 with open(config_file, 'wt') as fp:<br>                     self.write(fp)<br>             except IOError:<br>-                print "Could not open file ", config_file, " for writing"<br>+                print("Could not open file " + config_file + " for writing")<br>diff --git a/contrib/scripts/sip_to_pjsip/astdicts.py b/contrib/scripts/sip_to_pjsip/astdicts.py<br>index ae63075..39cab98 100644<br>--- a/contrib/scripts/sip_to_pjsip/astdicts.py<br>+++ b/contrib/scripts/sip_to_pjsip/astdicts.py<br>@@ -3,10 +3,12 @@<br> # copied from http://code.activestate.com/recipes/576693/<br> <br> try:<br>-    from thread import get_ident as _get_ident<br>+    from threading import get_ident as _get_ident<br> except ImportError:<br>-    from dummy_thread import get_ident as _get_ident<br>-<br>+    try:<br>+        from thread import get_ident as _get_ident<br>+    except ImportError:<br>+        from dummy_thread import get_ident as _get_ident<br> try:<br>     from _abcoll import KeysView, ValuesView, ItemsView<br> except ImportError:<br>@@ -267,11 +269,11 @@<br> <br>     def __setitem__(self, key, val, i=None):<br>         if key not in self:<br>-#            print "__setitem__ key = ", key, " val = ", val<br>+#            print("__setitem__ key = " + key + " val = " + val)<br>             OrderedDict.__setitem__(<br>                 self, key, val if isinstance(val, list) else [val])<br>             return<br>-#        print "inserting key = ", key, " val = ", val<br>+#        print("inserting key = " + key + " val = " + val)<br>         vals = self[key]<br>         if i is None:<br>             i = len(vals)<br>diff --git a/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py b/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py<br>index 9f7d991..d05f97d 100755<br>--- a/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py<br>+++ b/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py<br>@@ -1,9 +1,11 @@<br>-#!/usr/bin/python<br>+#!/usr/bin/env python<br> <br> import optparse<br> import socket<br>-import urlparse  # Python 2.7 required for Literal IPv6 Addresses<br>-<br>+try:<br>+    from urllib.parse import urlparse<br>+except ImportError:<br>+    from urlparse import urlparse # Python 2.7 required for Literal IPv6 Addresses<br> import astdicts<br> import astconfigparser<br> <br>@@ -90,32 +92,32 @@<br>         return _merge_codec_value<br> <br>     if key == 'allow':<br>-     try:<br>-             disallow = sip.get(section, 'disallow')[0]<br>-           if disallow == 'all':<br>-                    #don't inherit<br>-                    for i in sip.get(section, 'allow'):<br>-                     set_value(key, i, section, pjsip, nmapped, type)<br>-             else:<br>-                    merge_value(key, val, section, pjsip, nmapped, type, section_to, key_to)<br>-     except LookupError:<br>-              print "lookup error"<br>-               merge_value(key, val, section, pjsip, nmapped, type, section_to, key_to)<br>-             return<br>+        try:<br>+            disallow = sip.get(section, 'disallow')[0]<br>+            if disallow == 'all':<br>+                #don't inherit<br>+                for i in sip.get(section, 'allow'):<br>+                    set_value(key, i, section, pjsip, nmapped, type)<br>+            else:<br>+                merge_value(key, val, section, pjsip, nmapped, type, section_to, key_to)<br>+        except LookupError:<br>+            print("lookup error")<br>+            merge_value(key, val, section, pjsip, nmapped, type, section_to, key_to)<br>+            return<br>     elif key == 'disallow':<br>-        try:<br>-             allow = sip.get(section, 'allow')[0]<br>-         if allow == 'all':<br>-               #don't inherit<br>-                    for i in sip.get(section, 'disallow'):<br>-                  set_value(key, i, section, pjsip, nmapped, type)<br>-             else:<br>-                    merge_value(key, val, section, pjsip, nmapped, type, section_to, key_to)<br>-     except LookupError:<br>-              merge_value(key, val, section, pjsip, nmapped, type, section_to, key_to)<br>-             return<br>+        try:<br>+            allow = sip.get(section, 'allow')[0]<br>+            if allow == 'all':<br>+                #don't inherit<br>+                for i in sip.get(section, 'disallow'):<br>+                    set_value(key, i, section, pjsip, nmapped, type)<br>+            else:<br>+                merge_value(key, val, section, pjsip, nmapped, type, section_to, key_to)<br>+        except LookupError:<br>+            merge_value(key, val, section, pjsip, nmapped, type, section_to, key_to)<br>+            return<br>     else:<br>-  merge_value(key, val, section, pjsip, nmapped, type, section_to, key_to)<br>+        merge_value(key, val, section, pjsip, nmapped, type, section_to, key_to)<br> <br> <br> def non_mapped(nmapped):<br>@@ -162,9 +164,9 @@<br>         val = sip.get(section, 't38pt_udptl')[0]<br>     except LookupError:<br>         try:<br>-             val = sip.get('general', 't38pt_udptl')[0]<br>+            val = sip.get('general', 't38pt_udptl')[0]<br>         except LookupError:<br>-            return<br>+            return<br> <br>     ec = 'none'<br>     if 'yes' in val:<br>@@ -291,7 +293,7 @@<br> <br>     # Literal IPv6 (like [::]), IPv4, or hostname<br>     # does not work for IPv6 without brackets; case catched above<br>-    url = urlparse.urlparse('sip://' + host)<br>+    url = urlparse('sip://' + host)<br> <br>     if port_key:<br>         try:<br>@@ -435,8 +437,7 @@<br> ###############################################################################<br> <br> # options in pjsip.conf on an endpoint that have no sip.conf equivalent:<br>-# type, 100rel, trust_id_outbound, aggregate_mwi,<br>-# connected_line_method<br>+# type, 100rel, trust_id_outbound, aggregate_mwi, connected_line_method<br> <br> # known sip.conf peer keys that can be mapped to a pjsip.conf section/key<br> peer_map = [<br>@@ -591,7 +592,7 @@<br> <br>     # Literal IPv6 (like [::]), IPv4, or hostname<br>     # does not work for IPv6 without brackets; case catched above<br>-    url = urlparse.urlparse('sip://' + addr)<br>+    url = urlparse('sip://' + addr)<br>     # TODO Does not compress IPv6, for example 0:0:0:0:0:0:0:0 should get [::]<br>     return (url.hostname, url.port)<br> <br>@@ -839,11 +840,11 @@<br>         method = sip.multi_get('general', ['tlsclientmethod',<br>                                            'sslclientmethod'])[0]<br>         if section != 'transport-' + protocol + '6':  # print only once<br>-            print 'In chan_sip, you specified the TLS version. With chan_sip,' \<br>+            print('In chan_sip, you specified the TLS version. With chan_sip,' \<br>                   ' this was just for outbound client connections. In' \<br>                   ' chan_pjsip, this value is for client and server. Instead,' \<br>                   ' consider not to specify \'tlsclientmethod\' for chan_sip' \<br>-                  ' and \'method = sslv23\' for chan_pjsip.'<br>+                  ' and \'method = sslv23\' for chan_pjsip.')<br>     except LookupError:<br>         """<br>         OpenSSL emerged during the 90s. SSLv2 and SSLv3 were the only<br>@@ -1246,7 +1247,7 @@<br>             pjsip.write(fp)<br> <br>     except IOError:<br>-        print "Could not open file ", filename, " for writing"<br>+        print("Could not open file " + filename + " for writing")<br> <br> ###############################################################################<br> <br>@@ -1277,11 +1278,11 @@<br>     sip_filename, pjsip_filename = cli_options()<br>     # configuration parser for sip.conf<br>     sip = astconfigparser.MultiOrderedConfigParser()<br>-    print 'Please, report any issue at:'<br>-    print '    https://issues.asterisk.org/'<br>-    print 'Reading', sip_filename<br>+    print('Please, report any issue at:')<br>+    print('    https://issues.asterisk.org/')<br>+    print('Reading ' + sip_filename)<br>     sip.read(sip_filename)<br>-    print 'Converting to PJSIP...'<br>+    print('Converting to PJSIP...')<br>     pjsip, non_mappings = convert(sip, pjsip_filename, dict(), False)<br>-    print 'Writing', pjsip_filename<br>+    print('Writing ' + pjsip_filename)<br>     write_pjsip(pjsip_filename, pjsip, non_mappings)<br>diff --git a/contrib/scripts/sip_to_pjsip/sip_to_pjsql.py b/contrib/scripts/sip_to_pjsip/sip_to_pjsql.py<br>index d93bca5..71ddd45 100755<br>--- a/contrib/scripts/sip_to_pjsip/sip_to_pjsql.py<br>+++ b/contrib/scripts/sip_to_pjsip/sip_to_pjsql.py<br>@@ -1,6 +1,5 @@<br>-#!/usr/bin/python<br>+#!/usr/bin/env python<br> <br>-from sip_to_pjsip import cli_options<br> from sip_to_pjsip import convert<br> import sip_to_pjsip<br> import optparse<br>@@ -18,7 +17,7 @@<br>             pjsip.write(fp)<br> <br>     except IOError:<br>-        print "Could not open file ", filename, " for writing"<br>+        print("Could not open file " + filename + " for writing")<br> <br> def cli_options():<br>     """<br>@@ -70,12 +69,12 @@<br>     sip = sqlconfigparser.SqlConfigParser(table)<br>     sip_to_pjsip.sip = sip<br>     sip.connect(user,password,host,port,database)<br>-    print 'Please, report any issue at:'<br>-    print '    https://issues.asterisk.org/'<br>-    print 'Reading', sip_filename<br>+    print('Please, report any issue at:')<br>+    print('    https://issues.asterisk.org/')<br>+    print('Reading ' + sip_filename)<br>     sip.read(sip_filename)<br>-    print 'Converting to PJSIP realtime sql...'<br>+    print('Converting to PJSIP realtime sql...')<br>     pjsip, non_mappings = convert(sip, pjsip_filename, dict(), False)<br>-    print 'Writing', pjsip_filename<br>+    print('Writing ' + pjsip_filename)<br>     write_pjsip(pjsip_filename, pjsip, non_mappings)<br> <br>diff --git a/contrib/scripts/sip_to_pjsip/sqlconfigparser.py b/contrib/scripts/sip_to_pjsip/sqlconfigparser.py<br>index e87224f..55c6910 100644<br>--- a/contrib/scripts/sip_to_pjsip/sqlconfigparser.py<br>+++ b/contrib/scripts/sip_to_pjsip/sqlconfigparser.py<br>@@ -1,6 +1,13 @@<br> from astconfigparser import MultiOrderedConfigParser<br> <br>-import MySQLdb<br>+try:<br>+    import pymysql as MySQLdb<br>+    MySQLdb.install_as_MySQLdb()<br>+except ImportError:<br>+    # MySQLdb is compatible with Python 2 only.  Try it as a<br>+    # fallback if pymysql is unavailable.<br>+    import MySQLdb<br>+<br> import traceback<br> <br> class SqlConfigParser(MultiOrderedConfigParser):<br>@@ -61,9 +68,6 @@<br>         """Write configuration information out to a file"""<br>         try:<br>             self.write_dicts(config_file, self._sections)<br>-        except Exception,e:<br>-                print "Could not open file ", config_file, " for writing"<br>+        except:<br>+                print("Could not open file " + config_file + " for writing")<br>                 traceback.print_exc()<br>-<br>-<br>-<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/8805">change 8805</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/8805"/><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: I59cc6b52a1a89777eebcf25b3023bdf93babf835 </div>
<div style="display:none"> Gerrit-Change-Number: 8805 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: Alexander Traud <pabstraud@compuserve.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: Jenkins2 </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Torrey Searle <tsearle@gmail.com> </div>