Finished implementing the basic functionality of a license lister for pip installed packages (based on pip-licenses). eric7

Mon, 28 Mar 2022 18:13:15 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Mon, 28 Mar 2022 18:13:15 +0200
branch
eric7
changeset 9003
6bc210cd5726
parent 9002
31a7decd3393
child 9005
0f39e07a5e9b

Finished implementing the basic functionality of a license lister for pip installed packages (based on pip-licenses).

eric7.epj file | annotate | diff | comparison | revisions
eric7/PipInterface/Pip.py file | annotate | diff | comparison | revisions
eric7/PipInterface/PipLicensesDialog.py file | annotate | diff | comparison | revisions
eric7/PipInterface/PipLicensesDialog.ui file | annotate | diff | comparison | revisions
eric7/PipInterface/PipPackagesWidget.py file | annotate | diff | comparison | revisions
eric7/PipInterface/piplicenses.py file | annotate | diff | comparison | revisions
scripts/install.py file | annotate | diff | comparison | revisions
setup.py file | annotate | diff | comparison | revisions
--- a/eric7.epj	Sun Mar 27 19:56:41 2022 +0200
+++ b/eric7.epj	Mon Mar 28 18:13:15 2022 +0200
@@ -61,12 +61,17 @@
         "CopyrightMinFileSize": 0,
         "DocstringType": "eric",
         "EnabledCheckerCategories": "C, D, E, M, N, Y, W",
-        "ExcludeFiles": "*/ThirdParty/*, */coverage/*, */Ui_*.py, */Examples/*, */*_rc.py,*/pycodestyle.py,*/pyflakes/checker.py,*/mccabe.py,*/eradicate.py,*/ast_unparse.py",
+        "ExcludeFiles": "*/ThirdParty/*, */coverage/*, */Ui_*.py, */Examples/*, */*_rc.py,*/pycodestyle.py,*/pyflakes/checker.py,*/mccabe.py,*/eradicate.py,*/ast_unparse.py,*/piplicenses.py",
         "ExcludeMessages": "C101,E265,E266,E305,E402,M201,M301,M302,M303,M304,M305,M306,M307,M308,M311,M312,M313,M314,M315,M321,M701,M702,M811,M834,N802,N803,N807,N808,N821,W293,W504,Y119,Y401,Y402",
         "FixCodes": "",
         "FixIssues": false,
         "FutureChecker": "",
         "HangClosing": false,
+        "ImportsChecker": {
+          "ApplicationPackageNames": [],
+          "BanRelativeImports": "",
+          "BannedModules": []
+        },
         "IncludeMessages": "",
         "LineComplexity": 25,
         "LineComplexityScore": 10,
--- a/eric7/PipInterface/Pip.py	Sun Mar 27 19:56:41 2022 +0200
+++ b/eric7/PipInterface/Pip.py	Mon Mar 28 18:13:15 2022 +0200
@@ -975,12 +975,19 @@
     ## License handling methods below
     #######################################################################
     
-    def getLicenses(self, envName, summary=False):
+    def getLicenses(self, envName, localPackages=True, usersite=False,
+                    summary=False):
         """
         Public method to get the licenses per package for a given environment.
         
         @param envName name of the environment to get the licenses for
         @type str
+        @param localPackages flag indicating to get the licenses for local
+            packages only
+        @type bool
+        @param usersite flag indicating to get the licenses for packages
+            installed in user-site directory only
+        @type bool
         @param summary flag indicating to get a summary listing (defaults to
             False)
         @type bool (optional)
@@ -999,12 +1006,14 @@
                 args = [
                     "-c",
                     content,
-                    "--format",
-                    "json",
                     "--from",
                     "mixed",
                     "--with-system",
                 ]
+                if localPackages:
+                    args.append("--local-only")
+                if usersite:
+                    args.append("--user-only")
                 if summary:
                     args.append("--summary")
                 
@@ -1019,15 +1028,22 @@
         
         return licenses
     
-    def getLicensesSummary(self, envName):
+    def getLicensesSummary(self, envName, localPackages=True, usersite=False):
         """
         Public method to get a summary of licenses found in a given
         environment.
         
         @param envName name of the environment to get the licenses summary for
         @type str
