Last active
October 13, 2017 01:55
-
-
Save gfixler/b5c405e182ceb9ced70e91a47ed3e8c5 to your computer and use it in GitHub Desktop.
Maya Github Python project bootstrapping script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
Maya Python Github project bootstrapping script | |
Makes particular Maya Python Github project releases available in Maya via the | |
user script dir. Pass user, project, and release strings to getGithubRelease, | |
which will download the zip file to the user script dir, and unzip it in there | |
(if it doesn't yet exist). Returns the full path to the unzipped project | |
folder, which can be used to modify sys.path[1], circumventing installation. | |
Note: you still need to ensure all tools deal with one version of the project, | |
but this makes it easy to throw a call to the latest version in a startup file | |
to ensure the latest version is fetched and on the path each session[2]. | |
[1] this allows for standard "import <projectname>" semantics | |
[2] downside: tool versions will have no history of this dependency | |
''' | |
import os, sys | |
import urllib | |
import urllib2 | |
import zipfile | |
import maya.cmds as cmds | |
def ensurePath (path): | |
''' | |
Prepends given path to sys.path, if not already in sys.path (idempotent) | |
''' | |
if path not in sys.path: | |
sys.path.insert(0, path) | |
def getGithubRelease (user, project, release): | |
''' | |
Given user, project, and release, all taken from the Github release[1]: | |
1. downloads release zip to Maya user scripts dir (if missing) | |
2. unzips project to its own folder in user scripts dir (if missing) | |
Returns unzipped project folder path (which you can put on sys.path if needed) | |
[1] from the Github "Clone or download" ZIP link for a given branch or tag | |
e.g. for the following tagged release: | |
https://github.com/LumaPictures/pymel/archive/1.0.3.zip | |
pass these arguments: | |
user = "LumaPictures" | |
project = "pymel" | |
release = "1.0.3.zip" | |
''' | |
# set up remote and local paths | |
remotePath = "https://github.com/%s/%s/archive/%s.zip" % (user, project, release) | |
scriptsDir = cmds.internalVar(userScriptDir=True) | |
localZipPath = scriptsDir + project + "-" + release + ".zip" | |
# Note: This process is screwy; the only way to build up the impending, | |
# unzipped project path string, which is not tied to the zip name at all, | |
# is to query the zip for its root entry, and append it to the target path. | |
# if release zip doesn't exist in the scripts dir, retrieve it from Github | |
if not os.path.exists(localZipPath): | |
print ("retrieving " + remotePath) | |
# open zip URL just to see if we can; will error out if we can't | |
u = urllib2.urlopen(remotePath) | |
u.close() | |
# actually retrieve zip | |
urllib.urlretrieve(remotePath, localZipPath) | |
# the release zip should exist locally at this point | |
if not os.path.exists(localZipPath): | |
raise RuntimeError("Could not retrieve " + project + " zip from Github.") | |
# grab a handle to the zip file | |
z = zipfile.ZipFile(localZipPath) | |
# get the list of root entries in the zip; there must be only 1 | |
# (zip's spec guarantees '/' separators internally for Amiga/Unix compatibility) | |
roots = list(set(map(lambda x: x.split('/')[0], z.namelist()))) | |
if len(roots) != 1: | |
raise RuntimeError("must have exactly 1 root: " + localZipPath) | |
projDirName = roots[0] | |
# actual unzipping | |
try: | |
# unzip the file to the user scripts dir and close the handle | |
z.extractall(scriptsDir) | |
z.close() | |
except zipfile.BadZipfile: | |
z.close() | |
# decided against deleting here, so the bad zip could be analyzed | |
raise RuntimeError("Bad zip file: " + localZipPath) | |
# assemble the presumed path to our unzipped project folder | |
localProjDir = scriptsDir + projDirName | |
# check that the unzipped folder exists | |
if not os.path.isdir(localProjDir): | |
raise RuntimeError("Could not find project path: " + localProjDir) | |
# return path to project (for use in sys.path) | |
return localProjDir |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment