diff --git a/patch_version.py b/patch_version.py index 39a1ce3..d6ec377 100644 --- a/patch_version.py +++ b/patch_version.py @@ -8,7 +8,7 @@ def patch_installer(tag): conda_file = "speckle_arcgis_installer/conda_clone_activate.py" #toolbox_install_file = "speckle_arcgis_installer/toolbox_install.py" toolbox_manual_install_file = "speckle_arcgis_installer/toolbox_install_manual.py" - plugin_start_file = "speckle_toolbox/esri/toolboxes/speckle/speckle_arcgis.py" + plugin_start_file = "speckle_toolbox/esri/toolboxes/speckle/speckle/speckle_arcgis.py" #py_tag = get_specklepy_version() with open(iss_file, "r") as file: diff --git a/setup.py b/setup.py index cc01fef..df81e27 100644 --- a/setup.py +++ b/setup.py @@ -1,39 +1,54 @@ -# to build an installer: run cmd from this folder or use terminal: "%PROGRAMFILES%\\ArcGIS\\Pro\\bin\\Python\\envs\\arcgispro-py3\\python.exe" -# -# 1) python patch_version.py 2.x.x -# 2) python setup.py sdist bdist_wheel #C:\\Users\\username\\Documents\\00_Speckle\\GitHub\\speckle-arcgis\\setup.py sdist bdist_wheel -# copy .whl from "dist" to "speckle_arcgis_installer" +# to build an installer: run cmd from this folder or use terminal: "%PROGRAMFILES%\\ArcGIS\\Pro\\bin\\Python\\envs\\arcgispro-py3\\python.exe" +# +# 1) python patch_version.py 2.x.x +# 2) python setup.py sdist bdist_wheel #C:\\Users\\username\\Documents\\00_Speckle\\GitHub\\speckle-arcgis\\setup.py sdist bdist_wheel +# copy .whl from "dist" to "speckle_arcgis_installer" # ref: https://pro.arcgis.com/en/pro-app/2.8/arcpy/geoprocessing_and_python/distributing-python-modules.htm -import os -from setuptools import setup +import os +from setuptools import setup -def read(fname): - return open(os.path.join(os.path.dirname(__file__), fname)).read() - -setup(name='speckle_toolbox', - author='SpeckleSystems', - version="2.9.4", - author_email="connectors@speckle.systems", - url="https://speckle.systems/", - description=("Example for extending geoprocessing through Python modules"), - long_description=read('Readme.md'), - python_requires='~=3.3', - setup_requires=['wheel'], - packages=['speckle_toolbox'], - package_data={'speckle_toolbox':[ - 'esri/arcpy/*', - 'esri/help/gp/*', 'esri/help/gp/toolboxes/*', 'esri/help/gp/messages/*', - 'esri/toolboxes/*','esri/toolboxes/speckle/*', - 'esri/toolboxes/speckle/converter/*', 'esri/toolboxes/speckle/converter/geometry/*', 'esri/toolboxes/speckle/converter/layers/*', 'esri/toolboxes/speckle/converter/features/*', - 'esri/toolboxes/speckle/plugin_utils/*', - 'esri/toolboxes/speckle/ui/*'] - }, - ) +def read(fname): + return open(os.path.join(os.path.dirname(__file__), fname)).read() + + +setup( + name="speckle_toolbox", + author="SpeckleSystems", + version="2.9.9", + author_email="connectors@speckle.systems", + url="https://speckle.systems/", + description=("Example for extending geoprocessing through Python modules"), + long_description=read("Readme.md"), + python_requires="~=3.3", + setup_requires=["wheel"], + packages=["speckle_toolbox"], + package_data={ + "speckle_toolbox": [ + "esri/arcpy/*", + "esri/help/gp/*", + "esri/help/gp/toolboxes/*", + "esri/help/gp/messages/*", + "esri/toolboxes/*", + "esri/toolboxes/speckle/*", + "esri/toolboxes/speckle/plugin_utils/*", + "esri/toolboxes/speckle/speckle/*", + "esri/toolboxes/speckle/speckle/converter/*", + "esri/toolboxes/speckle/speckle/converter/features/*", + "esri/toolboxes/speckle/speckle/converter/geometry/*", + "esri/toolboxes/speckle/speckle/converter/layers/*", + "esri/toolboxes/speckle/speckle/plugin_utils/*", + "esri/toolboxes/speckle/speckle/utils/*", + "esri/toolboxes/speckle/specklepy_qt_ui/*", + "esri/toolboxes/speckle/ui/*", + "esri/toolboxes/speckle/ui_widgets/*", + ] + }, +) # then to install in ArcGIS: # import sysconfig; import subprocess; x = sysconfig.get_paths()['data'] + r"\python.exe"; subprocess.run((x, '-m','pip', 'install', 'C:\\Users\\username\\Documents\\00_Speckle\\GitHub\\speckle-arcgis\\dist\\foo-0.1-py3-none-any.whl'), capture_output=True, text=True, shell=True, timeout=1000 ) -# to uninstall: +# to uninstall: # "C:\\Users\\username\\AppData\\Local\\ESRI\\conda\\envs\\arcgispro-py3-speckle\\python.exe" -m pip uninstall C:\\Users\\username\\Documents\\00_Speckle\\GitHub\\speckle-arcgis\\dist\\foo-0.1-py3-none-any.whl diff --git a/speckle_arcgis_installer/conda_clone_activate.py b/speckle_arcgis_installer/conda_clone_activate.py index d03cf11..3c22ab0 100644 --- a/speckle_arcgis_installer/conda_clone_activate.py +++ b/speckle_arcgis_installer/conda_clone_activate.py @@ -1,4 +1,4 @@ -# clone env, install toolbox & dependencies into the cloned env; and into current one (if not default) +# clone env, install toolbox & dependencies into the cloned env; and into current one (if not default) import sys import sysconfig import os.path @@ -12,80 +12,139 @@ import sys ENV_NEW_NAME = "arcgispro-py3-speckle" + def setup(): - pythonExec = get_python_path() # import numpy; import os; print(os.path.abspath(numpy.__file__)) - return pythonExec # None if not successful - + pythonExec = ( + get_python_path() + ) # import numpy; import os; print(os.path.abspath(numpy.__file__)) + return pythonExec # None if not successful + + def get_default_python(): - pythonExec = os.environ["ProgramFiles"] + r'\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\python.exe' #(r"%PROGRAMFILES%\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\python.exe") #os.path.dirname(sys.executable) + "\\python.exe" # default python.exe - #print(pythonExec) + pythonExec = ( + os.environ["ProgramFiles"] + + r"\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\python.exe" + ) # (r"%PROGRAMFILES%\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\python.exe") #os.path.dirname(sys.executable) + "\\python.exe" # default python.exe + # print(pythonExec) if not os.path.exists(pythonExec): - pythonExec = os.getenv('APPDATA').replace("Roaming", "Local") + r'\Programs\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\python.exe' - if not os.path.exists(pythonExec): return None + pythonExec = ( + os.getenv("APPDATA").replace("Roaming", "Local") + + r"\Programs\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\python.exe" + ) + if not os.path.exists(pythonExec): + return None return pythonExec -def get_python_path(): # create a full copy of default env - #print("Get Python path") + +def get_python_path(): # create a full copy of default env + # print("Get Python path") # or: import site; site.getsitepackages()[0] # import specklepy; import os; print(os.path.abspath(specklepy.__file__)) ##currentPythonExec = sysconfig.get_paths()['data'] + r"\python.exe" def_exec = get_default_python() - #print(os.getenv('APPDATA') + r'\Programs\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\python.exe') + # print(os.getenv('APPDATA') + r'\Programs\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\python.exe') if sys.platform == "win32": - newExec = clone_env(def_exec) # only if doesn't exist yet - if not os.path.exists(newExec): return None - + newExec = clone_env(def_exec) # only if doesn't exist yet + if not os.path.exists(newExec): + return None + activate_env() return newExec - else: return None + else: + return None -def clone_env(pythonExec_old: str): - install_folder = os.getenv('APPDATA').replace("\\Roaming","") + r"\Local\ESRI\conda\envs" #r"%LOCALAPPDATA%\ESRI\conda\envs" - if not os.path.exists(install_folder): os.makedirs(install_folder) - - default_env = pythonExec_old.replace("Pro\\bin\\Python\\envs\\arcgispro-py3\\python.exe","Pro\\bin\\Python\\envs\\arcgispro-py3") # + "\\" + 'arcgispro-py3' - conda_exe = pythonExec_old.replace("Pro\\bin\\Python\\envs\\arcgispro-py3\\python.exe","Pro\\bin\\Python\\Scripts\\conda.exe") #%PROGRAMFILES%\ArcGIS\Pro\bin\Python\Scripts\conda.exe #base: %PROGRAMDATA%\Anaconda3\condabin\conda.bat - new_env = install_folder + "\\" + ENV_NEW_NAME # %LOCALAPPDATA%\ESRI\conda\envs\... - if os.path.exists(conda_exe) and os.path.exists(default_env) and os.path.exists(new_env) and not os.path.exists(new_env + "\\python.exe"): - # conda environment invalid: delete it's folder +def clone_env(pythonExec_old: str): + install_folder = ( + os.getenv("APPDATA").replace("\\Roaming", "") + r"\Local\ESRI\conda\envs" + ) # r"%LOCALAPPDATA%\ESRI\conda\envs" + if not os.path.exists(install_folder): + os.makedirs(install_folder) + + default_env = pythonExec_old.replace( + "Pro\\bin\\Python\\envs\\arcgispro-py3\\python.exe", + "Pro\\bin\\Python\\envs\\arcgispro-py3", + ) # + "\\" + 'arcgispro-py3' + conda_exe = pythonExec_old.replace( + "Pro\\bin\\Python\\envs\\arcgispro-py3\\python.exe", + "Pro\\bin\\Python\\Scripts\\conda.exe", + ) # %PROGRAMFILES%\ArcGIS\Pro\bin\Python\Scripts\conda.exe #base: %PROGRAMDATA%\Anaconda3\condabin\conda.bat + new_env = install_folder + "\\" + ENV_NEW_NAME # %LOCALAPPDATA%\ESRI\conda\envs\... + + # first check if venv invalid: + if ( + os.path.exists(conda_exe) + and os.path.exists(default_env) + and os.path.exists(new_env) + ): + # delete existing venv print(f"Removing invalid environment {new_env}") os.remove(new_env) - - if os.path.exists(conda_exe) and os.path.exists(default_env) and not os.path.exists(new_env): + elif ( + os.path.exists(conda_exe) + and os.path.exists(default_env) + and not os.path.exists(new_env) + ): print("Wait for the default ArcGIS Pro conda environment to be cloned") - subprocess_call( [ conda_exe, 'config', '--set', 'ssl_verify', 'False'] ) - subprocess_call( [ conda_exe, 'create', '--clone', default_env, '-p', new_env] ) # will not execute if already exists - subprocess_call( [ conda_exe, 'config', '--set', 'ssl_verify', 'True'] ) + subprocess_call([conda_exe, "config", "--set", "ssl_verify", "False"]) + subprocess_call( + [conda_exe, "create", "--clone", default_env, "-p", new_env] + ) # will not execute if already exists + subprocess_call([conda_exe, "config", "--set", "ssl_verify", "True"]) - elif os.path.exists(new_env) and os.path.exists(new_env + "\\python.exe"): - print(f"Environment {new_env} already exists, preparing to install packages..") + r""" + # repair venv: https://pro.arcgis.com/en/pro-app/3.1/arcpy/get-started/repair-an-environment.htm + # upgrade venv with conda: https://pro.arcgis.com/en/pro-app/3.1/arcpy/get-started/upgrade-an-environment.htm + elif ( + os.path.exists(conda_exe) + and os.path.exists(default_env) + and os.path.exists(new_env) + and os.path.exists(new_env + "\\python.exe") + ): + print(f"Environment {new_env} already exists, upgrading ..") + subprocess_call([conda_exe, "proup", "-n", ENV_NEW_NAME]) + """ + # final check + if os.path.exists(new_env) and os.path.exists(new_env + "\\python.exe"): + print("Preparing to install packages..") print(new_env + "\\python.exe") return new_env + "\\python.exe" + def activate_env(): - # using Popen, because process does not return result; subprocess.run will hang indefinitely - variable = subprocess.Popen((f'proswap {ENV_NEW_NAME}'),stdout = subprocess.PIPE,stderr = subprocess.PIPE,text = True,shell = True) + # using Popen, because process does not return result; subprocess.run will hang indefinitely + variable = subprocess.Popen( + (f"proswap {ENV_NEW_NAME}"), + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + shell=True, + ) # activate new env : https://support.esri.com/en/technical-article/000024206 def installToolbox(newExec: str): print("Installing Speckle Toolbox") - whl_file = os.path.join(os.path.dirname(__file__), "speckle_toolbox-2.9.4-py3-none-any.whl" ) + whl_file = os.path.join( + os.path.dirname(__file__), "speckle_toolbox-2.9.9-py3-none-any.whl" + ) print(whl_file) - subprocess_call([newExec, '-m','pip','install','--upgrade', '--force-reinstall', whl_file]) + subprocess_call( + [newExec, "-m", "pip", "install", "--upgrade", "--force-reinstall", whl_file] + ) # to uninstall: cmd.exe "X:\\xxx.whl return + def clearToolbox(pythonExec: str): # install pip print("CLEAR toolbox") print(pythonExec) try: - - speckle_path = pythonExec.replace("python.exe","Lib\\site-packages\\") - + + speckle_path = pythonExec.replace("python.exe", "Lib\\site-packages\\") + print(speckle_path) paths = os.listdir(speckle_path) for p in paths: @@ -96,77 +155,74 @@ def clearToolbox(pythonExec: str): print(e) pass + def installDependencies(pythonExec: str, pkgName: str, pkgVersion: str): # install pip print(pythonExec) try: import pip except: - getPipFilePath = os.path.join(os.path.dirname(__file__), "get_pip.py") #TODO: give actual folder path + getPipFilePath = os.path.join( + os.path.dirname(__file__), "get_pip.py" + ) # TODO: give actual folder path exec(open(getPipFilePath).read()) # just in case the included version is old subprocess_call([pythonExec, "-m", "pip", "install", "--upgrade", "pip"]) - + # install package try: - #import importlib #importlib.import_module(pkgName) + # import importlib #importlib.import_module(pkgName) if pkgName == "specklepy": - import specklepy - if pythonExec.replace("\\python.exe","") not in (os.path.abspath(specklepy.__file__)): + import specklepy + + if pythonExec.replace("\\python.exe", "") not in ( + os.path.abspath(specklepy.__file__) + ): print(f"Installing {pkgName} to {pythonExec}") - #subprocess_call( [pythonExec, "-m", "pip", "uninstall", f"{pkgName}"]) - subprocess_call( [pythonExec, "-m", "pip", "install", f"{pkgName}=={pkgVersion}"]) + # subprocess_call( [pythonExec, "-m", "pip", "uninstall", f"{pkgName}"]) + subprocess_call( + [pythonExec, "-m", "pip", "install", f"{pkgName}=={pkgVersion}"] + ) elif pkgName == "panda3d": - import panda3d - if pythonExec.replace("\\python.exe","") not in (os.path.abspath(panda3d.__file__)): + import panda3d + + if pythonExec.replace("\\python.exe", "") not in ( + os.path.abspath(panda3d.__file__) + ): print(f"Installing {pkgName} to {pythonExec}") - subprocess_call( [pythonExec, "-m", "pip", "install", f"{pkgName}=={pkgVersion}"]) + subprocess_call( + [pythonExec, "-m", "pip", "install", f"{pkgName}=={pkgVersion}"] + ) elif pkgName == "PyQt5": - import PyQt5 - if pythonExec.replace("\\python.exe","") not in (os.path.abspath(PyQt5.__file__)): + import PyQt5 + + if pythonExec.replace("\\python.exe", "") not in ( + os.path.abspath(PyQt5.__file__) + ): print(f"Installing {pkgName} to {pythonExec}") - subprocess_call( [pythonExec, "-m", "pip", "install", f"{pkgName}=={pkgVersion}"]) + subprocess_call( + [pythonExec, "-m", "pip", "install", f"{pkgName}=={pkgVersion}"] + ) except Exception as e: print(f"{pkgName} not installed") - subprocess_call( [pythonExec, "-m", "pip", "install", f"{pkgName}=={pkgVersion}"]) - - # Check if package needs updating - r''' - try: - print(f"Attempting to update {pkgName} to {pkgVersion}") - result = subprocess_call( - [ - pythonExec, - "-m", - "pip", - "install", - "--upgrade", - f"{pkgName}=={pkgVersion}", - ] + subprocess_call( + [pythonExec, "-m", "pip", "install", f"{pkgName}=={pkgVersion}"] ) - if result == True: - print(f"{pkgName} upgraded") - return True - else: - return False - except Exception as e: - print(e) - print(e.with_traceback) - ''' return True - + + pythonPath = setup() print(pythonPath) if pythonPath is not None: - #def_exec = get_default_python() - #conda_exe = def_exec.replace("Pro\\bin\\Python\\envs\\arcgispro-py3\\python.exe","Pro\\bin\\Python\\Scripts\\conda.exe") #%PROGRAMFILES%\ArcGIS\Pro\bin\Python\Scripts\conda.exe #base: %PROGRAMDATA%\Anaconda3\condabin\conda.bat - #subprocess_call([conda_exe, 'proup','-n', ENV_NEW_NAME]) - + # def_exec = get_default_python() + # conda_exe = def_exec.replace("Pro\\bin\\Python\\envs\\arcgispro-py3\\python.exe","Pro\\bin\\Python\\Scripts\\conda.exe") #%PROGRAMFILES%\ArcGIS\Pro\bin\Python\Scripts\conda.exe #base: %PROGRAMDATA%\Anaconda3\condabin\conda.bat + # subprocess_call([conda_exe, 'proup','-n', ENV_NEW_NAME]) + clearToolbox(pythonPath) installToolbox(pythonPath) - installDependencies(pythonPath, "specklepy", "2.17.12" ) - installDependencies(pythonPath, "panda3d", "1.10.11" ) - installDependencies(pythonPath, "PyQt5", "5.15.9" ) + installDependencies(pythonPath, "specklepy", "2.17.17") + installDependencies(pythonPath, "panda3d", "1.10.11") + installDependencies(pythonPath, "PyQt5", "5.15.9") # manual: import sysconfig; import subprocess; x = sysconfig.get_paths()['data'] + r"\python.exe"; subprocess.run((x, "-m", "pip", "install", "PyQt5==5.15.9"), capture_output=True, text=True, shell=True, timeout=1000 ) diff --git a/speckle_arcgis_installer/speckle_toolbox-2.9.9-py3-none-any.whl b/speckle_arcgis_installer/speckle_toolbox-2.9.9-py3-none-any.whl new file mode 100644 index 0000000..6cf9502 Binary files /dev/null and b/speckle_arcgis_installer/speckle_toolbox-2.9.9-py3-none-any.whl differ diff --git a/speckle_arcgis_installer/toolbox_install_manual.py b/speckle_arcgis_installer/toolbox_install_manual.py index 3fc8431..21a3424 100644 --- a/speckle_arcgis_installer/toolbox_install_manual.py +++ b/speckle_arcgis_installer/toolbox_install_manual.py @@ -20,7 +20,7 @@ def installToolbox(newExec: str): onlyfiles = [f for f in listdir(mypath) if (isfile(join(mypath, f)) and "py3-none-any.whl" in str(f))] onlyfiles.sort(key = lambda x: int(x.replace("speckle_toolbox-","").replace("-py3-none-any.whl","").split(".")[1]) ) whl_file = mypath + "\\" + onlyfiles[len(onlyfiles)-1] - #whl_file = os.path.join(os.path.dirname(__file__), "speckle_toolbox-2.11.3-py3-none-any.whl" ) + #whl_file = os.path.join(os.path.dirname(__file__), "speckle_toolbox-2.9.9-py3-none-any.whl" ) subprocess_call([newExec, '-m','pip','install','--upgrade', '--force-reinstall', whl_file]) return diff --git a/speckle_toolbox/esri/toolboxes/speckle/speckle/speckle_arcgis.py b/speckle_toolbox/esri/toolboxes/speckle/speckle/speckle_arcgis.py index a8a44e0..563eb5c 100644 --- a/speckle_toolbox/esri/toolboxes/speckle/speckle/speckle_arcgis.py +++ b/speckle_toolbox/esri/toolboxes/speckle/speckle/speckle_arcgis.py @@ -182,7 +182,7 @@ class SpeckleGIS: def __init__(self): """Constructor.""" print("Start SpeckleGIS") - self.version = "0.0.99" + self.version = "2.9.9" try: version = arcpy.GetInstallInfo()["Version"] python_version = f"python {'.'.join(map(str, sys.version_info[:2]))}"