Coverage for src/types/paths.py: 100.00%
61 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-10-18 15:02 +0000
« prev ^ index » next coverage.py v7.15.4, created at 2026-10-18 15:02 +0000
1#!/usr/bin/env python3
3# Standard libraries
4from glob import glob
5from os.path import expanduser
6from pathlib import Path, PurePosixPath
7from typing import List
9# Components
10from ..system.platform import Platform
11from .environment import Environment
13# Paths class
14class Paths:
16 # Basename
17 @staticmethod
18 def basename(data: str) -> str:
20 # POSIX path
21 path: PurePosixPath = PurePosixPath(data)
23 # Result
24 return str(path.name)
26 # Expand
27 @staticmethod
28 def expand(
29 path: str,
30 env: bool = True,
31 home: bool = True,
32 ) -> str:
34 # Expand environment
35 if env:
36 path = Environment.expand(path)
38 # Expand home
39 if home:
40 path = expanduser(path)
42 # Result
43 return path
45 # Get
46 @staticmethod
47 def get(data: Path | PurePosixPath | str) -> str:
49 # POSIX path
50 path: PurePosixPath = PurePosixPath(data)
52 # Result
53 return str(path)
55 # Home
56 @staticmethod
57 def home(user: str) -> str:
59 # Expand home
60 path: str = expanduser(f'~{user}')
61 if path[0:1] != '~':
62 return path
64 # Default root
65 if user == 'root': # pragma: no cover
66 return '/root'
68 # Default user
69 return f'/home/{user}'
71 # Resolve
72 @staticmethod
73 def resolve(data: Path | str) -> str:
75 # Resolve path
76 path: str = str(Path(data).resolve())
78 # Result
79 return path
81 # Translate
82 @staticmethod
83 def translate(data: str) -> str:
85 # Double backslash translation
86 if data[0:1] == '\\': # pragma: no cover
87 data = f'/{data[1:]}'
89 # Double slash translation
90 if data[0:2] == '//': # pragma: no cover
91 data = data[1:]
93 # Result
94 return data
96 # Wildcard
97 @staticmethod
98 def wildcard(
99 path: str,
100 strict: bool = False,
101 ) -> List[Path]:
103 # Variables
104 paths: List[Path] = []
105 variants: List[str] = []
107 # Apply strict wildcards
108 if strict:
109 path = path.replace('**', '*/**')
111 # Generate wildcard variants
112 def wildcard_variants(path: str) -> List[str]:
113 variants: List[str] = [path]
114 if path.startswith('*'): # pragma: no cover
115 variants += ['.' + path]
116 index = path.find(Platform.PATH_SEPARATOR + '*')
117 while index != -1:
118 variants_new = []
119 for variant in variants:
120 new_variant = variant[:index + 1] + '.' + variant[index + 1:]
121 variants_new.append(new_variant)
122 for variant_new in variants_new:
123 if variant_new not in variants:
124 variants += [variant_new]
125 index = variants[0].find(Platform.PATH_SEPARATOR + '*', index + 1)
126 return variants
128 # Evaluate wildcard variants
129 variants = wildcard_variants(path)
131 # Evaluate wildcards
132 for variant in variants:
133 for item in [Path(item) for item in glob(
134 variant,
135 recursive=True,
136 )]:
137 paths += [Path(item)]
139 # Fallback to input
140 if not paths:
141 paths += [Path(path)]
143 # Result
144 return paths