Skip to content

Commit 737bb48

Browse files
committed
Fix path detection algorithm
This commit ... 1. uses a more robust algorithm to determine special ST paths at startup, which no longer relies on location of `Default.sort` module, but uses `sys.executable` variable to determine, whether PC is running within ST plugin environment or on an external CI runner which mocks ST API. The new approach fixes an issue, which causes path detection to resolve invalid paths, if users extract whole Default package. PC assumed sublimehq's development environment in that case. 2. moves forward to rely on `__spec__` in favor of `__file__` and `__loader__` as this is what python is moving to in general. The ladder ones are dropped step by step by recent python releases (3.13).
1 parent 96bfda9 commit 737bb48

File tree

1 file changed

+52
-59
lines changed

1 file changed

+52
-59
lines changed

package_control/sys_path.py

Lines changed: 52 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2,77 +2,70 @@
22
import sys
33

44
import sublime
5-
import sublime_plugin
65

76
PREFIX = '\\\\?\\' if sys.platform == 'win32' else ''
87

9-
# Determine default packages path
10-
try:
11-
import Default.sort as default_module
12-
13-
__default_packages_path = os.path.dirname(os.path.dirname(default_module.__file__))
14-
15-
# When loaded as a .sublime-package file, __file__ ends up being
16-
# {data_dir}/Installed Packages/Package Control.sublime-package/package_control/sys_path.py
17-
if isinstance(__loader__, sublime_plugin.ZipLoader):
18-
__installed_packages_path = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
19-
# For a non-development build, the Packages are next to the Installed Packages dir
20-
__packages_path = os.path.join(os.path.dirname(__installed_packages_path), 'Packages')
21-
if not os.path.exists(__packages_path):
22-
__packages_path = None
23-
24-
# When loaded as unpacked package, __file__ ends up being
25-
# {data_dir}/Packages/Package Control/package_control/sys_path.py
8+
__executable_path = sublime.executable_path()
9+
if not __executable_path:
10+
# Until ST4187 sublime.executable_path() doesn't return anything at import time.
11+
# On python 3.3 os.abspath() is required to return absolute path of sys.executable
12+
__executable_path = os.path.abspath(sys.executable)
13+
14+
# Default packages are located in application installation directory next to executables.
15+
__default_packages_path = os.path.join(os.path.dirname(__executable_path), 'Packages')
16+
if not os.path.isdir(__default_packages_path):
17+
raise FileNotFoundError('Default Packages')
18+
19+
# Determine user's data path.
20+
# - for portable setups resolves to __executable_path/Data
21+
# - for Normal setups resolves to %APPDATA%\Sublime Text or ~/.config/sublime-text
22+
# When loaded as a .sublime-package file, __file__ ends up being
23+
# {data_dir}/Installed Packages/Package Control.sublime-package/package_control/sys_path.py
24+
# When loaded as unpacked package, __file__ ends up being
25+
# {data_dir}/Packages/Package Control/package_control/sys_path.py
26+
__data_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
27+
28+
# Determine extracted packages path
29+
__packages_path = os.path.join(__data_path, 'Packages')
30+
if not os.path.isdir(__packages_path):
31+
# in ST development environment default package must be a directory
32+
if not os.path.isdir(os.path.join(__default_packages_path, 'Default')):
33+
raise FileNotFoundError('Packages')
34+
__packages_path = __default_packages_path
35+
36+
# Determine installed packages path
37+
__installed_packages_path = os.path.join(__data_path, 'Installed Packages')
38+
if not os.path.isdir(__installed_packages_path):
39+
__installed_packages_path = None
40+
41+
if __installed_packages_path is None:
42+
if sys.platform == 'darwin':
43+
__data_path = os.path.expanduser('~/Library/Application Support')
44+
elif sys.platform == 'win32':
45+
__data_path = os.environ.get('APPDATA')
2646
else:
27-
__packages_path = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
28-
# For a non-development build, the Installed Packages are next to the Packages dir
29-
__installed_packages_path = os.path.join(os.path.dirname(__packages_path), 'Installed Packages')
30-
if not os.path.exists(__installed_packages_path):
31-
__installed_packages_path = None
32-
33-
if __packages_path is None:
34-
# default package must not be zipped in dev environment
35-
if isinstance(default_module.__loader__, sublime_plugin.ZipLoader):
36-
raise FileNotFoundError('Packages')
37-
__packages_path = __default_packages_path
47+
__data_path = os.environ.get('XDG_CONFIG_HOME')
48+
if __data_path is None:
49+
__data_path = os.path.expanduser('~/.config')
50+
51+
if __data_path:
52+
for __leaf in ('Sublime Text Development', 'Sublime Text 3 Development'):
53+
if sys.platform not in set(('win32', 'darwin')):
54+
__leaf = __leaf.lower().replace(' ', '-')
55+
__data_path = os.path.join(__data_path, __leaf)
56+
__installed_packages_path = os.path.join(__data_path, 'Installed Packages')
57+
if not os.path.exists(__installed_packages_path):
58+
__installed_packages_path = None
3859

3960
if __installed_packages_path is None:
40-
if sys.platform == 'darwin':
41-
__data_base = os.path.expanduser('~/Library/Application Support')
42-
elif sys.platform == 'win32':
43-
__data_base = os.environ.get('APPDATA')
44-
else:
45-
__data_base = os.environ.get('XDG_CONFIG_HOME')
46-
if __data_base is None:
47-
__data_base = os.path.expanduser('~/.config')
48-
49-
if __data_base:
50-
for __leaf in ('Sublime Text Development', 'Sublime Text 3 Development'):
51-
if sys.platform not in set(('win32', 'darwin')):
52-
__leaf = __leaf.lower().replace(' ', '-')
53-
__data_path = os.path.join(__data_base, __leaf)
54-
__installed_packages_path = os.path.join(__data_path, 'Installed Packages')
55-
if not os.path.exists(__installed_packages_path):
56-
__installed_packages_path = None
57-
58-
if __installed_packages_path is None:
59-
raise FileNotFoundError('Installed Packages')
60-
61-
except ImportError:
62-
# All this song and dance, just to satisfy CI test runner!
63-
# Import error of Default.sort indicates CI test environment
64-
# Unfortunately we can't use this simple lines in production
65-
# as API can be called at import time only with ST4088+.
66-
__default_packages_path = os.path.join(os.path.dirname(sublime.executable_path()))
67-
__installed_packages_path = sublime.installed_packages_path()
68-
__packages_path = sublime.packages_path()
61+
raise FileNotFoundError('Installed Packages')
6962

7063
if PREFIX:
64+
__data_path = PREFIX + __data_path
7165
__default_packages_path = PREFIX + __default_packages_path
7266
__installed_packages_path = PREFIX + __installed_packages_path
7367
__packages_path = PREFIX + __packages_path
7468

75-
__data_path = os.path.dirname(__installed_packages_path)
7669
__cache_path = None
7770
__package_control_cache_path = None
7871
__python_libs_cache_path = None

0 commit comments

Comments
 (0)