def start(base): generic.exit_cleanly() # http://stackoverflow.com/questions/11423225 signal.signal(signal.SIGPIPE, signal.SIG_DFL) plugins = os.path.join(base, "plugins") if not os.path.isdir(plugins): generic.error("no plugins directory: `%s`" % plugins, E_NO_PLUGINS) # TODO: Check for broken symlinks generic.populate(saxo_path, base) opt = configparser.ConfigParser() config = os.path.join(base, "config") opt.read(config) # TODO: defaulting? scripts = os.path.dirname(sys.modules["__main__"].__file__) scripts = os.path.abspath(scripts) sockname = os.path.join(base, "client.sock") serve(sockname, incoming) os.chmod(sockname, 0o600) def remove_sock(sockname): os.remove(sockname) atexit.register(remove_sock, sockname) generic.thread(scheduler.start, base, incoming) saxo = Saxo(base, opt) saxo.run()
def stop(args): if args.directory is None: directory = os.path.expanduser("~/.saxo") else: directory = args.directory pidfile = os.path.join(directory, "pid") if not os.path.exists(pidfile): generic.error("There is no bot currently running") with open(pidfile, encoding="ascii") as f: text = f.read() pid = int(text.rstrip("\n")) # TODO: Make this less crude os.kill(pid, signal.SIGTERM) # os.kill(pid, signal.SIGKILL) return 0
def main(argv, v): # NOTE: No default for argv, because what script name would we use? parser = argparse.ArgumentParser(description="Control saxo irc bot instances", add_help=False) parser.add_argument("-f", "--foreground", action="store_true", help="run in the foreground instead of as a daemon") parser.add_argument("-h", "--help", action="store_true", help="show a short help message") parser.add_argument("-o", "--output", metavar="filename", help="redirect daemon stdout and stderr to this filename") parser.add_argument("-v", "--version", action="store_true", help="show the current saxo version") parser.add_argument("action", nargs="?", help="use --help to show the available actions") parser.add_argument("directory", nargs="?", help="the path to the saxo configuration directory") args = parser.parse_args(argv[1:]) if args.help: help(args, v) elif args.version: version(args, v) elif args.action: if args.action in action.names: code = action.names[args.action](args) if isinstance(code, int): sys.exit(code) else: generic.error("unrecognised action: %s" % args.action, code=2) else: usage(args, v)
def default(base=None): if base is None: base = os.path.expanduser("~/.saxo") if os.path.isdir(base): generic.error("the directory `%s` already exists" % base, E_DIRECTORY_EXISTS) try: os.makedirs(base) except Exception as err: generic.error("could not create the directory `%s`" % base, E_UNMAKEABLE_DIRECTORY, err) config = os.path.join(base, "config") try: with open(config, "w", encoding="ascii") as f: # Generates a random bot name, from saxo00000 to saxo99999 inclusive f.write(DEFAULT_CONFIG % random.randrange(0, 100000)) except Exception as err: generic.error("could not write the config file `%s`" % config, E_UNWRITEABLE_CONFIG, err) plugins = os.path.join(base, "plugins") os.mkdir(plugins) commands = os.path.join(base, "commands") os.mkdir(commands) generic.populate(saxo_path, base) print("Created %s" % config) print("Modify this file with your own settings, and then run:") print("") print(" %s start" % sys.argv[0]) return True
def test_logging(): from generic import log,message,warn,error from generic import generic_settings,NexusError # send messages to object rather than stdout divert_nexus_log() logfile = generic_settings.devlog # test log # simple message s = 'simple message' logfile.reset() log(s) assert(logfile.s==s+'\n') # list of items items = ['a','b','c',1,2,3] logfile.reset() log(*items) assert(logfile.s=='a b c 1 2 3 \n') # message with indentation s = 'a message\nwith indentation' logfile.reset() log(s,indent=' ') assert(logfile.s==' a message\n with indentation\n') logfile.reset() log(s,indent='msg: ') assert(logfile.s=='msg: a message\nmsg: with indentation\n') # writing to separate log files logfile2 = FakeLog() s1 = 'message to log 1' s2 = 'message to log 2' logfile.reset() logfile2.reset() log(s1) assert(logfile.s==s1+'\n') assert(logfile2.s=='') logfile.reset() logfile2.reset() log(s2,logfile=logfile2) assert(logfile.s=='') assert(logfile2.s==s2+'\n') # test warn logfile.reset() s = 'this is a warning' warn(s) so = ''' warning: this is a warning ''' assert(logfile.s==so) logfile.reset() s = 'this is a warning' warn(s,header='Special') so = ''' Special warning: this is a warning ''' assert(logfile.s==so) # test error # in testing environment, should raise an error try: error('testing environment') raise FailedTest except NexusError: None except FailedTest: failed() except Exception as e: failed(str(e)) #end try # in standard/user environment, should print message generic_settings.raise_error = False logfile.reset() error('this is an error',header='User',exit=False) so = ''' User error: this is an error ''' assert(logfile.s==so) generic_settings.raise_error = True # in testing environment, should raise an error try: error('testing environment') raise FailedTest except NexusError: None except FailedTest: failed() except Exception as e: failed(str(e)) #end try restore_nexus_log()
def on_background_change(self, base_path): error("NOTE: I3WM has not been implemented yet. ") pass
def write_colours_to_file(self, colours, _ ): error("NOTE: I3WM has not been implemented yet. ") pass
def format_colours_for_file(self, colours): error("NOTE: I3WM has not been implemented yet. ") pass
def __init__(self): super(I3wm, self).__init__("I3 Window Manager") error("NOTE: I3WM has not been implemented yet. ")
import generic E_PYTHON_VERSION = """ Your version of the python programming language is too old to run saxo. Use a newer version if available. Otherwise you can get a newer version from here: http://www.python.org/ Or install one using your system's package manager. If you are using OS X for example, python3 can be installed using homebrew: http://mxcl.github.io/homebrew/ """ if sys.version_info < (3, 3): generic.error("requires python 3.3 or later", E_PYTHON_VERSION) def action(function): action.names[function.__name__] = function return function action.names = {} # Options def version(args, v): print("saxo %s" % v) USAGE = """ Usage: saxo -v saxo create [ directory ]
def check_keyspec_groups(): from generic import error, warn groups = GamessInput.keyspec_groups group_order = GamessInput.group_order glist = [] for group_name in group_order: if group_name in groups: glist.append(group_name) #end if #end for err = '' wrn = '' #check for unrecognized groups extra_groups = set(groups.keys()) - set(group_order) if len(extra_groups) > 0: err += ' encountered unrecognized keyspec groups: {0}\n'.format( sorted(extra_groups)) #end if #check that integers, reals, bools, strings, and arrays are non-overlapping subsets of keywords #check that allowed_values are a subset of keywords and values specified are of the correct type for group_name in glist: g = groups[group_name] go = obj(integers=g.integers, reals=g.reals, bools=g.bools, strings=g.strings, arrays=g.arrays) overlaps = obj() for tname1, tset1 in go.items(): for tname2, tset2 in go.items(): if tname1 != tname2: overlap = tset1 & tset2 if len(overlap) > 0: overlaps[tname1, tname2] = sorted(overlap) #end if #end if #end for #end for if len(overlaps) > 0: msg = ' keyspec group {0} has overlapping keywords'.format( g.__name__) for tname1, tname2 in sorted(overlaps.keys()): msg += ' \n {0} {1} overlap: {2}\n'.format( tname1, tname2, overlaps[tname1, tname2]) #end for err += msg #end if for tname in sorted(go.keys()): extra_keys = go[tname] - g.keywords if len(extra_keys) > 0: err += ' keyspec group {0} has unrecognized {1} keywords:\n {2}\n'.format( g.__name__, tname, sorted(extra_keys)) #end if #end for extra_keys = set(g.allowed_values.keys()) - g.keywords if len(extra_keys) > 0: err += ' keyspec group {0} has unrecognized allowed_value keywords:\n {1}\n'.format( g.__name__, sorted(extra_keys)) #end if type_keys = set() for keys in go: type_keys |= keys #end for undefined = g.keywords - type_keys if len(undefined) > 0: err += ' keyspec group {0} has keywords w/o type assignment:\n {1}\n'.format( g.__name__, sorted(undefined)) #end if #check that allowed values for each keyword have the right type to = obj(integers=int, reals=float, bools=bool, strings=str, arrays=ndarray) for tname in sorted(go.keys()): type = to[tname] for kw in sorted(go[tname]): if kw in g.allowed_values: for val in g.allowed_values[kw]: if not isinstance(val, type): err += ' allowed values of {0} keyword {1} are not all {2}: {3}\n'.format( g.__name__, kw, tname, sorted(g.allowed_values[kw])) break #end if #end for #end if #end for #end for #end for #note any overlapping keywords between groups (this is a feature, not an error) overlaps = obj() for gname1 in glist: kw1 = groups[gname1].keywords for gname2 in glist: kw2 = groups[gname2].keywords if gname1 != gname2: overlap = kw1 & kw2 if len(overlap) > 0: tup = tuple(sorted((gname1, gname2))) overlaps[tup] = sorted(overlap) #end if #end if #end for #end for if len(overlaps) > 0: wrn += '\n Note: some groups have overlapping keywords\n' for gname1, gname2 in sorted(overlaps.keys()): wrn += ' groups {0} and {1} have overlapping keywords:\n {2}\n'.format( gname1, gname2, overlaps[gname1, gname2]) #end for #end if #note any overlapping keyword and group names (also a feature) overlap = GamessInput.all_keywords & set(GamessInput.group_order) if len(overlap) > 0: wrn += '\n Note: some group names overlap with keywords:\n {0}\n'.format( sorted(overlap)) #end if if len(err) > 0: error(err) #end if if len(wrn) > 0: warn(wrn)