Title: [265254] trunk/Tools
Revision
265254
Author
jbed...@apple.com
Date
2020-08-04 12:06:47 -0700 (Tue, 04 Aug 2020)

Log Message

[webkitcorepy] Use setup.py for the autoinstaller
https://bugs.webkit.org/show_bug.cgi?id=215067
<rdar://problem/66432719>

Reviewed by Stephanie Lewis.

* Scripts/libraries/webkitcorepy/webkitcorepy/__init__.py: Add all requests dependencies.
* Scripts/libraries/webkitcorepy/webkitcorepy/autoinstall.py:
(Package.Archive__init__): Add extension, tar.gz by default.
(Package.Archive.path): Support multiple file types.
(Package.Archive.unpack): Support .zip files.
(Package.__init__): Add slow_install flag.
(Package.archives): Handle case were a library does not have a tiny version.
(Package.install): Call setup.py instead of just moving the library out of the package.

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (265253 => 265254)


--- trunk/Tools/ChangeLog	2020-08-04 18:56:34 UTC (rev 265253)
+++ trunk/Tools/ChangeLog	2020-08-04 19:06:47 UTC (rev 265254)
@@ -1,3 +1,20 @@
+2020-08-04  Jonathan Bedard  <jbed...@apple.com>
+
+        [webkitcorepy] Use setup.py for the autoinstaller
+        https://bugs.webkit.org/show_bug.cgi?id=215067
+        <rdar://problem/66432719>
+
+        Reviewed by Stephanie Lewis.
+
+        * Scripts/libraries/webkitcorepy/webkitcorepy/__init__.py: Add all requests dependencies.
+        * Scripts/libraries/webkitcorepy/webkitcorepy/autoinstall.py:
+        (Package.Archive__init__): Add extension, tar.gz by default.
+        (Package.Archive.path): Support multiple file types.
+        (Package.Archive.unpack): Support .zip files.
+        (Package.__init__): Add slow_install flag.
+        (Package.archives): Handle case were a library does not have a tiny version.
+        (Package.install): Call setup.py instead of just moving the library out of the package.
+
 2020-08-04  Hector Lopez  <hector_i_lo...@apple.com>
 
         Add myself to contributors.json

Modified: trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/__init__.py (265253 => 265254)


--- trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/__init__.py	2020-08-04 18:56:34 UTC (rev 265253)
+++ trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/__init__.py	2020-08-04 19:06:47 UTC (rev 265254)
@@ -21,6 +21,7 @@
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 import logging
+import platform
 import sys
 
 log = logging.getLogger('webkitcorepy')
@@ -28,13 +29,22 @@
 from webkitcorepy.version import Version
 from webkitcorepy.string_utils import BytesIO, StringIO, UnicodeIO, unicode
 
-version = Version(0, 0, 4)
+version = Version(0, 1, 0)
 
 from webkitcorepy.autoinstall import Package, AutoInstall
 if sys.version_info > (3, 0):
     AutoInstall.register(Package('mock', Version(4)))
+    AutoInstall.register(Package('setuptools', Version(41, 2,  0)))
 else:
     AutoInstall.register(Package('mock', Version(3, 0, 5)))
+    AutoInstall.register(Package('setuptools', Version(41, 0, 1)))
+    if platform.system() == 'Windows':
+        AutoInstall.register(Package('win_inet_pton', Version(1, 1, 0), pypi_name='win-inet-pton'))
 
 AutoInstall.register(Package('certifi', Version(2020, 6, 20)))
+AutoInstall.register(Package('chardet', Version(3, 0, 4)))
+AutoInstall.register(Package('funcsigs', Version(1, 0, 2)))
+AutoInstall.register(Package('idna', Version(2, 10)))
 AutoInstall.register(Package('requests', Version(2, 24)))
+AutoInstall.register(Package('socks', Version(1, 7, 1), pypi_name='PySocks'))
+AutoInstall.register(Package('urllib3', Version(1, 25, 10)))

Modified: trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/autoinstall.py (265253 => 265254)


--- trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/autoinstall.py	2020-08-04 18:56:34 UTC (rev 265253)
+++ trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/autoinstall.py	2020-08-04 19:06:47 UTC (rev 265254)
@@ -24,9 +24,11 @@
 import math
 import os
 import re
+import subprocess
 import shutil
 import sys
 import tarfile
+import zipfile
 
 from webkitcorepy import log
 from webkitcorepy.version import Version
@@ -40,10 +42,11 @@
 
 class Package(object):
     class Archive(object):
-        def __init__(self, name, link, version):
+        def __init__(self, name, link, version, extension=None):
             self.name = name
             self.link = link
             self.version = version
+            self.extension = extension or 'tar.gz'
 
         def __repr__(self):
             return '{}-{}.{}.{}'.format(self.name, self.version.major, self.version.minor, self.version.tiny)
@@ -52,7 +55,7 @@
         def path(self):
             if not AutoInstall.directory:
                 raise ValueError('No AutoInstall directory, archive cannot resolve local path')
-            return '{}/{}-{}.tar.gz'.format(AutoInstall.directory, self.name, self.version)
+            return '{}/{}-{}.{}'.format(AutoInstall.directory, self.name, self.version, self.extension)
 
         def download(self):
             response = AutoInstall._request(self.link)
