Sublime Forum

Depending on an extra module in a plugin

#1

So for the plugin I am developing, I have an extra module in the packages directory that I need to import.
In my plugin I use:

[code]from os.path import dirname
import sys

sys.path.insert(0, dirname(file))[/code]

to set the Python path for resolving. Is this the way to go about it in Sublime?

Edit: this trick seemed to work when I put my stuff in %APPDATA%\Sublime Text\Packages\User, but now that I moved to making my plugin a real package and placed it all in %APPDATA%\Sublime Text\Packages<NAME> I get an ImportError when the module tried to load one of its own files. Any hints/tips?

1 Like

#2

Ok, I am officially stumped on this one.

So my package resides in %APPDATA%\Sublime Text\Packages\MyPackage, in this I have my plugin code, plugin.py, and a subdirectory which is a full Python module. Now with or without any sys.path() tricks I simply keep on getting ImportErrors and others due to the module not being able to find specific files in MyPackage\module\subdir. Any hints/tips?

0 Likes

#3

sys.path will tell you which dirs python searches for modules. Remeber that there’s the Sublime python interpreter and possibly your system’s python. You only care about the first one.

How to add dirs to your python path

There are several ways to do this. Also, keep in mind that Sublime uses some tricks to work around paths containing unicode characters. As a result, all top-level folders under Packages are added to the python path, I think.

But I digress. Here’s how you can add directories to your python path:

  1. Append to sys.path from your module.
  2. Use pth files (I don’t know if these work under Sublime).
  3. Add the path to your PYTHONPATH env var.
  4. Create a package folder.

Go for (4), since most likely you are storing the code inside a Sublime package (terminology clash!–don’t conflate Sublime package with Python package). To create a python package, simply add a init.py file into any directory in your python path. That way you tell the interpreter to search for modules within that folder too.

(3) should work by setting env vars from Sublime option files, but I’ve never tried myself yet.

Hope that helps!

0 Likes

#4

I guess my posts were not clear enough.

Thanks for the explanation, but I am well versed in the Python module resolving. :smile:

I already have a package directory inside the %APPDATA%\Sublime Text\Packages for my package. The extra module (directory with subdirectories) lives in %APPDATA%\Sublime Text\Packages\MyPackage. Even if I sys.path.insert() MyPackage and/or MyPackage\module I still get problems with the module not being able to import lower directories/files in its directory structure. Funnily enough, this seems to work as it should when the files are just residing in %APPDATA%\Sublime Text\Packages\User.

0 Likes

#5

I think you’re doing something wrong, although I don’t know what. You shouldn’t need to alter sys.path().

As an example look at the WinSCP plugin

  • I have it installed in “Packages\WinSCP”
  • I have an external library installed in “Packages\WinSCP\grizzled\net\ftp\parse.py”, with a init.py in each of the directories.
  • In the plugin I use “from grizzled.net.ftp import parse”

It works, nothing special to do. Just copy the python module in your own package folder and do an import.

0 Likes

#6

In my case I am using Pygments in my plugin.

So I have Packages\Pygmentize as my package with pygmentize.py and Pygmentize.package-menu in this directoy and the pygments main module directory as well.

In my pygmentize.py file I do:

[code]from pygments import highlight
from pygments.lexers import get_lexer_by_name
from pygments.formatters import get_formatter_by_name

import sublime
import sublimeplugin

class DoPygmentize(sublimeplugin.TextCommand):
def run(self, view, args):
formatter = view.options().getString(‘pygmentsFormatter’) or u’html’
formatter = get_formatter_by_name(formatter)
…[/code]
When I run this from the plugin I get:

Traceback (most recent call last): File ".\sublimeplugin.py", line 119, in execTextCommand File ".\pygmentize.py", line 20, in run File ".\pygments\formatters\__init__.py", line 51, in get_formatter_by_name File ".\pygments\formatters\html.py", line 341, in __init__ File ".\pygments\formatter.py", line 67, in __init__ File ".\pygments\formatter.py", line 22, in _lookup_style File ".\pygments\styles\__init__.py", line 55, in get_style_by_name pygments.util.ClassNotFound: Could not find style module 'default', though it should be builtin.
This is despite every subdirectory having an init.py.

