util.py 3.81 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
# -*- coding: utf-8 -*-
#
# AWL simulator - common utility functions
#
# Copyright 2012-2014 Michael Buesch <m@bues.ch>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#

from __future__ import division, absolute_import, print_function, unicode_literals
from awlsim.common.compat import *

from awlsim.common.enumeration import *
from awlsim.common.exceptions import *

import sys
import os
import random


class Logging(object):
	EnumGen.start
	LOG_NONE	= EnumGen.item
	LOG_ERROR	= EnumGen.item
	LOG_INFO	= EnumGen.item
	LOG_DEBUG	= EnumGen.item
	EnumGen.end

	_loglevel = LOG_INFO

	@classmethod
	def setLoglevel(cls, loglevel):
		if loglevel not in (cls.LOG_NONE,
				    cls.LOG_ERROR,
				    cls.LOG_INFO,
				    cls.LOG_DEBUG):
			raise AwlSimError("Invalid log level '%d'" % loglevel)
		cls._loglevel = loglevel

	@classmethod
	def getLoglevel(cls):
		return cls._loglevel

	@classmethod
	def printDebug(cls, text):
		if cls._loglevel >= cls.LOG_DEBUG:
			sys.stdout.write(text)
			sys.stdout.write("\n")
			sys.stdout.flush()

	@classmethod
	def printInfo(cls, text):
		if cls._loglevel >= cls.LOG_INFO:
			sys.stdout.write(text)
			sys.stdout.write("\n")
			sys.stdout.flush()

	@classmethod
	def printError(cls, text):
		if cls._loglevel >= cls.LOG_ERROR:
			sys.stderr.write(text)
			sys.stderr.write("\n")
			sys.stderr.flush()

def printDebug(text):
	Logging.printDebug(text)

def printInfo(text):
	Logging.printInfo(text)

def printError(text):
	Logging.printError(text)

# Warning message helper
printWarning = printError

def awlFileRead(filename, encoding="latin_1"):
	try:
		fd = open(filename, "rb")
		data = fd.read()
		if encoding != "binary":
			data = data.decode(encoding)
		fd.close()
	except (IOError, UnicodeError) as e:
		raise AwlParserError("Failed to read '%s': %s" %\
			(filename, str(e)))
	return data

def awlFileWrite(filename, data, encoding="latin_1"):
	if encoding != "binary":
		data = "\r\n".join(data.splitlines()) + "\r\n"
	for count in range(1000):
		tmpFile = "%s-%d-%d.tmp" %\
			(filename, random.randint(0, 0xFFFF), count)
		if not os.path.exists(tmpFile):
			break
	else:
		raise AwlParserError("Could not create temporary file")
	try:
		fd = open(tmpFile, "wb")
		if encoding != "binary":
			data = data.encode(encoding)
		fd.write(data)
		fd.flush()
		fd.close()
		if not osIsPosix:
			# Can't use safe rename on non-POSIX.
			# Must unlink first.
121 122 123 124
			try:
				os.unlink(filename)
			except OSError as e:
				pass
125 126 127 128 129 130 131 132
		os.rename(tmpFile, filename)
	except (IOError, OSError, UnicodeError) as e:
		raise AwlParserError("Failed to write file:\n" + str(e))
	finally:
		try:
			os.unlink(tmpFile)
		except (IOError, OSError):
			pass
133

134 135
# Call a callable and suppress all exceptions,
# except for really fatal coding exceptions.
136 137 138
def CALL_NOEX(_callable, *args, **kwargs):
	try:
		return _callable(*args, **kwargs)
139 140 141 142 143 144 145 146 147 148 149
	except (SyntaxError, NameError, AttributeError) as e:
		raise
	except ValueError as e:
		import re
		if re.match(r'.*takes exactly \d+ argument \(\d+ given\).*', str(e)) or\
		   re.match(r'.*missing \d+ required positional argument.*', str(e)) or\
		   re.match(r'.*takes \d+ positional argument but \d+ were given.*', str(e)):
			raise
	except Exception as e:
		pass
	return None