15

How do I configure new External Language Input cell (that appears when pressing >) to use my instance of Python? I'm aware of ExternalEvaluate, but is there a way to attach ExternalSessionObject to this cell:

enter image description here

b3m2a1
  • 46,870
  • 3
  • 92
  • 239
swish
  • 7,881
  • 26
  • 48

2 Answers2

14

This has to be done at the stylesheet level and here's a way to do it. First we'll make a new CellEvaluationFunction that uses the TaggingRules to bind the ExternalSessionObject. Then we'll attach that to the "ExternalLanguage" cell. Here's the function:

currentCellExternalSessionEvaluate =
  Function[
   With[{ExternalEvaluate`FE`Private`cell = EvaluationCell[]},
    With[{ExternalEvaluate`FE`Private`sessions =
       Replace[
        CurrentValue[
         ExternalEvaluate`FE`Private`cell,
         {
          TaggingRules,
          "ExternalSessions"
           }
         ],
        Except[_?OptionQ] :>
         CurrentValue[
          EvaluationNotebook[],
          {
           TaggingRules,
           "ExternalSessions"
            },
          Replace[ExternalEvaluate`FE`$CellSessions,
           Except[_?OptionQ] -> <||>
           ]
          ]
        ]
      },
     Block[{ExternalEvaluate`FE`$CellSessions = 
        Association@ExternalEvaluate`FE`Private`sessions},
      FrontEnd`Private`ExternalLanguageCellEvaluationFunction[##]
      ]
     ]
    ]
   ];

Then we can add this to our stylesheet like so:

Get["http://raw.githubusercontent.com/b3m2a1/mathematica-tools/master/StylesheetEdit.wl"]

StyleSheetEdit["ExternalLanguage", 
 CellEvaluationFunction -> currentCellExternalSessionEvaluate,
 "MakeCell" -> True
 ]

And finally we'll start a session and bind it to our notebook:

myPy = FileNameJoin@{$UserDocumentsDirectory, "Python", "config", 
    "python3.4", "bin", "python3"};

CurrentValue[EvaluationNotebook[],
  {TaggingRules, "ExternalSessions", "Python"}
  ] = StartExternalSession[{"Python", "Executable" -> myPy}]

Then I can just call:

import sys
print(sys.version)

3.4.4 (v3.4.4:737efcadf5a6, Dec 19 2015, 20:38:52) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]

(somehow my ExternalSessionObject can't parse any results, but this is just proof of concept)

Then I can remove the binding:

CurrentValue[EvaluationNotebook[],
   {TaggingRules, "ExternalSessions", "Python"}
   ] = Inherited;

And it all works as normal:

import sys
sys.version

2.7.10 (default, Jul 15 2017, 17:16:57) 
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.31)]

Note that the TaggingRules may also be applied to specific cells to make this more fine-tuned.

b3m2a1
  • 46,870
  • 3
  • 92
  • 239
  • That's pretty sophisticated, but very cool! – swish Mar 11 '18 at 02:51
  • 2
    This once worked but seems to have stopped. Somehow the currentCellExternalSessionEvaluate now shows a syntax error... – M.R. Nov 30 '20 at 19:58
  • @b3m2a1 This is a very valuable answer, could you please update it when you can, I'm still sure why it's failing now in 12 – M.R. Nov 30 '20 at 20:33
  • 2
    @M.R. This seems to now be implemented via EvaluationMode -> "ExternalLanguage". It's not clear to me that this is accessible anymore. I'd contact WRI to tell them to tell John Fultz that he fracked up a good thing. – b3m2a1 Nov 30 '20 at 20:57
  • @b3m2a1 See this answer which works in 12.2 – M.R. Dec 11 '20 at 01:23
3

There is a https://resources.wolframcloud.com/FunctionRepository/resources/SetLanguageCellSession/ for some time already, and I've been using it to do this.

swish
  • 7,881
  • 26
  • 48