The part leading up to this in styles_init_.py:

try: mod = __import__('pygments.styles.' + mod, None, None, [cls]) except ImportError: raise ClassNotFound("Could not find style module %r" % mod + (builtin and ", though it should be builtin") + ".")

0 Likes

#7

Did you try to manually import the module to see if it works?

import pygments.styles.default
0 Likes

#8

I’m not quite sure what the cause of the issue is, but I suspect it’ll go away if you include pygments as an egg, rather than have it there as a subdirectory: Sublime Text adds all .egg files to the python path, so none of the importing weirdness that has to be done should effect them.

0 Likes

#9

Yes, that also fails, but it shouldn’t.

Within Sublime Text I get:

>>> import pygments.styles.default Traceback (most recent call last): File "<string>", line 1, in <module> ImportError: No module named default
And from a normal Python 2.6 environment:

[code]Python 2.6.5 (r265:79063, Aug 12 2010, 11:13:06)
[GCC 4.2.1 20070719 [FreeBSD]] on freebsd8
Type “help”, “copyright”, “credits” or “license” for more information.

import pygments.styles.default
[/code]

0 Likes

#10

Yeah, using an .egg works.

0 Likes

#11

Well almost.

Working on Python files it seems to do what it should.

When I try the same on a C++ or CSS file, I am suddenly greeted with:

IOError: zipimport: can not open file Pygments-1.3.1-py2.6.egg

Whereas doing the same steps with the exact same parameters from the internal interpreter console works.

Call me baffled. :open_mouth:

0 Likes

#12

OK, no idea why it initially worked on the .py files, but it doesn’t on this other install I have at work.

The sys.path shows that the egg is after the ‘.’.

'python26.zip', u'C:\\Users\\39865jru\\AppData\\Roaming\\Sublime Text\\Packages\\ZenCoding', '.', u'Pygments-1.3.1-py2.6.egg']

But trying to use dirname() on file for my plugin file only gives me back ‘.’. So not much sense in adding that to sys.path.

0 Likes

#13

Doesn’t seem to work. :frowning:

Reloading plugin C:\Users\39865jru\AppData\Roaming\Sublime Text\Packages\Pygmentize/pygmentize.py 'python26.zip', u'C:\\Users\\39865jru\\AppData\\Roaming\\Sublime Text\\Packages\\Pygmentize\\Pygments-1.3.1-py2.6.egg', u'C:\\Users\\39865jru\\AppData\\Roaming\\Sublime Text\\Packages\\ZenCoding', 'C:\\Users\\39865jru\\AppData\\Roaming\\Sublime Text\\Packages\\AAALoadFirstExtensions\\site-packages', 'C:\\Users\\39865jru\\AppData\\Roaming\\Sublime Text\\Packages\\AAALoadFirstExtensions', '.', u'Pygments-1.3.1-py2.6.egg', 'C:\\Python25\\Lib\\site-packages\\CherryPy-3.1.2-py2.5-win32.egg'] Traceback (most recent call last): File ".\sublimeplugin.py", line 119, in execTextCommand File ".\pygmentize.py", line 17, in run formatter = get_formatter_by_name(formatter) File "build\bdist.win32\egg\pygments\formatters\__init__.py", line 51, in get_formatter_by_name File "build\bdist.win32\egg\pygments\formatters\html.py", line 341, in __init__ File "build\bdist.win32\egg\pygments\formatter.py", line 67, in __init__ File "build\bdist.win32\egg\pygments\formatter.py", line 22, in _lookup_style File "build\bdist.win32\egg\pygments\styles\__init__.py", line 52, in get_style_by_name IOError: zipimport: can not open file Pygments-1.3.1-py2.6.egg

The code is over at bitbucket.org/asmodai/pygments-plugin in case someone wants to try with their installation. Maybe it’s something on my boxes that’s screwing up.

(Curious CherryPy include, must be AAA that’s doing that I guess, since I have no C:\Python25.)

0 Likes

#14

Yes, I do. Just wonder why it insists on putting that CherryPy on the path though. :smile:

0 Likes

#15

But that’s what I initially had done, unless I am totally misunderstanding what you are stating here.

0 Likes