Skip to content

Commit 373334d

Browse files
mhalanorussozfelixfontein
authored
Add xdg_mime module (#10007)
* Add version of xdg_mime module * Fix xdg_mime_get since the command is different * Add query parameter * Fix order of parameters * Add myself to BOTMETA * Add unit tests * Fix the way we deal when there is no handler set * Improve documentation * Remove unused import * Fix documentation * Strip xdg-mime from version string * Fix information about version * Add error message sample * Add test to invalid handler * Add support to multiple mime-types * Change the output parameter from handlers to handler * Change tests related to multiple mime-type support * Small fixes * Stop using constant to enable changed state * Add before_handlers and after_handlers * Change tests to use before and after structures * Add a stronger message about using a non-installed handler * Manage some edge cases * Change error message to match the new value * Add some fixes * Change some tests * Update plugins/modules/xdg_mime.py Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Remove a blank line * Remove single quote * Add xdg-mime to the version in the mocks * Remove after_handlers and make code simpler * Update tests to work without after_handlers * Remove diff_params and clean output_params * Make mime_type plural since it supports multiple items * Move the handler check to module init * Use anchors in the test to make yaml simpler * Update plugins/modules/xdg_mime.py Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Update plugins/modules/xdg_mime.py Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Update plugins/modules/xdg_mime.py Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Update plugins/modules/xdg_mime.py Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Update plugins/modules/xdg_mime.py Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Update plugins/modules/xdg_mime.py Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Update plugins/modules/xdg_mime.py Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Update plugins/modules/xdg_mime.py Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Update plugins/modules/xdg_mime.py Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Update plugins/modules/xdg_mime.py Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Add blank line to separe examples * Update plugins/modules/xdg_mime.py Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * Add a small homage to my late grandma * Update plugins/modules/xdg_mime.py Co-authored-by: Felix Fontein <felix@fontein.de> * Fix pep8 problem with the homage * Remove trailing whitespace * Update plugins/modules/xdg_mime.py Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> --------- Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> Co-authored-by: Felix Fontein <felix@fontein.de>
1 parent 8fa357e commit 373334d

File tree

5 files changed

+288
-0
lines changed

5 files changed

+288
-0
lines changed

.github/BOTMETA.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,8 @@ files:
419419
$module_utils/wdc_redfish_utils.py:
420420
labels: wdc_redfish_utils
421421
maintainers: $team_wdc
422+
$module_utils/xdg_mime.py:
423+
maintainers: mhalano
422424
$module_utils/xenserver.py:
423425
labels: xenserver
424426
maintainers: bvitnik
@@ -1447,6 +1449,8 @@ files:
14471449
maintainers: dinoocch the-maldridge
14481450
$modules/xcc_:
14491451
maintainers: panyy3 renxulei
1452+
$modules/xdg_mime.py:
1453+
maintainers: mhalano
14501454
$modules/xenserver_:
14511455
maintainers: bvitnik
14521456
$modules/xenserver_facts.py:

plugins/module_utils/xdg_mime.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# -*- coding: utf-8 -*-
2+
# Copyright (c) 2025, Marcos Alano <marcoshalano@gmail.com>
3+
# Based on gio_mime module. Copyright (c) 2022, Alexei Znamensky <russoz@gmail.com>
4+
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
5+
# SPDX-License-Identifier: GPL-3.0-or-later
6+
7+
from __future__ import absolute_import, division, print_function
8+
__metaclass__ = type
9+
10+
from ansible_collections.community.general.plugins.module_utils.cmd_runner import CmdRunner, cmd_runner_fmt
11+
12+
13+
def xdg_mime_runner(module, **kwargs):
14+
return CmdRunner(
15+
module,
16+
command=['xdg-mime'],
17+
arg_formats=dict(
18+
default=cmd_runner_fmt.as_fixed('default'),
19+
query=cmd_runner_fmt.as_fixed('query'),
20+
mime_types=cmd_runner_fmt.as_list(),
21+
handler=cmd_runner_fmt.as_list(),
22+
version=cmd_runner_fmt.as_fixed('--version'),
23+
),
24+
**kwargs
25+
)
26+
27+
28+
def xdg_mime_get(runner, mime_type):
29+
def process(rc, out, err):
30+
if not out.strip():
31+
return None
32+
out = out.splitlines()[0]
33+
return out.split()[-1]
34+
35+
with runner("query default mime_types", output_process=process) as ctx:
36+
return ctx.run(mime_types=mime_type)

plugins/modules/xdg_mime.py

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
#!/usr/bin/python
2+
# -*- coding: utf-8 -*-
3+
# Copyright (c) 2025, Marcos Alano <marcoshalano@gmail.com>
4+
# Based on gio_mime module. Copyright (c) 2022, Alexei Znamensky <russoz@gmail.com>
5+
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
6+
# SPDX-License-Identifier: GPL-3.0-or-later
7+
8+
# In memory: This code is dedicated to my late grandmother, Maria Marlene. 1936-2025. Rest in peace, grandma.
9+
# -Marcos Alano-
10+
11+
# TODO: Add support for diff mode
12+
13+
from __future__ import absolute_import, division, print_function
14+
__metaclass__ = type
15+
16+
DOCUMENTATION = r"""
17+
module: xdg_mime
18+
author:
19+
- "Marcos Alano (@mhalano)"
20+
short_description: Set default handler for MIME types, for applications using XDG tools
21+
version_added: 10.7.0
22+
description:
23+
- This module allows configuring the default handler for specific MIME types when you use applications that rely on XDG.
24+
extends_documentation_fragment:
25+
- community.general.attributes
26+
attributes:
27+
check_mode:
28+
support: full
29+
diff_mode:
30+
support: none
31+
options:
32+
mime_types:
33+
description:
34+
- One or more MIME types for which a default handler will be set.
35+
type: list
36+
elements: str
37+
required: true
38+
handler:
39+
description:
40+
- Sets the default handler for the specified MIME types.
41+
- The desktop file must be installed in the system.
42+
If the desktop file is not installed, the module
43+
does not fail, but the handler is not set either.
44+
- You must pass a handler in the form V(*.desktop), otherwise the module fails.
45+
type: str
46+
required: true
47+
notes:
48+
- This module is a thin wrapper around C(xdg-mime) tool.
49+
- See man xdg-mime(1) for more details.
50+
seealso:
51+
- name: C(xdg-mime) command manual page
52+
description: Manual page for the command.
53+
link: https://portland.freedesktop.org/doc/xdg-mime.html
54+
- name: xdg-utils Documentation
55+
description: Reference documentation for xdg-utils.
56+
link: https://www.freedesktop.org/wiki/Software/xdg-utils/
57+
"""
58+
59+
EXAMPLES = r"""
60+
- name: Set Chrome as the default handler for HTTPS
61+
community.general.xdg_mime:
62+
mime_types: x-scheme-handler/https
63+
handler: google-chrome.desktop
64+
register: result
65+
66+
- name: Set Chrome as the default handler for both HTTP and HTTPS
67+
community.general.xdg_mime:
68+
mime_types:
69+
- x-scheme-handler/http
70+
- x-scheme-handler/https
71+
handler: google-chrome.desktop
72+
register: result
73+
"""
74+
75+
RETURN = r"""
76+
current_handlers:
77+
description:
78+
- Currently set handlers for the passed MIME types.
79+
returned: success
80+
type: list
81+
elements: str
82+
sample:
83+
- google-chrome.desktop
84+
- firefox.desktop
85+
version:
86+
description: Version of the C(xdg-mime) tool.
87+
type: str
88+
returned: always
89+
sample: "1.2.1"
90+
"""
91+
92+
from ansible_collections.community.general.plugins.module_utils.module_helper import ModuleHelper
93+
from ansible_collections.community.general.plugins.module_utils.xdg_mime import xdg_mime_runner, xdg_mime_get
94+
95+
96+
class XdgMime(ModuleHelper):
97+
output_params = ['handler']
98+
99+
module = dict(
100+
argument_spec=dict(
101+
mime_types=dict(type='list', elements='str', required=True),
102+
handler=dict(type='str', required=True),
103+
),
104+
supports_check_mode=True,
105+
)
106+
use_old_vardict = False
107+
108+
def __init_module__(self):
109+
self.runner = xdg_mime_runner(self.module, check_rc=True)
110+
111+
with self.runner("version") as ctx:
112+
rc, out, err = ctx.run()
113+
self.vars.version = out.replace("xdg-mime ", "").strip()
114+
115+
if not self.vars.handler.endswith(".desktop"):
116+
self.do_raise(msg="Handler must be a .desktop file")
117+
118+
self.vars.current_handlers = []
119+
for mime in self.vars.mime_types:
120+
handler_value = xdg_mime_get(self.runner, mime)
121+
if not handler_value:
122+
handler_value = ''
123+
self.vars.current_handlers.append(handler_value)
124+
125+
def __run__(self):
126+
check_mode_return = (0, 'Module executed in check mode', '')
127+
128+
if any(h != self.vars.handler for h in self.vars.current_handlers):
129+
self.changed = True
130+
131+
if self.has_changed():
132+
with self.runner.context(args_order="default handler mime_types", check_mode_skip=True, check_mode_return=check_mode_return) as ctx:
133+
rc, out, err = ctx.run()
134+
self.vars.stdout = out
135+
self.vars.stderr = err
136+
self.vars.set("run_info", ctx.run_info, verbosity=1)
137+
138+
139+
def main():
140+
XdgMime.execute()
141+
142+
143+
if __name__ == '__main__':
144+
main()
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# -*- coding: utf-8 -*-
2+
# Copyright (c) 2025, Marcos Alano <marcoshalano@gmail.com>
3+
# Based on gio_mime module. Copyright (c) 2022, Alexei Znamensky <russoz@gmail.com>
4+
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
5+
# SPDX-License-Identifier: GPL-3.0-or-later
6+
7+
from __future__ import (absolute_import, division, print_function)
8+
__metaclass__ = type
9+
10+
11+
from ansible_collections.community.general.plugins.modules import xdg_mime
12+
from .uthelper import UTHelper, RunCommandMock
13+
14+
15+
UTHelper.from_module(xdg_mime, __name__, mocks=[RunCommandMock])
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# -*- coding: utf-8 -*-
2+
# Copyright (c) 2025, Marcos Alano <marcoshalano@gmail.com>
3+
# Based on gio_mime module. Copyright (c) 2022, Alexei Znamensky <russoz@gmail.com>
4+
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
5+
# SPDX-License-Identifier: GPL-3.0-or-later
6+
7+
# TODO: add tests for setting multiple mime types at once
8+
---
9+
anchors:
10+
environ: &env-def {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: true}
11+
input: &input
12+
mime_types: x-scheme-handler/http
13+
handler: google-chrome.desktop
14+
get_version: &get_version
15+
command: [/testbin/xdg-mime, --version]
16+
environ: *env-def
17+
rc: 0
18+
out: "xdg-mime 1.2.1\n"
19+
err: ''
20+
query_mime_type: &query_mime_type
21+
command: [/testbin/xdg-mime, query, default, x-scheme-handler/http]
22+
environ: *env-def
23+
rc: 0
24+
out: ''
25+
err: ''
26+
set_handler: &set_handler
27+
command: [/testbin/xdg-mime, default, google-chrome.desktop, x-scheme-handler/http]
28+
environ: *env-def
29+
rc: 0
30+
out: ''
31+
err: ''
32+
test_cases:
33+
- id: test_set_handler
34+
input: *input
35+
output:
36+
current_handlers: ['']
37+
changed: true
38+
mocks:
39+
run_command:
40+
- *get_version
41+
- *query_mime_type
42+
- *set_handler
43+
- id: test_set_handler_check
44+
input: *input
45+
output:
46+
current_handlers: ['google-chrome.desktop']
47+
changed: false
48+
flags:
49+
check: true
50+
mocks:
51+
run_command:
52+
- *get_version
53+
- <<: *query_mime_type
54+
out: |
55+
google-chrome.desktop
56+
- id: test_set_handler_idempot
57+
input: *input
58+
output:
59+
current_handlers: ['google-chrome.desktop']
60+
changed: false
61+
mocks:
62+
run_command:
63+
- *get_version
64+
- <<: *query_mime_type
65+
out: |
66+
google-chrome.desktop
67+
- id: test_set_handler_idempot_check
68+
input: *input
69+
output:
70+
current_handlers: ['google-chrome.desktop']
71+
changed: false
72+
flags:
73+
check: true
74+
mocks:
75+
run_command:
76+
- *get_version
77+
- <<: *query_mime_type
78+
out: |
79+
google-chrome.desktop
80+
- id: test_set_invalid_handler
81+
input:
82+
<<: *input
83+
handler: google-chrome.desktopX
84+
output:
85+
failed: true
86+
msg: Handler must be a .desktop file
87+
mocks:
88+
run_command:
89+
- *get_version

0 commit comments

Comments
 (0)