public
Last active

This method will help retrieve assets for Sublime Text 3 plugins.

  • Download Gist
get_package_asset.py
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
"""
MIT License
Copyright (c) 2013 Scott Kuroda <scott.kuroda@gmail.com>
"""
import sublime
import os
import zipfile
import tempfile
import re
 
 
def get_package_asset(package_name, asset_name, get_path=False, recursive_search=False, return_binary=False, encoding="utf-8"):
"""
Retrieve the asset specified in the specified package or None if it
cannot be found.
 
Arguments:
package_name Name of the packages whose asset you are searching for.
asset_name Name of the asset to search for
 
Keyword arguments:
get_path Boolean representing if the path or the content of the
asset should be returned (default False)
 
recursive_search Boolean representing if the file specified should
search for assets recursively or take the file as
an absolute path (default False).
 
return_binary Boolean representing if the binary representation of
a file should be returned. Only takes affect if get_path
is True (default False).
 
encoding String representing the encoding to use when reading.
Only takes affect when return_binary is True
(default utf-8).
 
Return Value:
None if the asset does not exists. The contents of the asset if get_path is
False. A path to the file if get_path is True.
"""
 
packages_path = sublime.packages_path()
sublime_package = package_name + ".sublime-package"
path = None
 
if os.path.exists(os.path.join(packages_path, package_name)):
if recursive_search:
path = _find_file(os.path.join(packages_path, package_name), asset_name)
elif os.path.exists(os.path.join(packages_path, package_name, asset_name)):
path = os.path.join(packages_path, package_name, asset_name)
 
if path != None and os.path.exists(path):
 
if get_path:
return path
else:
if return_binary:
mode = "rb"
encoding = None
else:
mode = "r"
with open(path, mode, encoding=encoding) as file_obj:
content = file_obj.read()
 
return content
 
packages_path = sublime.installed_packages_path()
 
if os.path.exists(os.path.join(packages_path, sublime_package)):
ret_value = _search_zip(packages_path, sublime_package, asset_name, get_path, recursive_search, return_binary, encoding)
if ret_value != None:
return ret_value
 
packages_path = os.path.dirname(sublime.executable_path()) + os.sep + "Packages"
 
if os.path.exists(os.path.join(packages_path, sublime_package)):
ret_value = _search_zip(packages_path, sublime_package, asset_name, get_path, recursive_search, return_binary, encoding)
if ret_value != None:
return ret_value
return None
 
def get_package_and_asset_name(path):
"""
This method will return the package name and asset name from a path.
 
Arguments:
path Path to parse for package and asset name.
"""
package = None
asset = None
 
if os.path.isabs(path):
packages_path = sublime.packages_path()
if path.startswith(packages_path):
package, asset = _search_for_package_and_asset(path, packages_path)
 
packages_path = sublime.installed_packages_path()
if path.startswith(packages_path):
package, asset = _search_for_package_and_asset(path, packages_path)
 
packages_path = os.path.dirname(sublime.executable_path()) + os.sep + "Packages"
if path.startswith(packages_path):
package, asset = _search_for_package_and_asset(path, packages_path)
else:
path = re.sub(r"^Packages[/\\]", "", path)
split = re.split(r"[/\\]", path, 1)
package = split[0]
asset = split[1]
 
return (package, asset)
 
def _search_for_package_and_asset(path, packages_path):
"""
Derive the package and asset from a path.
"""
package = os.path.basename(os.path.dirname(path))
 
directory, asset = os.path.split(path)
if directory == packages_path:
package = asset.replace(".sublime-package", "")
asset = None
else:
package, temp_asset = _search_for_package_and_asset(directory, packages_path)
 
if temp_asset is not None:
temp_asset += os.sep + asset
asset = temp_asset
 
return (package, asset)
 
def _search_zip(packages_path, package, file_name, path, recursive_search, return_binary, encoding):
"""
Search a zip for an asset.
"""
if not os.path.exists(os.path.join(packages_path, package)):
return None
 
ret_value = None
with zipfile.ZipFile(os.path.join(packages_path, package)) as zip_file:
namelist = zip_file.namelist()
if recursive_search:
indices = [i for i, name in enumerate(namelist) if name.endswith(file_name)]
if len(indices) > 0:
file_name = namelist[indices[0]]
if file_name in namelist:
if path:
temp_dir = tempfile.mkdtemp()
file_location = zip_file.extract(file_name, temp_dir)
ret_value = file_location
else:
ret_value = zip_file.read(file_name)
if not return_binary:
ret_value = ret_value.decode(encoding)
 
return ret_value
 
