Skip to content

Commit

Permalink
fix: engines correclty detected
Browse files Browse the repository at this point in the history
this partially rolls back 239d918 because it introduced a blocking bug.

fixes pyrevitlabs#2389 pyrevitlabs#2385
  • Loading branch information
Andrea Ghensi committed Sep 13, 2024
1 parent 0ccd821 commit e3e661a
Show file tree
Hide file tree
Showing 10 changed files with 189 additions and 215 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,5 @@ dist/
.idea
site/
*.pdb
*.deps.json
bin/**/*.xml
83 changes: 52 additions & 31 deletions dev/pyRevitLabs/pyRevitLabs.PyRevit/PyRevitClone.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
Expand Down Expand Up @@ -46,13 +46,10 @@ public class PyRevitClone
// constructors
public PyRevitClone(string clonePath, string name = null)
{
if (!IsCloneValid(clonePath))
{
throw new PyRevitException(
string.Format("Path does not point to a valid clone \"{0}\"", clonePath));
}
logger.Debug("Valid clone found at: {0}", clonePath);
ClonePath = clonePath.NormalizeAsPath();
var _clonePath = FindValidClonePathAbove(clonePath) ?? throw new PyRevitException(
$"Path does not point to a valid clone \"{clonePath}\"");
logger.Debug("Valid clone found at: {0}", _clonePath);
ClonePath = _clonePath.NormalizeAsPath();

if (name == null)
{
Expand All @@ -68,10 +65,6 @@ public PyRevitClone(string clonePath, string name = null)
}
}

private PyRevitClone(string clonePath) : this(clonePath, null)
{
}

// properties
public string Name { get; private set; }

Expand Down Expand Up @@ -156,10 +149,14 @@ public void Rename(string newName)

public List<PyRevitEngine> GetEngines() => GetEngines(ClonePath);

public List<PyRevitEngine> GetEngines(bool isNetCore) => GetEngines(ClonePath, isNetCore);

public PyRevitEngine GetEngine(int revitYear, PyRevitEngineVersion engineVer) => GetEngine(revitYear, ClonePath, engineVer: engineVer);

public PyRevitEngine GetCPythonEngine(PyRevitEngineVersion engineVer) => GetCPythonEngine(ClonePath, engineVer);

public IEnumerable<PyRevitEngine> GetCPythonEngines() => GetCPythonEngines(ClonePath);

public PyRevitEngine GetConfiguredEngine(string engineId) => GetConfiguredEngine(ClonePath, engineId);

public List<PyRevitEngine> GetConfiguredEngines() => GetConfiguredEngines(ClonePath);
Expand Down Expand Up @@ -281,18 +278,14 @@ public static PyRevitEngine GetEngine(int revitYear, string clonePath, PyRevitEn
{
return GetDefaultEngine(isNetCore, clonePath);
}
else
try
{
try
{
return GetEngines(clonePath)
.Single(x => x.Version == engineVer && x.IsNetCore == isNetCore);
}
catch (InvalidOperationException)
{
throw new PyRevitException(
$"Can not find engine or more than one engine found with specified version \"{engineVer.Version}\"");
}
return GetEngines(clonePath, isNetCore).Single(x => x.Version == engineVer);
}
catch (InvalidOperationException)
{
throw new PyRevitException(
$"Can not find engine or more than one engine found with specified version \"{engineVer.Version}\"");
}
}

Expand All @@ -301,7 +294,7 @@ public static PyRevitEngine GetCPythonEngine(string clonePath, PyRevitEngineVers
logger.Debug("Finding engine \"{0}\" path in \"{1}\"", engineVer, clonePath);
try
{
return GetEngines(clonePath).Single(x => x.Version == engineVer);
return GetCPythonEngines(clonePath).Single(x => x.Version == engineVer);
}
catch (InvalidOperationException)
{
Expand All @@ -310,10 +303,14 @@ public static PyRevitEngine GetCPythonEngine(string clonePath, PyRevitEngineVers
}
}

public static IEnumerable<PyRevitEngine> GetCPythonEngines(string clonePath)
{
return GetEngines(clonePath).Where(x => !x.Runtime);
}

private static PyRevitEngine GetDefaultEngine(bool isNetCore, string clonePath)
{
var eng = GetEngines(clonePath)
.FirstOrDefault(x => x.IsDefault && x.IsNetCore == isNetCore);
var eng = GetEngines(clonePath, isNetCore).FirstOrDefault(x => x.IsDefault);
return eng is null ? throw new PyRevitException("Can not find default engine") : eng;
}

Expand All @@ -326,13 +323,21 @@ public static List<PyRevitEngine> GetEngines(string clonePath)
{
return GetConfiguredEngines(clonePath);
}
else
logger.Debug("Finding engines in \"{0}\"", clonePath);
return FindEngines(false, FindEnginesDirectory(PyRevitConsts.NetFxFolder, clonePath))
.Union(FindEngines(true, FindEnginesDirectory(PyRevitConsts.NetCoreFolder, clonePath)))
.ToList();
}

