Source code for libdesktop.desktopfile

# coding: utf-8

# This file is part of libdesktop

# The MIT License (MIT)
#
# Copyright (c) 2016 Bharadwaj Raju
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

import os
import subprocess as sp
from libdesktop import system
import sys


[docs]def construct(name, exec_, terminal=False, additional_opts={}): '''Construct a .desktop file and return it as a string. Create a standards-compliant .desktop file, returning it as a string. Args: name (str) : The program's name. exec\_ (str) : The command. terminal (bool): Determine if program should be run in a terminal emulator or not. Defaults to ``False``. additional_opts (dict): Any additional fields. Returns: str: The constructed .desktop file. ''' desktop_file = '[Desktop Entry]\n' desktop_file_dict = { 'Name': name, 'Exec': exec_, 'Terminal': 'true' if terminal else 'false', 'Comment': additional_opts.get('Comment', name) } desktop_file = ('[Desktop Entry]\nName={name}\nExec={exec_}\n' 'Terminal={terminal}\nComment={comment}\n') desktop_file = desktop_file.format(name=desktop_file_dict['Name'], exec_=desktop_file_dict['Exec'], terminal=desktop_file_dict['Terminal'], comment=desktop_file_dict['Comment']) if additional_opts is None: additional_opts = {} for option in additional_opts: if not option in desktop_file_dict: desktop_file += '%s=%s\n' % (option, additional_opts[option]) return desktop_file
[docs]def execute(desktop_file, files=None, return_cmd=False, background=False): '''Execute a .desktop file. Executes a given .desktop file path properly. Args: desktop_file (str) : The path to the .desktop file. files (list): Any files to be launched by the .desktop. Defaults to empty list. return_cmd (bool): Return the command (as ``str``) instead of executing. Defaults to ``False``. background (bool): Run command in background. Defaults to ``False``. Returns: str: Only if ``return_cmd``. Returns command instead of running it. Else returns nothing. ''' # Attempt to manually parse and execute desktop_file_exec = parse(desktop_file)['Exec'] for i in desktop_file_exec.split(): if i.startswith('%'): desktop_file_exec = desktop_file_exec.replace(i, '') desktop_file_exec = desktop_file_exec.replace(r'%F', '') desktop_file_exec = desktop_file_exec.replace(r'%f', '') if files: for i in files: desktop_file_exec += ' ' + i if parse(desktop_file)['Terminal']: # Use eval and __import__ to bypass a circular dependency desktop_file_exec = eval( ('__import__("libdesktop").applications.terminal(exec_="%s",' ' keep_open_after_cmd_exec=True, return_cmd=True)') % desktop_file_exec) if return_cmd: return desktop_file_exec desktop_file_proc = sp.Popen([desktop_file_exec], shell=True) if not background: desktop_file_proc.wait()
[docs]def locate(desktop_filename_or_name): '''Locate a .desktop from the standard locations. Find the path to the .desktop file of a given .desktop filename or application name. Standard locations: - ``~/.local/share/applications/`` - ``/usr/share/applications`` Args: desktop_filename_or_name (str): Either the filename of a .desktop file or the name of an application. Returns: list: A list of all matching .desktop files found. ''' paths = [ os.path.expanduser('~/.local/share/applications'), '/usr/share/applications'] result = [] for path in paths: for file in os.listdir(path): if desktop_filename_or_name in file.split( '.') or desktop_filename_or_name == file: # Example: org.gnome.gedit result.append(os.path.join(path, file)) else: file_parsed = parse(os.path.join(path, file)) try: if desktop_filename_or_name.lower() == file_parsed[ 'Name'].lower(): result.append(file) elif desktop_filename_or_name.lower() == file_parsed[ 'Exec'].split(' ')[0]: result.append(file) except KeyError: pass for res in result: if not res.endswith('.desktop'): result.remove(res) if not result and not result.endswith('.desktop'): result.extend(locate(desktop_filename_or_name + '.desktop')) return result
[docs]def parse(desktop_file_or_string): '''Parse a .desktop file. Parse a .desktop file or a string with its contents into an easy-to-use dict, with standard values present even if not defined in file. Args: desktop_file_or_string (str): Either the path to a .desktop file or a string with a .desktop file as its contents. Returns: dict: A dictionary of the parsed file.''' if os.path.isfile(desktop_file_or_string): with open(desktop_file_or_string) as f: desktop_file = f.read() else: desktop_file = desktop_file_or_string result = {} for line in desktop_file.split('\n'): if '=' in line: result[line.split('=')[0]] = line.split('=')[1] for key, value in result.items(): if value == 'false': result[key] = False elif value == 'true': result[key] = True if not 'Terminal' in result: result['Terminal'] = False if not 'Hidden' in result: result['Hidden'] = False return result