Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add file type association to Spyder shortcuts on all platforms. #171

Merged
merged 13 commits into from
Aug 20, 2024
Merged
34 changes: 22 additions & 12 deletions recipe/bld.bat
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,32 @@ if errorlevel 1 exit 1
set MENU_DIR=%PREFIX%\Menu
IF NOT EXIST (%MENU_DIR%) mkdir %MENU_DIR%

rem Copy Spyder's icon
copy %RECIPE_DIR%\spyder.ico %MENU_DIR%\spyder.ico

rem Replace variables in menu files
for /F "delims=. tokens=1" %%i in ("%PKG_VERSION%") do set PKG_MAJOR_VER=%%i
call :replace spyder-menu.json spyder-menu.json
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this replacement correct? Shouldn't it be replacing a .bak file, like in the line just below this one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:replace reads the lines in the first file and replaces the __PKG_VERSION__ tokens with the major version number, then writes the lines to the second file. The default json file is for menuinst v2, so we just write back to the same file. Any *.json file will be executed by menuinst, so on the line below we also need to rename the spyder-menu-v1.json file so that menuinst does not try to execute on it. The post-link.bat script will determine whether v1 or v2 is in the base environment, and swap them if needed.

But perhaps it would be clearer to just have both files spyder-menu-v1.json and spyder-menu-v2.json, then let post-link.bat add .bak to the unnecessary file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, the file names in the Menu directory should not change on install so that they will all be removed on uninstall. So it will be best to have spyder-menu-v1.json.bak and spyder-menu.json. Then copy v1 to spyder-menu.json (overwriting) only if necessary.

call :replace spyder-menu-v1.json spyder-menu-v1.json.bak

