Move generic formatter specification to misc module
[wifi-radar.git] / wifiradar / misc.py
blob6c8a7dbdafbaca0a1ad164ff5c046e23a41a0745
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
4 # misc.py - collection of miscellaneous functions and classes
6 # Part of WiFi Radar: A utility for managing WiFi profiles on GNU/Linux.
8 # Copyright (C) 2004-2005 Ahmad Baitalmal <ahmad@baitalmal.com>
9 # Copyright (C) 2005 Nicolas Brouard <nicolas.brouard@mandrake.org>
10 # Copyright (C) 2005-2009 Brian Elliott Finley <brian@thefinleys.com>
11 # Copyright (C) 2006 David Decotigny <com.d2@free.fr>
12 # Copyright (C) 2006 Simon Gerber <gesimu@gmail.com>
13 # Copyright (C) 2006-2007 Joey Hurst <jhurst@lucubrate.org>
14 # Copyright (C) 2006, 2009 Ante Karamatic <ivoks@ubuntu.com>
15 # Copyright (C) 2009-2010,2014 Sean Robinson <robinson@tuxfamily.org>
16 # Copyright (C) 2010 Prokhor Shuchalov <p@shuchalov.ru>
18 # This program is free software; you can redistribute it and/or modify
19 # it under the terms of the GNU General Public License as published by
20 # the Free Software Foundation; version 2 of the License.
22 # This program is distributed in the hope that it will be useful,
23 # but WITHOUT ANY WARRANTY; without even the implied warranty of
24 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 # GNU General Public License in LICENSE.GPL for more details.
27 # You should have received a copy of the GNU General Public License
28 # along with this program; if not, write to:
29 # Free Software Foundation, Inc.
30 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
34 from __future__ import unicode_literals
36 import collections
37 import errno
38 import gettext
39 import logging
40 import os
41 import sys
43 from subprocess import check_call, Popen, PIPE, STDOUT
45 WIFI_RADAR_VERSION = '0.0.0'
47 # create a logger
48 logger = logging.getLogger(__name__)
50 __all__ = ['_', 'PYVERSION', 'WIFI_RADAR_VERSION', 'DeviceError',
51 'NoDeviceError', 'PipeError', 'KeySortedDict',
52 'get_new_profile', 'shellcmd']
54 PYVERSION = sys.version_info[0]
56 # Look for string translations in the default location, then in the po
57 # directory under the current directory. This second location is useful
58 # during development.
59 for locale_dir in [gettext.bindtextdomain(None), os.path.realpath('./po/')]:
60 try:
61 trans = gettext.translation('wifi-radar', locale_dir)
62 except IOError as e:
63 logger.warning("{EXC} in '{DIR}'".format(EXC=e, DIR=locale_dir))
64 else:
65 logger.info("Translation file found in '{DIR}'".format(DIR=locale_dir))
66 break
67 else:
68 logger.warning('Translation disabled. Please report this '
69 'at http://wifi-radar.tuxfamily.org/')
70 trans = gettext.NullTranslations()
71 # Return a reference to the unicode version of gettext, no matter
72 # the Python version.
73 if PYVERSION < 3:
74 _ = trans.ugettext
75 else:
76 _ = trans.gettext
78 class DeviceError(EnvironmentError):
79 """ DeviceError will be raised when a problem is found while changing
80 a wireless device's configuration (e.g. when 'ifconfig wlan0 up'
81 fails).
82 """
83 pass
86 class NoDeviceError(EnvironmentError):
87 """ NoDeviceError will be raised when a wireless device cannot be
88 found.
89 """
90 pass
93 class PipeError(IOError):
94 """ PipeError is raised when a communication Pipe closes unexpectedly.
95 """
96 pass
99 generic_formatter = logging.Formatter(
100 fmt='%(asctime)s.%(msecs)d %(levelname)s %(name)s: %(message)s',
101 datefmt='%Y-%m-%d %H:%M:%S')
104 class KeySortedDict(collections.MutableMapping):
105 """ :class:`KeySortedDict` provides a dictionary whose keys are always
106 returned in sorted order. Internal storage is not affected by the
107 sorting.
109 def __init__(self, *args, **kwargs):
110 self._key_list = list()
111 self._backing_dict = dict()
112 self.update(*args, **kwargs)
114 def __setitem__(self, key, value):
115 """ ksd.__setitem__(k, v) <==> ksd[k] = v """
116 if key in self:
117 # Update in place.
118 self._backing_dict[key] = value
119 else:
120 self._key_list.append(key)
121 self._backing_dict[key] = value
123 def __getitem__(self, key):
124 """ ksd.__getitem__(k) <==> ksd[k] """
125 return self._backing_dict[key]
127 def __delitem__(self, key):
128 """ ksd.__delitem__(k) <==> del ksd[k] """
129 del self._backing_dict[key]
130 self._key_list.remove(key)
132 def __iter__(self):
133 """ ksd.__iter__() <==> iter(ksd) """
134 self._key_list.sort()
135 for key in self._key_list:
136 yield key
138 def __len__(self):
139 """ ksd.__len__ <==> len(ksd) """
140 return len(self._key_list)
142 def __repr__(self):
143 return '{}({})'.format(self.__class__.__name__, self.items())
145 def copy(self):
146 return self._backing_dict.copy()
149 def get_new_profile():
150 """ Return a blank profile.
152 Parameters:
154 none
156 Returns:
158 dictionary -- An AP profile with defaults set.
160 return { 'known': False,
161 'available': False,
162 'encrypted': False,
163 'essid': '',
164 'bssid': '',
165 'roaming': False,
166 'protocol': 'g',
167 'signal': -193,
168 'channel': 'auto',
169 'con_prescript': '',
170 'con_postscript': '',
171 'dis_prescript': '',
172 'dis_postscript': '',
173 'key': '',
174 'mode': 'auto',
175 'security': 'none',
176 'wep_mode': '',
177 'wpa_psk': '',
178 'use_dhcp': True,
179 'ip': '',
180 'netmask': '',
181 'gateway': '',
182 'domain': '',
183 'dns1': '',
184 'dns2': ''
187 def shellcmd(command, environment=None):
188 """ Run 'command' through the shell, where 'command' is a tuple of
189 the program to execute and its arguments. 'environment' is a
190 dictionary of shell environment variables (as keys) and their
191 values. Returns 0 on success, otherwise, it raises
192 CalledProcessError.
194 env_tmp = os.environ
195 env_tmp.update(environment)
196 return check_call(command, shell=True, env=env_tmp)
199 # Make so we can be imported
200 if __name__ == '__main__':
201 pass