+        @param localPackages flag indicating to get the licenses summary for
+            local packages only
+        @type bool
+        @param usersite flag indicating to get the licenses summary for
+            packages installed in user-site directory only
+        @type bool
         @return list of dictionaries containing the license and the count of
             packages
         @rtype dict
         """
-        return self.getLicenses(envName, summary=True)
+        return self.getLicenses(envName, localPackages=localPackages,
+                                usersite=usersite, summary=True)
--- a/eric7/PipInterface/PipLicensesDialog.py	Sun Mar 27 19:56:41 2022 +0200
+++ b/eric7/PipInterface/PipLicensesDialog.py	Mon Mar 28 18:13:15 2022 +0200
@@ -7,15 +7,17 @@
 Module implementing a dialog to show the licenses of an environment.
 """
 
-from PyQt6.QtCore import Qt
+from PyQt6.QtCore import pyqtSlot, Qt
 from PyQt6.QtWidgets import QDialog, QTreeWidgetItem
 
+from EricGui.EricOverrideCursor import EricOverrideCursor
+
 from .Ui_PipLicensesDialog import Ui_PipLicensesDialog
 
 
 class PipLicensesDialog(QDialog, Ui_PipLicensesDialog):
     """
-    Class documentation goes here.
+    Class implementing a dialog to show the licenses of an environment.
     """
     LicensesPackageColumn = 0
     LicensesVersionColumn = 1
@@ -24,14 +26,21 @@
     SummaryCountColumn = 0
     SummaryLicenseColumn = 1
     
-    def __init__(self, pip, environment, parent=None):
+    def __init__(self, pip, environment, localPackages=True, usersite=False,
+                 parent=None):
         """
         Constructor
         
         @param pip reference to the pip interface object
         @type Pip
-        @param envName name of the environment to show the licenses for
+        @param environment name of the environment to show the licenses for
         @type str
+        @param localPackages flag indicating to show the licenses for local
+            packages only
+        @type bool
+        @param usersite flag indicating to show the licenses for packages
+            installed in user-site directory only
+        @type bool
         @param parent reference to the parent widget (defaults to None)
         @type QWidget (optional)
         """
@@ -39,20 +48,45 @@
         self.setupUi(self)
         
         self.__pip = pip
+        self.__environment = environment
+        
+        self.localCheckBox.setChecked(localPackages)
+        self.userCheckBox.setChecked(usersite)
+        
+        self.localCheckBox.toggled.connect(self.__refreshLicenses)
+        self.userCheckBox.toggled.connect(self.__refreshLicenses)
         
         if environment:
             self.environmentLabel.setText("<b>{0}</b>".format(
-                self.tr("Licenses of {0}").format(environment)
+                self.tr('Licenses of "{0}"').format(environment)
             ))
+        else:
+            # That should never happen; play it safe.
+            self.environmentLabel.setText(self.tr("No environment specified."))
+        
+        self.__refreshLicenses()
+        
+    @pyqtSlot()
+    def __refreshLicenses(self):
+        """
+        Private slot to refresh the license lists.
+        """
+        with EricOverrideCursor():
+            self.licensesList.clear()
+            self.summaryList.clear()
             
             # step 1: show the licenses per package
