Let´s say I have my extension at C:\Folder\Example.extension\
I want to get the Directory of the Extension in the python scripts of this extension, so in this case i want to get C:\Folder.
I need that because the directory will probably change over time so I´ll have to move my whole extension to another drive. I want to put log-files etc in the extension directory and I want my scripts to have correct directorypaths even if i move the whole extendion folder to another drive.
I want this as well.
I combed through the pyrevit source code but I couldn’t find anything that provides the root directory of the currently executing extension. The only thing I could find is a way to get the extension name.
If it doesn’t exist, I think adding a way to get the extension path would be a good addition to pyrevit.
Right now I have a path module in the lib folder of my extension which gets the relative path to the root directory.
import os
PROJECT_PATH = os.path.normpath(os.path.join(__file__, '../../../../'))
EXTENSION_PATH = os.path.join(PROJECT_PATH, 'Example.extension')
def get_ext_root_dirs(self):
"""Return a list of all extension directories.
Returns:
:obj:`list`: list of strings. user extension directories.
"""
dir_list = set()
if op.exists(EXTENSIONS_DEFAULT_DIR):
dir_list.add(EXTENSIONS_DEFAULT_DIR)
dir_list.update(self.get_thirdparty_ext_root_dirs())
return list(dir_list)
def get_ext_sources(self):
"""Return a list of extension definition source files"""
ext_sources = self.environment.get_option(
CONSTS.EnvConfigsExtensionLookupSourcesKey,
default_value=[],
)
return list(set(ext_sources))
I saw that option as well, but I think it would be nice to have it defined in the EXEC_PARAMS instead of only having the extension name provided.
I saw where the extension name was provided in the EXEC_PARAMS: pyRevit/__init__.py at b7704eacfe1e5ab4840c1759f5ee3830af38a328 · eirannejad/pyRevit · GitHub and was looking at potentially adding the extension directory as well. I was looking into what that change might effect, but I’m still somewhat unfamiliar with pyrevits runtime. I gave up, because I’m having some trouble finding where the ScriptData that is provided to the executor is defined and what it may affect.
@property # read-only
def command_extension(self):
"""str: Return current command extension name."""
if '__commandextension__' in __builtins__ \
and __builtins__['__commandextension__']:
return __builtins__['__commandextension__']
elif self.script_runtime:
return self.script_runtime.ScriptData.CommandExtension
Sorry this is somewhat off-topic. I just wanted to look into a solution for a user to get the extension directory very easily.
This might be a little opinionated, but I think its best practice to use the path library instead of string manipulation wherever possible. However, in this instance it shouldn’t make any functional difference, assuming you don’t rename any files.
Also, for best practices, you shouldn’t have “MODULE_PATH” and “DIRECTORY” variables as all uppercase. I only had my variables as uppercase, because they are constant variables in the global scope of my path module, which is the convention for python. In your case they are local variables inside of a function, so they should just be “module_path” and “directory”.
This is from pythons documentation of the path module.
Basically the “…/” that is added signals the normpath function to go up 4 steps in the path.
os.path.normpath(path )
Normalize a pathname by collapsing redundant separators and up-level references so that A//B, A/B/, A/./B and A/foo/../B all become A/B. This string manipulation may change the meaning of a path that contains symbolic links. On Windows, it converts forward slashes to backward slashes. To normalize case, use normcase().>
Also os.path.join is similar to just adding the strings with +, but it leaves the joining to the path module which supports multiple platforms.
Edit:
I was looking through the source code, and saw this. This is how pyrevit gets it’s root directory which is another reference. It uses os.path.dirname instead which may be more intuitive.
# -----------------------------------------------------------------------------
# config environment paths
# -----------------------------------------------------------------------------
# main pyrevit repo folder
try:
# 3 steps back for <home>/Lib/pyrevit
HOME_DIR = op.dirname(op.dirname(op.dirname(__file__)))
except NameError:
raise Exception('Critical Error. Can not find home directory.')
# BIN directory
BIN_DIR = op.join(HOME_DIR, 'bin')
# main pyrevit lib folders
MAIN_LIB_DIR = op.join(HOME_DIR, 'pyrevitlib')
MISC_LIB_DIR = op.join(HOME_DIR, 'site-packages')
# path to pyrevit module
MODULE_DIR = op.join(MAIN_LIB_DIR, 'pyrevit')
# loader directory
LOADER_DIR = op.join(MODULE_DIR, 'loader')
# runtime directory
RUNTIME_DIR = op.join(MODULE_DIR, 'runtime')
# addin directory
ADDIN_DIR = op.join(LOADER_DIR, 'addin')