Browse Source

Port pdeploy to Python 3

rdb 10 years ago
parent
commit
1ccf1cf29b

+ 63 - 46
direct/src/p3d/DeploymentTools.py

@@ -5,7 +5,7 @@ to build for as many platforms as possible. """
 __all__ = ["Standalone", "Installer"]
 __all__ = ["Standalone", "Installer"]
 
 
 import os, sys, subprocess, tarfile, shutil, time, zipfile, socket, getpass, struct
 import os, sys, subprocess, tarfile, shutil, time, zipfile, socket, getpass, struct
-from cStringIO import StringIO
+from io import BytesIO, TextIOWrapper
 from direct.directnotify.DirectNotifyGlobal import *
 from direct.directnotify.DirectNotifyGlobal import *
 from direct.showbase.AppRunnerGlobal import appRunner
 from direct.showbase.AppRunnerGlobal import appRunner
 from panda3d.core import PandaSystem, HTTPClient, Filename, VirtualFileSystem, Multifile
 from panda3d.core import PandaSystem, HTTPClient, Filename, VirtualFileSystem, Multifile
@@ -21,8 +21,8 @@ try:
 except ImportError:
 except ImportError:
     pwd = None
     pwd = None
 
 
-# Make sure this matches with the magic in p3dEmbed.cxx.
-P3DEMBED_MAGIC = "\xFF\x3D\x3D\x00"
+# Make sure this matches with the magic in p3dEmbedMain.cxx.
+P3DEMBED_MAGIC = 0xFF3D3D00
 
 
 # This filter function is used when creating
 # This filter function is used when creating
 # an archive that should be owned by root.
 # an archive that should be owned by root.
@@ -161,10 +161,10 @@ class Standalone:
 
 
         # Find the magic size string and replace it with the real size,
         # Find the magic size string and replace it with the real size,
         # regardless of the endianness of the p3dembed executable.
         # regardless of the endianness of the p3dembed executable.
-        hex_size = hex(size)[2:].rjust(8, "0")
-        enc_size = "".join([chr(int(hex_size[i] + hex_size[i + 1], 16)) for i in range(0, len(hex_size), 2)])
-        p3dembed_data = p3dembed_data.replace(P3DEMBED_MAGIC, enc_size)
-        p3dembed_data = p3dembed_data.replace(P3DEMBED_MAGIC[::-1], enc_size[::-1])
+        p3dembed_data = p3dembed_data.replace(struct.pack('>I', P3DEMBED_MAGIC),
+                                              struct.pack('>I', size))
+        p3dembed_data = p3dembed_data.replace(struct.pack('<I', P3DEMBED_MAGIC),
+                                              struct.pack('<I', size))
 
 
         # Write the output file
         # Write the output file
         Standalone.notify.info("Creating %s..." % output)
         Standalone.notify.info("Creating %s..." % output)
@@ -173,12 +173,15 @@ class Standalone:
         ohandle.write(p3dembed_data)
         ohandle.write(p3dembed_data)
 
 
         # Write out the tokens. Set log_basename to the basename by default
         # Write out the tokens. Set log_basename to the basename by default
-        tokens = {"log_basename" : self.basename}
+        tokens = {"log_basename": self.basename}
         tokens.update(self.tokens)
         tokens.update(self.tokens)
         tokens.update(extraTokens)
         tokens.update(extraTokens)
-        for token in tokens.items():
-            ohandle.write("\0%s=%s" % token)
-        ohandle.write("\0\0")
+        for key, value in tokens.items():
+            ohandle.write(b"\0")
+            ohandle.write(key.encode('ascii'))
+            ohandle.write(b"=")
+            ohandle.write(value.encode())
+        ohandle.write(b"\0\0")
 
 
         # Buffer the p3d file to the output file. 1 MB buffer size.
         # Buffer the p3d file to the output file. 1 MB buffer size.
         phandle = open(self.p3dfile.toOsSpecific(), "rb")
         phandle = open(self.p3dfile.toOsSpecific(), "rb")
@@ -394,7 +397,7 @@ class Icon:
         vfs = VirtualFileSystem.getGlobalPtr()
         vfs = VirtualFileSystem.getGlobalPtr()
         stream = vfs.openWriteFile(fn, False, True)
         stream = vfs.openWriteFile(fn, False, True)
         icns = open(stream, 'wb')
         icns = open(stream, 'wb')
-        icns.write('icns\0\0\0\0')
+        icns.write(b'icns\0\0\0\0')
 
 
         icon_types = {16: 'is32', 32: 'il32', 48: 'ih32', 128: 'it32'}
         icon_types = {16: 'is32', 32: 'il32', 48: 'ih32', 128: 'it32'}
         mask_types = {16: 's8mk', 32: 'l8mk', 48: 'h8mk', 128: 't8mk'}
         mask_types = {16: 's8mk', 32: 'l8mk', 48: 'h8mk', 128: 't8mk'}
@@ -407,7 +410,7 @@ class Icon:
                 if pngtype is None:
                 if pngtype is None:
                     continue
                     continue
                 icns.write(png_types[size])
                 icns.write(png_types[size])
-                icns.write('\0\0\0\0')
+                icns.write(b'\0\0\0\0')
                 start = icns.tell()
                 start = icns.tell()
 
 
                 image.write(stream, "", pngtype)
                 image.write(stream, "", pngtype)
@@ -800,16 +803,18 @@ class Installer:
         tempdir, totsize = self.__buildTempLinux(platform)
         tempdir, totsize = self.__buildTempLinux(platform)
 
 
         # Create a control file in memory.
         # Create a control file in memory.
-        controlfile = StringIO()
-        print >>controlfile, "Package: %s" % self.shortname.lower()
-        print >>controlfile, "Version: %s" % self.version
-        print >>controlfile, "Maintainer: %s <%s>" % (self.authorname, self.authoremail)
-        print >>controlfile, "Section: games"
-        print >>controlfile, "Priority: optional"
-        print >>controlfile, "Architecture: %s" % arch
-        print >>controlfile, "Installed-Size: %d" % -(-totsize / 1024)
-        print >>controlfile, "Description: %s" % self.fullname
-        print >>controlfile, "Depends: libc6, libgcc1, libstdc++6, libx11-6"
+        controlfile = BytesIO()
+        cout = TextIOWrapper(controlfile, encoding='utf-8', newline='')
+        cout.write(u"Package: %s\n" % self.shortname.lower())
+        cout.write(u"Version: %s\n" % self.version)
+        cout.write(u"Maintainer: %s <%s>\n" % (self.authorname, self.authoremail))
+        cout.write(u"Section: games\n")
+        cout.write(u"Priority: optional\n")
+        cout.write(u"Architecture: %s\n" % arch)
+        cout.write(u"Installed-Size: %d\n" % -(-totsize // 1024))
+        cout.write(u"Description: %s\n" % self.fullname)
+        cout.write(u"Depends: libc6, libgcc1, libstdc++6, libx11-6\n")
+        cout.flush()
         controlinfo = TarInfoRoot("control")
         controlinfo = TarInfoRoot("control")
         controlinfo.mtime = modtime
         controlinfo.mtime = modtime
         controlinfo.size = controlfile.tell()
         controlinfo.size = controlfile.tell()
@@ -820,33 +825,43 @@ class Installer:
         if output.exists():
         if output.exists():
             output.unlink()
             output.unlink()
         debfile = open(output.toOsSpecific(), "wb")
         debfile = open(output.toOsSpecific(), "wb")
-        debfile.write("!<arch>\x0A")
-        debfile.write("debian-binary   %-12lu0     0     100644  %-10ld\x60\x0A" % (modtime, 4))
-        debfile.write("2.0\x0A")
-
-        # Write the control.tar.gz to the archive.
-        debfile.write("control.tar.gz  %-12lu0     0     100644  %-10ld\x60\x0A" % (modtime, 0))
+        debfile.write(b"!<arch>\x0A")
+        pad_mtime = str(modtime).encode().ljust(12, b' ')
+
+        # The first entry is a special file that marks it a .deb.
+        debfile.write(b"debian-binary   ")
+        debfile.write(pad_mtime)
+        debfile.write(b"0     0     100644  4         \x60\x0A")
+        debfile.write(b"2.0\x0A")
+
+        # Write the control.tar.gz to the archive.  We'll leave the
+        # size 0 for now, and go back and fill it in later.
+        debfile.write(b"control.tar.gz  ")
+        debfile.write(pad_mtime)
+        debfile.write(b"0     0     100644  0         \x60\x0A")
         ctaroffs = debfile.tell()
         ctaroffs = debfile.tell()
         ctarfile = tarfile.open("control.tar.gz", "w:gz", debfile, tarinfo = TarInfoRoot)
         ctarfile = tarfile.open("control.tar.gz", "w:gz", debfile, tarinfo = TarInfoRoot)
         ctarfile.addfile(controlinfo, controlfile)
         ctarfile.addfile(controlinfo, controlfile)
         ctarfile.close()
         ctarfile.close()
         ctarsize = debfile.tell() - ctaroffs
         ctarsize = debfile.tell() - ctaroffs
-        if (ctarsize & 1): debfile.write("\x0A")
+        if (ctarsize & 1): debfile.write(b"\x0A")
 
 
-        # Write the data.tar.gz to the archive.
-        debfile.write("data.tar.gz     %-12lu0     0     100644  %-10ld\x60\x0A" % (modtime, 0))
+        # Write the data.tar.gz to the archive.  Again, leave size 0.
+        debfile.write(b"data.tar.gz     ")
+        debfile.write(pad_mtime)
+        debfile.write(b"0     0     100644  0         \x60\x0A")
         dtaroffs = debfile.tell()
         dtaroffs = debfile.tell()
         dtarfile = tarfile.open("data.tar.gz", "w:gz", debfile, tarinfo = TarInfoRoot)
         dtarfile = tarfile.open("data.tar.gz", "w:gz", debfile, tarinfo = TarInfoRoot)
         dtarfile.add(Filename(tempdir, "usr").toOsSpecific(), "/usr")
         dtarfile.add(Filename(tempdir, "usr").toOsSpecific(), "/usr")
         dtarfile.close()
         dtarfile.close()
         dtarsize = debfile.tell() - dtaroffs
         dtarsize = debfile.tell() - dtaroffs
-        if (dtarsize & 1): debfile.write("\x0A")
+        if (dtarsize & 1): debfile.write(b"\x0A")
 
 
         # Write the correct sizes of the archives.
         # Write the correct sizes of the archives.
         debfile.seek(ctaroffs - 12)
         debfile.seek(ctaroffs - 12)
-        debfile.write("%-10ld" % ctarsize)
+        debfile.write(str(ctarsize).encode().ljust(10, b' '))
         debfile.seek(dtaroffs - 12)
         debfile.seek(dtaroffs - 12)
-        debfile.write("%-10ld" % dtarsize)
+        debfile.write(str(dtarsize).encode().ljust(10, b' '))
 
 
         debfile.close()
         debfile.close()
 
 
@@ -873,18 +888,20 @@ class Installer:
         tempdir, totsize = self.__buildTempLinux(platform)
         tempdir, totsize = self.__buildTempLinux(platform)
 
 
         # Create a pkginfo file in memory.
         # Create a pkginfo file in memory.
-        pkginfo = StringIO()
-        print >>pkginfo, "# Generated using pdeploy"
-        print >>pkginfo, "# %s" % time.ctime(modtime)
-        print >>pkginfo, "pkgname = %s" % self.shortname.lower()
-        print >>pkginfo, "pkgver = %s" % pkgver
-        print >>pkginfo, "pkgdesc = %s" % self.fullname
-        print >>pkginfo, "builddate = %s" % modtime
-        print >>pkginfo, "packager = %s <%s>" % (self.authorname, self.authoremail)
-        print >>pkginfo, "size = %d" % totsize
-        print >>pkginfo, "arch = %s" % arch
+        pkginfo = BytesIO()
+        pout = TextIOWrapper(pkginfo, encoding='utf-8', newline='')
+        pout.write(u"# Generated using pdeploy\n")
+        pout.write(u"# %s\n" % time.ctime(modtime))
+        pout.write(u"pkgname = %s\n" % self.shortname.lower())
+        pout.write(u"pkgver = %s\n" % pkgver)
+        pout.write(u"pkgdesc = %s\n" % self.fullname)
+        pout.write(u"builddate = %s\n" % modtime)
+        pout.write(u"packager = %s <%s>\n" % (self.authorname, self.authoremail))
+        pout.write(u"size = %d\n" % totsize)
+        pout.write(u"arch = %s\n" % arch)
         if self.licensename != "":
         if self.licensename != "":
-            print >>pkginfo, "license = %s" % self.licensename
+            pout.write(u"license = %s\n" % self.licensename)
+        pout.flush()
         pkginfoinfo = TarInfoRoot(".PKGINFO")
         pkginfoinfo = TarInfoRoot(".PKGINFO")
         pkginfoinfo.mtime = modtime
         pkginfoinfo.mtime = modtime
         pkginfoinfo.size = pkginfo.tell()
         pkginfoinfo.size = pkginfo.tell()

+ 10 - 13
direct/src/p3d/HostInfo.py

@@ -513,18 +513,15 @@ class HostInfo:
         PackageInfo, returns it. """
         PackageInfo, returns it. """
 
 
         if not platform:
         if not platform:
-            # Ensure that we're on the same page with non-specified
-            # platforms.  We have to use the empty string, not None,
-            # since Python 3 can't sort lists with both strings and None.
-            platform = ""
+            platform = None
 
 
-        platforms = self.packages.setdefault((name, version), {})
-        package = platforms.get(platform, None)
+        platforms = self.packages.setdefault((name, version or ""), {})
+        package = platforms.get("", None)
         if not package:
         if not package:
             package = PackageInfo(self, name, version, platform = platform,
             package = PackageInfo(self, name, version, platform = platform,
                                   solo = solo, asMirror = self.asMirror,
                                   solo = solo, asMirror = self.asMirror,
                                   perPlatform = perPlatform)
                                   perPlatform = perPlatform)
-            platforms[platform] = package
+            platforms[platform or ""] = package
 
 
         return package
         return package
 
 
@@ -534,12 +531,12 @@ class HostInfo:
         platform, if one is provided by this host, or None if not. """
         platform, if one is provided by this host, or None if not. """
 
 
         assert self.hasContentsFile
         assert self.hasContentsFile
-        platforms = self.packages.get((name, version or None), {})
+        platforms = self.packages.get((name, version or ""), {})
 
 
-        if platform is not None:
+        if platform:
             # In this case, we are looking for a specific platform
             # In this case, we are looking for a specific platform
             # only.
             # only.
-            return platforms.get(platform or None, None)
+            return platforms.get(platform, None)
 
 
         # We are looking for one matching the current runtime
         # We are looking for one matching the current runtime
         # platform.  First, look for a package matching the current
         # platform.  First, look for a package matching the current
@@ -548,7 +545,7 @@ class HostInfo:
 
 
         # If not found, look for one matching no particular platform.
         # If not found, look for one matching no particular platform.
         if not package:
         if not package:
-            package = platforms.get(None, None)
+            package = platforms.get("", None)
 
 
         return package
         return package
 
 
@@ -564,7 +561,7 @@ class HostInfo:
             if name and pn != name:
             if name and pn != name:
                 continue
                 continue
 
 
-            if platform is None:
+            if not platform:
                 for p2 in platforms:
                 for p2 in platforms:
                     package = self.getPackage(pn, version, platform = p2)
                     package = self.getPackage(pn, version, platform = p2)
                     if package:
                     if package:
@@ -596,7 +593,7 @@ class HostInfo:
                 # current platform, or no particular platform.
                 # current platform, or no particular platform.
                 package = platforms.get(PandaSystem.getPlatform(), None)
                 package = platforms.get(PandaSystem.getPlatform(), None)
                 if not package:
                 if not package:
-                    package = platforms.get(None, None)
+                    package = platforms.get("", None)
 
 
                 if package:
                 if package:
                     result.append(package)
                     result.append(package)

+ 2 - 1
direct/src/p3d/PackageInfo.py

@@ -523,7 +523,8 @@ class PackageInfo:
 
 
         # In case of unexpected failures on the internet, we will retry
         # In case of unexpected failures on the internet, we will retry
         # the full download instead of just giving up.
         # the full download instead of just giving up.
-        for retry in range(core.ConfigVariableInt('package-full-dl-retries', 1)):
+        retries = core.ConfigVariableInt('package-full-dl-retries', 1).getValue()
+        for retry in range(retries):
             self.installPlans.append(planB[:])
             self.installPlans.append(planB[:])
 
 
         pc.stop()
         pc.stop()

+ 1 - 14
direct/src/stdpy/file.py

@@ -15,6 +15,7 @@ import sys
 import os
 import os
 import io
 import io
 import encodings
 import encodings
+from posixpath import join
 
 
 _vfs = core.VirtualFileSystem.getGlobalPtr()
 _vfs = core.VirtualFileSystem.getGlobalPtr()
 
 
@@ -331,20 +332,6 @@ def walk(top, topdown = True, onerror = None, followlinks = True):
     if not topdown:
     if not topdown:
         yield (top, dirnames, filenames)
         yield (top, dirnames, filenames)
 
 
-def join(path, *args):
-    for part in args:
-        if part == '':
-            continue
-
-        if part.startswith('/'):
-            path = part
-        elif path.endswith('/'):
-            path = path + part
-        else:
-            path = '/'.join((path, part))
-
-    return path
-
 def isfile(path):
 def isfile(path):
     return _vfs.isRegularFile(core.Filename.fromOsSpecific(path))
     return _vfs.isRegularFile(core.Filename.fromOsSpecific(path))