public static List<PyRevitEngine> GetEngines(string clonePath, bool isNetCore)
{
if (GetPyRevitFilePath(clonePath) != null)
{
logger.Debug("Finding engines in \"{0}\"", clonePath);
return FindEngines(false, FindEnginesDirectory(PyRevitConsts.NetFxFolder, clonePath))
.Union(FindEngines(true, FindEnginesDirectory(PyRevitConsts.NetCoreFolder, clonePath)))
.ToList();
return GetConfiguredEngines(clonePath).Where(e => e.IsNetCore == isNetCore).ToList();
}
logger.Debug("Finding engines in \"{0}\"", clonePath);
var dir = isNetCore ? PyRevitConsts.NetCoreFolder : PyRevitConsts.NetFxFolder;
return FindEngines(isNetCore, FindEnginesDirectory(dir, clonePath));
}

public static PyRevitEngine GetConfiguredEngine(string clonePath, string engineId)
Expand Down Expand Up @@ -610,6 +615,22 @@ private static PyRevitCloneFromImageArgs ReadDeploymentArgs(string clonePath)
}
}

// find valid clone directory upstream
private static string FindValidClonePathAbove(string startingPath)
{
logger.Debug("Searching for valid clones above: {0}", startingPath);
string testPath = startingPath;
while (!IsCloneValid(testPath))
{
testPath = Path.GetDirectoryName(testPath);
if (testPath is null || testPath == string.Empty)
return null;
}

logger.Debug("Valid clone found at: {0}", testPath);
return testPath;
}

