python-escpos/src/escpos/config.py

119 lines
3.6 KiB
Python
Raw Normal View History

2016-03-15 21:09:45 +00:00
""" ESC/POS configuration manager.
This module contains the implentations of abstract base class :py:class:`Config`.
"""
2016-03-15 19:00:46 +00:00
from __future__ import absolute_import
2016-03-30 20:29:28 +00:00
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
2016-03-15 19:00:46 +00:00
import os
import appdirs
2016-03-15 20:47:23 +00:00
import yaml
2016-03-15 19:00:46 +00:00
from . import printer
2016-03-15 19:14:12 +00:00
from . import exceptions
2016-03-15 19:00:46 +00:00
2016-06-19 10:25:40 +00:00
2016-03-15 19:00:46 +00:00
class Config(object):
2016-03-15 21:09:45 +00:00
""" Configuration handler class.
2016-03-15 19:00:46 +00:00
2016-03-15 21:09:45 +00:00
This class loads configuration from a default or specificed directory. It
can create your defined printer and return it to you.
"""
2016-03-15 19:00:46 +00:00
_app_name = 'python-escpos'
2016-03-15 20:47:23 +00:00
_config_file = 'config.yaml'
2016-03-15 19:00:46 +00:00
def __init__(self):
""" Initialize configuration.
Remember to add anything that needs to be reset between configurations
to self._reset_config
"""
self._has_loaded = False
self._printer = None
self._printer_name = None
self._printer_config = None
def _reset_config(self):
""" Clear the loaded configuration.
If we are loading a changed config, we don't want to have leftover
data.
"""
2016-03-15 19:00:46 +00:00
self._has_loaded = False
self._printer = None
self._printer_name = None
self._printer_config = None
def load(self, config_path=None):
2016-03-15 21:09:45 +00:00
""" Load and parse the configuration file using pyyaml
:param config_path: An optional file path, file handle, or byte string
for the configuration file.
"""
self._reset_config()
2016-03-15 19:00:46 +00:00
if not config_path:
config_path = os.path.join(
appdirs.user_config_dir(self._app_name),
self._config_file
)
2016-03-15 20:47:23 +00:00
try:
# First check if it's file like. If it is, pyyaml can load it.
2016-03-31 00:13:20 +00:00
# I'm checking type instead of catching exceptions to keep the
# exception handling simple
if hasattr(config_path, 'read'):
config = yaml.safe_load(config_path)
else:
2016-03-31 00:13:59 +00:00
# If it isn't, it's a path. We have to open it first, otherwise
# pyyaml will try to read it as yaml
2016-03-30 20:30:44 +00:00
with open(config_path, 'rb') as config_file:
config = yaml.safe_load(config_file)
2016-03-16 20:47:51 +00:00
except EnvironmentError:
raise exceptions.ConfigNotFoundError('Couldn\'t read config at {config_path}'.format(
config_path=str(config_path),
2016-03-15 19:00:46 +00:00
))
2016-03-16 21:28:53 +00:00
except yaml.YAMLError:
2016-03-15 20:47:23 +00:00
raise exceptions.ConfigSyntaxError('Error parsing YAML')
2016-03-15 19:00:46 +00:00
if 'printer' in config:
2016-03-15 20:47:23 +00:00
self._printer_config = config['printer']
2016-03-15 19:00:46 +00:00
self._printer_name = self._printer_config.pop('type').title()
if not self._printer_name or not hasattr(printer, self._printer_name):
2016-03-30 20:30:44 +00:00
raise exceptions.ConfigSyntaxError(
'Printer type "{printer_name}" is invalid'.format(
printer_name=self._printer_name,
)
)
2016-03-15 19:00:46 +00:00
self._has_loaded = True
def printer(self):
""" Returns a printer that was defined in the config, or throws an
exception.
2016-03-15 21:09:45 +00:00
This method loads the default config if one hasn't beeen already loaded.
"""
2016-03-15 19:00:46 +00:00
if not self._has_loaded:
self.load()
if not self._printer_name:
raise exceptions.ConfigSectionMissingError('printer')
2016-03-15 19:00:46 +00:00
if not self._printer:
2016-03-30 20:30:44 +00:00
# We could catch init errors and make them a ConfigSyntaxError,
2016-03-15 19:00:46 +00:00
# but I'll just let them pass
self._printer = getattr(printer, self._printer_name)(**self._printer_config)
return self._printer