Skip to content

Commit 1ae70be

Browse files
authored
Merge pull request #15 from manala/path/path-parse-components
[Path] Add a "parse" filter to get path components
2 parents 96fd037 + 7780fb1 commit 1ae70be

4 files changed

Lines changed: 144 additions & 0 deletions

File tree

path/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Add a "parse" filter to get path components
13+
1014
## [2.2.0] - 2026-01-02
1115

1216
### Added

path/plugins/filter/parse.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
from __future__ import annotations
2+
3+
from ansible.errors import AnsibleTemplateError
4+
from pathlib import Path
5+
6+
7+
def _parse(path):
8+
if not isinstance(path, dict):
9+
raise AnsibleTemplateError(f'parse input expects a dict but was given a {type(path).__name__}')
10+
11+
p = Path(path['path'])
12+
13+
# Parent
14+
parent = str(p.parent)
15+
if parent in ['.', '/']:
16+
parent = ''
17+
18+
# Extension
19+
extension = p.suffix.lstrip('.')
20+
21+
return {
22+
'parent': parent,
23+
'name': p.name,
24+
'stem': p.stem,
25+
'extension': extension,
26+
}
27+
28+
29+
class FilterModule(object):
30+
""" Manala path parse jinja2 filters """
31+
32+
def filters(self):
33+
return {
34+
'parse': _parse,
35+
}

path/plugins/filter/parse.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
3+
DOCUMENTATION:
4+
name: parse
5+
author:
6+
- Manala (@manala)
7+
short_description: Get the components of a path dict
8+
description:
9+
- Returns the components of a path dict.
10+
positional: _input
11+
options:
12+
_input:
13+
description: A path dict.
14+
type: dict
15+
required: true
16+
17+
RETURN:
18+
_value:
19+
description: Components.
20+
type: dict
21+
22+
EXAMPLES: |
23+
- ansible.builtin.debug:
24+
msg:
25+
- >
26+
{'path': 'foo'} | manala.path.parse
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
from __future__ import annotations
2+
3+
import unittest
4+
from plugins.filter.parse import _parse as _filter_parse
5+
6+
from ansible.errors import AnsibleTemplateError
7+
8+
9+
class TestParse(unittest.TestCase):
10+
11+
def test_invalid_inputs(self):
12+
path = NotImplemented
13+
14+
with self.assertRaisesRegex(AnsibleTemplateError, f'parse input expects a dict but was given a {type(path).__name__}'):
15+
_filter_parse(path)
16+
17+
def test(self):
18+
self.assertEqual({
19+
'parent': '',
20+
'name': '',
21+
'stem': '',
22+
'extension': '',
23+
} , _filter_parse(
24+
{'path': ''}
25+
))
26+
27+
self.assertEqual({
28+
'parent': '',
29+
'name': 'foo',
30+
'stem': 'foo',
31+
'extension': '',
32+
} , _filter_parse(
33+
{'path': 'foo'}
34+
))
35+
36+
self.assertEqual({
37+
'parent': '',
38+
'name': 'foo.bar',
39+
'stem': 'foo',
40+
'extension': 'bar',
41+
} , _filter_parse(
42+
{'path': 'foo.bar'}
43+
))
44+
45+
self.assertEqual({
46+
'parent': '',
47+
'name': 'foo',
48+
'stem': 'foo',
49+
'extension': '',
50+
} , _filter_parse(
51+
{'path': '/foo'}
52+
))
53+
54+
self.assertEqual({
55+
'parent': '',
56+
'name': 'foo.bar',
57+
'stem': 'foo',
58+
'extension': 'bar',
59+
} , _filter_parse(
60+
{'path': '/foo.bar'}
61+
))
62+
63+
self.assertEqual({
64+
'parent': '/foo/bar',
65+
'name': 'baz',
66+
'stem': 'baz',
67+
'extension': '',
68+
} , _filter_parse(
69+
{'path': '/foo/bar/baz'}
70+
))
71+
72+
self.assertEqual({
73+
'parent': '/foo/bar',
74+
'name': 'baz.qux',
75+
'stem': 'baz',
76+
'extension': 'qux',
77+
} , _filter_parse(
78+
{'path': '/foo/bar/baz.qux'}
79+
))

0 commit comments

Comments
 (0)