| 88 | |
| 89 | == Python 2 and Python 3 differences |
| 90 | The most important change between these two versions is dealing with strings. |
| 91 | * In Python 2: |
| 92 | * Bytes == Strings |
| 93 | * Unicodes != Strings |
| 94 | * In Python 3: |
| 95 | * Bytes != Strings |
| 96 | * Unicodes == Strings |
| 97 | |
| 98 | For Python 3, bytes objects can not contain character literals other than ASCII, therefore, we use bytes() to convert from unicode/string to byte object. |
| 99 | {{{ |
| 100 | >>> bytes('Příšerný kůň', encoding='utf-8') |
| 101 | b'P\xc5\x99\xc3\xad\xc5\xa1ern\xc3\xbd k\xc5\xaf\xc5\x88' |
| 102 | }}} |
| 103 | To decode, use decode(): |
| 104 | {{{ |
| 105 | >>>b'P\xc5\x99\xc3\xad\xc5\xa1ern\xc3\xbd k\xc5\xaf\xc5\x88'.decode() |
| 106 | 'Příšerný kůň' |
| 107 | }}} |
| 108 | We already have encode and decode functions available in (from grass.script.utils import encode, decode) lib/python/script/utils.py that makes it easy for us to convert back and forth. To make it work with Python3, made changes in those functions to avoid syntax errors and exceptions. |
| 109 | |
| 110 | |
| 111 | == How to write Python 3 compatible code |
| 112 | To check which Python version is being used, use sys.verson_info like: |
| 113 | {{{ |
| 114 | import sys |
| 115 | if sys.version_info.major >= 3: |
| 116 | //… |
| 117 | else: |
| 118 | //... |
| 119 | }}} |
| 120 | |
| 121 | === Other recommendations: |
| 122 | Use .format specifier for the strings and parameters. |
| 123 | For example instead of using: |
| 124 | {{{ |
| 125 | '%s %s' % ('one', 'two') |
| 126 | }}} |
| 127 | Use: |
| 128 | {{{ |
| 129 | '{} {}'.format('one', 'two') |
| 130 | }}} |
| 131 | .format is compatible with both Python 2 and Python 3. |
| 132 | |
| 133 | Read more at: |
| 134 | https://pyformat.info/ |
| 135 | |
| 136 | |
| 137 | == wxPython GUI |
| 138 | There are a lot of changes found in wxPython Phoenix version. It is recommended to follow the MIgration guide (https://docs.wxpython.org/MigrationGuide.html) to properly migrate from the Classic version of wxPython. To support both the versions. The wrap.py includes a lot of new classes that work as a wrapper to accommodate both the versions of wxPython and Python itself. |
| 139 | |
| 140 | All the changes for Classic vs Phoenix can be found here: |
| 141 | https://wxpython.org/Phoenix/docs/html/classic_vs_phoenix.html |
| 142 | |
| 143 | We have created a wrap.py class that contains overloaded classes for wx classes to support both versions. |
| 144 | Example: |
| 145 | {{{ |
| 146 | from gui_core.wrap TextCtrl, StaticText |
| 147 | }}} |
| 148 | Deprecated warnings can be removed by appropriately using the wx classes. Refer to the changes in both versions and see if the wrapper class is already created for the wx class; if not, create a new class in a similar manner as other wrapper classes in the wrap.py file. |
| 149 | |
| 150 | cmp function is not available in Python3, it has been custom created and included in gui/wxpython/core/utils.py file. Be sure to include it where cmp() is used. |
| 151 | |
| 152 | == References |