def _find_file(abs_dir, file_name):
"""
Find the absolute path to a specified file. Note that the first entry
matching the file will be used, even if it exists elsewhere in the
directory structure.
"""
ret_path = None
 
split = os.path.split(file_name)
abs_dir = os.path.join(abs_dir, split[0])
file_name = split[1]
 
for root, dirnames, filenames in os.walk(abs_dir):
if file_name in filenames:
ret_path = os.path.join(root, file_name)
break
 
return ret_path
get_package_asset_tests.py
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
class GetPackageAssetTests(unittest.TestCase):
def test_get_package_asset(self):
tc = get_package_asset
aseq = self.assertEquals
 
# Search sublime-package
res = tc("User", "package_test_asset.txt")
aseq(res, "")
res = tc("User", "not_here.txt")
aseq(res, None)
 
# Search user directory
 
# abc.txt is a nested resource
res = tc("User", "abc.txt", True, True)
aseq(res, os.path.join(sublime.packages_path(), "User", "nested_test", "abc.txt"))
res = tc("User", "abc.txt", False, True, True)
aseq(res, b"\xce\xb2")
res = tc("User", "abc.txt", False, True)
aseq(res, "β")
res = tc("User", "abc.txt", False, False)
aseq(res, None)
 
# Specify absolute path
res = tc("User", "nested_test" + os.sep + "abc.txt", False, True, True)
aseq(res, b"\xce\xb2")
res = tc("User", "nested_test" + os.sep + "abc.txt", False, False, True)
aseq(res, b"\xce\xb2")
 
def test_get_package_and_asset_name(self):
tc = get_package_and_asset_name
aseq = self.assertEquals
 
# Test relative unneted
r1 = (tc("Packages/Relative/one.py"))
r2 = (tc("Packages\\Relative\\one.py"))
r3 = (tc("Packages/Relative/nested/one.py"))
r4 = (tc("Packages\\Relative\\nested\\one.py"))
 
# Test nested
r5 = (tc("C:\\Abs\\Packages\\ZipPseudo.sublime-package\\nested\\sort.py"))
r6 = (tc(sublime.packages_path() + "/Absolute/Nested/asset.pth"))
r7 = (tc(sublime.packages_path() + "\\Absolute\\Nested\\asset.pth"))
r8 = (tc(sublime.installed_packages_path() + "/Absolute.sublime-package/Nested/asset.pth"))
r9 = (tc(sublime.installed_packages_path() + "\\Absolute.sublime-package\\Nested\\asset.pth"))
executable_path = os.path.dirname(sublime.executable_path()) + os.sep + "Packages"
r10 = (tc(executable_path + "/Absolute.sublime-package/Nested/asset.pth"))
r11 = (tc(executable_path + "\\Absolute.sublime-package\\Nested\\asset.pth"))
 
# Test Unnested
r12 = (tc(sublime.packages_path() + "/Absolute/asset.pth"))
r13 = (tc(sublime.packages_path() + "\\Absolute\\asset.pth"))
r14 = (tc(sublime.installed_packages_path() + "/Absolute.sublime-package/asset.pth"))
r15 = (tc(sublime.installed_packages_path() + "\\Absolute.sublime-package\\asset.pth"))
executable_path = os.path.dirname(sublime.executable_path()) + os.sep + "Packages"
r16 = (tc(executable_path + "/Absolute.sublime-package/asset.pth"))
r17 = (tc(executable_path + "\\Absolute.sublime-package\\asset.pth"))
 
aseq(r1, ('Relative', 'one.py'))
aseq(r2, ('Relative', 'one.py'))
aseq(r3, ('Relative', 'nested/one.py'))
aseq(r4, ('Relative', 'nested\\one.py'))
# aseq(r3, ('ZipPseudo', 'nested/sort.py'))
aseq(r5, (None, None))
aseq(r6, ('Absolute', 'Nested' + os.sep + 'asset.pth'))
aseq(r7, ('Absolute', 'Nested' + os.sep + 'asset.pth'))
aseq(r8, ('Absolute', 'Nested' + os.sep + 'asset.pth'))
aseq(r9, ('Absolute', 'Nested' + os.sep + 'asset.pth'))
aseq(r10, ('Absolute', 'Nested' + os.sep + 'asset.pth'))
aseq(r11, ('Absolute', 'Nested' + os.sep + 'asset.pth'))
 
aseq(r12, ('Absolute', 'asset.pth'))
aseq(r13, ('Absolute', 'asset.pth'))
aseq(r14, ('Absolute', 'asset.pth'))
aseq(r15, ('Absolute', 'asset.pth'))
aseq(r16, ('Absolute', 'asset.pth'))
aseq(r17, ('Absolute', 'asset.pth'))

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.