Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added support for --profile

This enables multiple "profiles" in a single config file, e.g.
[default]
engine = "GwClickatell"
... clickatel parameters ...

[mm]
engine = "GwMessageMedia"
... messagemedia parameters ...
  • Loading branch information...
commit 7c3ddf3fe8ff4d419e8ab07a9fffb5af4543702e 1 parent beddf2e
@mludvig authored
Showing with 65 additions and 20 deletions.
  1. +30 −16 Sms/Config.py
  2. +26 −0 Sms/Exceptions.py
  3. +9 −4 sms-cli
View
46 Sms/Config.py
@@ -6,6 +6,8 @@
from logging import debug, info, warning, error
import re
+from Exceptions import *
+
class Config(object):
_instance = None
_parsed_files = []
@@ -20,15 +22,18 @@ class Config(object):
## sms_url_pattern = "https://api.clickatell.com/http/sendmsg?api_id=APIID&user=USERNAME&password=PASSWORD&to=%(recipient)s&text=%(message)s"
## replace APIID, USERNAME and PASSWORD with the values of your Clickatell account
+ profile = "default"
verbosity = logging.INFO
## Creating a singleton
- def __new__(self, configfile = None):
+ def __new__(self, configfile = None, profile = None):
if self._instance is None:
self._instance = object.__new__(self)
return self._instance
- def __init__(self, configfile = None):
+ def __init__(self, configfile = None, profile = None):
+ if profile:
+ self.profile = profile
if configfile:
self.read_config_file(configfile)
@@ -48,13 +53,13 @@ def option_list(self):
return retval
def read_config_file(self, configfile):
- cp = ConfigParser(configfile)
+ cp = ConfigParser(configfile, self.profile)
for option in self.option_list():
self.update_option(option, cp.get(option))
self._parsed_files.append(configfile)
def dump_config(self, stream):
- ConfigDumper(stream).dump("default", self)
+ ConfigDumper(stream).dump(self.profile, self)
def update_option(self, option, value):
if value is None:
@@ -83,31 +88,38 @@ def update_option(self, option, value):
setattr(Config, option, value)
class ConfigParser(object):
- def __init__(self, file, sections = []):
+ def __init__(self, cfgfile, section):
self.cfg = {}
- self.parse_file(file, sections)
+ self.parse_file(cfgfile, section)
- def parse_file(self, file, sections = []):
- debug("ConfigParser: Reading file '%s'" % file)
- if type(sections) != type([]):
- sections = [sections]
- in_our_section = True
- f = open(file, "r")
+ def parse_file(self, cfgfile, section):
+ debug("ConfigParser: Reading file '%s' [section: %s]" % (cfgfile, section))
+ in_our_section = False
+ our_section_found = False
+ try:
+ f = open(cfgfile, "r")
+ except Exception, e:
+ error(str(e))
+ raise
r_comment = re.compile("^\s*#.*")
r_empty = re.compile("^\s*$")
r_section = re.compile("^\[([^\]]+)\]")
r_data = re.compile("^\s*(?P<key>\w+)\s*=\s*(?P<value>.*)")
r_quotes = re.compile("^\"(.*)\"\s*$")
for line in f:
+ line = line.strip()
if r_comment.match(line) or r_empty.match(line):
continue
is_section = r_section.match(line)
if is_section:
- section = is_section.groups()[0]
- in_our_section = (section in sections) or (len(sections) == 0)
+ this_section = is_section.groups()[0]
+ in_our_section = (this_section == section)
+ continue
+ if not in_our_section:
continue
+ our_section_found = True
is_data = r_data.match(line)
- if is_data and in_our_section:
+ if is_data:
data = is_data.groupdict()
if r_quotes.match(data["value"]):
data["value"] = data["value"][1:-1]
@@ -118,7 +130,9 @@ def parse_file(self, file, sections = []):
print_value = data["value"]
debug("ConfigParser: %s->%s" % (data["key"], print_value))
continue
- warning("Ignoring invalid line in '%s': %s" % (file, line))
+ raise SmsConfigError("%s: invalid line: %s" % (cfgfile, line))
+ if not our_section_found:
+ raise SmsConfigError("%s: profile [%s] not found" % (cfgfile, section))
def __getitem__(self, name):
return self.cfg[name]
View
26 Sms/Exceptions.py
@@ -0,0 +1,26 @@
+## Author: Michal Ludvig <mludvig@logix.net.nz>
+## http://www.logix.cz/michal
+## License: GPL Version 2
+
+class SmsException(Exception):
+ def __init__(self, message = ""):
+ self.message = message
+
+ def __str__(self):
+ return unicode(self)
+
+ def __unicode__(self):
+ return self.message
+
+ ## (Base)Exception.message has been deprecated in Python 2.6
+ def _get_message(self):
+ return self._message
+ def _set_message(self, message):
+ self._message = message
+ message = property(_get_message, _set_message)
+
+class SmsConfigError(SmsException):
+ pass
+
+# vim:et:ts=4:sts=4:ai
+
View
13 sms-cli
@@ -16,6 +16,7 @@ from logging import debug, info, warning, error
from Sms.Config import Config
from Sms.Sender import SmsSender
+from Sms.Exceptions import *
try:
default_config_file=os.getenv("HOME")+"/.sms-cli.conf"
@@ -28,12 +29,13 @@ optparser = OptionParser()
optparser.set_defaults(config=default_config_file)
optparser.set_defaults(verbosity = default_verbosity)
-optparser.add_option("-c", "--config", dest="config", metavar="FILE", help="Config file name. Defaults to %default")
+optparser.add_option("-r", "--recipient", dest="sms_recipients", action="append", metavar="PHONE-NUM", help="Cell phone number of message recipient. Can be used multiple times.")
+optparser.add_option("-m", "--message", dest="message", action="store", metavar="MESSAGE", help="Message to send to given Recipient(s)")
+optparser.add_option("-f", "--config", dest="config", metavar="FILE", help="Config file name. Optionally can include :PROFILE, e.g. --config=/etc/sms-cli.conf:clickatell or use --profile clickatell. Defaults to %default")
+optparser.add_option("-p", "--profile", dest="profile", action="store", metavar="PROFILE", help="Config file profile / section to process. Defaults to [default]")
optparser.add_option( "--debug", dest="verbosity", action="store_const", const=logging.DEBUG, help="Enable debug output.")
optparser.add_option( "--quiet", dest="verbosity", action="store_const", const=logging.WARNING, help="Suppres most messages. Only Warnings and Errors are printed.")
optparser.add_option( "--dump-config", dest="dump_config", action="store_true", help="Dump current configuration after parsing config files and command line options and exit.")
-optparser.add_option("-r", "--recipient", dest="sms_recipients", action="append", metavar="PHONE-NUM", help="Cell phone number of message recipient. Can be used multiple times.")
-optparser.add_option("-m", "--message", dest="message", action="store", metavar="MESSAGE", help="Message to send to given Recipient(s)")
(options, args) = optparser.parse_args()
@@ -43,13 +45,16 @@ logging.basicConfig(level=options.verbosity, format='%(levelname)s: %(message)s'
## Now finally parse the config file
try:
- cfg = Config(options.config)
+ cfg = Config(options.config, options.profile)
except IOError, e:
if options.config != default_config_file:
error("%s: %s" % (options.config, e.strerror))
sys.exit(1)
else:
cfg = Config()
+except SmsConfigError, e:
+ error(e.message)
+ sys.exit(1)
## And again some logging level adjustments
## according to configfile and command line parameters
Please sign in to comment.
Something went wrong with that request. Please try again.