-            self.licensesList.setUpdatesEnabled(True)
-            licenses = self.__pip.getLicenses(environment)
-            for license in licenses:
+            self.licensesList.setUpdatesEnabled(False)
+            licenses = self.__pip.getLicenses(
+                self.__environment,
+                localPackages=self.localCheckBox.isChecked(),
+                usersite=self.userCheckBox.isChecked(),
+            )
+            for lic in licenses:
                 QTreeWidgetItem(self.licensesList, [
-                    license["Name"],
-                    license["Version"],
-                    license["License"].replace("; ", "\n"),
+                    lic["Name"],
+                    lic["Version"],
+                    lic["License"].replace("; ", "\n"),
                 ])
             
             self.licensesList.sortItems(
@@ -63,12 +97,16 @@
             self.licensesList.setUpdatesEnabled(True)
             
             # step 2: show the licenses summary
-            self.summaryList.setUpdatesEnabled(True)
-            licenses = self.__pip.getLicensesSummary(environment)
-            for license in licenses:
+            self.summaryList.setUpdatesEnabled(False)
+            licenses = self.__pip.getLicensesSummary(
+                self.__environment,
+                localPackages=self.localCheckBox.isChecked(),
+                usersite=self.userCheckBox.isChecked(),
+            )
+            for lic in licenses:
                 QTreeWidgetItem(self.summaryList, [
-                    "{0:4d}".format(license["Count"]),
-                    license["License"].replace("; ", "\n"),
+                    "{0:4d}".format(lic["Count"]),
+                    lic["License"].replace("; ", "\n"),
                 ])
             
             self.summaryList.sortItems(
@@ -77,7 +115,3 @@
             for col in range(self.summaryList.columnCount()):
                 self.summaryList.resizeColumnToContents(col)
             self.summaryList.setUpdatesEnabled(True)
-            
-        else:
-            # That should never happen; play it safe.
-            self.environmentLabel.setText(self.tr("No environment specified."))
--- a/eric7/PipInterface/PipLicensesDialog.ui	Sun Mar 27 19:56:41 2022 +0200
+++ b/eric7/PipInterface/PipLicensesDialog.ui	Mon Mar 28 18:13:15 2022 +0200
@@ -21,6 +21,33 @@
     <widget class="QLabel" name="environmentLabel"/>
    </item>
    <item>
+    <layout class="QHBoxLayout" name="horizontalLayout_4">
+     <item>
+      <widget class="QCheckBox" name="localCheckBox">
+       <property name="toolTip">
+        <string>Select to show only licenses of locally installed packages</string>
+       </property>
+       <property name="text">
+        <string>Local packages only</string>
+       </property>
+       <property name="checked">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QCheckBox" name="userCheckBox">
+       <property name="toolTip">
+        <string>Select to show only licenses of packages installed to the user-site</string>
+       </property>
+       <property name="text">
+        <string>User-Site only</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
     <widget class="QTreeWidget" name="licensesList">
      <property name="sizePolicy">
       <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
@@ -107,6 +134,12 @@
    </item>
   </layout>
  </widget>
+ <tabstops>
+  <tabstop>localCheckBox</tabstop>
+  <tabstop>userCheckBox</tabstop>
+  <tabstop>licensesList</tabstop>
+  <tabstop>summaryList</tabstop>
+ </tabstops>
  <resources/>
  <connections>
   <connection>
--- a/eric7/PipInterface/PipPackagesWidget.py	Sun Mar 27 19:56:41 2022 +0200
+++ b/eric7/PipInterface/PipPackagesWidget.py	Mon Mar 28 18:13:15 2022 +0200
@@ -1824,5 +1824,21 @@
         from .PipLicensesDialog import PipLicensesDialog
         
         environment = self.environmentsComboBox.currentText()
-        dlg = PipLicensesDialog(self.__pip, environment, self)
+        localPackages = (
+            self.localDepCheckBox.isChecked()
+            if self.viewToggleButton.isChecked() else
+            self.localCheckBox.isChecked()
+        )
+        usersite = (
+            self.userDepCheckBox.isChecked()
+            if self.viewToggleButton.isChecked() else
+            self.userCheckBox.isChecked()
+        )
+        dlg = PipLicensesDialog(
+            self.__pip,
+            environment,
+            localPackages=localPackages,
+            usersite=usersite,
+            parent=self
+        )
         dlg.exec()
--- a/eric7/PipInterface/piplicenses.py	Sun Mar 27 19:56:41 2022 +0200
+++ b/eric7/PipInterface/piplicenses.py	Mon Mar 28 18:13:15 2022 +0200
@@ -26,46 +26,47 @@
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.
 """
+
+#
+# Modified to be used within the eric-ide project.
+#
+# Copyright (c) 2022 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
 import argparse
 import codecs
 import glob
+import json
 import os
 import sys
 from collections import Counter
 from email import message_from_string
 from email.parser import FeedParser
 from enum import Enum, auto
-from functools import partial
 from typing import List, Optional, Sequence, Text
 
-try:
-    from pip._internal.utils.misc import get_installed_distributions
-except ImportError:  # pragma: no cover
+
+def get_installed_distributions(local_only=True, user_only=False):
     try:
-        from pip import get_installed_distributions
+        from pip._internal.metadata import get_environment
     except ImportError:
-        def get_installed_distributions():
-            from pip._internal.metadata import (
-                get_default_environment, get_environment,
-            )
-            from pip._internal.metadata.pkg_resources import (
-                Distribution as _Dist,
-            )
-            from pip._internal.utils.compat import stdlib_pkgs
+        # For backward compatibility with pip version 20.3.4
+        from pip._internal.utils import misc
+        return misc.get_installed_distributions(
+            local_only=local_only,
+            user_only=user_only
+        )
+    else:
+        from pip._internal.utils.compat import stdlib_pkgs
+        dists = get_environment(None).iter_installed_distributions(
+            local_only=local_only,
+            user_only=user_only,
+            skip=stdlib_pkgs,
+            include_editables=True,
+            editables_only=False,
+        )
+        return [d._dist for d in dists]
 
-            env = get_default_environment()
-            dists = env.iter_installed_distributions(
-                local_only=True,
-                skip=stdlib_pkgs,
-                include_editables=True,
-                editables_only=False,
-                user_only=False,
-            )
-            return [dist._dist for dist in dists]
-
-from prettytable import PrettyTable
-
-open = open  # allow monkey patching
 
 __pkgname__ = 'pip-licenses'
 __version__ = '3.5.3'
@@ -90,12 +91,6 @@
 )
 
 
-SUMMARY_FIELD_NAMES = (
-    'Count',
-    'License',
-)
-
-
 DEFAULT_OUTPUT_FIELDS = (
     'Name',
     'Version',
@@ -217,7 +212,10 @@
 
         return pkg_info
 
-    pkgs = get_installed_distributions()
+    pkgs = get_installed_distributions(
+        local_only=args.local_only,
+        user_only=args.user_only,
+    )
     ignore_pkgs_as_lower = [pkg.lower() for pkg in args.ignore_packages]
     pkgs_as_lower = [pkg.lower() for pkg in args.packages]
 
@@ -287,7 +285,6 @@
                     args.from_, pkg['license_classifier'], pkg['license'])
                 license_str = '; '.join(sorted(license_set))
                 row[field] = license_str
-##                row.append(license_str)
             elif field == 'License-Classifier':
                 row[field] = ('; '.join(sorted(pkg['license_classifier']))
                            or LICENSE_UNKNOWN)
@@ -300,160 +297,20 @@
     return licenses
 
 
-def create_summary_table(args: "CustomNamespace"):
+def create_summary_list(args: "CustomNamespace"):
     counts = Counter(
         '; '.join(sorted(select_license_by_source(
             args.from_, pkg['license_classifier'], pkg['license'])))
         for pkg in get_packages(args))
 
-    table = factory_styled_table_with_args(args, SUMMARY_FIELD_NAMES)
+    licenses = []
     for license, count in counts.items():
-        table.add_row([count, license])
-    return table
-
-
-class JsonTable():
-
-    def _format_row(self, row, options):
-        resrow = {}
-        for (field, value) in zip(self._field_names, row):
-            if field not in options["fields"]:
-                continue
-
-            resrow[field] = value
-
-        return resrow
-
-    def get_string(self, **kwargs):
-        # import included here in order to limit dependencies
-        # if not interested in JSON output,
-        # then the dependency is not required
-        import json
-
-        options = self._get_options(kwargs)
-        rows = self._get_rows(options)
-        formatted_rows = self._format_rows(rows, options)
-
-        lines = []
-        for row in formatted_rows:
-            lines.append(row)
-
-        return json.dumps(lines, indent=2, sort_keys=True)
-##
-##
-##class JsonLicenseFinderTable(JsonPrettyTable):
-##    def _format_row(self, row, options):
-##        resrow = {}
-##        for (field, value) in zip(self._field_names, row):
-##            if field == 'Name':
-##                resrow['name'] = value
-##
-##            if field == 'Version':
-##                resrow['version'] = value
-##
-##            if field == 'License':
-##                resrow['licenses'] = [value]
-##
-##        return resrow
-##
-##    def get_string(self, **kwargs):
-##        # import included here in order to limit dependencies
-##        # if not interested in JSON output,
-##        # then the dependency is not required
-##        import json
-##
-##        options = self._get_options(kwargs)
-##        rows = self._get_rows(options)
-##        formatted_rows = self._format_rows(rows, options)
-##
-##        lines = []
-##        for row in formatted_rows:
-##            lines.append(row)
-##
-##        return json.dumps(lines, sort_keys=True)
-##
-##
-##class CSVPrettyTable(PrettyTable):
-##    """PrettyTable-like class exporting to CSV"""
-##
-##    def get_string(self, **kwargs):
-##
-##        def esc_quotes(val):
-##            """
-##            Meta-escaping double quotes
-##            https://tools.ietf.org/html/rfc4180
-##            """
-##            try:
-##                return val.replace('"', '""')
-##            except UnicodeDecodeError:  # pragma: no cover
-##                return val.decode('utf-8').replace('"', '""')
-##            except UnicodeEncodeError:  # pragma: no cover
-##                return val.encode('unicode_escape').replace('"', '""')
-##
-##        options = self._get_options(kwargs)
-##        rows = self._get_rows(options)
-##        formatted_rows = self._format_rows(rows, options)
-##
-##        lines = []
-##        formatted_header = ','.join(['"%s"' % (esc_quotes(val), )
-##                                     for val in self._field_names])
-##        lines.append(formatted_header)
-##        for row in formatted_rows:
-##            formatted_row = ','.join(['"%s"' % (esc_quotes(val), )
-##                                      for val in row])
-##            lines.append(formatted_row)
-##
-##        return '\n'.join(lines)
-##
-##
-##class PlainVerticalTable(PrettyTable):
-##    """PrettyTable for outputting to a simple non-column based style.
-##
-##    When used with --with-license-file, this style is similar to the default
-##    style generated from Angular CLI's --extractLicenses flag.
-##    """
-##
-##    def get_string(self, **kwargs):
-##        options = self._get_options(kwargs)
-##        rows = self._get_rows(options)
-##
-##        output = ''
-##        for row in rows:
-##            for v in row:
-##                output += '{}\n'.format(v)
-##            output += '\n'
-##
-##        return output
-##
-##
-def factory_styled_table_with_args(
-        args: "CustomNamespace", output_fields=DEFAULT_OUTPUT_FIELDS):
-    table = PrettyTable()
-    table.field_names = output_fields
-    table.align = 'l'
-    table.border = args.format_ in (FormatArg.MARKDOWN, FormatArg.RST,
-                                    FormatArg.CONFLUENCE, FormatArg.JSON)
-    table.header = True
-
-    if args.format_ == FormatArg.MARKDOWN:
-        table.junction_char = '|'
-        table.hrules = RULE_HEADER
-    elif args.format_ == FormatArg.RST:
-        table.junction_char = '+'
-        table.hrules = RULE_ALL
-    elif args.format_ == FormatArg.CONFLUENCE:
-        table.junction_char = '|'
-        table.hrules = RULE_NONE
-    elif args.format_ == FormatArg.JSON:
-        table = JsonPrettyTable(table.field_names)
-    elif args.format_ == FormatArg.JSON_LICENSE_FINDER:
-        table = JsonLicenseFinderTable(table.field_names)
-    elif args.format_ == FormatArg.CSV:
-        table = CSVPrettyTable(table.field_names)
-    elif args.format_ == FormatArg.PLAIN_VERTICAL:
-        table = PlainVerticalTable(table.field_names)
-
-    return table
+        licenses.append({
+            "Count": count,
+            "License": license,
+        })
+    
+    return licenses
 
 
 def find_license_from_classifier(message):
@@ -513,56 +370,15 @@
     return output_fields
 
 
-def get_sortby(args: "CustomNamespace"):
-    if args.summary and args.order == OrderArg.COUNT:
-        return 'Count'
-    elif args.summary or args.order == OrderArg.LICENSE:
-        return 'License'
-    elif args.order == OrderArg.NAME:
-        return 'Name'
-    elif args.order == OrderArg.AUTHOR and args.with_authors:
-        return 'Author'
-    elif args.order == OrderArg.URL and args.with_urls:
-        return 'URL'
-
-    return 'Name'
-
-
 def create_output_string(args: "CustomNamespace"):
     output_fields = get_output_fields(args)
 
     if args.summary:
-        table = create_summary_table(args)
+        licenses = create_summary_list(args)
     else:
-        table = create_licenses_list(args, output_fields)
+        licenses = create_licenses_list(args, output_fields)
     
-    return json.dumps(table)
-##
-##    sortby = get_sortby(args)
-##
-##    if args.format_ == FormatArg.HTML:
-##        return table.get_html_string(fields=output_fields, sortby=sortby)
-##    else:
-##        return table.get_string(fields=output_fields, sortby=sortby)
-##
-##
-##def create_warn_string(args: "CustomNamespace"):
-##    warn_messages = []
-##    warn = partial(output_colored, '33')
-##
-##    if args.with_license_file and not args.format_ == FormatArg.JSON:
-##        message = warn(('Due to the length of these fields, this option is '
-##                        'best paired with --format=json.'))
-##        warn_messages.append(message)
-##
-##    if args.summary and (args.with_authors or args.with_urls):
-##        message = warn(('When using this option, only --order=count or '
-##                        '--order=license has an effect for the --order '
-##                        'option. And using --with-authors and --with-urls '
-##                        'will be ignored.'))
-##        warn_messages.append(message)
-##
-##    return '\n'.join(warn_messages)
+    return json.dumps(licenses)
 
 
 class CustomHelpFormatter(argparse.HelpFormatter):  # pragma: no cover
@@ -606,8 +422,9 @@
 class CustomNamespace(argparse.Namespace):
     from_: "FromArg"
     order: "OrderArg"
-    format_: "FormatArg"
     summary: bool
+    local_only: bool
+    user_only:bool
     output_file: str
     ignore_packages: List[str]
     packages: List[str]
@@ -673,18 +490,6 @@
     URL = U = auto()
 
 
-class FormatArg(NoValueEnum):
-    PLAIN = P = auto()
-    PLAIN_VERTICAL = auto()
-    MARKDOWN = MD = M = auto()
-    RST = REST = R = auto()
-    CONFLUENCE = C = auto()
-    HTML = H = auto()
-    JSON = J = auto()
-    JSON_LICENSE_FINDER = JLF = auto()
-    CSV = auto()
-
-
 def value_to_enum_key(value: str) -> str:
     return value.replace('-', '_').upper()
 
@@ -701,7 +506,6 @@
 MAP_DEST_TO_ENUM = {
     'from_': FromArg,
     'order': OrderArg,
-    'format_': FormatArg,
 }
 
 
@@ -749,17 +553,6 @@
              '"name", "license", "author", "url"\n'
              '(default: %(default)s)')
     common_options.add_argument(
-        '-f', '--format',
-        dest='format_',
-        action=SelectAction, type=str,
-        default=FormatArg.PLAIN, metavar='STYLE',
-        choices=choices_from_enum(FormatArg),
-        help='R|dump as set format style\n'
-             '"plain", "plain-vertical" "markdown", "rst", \n'
-             '"confluence", "html", "json", \n'
-             '"json-license-finder",  "csv"\n'
-             '(default: %(default)s)')
-    common_options.add_argument(
         '--summary',
         action='store_true',
         default=False,
@@ -780,6 +573,17 @@
         nargs='+', metavar='PKG',
         default=[],
         help='only include selected packages in output')
+    common_options.add_argument(
+        '--local-only',
+        action='store_true',
+        default=False,
+        help='include only local packages')
+    common_options.add_argument(
+        '--user-only',
+        action='store_true',
+        default=False,
+        help='include only packages of the user site dir')
+    
     format_options.add_argument(
         '-s', '--with-system',
         action='store_true',
@@ -845,33 +649,6 @@
              'of the licenses not in the semicolon-separated list')
 
     return parser
-##
-##
-##def output_colored(code, text, is_bold=False):
-##    """
-##    Create function to output with color sequence
-##    """
-##    if is_bold:
-##        code = '1;%s' % code
-##
-##    return '\033[%sm%s\033[0m' % (code, text)
-##
-##
-##def save_if_needs(output_file, output_string):
-##    """
-##    Save to path given by args
-##    """
-##    if output_file is None:
-##        return
-##
-##    try:
-##        with open(output_file, 'w', encoding='utf-8') as f:
-##            f.write(output_string)
-##        sys.stdout.write('created path: ' + output_file + '\n')
-##        sys.exit(0)
-##    except IOError:
-##        sys.stderr.write('check path: --output-file\n')
-##        sys.exit(1)
 
 
 def main():  # pragma: no cover
@@ -880,13 +657,7 @@
 
     output_string = create_output_string(args)
 
-##    output_file = args.output_file
-##    save_if_needs(output_file, output_string)
-##
     print(output_string)
-##    warn_string = create_warn_string(args)
-##    if warn_string:
-##        print(warn_string, file=sys.stderr)
 
 
 if __name__ == '__main__':  # pragma: no cover
--- a/scripts/install.py	Sun Mar 27 19:56:41 2022 +0200
+++ b/scripts/install.py	Mon Mar 28 18:13:15 2022 +0200
@@ -1610,7 +1610,6 @@
         "jedi": ("jedi", ""),
         "packaging": ("packaging", ""),
         "pipdeptree": ("pipdeptree", ""),
-        "pip-licenses": ("piplicenses", ""),
     }
     if not ignorePyqt6Tools:
         optionalModulesList["qt6-applications"] = ("qt6_applications", "")
--- a/setup.py	Sun Mar 27 19:56:41 2022 +0200
+++ b/setup.py	Mon Mar 28 18:13:15 2022 +0200
@@ -357,7 +357,6 @@
         "jedi",
         "packaging",
         "pipdeptree",
-        "pip-licenses",
         "pywin32>=1.0;platform_system=='Windows'",
     ],
     data_files=getDataFiles(),

eric ide

mercurial