for /f "delims=" %%i in (%RECIPE_DIR%\spyder-menu.json) do (
set s=%%i
set s=!s:__PKG_VERSION__=%PKG_VERSION%!
echo !s:__PKG_MAJOR_VER__=%PKG_MAJOR_VER%!>> %MENU_DIR%\spyder-menu.json
rem Copy GUI executable stub
for /F "tokens=*" %%i in (
'%CONDA_PYTHON_EXE% -c "import conda_build, pathlib; print(pathlib.Path(conda_build.__file__).parent / 'gui-64.exe')"'
) do (
set exe_path=%%i
)
copy /y /b %exe_path% %SCRIPTS%

for /f "delims=" %%i in (%RECIPE_DIR%\spyder-menu-v1.json) do (
set s=%%i
set s=!s:__PKG_VERSION__=%PKG_VERSION%!
echo !s:__PKG_MAJOR_VER__=%PKG_MAJOR_VER%!>> %MENU_DIR%\spyder-menu-v1.json.bak
)
rem Copy launch script
copy /y %RECIPE_DIR%\spyder-script.pyw %SCRIPTS%

:exit
exit /b %errorlevel%

del %SCRIPTS%\spyder_win_post_install.py
del %SCRIPTS%\spyder.bat
del %SCRIPTS%\spyder
Comment on lines -25 to -27
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are not we removing these scripts now? I think they shouldn't be part of the package.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that they should not be part of the package. I removed these lines because these files were not being added to the %SCRIPTS% directory, so I assumed they were tech-debt. However, I can double check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I've confirmed that these files are not in the Scripts directory of the conda package (or anywhere else). Only the following:

Scripts/.spyder-post-link.bat
Scripts/gui-64.exe
Scripts/spyder-script.py
Scripts/spyder-script.pyw
Scripts/spyder.exe
Scripts/spyder.ico

:replace
for /f "delims=" %%i in (%RECIPE_DIR%\%1) do (
set s=%%i
set s=!s:__PKG_VERSION__=%PKG_VERSION%!
echo !s:__PKG_MAJOR_VER__=%PKG_MAJOR_VER%!>> %MENU_DIR%\%2
)
goto :eof
2 changes: 1 addition & 1 deletion recipe/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ requirements:
- watchdog >=0.10.3
- yarl >=1.9.4
run_constrained:
- menuinst >=2.0.2
- menuinst >=2.1
mrclary marked this conversation as resolved.
Show resolved Hide resolved

test:
requires:
Expand Down
14 changes: 6 additions & 8 deletions recipe/post-link.bat
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ setlocal ENABLEDELAYEDEXPANSION
set menudir=%PREFIX%\Menu
set menu=%menudir%\spyder-menu.json
set logfile=%PREFIX%\.messages.txt
set scriptsdir=%PREFIX%\Scripts

rem Cleanup GUI files
move /y %scriptsdir%\gui-64.exe %scriptsdir%\spyder.exe
del %scriptsdir%\spyder-script.py

rem Check for conda-based install
if exist "%menudir%\conda-based-app" (
Expand All @@ -18,7 +23,7 @@ rem Check for CONDA_PYTHON_EXE
if not exist "%conda_python_exe%" (
rem CONDA_PYTHON_EXE environment variable does not exist.
rem v1 type shortcuts will not work
goto :base_env
goto :exit
)

rem Check menuinst version
Expand All @@ -28,13 +33,6 @@ for /F "tokens=*" %%i in (
if "%%~i"=="True" call :use_menu_v1
)

:base_env
if exist "%PREFIX%\condabin\" if exist "%PREFIX%\envs\" (
rem Installed in a base environment, use distribution name
call :patch "ENV_NAME=DISTRIBUTION_NAME"
)
goto :exit

:exit
exit /b %errorlevel%

Expand Down
7 changes: 2 additions & 5 deletions recipe/post-link.sh
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
#!/bin/bash
set -e

[[ $(sed --version 2>/dev/null) ]] && opts=("-i" "-E") || opts=("-i" "''" "-E")
[[ $(sed --version 2>/dev/null) ]] && opts=("-i" "-E") || opts=("-i" "" "-E")
menu="${PREFIX}/Menu/spyder-menu.json"

if [[ -f "${PREFIX}/Menu/conda-based-app" ]]; then
# Installed in installer environment, abridge shortcut name
sed ${opts[@]} "s/ \(\{\{ ENV_NAME \}\}\)//g" $menu
elif [[ -d "${PREFIX}/condabin" && -d "${PREFIX}/envs" ]]; then
# Installed in a base environment, use distribution name
sed ${opts[@]} "s/ENV_NAME/DISTRIBUTION_NAME/g" $menu
sed "${opts[@]}" "s/ \(\{\{ ENV_NAME \}\}\)//g" $menu
fi
2 changes: 1 addition & 1 deletion recipe/spyder-menu-v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[
{
"name": "Spyder __PKG_MAJOR_VER__",
"pywscript": "${PYTHON_SCRIPTS}/spyder-script.py",
"pywscript": "${PYTHON_SCRIPTS}/spyder-script.pyw",
"workdir": "${PERSONALDIR}/Python Scripts",
"icon": "${MENU_DIR}/spyder.ico"
}
Expand Down
186 changes: 181 additions & 5 deletions recipe/spyder-menu.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
"menu_name": "{{ DISTRIBUTION_NAME }} spyder",
"menu_items": [
{
"name": "Spyder __PKG_MAJOR_VER__ ({{ ENV_NAME }})",
"name": {
"target_environment_is_base": "Spyder __PKG_MAJOR_VER__ ({{ DISTRIBUTION_NAME }})",
"target_environment_is_not_base": "Spyder __PKG_MAJOR_VER__ ({{ ENV_NAME }})"
},
"description": "Scientific PYthon Development EnviRonment",
"icon": "{{ MENU_DIR }}/spyder.{{ ICON_EXT }}",
"activate": false,
Expand All @@ -14,15 +17,81 @@
"win": {
"desktop": true,
"app_user_model_id": "spyder.Spyder",
"command": ["{{ PREFIX }}/pythonw.exe", "{{ PREFIX }}/Scripts/spyder-script.py"]
"command": ["{{ PREFIX }}/Scripts/spyder.exe", "%*"],
"file_extensions": [
".bat",
".c",
".cc",
".cfg",
".cl",
".cmd",
".cpp",
".css",
".cxx",
".desktop",
".diff",
".enaml",
".f",
".f03",
".f08",
".f2k",
".f77",
".f90",
".f95",
".for",
".h",
".hh",
".hpp",
".htm",
".html",
".hxx",
".inf",
".ini",
".ipy",
".ipynb",
".jl",
".js",
".json",
".m",
".md",
".nsh",
".nsi",
".patch",
".po",
".pot",
".pro",
".properties",
".pxd",
".pxi",
".py",
".pyw",
".pyx",
".reg",
".rej",
".rst",
".scss",
".session",
".txt",
".xml",
".yaml",
".yml"
]
},
"linux": {
"Categories": [
"Development",
"Science"
],
"command": ["{{ PREFIX }}/bin/spyder", "$@"],
"StartupWMClass": "Spyder"
"command": ["{{ PREFIX }}/bin/spyder", "%F"],
"StartupWMClass": "Spyder",
"MimeType": [
"text/x-python",
"text/plain",
"text/html",
"text/xml",
"text/x-c",
"text/x-perl"
]
},
"osx": {
"precommand": "pushd \"$(dirname \"$0\")\" &>/dev/null",
Expand All @@ -32,7 +101,114 @@
},
"CFBundleName": "Spyder __PKG_MAJOR_VER__",
"CFBundleIdentifier": "org.spyder-ide.Spyder",
"CFBundleVersion": "__PKG_VERSION__"
"CFBundleVersion": "__PKG_VERSION__",
"CFBundleDocumentTypes": [
{
"CFBundleTypeName": "text document",
"CFBundleTypeRole": "Editor",
"LSHandlerRank": "Default",
"CFBundleTypeIconFile": "spyder.icns",
"LSItemContentTypes": [
"com.apple.applescript.text",
"com.apple.ascii-property-list",
"com.apple.audio-unit-preset",
"com.apple.binary-property-list",
"com.apple.configprofile",
"com.apple.crashreport",
"com.apple.dashcode.css",
"com.apple.dashcode.javascript",
"com.apple.dashcode.json",
"com.apple.dashcode.manifest",
"com.apple.dt.document.ascii-property-list",
"com.apple.dt.document.script-suite-property-list",
"com.apple.dt.document.script-terminology-property-list",
"com.apple.property-list",
"com.apple.rez-source",
"com.apple.scripting-definition",
"com.apple.structured-text",
"com.apple.traditional-mac-plain-text",
"com.apple.xcode.ada-source",
"com.apple.xcode.apinotes",
"com.apple.xcode.bash-script",
"com.apple.xcode.configsettings",
"com.apple.xcode.csh-script",
"com.apple.xcode.entitlements-property-list",
"com.apple.xcode.fortran-source",
"com.apple.xcode.glsl-source",
"com.apple.xcode.ksh-script",
"com.apple.xcode.lex-source",
"com.apple.xcode.make-script",
"com.apple.xcode.mig-source",
"com.apple.xcode.pascal-source",
"com.apple.xcode.strings-text",
"com.apple.xcode.tcsh-script",
"com.apple.xcode.yacc-source",
"com.apple.xcode.zsh-script",
"com.apple.xml-property-list",
"com.netscape.javascript-source",
"com.scenarist.closed-caption",
"com.sun.java-source",
"com.sun.java-web-start",
"net.daringfireball.markdown",
"org.khronos.glsl-source",
"org.oasis-open.xliff",
"public.ada-source",
"public.assembly-source",
"public.bash-script",
"public.c-header",
"public.c-plus-plus-header",
"public.c-plus-plus-source",
"public.c-source",
"public.case-insensitive-text",
"public.comma-separated-values-text",
"public.csh-script",
"public.css",
"public.delimited-values-text",
"public.dylan-source",
"public.filename-extension",
"public.fortran-77-source",
"public.fortran-90-source",
"public.fortran-95-source",
"public.fortran-source",
"public.html",
"public.json",
"public.ksh-script",
"public.lex-source",
"public.log",
"public.m3u-playlist",
"public.make-source",
"public.mig-source",
"public.mime-type",
"public.module-map",
"public.nasm-assembly-source",
"public.objective-c-plus-plus-source",
"public.objective-c-source",
"public.opencl-source",
"public.pascal-source",
"public.patch-file",
"public.perl-script",
"public.php-script",
"public.plain-text",
"public.python-script",
"public.rss",
"public.ruby-script",
"public.script",
"public.shell-script",
"public.source-code",
"public.tcsh-script",
"public.text",
"public.utf16-external-plain-text",
"public.utf16-plain-text",
"public.utf8-plain-text",
"public.utf8-tab-separated-values-text",
"public.xhtml",
"public.xml",
"public.yacc-source",
"public.yaml",
"public.zsh-script"
]
}
]
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions recipe/spyder-script.pyw
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this script necessary now?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is required for Spyder to be listed as an application for file types in context menus. Windows looks at the shortcut executable for this, so when using pythonw.exe spyder-script.py, Spyder shows up as Python. In order to fix this, the shortcut must use the spyder.exe executable stub, but this executable stub looks for spyder-script.pyw rather than spyder-script.py.

See:
conda/menuinst#185 (comment)
conda/menuinst#185 (comment)
conda/menuinst#185 (comment)

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

# -*- coding: utf-8 -*-
mrclary marked this conversation as resolved.
Show resolved Hide resolved
import re
import sys

from spyder.app.start import main

if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
sys.exit(main())