Sublime Forum

Cant import a nested submodule from a plugin (ST2)

#1

My plugin (https://github.com/jdc0589/JsFormat/tree/jsbeautifier_upgrade) has a dependency on the jsbeautifier project (https://github.com/einars/js-beautify/tree/master/python). Previously I was able to just copy a single file over from the jsbeautifier project, but they have re-organized the strucure of the jsbeautifier/python submodule. Something about how sublime sets the path up is preventing the ‘unpackers’ submodule of jsbeautifier from being imported (it cant find it).

the basic structure of my plugin and jsbeautifier is as follows:

JsFormat
> Default (Linux).sublime-keymap
> js_formatter.py
> jsbeautifier
>> __init__.py (not empty)
>> tests
>>> __init__.py
>> unpackers
>>> __init__.py (not empty)

js_formatter.py contains the sublime textcommand for my plugin, which imports and runs jsbeautifier. jsbeautifier/init.py attempts to ‘import jsbeautifier.unpackers’, which fails, and is the real problem. The import fails on jsbeautifier/init.py line 255. If I fire up a python repl from the root of the plugin directory importing jsbeautifier or jsbeautifier.unpackers works as expected.

I have tried changing the import logic of my plugin as follows, but it has not resolved the problem:

import sublime, sublime_plugin, re, sys, os

directory = os.path.dirname(os.path.realpath(__file__)) + "\\"
jsb_unpackers = directory+"\\jsbeautifier\\unpackers\\"
sys.path.append(jsb_unpackers)

import jsbeautifier

Any suggestions?

1 Like

#2

You are going to kick yourself when you see how easy it is :smile:.

ST3 now treats each plugin folder kind of like it was a python module…so…assuming your plugin is found in a folder named JsFormat…

import JsFormat.jsbeautifier as jsbeautifier

Tah dah!

Side note, also initialize your settings object under a function called plugin_loaded (its a ST3 thing)

def plugin_loaded(): global s s = sublime.load_settings("JsFormat.sublime-settings")

1 Like

#3

[quote=“facelessuser”]You are going to kick yourself when you see how easy it is :smile:.

ST3 now treats each plugin folder kind of like it was a python module…so…assuming your plugin is found in a folder named JsFormat…

import JsFormat.jsbeautifier as jsbeautifier

Tah dah!

Side note, also initialize your settings object under a function called plugin_loaded (its a ST3 thing)

def plugin_loaded(): global s s = sublime.load_settings("JsFormat.sublime-settings")[/quote]

Cool, ill have to try it out in ST3. However this is really in reference to ST2, as that’s where my current userbase is.

0 Likes

#4

Pays to fully read the post…sorry…

Seems to only import globally correctly (top of file)…weird.

I don’t have a good anser off hand. Seems like some kind of ST python environment issue.

0 Likes

#5

I think when python is inside a function it is accessing the jsbeautifier module loaded in sys.modules, and that module does not expose unpackers because you never import it globally.

Here look at this: no unpacker found:

>>print dir(sys.modules'jsbeautifier']) 'Beautifier', 'BeautifierFlags', 'BeautifierOptions', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', 'beautify', 'beautify_file', 'default_options', 'getopt', 'main', 're', 'string', 'sys', 'usage']

I think when importing globally it isn’t looking at the module in sys.module, but using the path to find unpacker.

0 Likes

#6

Haven’t read this in great detail … but …

You can get into trouble with run time imports, cause the sublime text 2 does that retarded os.chdir() workaround

You basically have to pre-emptively import everything you wanna use while the current working directory is correct …

Dunno if that applies here …

Note also sys.path.append(pth) can give quite different results to sys.path.insert(0, pth) depending on the situation …

With the former you can still run into runtime import issues

0 Likes

#7

True, inserting at the beginning will ensure you get the module path you want used first instead of something else getting used before what you appended at the end.

0 Likes

#8

Oddly enough it looks like the following path modifications as well as explicitly importin jsbeautifier.unpackers (even though I don’t use it directly in my plugin) fixes the issue:

import sublime, sublime_plugin, re, sys, os

directory = os.path.dirname(os.path.realpath(__file__)) + "\\"
sys.path.append(directory+"\\jsbeaufifier")
sys.path.append(directory+"\\jsbeautifier\\unpackers")

import jsbeautifier, jsbeautifier.unpackers

The seems like a pretty bad hack…but if it works reliably then I guess I don’t care. Better than being stuck on an outdated version of jsbeautifier.

0 Likes