Wed, 23 Jun 2021 18:55:54 +0200
Streamline the install script a little bit.
--- a/eric7/APIs/Python3/eric7.api Wed Jun 23 18:54:41 2021 +0200 +++ b/eric7/APIs/Python3/eric7.api Wed Jun 23 18:55:54 2021 +0200 @@ -3662,6 +3662,7 @@ eric7.Plugins.CheckerPlugins.CodeStyleChecker.Simplify.ast_unparse._Unparser.write_item?4() eric7.Plugins.CheckerPlugins.CodeStyleChecker.Simplify.ast_unparse._Unparser.write_key_value_pair?4(v) eric7.Plugins.CheckerPlugins.CodeStyleChecker.Simplify.ast_unparse._Unparser?2(*, _avoid_backslashes=False) +eric7.Plugins.CheckerPlugins.CodeStyleChecker.Simplify.ast_unparse.nullcontext?1(enter_result=None) eric7.Plugins.CheckerPlugins.CodeStyleChecker.Simplify.ast_unparse.unparse?4(ast_obj) eric7.Plugins.CheckerPlugins.CodeStyleChecker.Simplify.translations._simplifyMessages?8 eric7.Plugins.CheckerPlugins.CodeStyleChecker.Simplify.translations._simplifyMessagesSampleArgs?8 @@ -12297,6 +12298,7 @@ install.sourceDir?7 install.updatePip?4() install.usage?4(rcode=2) +install.versionToStr?4(version) install.windowsDesktopEntries?4() install.windowsDesktopNames?4() install.windowsProgramsEntry?4()
--- a/eric7/APIs/Python3/eric7.bas Wed Jun 23 18:54:41 2021 +0200 +++ b/eric7/APIs/Python3/eric7.bas Wed Jun 23 18:55:54 2021 +0200 @@ -1051,3 +1051,4 @@ ZoomValuesModel QAbstractTableModel _Precedence IntEnum _Unparser ast.NodeVisitor +nullcontext AbstractContextManager
--- a/eric7/Documentation/Help/source.qhp Wed Jun 23 18:54:41 2021 +0200 +++ b/eric7/Documentation/Help/source.qhp Wed Jun 23 18:55:54 2021 +0200 @@ -18246,6 +18246,10 @@ <keyword name="normcaseabspath" id="normcaseabspath" ref="eric7.Utilities.__init__.html#normcaseabspath" /> <keyword name="normcasepath" id="normcasepath" ref="eric7.Utilities.__init__.html#normcasepath" /> <keyword name="normjoinpath" id="normjoinpath" ref="eric7.Utilities.__init__.html#normjoinpath" /> + <keyword name="nullcontext" id="nullcontext" ref="eric7.Plugins.CheckerPlugins.CodeStyleChecker.Simplify.ast_unparse.html#nullcontext" /> + <keyword name="nullcontext (Constructor)" id="nullcontext (Constructor)" ref="eric7.Plugins.CheckerPlugins.CodeStyleChecker.Simplify.ast_unparse.html#nullcontext.__init__" /> + <keyword name="nullcontext.__enter__" id="nullcontext.__enter__" ref="eric7.Plugins.CheckerPlugins.CodeStyleChecker.Simplify.ast_unparse.html#nullcontext.__enter__" /> + <keyword name="nullcontext.__exit__" id="nullcontext.__exit__" ref="eric7.Plugins.CheckerPlugins.CodeStyleChecker.Simplify.ast_unparse.html#nullcontext.__exit__" /> <keyword name="objectName" id="objectName" ref="eric7.Project.UicLoadUi5.html#objectName" /> <keyword name="objectName" id="objectName" ref="eric7.Project.UicLoadUi6.html#objectName" /> <keyword name="okToClearData" id="okToClearData" ref="eric7.EricWidgets.EricMessageBox.html#okToClearData" /> @@ -18517,6 +18521,7 @@ <keyword name="version" id="version" ref="eric7.Toolbox.Startup.html#version" /> <keyword name="version" id="version" ref="eric7.eric7_api.html#version" /> <keyword name="version" id="version" ref="eric7.eric7_doc.html#version" /> + <keyword name="versionToStr" id="versionToStr" ref="install.html#versionToStr" /> <keyword name="versionToTuple" id="versionToTuple" ref="eric7.Globals.__init__.html#versionToTuple" /> <keyword name="warning" id="warning" ref="eric7.EricWidgets.EricMessageBox.html#warning" /> <keyword name="weakCryptographicKey (Module)" id="weakCryptographicKey (Module)" ref="eric7.Plugins.CheckerPlugins.CodeStyleChecker.Security.Checks.weakCryptographicKey.html" />
--- a/eric7/Documentation/Source/eric7.Plugins.CheckerPlugins.CodeStyleChecker.Simplify.ast_unparse.html Wed Jun 23 18:54:41 2021 +0200 +++ b/eric7/Documentation/Source/eric7.Plugins.CheckerPlugins.CodeStyleChecker.Simplify.ast_unparse.html Wed Jun 23 18:55:54 2021 +0200 @@ -39,6 +39,10 @@ <td><a href="#_Unparser">_Unparser</a></td> <td>Methods in this class recursively traverse an AST and output source code for the abstract syntax; original formatting is disregarded.</td> </tr> +<tr> +<td><a href="#nullcontext">nullcontext</a></td> +<td>Context manager that does no additional processing.</td> +</tr> </table> <h3>Functions</h3> @@ -934,6 +938,71 @@ <div align="right"><a href="#top">Up</a></div> <hr /> <hr /> +<a NAME="nullcontext" ID="nullcontext"></a> +<h2>nullcontext</h2> + +<p> +Context manager that does no additional processing. +</p> +<p> + Used as a stand-in for a normal context manager, when a particular + block of code is only sometimes used with a normal context manager: +</p> +<p> + cm = optional_cm if condition else nullcontext() + with cm: + # Perform operation, using optional_cm if condition is True +</p> +<h3>Derived from</h3> +AbstractContextManager +<h3>Class Attributes</h3> + +<table> +<tr><td>None</td></tr> +</table> +<h3>Class Methods</h3> + +<table> +<tr><td>None</td></tr> +</table> +<h3>Methods</h3> + +<table> + +<tr> +<td><a href="#nullcontext.__init__">nullcontext</a></td> +<td></td> +</tr> +<tr> +<td><a href="#nullcontext.__enter__">__enter__</a></td> +<td></td> +</tr> +<tr> +<td><a href="#nullcontext.__exit__">__exit__</a></td> +<td></td> +</tr> +</table> +<h3>Static Methods</h3> + +<table> +<tr><td>None</td></tr> +</table> + +<a NAME="nullcontext.__init__" ID="nullcontext.__init__"></a> +<h4>nullcontext (Constructor)</h4> +<b>nullcontext</b>(<i>enter_result=None</i>) + +<a NAME="nullcontext.__enter__" ID="nullcontext.__enter__"></a> +<h4>nullcontext.__enter__</h4> +<b>__enter__</b>(<i></i>) + +<a NAME="nullcontext.__exit__" ID="nullcontext.__exit__"></a> +<h4>nullcontext.__exit__</h4> +<b>__exit__</b>(<i>*excinfo</i>) + +<div align="right"><a href="#top">Up</a></div> +<hr /> +<hr /> <a NAME="unparse" ID="unparse"></a> <h2>unparse</h2> <b>unparse</b>(<i>ast_obj</i>)
--- a/eric7/Documentation/Source/install.html Wed Jun 23 18:54:41 2021 +0200 +++ b/eric7/Documentation/Source/install.html Wed Jun 23 18:55:54 2021 +0200 @@ -168,6 +168,10 @@ <td>Display a usage message and exit.</td> </tr> <tr> +<td><a href="#versionToStr">versionToStr</a></td> +<td>Function to convert a version number into a version string.</td> +</tr> +<tr> <td><a href="#windowsDesktopEntries">windowsDesktopEntries</a></td> <td>Function to generate data for the Windows Desktop links.</td> </tr> @@ -753,6 +757,35 @@ <div align="right"><a href="#top">Up</a></div> <hr /> <hr /> +<a NAME="versionToStr" ID="versionToStr"></a> +<h2>versionToStr</h2> +<b>versionToStr</b>(<i>version</i>) + +<p> + Function to convert a version number into a version string. +</p> +<dl> + +<dt><i>version</i> (int)</dt> +<dd> +version number to convert +</dd> +</dl> +<dl> +<dt>Return:</dt> +<dd> +version string +</dd> +</dl> +<dl> +<dt>Return Type:</dt> +<dd> +str +</dd> +</dl> +<div align="right"><a href="#top">Up</a></div> +<hr /> +<hr /> <a NAME="windowsDesktopEntries" ID="windowsDesktopEntries"></a> <h2>windowsDesktopEntries</h2> <b>windowsDesktopEntries</b>(<i></i>)
--- a/scripts/install.py Wed Jun 23 18:54:41 2021 +0200 +++ b/scripts/install.py Wed Jun 23 18:55:54 2021 +0200 @@ -1421,10 +1421,36 @@ [sys.executable, "-m", "pip", "install", "--upgrade", "pip"]) +def versionToStr(version): + """ + Function to convert a version number into a version string. + + @param version version number to convert + @type int + @return version string + @rtype str + """ + parts = [] + while version: + parts.append(version & 0xff) + version >>= 8 + return '.'.join(str(p) for p in reversed(parts)) + + def doDependancyChecks(): """ Perform some dependency checks. """ + # TODO: update as necessary for PyQt6 6.2.0 + # TODO: change that once QScintilla 2.13.0 is released + requiredVersions = { + "pyqt6": 0x60101, + "pyqt6-charts": 0x60101, + #"pyqt6-webengine": 0x60200, + "pyqt6-qscintilla": 0x20c01, + "sip": 0x60100, + } + try: isSudo = os.getuid() == 0 and sys.platform != "darwin" # disregard sudo installs on macOS @@ -1455,7 +1481,7 @@ from PyQt6.QtCore import qVersion except ImportError as msg: installed = not isSudo and pipInstall( - "PyQt6>=6.1.0", + "PyQt6>={0}".format(versionToStr(requiredVersions["pyqt6"])), "'PyQt6' could not be detected.\nError: {0}".format(msg) ) if installed: @@ -1490,7 +1516,8 @@ print("Optional 'PyQt6-WebEngine' could not be detected.") else: pipInstall( - "PyQt6-WebEngine>=6.2.0", + "PyQt6-WebEngine>={0}".format( + versionToStr(requiredVersions["pyqt6-webengine"])), "Optional 'PyQt6-WebEngine' could not be detected.\n" "Error: {0}".format(msg) ) @@ -1502,7 +1529,8 @@ print("Optional 'PyQt6-Charts' could not be detected.") else: pipInstall( - "PyQt6-Charts>=6.1.0", + "PyQt6-Charts>={0}".format( + versionToStr(requiredVersions["pyqt6-charts"])), "Optional 'PyQt6-Charts' could not be detected.\n" "Error: {0}".format(msg) ) @@ -1512,7 +1540,8 @@ from PyQt6 import Qsci # __IGNORE_WARNING__ except ImportError as msg: installed = not isSudo and pipInstall( - "PyQt6-QScintilla", + "PyQt6-QScintilla>={0}".format( + versionToStr(requiredVersions["pyqt6-qscintilla"])), "'PyQt6-QScintilla' could not be detected.\nError: {0}".format(msg) ) if installed: @@ -1535,12 +1564,6 @@ "PyQt6.QtGui", "PyQt6.QtNetwork", "PyQt6.QtPrintSupport", "PyQt6.QtSql", "PyQt6.QtSvg", "PyQt6.QtSvgWidgets", "PyQt6.QtWidgets", ] - altModulesList = [ - # Tuple with alternatives, flag indicating it's ok to not be - # available (e.g. for 32-Bit Windows) - # TODO: enable this once PyQt 6.2.0/Qt 6.2.0 is released - #~ (("PyQt6.QtWebEngineWidgets", ), sys.maxsize <= 2**32), # __IGNORE_WARNING__ - ] optionalModulesList = { # key is pip project name # value is tuple of package name, pip install constraint @@ -1575,24 +1598,7 @@ modulesOK = False if not modulesOK: exit(1) - # check mandatory modules with alternatives - if altModulesList: - altModulesOK = True - for altModules, forcedOk in altModulesList: - modulesOK = False - for altModule in altModules: - name = altModule.split(".")[1] - with contextlib.suppress(ImportError): - __import__(altModule) - print("Found", name) - modulesOK = True - break - if not modulesOK and not forcedOk: - altModulesOK = False - print('Sorry, please install {0}.' - .format(" or ".join(altModules))) - if not altModulesOK: - exit(1) + # check optional modules for optPackage in optionalModulesList: try: @@ -1621,6 +1627,7 @@ print("-------------------") # check version of Qt + # =================== qtMajor = int(qVersion().split('.')[0]) qtMinor = int(qVersion().split('.')[1]) print("Qt6: {0}".format(qVersion().strip())) @@ -1629,92 +1636,80 @@ exit(2) # check version of sip + # ==================== with contextlib.suppress(ImportError, AttributeError): try: from PyQt6 import sip except ImportError: import sip - sipVersion = sip.SIP_VERSION_STR - print("sip:", sipVersion.strip()) + print("sip:", sip.SIP_VERSION_STR.strip()) # always assume, that snapshots or dev versions are new enough - if "snapshot" not in sipVersion and "dev" not in sipVersion: - while sipVersion.count('.') < 2: - sipVersion += '.0' - (major, minor, pat) = sipVersion.split('.')[:3] - major = int(major) - minor = int(minor) - pat = int(pat) - if ( - major < 6 or - (major == 6 and minor < 0) or - (major == 6 and minor == 1 and pat < 0) - ): - print('Sorry, you must have sip 6.1.0 or higher or' - ' a recent snapshot release.') + if ( + "snapshot" not in sip.SIP_VERSION_STR and + "dev" not in sip.SIP_VERSION_STR + ): + if sip.SIP_VERSION < requiredVersions["sip"]: + print( + 'Sorry, you must have sip {0} or higher or' + ' a recent development release.' + .format(versionToStr(requiredVersions["sip"])) + ) exit(3) # check for blacklisted versions for vers in BlackLists["sip"] + PlatformBlackLists["sip"]: - if vers == sipVersion: + if vers == sip.SIP_VERSION: print( 'Sorry, sip version {0} is not compatible with eric.' - .format(vers)) + .format(versionToStr(vers))) print('Please install another version.') exit(3) - # check version of PyQt - from PyQt6.QtCore import PYQT_VERSION_STR - pyqtVersion = PYQT_VERSION_STR - print("PyQt6:", pyqtVersion.strip()) + # check version of PyQt6 + # ====================== + from PyQt6.QtCore import PYQT_VERSION, PYQT_VERSION_STR + print("PyQt6:", PYQT_VERSION_STR.strip()) # always assume, that snapshots or dev versions are new enough - if "snapshot" not in pyqtVersion and "dev" not in pyqtVersion: - while pyqtVersion.count('.') < 2: - pyqtVersion += '.0' - (major, minor, pat) = pyqtVersion.split('.')[:3] - major = int(major) - minor = int(minor) - pat = int(pat) - if major == 6 and minor < 1: - print('Sorry, you must have PyQt 6.1.0 or better or' - ' a recent snapshot release.') + if "snapshot" not in PYQT_VERSION_STR and "dev" not in PYQT_VERSION_STR: + if PYQT_VERSION < requiredVersions["pyqt6"]: + print( + 'Sorry, you must have PyQt {0} or better or' + ' a recent development release.' + .format(versionToStr(requiredVersions["pyqt6"])) + ) exit(4) # check for blacklisted versions for vers in BlackLists["PyQt6"] + PlatformBlackLists["PyQt6"]: - if vers == pyqtVersion: + if vers == PYQT_VERSION: print('Sorry, PyQt version {0} is not compatible with eric.' - .format(vers)) + .format(versionToStr(vers))) print('Please install another version.') exit(4) # check version of QScintilla - from PyQt6.Qsci import QSCINTILLA_VERSION_STR - scintillaVersion = QSCINTILLA_VERSION_STR + # =========================== + from PyQt6.Qsci import QSCINTILLA_VERSION, QSCINTILLA_VERSION_STR print("PyQt6-QScintilla:", QSCINTILLA_VERSION_STR.strip()) # always assume, that snapshots or dev versions are new enough - if "snapshot" not in scintillaVersion and "dev" not in scintillaVersion: - while scintillaVersion.count('.') < 2: - scintillaVersion += '.0' - (major, minor, pat) = scintillaVersion.split('.')[:3] - major = int(major) - minor = int(minor) - pat = int(pat) - if ( - major < 2 or - (major == 2 and minor < 12) or - # TODO: raise pat once QScintilla 2.12.2 is released - (major == 2 and minor == 12 and pat < 1) - ): - print('Sorry, you must have PyQt6-QScintilla 2.12.1 or higher or' - ' a recent snapshot release.') + if ( + "snapshot" not in QSCINTILLA_VERSION_STR and + "dev" not in QSCINTILLA_VERSION_STR + ): + if QSCINTILLA_VERSION < requiredVersions["pyqt6-qscintilla"]: + print( + 'Sorry, you must have PyQt6-QScintilla {0} or higher or' + ' a recent development release.' + .format(versionToStr(requiredVersions["pyqt6-qscintilla"])) + ) exit(5) # check for blacklisted versions for vers in ( BlackLists["QScintilla2"] + PlatformBlackLists["QScintilla2"] ): - if vers == scintillaVersion: + if vers == QSCINTILLA_VERSION: print( 'Sorry, QScintilla2 version {0} is not compatible with' - ' eric.'.format(vers)) + ' eric.'.format(versionToStr(vers))) print('Please install another version.') exit(5)
--- a/setup.py Wed Jun 23 18:54:41 2021 +0200 +++ b/setup.py Wed Jun 23 18:55:54 2021 +0200 @@ -337,9 +337,9 @@ "pip>=19.0", "wheel", "PyQt6>=6.1.1", - "PyQt6-Charts>=6.1.0", + "PyQt6-Charts>=6.1.1", #~ "PyQt6-WebEngine>=6.2.0", # __IGNORE_WARNING__ - "PyQt6-QScintilla>=2.12.2", + "PyQt6-QScintilla>=2.13.0", "docutils", "Markdown", "pyyaml",