@@ -72,17 +75,25 @@
             if not os.path.isfile(self.path):
                 raise IOError('Failed to find archive at {}'.format(self.path))
             shutil.rmtree(target, ignore_errors=True)
-            file = tarfile.open(self.path)
-            try:
-                file.extractall(target)
-            finally:
-                file.close()
 
-    def __init__(self, name, version=None, pypi_name=None):
+            if self.extension == 'tar.gz':
+                file = tarfile.open(self.path)
+                try:
+                    file.extractall(target)
+                finally:
+                    file.close()
+            elif self.extension == 'zip':
+                with zipfile.ZipFile(self.path, 'r') as file:
+                    file.extractall(target)
+            else:
+                raise OSError('{} has an  unrecognized package format'.format(self.path))
+
+    def __init__(self, name, version=None, pypi_name=None, slow_install=False):
         self.name = name
         self.version = version
         self._archives = []
         self.pypi_name = pypi_name or self.name
+        self.slow_install = slow_install
 
     @property
     def location(self):
@@ -115,7 +126,12 @@
                     attributes[element.attributes.item(index).name] = element.attributes.item(index).value
                 if not attributes.get('href', None):
                     continue
-                if not element.childNodes[0].data.endswith('tar.gz'):
+
+                if element.childNodes[0].data.endswith('tar.gz'):
+                    extension = 'tar.gz'
+                elif element.childNodes[0].data.endswith('.zip'):
+                    extension = 'zip'
+                else:
                     continue
 
                 requires = attributes.get('data-requires-python')
@@ -122,7 +138,7 @@
                 if requires and not AutoInstall.version.matches(requires):
                     continue
 
-                version_candidate = re.search(r'\d+\.\d+\.\d+', element.childNodes[0].data)
+                version_candidate = re.search(r'\d+\.\d+(\.\d+)?', element.childNodes[0].data)
                 if not version_candidate:
                     continue
                 version = Version(*version_candidate.group().split('.'))
@@ -141,6 +157,7 @@
                     name=self.pypi_name,
                     link=link,
                     version=version,
+                    extension=extension,
                 ))
 
             self._archives = sorted(self._archives, key=lambda archive: archive.version)
@@ -163,11 +180,19 @@
         if self.is_cached():
             return
 
+        # Make sure that setuptools are installed, since setup.py relies on it
+        if self.name != 'setuptools':
+            AutoInstall.install('setuptools')
+
         if not self.archives():
             raise ValueError('No archives for {}-{} found'.format(self.pypi_name, self.version))
         archive = self.archives()[-1]
 
         try:
+            install_location = os.path.dirname(self.location)
+            shutil.rmtree(self.location, ignore_errors=True)
+            already_owned = set(os.listdir(install_location))
+
             log.warning('Installing {}...'.format(archive))
             archive.download()
 
@@ -174,15 +199,56 @@
             temp_location = '{}.tmp'.format(self.location)
             archive.unpack(temp_location)
 
-            shutil.rmtree(self.location, ignore_errors=True)
-            shutil.move(os.path.join(temp_location, str(archive), self.name), self.location)
+            for candidate in [
+                os.path.join(temp_location, str(archive)),
+                os.path.join(temp_location, '{}-{}.{}'.format(archive.name, archive.version.major, archive.version.minor)),
+            ]:
+                if not os.path.exists(os.path.join(candidate, 'setup.py')):
+                    continue
 
+                log.warning('Installing {}...'.format(archive))
+
+                if self.slow_install:
+                    log.warning('{} is known to be slow to install'.format(archive))
+
+                with open(os.devnull, 'w') as devnull:
+                    subprocess.check_call(
+                        [
+                            sys.executable,
+                            os.path.join(candidate, 'setup.py'),
+                            'install',
+                            '--home={}'.format(install_location),
+                            '--root=/',
+                            '--single-version-externally-managed',
+                            '--install-lib={}'.format(install_location),
+                            '--install-scripts={}'.format(install_location),
+                            '--install-data="" 'data')),
+                            '--install-headers={}'.format(os.path.join(install_location, 'headers')),
+                            # Do not automatically install package dependencies, force scripts to be explicit
+                            # Even without this flag, setup.py is not consistent about installing dependencies.
+                            '--old-and-unmanageable',
+                        ],
+                        cwd=candidate,
+                        env=dict(
+                            PATH=os.environ.get('PATH', ''),
+                            PATHEXT=os.environ.get('PATHEXT', ''),
+                            PYTHONPATH=install_location,
+                        ),
+                        stdout=devnull,
+                        stderr=devnull,
+                    )
+
+                break
+            else:
+                raise OSError('Cannot install {}, could not find setup.py'.format(self.name))
+
             self.do_post_install(temp_location)
 
             os.remove(archive.path)
             shutil.rmtree(temp_location, ignore_errors=True)
 
-            AutoInstall.userspace_should_own(self.location)
+            for installed in set(os.listdir(install_location)) - already_owned:
+                AutoInstall.userspace_should_own(os.path.join(install_location, installed))
 
             AutoInstall.manifest[self.name] = {
                 'index': AutoInstall.index,
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to