Sublime Forum

Permission denied when creating folder

#1

My plugin resides in the packages folder under Packages/PluginX. When I try to create a folder named PluginX in the Packages/PluginX folder I get en error:

  File "./python3.3/os.py", line 251, in makedirs
  File "./python3.3/os.py", line 262, in makedirs

PermissionError: [Errno 13] Permission denied: 'PluginX'

My Code:

def plugin_loaded():
    command = TestCommand()

class TestCommand(sublime_plugin.ApplicationCommand):
    def __init__(self):
        self.createPaths()

    def createPaths(self):
        project_name = 'PluginX'
        project_path = os.path.join(sublime.packages_path(), project_name)
        if not os.path.exists(project_path):
            os.makedirs(project_path)
1 Like

#2

Some ideas:

  1. Use os.makedirs(project_path, exist_ok=True)
  2. Don’t instantiate commands yourself unless you know what you’re doing
  3. Don’t define __init__
  4. Define a run(self) method that calls self.createPaths(). Invoke your command with sublime.run_command("test") (you can do this from the console)
1 Like

#3

I’m still not sure about the plugin lifecycle flow, what is the reason for 2 and 3?
I need to perform some preliminary work on plugin load before run is executed (index files)

1 Like

#4

The API to call commands is to use sublime.run_command(...) for ApplicationCommands, window.run_command(...) for WindowCommands and view.run_command(...) for TextCommands. Sublime may or may not do various set up and teardown before running a command. As for __init__, it’s honestly fine to define one yourself, but you could also do all of your initialization in your run method. Sublime calls is_enabled on each command to decide if it should show up in the menu’s and command palette. If you do your initialization in the init method, all that initialization was for nothing if the command is not enabled.

That said, if you don’t use is_enabled then the command is always enabled and you can just as well do your initialization in the init method.

1 Like

#5

When the plugin is loaded:

  1. does Sublime instantiate all of the commands?
  2. Is the command object alive in the background after the command has finished running?
1 Like

#6

Sublime will only instantiate a command when a call to run_command is made. It’ll be cleaned up by the GC once the run method has finished and there are no more references to it.

Well, if by “finished running” you mean “the end of the run method”, then usually yes, but sometimes no. This depends on your run implementation. For instance, you could have a command that asks the user for input. The run method may call self.window.show_quick_panel, and then exit. But the quick panel is still there, and it was given a reference to a callback method of the command, so the command must stay alive.

All this talk about lifetime doesn’t really matter… Python will take care of it.

1 Like

#7

Thanks for the detailed explanation. How is_enabled can help me perform commands
in a certain order? ie. On plugin load, Cmd1 must run before Cmd2, and Cmd2 can’t run if Cmd1 didn’t before.

1 Like

#8

You could use a simple boolean flag to denote if Cmd1 has run at least once. Then do something like


_cmd1_has_run_once = False

class Cmd1Command(sublime_plugin.ApplicationCommand):
    def run(self):
        global _cmd1_has_run_once
        _cmd1_has_run_once = True
        print("command1")

class Cmd2Command(sublime_plugin.ApplicationCommand):
    def is_enabled(self):
        return _cmd1_has_run_once

    def run(self):
        print("command2")

I have to note that is_enabled is only useful for user interaction, so it’s only useful if you also have a Main.sublime-menu file and/or a PluginX.sublime-commands in your plugin folder.

About plugin_loaded: you don’t have to call any commands in there, just use your regular ol’ python functions.

1 Like

#9

Thank you. I’ll explore your recommendations

1 Like

#10

Is there a way to force sublime to keep an object alive for as long as sublime is running?

0 Likes

#11

That is what global variables do.

0 Likes

#12

I’m aware of global variables, just thought there’s a more elegant way of doing it.
Sublime command API isn’t really geared towards plugins that need to maintain a state.

0 Likes

#13

Sublime API is for python programs (packages, plugins, addons, addins, …, any name you call it) to interact with the Sublime Text editor and extend it, improve, customize it. For everything else, there is Python language.

0 Likes