Skip to content

Commit

Permalink
Split config finding functions to workspace/finders.py
Browse files Browse the repository at this point in the history
  • Loading branch information
tony committed Oct 30, 2022
1 parent bb4d9ac commit 8da490d
Show file tree
Hide file tree
Showing 13 changed files with 545 additions and 536 deletions.
2 changes: 1 addition & 1 deletion conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

from libtmux.test import namer
from tests.fixtures import utils as test_utils
from tmuxp.cli.utils import get_workspace_dir
from tmuxp.workspace.finders import get_workspace_dir

if t.TYPE_CHECKING:
from libtmux.session import Session
Expand Down
14 changes: 7 additions & 7 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,6 @@ If you need an internal API stabilized please [file an issue](https://github.com

## CLI

```{eval-rst}
.. automethod:: tmuxp.cli.utils.get_workspace_dir
```

```{eval-rst}
.. automethod:: tmuxp.cli.import_config.get_teamocil_dir
```
Expand All @@ -70,15 +66,19 @@ If you need an internal API stabilized please [file an issue](https://github.com
### Finding

```{eval-rst}
.. automethod:: tmuxp.workspace.config.is_workspace_file
.. automethod:: tmuxp.workspace.finders.is_workspace_file
```

```{eval-rst}
.. automethod:: tmuxp.workspace.finders.in_dir
```

```{eval-rst}
.. automethod:: tmuxp.workspace.config.in_dir
.. automethod:: tmuxp.workspace.finders.in_cwd
```

```{eval-rst}
.. automethod:: tmuxp.workspace.config.in_cwd
.. automethod:: tmuxp.workspace.finders.get_workspace_dir
```

### Validation
Expand Down
3 changes: 2 additions & 1 deletion src/tmuxp/cli/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
import typing as t

from tmuxp.config_reader import ConfigReader
from tmuxp.workspace.finders import find_workspace_file, get_workspace_dir

from .utils import find_workspace_file, get_workspace_dir, prompt_yes_no
from .utils import prompt_yes_no


def create_convert_subparser(
Expand Down
2 changes: 1 addition & 1 deletion src/tmuxp/cli/edit.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import subprocess
import typing as t

from .utils import find_workspace_file
from tmuxp.workspace.finders import find_workspace_file


def create_edit_subparser(
Expand Down
3 changes: 2 additions & 1 deletion src/tmuxp/cli/freeze.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
from libtmux.server import Server
from tmuxp.config_reader import ConfigReader
from tmuxp.exc import TmuxpException
from tmuxp.workspace.finders import get_workspace_dir

from .. import util
from ..workspace import freezer
from .utils import get_workspace_dir, prompt, prompt_choices, prompt_yes_no
from .utils import prompt, prompt_choices, prompt_yes_no

if t.TYPE_CHECKING:
from typing_extensions import Literal, TypeAlias, TypeGuard
Expand Down
9 changes: 2 additions & 7 deletions src/tmuxp/cli/import_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,10 @@
import typing as t

from tmuxp.config_reader import ConfigReader
from tmuxp.workspace.finders import find_workspace_file

from ..workspace import importers
from .utils import (
find_workspace_file,
prompt,
prompt_choices,
prompt_yes_no,
tmuxp_echo,
)
from .utils import prompt, prompt_choices, prompt_yes_no, tmuxp_echo


def get_tmuxinator_dir() -> str:
Expand Down
14 changes: 4 additions & 10 deletions src/tmuxp/cli/load.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,8 @@
from .. import config_reader, exc, log, util
from ..workspace import config
from ..workspace.builder import WorkspaceBuilder
from .utils import (
find_workspace_file,
get_workspace_dir,
prompt_choices,
prompt_yes_no,
style,
tmuxp_echo,
)
from ..workspace.finders import find_workspace_file, get_workspace_dir, in_dir
from .utils import prompt_choices, prompt_yes_no, style, tmuxp_echo

if t.TYPE_CHECKING:
from typing_extensions import Literal, NotRequired, TypeAlias, TypedDict
Expand Down Expand Up @@ -478,7 +472,7 @@ def workspace_file_completion(ctx, params, incomplete):
choices += sorted(
pathlib.Path(os.path.relpath(p, pathlib.Path.cwd()))
for p in [pathlib.Path.cwd(), *pathlib.Path.cwd().parents]
if config.in_dir(str(p)) or len(list(p.glob(".tmuxp.*")))
if in_dir(str(p)) or len(list(p.glob(".tmuxp.*")))
)
# CWD look one directory up
choices += [
Expand All @@ -487,7 +481,7 @@ def workspace_file_completion(ctx, params, incomplete):
]

# Project configs
choices += sorted((config_dir / c).stem for c in config.in_dir(str(config_dir)))
choices += sorted((config_dir / c).stem for c in in_dir(str(config_dir)))

return sorted(str(c) for c in choices if str(c).startswith(incomplete))

Expand Down
3 changes: 1 addition & 2 deletions src/tmuxp/cli/ls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
import typing as t

from tmuxp.workspace.constants import VALID_WORKSPACE_DIR_FILE_EXTENSIONS

from .utils import get_workspace_dir
from tmuxp.workspace.finders import get_workspace_dir


def create_ls_subparser(
Expand Down
162 changes: 0 additions & 162 deletions src/tmuxp/cli/utils.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import logging
import os
import re
import typing as t

from colorama import Fore

from tmuxp.types import StrPath
from tmuxp.workspace.constants import VALID_WORKSPACE_DIR_FILE_EXTENSIONS

from .. import log

logger = logging.getLogger(__name__)
Expand All @@ -32,162 +26,6 @@ def tmuxp_echo(
print(message)


def get_workspace_dir() -> str:
"""
Return tmuxp configuration directory.
``TMUXP_CONFIGDIR`` environmental variable has precedence if set. We also
evaluate XDG default directory from XDG_CONFIG_HOME environmental variable
if set or its default. Then the old default ~/.tmuxp is returned for
compatibility.
Returns
-------
str :
absolute path to tmuxp config directory
"""

paths = []
if "TMUXP_CONFIGDIR" in os.environ:
paths.append(os.environ["TMUXP_CONFIGDIR"])
if "XDG_CONFIG_HOME" in os.environ:
paths.append(os.path.join(os.environ["XDG_CONFIG_HOME"], "tmuxp"))
else:
paths.append("~/.config/tmuxp/")
paths.append("~/.tmuxp")

for path in paths:
path = os.path.expanduser(path)
if os.path.isdir(path):
return path
# Return last path as default if none of the previous ones matched
return path


def find_workspace_file(
workspace_file: StrPath,
workspace_dir: t.Optional[StrPath] = None,
) -> str:
"""
Return the real config path or raise an exception.
If config is directory, scan for .tmuxp.{yaml,yml,json} in directory. If
one or more found, it will warn and pick the first.
If config is ".", "./" or None, it will scan current directory.
If config is has no path and only a filename, e.g. "myconfig.yaml" it will
search config dir.
If config has no path and only a name with no extension, e.g. "myconfig",
it will scan for file name with yaml, yml and json. If multiple exist, it
will warn and pick the first.
Parameters
----------
workspace_file : str
workspace file, valid examples:
- a file name, myconfig.yaml
- relative path, ../config.yaml or ../project
- a period, .
"""
if not workspace_dir:
workspace_dir = get_workspace_dir()
path = os.path
exists, join, isabs = path.exists, path.join, path.isabs
dirname, normpath, splitext = path.dirname, path.normpath, path.splitext
cwd = os.getcwd()
is_name = False
file_error = None

workspace_file = os.path.expanduser(workspace_file)
# if purename, resolve to confg dir
if is_pure_name(workspace_file):
is_name = True
elif (
not isabs(workspace_file)
or len(dirname(workspace_file)) > 1
or workspace_file == "."
or workspace_file == ""
or workspace_file == "./"
): # if relative, fill in full path
workspace_file = normpath(join(cwd, workspace_file))

# no extension, scan
if path.isdir(workspace_file) or not splitext(workspace_file)[1]:
if is_name:
candidates = [
x
for x in [
f"{join(workspace_dir, workspace_file)}{ext}"
for ext in VALID_WORKSPACE_DIR_FILE_EXTENSIONS
]
if exists(x)
]
if not len(candidates):
file_error = (
"workspace-file not found in workspace dir (yaml/yml/json) %s "
"for name" % (workspace_dir)
)
else:
candidates = [
x
for x in [
join(workspace_file, ext)
for ext in [".tmuxp.yaml", ".tmuxp.yml", ".tmuxp.json"]
]
if exists(x)
]

if len(candidates) > 1:
tmuxp_echo(
Fore.RED
+ "Multiple .tmuxp.{yml,yaml,json} workspace_files in %s"
% dirname(workspace_file)
+ Fore.RESET
)
tmuxp_echo(
"This is undefined behavior, use only one. "
"Use file names e.g. myproject.json, coolproject.yaml. "
"You can load them by filename."
)
elif not len(candidates):
file_error = "No tmuxp files found in directory"
if len(candidates):
workspace_file = candidates[0]
elif not exists(workspace_file):
file_error = "file not found"

if file_error:
raise FileNotFoundError(file_error, workspace_file)

return workspace_file


def is_pure_name(path: str) -> bool:
"""
Return True if path is a name and not a file path.
Parameters
----------
path : str
Path (can be absolute, relative, etc.)
Returns
-------
bool
True if path is a name of config in config dir, not file path.
"""
return (
not os.path.isabs(path)
and len(os.path.dirname(path)) == 0
and not os.path.splitext(path)[1]
and path != "."
and path != ""
)


def prompt(
name: str,
default: t.Any = None,
Expand Down
70 changes: 0 additions & 70 deletions src/tmuxp/workspace/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,76 +44,6 @@ def validate_schema(workspace_dict):
return True


def is_workspace_file(filename, extensions=[".yml", ".yaml", ".json"]):
"""
Return True if file has a valid workspace file type.
Parameters
----------
filename : str
filename to check (e.g. ``mysession.json``).
extensions : str or list
filetypes to check (e.g. ``['.yaml', '.json']``).
Returns
-------
bool
"""
extensions = [extensions] if isinstance(extensions, str) else extensions
return any(filename.endswith(e) for e in extensions)


def in_dir(
config_dir=os.path.expanduser("~/.tmuxp"), extensions=[".yml", ".yaml", ".json"]
):
"""
Return a list of configs in ``config_dir``.
Parameters
----------
config_dir : str
directory to search
extensions : list
filetypes to check (e.g. ``['.yaml', '.json']``).
Returns
-------
list
"""
configs = []

for filename in os.listdir(config_dir):
if is_workspace_file(filename, extensions) and not filename.startswith("."):
configs.append(filename)

return configs


def in_cwd():
"""
Return list of configs in current working directory.
If filename is ``.tmuxp.py``, ``.tmuxp.json``, ``.tmuxp.yaml``.
Returns
-------
list
configs in current working directory
Examples
--------
>>> sorted(in_cwd())
['.tmuxp.json', '.tmuxp.yaml']
"""
configs = []

for filename in os.listdir(os.getcwd()):
if filename.startswith(".tmuxp") and is_workspace_file(filename):
configs.append(filename)

return configs


def expandshell(_path):
"""
Return expanded path based on user's ``$HOME`` and ``env``.
Expand Down
Loading

0 comments on commit 8da490d

Please sign in to comment.