Skip to content

Instantly share code, notes, and snippets.

@vmuriart
Forked from kaste/Main.sublime-menu
Created June 24, 2017 14:31
Show Gist options
  • Save vmuriart/41cda77ec2a01b4c6f0048ac8d1cc522 to your computer and use it in GitHub Desktop.
Save vmuriart/41cda77ec2a01b4c6f0048ac8d1cc522 to your computer and use it in GitHub Desktop.

Revisions

  1. @kaste kaste revised this gist Dec 5, 2013. 2 changed files with 2 additions and 12 deletions.
    10 changes: 0 additions & 10 deletions Default.sublime-commands
    Original file line number Diff line number Diff line change
    @@ -1,10 +0,0 @@
    [
    {"caption": "PyTest: Set and Run", "command": "run_pytest",
    "args": {"rerun": false}},
    {"caption": "PyTest: Overview", "command": "run_pytest",
    "args": {"options": "--tb=line --lf"}},
    {"caption": "PyTest: Re-Run last test", "command": "run_pytest",
    "args": {"rerun": true}},
    {"caption": "PyTest: Clear markers", "command": "pytest_set_markers"}

    ]
    4 changes: 2 additions & 2 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -6,8 +6,8 @@ The plugin basically runs (and re-runs) some given tests, and annotates your fil

    You usually set up at least two keyboard shortcuts.

    { "keys": ["ctrl+t"], "command": "run_pytest", "args": {"rerun": true}},
    { "keys": ["ctrl+shift+t"], "command": "run_pytest", "args": {"rerun": false}}
    { "keys": ["ctrl+t"], "command": "pytest_rerun"},
    { "keys": ["ctrl+shift+t"], "command": "pytest_set_and_run"}

    With that given, hit `ctrl+shift+t` while you're in a test and the file will be run. `ctrl-t` will re-run the command at any time. If you `ctrl+shift+t` while not editing a test, **all** tests will be run. Again `ctrl+t` will re-run the last command.

  2. @kaste kaste revised this gist Dec 5, 2013. 1 changed file with 94 additions and 0 deletions.
    94 changes: 94 additions & 0 deletions xexec.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,94 @@
    import sublime
    import os

    standard_exec = __import__("exec")


    class ExecCommand(standard_exec.ExecCommand):
    def create_output_view(self, title):
    view = self.window.new_file()
    view.settings().set("no_history", True)
    # view.settings().set("gutter", False)
    view.settings().set("line_numbers", False)

    view.settings().set("syntax", "Packages/Python/Python.tmLanguage")
    view.set_name(title)
    view.set_scratch(True)
    return view

    def run(self, cmd = [], file_regex = "", line_regex = "", working_dir = "",
    encoding = "utf-8", env = {}, quiet = False, kill = False,
    title = "", # xeno.by
    # Catches "path" and "shell"
    **kwargs):

    if kill:
    if self.proc:
    self.proc.kill()
    self.proc = None
    self.append_data(None, "[Cancelled]")
    return

    # modified version of xeno.by:
    wannabes = filter(lambda v: v.name() == (title or " ".join(cmd)),
    self.window.views())
    if len(wannabes):
    self.output_view = wannabes[0]

    self.output_view.show(self.output_view.size())
    self.output_view.set_read_only(False)
    edit = self.output_view.begin_edit()
    self.output_view.erase(edit, sublime.Region(0, self.output_view.size()))
    self.output_view.sel().clear()
    self.output_view.sel().add(sublime.Region(self.output_view.size()))
    self.output_view.end_edit(edit)
    self.output_view.set_read_only(True)
    else:
    self.output_view = self.create_output_view(title or " ".join(cmd))

    # Default the to the current files directory if no working directory was given
    if (working_dir == "" and self.window.active_view()
    and self.window.active_view().file_name()):
    working_dir = os.path.dirname(self.window.active_view().file_name())

    self.output_view.settings().set("result_file_regex", file_regex)
    self.output_view.settings().set("result_line_regex", line_regex)
    self.output_view.settings().set("result_base_dir", working_dir)

    self.encoding = encoding
    self.quiet = quiet

    self.proc = None
    if not self.quiet:
    print "Running " + " ".join(cmd)
    sublime.status_message("Running " + " ".join(cmd))

    merged_env = env.copy()
    if self.window.active_view():
    user_env = self.window.active_view().settings().get('build_env')
    if user_env:
    merged_env.update(user_env)

    # Change to the working dir, rather than spawning the process with it,
    # so that emitted working dir relative path names make sense
    if working_dir != "":
    os.chdir(working_dir)

    err_type = OSError
    if os.name == "nt":
    err_type = WindowsError

    try:
    # Forward kwargs to AsyncProcess
    self.proc = standard_exec.AsyncProcess(cmd, merged_env, self, **kwargs)
    except err_type as e:
    self.append_data(None, str(e) + "\n")
    self.append_data(None, "[cmd: " + str(cmd) + "]\n")
    self.append_data(None, "[dir: " + str(os.getcwdu()) + "]\n")
    if "PATH" in merged_env:
    self.append_data(None, "[path: " + str(merged_env["PATH"]) + "]\n")
    else:
    self.append_data(None, "[path: " + str(os.environ["PATH"]) + "]\n")
    if not self.quiet:
    self.append_data(None, "[Finished]")

  3. @kaste kaste revised this gist Dec 5, 2013. 1 changed file with 44 additions and 0 deletions.
    44 changes: 44 additions & 0 deletions Main.sublime-menu
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,44 @@
    [
    {
    "caption": "Preferences",
    "mnemonic": "n",
    "id": "preferences",
    "children":
    [
    {
    "caption": "Package Settings",
    "mnemonic": "P",
    "id": "package-settings",
    "children":
    [
    {
    "caption": "PyTest Runner",
    "children":
    [
    // {
    // "command": "open_file",
    // "args": {"file": "${packages}/SublimeOnSaveBuild/README.md"},
    // "caption": "README"
    // },
    // { "caption": "-" },
    {
    "command": "open_file",
    "args": {"file": "${packages}/PyTest/PyTest.sublime-settings"},
    "caption": "Settings – Default"
    },
    {
    "command": "open_file",
    "args": {"file": "${packages}/User/PyTest.sublime-settings"},
    "caption": "Settings – User"
    },
    {
    "command": "open_file_settings",
    "caption": "Settings – Syntax Specific – User"
    }
    ]
    }
    ]
    }
    ]
    }
    ]
  4. @kaste kaste revised this gist Dec 5, 2013. 1 changed file with 10 additions and 0 deletions.
    10 changes: 10 additions & 0 deletions Default.sublime-commands
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,10 @@
    [
    {"caption": "PyTest: Set and Run", "command": "run_pytest",
    "args": {"rerun": false}},
    {"caption": "PyTest: Overview", "command": "run_pytest",
    "args": {"options": "--tb=line --lf"}},
    {"caption": "PyTest: Re-Run last test", "command": "run_pytest",
    "args": {"rerun": true}},
    {"caption": "PyTest: Clear markers", "command": "pytest_set_markers"}

    ]
  5. @kaste kaste revised this gist Dec 5, 2013. 1 changed file with 255 additions and 0 deletions.
    255 changes: 255 additions & 0 deletions PyTest.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,255 @@
    import sublime
    import sublime_plugin

    import sys
    import os
    import functools



    class TemporaryStorage(object):
    settings = {}
    markers = []

    LastRun = TemporaryStorage()

    class Settings(object):
    def __init__(self, name):
    self.name = name

    @property
    def global_(self):
    return sublime.load_settings(self.name + '.sublime-settings')

    @property
    def user(self):
    try:
    return (sublime.active_window().active_view()
    .settings().get(self.name, {}))
    except:
    return {}

    def get(self, key, default=None):
    return self.user.get(key, self.global_.get(key, default))

    Settings = Settings(__name__)



    class PytestSetAndRunCommand(sublime_plugin.WindowCommand):
    def run(self, options=None):
    """"""
    settings = self.get_settings()
    if options:
    settings['options'] = options
    else:
    settings['options'] = Settings.get('first')

    self.window.run_command("pytest_run", settings)
    LastRun.settings = settings


    def get_settings(self):
    rv = {}
    for key in ['pytest', 'working_dir', 'file_regex']:
    rv[key] = Settings.get(key)

    view = self.window.active_view()
    env = environment(view)
    try:
    filename = env['file_base']
    if "_test" in filename or "test_" in filename:
    rv['target'] = env['file']
    else:
    rv['target'] = Settings.get('tests_dir').format(**env)
    except KeyError:
    rv['target'] = Settings.get('tests_dir').format(**env)

    return rv


    class PytestRerunCommand(sublime_plugin.WindowCommand):
    def run(self, options=None):
    """"""
    settings = LastRun.settings
    if not settings:
    self.window.run_command("pytest_set_and_run")
    return

    if options:
    settings['options'] = options
    else:
    settings['options'] = Settings.get("then")

    self.window.run_command("pytest_run", settings)


    def environment(view):
    window = view.window()

    rv = {}

    filename = view.file_name()
    if filename:
    rv['file'] = filename
    rv['file_path'] = os.path.dirname(filename)
    rv['file_base'] = os.path.basename(filename)


    if window and window.folders():
    rv['project_path'] = window.folders()[0]
    elif filename:
    rv['project_path'] = rv['file_path']

    if 'project_path' in rv:
    rv['project_base'] = os.path.basename(rv['project_path'])

    return rv



    class PytestRunCommand(sublime_plugin.WindowCommand):
    def run(self, **kwargs):
    """
    kwargs: pytest, options, target, working_dir, file_regex
    """
    args = self.make_args(kwargs)
    sublime.status_message("Running %s" % args['cmd'][0])

    save = Settings.get('save_before_test')
    if save is True:
    av = self.window.active_view()
    if av and av.is_dirty():
    self.window.run_command("save")
    elif save == 'all':
    selfs.window.run_command("save_all")

    output_view = Settings.get('output')
    if output_view == 'panel':
    self.window.run_command("test_exec", args)
    if Settings.get('hide_panel_unless_failures'):
    self.window.run_command("hide_panel", {"panel": "output.exec"})

    elif output_view == 'view':
    args['title'] = "Test Results"
    self.window.run_command("test_xexec", args)


    def make_args(self, kwargs):
    env = environment(self.window.active_view())
    for key in ['pytest', 'target', 'working_dir']:
    kwargs[key] = kwargs[key].format(**env)

    command = "{pytest} {options} {target}".format(**kwargs)

    return {
    "file_regex": kwargs['file_regex'],
    "cmd": [command],
    "shell": True,
    "working_dir": kwargs['working_dir'],
    "quiet": True
    }





    def annotate_view(view, markers):
    filename = view.file_name()
    if not filename:
    return

    view.erase_regions('PyTestRunner')

    regions = []
    for marker in markers:
    fn, line, h = marker
    if sys.platform == 'win32':
    # we have a cygwin like path e.g. "/c/users" instead of "c:\"
    fn = os.path.normpath(fn)
    fn = fn[2:]
    filename = os.path.splitdrive(filename)[1]

    if fn == filename:
    region = view.full_line(view.text_point(line-1, h))
    regions.append(region)

    view.add_regions('PyTestRunner', regions,
    'markup.deleted.diff',
    'bookmark',
    sublime.DRAW_OUTLINED)


    class PytestSetMarkersCommand(sublime_plugin.WindowCommand):
    def run(self, markers=[]):
    LastRun.markers = markers

    # immediately paint the visible tabs
    window = sublime.active_window()
    views = [window.active_view_in_group(group)
    for group in range(window.num_groups())]

    # print markers
    for view in views:
    annotate_view(view, markers)

    class PytestMarkCurrentViewCommand(sublime_plugin.EventListener):
    def on_activated(self, view):
    markers = LastRun.markers
    # print markers
    annotate_view(view, markers)



    standard_exec = __import__('exec')
    import xexec

    class TestExecCommand(standard_exec.ExecCommand):

    def run(self, **kw):
    self.dots = ""
    return super(TestExecCommand, self).run(**kw)

    def finish(self, proc):
    super(TestExecCommand, self).finish(proc)
    sublime.status_message("Ran %s tests." % len(self.dots))

    markers = self.output_view.find_all_results()
    # we can't serialize a tuple in the settings, so we listify each marker
    markers = [list(marker) for marker in markers]

    sublime.active_window().run_command("pytest_set_markers",
    {"markers": markers})

    def append_dots(self, dot):
    self.dots += dot
    sublime.status_message("Testing " + self.dots[-400:])

    if dot in 'FX':
    sublime.active_window().run_command(
    "show_panel", {"panel": "output.exec"})

    def on_data(self, proc, data):
    # print ">>", proc, ">>", data
    if data in '.FxXs':
    sublime.set_timeout(functools.partial(self.append_dots, data), 0)
    super(TestExecCommand, self).on_data(proc, data)

    class TestXexecCommand(xexec.ExecCommand):

    def finish(self, proc):
    super(TestXexecCommand, self).finish(proc)

    markers = self.output_view.find_all_results()
    # we can't serialize a tuple in the settings, so we listify each marker
    markers = [list(marker) for marker in markers]

    sublime.active_window().run_command("pytest_set_markers",
    {"markers": markers})







  6. @kaste kaste revised this gist Dec 5, 2013. 1 changed file with 38 additions and 0 deletions.
    38 changes: 38 additions & 0 deletions PyTest.sublime-settings
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,38 @@
    {
    // point to your py.test executable
    // usually use the one from your virtualenv
    // e.g. "~/venvs/{project_base}/scripts/py.test"
    "pytest": "py.test",

    "options": "--tb=long --lf",

    // the options for the first run (t.i.not a re-run)
    // I like to have a "--tb=line" here so I get an overview, probably I just
    // have a couple of failures pointing to the same line
    "first": "--tb=line",

    // the options to use on consecutive calls
    "then": "--tb=short",

    // usually your project_path (which is the first folder in your project
    // settings)
    "working_dir": "{project_path}",

    // where your tests are located
    // usually below your project_path so use a relative path
    // e.g. "tests" "foo/tests"
    "tests_dir": "",

    // false | true | 'all'
    // if true saves the current view only
    "save_before_test": true,

    // determines the kind of the output view. Either 'panel' or 'view'
    "output": "panel",

    "hide_panel_unless_failures": true,


    "file_regex": "^(.*):([0-9]+):"

    }
  7. @kaste kaste created this gist Dec 5, 2013.
    31 changes: 31 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,31 @@
    # py.test plugin for the sublime text editor

    The plugin basically runs (and re-runs) some given tests, and annotates your files using the tracebacks.

    # common workflow

    You usually set up at least two keyboard shortcuts.

    { "keys": ["ctrl+t"], "command": "run_pytest", "args": {"rerun": true}},
    { "keys": ["ctrl+shift+t"], "command": "run_pytest", "args": {"rerun": false}}

    With that given, hit `ctrl+shift+t` while you're in a test and the file will be run. `ctrl-t` will re-run the command at any time. If you `ctrl+shift+t` while not editing a test, **all** tests will be run. Again `ctrl+t` will re-run the last command.

    By default, the output panel will only show up if there are actually any failures. The traceback will be annotated in your source files.

    # install

    Manually download/clone from github and put it in your Packages directory.

    At least **look** at the global settings. You usually have to edit the `pytest` setting to point at your py.test from your current virtualenv (the default is to run your global py.test which is usually *not* what you want). E.g.

    "pytest": "~/venvs/{project_base}/bin/py.test"
    OR:
    "pytest": ".env\\Scripts\\py.test"
    OR even:
    "pytest": "venv/path/to/python -m pytest"

    The plugin will expand {project_path}, {project_base}, {file}, {file_path} and {file_base}.