// find all engines under a given engine path
// @handled @logs
private static List<PyRevitEngine> FindEngines(bool isNetCore, string enginesDir)
Expand Down
2 changes: 1 addition & 1 deletion dev/pyRevitLabs/pyRevitLabs.PyRevit/PyRevitEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public PyRevitEngine(string id,

public override string ToString() {
var folder = IsNetCore ? PyRevitConsts.NetCoreFolder : PyRevitConsts.NetFxFolder;
return $"{Id} ({folder}) | Kernel: {KernelName} | Version: {Version} | Runtime: {Runtime} | Path: \"{AssemblyPath}\" | Desc: \"{Description}\"";
return $"{Id} ({folder}) | Kernel: {KernelName} | Version: {Version.Version} | Runtime: {Runtime} | Path: \"{AssemblyPath}\" | Desc: \"{Description}\"";
}

public string Id { get; private set; }
Expand Down
1 change: 0 additions & 1 deletion dev/pyRevitLoader/Source/PyRevitLoaderApplication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ private static void LoadAssembliesInFolder(string folder)
}
catch
{
////
}
}
}
Expand Down
31 changes: 24 additions & 7 deletions dev/pyRevitLoader/Source/PyRevitRunnerApplication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,37 @@ class PyRevitRunnerApplication : IExternalApplication {

// Hook into Revit to allow starting a command.
Result IExternalApplication.OnStartup(UIControlledApplication application) {
try {
// load all engine assemblies
// this is to ensure pyRevit is loaded on its own assemblies
foreach (var engineDll in Directory.GetFiles(LoaderPath, "*.dll"))
Assembly.LoadFrom(engineDll);

LoadAssembliesInFolder(LoaderPath);
// We need to also looad dlls from two folders up
var commonFolder = Path.GetDirectoryName(Path.GetDirectoryName(LoaderPath));
LoadAssembliesInFolder(commonFolder);
try
{
return RegisterExternalCommand(application);
}
catch (Exception ex) {
catch (Exception ex)
{
TaskDialog.Show("Error Loading Script Runner Application", ex.ToString());
return Result.Failed;
}
}

private static void LoadAssembliesInFolder(string folder)
{
// load all engine assemblies
// this is to ensure pyRevit is loaded on its own assemblies
foreach (var engineDll in Directory.GetFiles(folder, "*.dll"))
{
try
{
Assembly.LoadFrom(engineDll);
}
catch
{
}
}
}

private static Result RegisterExternalCommand(UIControlledApplication application) {
var assembly = typeof(PyRevitRunnerApplication).Assembly;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import os.path as op
import re

from pyrevit import HOST_APP, EXEC_PARAMS
from pyrevit import HOST_APP, EXEC_PARAMS, IS_DOTNET_CORE
from pyrevit.framework import System, Windows, Controls, Documents
from pyrevit.runtime.types import EventType, EventUtils
from pyrevit.loader import hooks
Expand Down Expand Up @@ -144,44 +144,63 @@ def _setup_core_options(self):
self.loadbetatools_cb.IsChecked = user_config.load_beta

def _setup_engines(self):
"""Sets up the list of available engines."""
attachment = user_config.get_current_attachment()
if attachment and attachment.Clone:
engine_cfgs = \
[PyRevitEngineConfig(x) for x in attachment.Clone.GetEngines()]
engine_cfgs = \
sorted(engine_cfgs,
key=lambda x: x.engine.Version, reverse=True)

# add engines to ui
self.availableEngines.ItemsSource = \
[x for x in engine_cfgs if x.engine.Runtime]
self.cpythonEngines.ItemsSource = \
[x for x in engine_cfgs if not x.engine.Runtime]

# now select the current runtime engine
for engine_cfg in self.availableEngines.ItemsSource:
if engine_cfg.engine.Version == int(EXEC_PARAMS.engine_ver):
self.availableEngines.SelectedItem = engine_cfg
break

# if addin-file is not writable, lock changing of the engine
if attachment.IsReadOnly():
self.availableEngines.IsEnabled = False

# now select the current runtime engine
self.active_cpyengine = user_config.get_active_cpython_engine()
if self.active_cpyengine:
for engine_cfg in self.cpythonEngines.ItemsSource:
if engine_cfg.engine.Version == \
self.active_cpyengine.Version:
self.cpythonEngines.SelectedItem = engine_cfg
break
else:
logger.debug('Failed getting active cpython engine.')
self.cpythonEngines.IsEnabled = False
else:
if not attachment or not attachment.Clone:
logger.debug('Error determining current attached clone.')
self.disable_element(self.availableEngines)
return

self._setup_runtime_engines(attachment)
self._setup_cpython_engines(attachment)

def _setup_runtime_engines(self, attachment):
"""Sets up the list of available runtime engines."""
engine_cfgs = [
PyRevitEngineConfig(x)
for x in attachment.Clone.GetEngines(IS_DOTNET_CORE)
if x.Runtime
]
engine_cfgs = sorted(
engine_cfgs, key=lambda x: x.engine.Version, reverse=True
)

# add engines to ui
self.availableEngines.ItemsSource = engine_cfgs

# now select the current runtime engine
self.availableEngines.SelectedItem = next(
(
cfg for cfg in engine_cfgs
if cfg.engine.Version == int(EXEC_PARAMS.engine_ver)
),
None
)

# if addin-file is not writable, lock changing of the engine
if attachment.IsReadOnly():
self.availableEngines.IsEnabled = False

def _setup_cpython_engines(self, attachment):
"""Sets up the list of available cpython engines."""
cengine_cfgs = [
PyRevitEngineConfig(x) for x in attachment.Clone.GetCPythonEngines()
]
cengine_cfgs = sorted(
cengine_cfgs, key=lambda x: x.engine.Version, reverse=True
)
self.cpythonEngines.ItemsSource = cengine_cfgs

# now select the current cpython engine
self.active_cpyengine = user_config.get_active_cpython_engine()
if not self.active_cpyengine:
logger.debug('Failed getting active cpython engine.')
self.cpythonEngines.IsEnabled = False
return
self.cpythonEngines.SelectedItem = next(
cfg for cfg in cengine_cfgs
if cfg.engine.Version == self.active_cpyengine.Version
)

def _setup_user_extensions_list(self):
"""Reads the user extension folders and updates the list"""
Expand Down
13 changes: 10 additions & 3 deletions pyrevitlib/pyrevit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@

import clr # pylint: disable=E0401

import System
import System.Runtime.InteropServices as SRI

from pyrevit import compat

PYREVIT_ADDON_NAME = 'pyRevit'
Expand Down Expand Up @@ -54,12 +57,16 @@
except NameError:
raise Exception('Critical Error. Can not find home directory.')

# Determine dotnet runtime
DOTNET_RUNTIME_ID = "netfx"
if System.Environment.Version.Major >= 5 or \
(".NET Core" in SRI.RuntimeInformation.FrameworkDescription):
DOTNET_RUNTIME_ID = "netcore"

# try get net folder
net_folder = "netcore" if compat.is_netcore() else "netfx"
IS_DOTNET_CORE = DOTNET_RUNTIME_ID == "netcore"

# BIN directory
BIN_DIR = op.join(HOME_DIR, 'bin', net_folder)
BIN_DIR = op.join(HOME_DIR, 'bin', DOTNET_RUNTIME_ID)

# main pyrevit lib folders
MAIN_LIB_DIR = op.join(HOME_DIR, 'pyrevitlib')
Expand Down
2 changes: 1 addition & 1 deletion pyrevitlib/pyrevit/runtime/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
INTERFACE_TYPES_DIR, '', SOURCE_FILE_FILTER
)
+ EXEC_PARAMS.engine_ver
+ str(CPYTHON_ENGINE.Version)
+ str(CPYTHON_ENGINE.Version) if CPYTHON_ENGINE else "0"
)[:HASH_CUTOFF_LENGTH]
RUNTIME_ASSM_FILE_ID = '{}_{}'\
.format(BASE_TYPES_DIR_HASH, RUNTIME_NAMESPACE)
Expand Down
Loading

0 comments on commit e3e661a

Please sign in to comment.