]> kaliko git repositories - mpd-sima.git/blob - sima/utils/utils.py
Catches SIGHUP/SIGUSR1 to trigger conf reload
[mpd-sima.git] / sima / utils / utils.py
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (c) 2010, 2011, 2013 Jack Kaliko <kaliko@azylum.org>
4 #
5 #  This file is part of sima
6 #
7 #  sima is free software: you can redistribute it and/or modify
8 #  it under the terms of the GNU General Public License as published by
9 #  the Free Software Foundation, either version 3 of the License, or
10 #  (at your option) any later version.
11 #
12 #  sima is distributed in the hope that it will be useful,
13 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #  GNU General Public License for more details.
16 #
17 #  You should have received a copy of the GNU General Public License
18 #  along with sima.  If not, see <http://www.gnu.org/licenses/>.
19 #
20 #
21 """generic tools and utilitaries for sima
22 """
23
24 import traceback
25 import sys
26
27 from argparse import ArgumentError, Action
28 from os import environ, access, getcwd, W_OK, R_OK
29 from os.path import dirname, isabs, join, normpath, exists, isdir, isfile
30
31 def get_mpd_environ():
32     """
33     Retrieve MPD env. var.
34     """
35     passwd = host = None
36     mpd_host_env = environ.get('MPD_HOST')
37     if mpd_host_env:
38         # If password is set:
39         # mpd_host_env = ['pass', 'host'] because MPD_HOST=pass@host
40         mpd_host_env = mpd_host_env.split('@')
41         mpd_host_env.reverse()
42         host = mpd_host_env[0]
43         if len(mpd_host_env) > 1 and mpd_host_env[1]:
44             passwd = mpd_host_env[1]
45     return (host, environ.get('MPD_PORT', None), passwd)
46
47 def normalize_path(path):
48     """Get absolute path
49     """
50     if not isabs(path):
51         return normpath(join(getcwd(), path))
52     return path
53
54 def exception_log():
55     """Log unknown exceptions"""
56     import logging
57     log = logging.getLogger('sima')
58     log.error('Unhandled Exception!!!')
59     log.error(''.join(traceback.format_exc()))
60     log.info('Please report the previous message'
61              ' along with some log entries right before the crash.')
62     log.info('thanks for your help :)')
63     log.info('Quiting now!')
64     sys.exit(1)
65
66 class SigHup(Exception):
67     pass
68
69 # ArgParse Callbacks
70 class Obsolete(Action):
71     # pylint: disable=R0903
72     """Deal with obsolete arguments
73     """
74     def __call__(self, parser, namespace, values, option_string=None):
75         raise ArgumentError(self, 'obsolete argument')
76
77 class FileAction(Action):
78     """Generic class to inherit from for ArgParse action on file/dir
79     """
80     # pylint: disable=R0903
81     def __call__(self, parser, namespace, values, option_string=None):
82         self._file = normalize_path(values)
83         self._dir = dirname(self._file)
84         self.parser = parser
85         self.checks()
86         setattr(namespace, self.dest, self._file)
87
88     def checks(self):
89         """control method
90         """
91         pass
92
93 class Wfile(FileAction):
94     # pylint: disable=R0903
95     """Is file writable
96     """
97     def checks(self):
98         if not exists(self._dir):
99             #raise ArgumentError(self, '"{0}" does not exist'.format(self._dir))
100             self.parser.error('file does not exist: {0}'.format(self._dir))
101         if not exists(self._file):
102             # Is parent directory writable then
103             if not access(self._dir, W_OK):
104                 self.parser.error('no write access to "{0}"'.format(self._dir))
105         else:
106             if not access(self._file, W_OK):
107                 self.parser.error('no write access to "{0}"'.format(self._file))
108
109 class Rfile(FileAction):
110     # pylint: disable=R0903
111     """Is file readable
112     """
113     def checks(self):
114         if not exists(self._file):
115             self.parser.error('file does not exist: {0}'.format(self._file))
116         if not isfile(self._file):
117             self.parser.error('not a file: {0}'.format(self._file))
118         if not access(self._file, R_OK):
119             self.parser.error('no read access to "{0}"'.format(self._file))
120
121 class Wdir(FileAction):
122     # pylint: disable=R0903
123     """Is directory writable
124     """
125     def checks(self):
126         if not exists(self._file):
127             self.parser.error('directory does not exist: {0}'.format(self._file))
128         if not isdir(self._file):
129             self.parser.error('not a directory: {0}'.format(self._file))
130         if not access(self._file, W_OK):
131             self.parser.error('no write access to "{0}"'.format(self._file))
132
133
134 # VIM MODLINE
135 # vim: ai ts=4 sw=4 sts=4 expandtab