From 1ccf1cf29b73cc7d1817d90cda666a50ce7e4910 Mon Sep 17 00:00:00 2001 From: rdb Date: Wed, 30 Sep 2015 14:06:12 +0200 Subject: [PATCH] Port pdeploy to Python 3 --- direct/src/p3d/DeploymentTools.py | 107 +++++++++++++++++------------- direct/src/p3d/HostInfo.py | 23 +++---- direct/src/p3d/PackageInfo.py | 3 +- direct/src/stdpy/file.py | 15 +---- 4 files changed, 75 insertions(+), 73 deletions(-) diff --git a/direct/src/p3d/DeploymentTools.py b/direct/src/p3d/DeploymentTools.py index 880a32f7f5..7f18bd10e7 100644 --- a/direct/src/p3d/DeploymentTools.py +++ b/direct/src/p3d/DeploymentTools.py @@ -5,7 +5,7 @@ to build for as many platforms as possible. """ __all__ = ["Standalone", "Installer"] 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.showbase.AppRunnerGlobal import appRunner from panda3d.core import PandaSystem, HTTPClient, Filename, VirtualFileSystem, Multifile @@ -21,8 +21,8 @@ try: except ImportError: 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 # 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, # 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('>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.mtime = modtime controlinfo.size = controlfile.tell() @@ -820,33 +825,43 @@ class Installer: if output.exists(): output.unlink() debfile = open(output.toOsSpecific(), "wb") - debfile.write("!\x0A") - debfile.write("debian-binary %-12lu0 0 100644 %-10ld\x60\x0A" % (modtime, 4)) - debfile.write("2.0\x0A") + debfile.write(b"!\x0A") + pad_mtime = str(modtime).encode().ljust(12, b' ') - # Write the control.tar.gz to the archive. - debfile.write("control.tar.gz %-12lu0 0 100644 %-10ld\x60\x0A" % (modtime, 0)) + # 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() ctarfile = tarfile.open("control.tar.gz", "w:gz", debfile, tarinfo = TarInfoRoot) ctarfile.addfile(controlinfo, controlfile) ctarfile.close() 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() dtarfile = tarfile.open("data.tar.gz", "w:gz", debfile, tarinfo = TarInfoRoot) dtarfile.add(Filename(tempdir, "usr").toOsSpecific(), "/usr") dtarfile.close() dtarsize = debfile.tell() - dtaroffs - if (dtarsize & 1): debfile.write("\x0A") + if (dtarsize & 1): debfile.write(b"\x0A") # Write the correct sizes of the archives. debfile.seek(ctaroffs - 12) - debfile.write("%-10ld" % ctarsize) + debfile.write(str(ctarsize).encode().ljust(10, b' ')) debfile.seek(dtaroffs - 12) - debfile.write("%-10ld" % dtarsize) + debfile.write(str(dtarsize).encode().ljust(10, b' ')) debfile.close() @@ -873,18 +888,20 @@ class Installer: tempdir, totsize = self.__buildTempLinux(platform) # 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 != "": - print >>pkginfo, "license = %s" % self.licensename + pout.write(u"license = %s\n" % self.licensename) + pout.flush() pkginfoinfo = TarInfoRoot(".PKGINFO") pkginfoinfo.mtime = modtime pkginfoinfo.size = pkginfo.tell() diff --git a/direct/src/p3d/HostInfo.py b/direct/src/p3d/HostInfo.py index da5d9723c4..ad9942c6a0 100644 --- a/direct/src/p3d/HostInfo.py +++ b/direct/src/p3d/HostInfo.py @@ -513,18 +513,15 @@ class HostInfo: PackageInfo, returns it. """ 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: package = PackageInfo(self, name, version, platform = platform, solo = solo, asMirror = self.asMirror, perPlatform = perPlatform) - platforms[platform] = package + platforms[platform or ""] = package return package @@ -534,12 +531,12 @@ class HostInfo: platform, if one is provided by this host, or None if not. """ 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 # only. - return platforms.get(platform or None, None) + return platforms.get(platform, None) # We are looking for one matching the current runtime # 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 package: - package = platforms.get(None, None) + package = platforms.get("", None) return package @@ -564,7 +561,7 @@ class HostInfo: if name and pn != name: continue - if platform is None: + if not platform: for p2 in platforms: package = self.getPackage(pn, version, platform = p2) if package: @@ -596,7 +593,7 @@ class HostInfo: # current platform, or no particular platform. package = platforms.get(PandaSystem.getPlatform(), None) if not package: - package = platforms.get(None, None) + package = platforms.get("", None) if package: result.append(package) diff --git a/direct/src/p3d/PackageInfo.py b/direct/src/p3d/PackageInfo.py index b48392dd28..08a73365b8 100644 --- a/direct/src/p3d/PackageInfo.py +++ b/direct/src/p3d/PackageInfo.py @@ -523,7 +523,8 @@ class PackageInfo: # In case of unexpected failures on the internet, we will retry # 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[:]) pc.stop() diff --git a/direct/src/stdpy/file.py b/direct/src/stdpy/file.py index 463eb8639c..c7b198be50 100644 --- a/direct/src/stdpy/file.py +++ b/direct/src/stdpy/file.py @@ -15,6 +15,7 @@ import sys import os import io import encodings +from posixpath import join _vfs = core.VirtualFileSystem.getGlobalPtr() @@ -331,20 +332,6 @@ def walk(top, topdown = True, onerror = None, followlinks = True): if not topdown: 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): return _vfs.isRegularFile(core.Filename.fromOsSpecific(path))