diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 1677714..0000000 --- a/.coveragerc +++ /dev/null @@ -1,8 +0,0 @@ -[run] -omit = - */tests/* - */vendor/* - */_compat/* - -[report] -show_missing = True diff --git a/.flake8 b/.flake8 deleted file mode 100644 index 9fd7e92..0000000 --- a/.flake8 +++ /dev/null @@ -1,12 +0,0 @@ -[flake8] - -ignore = - E731, # do not assign a lambda expression, use a def - W503, # line break before binary operator - -exclude = - .git, - st3/sublime_lib/vendor, - .venv, - -max-line-length = 99 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cb9629f..6eeb2b6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,39 +3,15 @@ name: CI on: [push, pull_request] jobs: - flake8: + black: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 - + - uses: actions/checkout@v5 - name: Setup Python - uses: actions/setup-python@v1 + uses: actions/setup-python@v6 with: - python-version: 3.x - - - name: Install flake8 - run: | - python -m pip install -U pip - pip install flake8 - - - run: flake8 . - - pydocstyle: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - - name: Setup Python - uses: actions/setup-python@v1 - with: - python-version: 3.x - - - name: Install pydocstyle - run: | - python -m pip install -U pip - pip install pydocstyle - - - name: Run pydocstyle (allow failure) - run: pydocstyle - working-directory: st3/sublime_lib - continue-on-error: true + python-version: 3 + - name: Install black + run: pip --disable-pip-version-check --no-color install black + - name: Run black + run: black --check . diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml new file mode 100644 index 0000000..80cad57 --- /dev/null +++ b/.github/workflows/publish-release.yml @@ -0,0 +1,19 @@ +name: Publish Release + +on: + workflow_dispatch: + +jobs: + release: + name: Create and publish release + env: + GH_TOKEN: ${{ github.token }} + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - name: Install uv + uses: astral-sh/setup-uv@v6 + - name: Building wheel and publishing release + run: scripts/release diff --git a/.gitignore b/.gitignore index 00ac3f8..d27229c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,23 @@ -__pycache__ -.mypy_cache +# editors +.sublime/ +.vscode/ + +# python cache +__pycache__/ +*.pickle +*.py[co] + +# tool cache +.pytest_cache/ +.mypy_cache/ +.venv/ +*.lock + +# build output +dist/ + +# documentation docs/html/ docs/source/modules/ *.doctree -*.pickle modules.rst diff --git a/.sublime-dependency b/.sublime-dependency deleted file mode 100644 index 8a0f05e..0000000 --- a/.sublime-dependency +++ /dev/null @@ -1 +0,0 @@ -01 diff --git a/LICENSE b/LICENSE index 507e13d..1ce6696 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018 Thomas Smith +Copyright (c) 2025 Thomas Smith Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/docs/source/conf.py b/docs/source/conf.py index a1887f0..fe65647 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -14,20 +14,21 @@ # import os import sys -sys.path.insert(0, os.path.abspath('../../st3')) -sys.path.insert(0, os.path.abspath('extensions')) -sys.path.insert(0, os.path.abspath('mocks')) + +sys.path.insert(0, os.path.abspath("../../st3")) +sys.path.insert(0, os.path.abspath("extensions")) +sys.path.insert(0, os.path.abspath("mocks")) # -- Project information ----------------------------------------------------- -project = 'sublime_lib' -copyright = '2018, Thomas Smith' -author = 'Thomas Smith' +project = "sublime_lib" +copyright = "2018, Thomas Smith" +author = "Thomas Smith" # The short X.Y version -version = '' +version = "" # The full version, including alpha/beta/rc tags -release = '' +release = "" # -- General configuration --------------------------------------------------- @@ -40,30 +41,27 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.intersphinx', - 'sphinxcontrib.prettyspecialmethods', + "sphinx.ext.autodoc", + "sphinx.ext.intersphinx", + "sphinxcontrib.prettyspecialmethods", ] -autodoc_member_order = 'bysource' -autodoc_default_options = { - 'members': None, - 'mock_imports': ['sublime_plugin'] -} +autodoc_member_order = "bysource" +autodoc_default_options = {"members": None, "mock_imports": ["sublime_plugin"]} -intersphinx_mapping = {'python': ('https://docs.python.org/3', None)} +intersphinx_mapping = {"python": ("https://docs.python.org/3", None)} # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] -source_suffix = '.rst' +source_suffix = ".rst" # The master toctree document. -master_doc = 'index' +master_doc = "index" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -78,7 +76,7 @@ exclude_patterns = [] # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # -- Options for HTML output ------------------------------------------------- @@ -86,21 +84,20 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'basic' +html_theme = "basic" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # -html_theme_options = { -} +html_theme_options = {} html_experimental_html5_writer = True # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # Custom sidebar templates, must be a dictionary that maps document names # to template names. @@ -112,9 +109,7 @@ # # html_sidebars = {} -html_sidebars = {'**': [ - "localtoc.html" -]} +html_sidebars = {"**": ["localtoc.html"]} html_use_index = False html_use_smartypants = False @@ -123,9 +118,11 @@ def setup(app): from better_toctree import TocTreeCollector + app.add_env_collector(TocTreeCollector) - app.add_css_file('style.css') + app.add_css_file("style.css") from strip_annotations import strip_annotations - app.connect('autodoc-process-signature', strip_annotations) + + app.connect("autodoc-process-signature", strip_annotations) diff --git a/docs/source/mocks/sublime.py b/docs/source/mocks/sublime.py index 7c97f9a..459f3fb 100644 --- a/docs/source/mocks/sublime.py +++ b/docs/source/mocks/sublime.py @@ -12,10 +12,10 @@ def __repr__(self): class SublimeMock: - Region = MockType('sublime.Region') - View = MockType('sublime.View') - Window = MockType('sublime.Window') - Settings = MockType('sublime.Settings') + Region = MockType("sublime.Region") + View = MockType("sublime.View") + Window = MockType("sublime.Window") + Settings = MockType("sublime.Settings") def __getattr__(self, key): if key.isupper(): diff --git a/mypy.ini b/mypy.ini deleted file mode 100644 index 8417946..0000000 --- a/mypy.ini +++ /dev/null @@ -1,12 +0,0 @@ -[mypy] -check_untyped_defs = True -disallow_untyped_defs = True -mypy_path = - st3, - stubs, - -[mypy-sublime_lib.vendor.*] -ignore_errors=True - -[mypy-sublime_lib._compat.typing_stubs] -disallow_untyped_defs = False diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..f865826 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,40 @@ +[project] +name = "sublime_lib" +version = "1.6.0" +description = "Utility library for frequently used functionality in Sublime Text" +readme = "README.md" +license = {file = "LICENSE"} +authors = [{name = "FichteFoll"}, {name = "Thom1729"}] +classifiers = [ + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + "Topic :: Software Development :: Libraries :: Python Modules", +] +requires-python = ">= 3.3" + +[build-system] +requires = ["flit_core"] +build-backend = "flit_core.buildapi" + +[tool.flit.sdist] +include = ["src/**/*.py"] +exclude = ["**/__pycache__/", "**/.*/", "*.lock"] + +[tool.black] +line-length = 100 +exclude = "(.mypy_cache|docs/source/extensions|src/sublime_lib/vendor|stubs)/" + +[tool.coverage.run] +omit = [ + "*/_compat/*", + "*/tests/*", + "*/vendor/*", +] + +[tool.coverage.report] +show_missing = true + +[tool.pyright] +pythonVersion = "3.3" +typeCheckingMode = "basic" diff --git a/scripts/release b/scripts/release new file mode 100755 index 0000000..f321c5f --- /dev/null +++ b/scripts/release @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# build wheel +uv build --wheel +# create release +version=$(uv version | cut -d ' ' -f 2) +gh release create --generate-notes --latest -t "v${version}" "v${version}" dist/*.whl diff --git a/st3/sublime_lib/__init__.py b/src/sublime_lib/__init__.py similarity index 100% rename from st3/sublime_lib/__init__.py rename to src/sublime_lib/__init__.py diff --git a/st3/sublime_lib/_compat/__init__.py b/src/sublime_lib/_compat/__init__.py similarity index 100% rename from st3/sublime_lib/_compat/__init__.py rename to src/sublime_lib/_compat/__init__.py diff --git a/st3/sublime_lib/_compat/enum.py b/src/sublime_lib/_compat/enum.py similarity index 100% rename from st3/sublime_lib/_compat/enum.py rename to src/sublime_lib/_compat/enum.py diff --git a/st3/sublime_lib/_compat/pathlib.py b/src/sublime_lib/_compat/pathlib.py similarity index 100% rename from st3/sublime_lib/_compat/pathlib.py rename to src/sublime_lib/_compat/pathlib.py diff --git a/st3/sublime_lib/_compat/typing.py b/src/sublime_lib/_compat/typing.py similarity index 100% rename from st3/sublime_lib/_compat/typing.py rename to src/sublime_lib/_compat/typing.py diff --git a/st3/sublime_lib/_compat/typing_stubs.py b/src/sublime_lib/_compat/typing_stubs.py similarity index 68% rename from st3/sublime_lib/_compat/typing_stubs.py rename to src/sublime_lib/_compat/typing_stubs.py index 25c70b7..8c86d07 100644 --- a/st3/sublime_lib/_compat/typing_stubs.py +++ b/src/sublime_lib/_compat/typing_stubs.py @@ -7,10 +7,7 @@ def __getitem__(self, args): if not isinstance(args, tuple): args = (args,) - name = '{}[{}]'.format( - str(self), - ', '.join(map(str, args)) - ) + name = "{}[{}]".format(str(self), ", ".join(map(str, args))) return _MakeType(name) def __str__(self): @@ -19,79 +16,74 @@ def __str__(self): __all__ = [ # Super-special typing primitives. - 'Any', - 'Callable', - 'ClassVar', - 'Generic', - 'Optional', - 'Tuple', - 'Type', - 'TypeVar', - 'Union', - + "Any", + "Callable", + "ClassVar", + "Generic", + "Optional", + "Tuple", + "Type", + "TypeVar", + "Union", # ABCs (from collections.abc). - 'AbstractSet', # collections.abc.Set. - 'GenericMeta', # subclass of abc.ABCMeta and a metaclass - # for 'Generic' and ABCs below. - 'ByteString', - 'Container', - 'ContextManager', - 'Hashable', - 'ItemsView', - 'Iterable', - 'Iterator', - 'KeysView', - 'Mapping', - 'MappingView', - 'MutableMapping', - 'MutableSequence', - 'MutableSet', - 'Sequence', - 'Sized', - 'ValuesView', + "AbstractSet", # collections.abc.Set. + "GenericMeta", # subclass of abc.ABCMeta and a metaclass + # for 'Generic' and ABCs below. + "ByteString", + "Container", + "ContextManager", + "Hashable", + "ItemsView", + "Iterable", + "Iterator", + "KeysView", + "Mapping", + "MappingView", + "MutableMapping", + "MutableSequence", + "MutableSet", + "Sequence", + "Sized", + "ValuesView", # The following are added depending on presence # of their non-generic counterparts in stdlib: - 'Awaitable', - 'AsyncIterator', - 'AsyncIterable', - 'Coroutine', - 'Collection', - 'AsyncGenerator', + "Awaitable", + "AsyncIterator", + "AsyncIterable", + "Coroutine", + "Collection", + "AsyncGenerator", # AsyncContextManager - # Structural checks, a.k.a. protocols. - 'Reversible', - 'SupportsAbs', - 'SupportsBytes', - 'SupportsComplex', - 'SupportsFloat', - 'SupportsInt', - 'SupportsRound', - + "Reversible", + "SupportsAbs", + "SupportsBytes", + "SupportsComplex", + "SupportsFloat", + "SupportsInt", + "SupportsRound", # Concrete collection types. - 'Counter', - 'Deque', - 'Dict', - 'DefaultDict', - 'List', - 'Set', - 'FrozenSet', - 'NamedTuple', # Not really a type. - 'Generator', - + "Counter", + "Deque", + "Dict", + "DefaultDict", + "List", + "Set", + "FrozenSet", + "NamedTuple", # Not really a type. + "Generator", # One-off things. - 'AnyStr', - 'cast', - 'get_type_hints', - 'NewType', - 'no_type_check', - 'no_type_check_decorator', - 'overload', - 'Text', - 'TYPE_CHECKING', - - 'ChainMap', - 'NoReturn', + "AnyStr", + "cast", + "get_type_hints", + "NewType", + "no_type_check", + "no_type_check_decorator", + "overload", + "Text", + "TYPE_CHECKING", + "ChainMap", + "NoReturn", ] diff --git a/st3/sublime_lib/_util/__init__.py b/src/sublime_lib/_util/__init__.py similarity index 100% rename from st3/sublime_lib/_util/__init__.py rename to src/sublime_lib/_util/__init__.py diff --git a/st3/sublime_lib/_util/collections.py b/src/sublime_lib/_util/collections.py similarity index 68% rename from st3/sublime_lib/_util/collections.py rename to src/sublime_lib/_util/collections.py index cac381b..8134602 100644 --- a/st3/sublime_lib/_util/collections.py +++ b/src/sublime_lib/_util/collections.py @@ -3,19 +3,16 @@ from .._compat.typing import Callable, Dict, Iterable, TypeVar, Union -_V = TypeVar('_V') -_Result = TypeVar('_Result') -_Default = TypeVar('_Default') +_V = TypeVar("_V") +_Result = TypeVar("_Result") +_Default = TypeVar("_Default") _Value = Union[bool, int, float, str, list, dict, None] -__all__ = ['projection', 'get_selector', 'isiterable', 'ismapping', 'is_sequence_not_str'] +__all__ = ["projection", "get_selector", "isiterable", "ismapping", "is_sequence_not_str"] -def projection( - d: Dict[str, _V], - keys: Union[Dict[str, str], Iterable[str]] -) -> Dict[str, _V]: +def projection(d: Dict[str, _V], keys: Union[Dict[str, str], Iterable[str]]) -> Dict[str, _V]: """ Return a new :class:`dict` with keys of ``d`` restricted to values in ``keys``. @@ -34,16 +31,10 @@ def projection( """ if isinstance(keys, dict): return { - new_key: d[original_key] - for original_key, new_key in keys.items() - if original_key in d + new_key: d[original_key] for original_key, new_key in keys.items() if original_key in d } else: - return { - key: d[key] - for key in keys - if key in d - } + return {key: d[key] for key in keys if key in d} def get_selector(selector: object, default_value: object = None) -> Callable: # noqa: F811 @@ -54,9 +45,7 @@ def get_selector(selector: object, default_value: object = None) -> Callable: # elif isiterable(selector): return lambda this: projection(this, selector) # type: ignore else: - raise TypeError( - 'The selector should be a function, string, or iterable of strings.' - ) + raise TypeError("The selector should be a function, string, or iterable of strings.") def isiterable(obj: object) -> bool: diff --git a/st3/sublime_lib/_util/enum.py b/src/sublime_lib/_util/enum.py similarity index 73% rename from st3/sublime_lib/_util/enum.py rename to src/sublime_lib/_util/enum.py index eb8aa1b..4c3e7ee 100644 --- a/st3/sublime_lib/_util/enum.py +++ b/src/sublime_lib/_util/enum.py @@ -4,7 +4,7 @@ from .._compat.typing import Any, Callable, Optional -__all__ = ['ExtensibleConstructorMeta', 'construct_with_alternatives', 'construct_union'] +__all__ = ["ExtensibleConstructorMeta", "construct_with_alternatives", "construct_union"] class ExtensibleConstructorMeta(EnumMeta): @@ -12,9 +12,7 @@ def __call__(cls, *args: Any, **kwargs: Any) -> Any: return cls.__new__(cls, *args, **kwargs) # type: ignore -def extend_constructor( - constructor: Callable[..., Enum] -) -> Callable[[EnumMeta], EnumMeta]: +def extend_constructor(constructor: Callable[..., Enum]) -> Callable[[EnumMeta], EnumMeta]: def decorator(cls: EnumMeta) -> EnumMeta: next_constructor = partial(cls.__new__, cls) @@ -28,10 +26,11 @@ def __new__(cls: EnumMeta, *args: Any, **kwargs: Any) -> Enum: def construct_with_alternatives( - provider: Callable[..., Optional[Enum]] + provider: Callable[..., Optional[Enum]], ) -> Callable[[EnumMeta], EnumMeta]: - def constructor(next_constructor: Callable[..., Enum], cls: EnumMeta, - *args: Any, **kwargs: Any) -> Enum: + def constructor( + next_constructor: Callable[..., Enum], cls: EnumMeta, *args: Any, **kwargs: Any + ) -> Enum: try: return next_constructor(*args, **kwargs) except ValueError: @@ -45,9 +44,7 @@ def constructor(next_constructor: Callable[..., Enum], cls: EnumMeta, def _construct_union( - next_constructor: Callable[[Any], Flag], - cls: ExtensibleConstructorMeta, - *args: Any + next_constructor: Callable[[Any], Flag], cls: ExtensibleConstructorMeta, *args: Any ) -> Any: if args: ret, *rest = iter(next_constructor(arg) for arg in args) diff --git a/src/sublime_lib/_util/glob.py b/src/sublime_lib/_util/glob.py new file mode 100644 index 0000000..94824fe --- /dev/null +++ b/src/sublime_lib/_util/glob.py @@ -0,0 +1,53 @@ +import re +from functools import lru_cache + +from .._compat.typing import Callable + +__all__ = ["get_glob_matcher"] + + +GLOB_RE = re.compile( + r"""(?x)( + \* + | \? + | \[ .*? \] +)""" +) + + +@lru_cache() +def get_glob_matcher(pattern: str) -> Callable[[str], bool]: + if pattern.startswith("/"): + pattern = pattern[1:] + else: + pattern = "**/" + pattern + + expr_string = r"\A" + for component in pattern.split("/"): + if component == "": + pass + elif component == "*": + # Component must not be empty. + expr_string += r"(?:[^/])+" + "/" + elif component == "**": + expr_string += r"(?:.*(?:\Z|/))?" + elif "**" in component: + raise ValueError("Invalid pattern: '**' can only be an entire path component") + else: + for part in GLOB_RE.split(component): + if part == "": + pass + elif part == "*": + expr_string += r"(?:[^/])*" + elif part == "?": + expr_string += r"(?:[^/])" + elif part[0] == "[": + expr_string += part + else: + expr_string += re.escape(part) + expr_string += "/" + + expr_string = expr_string.rstrip("/") + r"\Z" + expr = re.compile(expr_string) + + return lambda path: (expr.search(path) is not None) diff --git a/st3/sublime_lib/_util/guard.py b/src/sublime_lib/_util/guard.py similarity index 86% rename from st3/sublime_lib/_util/guard.py rename to src/sublime_lib/_util/guard.py index e08f2c8..19724b1 100644 --- a/st3/sublime_lib/_util/guard.py +++ b/src/sublime_lib/_util/guard.py @@ -3,13 +3,13 @@ from .._compat.typing import Any, Callable, ContextManager, Optional, TypeVar -_Self = TypeVar('_Self') -_R = TypeVar('_R') +_Self = TypeVar("_Self") +_R = TypeVar("_R") _WrappedType = Callable[..., _R] def define_guard( - guard_fn: Callable[[_Self], Optional[ContextManager]] + guard_fn: Callable[[_Self], Optional[ContextManager]], ) -> Callable[[_WrappedType], _WrappedType]: def decorator(wrapped: _WrappedType) -> _WrappedType: @wraps(wrapped) diff --git a/st3/sublime_lib/_util/named_value.py b/src/sublime_lib/_util/named_value.py similarity index 85% rename from st3/sublime_lib/_util/named_value.py rename to src/sublime_lib/_util/named_value.py index e58ddc0..32ad9bd 100644 --- a/st3/sublime_lib/_util/named_value.py +++ b/src/sublime_lib/_util/named_value.py @@ -1,4 +1,4 @@ -class NamedValue(): +class NamedValue: def __init__(self, name: str): self.name = name diff --git a/st3/sublime_lib/_util/simple_yaml.py b/src/sublime_lib/_util/simple_yaml.py similarity index 78% rename from st3/sublime_lib/_util/simple_yaml.py rename to src/sublime_lib/_util/simple_yaml.py index 0a8ac24..c239fff 100644 --- a/st3/sublime_lib/_util/simple_yaml.py +++ b/src/sublime_lib/_util/simple_yaml.py @@ -5,14 +5,13 @@ YamlScalar = Union[str, bool, None] -__all__ = ['parse_simple_top_level_keys'] +__all__ = ["parse_simple_top_level_keys"] def parse_simple_top_level_keys(text: str) -> Dict[YamlScalar, YamlScalar]: return { - _parse_yaml_value(match.group(1)): - _parse_yaml_value(match.group(2)) - for match in re.finditer(r'(?m)^([^\s#].*?\s*): *(.+) *$', text) + _parse_yaml_value(match.group(1)): _parse_yaml_value(match.group(2)) + for match in re.finditer(r"(?m)^([^\s#].*?\s*): *(.+) *$", text) } diff --git a/st3/sublime_lib/_util/weak_method.py b/src/sublime_lib/_util/weak_method.py similarity index 95% rename from st3/sublime_lib/_util/weak_method.py rename to src/sublime_lib/_util/weak_method.py index 4f9d377..f518db5 100644 --- a/st3/sublime_lib/_util/weak_method.py +++ b/src/sublime_lib/_util/weak_method.py @@ -4,7 +4,7 @@ from types import MethodType -__all__ = ['weak_method'] +__all__ = ["weak_method"] def weak_method(method: Callable) -> Callable: diff --git a/st3/sublime_lib/activity_indicator.py b/src/sublime_lib/activity_indicator.py similarity index 82% rename from st3/sublime_lib/activity_indicator.py rename to src/sublime_lib/activity_indicator.py index e6095be..718792c 100644 --- a/st3/sublime_lib/activity_indicator.py +++ b/src/sublime_lib/activity_indicator.py @@ -11,17 +11,15 @@ from threading import Lock -__all__ = ['ActivityIndicator'] +__all__ = ["ActivityIndicator"] class StatusTarget(metaclass=ABCMeta): # pragma: no cover @abstractmethod - def set(self, message: str) -> None: - ... + def set(self, message: str) -> None: ... @abstractmethod - def clear(self) -> None: - ... + def clear(self) -> None: ... class WindowTarget(StatusTarget): @@ -39,7 +37,7 @@ class ViewTarget(StatusTarget): def __init__(self, view: sublime.View, key: Optional[str] = None) -> None: self.view = view if key is None: - self.key = '_{!s}'.format(uuid4()) + self.key = "_{!s}".format(uuid4()) else: self.key = key @@ -62,6 +60,7 @@ class ActivityIndicator: .. versionadded:: 1.4 """ + width = 10 # type: int interval = 100 # type: int @@ -93,12 +92,7 @@ def __del__(self) -> None: def __enter__(self) -> None: self.start() - def __exit__( - self, - exc_type: type, - exc_value: Exception, - traceback: TracebackType - ) -> None: + def __exit__(self, exc_type: type, exc_value: Exception, traceback: TracebackType) -> None: self.stop() def start(self) -> None: @@ -109,14 +103,11 @@ def start(self) -> None: """ with self._lock: if self._running: - raise ValueError('Timer is already running') + raise ValueError("Timer is already running") else: self._running = True self.update() - sublime.set_timeout( - partial(self._run, self._invocation_id), - self.interval - ) + sublime.set_timeout(partial(self._run, self._invocation_id), self.interval) def stop(self) -> None: """ @@ -134,10 +125,7 @@ def _run(self, invocation_id: int) -> None: with self._lock: if invocation_id == self._invocation_id: self.tick() - sublime.set_timeout( - partial(weak_method(self._run), invocation_id), - self.interval - ) + sublime.set_timeout(partial(weak_method(self._run), invocation_id), self.interval) def tick(self) -> None: self._ticks += 1 @@ -152,7 +140,7 @@ def render(self, ticks: int) -> str: after = self.width - before return "{}[{}={}]".format( - self.label + ' ' if self.label else '', + self.label + " " if self.label else "", " " * before, " " * after, ) diff --git a/st3/sublime_lib/encodings.py b/src/sublime_lib/encodings.py similarity index 93% rename from st3/sublime_lib/encodings.py rename to src/sublime_lib/encodings.py index 1857996..4fe9999 100644 --- a/st3/sublime_lib/encodings.py +++ b/src/sublime_lib/encodings.py @@ -1,6 +1,6 @@ from codecs import lookup -__all__ = ['from_sublime', 'to_sublime'] +__all__ = ["from_sublime", "to_sublime"] def from_sublime(name: str) -> str: @@ -82,7 +82,6 @@ def to_sublime(name: str) -> str: STANDARD_TO_SUBLIME = { # noqa: E121 - standard_name: sublime_name - for sublime_name, standard_name in SUBLIME_TO_STANDARD.items() + standard_name: sublime_name for sublime_name, standard_name in SUBLIME_TO_STANDARD.items() } -STANDARD_TO_SUBLIME['utf-16'] = 'UTF-16 LE with BOM' +STANDARD_TO_SUBLIME["utf-16"] = "UTF-16 LE with BOM" diff --git a/st3/sublime_lib/flags.py b/src/sublime_lib/flags.py similarity index 90% rename from st3/sublime_lib/flags.py rename to src/sublime_lib/flags.py index 0027ff5..7c43dc2 100644 --- a/st3/sublime_lib/flags.py +++ b/src/sublime_lib/flags.py @@ -41,25 +41,42 @@ __all__ = [ - 'DialogResult', 'PointClass', 'FindOption', 'RegionOption', - 'PopupOption', 'PhantomLayout', 'OpenFileOption', 'QuickPanelOption', - 'HoverLocation', 'QueryContextOperator', 'CompletionOptions' + "DialogResult", + "PointClass", + "FindOption", + "RegionOption", + "PopupOption", + "PhantomLayout", + "OpenFileOption", + "QuickPanelOption", + "HoverLocation", + "QueryContextOperator", + "CompletionOptions", ] def autodoc(prefix: Optional[str] = None) -> Callable[[EnumMeta], EnumMeta]: if prefix is None: - prefix_str = '' + prefix_str = "" else: - prefix_str = prefix + '_' + prefix_str = prefix + "_" def decorator(enum: EnumMeta) -> EnumMeta: - enum.__doc__ = (getdoc(enum) or '') + '\n\n' + '\n'.join([ - cleandoc(""" + enum.__doc__ = ( + (getdoc(enum) or "") + + "\n\n" + + "\n".join( + [ + cleandoc( + """ .. py:attribute:: {name} :annotation: = sublime.{pre}{name} - """).format(name=name, pre=prefix_str) for name in enum.__members__ - ]) + """ + ).format(name=name, pre=prefix_str) + for name in enum.__members__ + ] + ) + ) return enum @@ -71,18 +88,19 @@ def decorator(enum: EnumMeta) -> EnumMeta: ) -@autodoc('DIALOG') +@autodoc("DIALOG") @construct_from_name class DialogResult(IntEnum): """ An :class:`~enum.IntEnum` for use with :func:`sublime.yes_no_cancel_dialog`. """ + CANCEL = sublime.DIALOG_CANCEL YES = sublime.DIALOG_YES NO = sublime.DIALOG_NO -@autodoc('CLASS') +@autodoc("CLASS") @construct_union @construct_from_name class PointClass(IntFlag, metaclass=ExtensibleConstructorMeta): @@ -93,6 +111,7 @@ class PointClass(IntFlag, metaclass=ExtensibleConstructorMeta): - :meth:`~sublime.View.find_by_class` - :meth:`~sublime.View.expand_by_class` """ + WORD_START = sublime.CLASS_WORD_START WORD_END = sublime.CLASS_WORD_END PUNCTUATION_START = sublime.CLASS_PUNCTUATION_START @@ -114,6 +133,7 @@ class FindOption(IntFlag, metaclass=ExtensibleConstructorMeta): - :meth:`~sublime.View.find` - :meth:`~sublime.View.find_all` """ + LITERAL = sublime.LITERAL IGNORECASE = sublime.IGNORECASE @@ -125,6 +145,7 @@ class RegionOption(IntFlag, metaclass=ExtensibleConstructorMeta): """ An :class:`~enum.IntFlag` for use with :meth:`sublime.View.add_regions`. """ + DRAW_EMPTY = sublime.DRAW_EMPTY HIDE_ON_MINIMAP = sublime.HIDE_ON_MINIMAP DRAW_EMPTY_AS_OVERWRITE = sublime.DRAW_EMPTY_AS_OVERWRITE @@ -144,18 +165,20 @@ class PopupOption(IntFlag, metaclass=ExtensibleConstructorMeta): """ An :class:`~enum.IntFlag` for use with :meth:`sublime.View.show_popup`. """ + COOPERATE_WITH_AUTO_COMPLETE = sublime.COOPERATE_WITH_AUTO_COMPLETE HIDE_ON_MOUSE_MOVE = sublime.HIDE_ON_MOUSE_MOVE HIDE_ON_MOUSE_MOVE_AWAY = sublime.HIDE_ON_MOUSE_MOVE_AWAY -@autodoc('LAYOUT') +@autodoc("LAYOUT") @construct_union @construct_from_name class PhantomLayout(IntFlag, metaclass=ExtensibleConstructorMeta): """ An :class:`~enum.IntFlag` for use with :class:`sublime.Phantom`. """ + INLINE = sublime.LAYOUT_INLINE BELOW = sublime.LAYOUT_BELOW BLOCK = sublime.LAYOUT_BLOCK @@ -168,6 +191,7 @@ class OpenFileOption(IntFlag, metaclass=ExtensibleConstructorMeta): """ An :class:`~enum.IntFlag` for use with :meth:`sublime.Window.open_file`. """ + ENCODED_POSITION = sublime.ENCODED_POSITION TRANSIENT = sublime.TRANSIENT FORCE_GROUP = sublime.FORCE_GROUP @@ -180,11 +204,12 @@ class QuickPanelOption(IntFlag, metaclass=ExtensibleConstructorMeta): """ An :class:`~enum.IntFlag` for use with :meth:`sublime.Window.show_quick_panel`. """ + MONOSPACE_FONT = sublime.MONOSPACE_FONT KEEP_OPEN_ON_FOCUS_LOST = sublime.KEEP_OPEN_ON_FOCUS_LOST -@autodoc('HOVER') +@autodoc("HOVER") @construct_from_name class HoverLocation(IntEnum): """ @@ -193,13 +218,14 @@ class HoverLocation(IntEnum): .. versionadded:: 1.4 """ + TEXT = sublime.HOVER_TEXT GUTTER = sublime.HOVER_GUTTER MARGIN = sublime.HOVER_MARGIN def regex_match(value: str, operand: str) -> bool: - expr = r'(?:{})\Z'.format(operand) + expr = r"(?:{})\Z".format(operand) return re.match(expr, value) is not None @@ -215,7 +241,7 @@ def not_regex_contains(value: str, operand: str) -> bool: return not regex_contains(value, operand) -@autodoc('OP') +@autodoc("OP") @construct_from_name class QueryContextOperator(IntEnum): """ @@ -246,6 +272,7 @@ def on_query_context(self, view, key, operator, operand, match_all): else: return None """ + EQUAL = (sublime.OP_EQUAL, operator.eq) NOT_EQUAL = (sublime.OP_NOT_EQUAL, operator.ne) REGEX_MATCH = (sublime.OP_REGEX_MATCH, regex_match) @@ -255,7 +282,7 @@ def on_query_context(self, view, key, operator, operand, match_all): # _apply_ = None # type: Callable[[str, str], bool] - def __new__(cls, value: int, operator: Callable[[str, str], bool]) -> 'QueryContextOperator': + def __new__(cls, value: int, operator: Callable[[str, str], bool]) -> "QueryContextOperator": obj = int.__new__(cls, value) # type: ignore obj._value_ = value obj._apply_ = operator @@ -275,5 +302,6 @@ class CompletionOptions(IntFlag, metaclass=ExtensibleConstructorMeta): .. versionadded:: 1.4 """ + INHIBIT_WORD_COMPLETIONS = sublime.INHIBIT_WORD_COMPLETIONS INHIBIT_EXPLICIT_COMPLETIONS = sublime.INHIBIT_EXPLICIT_COMPLETIONS diff --git a/st3/sublime_lib/panel.py b/src/sublime_lib/panel.py similarity index 98% rename from st3/sublime_lib/panel.py rename to src/sublime_lib/panel.py index c5929a5..d7c59c4 100644 --- a/st3/sublime_lib/panel.py +++ b/src/sublime_lib/panel.py @@ -6,10 +6,10 @@ from ._compat.typing import Any -__all__ = ['Panel', 'OutputPanel'] +__all__ = ["Panel", "OutputPanel"] -class Panel(): +class Panel: """An abstraction of a panel, such as the console or an output panel. :raise ValueError: if `window` has no panel called `panel_name`. @@ -81,6 +81,7 @@ class OutputPanel(ViewStream, Panel): .. versionchanged:: 1.3 Now a subclass of :class:`Panel`. """ + @classmethod def create( cls, @@ -91,7 +92,7 @@ def create( follow_cursor: bool = False, unlisted: bool = False, **kwargs: Any - ) -> 'OutputPanel': + ) -> "OutputPanel": """Create a new output panel with the given `name` in the given `window`. If `kwargs` are given, diff --git a/st3/sublime_lib/region_manager.py b/src/sublime_lib/region_manager.py similarity index 91% rename from st3/sublime_lib/region_manager.py rename to src/sublime_lib/region_manager.py index 747a0ab..3f4df1c 100644 --- a/st3/sublime_lib/region_manager.py +++ b/src/sublime_lib/region_manager.py @@ -4,10 +4,10 @@ from .flags import RegionOption -__all__ = ['RegionManager'] +__all__ = ["RegionManager"] -T = TypeVar('T') +T = TypeVar("T") def _coalesce(*values: Optional[T]) -> T: @@ -68,8 +68,8 @@ def set( self.view.add_regions( self.key, regions, - _coalesce(scope, self.scope, ''), - _coalesce(icon, self.icon, ''), + _coalesce(scope, self.scope, ""), + _coalesce(icon, self.icon, ""), _coalesce(flags, self.flags, 0), ) @@ -78,6 +78,5 @@ def get(self) -> List[sublime.Region]: return self.view.get_regions(self.key) def erase(self) -> None: - """Erase all managed regions. - """ + """Erase all managed regions.""" self.view.erase_regions(self.key) diff --git a/st3/sublime_lib/resource_path.py b/src/sublime_lib/resource_path.py similarity index 86% rename from st3/sublime_lib/resource_path.py rename to src/sublime_lib/resource_path.py index f77ed4d..d604aee 100644 --- a/st3/sublime_lib/resource_path.py +++ b/src/sublime_lib/resource_path.py @@ -10,7 +10,7 @@ from ._compat.typing import List, Optional, Tuple, Iterable, Union -__all__ = ['ResourcePath'] +__all__ = ["ResourcePath"] def _abs_parts(path: Path) -> Tuple[str, ...]: @@ -44,6 +44,7 @@ class ResourceRoot(metaclass=ABCMeta): """ Represents a directory containing packages. """ + def __init__(self, root: object, path: Union[Path, str]) -> None: self.resource_root = ResourcePath(root) self.file_root = Path(path) @@ -63,7 +64,7 @@ def resource_to_file_path(self, resource_path: object) -> Path: else: return self._package_file_path(*parts) - def file_to_resource_path(self, file_path: Union[Path, str]) -> Optional['ResourcePath']: + def file_to_resource_path(self, file_path: Union[Path, str]) -> Optional["ResourcePath"]: """ Given an absolute :class:`Path`, return the corresponging :class:`ResourcePath` within this resource root, @@ -85,11 +86,7 @@ def file_to_resource_path(self, file_path: Union[Path, str]) -> Optional['Resour return self._package_resource_path(*parts) @abstractmethod - def _package_file_path( - self, - package: str, - *parts: str - ) -> Path: # pragma: no cover + def _package_file_path(self, package: str, *parts: str) -> Path: # pragma: no cover """ Given a package name and zero or more path segments, return the corresponding :class:`Path` within this resource root. @@ -98,10 +95,8 @@ def _package_file_path( @abstractmethod def _package_resource_path( - self, - package: str, - *parts: str - ) -> 'ResourcePath': # pragma: no cover + self, package: str, *parts: str + ) -> "ResourcePath": # pragma: no cover """ Given a package name and zero or more path segments, return the corresponding :class:`ResourcePath` within this resource root. @@ -113,10 +108,11 @@ class DirectoryResourceRoot(ResourceRoot): """ Represents a directory containing unzipped package directories. """ + def _package_file_path(self, *parts: str) -> Path: return self.file_root.joinpath(*parts) - def _package_resource_path(self, *parts: str) -> 'ResourcePath': + def _package_resource_path(self, *parts: str) -> "ResourcePath": return self.resource_root.joinpath(*parts) @@ -124,12 +120,13 @@ class InstalledResourceRoot(ResourceRoot): """ Represents a directory containing zipped sublime-package files. """ + def _package_file_path(self, package: str, *rest: str) -> Path: # This is not currently called because there are no installed-only roots. - return self.file_root.joinpath(package + '.sublime-package', *rest) + return self.file_root.joinpath(package + ".sublime-package", *rest) - def _package_resource_path(self, package: str, *rest: str) -> 'ResourcePath': - package_path = (self.resource_root / package).remove_suffix('.sublime-package') + def _package_resource_path(self, package: str, *rest: str) -> "ResourcePath": + package_path = (self.resource_root / package).remove_suffix(".sublime-package") return package_path.joinpath(*rest) @@ -147,15 +144,15 @@ def get_roots() -> List[ResourceRoot]: global _ROOTS if _ROOTS is None: _ROOTS = [ - DirectoryResourceRoot('Cache', sublime.cache_path()), - DirectoryResourceRoot('Packages', sublime.packages_path()), - InstalledResourceRoot('Packages', sublime.installed_packages_path()), - InstalledResourceRoot('Packages', Path(sublime.executable_path()).parent / 'Packages'), + DirectoryResourceRoot("Cache", sublime.cache_path()), + DirectoryResourceRoot("Packages", sublime.packages_path()), + InstalledResourceRoot("Packages", sublime.installed_packages_path()), + InstalledResourceRoot("Packages", Path(sublime.executable_path()).parent / "Packages"), ] return _ROOTS -class ResourcePath(): +class ResourcePath: """ A pathlib-inspired representation of a Sublime Text resource path. @@ -189,19 +186,16 @@ class ResourcePath(): """ @classmethod - def glob_resources(cls, pattern: str) -> List['ResourcePath']: + def glob_resources(cls, pattern: str) -> List["ResourcePath"]: """ Find all resources that match the given pattern and return them as :class:`ResourcePath` objects. """ match = get_glob_matcher(pattern) - return [ - cls(path) for path in sublime.find_resources('') - if match(path) - ] + return [cls(path) for path in sublime.find_resources("") if match(path)] @classmethod - def from_file_path(cls, file_path: Union[Path, str]) -> 'ResourcePath': + def from_file_path(cls, file_path: Union[Path, str]) -> "ResourcePath": """ Return a :class:`ResourcePath` corresponding to the given file path. @@ -256,8 +250,9 @@ def __init__(self, *pathsegments: object): def _parse_segments(self, pathsegments: Iterable[object]) -> Tuple[str, ...]: return tuple( part - for segment in pathsegments if segment - for part in posixpath.normpath(str(segment)).split('/') + for segment in pathsegments + if segment + for part in posixpath.normpath(str(segment)).split("/") ) def __hash__(self) -> int: @@ -267,12 +262,12 @@ def __repr__(self) -> str: return "{}({!r})".format(self.__class__.__name__, str(self)) def __str__(self) -> str: - return '/'.join(self.parts) + return "/".join(self.parts) def __eq__(self, other: object) -> bool: return isinstance(other, ResourcePath) and self._parts == other.parts - def __truediv__(self, other: object) -> 'ResourcePath': + def __truediv__(self, other: object) -> "ResourcePath": return self.joinpath(other) @property @@ -283,7 +278,7 @@ def parts(self) -> Tuple[str, ...]: return self._parts @property - def parent(self) -> 'ResourcePath': + def parent(self) -> "ResourcePath": """ The logical parent of the path. A root path is its own parent. """ @@ -293,7 +288,7 @@ def parent(self) -> 'ResourcePath': return self.__class__(*self._parts[:-1]) @property - def parents(self) -> Tuple['ResourcePath', ...]: + def parents(self) -> Tuple["ResourcePath", ...]: """ An immutable sequence providing access to the path's logical ancestors. """ @@ -316,11 +311,11 @@ def suffix(self) -> str: The final component's last suffix, if any. """ name = self.name - i = name.rfind('.') + i = name.rfind(".") if 0 < i < len(name) - 1: return name[i:] else: - return '' + return "" @property def suffixes(self) -> List[str]: @@ -328,10 +323,10 @@ def suffixes(self) -> List[str]: A list of the final component's suffixes, if any. """ name = self.name - if name.endswith('.'): + if name.endswith("."): return [] - name = name.lstrip('.') - return ['.' + suffix for suffix in name.split('.')[1:]] + name = name.lstrip(".") + return ["." + suffix for suffix in name.split(".")[1:]] @property def stem(self) -> str: @@ -339,7 +334,7 @@ def stem(self) -> str: The final path component, minus its last suffix. """ name = self.name - i = name.rfind('.') + i = name.rfind(".") if 0 < i < len(name) - 1: return name[:i] else: @@ -373,7 +368,7 @@ def match(self, pattern: str) -> bool: match = get_glob_matcher(pattern) return match(str(self)) - def joinpath(self, *other: object) -> 'ResourcePath': + def joinpath(self, *other: object) -> "ResourcePath": """ Combine this path with all of the given strings. """ @@ -397,7 +392,7 @@ def relative_to(self, *other: object) -> Tuple[str, ...]: else: raise ValueError("{!s} does not start with {!s}".format(self, other_path)) - def with_name(self, name: str) -> 'ResourcePath': + def with_name(self, name: str) -> "ResourcePath": """ Return a new path with the name changed. """ @@ -406,7 +401,7 @@ def with_name(self, name: str) -> 'ResourcePath': else: return self.parent / name - def add_suffix(self, suffix: str) -> 'ResourcePath': + def add_suffix(self, suffix: str) -> "ResourcePath": """ Return a new path with the suffix added. @@ -416,7 +411,7 @@ def add_suffix(self, suffix: str) -> 'ResourcePath': def remove_suffix( self, suffix: Optional[str] = None, *, must_remove: bool = True - ) -> 'ResourcePath': + ) -> "ResourcePath": """ Return a new path with the suffix removed. @@ -442,21 +437,18 @@ def remove_suffix( suffixes = sorted(suffix, key=len, reverse=True) old_name = self.name - new_name = next(( - old_name[:i] - for s in suffixes - for i in (old_name.rfind(s),) - if i > 0 - ), None) + new_name = next( + (old_name[:i] for s in suffixes for i in (old_name.rfind(s),) if i > 0), None + ) if new_name is not None: return self.with_name(new_name) elif must_remove: - raise ValueError('Cannot remove suffix {!r} from {!r}.'.format(suffix, self)) + raise ValueError("Cannot remove suffix {!r} from {!r}.".format(suffix, self)) else: return self - def with_suffix(self, suffix: str) -> 'ResourcePath': + def with_suffix(self, suffix: str) -> "ResourcePath": """ Return a new path with the suffix changed. @@ -522,16 +514,16 @@ def read_bytes(self) -> bytes: except IOError as err: raise FileNotFoundError(str(self)) from err - def glob(self, pattern: str) -> List['ResourcePath']: + def glob(self, pattern: str) -> List["ResourcePath"]: """ Glob the given pattern at this path, returning all matching resources. :raise ValueError: if `pattern` is invalid. """ - base = '/' + str(self) + '/' if self._parts else '' + base = "/" + str(self) + "/" if self._parts else "" return ResourcePath.glob_resources(base + pattern) - def rglob(self, pattern: str) -> List['ResourcePath']: + def rglob(self, pattern: str) -> List["ResourcePath"]: """ Shorthand for ``path.glob('**/' + pattern)``. @@ -539,12 +531,12 @@ def rglob(self, pattern: str) -> List['ResourcePath']: :raise NotImplementedError: if `pattern` begins with a slash. """ - if pattern.startswith('/'): + if pattern.startswith("/"): raise NotImplementedError("Non-relative patterns are unsupported") - return self.glob('**/' + pattern) + return self.glob("**/" + pattern) - def children(self) -> List['ResourcePath']: + def children(self) -> List["ResourcePath"]: """ Return a list of paths that are direct children of this path and point to a resource at or beneath that path. @@ -553,8 +545,7 @@ def children(self) -> List['ResourcePath']: return [ self / next_part for next_part in OrderedDict.fromkeys( - resource.parts[depth] - for resource in self.glob('**') + resource.parts[depth] for resource in self.glob("**") ) ] @@ -575,12 +566,12 @@ def copy(self, target: object, exist_ok: bool = True) -> None: .. versionadded:: 1.3 """ if exist_ok: - mode = 'w' + mode = "w" else: - mode = 'x' + mode = "x" data = self.read_bytes() - with open(str(target), mode + 'b') as file: + with open(str(target), mode + "b") as file: file.write(data) def copytree(self, target: Union[Path, str], exist_ok: bool = False) -> None: @@ -602,7 +593,7 @@ def copytree(self, target: Union[Path, str], exist_ok: bool = False) -> None: os.makedirs(str(target), exist_ok=exist_ok) - for resource in self.rglob('*'): + for resource in self.rglob("*"): file_path = target.joinpath(*resource.relative_to(self)) os.makedirs(str(file_path.parent), exist_ok=True) resource.copy(file_path) diff --git a/st3/sublime_lib/settings_dict.py b/src/sublime_lib/settings_dict.py similarity index 94% rename from st3/sublime_lib/settings_dict.py rename to src/sublime_lib/settings_dict.py index a5158b0..26d2ae7 100644 --- a/st3/sublime_lib/settings_dict.py +++ b/src/sublime_lib/settings_dict.py @@ -9,16 +9,16 @@ from ._compat.typing import Any, Callable, Iterable, NoReturn, TypeVar, Union, Mapping as _Mapping -_Default = TypeVar('_Default') +_Default = TypeVar("_Default") Value = Union[bool, int, float, str, list, dict, None] -__all__ = ['SettingsDict', 'NamedSettingsDict'] +__all__ = ["SettingsDict", "NamedSettingsDict"] -_NO_DEFAULT = NamedValue('SettingsDict.NO_DEFAULT') +_NO_DEFAULT = NamedValue("SettingsDict.NO_DEFAULT") -class SettingsDict(): +class SettingsDict: """Wraps a :class:`sublime.Settings` object `settings` with a :class:`dict`-like interface. @@ -128,8 +128,7 @@ def pop( return default # type: ignore def setdefault(self, key: str, default: Value = None) -> Value: - """Set `self[key]` to `default` if it wasn't already defined and return `self[key]`. - """ + """Set `self[key]` to `default` if it wasn't already defined and return `self[key]`.""" if key in self: return self[key] else: @@ -137,9 +136,7 @@ def setdefault(self, key: str, default: Value = None) -> Value: return default def update( - self, - other: Union[_Mapping[str, Value], Iterable[Iterable[str]]] = [], - **kwargs: Value + self, other: Union[_Mapping[str, Value], Iterable[Iterable[str]]] = [], **kwargs: Value ) -> None: """Update the dictionary with the key/value pairs from `other`, overwriting existing keys. @@ -210,12 +207,12 @@ class NamedSettingsDict(SettingsDict): def file_name(self) -> str: """The name of the sublime-settings files associated with the :class:`NamedSettingsDict`.""" - return self.name + '.sublime-settings' + return self.name + ".sublime-settings" def __init__(self, name: str): """Return a new :class:`NamedSettingsDict` corresponding to the given name.""" - if name.endswith('.sublime-settings'): + if name.endswith(".sublime-settings"): self.name = name[:-17] else: self.name = name diff --git a/st3/sublime_lib/show_selection_panel.py b/src/sublime_lib/show_selection_panel.py similarity index 94% rename from st3/sublime_lib/show_selection_panel.py rename to src/sublime_lib/show_selection_panel.py index 70ef5cf..e193834 100644 --- a/st3/sublime_lib/show_selection_panel.py +++ b/src/sublime_lib/show_selection_panel.py @@ -7,12 +7,12 @@ from ._compat.typing import Any, Callable, List, Optional, TypeVar, Union, Sequence as _Sequence -_ItemType = TypeVar('_ItemType') +_ItemType = TypeVar("_ItemType") -__all__ = ['show_selection_panel', 'NO_SELECTION'] +__all__ = ["show_selection_panel", "NO_SELECTION"] -NO_SELECTION = NamedValue('NO_SELECTION') +NO_SELECTION = NamedValue("NO_SELECTION") def show_selection_panel( @@ -99,7 +99,7 @@ def normalize_label(label: object) -> List[str]: label_strings = list(map(normalize_label, labels)) max_len = max(map(len, label_strings)) - label_strings = [rows + [''] * (max_len - len(rows)) for rows in label_strings] + label_strings = [rows + [""] * (max_len - len(rows)) for rows in label_strings] def on_done(index: int) -> None: if index == -1: @@ -129,5 +129,5 @@ def on_done(index: int) -> None: on_select=on_done, flags=flags, selected_index=selected_index, - on_highlight=on_highlight_callback + on_highlight=on_highlight_callback, ) diff --git a/st3/sublime_lib/syntax.py b/src/sublime_lib/syntax.py similarity index 58% rename from st3/sublime_lib/syntax.py rename to src/sublime_lib/syntax.py index cab66c5..027457a 100644 --- a/st3/sublime_lib/syntax.py +++ b/src/sublime_lib/syntax.py @@ -6,19 +6,19 @@ from ._compat.typing import List -__all__ = ['list_syntaxes', 'get_syntax_for_scope'] +__all__ = ["list_syntaxes", "get_syntax_for_scope"] -SyntaxInfo = namedtuple('SyntaxInfo', ['path', 'name', 'scope', 'hidden']) +SyntaxInfo = namedtuple("SyntaxInfo", ["path", "name", "scope", "hidden"]) SyntaxInfo.__new__.__defaults__ = (None, None, False) # type: ignore def get_sublime_syntax_metadata(path: ResourcePath) -> dict: yaml = parse_simple_top_level_keys(path.read_text()) return { - 'name': yaml.get('name') or path.stem, - 'hidden': yaml.get('hidden', False), - 'scope': yaml.get('scope'), + "name": yaml.get("name") or path.stem, + "hidden": yaml.get("hidden", False), + "scope": yaml.get("scope"), } @@ -26,9 +26,9 @@ def get_tmlanguage_metadata(path: ResourcePath) -> dict: tree = plistlib.readPlistFromBytes(path.read_bytes()) return { - 'name': tree.get('name') or path.stem, - 'hidden': tree.get('hidden', False), - 'scope': tree.get('scopeName'), + "name": tree.get("name") or path.stem, + "hidden": tree.get("hidden", False), + "scope": tree.get("scopeName"), } @@ -36,24 +36,21 @@ def get_hidden_tmlanguage_metadata(path: ResourcePath) -> dict: tree = plistlib.readPlistFromBytes(path.read_bytes()) return { - 'name': path.stem, # `name` key is ignored - 'hidden': True, # `hidden` key is ignored - 'scope': tree.get('scopeName'), + "name": path.stem, # `name` key is ignored + "hidden": True, # `hidden` key is ignored + "scope": tree.get("scopeName"), } SYNTAX_TYPES = { - '.sublime-syntax': get_sublime_syntax_metadata, - '.tmLanguage': get_tmlanguage_metadata, - '.hidden-tmLanguage': get_hidden_tmlanguage_metadata, + ".sublime-syntax": get_sublime_syntax_metadata, + ".tmLanguage": get_tmlanguage_metadata, + ".hidden-tmLanguage": get_hidden_tmlanguage_metadata, } def get_syntax_metadata(path: ResourcePath) -> SyntaxInfo: - return SyntaxInfo( - path=str(path), - **SYNTAX_TYPES[path.suffix](path) - ) + return SyntaxInfo(path=str(path), **SYNTAX_TYPES[path.suffix](path)) def list_syntaxes() -> List[SyntaxInfo]: @@ -74,16 +71,15 @@ def list_syntaxes() -> List[SyntaxInfo]: Whether the syntax will appear in the syntax menus and the command palette. """ syntax_definition_paths = [ - path for path in ResourcePath.glob_resources('') - if path.suffix in SYNTAX_TYPES + path for path in ResourcePath.glob_resources("") if path.suffix in SYNTAX_TYPES ] return [ get_syntax_metadata(path) for path in syntax_definition_paths if not ( - path.suffix in {'.tmLanguage', '.hidden-tmLanguage'} - and path.with_suffix('.sublime-syntax') in syntax_definition_paths + path.suffix in {".tmLanguage", ".hidden-tmLanguage"} + and path.with_suffix(".sublime-syntax") in syntax_definition_paths ) ] @@ -91,10 +87,6 @@ def list_syntaxes() -> List[SyntaxInfo]: def get_syntax_for_scope(scope: str) -> str: """Returns the last syntax in load order that matches `scope`.""" try: - return next( - syntax.path - for syntax in reversed(list_syntaxes()) - if syntax.scope == scope - ) + return next(syntax.path for syntax in reversed(list_syntaxes()) if syntax.scope == scope) except StopIteration: raise ValueError("Cannot find syntax for scope {!r}.".format(scope)) from None diff --git a/st3/sublime_lib/vendor/__init__.py b/src/sublime_lib/vendor/__init__.py similarity index 100% rename from st3/sublime_lib/vendor/__init__.py rename to src/sublime_lib/vendor/__init__.py diff --git a/st3/sublime_lib/vendor/pathlib/LICENSE.txt b/src/sublime_lib/vendor/pathlib/LICENSE.txt similarity index 100% rename from st3/sublime_lib/vendor/pathlib/LICENSE.txt rename to src/sublime_lib/vendor/pathlib/LICENSE.txt diff --git a/st3/sublime_lib/vendor/pathlib/__init__.py b/src/sublime_lib/vendor/pathlib/__init__.py similarity index 100% rename from st3/sublime_lib/vendor/pathlib/__init__.py rename to src/sublime_lib/vendor/pathlib/__init__.py diff --git a/st3/sublime_lib/vendor/pathlib/pathlib.py b/src/sublime_lib/vendor/pathlib/pathlib.py similarity index 100% rename from st3/sublime_lib/vendor/pathlib/pathlib.py rename to src/sublime_lib/vendor/pathlib/pathlib.py diff --git a/st3/sublime_lib/vendor/pathlib/test_pathlib.py b/src/sublime_lib/vendor/pathlib/test_pathlib.py old mode 100755 new mode 100644 similarity index 100% rename from st3/sublime_lib/vendor/pathlib/test_pathlib.py rename to src/sublime_lib/vendor/pathlib/test_pathlib.py diff --git a/st3/sublime_lib/vendor/python/LICENSE b/src/sublime_lib/vendor/python/LICENSE similarity index 100% rename from st3/sublime_lib/vendor/python/LICENSE rename to src/sublime_lib/vendor/python/LICENSE diff --git a/st3/sublime_lib/vendor/python/README b/src/sublime_lib/vendor/python/README similarity index 100% rename from st3/sublime_lib/vendor/python/README rename to src/sublime_lib/vendor/python/README diff --git a/st3/sublime_lib/vendor/python/__init__.py b/src/sublime_lib/vendor/python/__init__.py similarity index 100% rename from st3/sublime_lib/vendor/python/__init__.py rename to src/sublime_lib/vendor/python/__init__.py diff --git a/st3/sublime_lib/vendor/python/enum.py b/src/sublime_lib/vendor/python/enum.py similarity index 100% rename from st3/sublime_lib/vendor/python/enum.py rename to src/sublime_lib/vendor/python/enum.py diff --git a/st3/sublime_lib/vendor/python/types.py b/src/sublime_lib/vendor/python/types.py similarity index 100% rename from st3/sublime_lib/vendor/python/types.py rename to src/sublime_lib/vendor/python/types.py diff --git a/st3/sublime_lib/view_stream.py b/src/sublime_lib/view_stream.py similarity index 94% rename from st3/sublime_lib/view_stream.py rename to src/sublime_lib/view_stream.py index 2ec8240..cf4932f 100644 --- a/st3/sublime_lib/view_stream.py +++ b/src/sublime_lib/view_stream.py @@ -51,10 +51,10 @@ def guard_read_only(self) -> Generator[Any, None, None]: @contextmanager def guard_auto_indent(self) -> Generator[Any, None, None]: settings = self.view.settings() - if settings.get('auto_indent'): - settings.set('auto_indent', False) + if settings.get("auto_indent"): + settings.set("auto_indent", False) yield - settings.set('auto_indent', True) + settings.set("auto_indent", True) else: yield @@ -126,11 +126,11 @@ def write(self, s: str) -> int: the length of the argument. """ old_size = self.view.size() - self.view.run_command('insert', {'characters': s}) + self.view.run_command("insert", {"characters": s}) self._maybe_show_cursor() return self.view.size() - old_size - def print(self, *objects: object, sep: str = ' ', end: str = '\n') -> None: + def print(self, *objects: object, sep: str = " ", end: str = "\n") -> None: """Shorthand for :func:`print()` passing this ViewStream as the `file` argument.""" print(*objects, file=self, sep=sep, end=end) # type: ignore @@ -205,5 +205,5 @@ def _maybe_show_cursor(self) -> None: @guard_read_only def clear(self) -> None: """Erase all text in the view.""" - self.view.run_command('select_all') - self.view.run_command('left_delete') + self.view.run_command("select_all") + self.view.run_command("left_delete") diff --git a/st3/sublime_lib/view_utils.py b/src/sublime_lib/view_utils.py similarity index 89% rename from st3/sublime_lib/view_utils.py rename to src/sublime_lib/view_utils.py index b93512e..d908b0c 100644 --- a/st3/sublime_lib/view_utils.py +++ b/src/sublime_lib/view_utils.py @@ -11,19 +11,20 @@ from ._compat.typing import Any, Optional, Mapping, Iterable, Generator, Type, TypeVar -EnumType = TypeVar('EnumType', bound=Enum) +EnumType = TypeVar("EnumType", bound=Enum) __all__ = [ - 'LineEnding', 'new_view', 'close_view', + "LineEnding", + "new_view", + "close_view", ] def case_insensitive_value(cls: Type[EnumType], value: str) -> Optional[EnumType]: - return next(( - member for name, member in cls.__members__.items() - if name.lower() == value.lower() - ), None) + return next( + (member for name, member in cls.__members__.items() if name.lower() == value.lower()), None + ) @construct_with_alternatives(case_insensitive_value) @@ -44,9 +45,10 @@ class LineEnding(Enum, metaclass=ExtensibleConstructorMeta): .. versionadded:: 1.2 """ - Unix = '\n' - Windows = '\r\n' - CR = '\r' + + Unix = "\n" + Windows = "\r\n" + CR = "\r" def new_view(window: sublime.Window, **kwargs: Any) -> sublime.View: @@ -98,7 +100,7 @@ def new_view(window: sublime.Window, **kwargs: Any) -> sublime.View: @contextmanager def _temporarily_scratch_unsaved_views( - unsaved_views: Iterable[sublime.View] + unsaved_views: Iterable[sublime.View], ) -> Generator[None, None, None]: buffer_ids = {view.buffer_id() for view in unsaved_views} for view in unsaved_views: @@ -123,7 +125,7 @@ def _clone_view(view: sublime.View) -> sublime.View: raise ValueError("View has no window.") window.focus_view(view) - window.run_command('clone_file') + window.run_command("clone_file") clone = window.active_view() if clone is None: # pragma: no cover raise RuntimeError("Clone was not created.") @@ -143,7 +145,7 @@ def close_view(view: sublime.View, *, force: bool = False) -> None: if unsaved: if not force: - raise ValueError('The view has unsaved changes.') + raise ValueError("The view has unsaved changes.") with _temporarily_scratch_unsaved_views([view]): closed = view.close() @@ -151,19 +153,19 @@ def close_view(view: sublime.View, *, force: bool = False) -> None: closed = view.close() if not closed: - raise ValueError('The view could not be closed.') + raise ValueError("The view could not be closed.") def validate_view_options(options: Mapping[str, Any]) -> None: unknown = set(options) - VIEW_OPTIONS if unknown: - raise ValueError('Unknown view options: %s.' % ', '.join(list(unknown))) + raise ValueError("Unknown view options: %s." % ", ".join(list(unknown))) - if 'scope' in options and 'syntax' in options: + if "scope" in options and "syntax" in options: raise ValueError('The "syntax" and "scope" arguments are exclusive.') - if 'line_endings' in options: - LineEnding(options['line_endings']) + if "line_endings" in options: + LineEnding(options["line_endings"]) def set_view_options( @@ -184,7 +186,7 @@ def set_view_options( view.set_name(name) if content is not None: - view.run_command('append', {'characters': content}) + view.run_command("append", {"characters": content}) if settings is not None: view_settings = view.settings() diff --git a/st3/sublime_lib/window_utils.py b/src/sublime_lib/window_utils.py similarity index 88% rename from st3/sublime_lib/window_utils.py rename to src/sublime_lib/window_utils.py index 35a1579..adf3704 100644 --- a/st3/sublime_lib/window_utils.py +++ b/src/sublime_lib/window_utils.py @@ -4,7 +4,7 @@ from .view_utils import _temporarily_scratch_unsaved_views -__all__ = ['new_window', 'close_window'] +__all__ = ["new_window", "close_window"] def new_window( @@ -54,7 +54,7 @@ def new_window( """ original_ids = set(window.id() for window in sublime.windows()) - sublime.run_command('new_window') + sublime.run_command("new_window") try: window = next(window for window in sublime.windows() if window.id() not in original_ids) @@ -90,16 +90,13 @@ def close_window(window: sublime.Window, *, force: bool = False) -> None: .. versionadded:: 1.2 """ - unsaved = [ - view for view in window.views() - if view.is_dirty() and not view.is_scratch() - ] + unsaved = [view for view in window.views() if view.is_dirty() and not view.is_scratch()] if unsaved: if not force: - raise ValueError('A view has unsaved changes.') + raise ValueError("A view has unsaved changes.") with _temporarily_scratch_unsaved_views(unsaved): - window.run_command('close_window') + window.run_command("close_window") else: - window.run_command('close_window') + window.run_command("close_window") diff --git a/st3/.pydocstyle b/st3/.pydocstyle deleted file mode 100644 index 3ec40c2..0000000 --- a/st3/.pydocstyle +++ /dev/null @@ -1,4 +0,0 @@ -[pydocstyle] - -match_dir = ^(?!_) -match = ^(?!_).*\.py diff --git a/st3/sublime_lib/_util/glob.py b/st3/sublime_lib/_util/glob.py deleted file mode 100644 index d6e178a..0000000 --- a/st3/sublime_lib/_util/glob.py +++ /dev/null @@ -1,51 +0,0 @@ -import re -from functools import lru_cache - -from .._compat.typing import Callable - -__all__ = ['get_glob_matcher'] - - -GLOB_RE = re.compile(r"""(?x)( - \* - | \? - | \[ .*? \] -)""") - - -@lru_cache() -def get_glob_matcher(pattern: str) -> Callable[[str], bool]: - if pattern.startswith('/'): - pattern = pattern[1:] - else: - pattern = '**/' + pattern - - expr_string = r'\A' - for component in pattern.split('/'): - if component == '': - pass - elif component == '*': - # Component must not be empty. - expr_string += r'(?:[^/])+' + '/' - elif component == '**': - expr_string += r'(?:.*(?:\Z|/))?' - elif '**' in component: - raise ValueError("Invalid pattern: '**' can only be an entire path component") - else: - for part in GLOB_RE.split(component): - if part == '': - pass - elif part == '*': - expr_string += r'(?:[^/])*' - elif part == '?': - expr_string += r'(?:[^/])' - elif part[0] == '[': - expr_string += part - else: - expr_string += re.escape(part) - expr_string += '/' - - expr_string = expr_string.rstrip('/') + r'\Z' - expr = re.compile(expr_string) - - return lambda path: (expr.search(path) is not None) diff --git a/stubs/sublime.pyi b/stubs/sublime.pyi deleted file mode 100644 index fe2b920..0000000 --- a/stubs/sublime.pyi +++ /dev/null @@ -1,382 +0,0 @@ -from typing import Tuple, List, Any, Union, Callable, Optional, TypeVar, Collection - -location = Tuple[str, str, Tuple[int, int]] -vector = Tuple[float, float] -value = Union[bool, int, float, str, list, dict, None] - -T = TypeVar('T') -Callback0 = Callable[[], Any] -Callback1 = Callable[[T], Any] - -HOVER_TEXT: int -HOVER_GUTTER: int -HOVER_MARGIN: int - -ENCODED_POSITION: int -TRANSIENT: int -FORCE_GROUP: int -IGNORECASE: int -LITERAL: int -MONOSPACE_FONT: int -KEEP_OPEN_ON_FOCUS_LOST: int -HTML: int -COOPERATE_WITH_AUTO_COMPLETE: int -HIDE_ON_MOUSE_MOVE: int -HIDE_ON_MOUSE_MOVE_AWAY: int - -DRAW_EMPTY: int -HIDE_ON_MINIMAP: int -DRAW_EMPTY_AS_OVERWRITE: int -PERSISTENT: int -DRAW_OUTLINED: int -DRAW_NO_FILL: int -DRAW_NO_OUTLINE: int -DRAW_SOLID_UNDERLINE: int -DRAW_STIPPLED_UNDERLINE: int -DRAW_SQUIGGLY_UNDERLINE: int -HIDDEN: int - -OP_EQUAL: int -OP_NOT_EQUAL: int -OP_REGEX_MATCH: int -OP_NOT_REGEX_MATCH: int -OP_REGEX_CONTAINS: int -OP_NOT_REGEX_CONTAINS: int -CLASS_WORD_START: int -CLASS_WORD_END: int -CLASS_PUNCTUATION_START: int -CLASS_PUNCTUATION_END: int -CLASS_SUB_WORD_START: int -CLASS_SUB_WORD_END: int -CLASS_LINE_START: int -CLASS_LINE_END: int -CLASS_EMPTY_LINE: int -INHIBIT_WORD_COMPLETIONS: int -INHIBIT_EXPLICIT_COMPLETIONS: int - -DIALOG_CANCEL: int -DIALOG_YES: int -DIALOG_NO: int - -UI_ELEMENT_SIDE_BAR: int -UI_ELEMENT_MINIMAP: int -UI_ELEMENT_TABS: int -UI_ELEMENT_STATUS_BAR: int -UI_ELEMENT_MENU: int -UI_ELEMENT_OPEN_FILES: int - -LAYOUT_INLINE: int -LAYOUT_BELOW: int -LAYOUT_BLOCK: int - -def version() -> str: ... -def platform() -> str: ... -def arch() -> str: ... -def channel() -> str: ... -def executable_path() -> str: ... -def executable_hash() -> Tuple[str, str, str]: ... -def packages_path() -> str: ... -def installed_packages_path() -> str: ... -def cache_path() -> str: ... -def status_message(msg: str) -> None: ... -def error_message(msg: str) -> None: ... -def message_dialog(msg: str) -> None: ... -def ok_cancel_dialog(msg: str, ok_title: str = "") -> bool: ... -def yes_no_cancel_dialog(msg: str, yes_title: str = "", no_title: str = "") -> int: ... -def run_command(cmd: str, args: Optional[dict] = None) -> None: ... -def get_clipboard(size_limit: int = 16777216) -> str: ... -def set_clipboard(text: str) -> None: ... -def log_commands(flag: bool) -> None: ... -def log_input(flag: bool) -> None: ... -def log_result_regex(flag: bool) -> None: ... -def log_indexing(flag: bool) -> None: ... -def log_build_systems(flag: bool) -> None: ... -def score_selector(scope_name: str, selector: str) -> int: ... -def load_resource(name: str) -> str: ... -def load_binary_resource(name: str) -> bytes: ... -def find_resources(pattern: str) -> List[str]: ... -def encode_value(val: Any, pretty: bool = False) -> str: ... -def decode_value(data: str) -> Any: ... -def expand_variables(val: Union[str, list, dict], variables: dict) -> str: ... -def load_settings(base_name: str) -> Settings: ... -def save_settings(base_name: str) -> None: ... -def set_timeout(f: Callback0, timeout_ms: int = 0) -> None: ... -def set_timeout_async(f: Callback0, timeout_ms: int = 0) -> None: ... -def active_window() -> Window: ... -def windows() -> List[Window]: ... -def get_macro() -> list: ... - -class Window: - def __init__(self, id: int): ... - def __eq__(self, other: Any) -> bool: ... - def __bool__(self) -> bool: ... - def id(self) -> int: ... - def is_valid(self) -> bool: ... - def hwnd(self) -> int: ... - def active_sheet(self) -> Optional[Sheet]: ... - def active_view(self) -> Optional[View]: ... - def run_command(self, cmd: str, args: Optional[dict] = None) -> None: ... - def new_file(self, flags: int = 0, syntax: str = "") -> View: ... - def open_file(self, fname: str, flags: int = 0, group: int = -1) -> View: ... - def find_open_file(self, fname: str) -> Optional[View]: ... - def num_groups(self) -> int: ... - def active_group(self) -> int: ... - def focus_group(self, idx: int) -> None: ... - def focus_sheet(self, sheet: Sheet) -> None: ... - def focus_view(self, view: View) -> None: ... - def get_sheet_index(self, sheet: Sheet) -> Tuple[int, int]: ... - def get_view_index(self, view: View) -> Tuple[int, int]: ... - def set_sheet_index(self, sheet: Sheet, group: int, idx: int) -> None: ... - def set_view_index(self, view: View, group: int, idx: int) -> None: ... - def sheets(self) -> List[Sheet]: ... - def views(self) -> List[View]: ... - def active_sheet_in_group(self, group: int) -> Optional[Sheet]: ... - def active_view_in_group(self, group: int) -> Optional[View]: ... - def sheets_in_group(self, group: int) -> List[Sheet]: ... - def views_in_group(self, group: int) -> List[View]: ... - def transient_sheet_in_group(self, group: int) -> Optional[Sheet]: ... - def transient_view_in_group(self, group: int) -> Optional[View]: ... - def layout(self) -> dict: ... - def get_layout(self) -> dict: ... - def set_layout(self, layout: dict) -> None: ... - def create_output_panel(self, name: str, unlisted: bool = False) -> View: ... - def find_output_panel(self, name: str) -> Optional[View]: ... - def destroy_output_panel(self, name: str) -> None: ... - def active_panel(self) -> Optional[str]: ... - def panels(self) -> List[str]: ... - def get_output_panel(self, name: str) -> View: ... - def show_input_panel( - self, - caption: str, - initial_text: str, - on_done: Optional[Callback0], - on_change: Optional[Callback1[str]], - on_cancel: Optional[Callback0] - ) -> View: ... - - def show_quick_panel( - self, - items: Union[List[str], List[List[str]]], - on_select: Callback1[int], - flags: int = 0, - selected_index: int = -1, - on_highlight: Optional[Callback1[int]] = None - ) -> None: ... - - def is_sidebar_visible(self) -> bool: ... - def set_sidebar_visible(self, flag: bool) -> None: ... - def is_minimap_visible(self) -> bool: ... - def set_minimap_visible(self, flag: bool) -> None: ... - def is_status_bar_visible(self) -> bool: ... - def set_status_bar_visible(self, flag: bool) -> None: ... - def get_tabs_visible(self) -> bool: ... - def set_tabs_visible(self, flag: bool) -> None: ... - def is_menu_visible(self) -> bool: ... - def set_menu_visible(self, flag: bool) -> None: ... - def folders(self) -> List[str]: ... - def project_file_name(self) -> Optional[str]: ... - def project_data(self) -> dict: ... - def set_project_data(self, v: dict) -> None: ... - def settings(self) -> Settings: ... - def template_settings(self) -> Settings: ... - def lookup_symbol_in_index(self, sym: str) -> List[location]: ... - def lookup_symbol_in_open_files(self, sym: str) -> List[location]: ... - def lookup_references_in_index(self, sym: str) -> List[location]: ... - def lookup_references_in_open_files(self, sym: str) -> List[location]: ... - def extract_variables(self) -> dict: ... - def status_message(self, msg: str) -> None: ... - -class Edit: - def __init__(self, token: int) -> None: ... - -class Region: - __slots__ = ['a', 'b', 'xpos'] - - a = 0 # type: int - b = 0 # type: int - xpos = 0 # type: int - - def __init__(self, a: int, b: Optional[int] = None, xpos: int = -1): ... - def __str__(self) -> str: ... - def __repr__(self) -> str: ... - def __len__(self) -> int: ... - def __eq__(self, rhs: Any) -> bool: ... - def __lt__(self, rhs: Region) -> bool: ... - def empty(self) -> bool: ... - def begin(self) -> int: ... - def end(self) -> int: ... - def size(self) -> int: ... - def contains(self, x: Union[int, Region]) -> bool: ... - def cover(self, rhs: Region) -> Region: ... - def intersection(self, rhs: Region) -> Region: ... - def intersects(self, rhs: Region) -> bool: ... - -class Selection: - def __init__(self, id: int) -> None: ... - def __len__(self) -> int: ... - def __getitem__(self, index: int) -> Region: ... - def __delitem__(self, index: int) -> None: ... - def __eq__(self, rhs: Any) -> bool: ... - def __lt__(self, rhs: Selection) -> bool: ... - def __bool__(self) -> bool: ... - def is_valid(self) -> bool: ... - def clear(self) -> None: ... - def add(self, x: Region) -> None: ... - def add_all(self, regions: List[Region]) -> None: ... - def subtract(self, region: Region) -> None: ... - def contains(self, region: Region) -> bool: ... - -class Sheet: - def __init__(self, id: int) -> None: ... - def __eq__(self, other: Any) -> bool: ... - def id(self) -> int: ... - def window(self) -> Optional[Window]: ... - def view(self) -> Optional[View]: ... - -class View: - def __init__(self, id: int) -> None: ... - def __len__(self) -> int: ... - def __eq__(self, other: Any) -> bool: ... - def __bool__(self) -> bool: ... - def id(self) -> int: ... - def buffer_id(self) -> int: ... - def is_valid(self) -> bool: ... - def is_primary(self) -> bool: ... - def window(self) -> Optional[Window]: ... - def file_name(self) -> Optional[str]: ... - def close(self) -> bool: ... - def retarget(self, new_fname: str) -> None: ... - def name(self) -> str: ... - def set_name(self, name: str) -> None: ... - def reset_reference_document(self) -> None: ... - def set_reference_document(self, reference: str) -> None: ... - def is_loading(self) -> bool: ... - def is_dirty(self) -> bool: ... - def is_read_only(self) -> bool: ... - def set_read_only(self, read_only: bool) -> None: ... - def is_scratch(self) -> bool: ... - def set_scratch(self, scratch: bool) -> None: ... - def encoding(self) -> str: ... - def set_encoding(self, encoding_name: str) -> None: ... - def line_endings(self) -> str: ... - def set_line_endings(self, line_ending_name: str) -> None: ... - def size(self) -> int: ... - def begin_edit(self, edit_token: int, cmd: str, args: Optional[dict] = None) -> Edit: ... - def end_edit(self, edit: Edit) -> None: ... - def is_in_edit(self) -> bool: ... - def insert(self, edit: Edit, pt: int, text: str) -> None: ... - def erase(self, edit: Edit, r: Region) -> None: ... - def replace(self, edit: Edit, r: Region, text: str) -> None: ... - def change_count(self) -> int: ... - def run_command(self, cmd: str, args: Optional[dict] = None) -> None: ... - def sel(self) -> Selection: ... - def substr(self, x: Union[Region, int]) -> str: ... - def find(self, pattern: str, start_pt: int, flags: int = 0) -> Region: ... - def find_all(self, pattern: str, flags: int = 0, fmt: Optional[str] = None, extractions: Optional[list] = None) -> List[Region]: ... - def settings(self) -> Settings: ... - def meta_info(self, key: str, pt: int) -> dict: ... - def extract_tokens_with_scopes(self, r: Region) -> List[Tuple[Region, str]]: ... - def extract_scope(self, pt: int) -> Region: ... - def scope_name(self, pt: int) -> str: ... - def match_selector(self, pt: int, selector: str) -> bool: ... - def score_selector(self, pt: int, selector: str) -> int: ... - def find_by_selector(self, selector: str) -> List[Region]: ... - def style(self) -> dict: ... - def style_for_scope(self, scope: str) -> dict: ... - def indented_region(self, pt: int) -> Region: ... - def indentation_level(self, pt: int) -> int: ... - def has_non_empty_selection_region(self) -> bool: ... - def lines(self, r: Region) -> List[Region]: ... - def split_by_newlines(self, r: Region) -> List[Region]: ... - def line(self, x: Union[int, Region]) -> Region: ... - def full_line(self, x: Union[int, Region]) -> Region: ... - def word(self, x: Union[int, Region]) -> Region: ... - def classify(self, pt: int) -> int: ... - def find_by_class(self, pt: int, forward: bool, classes: int, separators: str = "") -> Region: ... - def expand_by_class(self, x: Union[int, Region], classes: int, separators: str = "") -> Region: ... - def rowcol(self, tp: int) -> Tuple[int, int]: ... - def text_point(self, row: int, col: int) -> int: ... - def visible_region(self) -> Region: ... - def show(self, x: Union[int, Region, Selection], show_surrounds: bool = True) -> None: ... - def show_at_center(self, x: Union[int, Region]) -> None: ... - def viewport_position(self) -> vector: ... - def set_viewport_position(self, xy: vector, animate: bool = True) -> None: ... - def viewport_extent(self) -> vector: ... - def layout_extent(self) -> vector: ... - def text_to_layout(self, tp: int) -> vector: ... - def text_to_window(self, tp: int) -> vector: ... - def layout_to_text(self, xy: vector) -> int: ... - def layout_to_window(self, xy: vector) -> vector: ... - def window_to_layout(self, xy: vector) -> vector: ... - def window_to_text(self, xy: vector) -> int: ... - def line_height(self) -> float: ... - def em_width(self) -> float: ... - def is_folded(self, sr: Region) -> bool: ... - def folded_regions(self) -> List[Region]: ... - def fold(self, x: Union[Region, List[Region]]) -> bool: ... - def unfold(self, x: Union[Region, List[Region]]) -> List[Region]: ... - def add_regions(self, key: str, regions: Collection[Region], scope: str = "", icon: str = "", flags: int = 0) -> None: ... - def get_regions(self, key: str) -> List[Region]: ... - def erase_regions(self, key: str) -> None: ... - def add_phantom(self, key: str, region: Region, content: str, layout: int, on_navigate: Optional[Callback1[str]] = None) -> int: ... - def erase_phantoms(self, key: str) -> None: ... - def erase_phantom_by_id(self, pid: int) -> None: ... - def query_phantom(self, pid: int) -> List[Tuple[int, int]]: ... - def query_phantoms(self, pids: List[int]) -> List[Tuple[int, int]]: ... - def assign_syntax(self, syntax_file: str) -> None: ... - def set_syntax_file(self, syntax_file: str) -> None: ... - def symbols(self) -> List[Tuple[Region, str]]: ... - def get_symbols(self) -> List[Tuple[Region, str]]: ... - def indexed_symbols(self) -> List[Tuple[Region, str]]: ... - def indexed_references(self) -> List[Tuple[Region, str]]: ... - def set_status(self, key: str, value: str) -> None: ... - def get_status(self, key: str) -> None: ... - def erase_status(self, key: str) -> None: ... - def extract_completions(self, prefix: str, tp: int = -1) -> List[str]: ... - def find_all_results(self) -> List[Tuple[str, int, int]]: ... - def find_all_results_with_text(self) -> List[Tuple[str, int, int, str]]: ... - def command_history(self, delta: int, modifying_only: bool = False) -> Tuple[str, dict, int]: ... - def overwrite_status(self) -> bool: ... - def set_overwrite_status(self, value: bool) -> None: ... - def show_popup_menu(self, items: List[str], on_select: Callable[[int], Any], flags: int = 0) -> None: ... - def show_popup( - self, - content: str, - flags: int = 0, - location: int = -1, - max_width: int = 320, - max_height: int = 240, - on_navigate: Optional[Callable[[str], Any]] = None, - on_hide: Optional[Callable[[], Any]] = None - ) -> None: ... - - def update_popup(self, content: str) -> None: ... - def is_popup_visible(self) -> bool: ... - def hide_popup(self) -> None: ... - def is_auto_complete_visible(self) -> bool: ... - -class Settings: - settings_id: int - - def __init__(self, id: int) -> None: ... - def get(self, key: str, default: Any = None) -> Any: ... - def has(self, key: str) -> bool: ... - def set(self, key: str, value: value) -> None: ... - def erase(self, key: str) -> None: ... - def add_on_change(self, tag: str, callback: Callable[[], Any]) -> None: ... - def clear_on_change(self, tag: str) -> None: ... - -class Phantom: - def __init__(self, region: Region, content: str, layout: int, on_navigate: Callable[[str], Any] = None) -> None: ... - def __eq__(self, rhs: Any) -> bool: ... - -class PhantomSet: - def __init__(self, view: View, key: str = "") -> None: ... - def __del__(self) -> None: ... - def update(self, new_phantoms: List[Phantom]) -> None: ... - -class Html: - __slots__ = ['data'] - - def __init__(self, data: Any) -> None: ... - def __str__(self) -> str: ... diff --git a/stubs/sublime_plugin.pyi b/stubs/sublime_plugin.pyi deleted file mode 100644 index 5ad9e28..0000000 --- a/stubs/sublime_plugin.pyi +++ /dev/null @@ -1,127 +0,0 @@ -import sublime - -from typing import Callable, Generic, TypeVar, Optional, Union, List, Tuple, overload - - -InputType = TypeVar('InputType', bound=Union[str, int, float, list, dict, tuple, None]) - - -class CommandInputHandler(Generic[InputType]): - def name(self) -> str: ... - def next_input(self, args: dict) -> Optional[CommandInputHandler]: ... - def placeholder(self) -> str: ... - def initial_text(self) -> str: ... - def preview(self, arg: InputType) -> Union[str, sublime.Html]: ... - def validate(self, arg: InputType) -> bool: ... - def cancel(self) -> None: ... - - @overload - def confirm(self, arg: InputType) -> None: ... - @overload - def confirm(self, arg: InputType, event: dict) -> None: ... - - -class BackInputHandler(CommandInputHandler[None]): - pass - - -class TextInputHandler(CommandInputHandler[str]): - def description(self, text: str) -> str: ... - - -ListItem = Union[str, Tuple[str, InputType]] - - -class ListInputHandler(CommandInputHandler[InputType], Generic[InputType]): - def list_items(self) -> Union[List[ListItem], Tuple[List[ListItem], int]]: ... - def description(self, v: object, text: str) -> str: ... - - -class Command: - def is_enabled(self) -> bool: ... - def is_visible(self) -> bool: ... - def is_checked(self) -> bool: ... - def description(self) -> str: ... - def input(self, args: dict) -> Optional[CommandInputHandler]: ... - def input_description(self) -> str: ... - - -class ApplicationCommand(Command): - run: Callable[..., None] - - -class WindowCommand(Command): - window: sublime.Window - - run: Callable[..., None] - - -class TextCommand(Command): - view: sublime.View - - run: Callable[..., None] - def want_event(self) -> bool: ... - - -Completion = Union[str, Tuple[str, str], List[str]] - -class EventListener: - def on_new(self, view: sublime.View) -> None: ... - def on_new_async(self, view: sublime.View) -> None: ... - def on_clone(self, view: sublime.View) -> None: ... - def on_clone_async(self, view: sublime.View) -> None: ... - def on_load(self, view: sublime.View) -> None: ... - def on_load_async(self, view: sublime.View) -> None: ... - def on_pre_close(self, view: sublime.View) -> None: ... - def on_close(self, view: sublime.View) -> None: ... - def on_pre_save(self, view: sublime.View) -> None: ... - def on_pre_save_async(self, view: sublime.View) -> None: ... - def on_post_save(self, view: sublime.View) -> None: ... - def on_post_save_async(self, view: sublime.View) -> None: ... - def on_modified(self, view: sublime.View) -> None: ... - def on_modified_async(self, view: sublime.View) -> None: ... - def on_selection_modified(self, view: sublime.View) -> None: ... - def on_selection_modified_async(self, view: sublime.View) -> None: ... - def on_activated(self, view: sublime.View) -> None: ... - def on_activated_async(self, view: sublime.View) -> None: ... - def on_deactivated(self, view: sublime.View) -> None: ... - def on_deactivated_async(self, view: sublime.View) -> None: ... - def on_hover(self, view: sublime.View, point: int, hover_zone: int) -> None: ... - def on_query_context(self, view: sublime.View, key: str, operator: int, operand: str, match_all: bool) -> Optional[bool]: ... - def on_query_completions(self, view: sublime.View, prefix: str, locations: List[int]) -> Union[None, List[Completion], Tuple[List[Completion], int]]: ... - def on_text_command(self, view: sublime.View, command_name: str, args: dict) -> Optional[Tuple[str, dict]]: ... - def on_post_text_command(self, view: sublime.View, command_name: str, args: dict) -> None: ... - def on_window_command(self, view: sublime.Window, command_name: str, args: dict) -> Optional[Tuple[str, dict]]: ... - def on_post_window_command(self, view: sublime.Window, command_name: str, args: dict) -> None: ... - - -class ViewEventListener: - view: sublime.View - - @classmethod - def is_applicable(cls, settings: sublime.Settings) -> bool: ... - - @classmethod - def applies_to_primary_view_only(cls) -> bool: ... - - def on_load(self) -> None: ... - def on_load_async(self) -> None: ... - def on_pre_close(self) -> None: ... - def on_close(self) -> None: ... - def on_pre_save(self) -> None: ... - def on_pre_save_async(self) -> None: ... - def on_post_save(self) -> None: ... - def on_post_save_async(self) -> None: ... - def on_modified(self) -> None: ... - def on_modified_async(self) -> None: ... - def on_selection_modified(self) -> None: ... - def on_selection_modified_async(self) -> None: ... - def on_activated_modified(self) -> None: ... - def on_activated_modified_async(self) -> None: ... - def on_deactivated_modified(self) -> None: ... - def on_deactivated_modified_async(self) -> None: ... - def on_hover(self, point: int, hover_zone: int) -> None: ... - def on_query_context(self, key: str, operator: int, operand: str, match_all: bool) -> Optional[bool]: ... - def on_query_completions(self, prefix: str, locations: List[int]) -> Union[None, List[Completion], Tuple[List[Completion], int]]: ... - def on_text_command(self, command_name: str, args: dict) -> Optional[Tuple[str, dict]]: ... - def on_post_text_command(self, command_name: str, args: dict) -> None: ... diff --git a/tests/temporary_package.py b/tests/temporary_package.py index 69281e8..5b3217f 100644 --- a/tests/temporary_package.py +++ b/tests/temporary_package.py @@ -2,7 +2,7 @@ from sublime_lib import ResourcePath -__all__ = ['TemporaryPackage'] +__all__ = ["TemporaryPackage"] class TemporaryPackage: @@ -21,10 +21,7 @@ def create(self) -> None: ) def destroy(self) -> None: - shutil.rmtree( - str(self.package_path.file_path()), - ignore_errors=True - ) + shutil.rmtree(str(self.package_path.file_path()), ignore_errors=True) def exists(self) -> bool: - return len(self.package_path.rglob('*')) > 0 + return len(self.package_path.rglob("*")) > 0 diff --git a/tests/test_activity_indicator.py b/tests/test_activity_indicator.py index ab0351b..babc266 100644 --- a/tests/test_activity_indicator.py +++ b/tests/test_activity_indicator.py @@ -9,7 +9,7 @@ class TestActivityIndicator(DeferrableTestCase): def test_window_target(self): - message = 'Hello, World!' + message = "Hello, World!" window = Mock() target = WindowTarget(window) @@ -18,11 +18,11 @@ def test_window_target(self): window.status_message.reset_mock() target.clear() - window.status_message.assert_called_once_with('') + window.status_message.assert_called_once_with("") def test_view_target(self): - key = 'test' - message = 'Hello, World!' + key = "test" + message = "Hello, World!" view = Mock() target = ViewTarget(view, key) @@ -47,28 +47,28 @@ def test_tick(self): indicator = ActivityIndicator(target) results = [ - '[= ]', - '[ = ]', - '[ = ]', - '[ = ]', - '[ = ]', - '[ = ]', - '[ = ]', - '[ = ]', - '[ = ]', - '[ = ]', - '[ =]', - '[ = ]', - '[ = ]', - '[ = ]', - '[ = ]', - '[ = ]', - '[ = ]', - '[ = ]', - '[ = ]', - '[ = ]', - '[= ]', - '[ = ]', + "[= ]", + "[ = ]", + "[ = ]", + "[ = ]", + "[ = ]", + "[ = ]", + "[ = ]", + "[ = ]", + "[ = ]", + "[ = ]", + "[ =]", + "[ = ]", + "[ = ]", + "[ = ]", + "[ = ]", + "[ = ]", + "[ = ]", + "[ = ]", + "[ = ]", + "[ = ]", + "[= ]", + "[ = ]", ] indicator.update() @@ -79,24 +79,24 @@ def test_tick(self): def test_label(self): target = Mock() - indicator = ActivityIndicator(target, 'Hello, World!') + indicator = ActivityIndicator(target, "Hello, World!") with indicator: - target.set.assert_called_once_with('Hello, World! [= ]') + target.set.assert_called_once_with("Hello, World! [= ]") def test_start_stop(self): target = Mock() indicator = ActivityIndicator(target) indicator.start() - target.set.assert_called_once_with('[= ]') + target.set.assert_called_once_with("[= ]") target.set.reset_mock() indicator.stop() target.clear.assert_called_once_with() indicator.start() - target.set.assert_called_once_with('[= ]') + target.set.assert_called_once_with("[= ]") indicator.stop() @@ -104,10 +104,10 @@ def test_tick_called(self): target = Mock() indicator = ActivityIndicator(target) with indicator: - target.set.assert_called_once_with('[= ]') + target.set.assert_called_once_with("[= ]") target.set.reset_mock() yield 150 - target.set.assert_called_once_with('[ = ]') + target.set.assert_called_once_with("[ = ]") def test_start_twice_error(self): target = Mock() @@ -122,6 +122,6 @@ def test_contextmanager(self): indicator = ActivityIndicator(target) with indicator: - target.set.assert_called_once_with('[= ]') + target.set.assert_called_once_with("[= ]") target.clear.assert_called_once_with() diff --git a/tests/test_collection_util.py b/tests/test_collection_util.py index 9a61929..e96e913 100644 --- a/tests/test_collection_util.py +++ b/tests/test_collection_util.py @@ -1,5 +1,9 @@ from sublime_lib._util.collections import ( - projection, get_selector, isiterable, ismapping, is_sequence_not_str + projection, + get_selector, + isiterable, + ismapping, + is_sequence_not_str, ) from unittest import TestCase @@ -9,83 +13,71 @@ class TestSettingsDict(TestCase): def test_projection(self): d = { - 'a': 1, - 'b': 2, - 'c': 3, + "a": 1, + "b": 2, + "c": 3, } - self.assertEquals( - projection(d, ()), - {} - ) + self.assertEquals(projection(d, ()), {}) self.assertEquals( - projection(d, ('a', 'c')), + projection(d, ("a", "c")), { - 'a': 1, - 'c': 3, - } + "a": 1, + "c": 3, + }, ) self.assertEquals( - projection(d, { - 'a': 'x', - 'b': 'y', - }), + projection( + d, + { + "a": "x", + "b": "y", + }, + ), { - 'x': 1, - 'y': 2, - } + "x": 1, + "y": 2, + }, ) def test_get_selector(self): d = { - 'a': 1, - 'b': 2, - 'c': 3, + "a": 1, + "b": 2, + "c": 3, } - self.assertEqual( - get_selector('a')(d), - 1 - ) + self.assertEqual(get_selector("a")(d), 1) - self.assertEqual( - get_selector('x')(d), - None - ) + self.assertEqual(get_selector("x")(d), None) - self.assertEqual( - get_selector('x', 42)(d), - 42 - ) + self.assertEqual(get_selector("x", 42)(d), 42) - self.assertEqual( - get_selector(lambda d: d['a'])(d), - 1 - ) + self.assertEqual(get_selector(lambda d: d["a"])(d), 1) self.assertEqual( - get_selector(('a',))(d), + get_selector(("a",))(d), { - 'a': 1, - } + "a": 1, + }, ) self.assertEqual( - get_selector(('a', 'b'))(d), + get_selector(("a", "b"))(d), { - 'a': 1, - 'b': 2, - } + "a": 1, + "b": 2, + }, ) self.assertEqual( - get_selector({'a': 'x', 'b': 'y'})(d), + get_selector({"a": "x", "b": "y"})(d), { - 'x': 1, - 'y': 2, - } + "x": 1, + "y": 2, + }, ) def test_get_selector_error(self): @@ -96,7 +88,7 @@ def test_isiterable(self): def generator(): yield - self.assertTrue(isiterable('')) + self.assertTrue(isiterable("")) self.assertTrue(isiterable(())) self.assertTrue(isiterable([])) self.assertTrue(isiterable(generator())) @@ -114,4 +106,4 @@ def test_is_sequence_not_str(self): self.assertTrue(is_sequence_not_str([])) self.assertFalse(is_sequence_not_str({})) - self.assertFalse(is_sequence_not_str('')) + self.assertFalse(is_sequence_not_str("")) diff --git a/tests/test_encodings.py b/tests/test_encodings.py index 74cfde3..20795bf 100644 --- a/tests/test_encodings.py +++ b/tests/test_encodings.py @@ -6,36 +6,21 @@ class TestEncodings(TestCase): def test_from(self): - self.assertEqual( - from_sublime("Western (Windows 1252)"), - "cp1252" - ) + self.assertEqual(from_sublime("Western (Windows 1252)"), "cp1252") def test_from_error(self): with self.assertRaises(ValueError): from_sublime("Nonexistent") def test_to(self): - self.assertEqual( - to_sublime("cp1252"), - "Western (Windows 1252)" - ) + self.assertEqual(to_sublime("cp1252"), "Western (Windows 1252)") def test_to_with_aliases(self): - self.assertEqual( - to_sublime("mac-latin2"), - "Central European (Mac)" - ) - self.assertEqual( - to_sublime("mac_latin2"), - "Central European (Mac)" - ) + self.assertEqual(to_sublime("mac-latin2"), "Central European (Mac)") + self.assertEqual(to_sublime("mac_latin2"), "Central European (Mac)") self.assertEqual( - to_sublime(from_sublime( - "Central European (Mac)" - )), - "Central European (Mac)" + to_sublime(from_sublime("Central European (Mac)")), "Central European (Mac)" ) def test_to_error(self): diff --git a/tests/test_flags.py b/tests/test_flags.py index 6a786b3..a4f9893 100644 --- a/tests/test_flags.py +++ b/tests/test_flags.py @@ -9,23 +9,20 @@ class TestFlags(TestCase): - def _test_enum(self, enum, prefix=''): + def _test_enum(self, enum, prefix=""): for item in enum: self.assertEqual(item, getattr(sublime, prefix + item.name)) self.assertEqual(item, enum(item.name)) if issubclass(enum, IntFlag): - self.assertEqual( - enum(*[item.name for item in enum]), - reduce(lambda a, b: a | b, enum) - ) + self.assertEqual(enum(*[item.name for item in enum]), reduce(lambda a, b: a | b, enum)) def test_flags(self): - self._test_enum(flags.DialogResult, 'DIALOG_') - self._test_enum(flags.PointClass, 'CLASS_') - self._test_enum(flags.PhantomLayout, 'LAYOUT_') - self._test_enum(flags.HoverLocation, 'HOVER_') - self._test_enum(flags.QueryContextOperator, 'OP_') + self._test_enum(flags.DialogResult, "DIALOG_") + self._test_enum(flags.PointClass, "CLASS_") + self._test_enum(flags.PhantomLayout, "LAYOUT_") + self._test_enum(flags.HoverLocation, "HOVER_") + self._test_enum(flags.QueryContextOperator, "OP_") self._test_enum(flags.FindOption) self._test_enum(flags.RegionOption) @@ -36,28 +33,25 @@ def test_flags(self): def test_from_strings(self): self.assertEqual( - flags.RegionOption('DRAW_EMPTY', 'HIDE_ON_MINIMAP'), - flags.RegionOption.DRAW_EMPTY | flags.RegionOption.HIDE_ON_MINIMAP + flags.RegionOption("DRAW_EMPTY", "HIDE_ON_MINIMAP"), + flags.RegionOption.DRAW_EMPTY | flags.RegionOption.HIDE_ON_MINIMAP, ) def test_from_strings_empty(self): - self.assertEqual( - flags.RegionOption(), - flags.RegionOption(0) - ) + self.assertEqual(flags.RegionOption(), flags.RegionOption(0)) def test_query_context_operators(self): ops = flags.QueryContextOperator tests = [ - ('EQUAL', 'x', 'x', 'y'), - ('REGEX_MATCH', 'aaa', r'a+', r'a'), - ('REGEX_CONTAINS', 'aaa', r'a', r'b'), + ("EQUAL", "x", "x", "y"), + ("REGEX_MATCH", "aaa", r"a+", r"a"), + ("REGEX_CONTAINS", "aaa", r"a", r"b"), ] for op, key, success, failure in tests: self.assertTrue(ops(op).apply(key, success)) self.assertFalse(ops(op).apply(key, failure)) - self.assertTrue(ops('NOT_' + op).apply(key, failure)) - self.assertFalse(ops('NOT_' + op).apply(key, success)) + self.assertTrue(ops("NOT_" + op).apply(key, failure)) + self.assertFalse(ops("NOT_" + op).apply(key, success)) diff --git a/tests/test_glob.py b/tests/test_glob.py index 904ae14..c8d290a 100644 --- a/tests/test_glob.py +++ b/tests/test_glob.py @@ -9,197 +9,193 @@ def _test_matches(self, pattern, positive, negative): for path in positive: if not matcher(path): - raise self.failureException( - "{!r} does not match {!r}".format(pattern, path) - ) + raise self.failureException("{!r} does not match {!r}".format(pattern, path)) for path in negative: if matcher(path): - raise self.failureException( - "{!r} matches {!r}".format(pattern, path) - ) + raise self.failureException("{!r} matches {!r}".format(pattern, path)) def test_recursive_invalid(self): with self.assertRaises(ValueError): - get_glob_matcher('foo**') + get_glob_matcher("foo**") def test_basic(self): self._test_matches( - '/Packages/Foo/bar', + "/Packages/Foo/bar", [ - 'Packages/Foo/bar', + "Packages/Foo/bar", ], [ - 'Packages/Foo', - 'Packages/Foo/barr', - 'Packages/Foo/bar/baz', - ] + "Packages/Foo", + "Packages/Foo/barr", + "Packages/Foo/bar/baz", + ], ) self._test_matches( - 'Foo/bar', + "Foo/bar", [ - 'Foo/bar', - 'Packages/Foo/bar', + "Foo/bar", + "Packages/Foo/bar", ], [ - 'Packages/Foo/bar/baz', - 'FooFoo/bar', - ] + "Packages/Foo/bar/baz", + "FooFoo/bar", + ], ) def test_star(self): self._test_matches( - '/Packages/Foo/*', + "/Packages/Foo/*", [ - 'Packages/Foo/bar', + "Packages/Foo/bar", ], [ - 'Packages/Foo', - 'Packages/Foo/bar/baz', - ] + "Packages/Foo", + "Packages/Foo/bar/baz", + ], ) self._test_matches( - 'Foo/*', + "Foo/*", [ - 'Packages/Foo/bar', + "Packages/Foo/bar", ], [ - 'Packages/Foo', - 'Packages/Foo/bar/baz', - ] + "Packages/Foo", + "Packages/Foo/bar/baz", + ], ) self._test_matches( - '/Packages/Foo/A*Z', + "/Packages/Foo/A*Z", [ - 'Packages/Foo/AZ', - 'Packages/Foo/AfoobarZ', - 'Packages/Foo/AAAZZZ', + "Packages/Foo/AZ", + "Packages/Foo/AfoobarZ", + "Packages/Foo/AAAZZZ", ], [ - 'Packages/Foo/AZbar', - 'Packages/Foo/AZ/bar', - 'Packages/Foo/A/Z', - ] + "Packages/Foo/AZbar", + "Packages/Foo/AZ/bar", + "Packages/Foo/A/Z", + ], ) self._test_matches( - 'Foo/A*Z', + "Foo/A*Z", [ - 'Packages/Foo/AZ', - 'Packages/Foo/AfoobarZ', - 'Packages/Foo/AAAZZZ', + "Packages/Foo/AZ", + "Packages/Foo/AfoobarZ", + "Packages/Foo/AAAZZZ", ], [ - 'Packages/Foo/AZbar', - 'Packages/Foo/AZ/bar', - 'Packages/Foo/A/Z', - ] + "Packages/Foo/AZbar", + "Packages/Foo/AZ/bar", + "Packages/Foo/A/Z", + ], ) def test_recursive(self): self._test_matches( - '/Packages/Foo/**', + "/Packages/Foo/**", [ - 'Packages/Foo/bar', - 'Packages/Foo/bar/baz', + "Packages/Foo/bar", + "Packages/Foo/bar/baz", ], [ - 'Packages/Foo', - 'Packages/Foobar', - ] + "Packages/Foo", + "Packages/Foobar", + ], ) self._test_matches( - 'Foo/**', + "Foo/**", [ - 'Packages/Foo/', - 'Packages/Foo/bar', - 'Packages/Foo/bar/baz', + "Packages/Foo/", + "Packages/Foo/bar", + "Packages/Foo/bar/baz", ], [ - 'Packages/Foo', - 'Packages/Foobar', - ] + "Packages/Foo", + "Packages/Foobar", + ], ) self._test_matches( - '/Packages/Foo/**/bar', + "/Packages/Foo/**/bar", [ - 'Packages/Foo/bar', - 'Packages/Foo/xyzzy/bar', + "Packages/Foo/bar", + "Packages/Foo/xyzzy/bar", ], [ - 'Packages/Foo/bar/baz', - ] + "Packages/Foo/bar/baz", + ], ) self._test_matches( - 'Foo/**/bar', + "Foo/**/bar", [ - 'Packages/Foo/bar', - 'Packages/Foo/xyzzy/bar', + "Packages/Foo/bar", + "Packages/Foo/xyzzy/bar", ], [ - 'Packages/Foo/bar/baz', - ] + "Packages/Foo/bar/baz", + ], ) self._test_matches( - '/**/Packages/Foo/bar', + "/**/Packages/Foo/bar", [ - 'Packages/Foo/bar', + "Packages/Foo/bar", ], - [] + [], ) self._test_matches( - 'Foo/**/*', + "Foo/**/*", [ - 'Foo/bar', - 'Foo/bar/baz', + "Foo/bar", + "Foo/bar/baz", ], [ - 'Foo', - 'Foo/', - ] + "Foo", + "Foo/", + ], ) def test_placeholder(self): self._test_matches( - '/Packages/Foo/ba?', + "/Packages/Foo/ba?", [ - 'Packages/Foo/bar', - 'Packages/Foo/baz', + "Packages/Foo/bar", + "Packages/Foo/baz", ], [ - 'Packages/Foo/bar/baz', - ] + "Packages/Foo/bar/baz", + ], ) def test_range(self): self._test_matches( - '/Packages/Foo/ba[rz]', + "/Packages/Foo/ba[rz]", [ - 'Packages/Foo/bar', - 'Packages/Foo/baz', + "Packages/Foo/bar", + "Packages/Foo/baz", ], [ - 'Packages/Foo/bar/baz', - 'Packages/Foo/barr', - 'Packages/Foo/bat', - ] + "Packages/Foo/bar/baz", + "Packages/Foo/barr", + "Packages/Foo/bat", + ], ) self._test_matches( - '/Packages/Foo/ba[a-z]', + "/Packages/Foo/ba[a-z]", [ - 'Packages/Foo/bar', - 'Packages/Foo/baz', + "Packages/Foo/bar", + "Packages/Foo/baz", ], [ - '/Packages/Foo/baR', - ] + "/Packages/Foo/baR", + ], ) diff --git a/tests/test_named_settings_dict.py b/tests/test_named_settings_dict.py index 67ffe97..8913602 100644 --- a/tests/test_named_settings_dict.py +++ b/tests/test_named_settings_dict.py @@ -11,7 +11,7 @@ class TestNamedSettingsDict(DeferrableTestCase): def setUp(self): self.name = "_sublime_lib_NamedSettingsDictTest" self.fancy = NamedSettingsDict(self.name) - self.settings_path = path.join(sublime.packages_path(), 'User', self.fancy.file_name) + self.settings_path = path.join(sublime.packages_path(), "User", self.fancy.file_name) def tearDown(self): try: @@ -36,19 +36,19 @@ def test_named(self): self.assertTrue(path.exists(self.settings_path)) def test_file_extension(self): - other = NamedSettingsDict(self.name + '.sublime-settings') + other = NamedSettingsDict(self.name + ".sublime-settings") self.fancy.pop("example_setting", None) self.assertNotIn("example_setting", self.fancy) self.fancy["example_setting"] = "Hello, World!" - self.assertEquals(other['example_setting'], 'Hello, World!') + self.assertEquals(other["example_setting"], "Hello, World!") def test_equal(self): - other = NamedSettingsDict(self.name + '.sublime-settings') + other = NamedSettingsDict(self.name + ".sublime-settings") self.assertEqual(self.fancy, other) def test_not_equal(self): - other = NamedSettingsDict('Preferences.sublime-settings') + other = NamedSettingsDict("Preferences.sublime-settings") self.assertNotEqual(self.fancy, other) def test_not_equal_unnamed(self): diff --git a/tests/test_named_value.py b/tests/test_named_value.py index 8fa699c..3f2ccce 100644 --- a/tests/test_named_value.py +++ b/tests/test_named_value.py @@ -7,7 +7,4 @@ class TestNamedValue(TestCase): def test_named_value(self): s = "Hello, World!" - self.assertEqual( - repr(NamedValue(s)), - s - ) + self.assertEqual(repr(NamedValue(s)), s) diff --git a/tests/test_output_panel.py b/tests/test_output_panel.py index ca21adf..f4f25cd 100644 --- a/tests/test_output_panel.py +++ b/tests/test_output_panel.py @@ -13,7 +13,7 @@ def setUp(self): self.panel_name = "test_panel" def tearDown(self): - if getattr(self, 'panel', None): + if getattr(self, "panel", None): self.panel.destroy() if self.panel_to_restore: @@ -21,10 +21,7 @@ def tearDown(self): def assertContents(self, text): view = self.panel.view - self.assertEqual( - view.substr(sublime.Region(0, view.size())), - text - ) + self.assertEqual(view.substr(sublime.Region(0, view.size())), text) def test_stream_operations(self): self.panel = OutputPanel.create(self.window, self.panel_name) @@ -83,9 +80,9 @@ def test_destroy(self): self.assertIsNone(self.window.find_output_panel(self.panel.name)) def test_settings(self): - self.panel = OutputPanel.create(self.window, self.panel_name, settings={ - "test_setting": "Hello, World!" - }) + self.panel = OutputPanel.create( + self.window, self.panel_name, settings={"test_setting": "Hello, World!"} + ) view_settings = self.panel.view.settings() self.assertEqual(view_settings.get("test_setting"), "Hello, World!") @@ -109,4 +106,4 @@ def test_attach(self): def test_init_nonexistent_error(self): with self.assertRaises(ValueError): - OutputPanel(self.window, 'nonexistent_output_panel') + OutputPanel(self.window, "nonexistent_output_panel") diff --git a/tests/test_pure_resource_path.py b/tests/test_pure_resource_path.py index dba5559..397fd98 100644 --- a/tests/test_pure_resource_path.py +++ b/tests/test_pure_resource_path.py @@ -10,43 +10,29 @@ def test_empty_error(self): ResourcePath("") def test_eq(self): - self.assertEqual( - ResourcePath("Packages/Foo/bar.py"), - ResourcePath("Packages/Foo/bar.py") - ) + self.assertEqual(ResourcePath("Packages/Foo/bar.py"), ResourcePath("Packages/Foo/bar.py")) def test_ordering_error(self): with self.assertRaises(TypeError): - ResourcePath("Packages") < 'Packages' + ResourcePath("Packages") < "Packages" def test_hash(self): - self.assertIsInstance( - hash(ResourcePath("Packages/Foo/bar.py")), - int - ) + self.assertIsInstance(hash(ResourcePath("Packages/Foo/bar.py")), int) def test_eq_false(self): - self.assertNotEqual( - ResourcePath("Packages/Foo/bar.py"), - "Packages/Foo/bar.py" - ) + self.assertNotEqual(ResourcePath("Packages/Foo/bar.py"), "Packages/Foo/bar.py") def test_eq_slash(self): self.assertEqual( - ResourcePath("Packages/Foo/bar.py"), - ResourcePath("Packages/Foo/bar.py///") + ResourcePath("Packages/Foo/bar.py"), ResourcePath("Packages/Foo/bar.py///") ) def test_str(self): - self.assertEqual( - str(ResourcePath("Packages/Foo/bar.py")), - "Packages/Foo/bar.py" - ) + self.assertEqual(str(ResourcePath("Packages/Foo/bar.py")), "Packages/Foo/bar.py") def test_repr(self): self.assertEqual( - repr(ResourcePath("Packages/Foo/bar.py")), - "ResourcePath('Packages/Foo/bar.py')" + repr(ResourcePath("Packages/Foo/bar.py")), "ResourcePath('Packages/Foo/bar.py')" ) def test_parts(self): @@ -54,218 +40,138 @@ def test_parts(self): self.assertEqual(path.parts, ("Packages", "Foo", "bar.py")) def test_parent(self): - self.assertEqual( - ResourcePath("Packages/Foo/bar.py").parent, - ResourcePath("Packages/Foo") - ) + self.assertEqual(ResourcePath("Packages/Foo/bar.py").parent, ResourcePath("Packages/Foo")) def test_top_parent(self): - self.assertEqual( - ResourcePath("Packages").parent, - ResourcePath("Packages") - ) + self.assertEqual(ResourcePath("Packages").parent, ResourcePath("Packages")) def test_parents(self): self.assertEqual( ResourcePath("Packages/Foo/bar.py").parents, - ( - ResourcePath("Packages/Foo"), - ResourcePath("Packages") - ) + (ResourcePath("Packages/Foo"), ResourcePath("Packages")), ) def test_parents_root(self): - self.assertEqual( - ResourcePath("Packages").parents, - () - ) + self.assertEqual(ResourcePath("Packages").parents, ()) def test_name(self): - self.assertEqual( - ResourcePath("Packages/Foo/bar.py").name, - 'bar.py' - ) + self.assertEqual(ResourcePath("Packages/Foo/bar.py").name, "bar.py") def test_name_directory(self): - self.assertEqual( - ResourcePath("Packages/Foo/").name, - 'Foo' - ) + self.assertEqual(ResourcePath("Packages/Foo/").name, "Foo") def test_suffix(self): - self.assertEqual( - ResourcePath("Packages/Foo/bar.py").suffix, - '.py' - ) + self.assertEqual(ResourcePath("Packages/Foo/bar.py").suffix, ".py") def test_suffix_none(self): - self.assertEqual( - ResourcePath("Packages/Foo/bar").suffix, - '' - ) + self.assertEqual(ResourcePath("Packages/Foo/bar").suffix, "") def test_suffix_dots_end(self): - self.assertEqual( - ResourcePath("foo...").suffix, - "" - ) + self.assertEqual(ResourcePath("foo...").suffix, "") def test_suffix_multiple(self): - self.assertEqual( - ResourcePath("Packages/Foo/bar.tar.gz").suffix, - '.gz' - ) + self.assertEqual(ResourcePath("Packages/Foo/bar.tar.gz").suffix, ".gz") def test_suffixes(self): - self.assertEqual( - ResourcePath("Packages/Foo/bar.tar.gz").suffixes, - ['.tar', '.gz'] - ) + self.assertEqual(ResourcePath("Packages/Foo/bar.tar.gz").suffixes, [".tar", ".gz"]) def test_suffixes_none(self): - self.assertEqual( - ResourcePath("Packages/Foo/bar").suffixes, - [] - ) + self.assertEqual(ResourcePath("Packages/Foo/bar").suffixes, []) def test_suffixes_dotend(self): - self.assertEqual( - ResourcePath("foo.bar.").suffixes, - [] - ) + self.assertEqual(ResourcePath("foo.bar.").suffixes, []) def test_suffixes_dots(self): - self.assertEqual( - ResourcePath("foo.bar...baz").suffixes, - ['.bar', '.', '.', '.baz'] - ) + self.assertEqual(ResourcePath("foo.bar...baz").suffixes, [".bar", ".", ".", ".baz"]) def test_stem(self): - self.assertEqual( - ResourcePath("Packages/Foo/bar.py").stem, - 'bar' - ) + self.assertEqual(ResourcePath("Packages/Foo/bar.py").stem, "bar") def test_stem_dots_end(self): - self.assertEqual( - ResourcePath("foo...").stem, - "foo..." - ) + self.assertEqual(ResourcePath("foo...").stem, "foo...") def test_stem_multiple(self): - self.assertEqual( - ResourcePath("Packages/Foo/bar.tar.gz").stem, - 'bar.tar' - ) + self.assertEqual(ResourcePath("Packages/Foo/bar.tar.gz").stem, "bar.tar") def test_stem_none(self): - self.assertEqual( - ResourcePath("Packages/Foo/bar").stem, - 'bar' - ) + self.assertEqual(ResourcePath("Packages/Foo/bar").stem, "bar") def test_root(self): - self.assertEqual( - ResourcePath("Packages/Foo/bar").root, - 'Packages' - ) + self.assertEqual(ResourcePath("Packages/Foo/bar").root, "Packages") def test_package(self): - self.assertEqual( - ResourcePath("Packages/Foo/bar").package, - 'Foo' - ) + self.assertEqual(ResourcePath("Packages/Foo/bar").package, "Foo") def test_package_none(self): - self.assertEqual( - ResourcePath("Packages").package, - None - ) + self.assertEqual(ResourcePath("Packages").package, None) def test_package_cache(self): - self.assertEqual( - ResourcePath("Cache/Foo").package, - 'Foo' - ) + self.assertEqual(ResourcePath("Cache/Foo").package, "Foo") def test_match(self): path = ResourcePath("Packages/Foo/bar") - self.assertTrue(path.match('bar')) - self.assertTrue(path.match('Foo/bar')) - self.assertTrue(path.match('Foo/*')) - self.assertTrue(path.match('Packages/*/bar')) - self.assertTrue(path.match('Packages/Foo/**/bar')) + self.assertTrue(path.match("bar")) + self.assertTrue(path.match("Foo/bar")) + self.assertTrue(path.match("Foo/*")) + self.assertTrue(path.match("Packages/*/bar")) + self.assertTrue(path.match("Packages/Foo/**/bar")) self.assertTrue(path.match("/Packages/Foo/bar")) - self.assertFalse(path.match('baz')) - self.assertFalse(path.match('Foo')) - self.assertFalse(path.match('Packages/*/*/bar')) - self.assertFalse(path.match('/Foo/bar')) - self.assertFalse(path.match('ar')) + self.assertFalse(path.match("baz")) + self.assertFalse(path.match("Foo")) + self.assertFalse(path.match("Packages/*/*/bar")) + self.assertFalse(path.match("/Foo/bar")) + self.assertFalse(path.match("ar")) def test_joinpath(self): self.assertEqual( - ResourcePath("Packages/Foo/").joinpath('bar/', 'baz/xyzzy'), - ResourcePath("Packages/Foo/bar/baz/xyzzy") + ResourcePath("Packages/Foo/").joinpath("bar/", "baz/xyzzy"), + ResourcePath("Packages/Foo/bar/baz/xyzzy"), ) def test_joinpath_operator(self): self.assertEqual( - ResourcePath("Packages/Foo/") / 'bar/' / 'baz/xyzzy', - ResourcePath("Packages/Foo/bar/baz/xyzzy") + ResourcePath("Packages/Foo/") / "bar/" / "baz/xyzzy", + ResourcePath("Packages/Foo/bar/baz/xyzzy"), ) def test_relative_to(self): self.assertEqual( - ResourcePath("Packages/Foo/baz/bar.py").relative_to( - ResourcePath("Packages/Foo") - ), - ('baz', 'bar.py') + ResourcePath("Packages/Foo/baz/bar.py").relative_to(ResourcePath("Packages/Foo")), + ("baz", "bar.py"), ) def test_relative_to_same(self): - self.assertEqual( - ResourcePath("Packages/Foo").relative_to( - ResourcePath("Packages/Foo") - ), - () - ) + self.assertEqual(ResourcePath("Packages/Foo").relative_to(ResourcePath("Packages/Foo")), ()) def test_relative_to_error(self): with self.assertRaises(ValueError): - ResourcePath("Packages/Foo").relative_to( - ResourcePath("Packages/Bar") - ) + ResourcePath("Packages/Foo").relative_to(ResourcePath("Packages/Bar")) def test_with_name(self): self.assertEqual( - ResourcePath("Packages/Foo/bar.py").with_name('baz.js'), - ResourcePath("Packages/Foo/baz.js") + ResourcePath("Packages/Foo/bar.py").with_name("baz.js"), + ResourcePath("Packages/Foo/baz.js"), ) def test_with_name_root(self): - self.assertEqual( - ResourcePath("Packages").with_name('Cache'), - ResourcePath("Cache") - ) + self.assertEqual(ResourcePath("Packages").with_name("Cache"), ResourcePath("Cache")) def test_add_suffix(self): self.assertEqual( - ResourcePath("Packages/Foo/bar").add_suffix('.py'), - ResourcePath("Packages/Foo/bar.py") + ResourcePath("Packages/Foo/bar").add_suffix(".py"), ResourcePath("Packages/Foo/bar.py") ) def test_remove_suffix(self): self.assertEqual( - ResourcePath("Packages/Foo/bar.py").remove_suffix(), - ResourcePath("Packages/Foo/bar") + ResourcePath("Packages/Foo/bar.py").remove_suffix(), ResourcePath("Packages/Foo/bar") ) def test_remove_suffix_none(self): self.assertEqual( ResourcePath("Packages/Foo/bar").remove_suffix(must_remove=False), - ResourcePath("Packages/Foo/bar") + ResourcePath("Packages/Foo/bar"), ) def test_remove_suffix_none_error(self): @@ -274,74 +180,69 @@ def test_remove_suffix_none_error(self): def test_remove_suffix_specified(self): self.assertEqual( - ResourcePath("Packages/Foo/bar.py").remove_suffix('.py'), - ResourcePath("Packages/Foo/bar") + ResourcePath("Packages/Foo/bar.py").remove_suffix(".py"), + ResourcePath("Packages/Foo/bar"), ) def test_remove_suffix_specified_no_match(self): self.assertEqual( - ResourcePath("Packages/Foo/bar.py").remove_suffix('.zip', must_remove=False), - ResourcePath("Packages/Foo/bar.py") + ResourcePath("Packages/Foo/bar.py").remove_suffix(".zip", must_remove=False), + ResourcePath("Packages/Foo/bar.py"), ) def test_remove_suffix_specified_no_match_error(self): with self.assertRaises(ValueError): - ResourcePath("Packages/Foo/bar.py").remove_suffix('.zip') + ResourcePath("Packages/Foo/bar.py").remove_suffix(".zip") def test_remove_suffix_specified_no_dot(self): self.assertEqual( - ResourcePath("Packages/Foo/bar.py").remove_suffix('r.py'), - ResourcePath("Packages/Foo/ba") + ResourcePath("Packages/Foo/bar.py").remove_suffix("r.py"), + ResourcePath("Packages/Foo/ba"), ) def test_remove_suffix_specified_entire_name(self): self.assertEqual( - ResourcePath("Packages/Foo/bar.py").remove_suffix('bar.py', must_remove=False), - ResourcePath("Packages/Foo/bar.py") + ResourcePath("Packages/Foo/bar.py").remove_suffix("bar.py", must_remove=False), + ResourcePath("Packages/Foo/bar.py"), ) def test_remove_suffix_specified_entire_name_error(self): with self.assertRaises(ValueError): - ResourcePath("Packages/Foo/bar.py").remove_suffix('bar.py') + ResourcePath("Packages/Foo/bar.py").remove_suffix("bar.py") def test_remove_suffix_multiple(self): self.assertEqual( - ResourcePath("Packages/Foo/bar.py").remove_suffix(['.zip', '.py']), - ResourcePath("Packages/Foo/bar") + ResourcePath("Packages/Foo/bar.py").remove_suffix([".zip", ".py"]), + ResourcePath("Packages/Foo/bar"), ) def test_remove_suffix_multiple_matches(self): self.assertEqual( - ResourcePath("Packages/Foo/bar.tar.gz").remove_suffix(['.tar.gz', '.gz']), - ResourcePath("Packages/Foo/bar") + ResourcePath("Packages/Foo/bar.tar.gz").remove_suffix([".tar.gz", ".gz"]), + ResourcePath("Packages/Foo/bar"), ) def test_remove_suffix_multiple_matches_backward(self): self.assertEqual( - ResourcePath("Packages/Foo/bar.tar.gz").remove_suffix(['.gz', '.tar.gz']), - ResourcePath("Packages/Foo/bar") + ResourcePath("Packages/Foo/bar.tar.gz").remove_suffix([".gz", ".tar.gz"]), + ResourcePath("Packages/Foo/bar"), ) def test_with_suffix(self): self.assertEqual( - ResourcePath("Packages/Foo/bar.tar.gz").with_suffix('.bz2'), - ResourcePath("Packages/Foo/bar.tar.bz2") + ResourcePath("Packages/Foo/bar.tar.gz").with_suffix(".bz2"), + ResourcePath("Packages/Foo/bar.tar.bz2"), ) def test_with_suffix_empty(self): self.assertEqual( - ResourcePath("Packages/Foo/bar").with_suffix('.py'), - ResourcePath("Packages/Foo/bar.py") + ResourcePath("Packages/Foo/bar").with_suffix(".py"), ResourcePath("Packages/Foo/bar.py") ) def test_with_suffix_remove(self): self.assertEqual( - ResourcePath("Packages/Foo/bar.py").with_suffix(''), - ResourcePath("Packages/Foo/bar") + ResourcePath("Packages/Foo/bar.py").with_suffix(""), ResourcePath("Packages/Foo/bar") ) def test_with_suffix_root(self): - self.assertEqual( - ResourcePath("Packages").with_suffix('.bz2'), - ResourcePath("Packages.bz2") - ) + self.assertEqual(ResourcePath("Packages").with_suffix(".bz2"), ResourcePath("Packages.bz2")) diff --git a/tests/test_region_manager.py b/tests/test_region_manager.py index 6182cb1..316d1cb 100644 --- a/tests/test_region_manager.py +++ b/tests/test_region_manager.py @@ -18,92 +18,59 @@ def setUp(self): self.window = sublime.active_window() def tearDown(self): - if getattr(self, 'view', None): + if getattr(self, "view", None): try: close_view(self.view, force=True) except ValueError: pass def test_set(self): - self.view = new_view(self.window, scratch=True, content='Hello, World!') + self.view = new_view(self.window, scratch=True, content="Hello, World!") manager = RegionManager(self.view) manager.set([Region(0, 5)]) - self.assertEqual( - manager.get(), - [Region(0, 5)] - ) + self.assertEqual(manager.get(), [Region(0, 5)]) - self.assertEqual( - self.view.get_regions(manager.key), - [Region(0, 5)] - ) + self.assertEqual(self.view.get_regions(manager.key), [Region(0, 5)]) manager.set([Region(7, 13)]) - self.assertEqual( - manager.get(), - [Region(7, 13)] - ) + self.assertEqual(manager.get(), [Region(7, 13)]) - self.assertEqual( - self.view.get_regions(manager.key), - [Region(7, 13)] - ) + self.assertEqual(self.view.get_regions(manager.key), [Region(7, 13)]) manager.erase() - self.assertEqual( - manager.get(), - [] - ) + self.assertEqual(manager.get(), []) - self.assertEqual( - self.view.get_regions(manager.key), - [] - ) + self.assertEqual(self.view.get_regions(manager.key), []) def test_del(self): - self.view = new_view(self.window, scratch=True, content='Hello, World!') + self.view = new_view(self.window, scratch=True, content="Hello, World!") manager = RegionManager(self.view) manager.set([Region(0, 5)]) - self.assertEqual( - manager.get(), - [Region(0, 5)] - ) + self.assertEqual(manager.get(), [Region(0, 5)]) - self.assertEqual( - self.view.get_regions(manager.key), - [Region(0, 5)] - ) + self.assertEqual(self.view.get_regions(manager.key), [Region(0, 5)]) key = manager.key del manager - self.assertEqual( - self.view.get_regions(key), - [] - ) + self.assertEqual(self.view.get_regions(key), []) def test_key(self): - self.view = new_view(self.window, scratch=True, content='Hello, World!') - key = 'TestRegionManager' + self.view = new_view(self.window, scratch=True, content="Hello, World!") + key = "TestRegionManager" manager = RegionManager(self.view, key) manager.set([Region(0, 5)]) - self.assertEqual( - manager.get(), - [Region(0, 5)] - ) + self.assertEqual(manager.get(), [Region(0, 5)]) - self.assertEqual( - self.view.get_regions(key), - [Region(0, 5)] - ) + self.assertEqual(self.view.get_regions(key), [Region(0, 5)]) def test_no_default_args(self): view = ViewMock() @@ -112,20 +79,14 @@ def test_no_default_args(self): regions = [Region(0, 5)] manager.set(regions) - view.add_regions.assert_called_once_with( - manager.key, - regions, - '', - '', - 0 - ) + view.add_regions.assert_called_once_with(manager.key, regions, "", "", 0) def test_args(self): view = ViewMock() manager = RegionManager( view, - scope='region.reddish', - icon='dot', + scope="region.reddish", + icon="dot", flags=sublime.DRAW_EMPTY, ) @@ -133,25 +94,12 @@ def test_args(self): manager.set(regions) view.add_regions.assert_called_once_with( - manager.key, - regions, - 'region.reddish', - 'dot', - sublime.DRAW_EMPTY + manager.key, regions, "region.reddish", "dot", sublime.DRAW_EMPTY ) view.add_regions.reset_mock() - manager.set( - regions, - scope='region.bluish', - icon='circle', - flags=sublime.HIDE_ON_MINIMAP - ) + manager.set(regions, scope="region.bluish", icon="circle", flags=sublime.HIDE_ON_MINIMAP) view.add_regions.assert_called_once_with( - manager.key, - regions, - 'region.bluish', - 'circle', - sublime.HIDE_ON_MINIMAP + manager.key, regions, "region.bluish", "circle", sublime.HIDE_ON_MINIMAP ) diff --git a/tests/test_resource_path.py b/tests/test_resource_path.py index 29c1a76..0ae1ec2 100644 --- a/tests/test_resource_path.py +++ b/tests/test_resource_path.py @@ -12,8 +12,7 @@ class TestResourcePath(DeferrableTestCase): def setUp(self): self.temp = TemporaryPackage( - 'test_package', - ResourcePath("Packages/sublime_lib/tests/test_package") + "test_package", ResourcePath("Packages/sublime_lib/tests/test_package") ) self.temp.create() @@ -28,95 +27,84 @@ def test_glob_resources(self): [ ResourcePath("Packages/test_package/helloworld.txt"), ResourcePath("Packages/test_package/UTF-8-test.txt"), - ] + ], ) - self.assertEqual( - ResourcePath.glob_resources("ks27jArEz4"), - [] - ) + self.assertEqual(ResourcePath.glob_resources("ks27jArEz4"), []) self.assertEqual( ResourcePath.glob_resources("*ks27jArEz4"), - [ - ResourcePath('Packages/sublime_lib/tests/uniquely_named_file_ks27jArEz4') - ] + [ResourcePath("Packages/sublime_lib/tests/uniquely_named_file_ks27jArEz4")], ) def test_from_file_path_packages(self): self.assertEqual( - ResourcePath.from_file_path(Path(sublime.packages_path(), 'test_package')), - ResourcePath("Packages/test_package") + ResourcePath.from_file_path(Path(sublime.packages_path(), "test_package")), + ResourcePath("Packages/test_package"), ) def test_from_file_path_cache(self): self.assertEqual( - ResourcePath.from_file_path(Path(sublime.cache_path(), 'test_package')), - ResourcePath("Cache/test_package") + ResourcePath.from_file_path(Path(sublime.cache_path(), "test_package")), + ResourcePath("Cache/test_package"), ) def test_from_file_path_installed_packages(self): self.assertEqual( ResourcePath.from_file_path( - Path(sublime.installed_packages_path(), 'test_package.sublime-package', 'foo.py') + Path(sublime.installed_packages_path(), "test_package.sublime-package", "foo.py") ), - ResourcePath("Packages/test_package/foo.py") + ResourcePath("Packages/test_package/foo.py"), ) def test_from_file_path_installed_packages_not_installed(self): with self.assertRaises(ValueError): ResourcePath.from_file_path( - Path(sublime.installed_packages_path(), 'test_package', 'foo.py') + Path(sublime.installed_packages_path(), "test_package", "foo.py") ), def test_from_file_path_installed_packages_root(self): self.assertEqual( ResourcePath.from_file_path(Path(sublime.installed_packages_path())), - ResourcePath("Packages") + ResourcePath("Packages"), ) def test_from_file_path_default_packages(self): self.assertEqual( ResourcePath.from_file_path( Path(sublime.executable_path()).parent.joinpath( - 'Packages', 'test_package.sublime-package', 'foo.py' + "Packages", "test_package.sublime-package", "foo.py" ) ), - ResourcePath("Packages/test_package/foo.py") + ResourcePath("Packages/test_package/foo.py"), ) def test_from_file_path_default_packages_root(self): self.assertEqual( - ResourcePath.from_file_path( - Path(sublime.executable_path()).parent / 'Packages' - ), - ResourcePath("Packages") + ResourcePath.from_file_path(Path(sublime.executable_path()).parent / "Packages"), + ResourcePath("Packages"), ) def test_from_file_path_error(self): with self.assertRaises(ValueError): - ResourcePath.from_file_path(Path('/test_package')), + ResourcePath.from_file_path(Path("/test_package")), def test_from_file_path_relative(self): with self.assertRaises(ValueError): - ResourcePath.from_file_path(Path('test_package')), + ResourcePath.from_file_path(Path("test_package")), def test_file_path_packages(self): self.assertEqual( ResourcePath("Packages/Foo/bar.py").file_path(), - Path(sublime.packages_path(), 'Foo/bar.py') + Path(sublime.packages_path(), "Foo/bar.py"), ) def test_file_path_packages_root(self): - self.assertEqual( - ResourcePath("Packages").file_path(), - Path(sublime.packages_path()) - ) + self.assertEqual(ResourcePath("Packages").file_path(), Path(sublime.packages_path())) def test_file_path_cache(self): self.assertEqual( - ResourcePath("Cache/Foo/bar.py").file_path(), - Path(sublime.cache_path(), 'Foo/bar.py') + ResourcePath("Cache/Foo/bar.py").file_path(), Path(sublime.cache_path(), "Foo/bar.py") ) def test_file_path_error(self): @@ -124,19 +112,14 @@ def test_file_path_error(self): ResourcePath("Elsewhere/Foo/bar.py").file_path(), def test_exists(self): - self.assertTrue( - ResourcePath("Packages/test_package/helloworld.txt").exists() - ) + self.assertTrue(ResourcePath("Packages/test_package/helloworld.txt").exists()) def test_not_exists(self): - self.assertFalse( - ResourcePath("Packages/test_package/nonexistentfile.txt").exists() - ) + self.assertFalse(ResourcePath("Packages/test_package/nonexistentfile.txt").exists()) def test_read_text(self): self.assertEqual( - ResourcePath("Packages/test_package/helloworld.txt").read_text(), - "Hello, World!\n" + ResourcePath("Packages/test_package/helloworld.txt").read_text(), "Hello, World!\n" ) def test_read_text_missing(self): @@ -149,8 +132,7 @@ def test_read_text_invalid_unicode(self): def test_read_bytes(self): self.assertEqual( - ResourcePath("Packages/test_package/helloworld.txt").read_bytes(), - b"Hello, World!\n" + ResourcePath("Packages/test_package/helloworld.txt").read_bytes(), b"Hello, World!\n" ) def test_read_bytes_missing(self): @@ -163,26 +145,26 @@ def test_read_bytes_invalid_unicode(self): def test_glob(self): self.assertEqual( - ResourcePath("Packages/test_package").glob('*.txt'), + ResourcePath("Packages/test_package").glob("*.txt"), [ ResourcePath("Packages/test_package/helloworld.txt"), ResourcePath("Packages/test_package/UTF-8-test.txt"), - ] + ], ) def test_rglob(self): self.assertEqual( - ResourcePath("Packages/test_package").rglob('*.txt'), + ResourcePath("Packages/test_package").rglob("*.txt"), [ ResourcePath("Packages/test_package/helloworld.txt"), ResourcePath("Packages/test_package/UTF-8-test.txt"), ResourcePath("Packages/test_package/directory/goodbyeworld.txt"), - ] + ], ) def test_rglob_error(self): with self.assertRaises(NotImplementedError): - ResourcePath("Packages/test_package").rglob('/*.txt') + ResourcePath("Packages/test_package").rglob("/*.txt") def test_children(self): self.assertEqual( @@ -192,19 +174,19 @@ def test_children(self): ResourcePath("Packages/test_package/helloworld.txt"), ResourcePath("Packages/test_package/UTF-8-test.txt"), ResourcePath("Packages/test_package/directory"), - ] + ], ) def test_copy_text(self): with tempfile.TemporaryDirectory() as directory: source = ResourcePath("Packages/test_package/helloworld.txt") - destination = Path(directory) / 'helloworld.txt' + destination = Path(directory) / "helloworld.txt" source.copy(destination) self.assertTrue(destination.is_file()) - with open(str(destination), 'r') as file: + with open(str(destination), "r") as file: text = file.read() self.assertEqual(text, source.read_text()) @@ -212,13 +194,13 @@ def test_copy_text(self): def test_copy_binary(self): with tempfile.TemporaryDirectory() as directory: source = ResourcePath("Packages/test_package/UTF-8-test.txt") - destination = Path(directory) / 'UTF-8-test.txt' + destination = Path(directory) / "UTF-8-test.txt" source.copy(destination) self.assertTrue(destination.is_file()) - with open(str(destination), 'rb') as file: + with open(str(destination), "rb") as file: data = file.read() self.assertEqual(data, source.read_bytes()) @@ -226,16 +208,16 @@ def test_copy_binary(self): def test_copy_existing(self): with tempfile.TemporaryDirectory() as directory: source = ResourcePath("Packages/test_package/helloworld.txt") - destination = Path(directory) / 'helloworld.txt' + destination = Path(directory) / "helloworld.txt" - with open(str(destination), 'w') as file: + with open(str(destination), "w") as file: file.write("Nothing to see here.\n") source.copy(destination) self.assertTrue(destination.is_file()) - with open(str(destination), 'r') as file: + with open(str(destination), "r") as file: text = file.read() self.assertEqual(text, source.read_text()) @@ -243,10 +225,10 @@ def test_copy_existing(self): def test_copy_existing_error(self): with tempfile.TemporaryDirectory() as directory: source = ResourcePath("Packages/test_package/helloworld.txt") - destination = Path(directory) / 'helloworld.txt' + destination = Path(directory) / "helloworld.txt" text = "Nothing to see here.\n" - with open(str(destination), 'w') as file: + with open(str(destination), "w") as file: file.write(text) with self.assertRaises(FileExistsError): @@ -255,7 +237,7 @@ def test_copy_existing_error(self): def test_copy_directory_error(self): with tempfile.TemporaryDirectory() as directory: source = ResourcePath("Packages/test_package/helloworld.txt") - destination = Path(directory) / 'helloworld.txt' + destination = Path(directory) / "helloworld.txt" destination.mkdir() @@ -267,26 +249,23 @@ def test_copy_directory_error(self): def test_copytree(self): with tempfile.TemporaryDirectory() as directory: source = ResourcePath("Packages/test_package") - destination = Path(directory) / 'tree' + destination = Path(directory) / "tree" source.copytree(destination) self.assertEqual( { path.relative_to(destination).parts - for path in destination.rglob('*') + for path in destination.rglob("*") if path.is_file() }, - { - path.relative_to(source) - for path in source.rglob('*') - } + {path.relative_to(source) for path in source.rglob("*")}, ) def test_copytree_exists_error(self): with tempfile.TemporaryDirectory() as directory: source = ResourcePath("Packages/test_package") - destination = Path(directory) / 'tree' + destination = Path(directory) / "tree" destination.mkdir() with self.assertRaises(FileExistsError): @@ -295,12 +274,12 @@ def test_copytree_exists_error(self): def test_copytree_exists(self): with tempfile.TemporaryDirectory() as directory: source = ResourcePath("Packages/test_package") - destination = Path(directory) / 'tree' + destination = Path(directory) / "tree" destination.mkdir() - helloworld_file = destination / 'helloworld.txt' + helloworld_file = destination / "helloworld.txt" - with open(str(helloworld_file), 'w') as file: + with open(str(helloworld_file), "w") as file: file.write("Nothing to see here.\n") source.copytree(destination, exist_ok=True) @@ -308,19 +287,13 @@ def test_copytree_exists(self): self.assertEqual( { path.relative_to(destination).parts - for path in destination.rglob('*') + for path in destination.rglob("*") if path.is_file() }, - { - path.relative_to(source) - for path in source.rglob('*') - } + {path.relative_to(source) for path in source.rglob("*")}, ) with open(str(helloworld_file)) as file: helloworld_contents = file.read() - self.assertEqual( - helloworld_contents, - (source / 'helloworld.txt').read_text() - ) + self.assertEqual(helloworld_contents, (source / "helloworld.txt").read_text()) diff --git a/tests/test_selection_panel.py b/tests/test_selection_panel.py index 46eb0ac..aa687f3 100644 --- a/tests/test_selection_panel.py +++ b/tests/test_selection_panel.py @@ -12,40 +12,40 @@ def __init__(self, callback=None): super().__init__() def side_effect(*args, **kwargs): - bound_args = (signature(sublime.Window.show_quick_panel) - .bind(self, *args, **kwargs).arguments) + bound_args = ( + signature(sublime.Window.show_quick_panel).bind(self, *args, **kwargs).arguments + ) callback(**bound_args) self.show_quick_panel = MagicMock( - spec=sublime.Window.show_quick_panel, - side_effect=side_effect if callback else None + spec=sublime.Window.show_quick_panel, side_effect=side_effect if callback else None ) # From Python 3.5 # https://github.com/python/cpython/blob/master/Lib/unittest/mock.py def assert_not_called(_mock_self): - """assert that the mock was never called. - """ + """assert that the mock was never called.""" self = _mock_self if self.call_count != 0: - msg = ("Expected '%s' to not have been called. Called %s times.%s" - % (self._mock_name or 'mock', - self.call_count, - self._calls_repr())) + msg = "Expected '%s' to not have been called. Called %s times.%s" % ( + self._mock_name or "mock", + self.call_count, + self._calls_repr(), + ) raise AssertionError(msg) # From Python 3.5 def assert_called_once(_mock_self): - """assert that the mock was called only once. - """ + """assert that the mock was called only once.""" self = _mock_self if not self.call_count == 1: - msg = ("Expected '%s' to have been called once. Called %s times.%s" - % (self._mock_name or 'mock', - self.call_count, - self._calls_repr())) + msg = "Expected '%s' to have been called once. Called %s times.%s" % ( + self._mock_name or "mock", + self.call_count, + self._calls_repr(), + ) raise AssertionError(msg) @@ -54,14 +54,14 @@ def assert_called_once_with_partial(mock, **specified_args): optionally with other args.""" assert_called_once(mock) called_args, called_kwargs = mock.call_args - called_dict = (signature(sublime.Window.show_quick_panel) - .bind(None, *called_args, **called_kwargs).arguments) - - failures = any( - k in specified_args and v != specified_args[k] - for k, v in called_dict.items() + called_dict = ( + signature(sublime.Window.show_quick_panel) + .bind(None, *called_args, **called_kwargs) + .arguments ) + failures = any(k in specified_args and v != specified_args[k] for k, v in called_dict.items()) + if failures: mock.assert_called_once_with(**specified_args) @@ -76,7 +76,7 @@ def test_type_coercion(self): assert_called_once_with_partial( window.show_quick_panel, - items=[['10'], ['20'], ['30']], + items=[["10"], ["20"], ["30"]], ) def test_multiline_type_coercion(self): @@ -84,61 +84,46 @@ def test_multiline_type_coercion(self): show_selection_panel( window=window, items=[ - ['a', 10], - ['b', 20], - ('c', 30), + ["a", 10], + ["b", 20], + ("c", 30), ], ) assert_called_once_with_partial( window.show_quick_panel, items=[ - ['a', '10'], - ['b', '20'], - ['c', '30'], + ["a", "10"], + ["b", "20"], + ["c", "30"], ], ) def test_empty_items_error(self): with self.assertRaises(ValueError): - show_selection_panel( - WindowMock(), - items=[] - ) + show_selection_panel(WindowMock(), items=[]) def test_mixed_label_types(self): window = WindowMock() - show_selection_panel( - window=window, - items=['a', 'b'], - labels=[['a'], 'b'] - ) + show_selection_panel(window=window, items=["a", "b"], labels=[["a"], "b"]) assert_called_once_with_partial( window.show_quick_panel, - items=[['a'], ['b']], + items=[["a"], ["b"]], ) def test_mixed_label_lengths(self): window = WindowMock() - show_selection_panel( - window=window, - items=['a', 'b'], - labels=[['a'], ['b', 'c']] - ) + show_selection_panel(window=window, items=["a", "b"], labels=[["a"], ["b", "c"]]) assert_called_once_with_partial( window.show_quick_panel, - items=[['a', ''], ['b', 'c']], + items=[["a", ""], ["b", "c"]], ) def test_item_labels_lengths_error(self): with self.assertRaises(ValueError): - show_selection_panel( - WindowMock(), - items=['a', 'b', 'c'], - labels=['x', 'y'] - ) + show_selection_panel(WindowMock(), items=["a", "b", "c"], labels=["x", "y"]) def test_selected(self): on_select = MagicMock() @@ -146,11 +131,11 @@ def test_selected(self): show_selection_panel( window=WindowMock(lambda on_select, **rest: on_select(1)), - items=['a', 'b', 'c'], + items=["a", "b", "c"], on_select=on_select, - on_cancel=on_cancel + on_cancel=on_cancel, ) - on_select.assert_called_once_with('b') + on_select.assert_called_once_with("b") assert_not_called(on_cancel) def test_cancel(self): @@ -159,9 +144,9 @@ def test_cancel(self): show_selection_panel( window=WindowMock(lambda on_select, **rest: on_select(-1)), - items=['a', 'b', 'c'], + items=["a", "b", "c"], on_select=on_select, - on_cancel=on_cancel + on_cancel=on_cancel, ) assert_not_called(on_select) on_cancel.assert_called_once_with() @@ -171,54 +156,37 @@ def test_highlight(self): show_selection_panel( window=WindowMock(lambda on_highlight, **rest: on_highlight(1)), - items=['a', 'b', 'c'], + items=["a", "b", "c"], on_highlight=on_highlight, ) - on_highlight.assert_called_once_with('b') + on_highlight.assert_called_once_with("b") def test_no_flags(self): window = WindowMock() - show_selection_panel( - window=window, - items=['a', 'b', 'c'] - ) + show_selection_panel(window=window, items=["a", "b", "c"]) - assert_called_once_with_partial( - window.show_quick_panel, - flags=0 - ) + assert_called_once_with_partial(window.show_quick_panel, flags=0) def test_flags(self): window = WindowMock() flags = sublime.MONOSPACE_FONT | sublime.KEEP_OPEN_ON_FOCUS_LOST - show_selection_panel( - window=window, - items=['a', 'b', 'c'], - flags=flags - ) + show_selection_panel(window=window, items=["a", "b", "c"], flags=flags) - assert_called_once_with_partial( - window.show_quick_panel, - flags=flags - ) + assert_called_once_with_partial(window.show_quick_panel, flags=flags) def test_flags_conversion(self): window = WindowMock() - flags = ['MONOSPACE_FONT', 'KEEP_OPEN_ON_FOCUS_LOST'] + flags = ["MONOSPACE_FONT", "KEEP_OPEN_ON_FOCUS_LOST"] - show_selection_panel( - window=window, - items=['a', 'b', 'c'], - flags=flags - ) + show_selection_panel(window=window, items=["a", "b", "c"], flags=flags) assert_called_once_with_partial( window.show_quick_panel, - flags=(sublime.MONOSPACE_FONT | sublime.KEEP_OPEN_ON_FOCUS_LOST) + flags=(sublime.MONOSPACE_FONT | sublime.KEEP_OPEN_ON_FOCUS_LOST), ) def test_labels_function(self): @@ -227,16 +195,16 @@ def test_labels_function(self): show_selection_panel( window=window, items=[ - {'name': 'a'}, - {'name': 'b'}, - {'name': 'c'}, + {"name": "a"}, + {"name": "b"}, + {"name": "c"}, ], - labels=lambda item: item['name'] + labels=lambda item: item["name"], ) assert_called_once_with_partial( window.show_quick_panel, - items=[['a'], ['b'], ['c']], + items=[["a"], ["b"], ["c"]], ) def test_labels_list(self): @@ -245,16 +213,16 @@ def test_labels_list(self): show_selection_panel( window=window, items=[ - {'name': 'a'}, - {'name': 'b'}, - {'name': 'c'}, + {"name": "a"}, + {"name": "b"}, + {"name": "c"}, ], - labels=['a', 'b', 'c'], + labels=["a", "b", "c"], ) assert_called_once_with_partial( window.show_quick_panel, - items=[['a'], ['b'], ['c']], + items=[["a"], ["b"], ["c"]], ) def test_no_selected(self): @@ -262,27 +230,17 @@ def test_no_selected(self): show_selection_panel( window=window, - items=['a', 'b', 'c'], + items=["a", "b", "c"], ) - assert_called_once_with_partial( - window.show_quick_panel, - selected_index=-1 - ) + assert_called_once_with_partial(window.show_quick_panel, selected_index=-1) def test_selected_simple(self): window = WindowMock() - show_selection_panel( - window=window, - items=['a', 'b', 'c'], - selected='b' - ) + show_selection_panel(window=window, items=["a", "b", "c"], selected="b") - assert_called_once_with_partial( - window.show_quick_panel, - selected_index=1 - ) + assert_called_once_with_partial(window.show_quick_panel, selected_index=1) def test_selected_complex(self): window = WindowMock() @@ -290,26 +248,17 @@ def test_selected_complex(self): show_selection_panel( window=window, items=[ - {'name': 'a'}, - {'name': 'b'}, - {'name': 'c'}, + {"name": "a"}, + {"name": "b"}, + {"name": "c"}, ], - labels=lambda item: item['name'], - selected={'name': 'b'} + labels=lambda item: item["name"], + selected={"name": "b"}, ) - assert_called_once_with_partial( - window.show_quick_panel, - selected_index=1 - ) + assert_called_once_with_partial(window.show_quick_panel, selected_index=1) def test_selected_invalid(self): window = WindowMock() - self.assertRaises( - ValueError, - show_selection_panel, - window=window, - items=[], - selected='b' - ) + self.assertRaises(ValueError, show_selection_panel, window=window, items=[], selected="b") diff --git a/tests/test_settings_dict.py b/tests/test_settings_dict.py index d57f385..bcf99eb 100644 --- a/tests/test_settings_dict.py +++ b/tests/test_settings_dict.py @@ -21,7 +21,7 @@ def tearDown(self): def test_item(self): self.settings.set("example_setting", "Hello, World!") - self.assertEqual(self.fancy['example_setting'], "Hello, World!") + self.assertEqual(self.fancy["example_setting"], "Hello, World!") def test_item_missing_error(self): self.settings.erase("example_setting") @@ -31,7 +31,7 @@ def test_item_missing_error(self): def test_get(self): self.settings.set("example_setting", "Hello, World!") - self.assertEqual(self.fancy.get('example_setting'), "Hello, World!") + self.assertEqual(self.fancy.get("example_setting"), "Hello, World!") def test_get_missing_none(self): self.settings.erase("example_setting") @@ -46,7 +46,7 @@ def test_get_missing_default(self): def test_set(self): self.fancy["example_setting"] = "Hello, World!" - self.assertEqual(self.settings.get('example_setting'), "Hello, World!") + self.assertEqual(self.settings.get("example_setting"), "Hello, World!") def test_delete(self): self.fancy["example_setting"] = "Hello, World!" @@ -95,34 +95,34 @@ def test_setdefault_none(self): def test_update(self): self.fancy["foo"] = "Hello, World!" - self.fancy.update({'foo': 1, 'bar': 2}, xyzzy=3) - self.fancy.update([('bar', 20), ('baz', 30)], yzzyx=4) + self.fancy.update({"foo": 1, "bar": 2}, xyzzy=3) + self.fancy.update([("bar", 20), ("baz", 30)], yzzyx=4) - self.assertEqual(self.fancy['foo'], 1) - self.assertEqual(self.fancy['bar'], 20) - self.assertEqual(self.fancy['baz'], 30) - self.assertEqual(self.fancy['xyzzy'], 3) - self.assertEqual(self.fancy['yzzyx'], 4) + self.assertEqual(self.fancy["foo"], 1) + self.assertEqual(self.fancy["bar"], 20) + self.assertEqual(self.fancy["baz"], 30) + self.assertEqual(self.fancy["xyzzy"], 3) + self.assertEqual(self.fancy["yzzyx"], 4) def test_not_iterable(self): self.assertRaises(NotImplementedError, iter, self.fancy) def test_get_default(self): - defaults = {'example_1': 'Hello, World!'} + defaults = {"example_1": "Hello, World!"} chained = ChainMap(self.fancy, defaults) - self.assertNotIn('example_1', self.fancy) - self.assertIn('example_1', chained) + self.assertNotIn("example_1", self.fancy) + self.assertIn("example_1", chained) - self.assertEqual(chained['example_1'], 'Hello, World!') + self.assertEqual(chained["example_1"], "Hello, World!") - chained['example_1'] = 'Goodbye, World!' - self.assertEqual(chained['example_1'], 'Goodbye, World!') - self.assertEqual(self.fancy['example_1'], 'Goodbye, World!') - self.assertEqual(defaults['example_1'], 'Hello, World!') + chained["example_1"] = "Goodbye, World!" + self.assertEqual(chained["example_1"], "Goodbye, World!") + self.assertEqual(self.fancy["example_1"], "Goodbye, World!") + self.assertEqual(defaults["example_1"], "Hello, World!") - self.assertRaises(KeyError, chained.__getitem__, 'example_2') + self.assertRaises(KeyError, chained.__getitem__, "example_2") self.assertRaises(NotImplementedError, iter, chained) @@ -151,7 +151,7 @@ def tearDown(self): self.view.window().run_command("close_file") def test_subscribe(self): - self.fancy['example_setting'] = 1 + self.fancy["example_setting"] = 1 values = None @@ -159,20 +159,17 @@ def callback(new, old): nonlocal values values = (new, old) - unsubscribe = self.fancy.subscribe('example_setting', callback) + unsubscribe = self.fancy.subscribe("example_setting", callback) - self.fancy['example_setting'] = 2 + self.fancy["example_setting"] = 2 self.assertEqual(values, (2, 1)) unsubscribe() - self.fancy['example_setting'] = 3 + self.fancy["example_setting"] = 3 self.assertEqual(values, (2, 1)) def test_subscribe_multiple(self): - self.fancy.update( - example_1=1, - example_2=2 - ) + self.fancy.update(example_1=1, example_2=2) values = None @@ -180,26 +177,21 @@ def callback(new, old): nonlocal values values = new - self.fancy.subscribe({'example_1', 'example_2', 'example_3'}, callback) + self.fancy.subscribe({"example_1", "example_2", "example_3"}, callback) - self.fancy['example_1'] = 10 + self.fancy["example_1"] = 10 - self.assertEqual(values, { - 'example_1': 10, - 'example_2': 2 - }) + self.assertEqual(values, {"example_1": 10, "example_2": 2}) def test_settings_change_in_callback(self): calls = [] def callback(new, old): calls.append((new, old)) - self.fancy['bar'] = True + self.fancy["bar"] = True - self.fancy.subscribe('foo', callback) + self.fancy.subscribe("foo", callback) - self.fancy['foo'] = True + self.fancy["foo"] = True - self.assertEqual(calls, [ - (True, None) - ]) + self.assertEqual(calls, [(True, None)]) diff --git a/tests/test_syntax.py b/tests/test_syntax.py index ba17af5..cb7ed32 100644 --- a/tests/test_syntax.py +++ b/tests/test_syntax.py @@ -8,7 +8,7 @@ from unittest import TestCase -TEST_SYNTAXES_PATH = ResourcePath('Packages/sublime_lib/tests/syntax_test_package') +TEST_SYNTAXES_PATH = ResourcePath("Packages/sublime_lib/tests/syntax_test_package") class TestSyntax(TestCase): @@ -19,26 +19,22 @@ def test_list_syntaxes(self): def test_get_syntax(self): self.assertEqual( - get_syntax_for_scope('source.python'), - 'Packages/Python/Python.sublime-syntax' + get_syntax_for_scope("source.python"), "Packages/Python/Python.sublime-syntax" ) def test_get_syntax_none(self): with self.assertRaises(ValueError): - get_syntax_for_scope('sublime_lib.nonexistent_scope') + get_syntax_for_scope("sublime_lib.nonexistent_scope") class TestGetMetadata(TestCase): def test_defaults(self): - self.assertEqual( - SyntaxInfo(path="a file"), - SyntaxInfo("a file", None, None, False) - ) + self.assertEqual(SyntaxInfo(path="a file"), SyntaxInfo("a file", None, None, False)) def test_sublime_syntax(self): - path = TEST_SYNTAXES_PATH / 'sublime_lib_test.sublime-syntax' + path = TEST_SYNTAXES_PATH / "sublime_lib_test.sublime-syntax" self.assertEqual( get_syntax_metadata(path), SyntaxInfo( @@ -46,54 +42,40 @@ def test_sublime_syntax(self): name="sublime_lib test syntax (sublime-syntax)", hidden=True, scope="source.sublime_lib_test", - ) + ), ) def test_sublime_syntax_no_name(self): - path = TEST_SYNTAXES_PATH / 'sublime_lib_test_no_name.sublime-syntax' - self.assertEqual( - get_syntax_metadata(path).name, - 'sublime_lib_test_no_name' - ) + path = TEST_SYNTAXES_PATH / "sublime_lib_test_no_name.sublime-syntax" + self.assertEqual(get_syntax_metadata(path).name, "sublime_lib_test_no_name") def test_sublime_syntax_null_name(self): - path = TEST_SYNTAXES_PATH / 'sublime_lib_test_null_name.sublime-syntax' - self.assertEqual( - get_syntax_metadata(path).name, - 'sublime_lib_test_null_name' - ) + path = TEST_SYNTAXES_PATH / "sublime_lib_test_null_name.sublime-syntax" + self.assertEqual(get_syntax_metadata(path).name, "sublime_lib_test_null_name") def test_sublime_syntax_empty_name(self): - path = TEST_SYNTAXES_PATH / 'sublime_lib_test_empty_name.sublime-syntax' - self.assertEqual( - get_syntax_metadata(path).name, - 'sublime_lib_test_empty_name' - ) + path = TEST_SYNTAXES_PATH / "sublime_lib_test_empty_name.sublime-syntax" + self.assertEqual(get_syntax_metadata(path).name, "sublime_lib_test_empty_name") def test_tmlanguage_empty_name(self): - path = TEST_SYNTAXES_PATH / 'sublime_lib_test_empty_name_tmLanguage.tmLanguage' - self.assertEqual( - get_syntax_metadata(path).name, - 'sublime_lib_test_empty_name_tmLanguage' - ) + path = TEST_SYNTAXES_PATH / "sublime_lib_test_empty_name_tmLanguage.tmLanguage" + self.assertEqual(get_syntax_metadata(path).name, "sublime_lib_test_empty_name_tmLanguage") def _syntax_at_path(self, path): - return next(( - info for info in list_syntaxes() if info.path == str(path) - ), None) + return next((info for info in list_syntaxes() if info.path == str(path)), None) def test_shadowed_tmlanguage(self): - path = TEST_SYNTAXES_PATH / 'sublime_lib_test.tmLanguage' + path = TEST_SYNTAXES_PATH / "sublime_lib_test.tmLanguage" self.assertTrue(path.exists()) self.assertIsNone(self._syntax_at_path(path)) def test_shadowed_hidden_tmlanguage(self): - path = TEST_SYNTAXES_PATH / 'sublime_lib_test.hidden-tmLanguage' + path = TEST_SYNTAXES_PATH / "sublime_lib_test.hidden-tmLanguage" self.assertTrue(path.exists()) self.assertIsNone(self._syntax_at_path(path)) def test_tmlanguage(self): - path = TEST_SYNTAXES_PATH / 'sublime_lib_test_2.tmLanguage' + path = TEST_SYNTAXES_PATH / "sublime_lib_test_2.tmLanguage" self.assertEqual( get_syntax_metadata(path), SyntaxInfo( @@ -101,11 +83,11 @@ def test_tmlanguage(self): name="sublime_lib test syntax 2 (tmLanguage)", hidden=True, scope="source.sublime_lib_test_2", - ) + ), ) def test_hidden_tmlanguage(self): - path = TEST_SYNTAXES_PATH / 'sublime_lib_test_2.hidden-tmLanguage' + path = TEST_SYNTAXES_PATH / "sublime_lib_test_2.hidden-tmLanguage" self.assertEqual( get_syntax_metadata(path), SyntaxInfo( @@ -113,5 +95,5 @@ def test_hidden_tmlanguage(self): name="sublime_lib_test_2", hidden=True, scope="source.sublime_lib_test_2", - ) + ), ) diff --git a/tests/test_view_stream.py b/tests/test_view_stream.py index 5dc498e..5333829 100644 --- a/tests/test_view_stream.py +++ b/tests/test_view_stream.py @@ -17,10 +17,7 @@ def tearDown(self): self.view.close() def assertContents(self, text): - self.assertEqual( - self.view.substr(sublime.Region(0, self.view.size())), - text - ) + self.assertEqual(self.view.substr(sublime.Region(0, self.view.size())), text) def test_stream_operations(self): self.stream.write("Hello, ") @@ -49,22 +46,22 @@ def test_write_size(self): def test_no_indent(self): text = " " - self.stream.view.settings().set('auto_indent', True) + self.stream.view.settings().set("auto_indent", True) self.stream.write(text) self.stream.write("\n") self.assertContents(text + "\n") - self.assertTrue(self.stream.view.settings().get('auto_indent')) + self.assertTrue(self.stream.view.settings().get("auto_indent")) def test_no_indent_off(self): text = " " - self.stream.view.settings().set('auto_indent', False) + self.stream.view.settings().set("auto_indent", False) self.stream.write(text) self.stream.write("\n") self.assertContents(text + "\n") - self.assertFalse(self.stream.view.settings().get('auto_indent')) + self.assertFalse(self.stream.view.settings().get("auto_indent")) def test_clear(self): self.stream.write("Some text") @@ -128,18 +125,18 @@ def test_readline(self): def test_write_read_only_failure(self): self.stream.view.set_read_only(True) - self.assertRaises(ValueError, self.stream.write, 'foo') + self.assertRaises(ValueError, self.stream.write, "foo") self.assertRaises(ValueError, self.stream.clear) def test_write_read_only_success(self): self.stream.view.set_read_only(True) self.stream.force_writes = True - self.stream.write('foo') - self.assertContents('foo') + self.stream.write("foo") + self.assertContents("foo") self.stream.clear() - self.assertContents('') + self.assertContents("") def _compare_print(self, *args, **kwargs): s = StringIO() @@ -160,31 +157,31 @@ def test_print(self): number = 42 self._compare_print(text, number) - self._compare_print(text, number, sep=',', end=';') - self._compare_print(text, number, sep='', end='') + self._compare_print(text, number, sep=",", end=";") + self._compare_print(text, number, sep="", end="") def test_print_no_indent(self): text = " " - self.stream.view.settings().set('auto_indent', True) + self.stream.view.settings().set("auto_indent", True) self.stream.print(text) self.assertContents(text + "\n") def test_print_read_only_failure(self): self.stream.view.set_read_only(True) - self.assertRaises(ValueError, self.stream.print, 'foo') + self.assertRaises(ValueError, self.stream.print, "foo") self.assertRaises(ValueError, self.stream.clear) def test_print_read_only_success(self): self.stream.view.set_read_only(True) self.stream.force_writes = True - self.stream.print('foo') + self.stream.print("foo") self.assertContents("foo\n") self.stream.clear() - self.assertContents('') + self.assertContents("") def assertSeek(self, expected, *args): returned = self.stream.seek(*args) @@ -195,7 +192,7 @@ def assertSeek(self, expected, *args): def test_seek(self): from io import SEEK_SET, SEEK_CUR, SEEK_END - self.stream.write('test\n' * 10) + self.stream.write("test\n" * 10) self.assertSeek(0, -100) self.assertSeek(50, 100) @@ -212,14 +209,10 @@ def test_seek_invalid(self): self.stream.seek(0, -99) def assertCursorVisible(self): - self.assertTrue( - self.stream.view.visible_region().contains( - self.stream.tell() - ) - ) + self.assertTrue(self.stream.view.visible_region().contains(self.stream.tell())) def test_show_cursor(self): - self.stream.write('test\n' * 200) + self.stream.write("test\n" * 200) self.stream.show_cursor() yield 200 @@ -228,7 +221,7 @@ def test_show_cursor(self): def test_show_cursor_auto(self): self.stream.follow_cursor = True - self.stream.write('test\n' * 200) + self.stream.write("test\n" * 200) yield 200 self.assertCursorVisible() diff --git a/tests/test_view_utils.py b/tests/test_view_utils.py index 20c61d9..5c37eab 100644 --- a/tests/test_view_utils.py +++ b/tests/test_view_utils.py @@ -11,7 +11,7 @@ def setUp(self): self.window = sublime.active_window() def tearDown(self): - if getattr(self, 'view', None): + if getattr(self, "view", None): try: close_view(self.view, force=True) except ValueError: @@ -22,17 +22,17 @@ def test_new_view(self): self.assertTrue(self.view.is_valid()) - self.assertEquals(self.view.name(), '') + self.assertEquals(self.view.name(), "") self.assertFalse(self.view.is_read_only()) self.assertFalse(self.view.is_scratch()) self.assertFalse(self.view.overwrite_status()) - self.assertEquals(self.view.scope_name(0).strip(), 'text.plain') + self.assertEquals(self.view.scope_name(0).strip(), "text.plain") def test_name(self): - self.view = new_view(self.window, name='My Name') + self.view = new_view(self.window, name="My Name") - self.assertEquals(self.view.name(), 'My Name') + self.assertEquals(self.view.name(), "My Name") def test_read_only(self): self.view = new_view(self.window, read_only=True) @@ -50,53 +50,45 @@ def test_overwrite(self): self.assertTrue(self.view.overwrite_status()) def test_settings(self): - self.view = new_view(self.window, settings={ - 'example_setting': 'Hello, World!', - }) - - self.assertEquals( - self.view.settings().get('example_setting'), - 'Hello, World!' + self.view = new_view( + self.window, + settings={ + "example_setting": "Hello, World!", + }, ) + self.assertEquals(self.view.settings().get("example_setting"), "Hello, World!") + def test_scope(self): - self.view = new_view(self.window, scope='source.js') + self.view = new_view(self.window, scope="source.js") - self.assertTrue(self.view.scope_name(0).startswith('source.js')) + self.assertTrue(self.view.scope_name(0).startswith("source.js")) def test_syntax(self): - path = 'Packages/JavaScript/JavaScript.sublime-syntax' + path = "Packages/JavaScript/JavaScript.sublime-syntax" self.view = new_view(self.window, syntax=path) - self.assertEquals( - self.view.settings().get('syntax'), - path - ) + self.assertEquals(self.view.settings().get("syntax"), path) def test_unknown_args(self): - self.assertRaises( - ValueError, - new_view, - self.window, - bogus_arg="Hello, World!" - ) + self.assertRaises(ValueError, new_view, self.window, bogus_arg="Hello, World!") def test_syntax_scope_exclusive(self): self.assertRaises( ValueError, new_view, self.window, - scope='source.js', - syntax='Packages/JavaScript/JavaScript.sublime-syntax' + scope="source.js", + syntax="Packages/JavaScript/JavaScript.sublime-syntax", ) def test_encoding(self): - self.view = new_view(self.window, encoding='utf-16') + self.view = new_view(self.window, encoding="utf-16") self.assertEquals(self.view.encoding(), "UTF-16 LE with BOM") def test_line_endings_unix(self): - self.view = new_view(self.window, line_endings='unix') + self.view = new_view(self.window, line_endings="unix") self.assertEquals(self.view.line_endings(), "Unix") @@ -106,29 +98,23 @@ def test_line_endings_windows(self): self.assertEquals(self.view.line_endings(), "Windows") def test_line_endings_cr(self): - self.view = new_view(self.window, line_endings='\r') + self.view = new_view(self.window, line_endings="\r") self.assertEquals(self.view.line_endings(), "CR") def test_line_endings_invalid(self): with self.assertRaises(ValueError): - self.view = new_view(self.window, line_endings='other') + self.view = new_view(self.window, line_endings="other") def test_content(self): self.view = new_view(self.window, content="Hello, World!") - self.assertEquals( - self.view.substr(sublime.Region(0, self.view.size())), - "Hello, World!" - ) + self.assertEquals(self.view.substr(sublime.Region(0, self.view.size())), "Hello, World!") def test_content_read_only(self): self.view = new_view(self.window, content="Hello, World!", read_only=True) - self.assertEquals( - self.view.substr(sublime.Region(0, self.view.size())), - "Hello, World!" - ) + self.assertEquals(self.view.substr(sublime.Region(0, self.view.size())), "Hello, World!") def test_close_view(self): self.view = new_view(self.window) @@ -162,8 +148,8 @@ def test_close_closed_error(self): self.assertRaises(ValueError, close_view, self.view) def test_close_panel_error(self): - view = self.window.create_output_panel('sublime_lib-TestViewUtils') + view = self.window.create_output_panel("sublime_lib-TestViewUtils") self.assertRaises(ValueError, close_view, view) - self.window.destroy_output_panel('sublime_lib-TestViewUtils') + self.window.destroy_output_panel("sublime_lib-TestViewUtils") diff --git a/tests/test_window_utils.py b/tests/test_window_utils.py index 6242ae8..da32c15 100644 --- a/tests/test_window_utils.py +++ b/tests/test_window_utils.py @@ -11,7 +11,7 @@ def tearDown(self): # We have to wait between opening and closing a window to avoid a crash. # See https://github.com/sublimehq/sublime_text/issues/3960 yield 100 - if getattr(self, '_window', None): + if getattr(self, "_window", None): close_window(self._window, force=True) def test_is_valid(self): @@ -32,7 +32,7 @@ def test_close_window(self): def test_close_unsaved(self): self._window = new_window() - self._window.active_view().run_command('insert', {'characters': 'Hello, World!'}) + self._window.active_view().run_command("insert", {"characters": "Hello, World!"}) yield 100 with self.assertRaises(ValueError): @@ -46,7 +46,7 @@ def test_menu_visible(self): self._window = new_window(menu_visible=True) self.assertTrue(self._window.is_menu_visible()) - @skipIf(sublime.platform() == 'osx', "Menus are always visible on Mac OS.") + @skipIf(sublime.platform() == "osx", "Menus are always visible on Mac OS.") def test_menu_not_visible(self): self._window = new_window(menu_visible=False) self.assertFalse(self._window.is_menu_visible()) @@ -85,13 +85,10 @@ def test_status_bar_not_visible(self): def test_project_data(self): data = { - 'folders': [ - {'path': sublime.packages_path()}, + "folders": [ + {"path": sublime.packages_path()}, ], } self._window = new_window(project_data=data) - self.assertEqual( - self._window.project_data(), - data - ) + self.assertEqual(self._window.project_data(), data) diff --git a/tests/test_yaml_util.py b/tests/test_yaml_util.py index 6b1a233..6d4581b 100644 --- a/tests/test_yaml_util.py +++ b/tests/test_yaml_util.py @@ -22,11 +22,11 @@ def test_parse_simple_top_level_keys(self): self.assertEqual( parse_simple_top_level_keys(TEXT), { - 'single': 'test \' value', - 'double': 'test\nvalue', - 'unquoted': 'test\\value', + "single": "test ' value", + "double": "test\nvalue", + "unquoted": "test\\value", True: True, False: False, None: None, - } + }, ) diff --git a/unittesting.json b/unittesting.json deleted file mode 100644 index 5fcf8eb..0000000 --- a/unittesting.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "deferred": true -}