<commit_before>#-*- encoding: utf-8

"""
The main class that starts and runs Suplemon.
"""

__version__ = "0.1.11"

import os
import sys
import time

import ui
import modules

from helpers import *
from logger import *
from config import *
from editor import *
from file import *

class App:
    def __init__(self, filenames=None):
        """
        Handle App initialization

        :param list filenames: Names of files to load initially
        :param str filenames[*]: Path to a file to load
        """
        self.version = __version__
        self.inited = 0
        self.running = 0

        # Set default variables
        self.path = os.path.dirname(os.path.realpath(__file__))
        self.files = []
        self.current_file = 0
        self.status_msg = ""
        self.last_input = None
        self.global_buffer = []
        self.event_bindings = {}

        # Define core operations
        self.operations = {
            "help": self.help,
            "save_file": self.save_file,
            "run_command": self.run_command,
            "find": self.find,
            "go_to": self.go_to,
            "open": self.open,
            "close_file": self.close_file,
            "new_file": self.new_file,
            "ask_exit": self.ask_exit,
            "prev_file": self.prev_file,
            "next_file": self.next_file,
            "save_file_as": self.save_file_as,
            "reload_file": self.reload_file,
            "toggle_mouse": self.toggle_mouse,
            "toggle_fullscreen": self.toggle_fullscreen,
        }

        # Load core components
        self.logger = Logger()
        self.config = Config(self)
        self.config.load()
        self.ui = ui.UI(self) # Load user interface
        self.ui.init()

        # Load extension modules
        self.modules = modules.ModuleLoader(self)
        self.modules.load()

        # Save filenames for later
        self.filenames = filenames

        # Indicate that windows etc. have been created.
        self.inited = 1

    def log(self, text, log_type=LOG_ERROR):
        """Add text to the log buffer."""
        self.logger.log(text, log_type)

    def init(self):
        """Run the app via the ui wrapper."""
        self.ui.run(self.run)

    def exit(self):
        """Stop the main loop and exit."""
        self.running = 0

    def run(self, *args):
        """Run the app."""
        # Load ui and files etc
        self.load()
        # Initial render
        self.get_editor().resize()
        self.ui.refresh()
        # Start mainloop
        self.main_loop()
        # Unload ui
        self.ui.unload()

    def load(self):
        """Load the app."""
        self.ui.load()
        if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] < 3):
            ver = ".".join(map(str, sys.version_info[0:2]))
            self.log("Running Suplemon with Python "+ver+" which isn't officialy supported. Please use Python 3.3 or higher.", LOG_WARNING)
        self.load_files()
        self.running = 1
        self.trigger_event("app_loaded")

    def main_loop(self):
        """Run the terminal IO loop until exit() is called."""
        while self.running:
            # Update ui before refreshing it
            self.ui.update()
            # See if we have input to process
            event = self.ui.get_input()
            if event:
                #self.log("INPUT:"+str(event), LOG_INFO)
                # Handle the input or give it to the editor
                if not self.handle_input(event):
                    # Pass the input to the editor component
                    self.get_editor().handle_input(event)
                #TODO: why do I need resize here? (View won't update after switching files, WTF)
                self.get_editor().resize()
                self.ui.refresh()

    def get_status(self):
        """Set the status message."""
        return self.status_msg

    def get_file_index(self, file_obj):
        """Get file index by file object."""
        return self.files.index(file_obj)

    def get_key_bindings(self):
        """Returns the list of key bindings."""
        return self.config["app"]["keys"]

    def get_event_bindings(self):
        """Returns the dict of event bindings."""
        return self.event_bindings

    def set_key_binding(self, key, operation):
        """Bind a key to an operation."""
        self.get_key_bindings()[key] = operation

    def set_event_binding(self, event, callback):
        """Bind a key to an operatio n."""
        event_bindings = self.get_event_bindings()
        if event in event_bindings.keys():
            event_bindings[event].append(callback)
        else:
            event_bindings[event] = [callback]

    def set_status(self, s):
        """Set the status message."""
        self.status_msg = str(s)

    def unsaved_changes(self):
        """Check if there are unsaved changes in any file."""
        for f in self.files:
            if f.is_changed():
                return True
        return False

    def reload_config(self):
        """Reload configuration."""
        self.config.reload()
        for f in self.files:
            self.setup_editor(f.editor)
        self.ui.resize()
        self.ui.refresh()

    def handle_input(self, event):
        """Handle an input event."""
        if not event:
            return False
        self.last_input = event

        if event.type == "key":
            return self.handle_key(event)
        elif event.type == "mouse":
            return self.handle_mouse(event)
        return False

    def handle_key(self, event):
        """Handle a keyboard event."""
        key_bindings = self.get_key_bindings()
        if event.key_name in key_bindings.keys():
            operation = key_bindings[event.key_name]
        elif event.key_code in key_bindings.keys():
            operation = key_bindings[event.key_code]
        else:
            return False
        self.run_operation(operation)
        return True

    def handle_mouse(self, event):
        """Handle a mouse event."""
        editor = self.get_editor()
        if event.mouse_code == 1:                    # Left mouse button release
            editor.set_single_cursor(event.mouse_pos)
        elif event.mouse_code == 134217728:          # Wheel up (and unfortunately left button drag)
            editor.page_up()
        elif event.mouse_code == 524288:             # Wheel down
            editor.page_down()
        else:
            return False
        return True

    ###########################################################################
    # User Interactions
    ###########################################################################

    def help(self):
        """Open help file."""
        f = self.default_file()
        import help
        f.set_data(help.help_text)
        self.files.append(f)
        self.switch_to_file(self.last_file_index())

    def new_file(self, path=None):
        """Open new empty file."""
        new_file = self.default_file()
        if path:
            new_file.set_path(path)
        self.files.append(new_file)
        self.current_file = self.last_file_index()

    def ask_exit(self):
        """Exit if no unsaved changes, else make sure the user really wants to exit."""
        if self.unsaved_changes():
            yes = self.ui.query_bool("Exit?")
            if yes:
                self.exit()
                return True
            return False
        else:
            self.exit()
            return True

    def switch_to_file(self, index):
        """Load a default file if no files specified."""
        self.current_file = index

    def next_file(self):
        """Switch to next file."""
        if len(self.files) < 2: return
        cur = self.current_file
        cur += 1
        if cur > len(self.files)-1:
            cur = 0
        self.switch_to_file(cur)

    def prev_file(self):
        """Switch to previous file."""
        if len(self.files) < 2: return
        cur = self.current_file
        cur -= 1
        if cur < 0:
            cur = len(self.files)-1
        self.switch_to_file(cur)

    def go_to(self):
        """Go to a line or a file (or a line in a specific file with 'name:lineno')."""
        input_str = self.ui.query("Go to:")
        lineno = None
        fname = None
        if input_str == False:
            return False
        if input_str.find(":") != -1:
            parts = input_str.split(":")
            fname = parts[0]
            lineno = parts[1]
            file_index = self.find_file(fname)
            if file_index != -1:
                self.switch_to_file(file_index)
                try:
                    input_str = int(lineno)
                    self.get_editor().go_to_pos(input_str)
                except:
                    pass
        else:
            try:
                line_no = int(input_str)
                self.get_editor().go_to_pos(line_no)
            except:
                file_index = self.find_file(input_str)
                if file_index != -1:
                    self.switch_to_file(file_index)

    def find(self):
        """Find in file."""
        editor = self.get_editor()
        what = self.ui.query("Find:", editor.last_find)
        if what:
            editor.find(what)

    def find_file(self, s):
        """Return index of file matching string."""
        i = 0
        for file in self.files:
            if file.name[:len(s)].lower() == s.lower():
                return i
            i += 1
        return -1

    def run_command(self):
        """Run editor commands."""
        data = self.ui.query("Command:")
        if not data:
            return False
        parts = data.split(" ")
        cmd = parts[0].lower()
        self.logger.log("Looking for command '" + cmd +"'", LOG_INFO)
        if cmd in self.modules.modules.keys():
            self.logger.log("Trying to run command '" + cmd +"'", LOG_INFO)
            self.get_editor().store_action_state(cmd)
            self.modules.modules[cmd].run(self, self.get_editor())
        else:
            self.set_status("Command '" + cmd + "' not found.")
        return True

    def run_operation(self, operation):
        """Run an app core operation."""
        # Support arbitrary callables
        if hasattr(operation, '__call__'):
            operation()
        elif operation in self.operations.keys():
            cancel = self.trigger_event(operation)
            if not cancel:
                result = self.operations[operation]()
                return result
        return False

    def trigger_event(self, event):
        """Triggers event and runs registered callbacks."""
        status = False
        bindings = self.get_event_bindings()
        if event in bindings.keys():
            callbacks = bindings[event]
            for cb in callbacks:
                val = cb(event)
                if val:
                    status = True
        return status

    def toggle_fullscreen(self):
        """Toggle full screen editor."""
        display = self.config["display"]
        if display["show_top_bar"]:
            display["show_top_bar"] = 0
            display["show_bottom_bar"] = 0
            display["show_legend"] = 0
        else:
            display["show_top_bar"] = 1
            display["show_bottom_bar"] = 1
            display["show_legend"] = 1
        # Virtual curses windows need to be resized
        self.ui.resize()

    def toggle_mouse(self):
        """Toggle mouse support."""
        # Invert the boolean
        self.config["editor"]["use_mouse"] = not self.config["editor"]["use_mouse"]
        self.ui.setup_mouse()
        if self.config["editor"]["use_mouse"]:
            self.set_status("Mouse enabled")
        else:
            self.set_status("Mouse disabled")

    ###########################################################################
    # Editor operations
    ###########################################################################

    def new_editor(self):
        """Create a new editor instance."""
        editor = Editor(self, self.ui.editor_win)
        self.setup_editor(editor)
        return editor

    def get_editor(self):
        """Return the current editor."""
        return self.files[self.current_file].editor

    def setup_editor(self, editor):
        """Setup an editor instance with configuration."""
        config = self.config["editor"]
        editor.set_config(config)

    ###########################################################################
    # File operations
    ###########################################################################

    def open(self):
        """Ask for file name and try to open it."""
        name = self.ui.query("Open file:")
        if not name:
            return False
        exists = self.file_is_open(name)
        if exists:
            self.switch_to_file(self.files.index(exists))
            return True

        if not self.open_file(name):
            self.set_status("Failed to load '" + name + "'")
            return False
        self.switch_to_file(self.last_file_index())
        return True

    def close_file(self):
        """Close current file if user confirms action."""
        if self.get_file().is_changed():
            if not self.ui.query_bool("Close file?"):
                return False
        self.files.pop(self.current_file)
        if not len(self.files):
            self.new_file()
            return False
        if self.current_file == len(self.files):
            self.current_file -= 1

    def save_file(self, file = False):
        """Save current file."""
        f = file or self.get_file()
        if not f.get_name():
            return self.save_file_as(f)
        if f.save():
            self.set_status("Saved [" + curr_time_sec() + "] '" + f.name + "'")
            if f.path() == self.config.path():
                self.reload_config()
            return True
        self.set_status("Couldn't write to '" + f.name + "'")
        return False

    def save_file_as(self, file = False):
        """Save current file."""
        f = file or self.get_file()
        name = self.ui.query("Save as:", f.name)
        if not name:
            return False
        f.set_name(name)
        return self.save_file(f)

    def reload_file(self):
        """Reload the current file."""
        if self.ui.query_bool("Reload '" + self.get_file().name + "'?"):
            if self.get_file().reload():
                return True
        return False

    def get_files(self):
        """Return list of open files."""
        return self.files

    def get_file(self):
        """Return the current file."""
        return self.files[self.current_file]

    def last_file_index(self):
        """Get index of last file."""
        cur = len(self.files)-1
        return cur

    def current_file_index(self):
        """Get index of current file."""
        return self.current_file

    def open_file(self, filename):
        """Open a file."""
        file = File(self)
        file.set_path(filename)
        file.set_editor(self.new_editor())
        if not file.load():
            return False
        self.files.append(file)
        return True

    def load_files(self):
        """Try to load all files specified in arguments."""
        if self.filenames:
            for name in self.filenames:
                if self.file_is_open(name): continue
                if self.open_file(name):
                    loaded = True
                else:
                    self.new_file(name)
        else:
            self.load_default()

    def file_is_open(self, path):
        """Check if file is open. Returns the File object or False."""
        for file in self.files:
            if file.path() == os.path.abspath(path):
                return file
        return False

    def load_default(self):
        """Load a default file if no files specified."""
        file = self.default_file()
        self.files.append(file)

    def default_file(self):
        """Create the default file."""
        file = File(self)
        file.set_editor(self.new_editor())
        # Specify contents to avoid appearing as modified
        file.set_data("")
        # Set markdown as the default file type
        file.editor.set_file_extension("md")
        return file
<commit_msg>Removed 'from helpers import *'.<commit_after>#-*- encoding: utf-8

"""
The main class that starts and runs Suplemon.
"""

__version__ = "0.1.11"

import os
import sys
import time

import ui
import modules
import helpers

from logger import *
from config import *
from editor import *
from file import *

class App:
    def __init__(self, filenames=None):
        """
        Handle App initialization

        :param list filenames: Names of files to load initially
        :param str filenames[*]: Path to a file to load
        """
        self.version = __version__
        self.inited = 0
        self.running = 0

        # Set default variables
        self.path = os.path.dirname(os.path.realpath(__file__))
        self.files = []
        self.current_file = 0
        self.status_msg = ""
        self.last_input = None
        self.global_buffer = []
        self.event_bindings = {}

        # Define core operations
        self.operations = {
            "help": self.help,
            "save_file": self.save_file,
            "run_command": self.run_command,
            "find": self.find,
            "go_to": self.go_to,
            "open": self.open,
            "close_file": self.close_file,
            "new_file": self.new_file,
            "ask_exit": self.ask_exit,
            "prev_file": self.prev_file,
            "next_file": self.next_file,
            "save_file_as": self.save_file_as,
            "reload_file": self.reload_file,
            "toggle_mouse": self.toggle_mouse,
            "toggle_fullscreen": self.toggle_fullscreen,
        }

        # Load core components
        self.logger = Logger()
        self.config = Config(self)
        self.config.load()
        self.ui = ui.UI(self) # Load user interface
        self.ui.init()

        # Load extension modules
        self.modules = modules.ModuleLoader(self)
        self.modules.load()

        # Save filenames for later
        self.filenames = filenames

        # Indicate that windows etc. have been created.
        self.inited = 1

    def log(self, text, log_type=LOG_ERROR):
        """Add text to the log buffer."""
        self.logger.log(text, log_type)

    def init(self):
        """Run the app via the ui wrapper."""
        self.ui.run(self.run)

    def exit(self):
        """Stop the main loop and exit."""
        self.running = 0

    def run(self, *args):
        """Run the app."""
        # Load ui and files etc
        self.load()
        # Initial render
        self.get_editor().resize()
        self.ui.refresh()
        # Start mainloop
        self.main_loop()
        # Unload ui
        self.ui.unload()

    def load(self):
        """Load the app."""
        self.ui.load()
        if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] < 3):
            ver = ".".join(map(str, sys.version_info[0:2]))
            self.log("Running Suplemon with Python "+ver+" which isn't officialy supported. Please use Python 3.3 or higher.", LOG_WARNING)
        self.load_files()
        self.running = 1
        self.trigger_event("app_loaded")

    def main_loop(self):
        """Run the terminal IO loop until exit() is called."""
        while self.running:
            # Update ui before refreshing it
            self.ui.update()
            # See if we have input to process
            event = self.ui.get_input()
            if event:
                #self.log("INPUT:"+str(event), LOG_INFO)
                # Handle the input or give it to the editor
                if not self.handle_input(event):
                    # Pass the input to the editor component
                    self.get_editor().handle_input(event)
                #TODO: why do I need resize here? (View won't update after switching files, WTF)
                self.get_editor().resize()
                self.ui.refresh()

    def get_status(self):
        """Set the status message."""
        return self.status_msg

    def get_file_index(self, file_obj):
        """Get file index by file object."""
        return self.files.index(file_obj)

    def get_key_bindings(self):
        """Returns the list of key bindings."""
        return self.config["app"]["keys"]

    def get_event_bindings(self):
        """Returns the dict of event bindings."""
        return self.event_bindings

    def set_key_binding(self, key, operation):
        """Bind a key to an operation."""
        self.get_key_bindings()[key] = operation

    def set_event_binding(self, event, callback):
        """Bind a key to an operatio n."""
        event_bindings = self.get_event_bindings()
        if event in event_bindings.keys():
            event_bindings[event].append(callback)
        else:
            event_bindings[event] = [callback]

    def set_status(self, s):
        """Set the status message."""
        self.status_msg = str(s)

    def unsaved_changes(self):
        """Check if there are unsaved changes in any file."""
        for f in self.files:
            if f.is_changed():
                return True
        return False

    def reload_config(self):
        """Reload configuration."""
        self.config.reload()
        for f in self.files:
            self.setup_editor(f.editor)
        self.ui.resize()
        self.ui.refresh()

    def handle_input(self, event):
        """Handle an input event."""
        if not event:
            return False
        self.last_input = event

        if event.type == "key":
            return self.handle_key(event)
        elif event.type == "mouse":
            return self.handle_mouse(event)
        return False

    def handle_key(self, event):
        """Handle a keyboard event."""
        key_bindings = self.get_key_bindings()
        if event.key_name in key_bindings.keys():
            operation = key_bindings[event.key_name]
        elif event.key_code in key_bindings.keys():
            operation = key_bindings[event.key_code]
        else:
            return False
        self.run_operation(operation)
        return True

    def handle_mouse(self, event):
        """Handle a mouse event."""
        editor = self.get_editor()
        if event.mouse_code == 1:                    # Left mouse button release
            editor.set_single_cursor(event.mouse_pos)
        elif event.mouse_code == 134217728:          # Wheel up (and unfortunately left button drag)
            editor.page_up()
        elif event.mouse_code == 524288:             # Wheel down
            editor.page_down()
        else:
            return False
        return True

    ###########################################################################
    # User Interactions
    ###########################################################################

    def help(self):
        """Open help file."""
        f = self.default_file()
        import help
        f.set_data(help.help_text)
        self.files.append(f)
        self.switch_to_file(self.last_file_index())

    def new_file(self, path=None):
        """Open new empty file."""
        new_file = self.default_file()
        if path:
            new_file.set_path(path)
        self.files.append(new_file)
        self.current_file = self.last_file_index()

    def ask_exit(self):
        """Exit if no unsaved changes, else make sure the user really wants to exit."""
        if self.unsaved_changes():
            yes = self.ui.query_bool("Exit?")
            if yes:
                self.exit()
                return True
            return False
        else:
            self.exit()
            return True

    def switch_to_file(self, index):
        """Load a default file if no files specified."""
        self.current_file = index

    def next_file(self):
        """Switch to next file."""
        if len(self.files) < 2: return
        cur = self.current_file
        cur += 1
        if cur > len(self.files)-1:
            cur = 0
        self.switch_to_file(cur)

    def prev_file(self):
        """Switch to previous file."""
        if len(self.files) < 2: return
        cur = self.current_file
        cur -= 1
        if cur < 0:
            cur = len(self.files)-1
        self.switch_to_file(cur)

    def go_to(self):
        """Go to a line or a file (or a line in a specific file with 'name:lineno')."""
        input_str = self.ui.query("Go to:")
        lineno = None
        fname = None
        if input_str == False:
            return False
        if input_str.find(":") != -1:
            parts = input_str.split(":")
            fname = parts[0]
            lineno = parts[1]
            file_index = self.find_file(fname)
            if file_index != -1:
                self.switch_to_file(file_index)
                try:
                    input_str = int(lineno)
                    self.get_editor().go_to_pos(input_str)
                except:
                    pass
        else:
            try:
                line_no = int(input_str)
                self.get_editor().go_to_pos(line_no)
            except:
                file_index = self.find_file(input_str)
                if file_index != -1:
                    self.switch_to_file(file_index)

    def find(self):
        """Find in file."""
        editor = self.get_editor()
        what = self.ui.query("Find:", editor.last_find)
        if what:
            editor.find(what)

    def find_file(self, s):
        """Return index of file matching string."""
        i = 0
        for file in self.files:
            if file.name[:len(s)].lower() == s.lower():
                return i
            i += 1
        return -1

    def run_command(self):
        """Run editor commands."""
        data = self.ui.query("Command:")
        if not data:
            return False
        parts = data.split(" ")
        cmd = parts[0].lower()
        self.logger.log("Looking for command '" + cmd +"'", LOG_INFO)
        if cmd in self.modules.modules.keys():
            self.logger.log("Trying to run command '" + cmd +"'", LOG_INFO)
            self.get_editor().store_action_state(cmd)
            self.modules.modules[cmd].run(self, self.get_editor())
        else:
            self.set_status("Command '" + cmd + "' not found.")
        return True

    def run_operation(self, operation):
        """Run an app core operation."""
        # Support arbitrary callables
        if hasattr(operation, '__call__'):
            operation()
        elif operation in self.operations.keys():
            cancel = self.trigger_event(operation)
            if not cancel:
                result = self.operations[operation]()
                return result
        return False

    def trigger_event(self, event):
        """Triggers event and runs registered callbacks."""
        status = False
        bindings = self.get_event_bindings()
        if event in bindings.keys():
            callbacks = bindings[event]
            for cb in callbacks:
                val = cb(event)
                if val:
                    status = True
        return status

    def toggle_fullscreen(self):
        """Toggle full screen editor."""
        display = self.config["display"]
        if display["show_top_bar"]:
            display["show_top_bar"] = 0
            display["show_bottom_bar"] = 0
            display["show_legend"] = 0
        else:
            display["show_top_bar"] = 1
            display["show_bottom_bar"] = 1
            display["show_legend"] = 1
        # Virtual curses windows need to be resized
        self.ui.resize()

    def toggle_mouse(self):
        """Toggle mouse support."""
        # Invert the boolean
        self.config["editor"]["use_mouse"] = not self.config["editor"]["use_mouse"]
        self.ui.setup_mouse()
        if self.config["editor"]["use_mouse"]:
            self.set_status("Mouse enabled")
        else:
            self.set_status("Mouse disabled")

    ###########################################################################
    # Editor operations
    ###########################################################################

    def new_editor(self):
        """Create a new editor instance."""
        editor = Editor(self, self.ui.editor_win)
        self.setup_editor(editor)
        return editor

    def get_editor(self):
        """Return the current editor."""
        return self.files[self.current_file].editor

    def setup_editor(self, editor):
        """Setup an editor instance with configuration."""
        config = self.config["editor"]
        editor.set_config(config)

    ###########################################################################
    # File operations
    ###########################################################################

    def open(self):
        """Ask for file name and try to open it."""
        name = self.ui.query("Open file:")
        if not name:
            return False
        exists = self.file_is_open(name)
        if exists:
            self.switch_to_file(self.files.index(exists))
            return True

        if not self.open_file(name):
            self.set_status("Failed to load '" + name + "'")
            return False
        self.switch_to_file(self.last_file_index())
        return True

    def close_file(self):
        """Close current file if user confirms action."""
        if self.get_file().is_changed():
            if not self.ui.query_bool("Close file?"):
                return False
        self.files.pop(self.current_file)
        if not len(self.files):
            self.new_file()
            return False
        if self.current_file == len(self.files):
            self.current_file -= 1

    def save_file(self, file = False):
        """Save current file."""
        f = file or self.get_file()
        if not f.get_name():
            return self.save_file_as(f)
        if f.save():
            self.set_status("Saved [" + helpers.curr_time_sec() + "] '" + f.name + "'")
            if f.path() == self.config.path():
                self.reload_config()
            return True
        self.set_status("Couldn't write to '" + f.name + "'")
        return False

    def save_file_as(self, file = False):
        """Save current file."""
        f = file or self.get_file()
        name = self.ui.query("Save as:", f.name)
        if not name:
            return False
        f.set_name(name)
        return self.save_file(f)

    def reload_file(self):
        """Reload the current file."""
        if self.ui.query_bool("Reload '" + self.get_file().name + "'?"):
            if self.get_file().reload():
                return True
        return False

    def get_files(self):
        """Return list of open files."""
        return self.files

    def get_file(self):
        """Return the current file."""
        return self.files[self.current_file]

    def last_file_index(self):
        """Get index of last file."""
        cur = len(self.files)-1
        return cur

    def current_file_index(self):
        """Get index of current file."""
        return self.current_file

    def open_file(self, filename):
        """Open a file."""
        file = File(self)
        file.set_path(filename)
        file.set_editor(self.new_editor())
        if not file.load():
            return False
        self.files.append(file)
        return True

    def load_files(self):
        """Try to load all files specified in arguments."""
        if self.filenames:
            for name in self.filenames:
                if self.file_is_open(name): continue
                if self.open_file(name):
                    loaded = True
                else:
                    self.new_file(name)
        else:
            self.load_default()

    def file_is_open(self, path):
        """Check if file is open. Returns the File object or False."""
        for file in self.files:
            if file.path() == os.path.abspath(path):
                return file
        return False

    def load_default(self):
        """Load a default file if no files specified."""
        file = self.default_file()
        self.files.append(file)

    def default_file(self):
        """Create the default file."""
        file = File(self)
        file.set_editor(self.new_editor())
        # Specify contents to avoid appearing as modified
        file.set_data("")
        # Set markdown as the default file type
        file.editor.set_file_extension("md")
        return file
<|endoftext|>


<commit_before>#!/usr/bin/env python
import webapp2
from google.appengine.api import app_identity
from google.appengine.api import mail
from conference import ConferenceApi

class SetAnnouncementHandler(webapp2.RequestHandler):
    def get(self):
        """Set Announcement in Memcache."""
        # TODO 1
        # use _cacheAnnouncement() to set announcement in Memcache
        ConferenceApi._cacheAnnouncement()

app = webapp2.WSGIApplication([
    ('/crons/set_announcement', SetAnnouncementHandler),
], debug=True)
<commit_msg> add sendConfirmationEmilHandler to main.py<commit_after>#!/usr/bin/env python
import webapp2
from google.appengine.api import app_identity
from google.appengine.api import mail
from conference import ConferenceApi

class SetAnnouncementHandler(webapp2.RequestHandler):
    def get(self):
        """Set Announcement in Memcache."""
        # TODO 1
        # use _cacheAnnouncement() to set announcement in Memcache
        ConferenceApi._cacheAnnouncement()

class SendConfirmationEmailHandler(webapp2.RequestHandler):
    def post(self):
        """Send email confirming Conference creation."""
        mail.send_mail(
            'noreply@%s.appspotmail.com' % (
                app_identity.get_application_id()),     # from
            self.request.get('email'),                  # to
            'You created a new Conference!',            # subj
            'Hi, you have created a following '         # body
            'conference:\r\n\r\n%s' % self.request.get(
                'conferenceInfo')
        )

app = webapp2.WSGIApplication([
    ('/crons/set_announcement', SetAnnouncementHandler),
    ('/tasks/send_confirmation_email', SendConfirmationEmailHandler),
], debug=True)
<|endoftext|>


<commit_before>import collections

from kivy.app import App
from kivy import properties
from kivy import graphics
from kivy.uix import label
from kivy.uix.floatlayout import FloatLayout
import math

MapCoords = collections.namedtuple('MapCoords', ['row', 'col'])

class StrategyGame(FloatLayout):
    main_map = properties.ObjectProperty(None)
    map_rows = properties.NumericProperty(0)
    map_cols = properties.NumericProperty(0)

    def __init__(self, **kwargs):
        super(StrategyGame, self).__init__(**kwargs)

        number_of_regions = self.map_rows * self.map_cols
        for region in xrange(0, number_of_regions):
            row = region / self.map_cols
            col = region % self.map_cols
            self.main_map.add_widget(self.pick_hex_cell(row=row, col=col))

    def pick_hex_cell(self, row, col):
        row_mod = row % 6
        if col % 2 == 0:
            if row_mod == 0:
                return BU()
            elif row_mod in (1, 2):
                return L()
            elif row_mod == 3:
                return TD()
            elif row_mod in (4, 5):
                return R()
        else:
            if row_mod == 0:
                return TD()
            elif row_mod in (1, 2):
                return R()
            elif row_mod == 3:
                return BU()
            elif row_mod in (4, 5):
                return L()

class HexMapCell(label.Label):

    def __init__(self, row=0, col=0, **kwargs):
        self.region_in_map = MapCoords(row, col)
        super(HexMapCell, self).__init__(**kwargs)

class BU(HexMapCell):
    pass
class TD(HexMapCell):
    pass
class L(HexMapCell):
    pass
class R(HexMapCell):
    pass

class StrategyGameApp(App):
    def build(self):
        return StrategyGame()

if __name__ == '__main__':
    StrategyGameApp().run()
<commit_msg>Add in way to add in a single and multiple boxes for handling control of units.<commit_after>import collections
import random

from kivy import app, properties
from kivy.uix import button, label
from kivy.uix.floatlayout import FloatLayout

MapCoords = collections.namedtuple('MapCoords', ['row', 'col'])

class StrategyGame(FloatLayout):
    main_map = properties.ObjectProperty(None)
    map_rows = properties.NumericProperty(0)
    map_cols = properties.NumericProperty(0)

    def __init__(self, **kwargs):
        super(StrategyGame, self).__init__(**kwargs)

        number_of_regions = self.map_rows * self.map_cols
        for region in xrange(0, number_of_regions):
            row = region / self.map_cols
            col = region % self.map_cols

            # Add hex cells to make up the map.
            hex_cell = self.pick_hex_cell(row=row, col=col)
            self.main_map.add_widget(hex_cell)

            # Add overlay conditionally.
            # if (row % 6 == 2 and col % 2 == 0) or (row % 6 == 5 and col % 2 == 1):
            if row == 2 and col == 0:
                self.add_widget(HexMapControlCell(hex_bind=hex_cell))

    @staticmethod
    def pick_hex_cell(row, col):
        row_mod = row % 6
        if col % 2 == 0:
            if row_mod == 0:
                return BU()
            elif row_mod in (1, 2):
                return L()
            elif row_mod == 3:
                return TD()
            elif row_mod in (4, 5):
                return R()
        else:
            if row_mod == 0:
                return TD()
            elif row_mod in (1, 2):
                return R()
            elif row_mod == 3:
                return BU()
            elif row_mod in (4, 5):
                return L()

class HexMapCell(label.Label):
    def __init__(self, row=0, col=0, **kwargs):
        super(HexMapCell, self).__init__(**kwargs)
        self.coords = MapCoords(row, col)

class BU(HexMapCell):
    pass
class TD(HexMapCell):
    pass
class L(HexMapCell):
    pass
class R(HexMapCell):
    pass

class HexMapControlCell(button.Button):
    def __init__(self, hex_bind=None, **kwargs):
        super(HexMapControlCell, self).__init__(**kwargs)
        self.hex_bind = hex_bind
        # self.background_color = random.random(), random.random(), random.random(), 0.1
        # self.background_color = random.random(), random.random(), random.random(), 0.25
        self.background_color = random.random(), random.random(), random.random(), 1
        self.bind(pos=self.reposition_control_cell, size=self.resize_control_cell)

    def reposition_control_cell(self, obj, value):
        # import pdb
        # pdb.set_trace()
        self.pos = self.hex_bind.pos

    def resize_control_cell(self, obj, value):
        self.height = self.hex_bind.height * 2
        self.width = self.hex_bind.width * 2

class StrategyGameApp(app.App):
    def build(self):
        return StrategyGame()

if __name__ == '__main__':
    StrategyGameApp().run()
<|endoftext|>


<commit_before><commit_msg>edits<commit_after><|endoftext|>


<commit_before>#    Copyright 2011 Google Inc.
#
#    Licensed under the Apache License, Version 2.0 (the "License");
#    you may not use this file except in compliance with the License.
#    You may obtain a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.

# "Makefile" replacement to build skia for Windows.
# More info at http://code.google.com/p/skia/wiki/DocRoot

import os
import shutil
import sys

# TODO(epoger): allow caller to override BUILDTYPE
BUILDTYPE = 'Debug'

# TODO(epoger): add special 'all' target
TARGET_CLEAN = 'clean'

SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
OUT_SUBDIR = 'out'
GYP_SUBDIR = 'gyp'

# Simple functions that report what they are doing, and exit(1) on failure.
def cd(path):
    print '> cd %s' % path
    if not os.path.isdir(path):
        print 'directory %s does not exist' % path
        sys.exit(1)
    os.chdir(path)

def rmtree(path):
    print '> rmtree %s' % path
    shutil.rmtree(path, ignore_errors=True)

def mkdirs(path):
    print '> mkdirs %s' % path
    if not os.path.isdir(path):
        os.makedirs(path)

def runcommand(command):
    print '> %s' % command
    if os.system(command):
        sys.exit(1)

def MakeClean():
    """Cross-platform "make clean" operation."""
    cd(SCRIPT_DIR)
    rmtree(OUT_SUBDIR)
    # clean up the directory that XCode (on Mac) creates
    rmtree('xcodebuild')

def CheckWindowsEnvironment():
    """For Windows: check environment variables needed for command-line build.

    If those environment variables are missing, try to set them.
    If environment variables can be set up, this function returns; otherwise,
    it displays an error message and exits.
    """
    # If we already have the proper environment variables, nothing to do here.
    try:
        env_DevEnvDir = os.environ['DevEnvDir']
        return  # found it, so we are done
    except KeyError:
        pass # go on and run the rest of this function

    print ('\nCould not find Visual Studio environment variables.'
           '\nPerhaps you have not yet run vcvars32.bat as described at'
           '\nhttp://msdn.microsoft.com/en-us/library/f2ccy3wt.aspx ?')
    found_path = None
    try:
        possible_path = os.path.abspath(os.path.join(
            os.environ['VS100COMNTOOLS'], os.path.pardir, os.path.pardir,
            'VC', 'bin', 'vcvars32.bat'))
        if os.path.exists(possible_path):
            found_path = possible_path
    except KeyError:
        pass
    if found_path:
        print '\nIt looks like you can run that script at:\n%s' % found_path
    else:
        print '\nUnable to find vcvars32.bat on your system.'
    sys.exit(1)

def MakeWindows(args):
    """For Windows: build as appropriate for the command line arguments.

    parameters:
        args: command line arguments as a list of strings
    """
    CheckWindowsEnvironment()

    # TODO(epoger): what about fixed vs float?
    # TODO(epoger): what about "make" flags (like -j) that Windows doesn't support?

    # Run gyp_skia to prepare Visual Studio projects.
    cd(SCRIPT_DIR)
    runcommand('python gyp_skia')

    # Prepare final output dir into which we will copy all binaries.
    msbuild_working_dir = os.path.join(SCRIPT_DIR, OUT_SUBDIR, GYP_SUBDIR)
    msbuild_output_dir = os.path.join(msbuild_working_dir, BUILDTYPE)
    final_output_dir = os.path.join(SCRIPT_DIR, OUT_SUBDIR, BUILDTYPE)
    mkdirs(final_output_dir)

    for target in args:
        # Check for special-case targets
        if target == TARGET_CLEAN:
            MakeClean()
        else:
            cd(msbuild_working_dir)
            runcommand(
                ('msbuild /nologo /property:Configuration=%s'
                ' /target:%s /verbosity:minimal %s.sln') % (
                    BUILDTYPE, target, target))
            runcommand('xcopy /y %s\* %s' % (
                msbuild_output_dir, final_output_dir))

# main:
# dispatch to appropriate Make<Platform>() variant.
if os.name == 'nt':
    MakeWindows(sys.argv[1:])
    sys.exit(0)
elif os.name == 'posix':
    if sys.platform == 'darwin':
        print 'Mac developers should not run this script; see ' \
            'http://code.google.com/p/skia/wiki/GettingStartedOnMac'
        sys.exit(1)
    elif sys.platform == 'cygwin':
        print 'Windows development on Cygwin is not currently supported; see ' \
            'http://code.google.com/p/skia/wiki/GettingStartedOnWindows'
        sys.exit(1)
    else:
        print 'Unix developers should not run this script; see ' \
            'http://code.google.com/p/skia/wiki/GettingStartedOnLinux'
        sys.exit(1)
else:
    print 'unknown platform (os.name=%s, sys.platform=%s); see %s' % (
        os.name, sys.platform, 'http://code.google.com/p/skia/wiki/DocRoot')
    sys.exit(1)
sys.exit(0)

<commit_msg>Implement remaining options in Windows command-line build (float vs fixed, Debug vs Release, "all" target, etc.) Review URL: http://codereview.appspot.com/4740041<commit_after>#    Copyright 2011 Google Inc.
#
#    Licensed under the Apache License, Version 2.0 (the "License");
#    you may not use this file except in compliance with the License.
#    You may obtain a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.

# "Makefile" replacement to build skia for Windows.
# More info at http://code.google.com/p/skia/wiki/DocRoot
#
# Some usage examples:
#   make clean
#   make tests
#   make bench BUILDTYPE=Release
#   make gm GYP_DEFINES=skia_scalar=fixed BUILDTYPE=Release
#   make all

import os
import shutil
import sys

BUILDTYPE = 'Debug'

# special targets
TARGET_ALL = 'all'
TARGET_CLEAN = 'clean'
LIST_OF_ALL_TARGETS = ['SampleApp', 'bench', 'gm', 'tests', 'tools']

SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
OUT_SUBDIR = 'out'
GYP_SUBDIR = 'gyp'

# Simple functions that report what they are doing, and exit(1) on failure.
def cd(path):
    print '> cd %s' % path
    if not os.path.isdir(path):
        print 'directory %s does not exist' % path
        sys.exit(1)
    os.chdir(path)

def rmtree(path):
    print '> rmtree %s' % path
    shutil.rmtree(path, ignore_errors=True)

def mkdirs(path):
    print '> mkdirs %s' % path
    if not os.path.isdir(path):
        os.makedirs(path)

def runcommand(command):
    print '> %s' % command
    if os.system(command):
        sys.exit(1)

def MakeClean():
    """Cross-platform "make clean" operation."""
    cd(SCRIPT_DIR)
    rmtree(OUT_SUBDIR)
    # clean up the directory that XCode (on Mac) creates
    rmtree('xcodebuild')

def CheckWindowsEnvironment():
    """For Windows: check environment variables needed for command-line build.

    If those environment variables are missing, try to set them.
    If environment variables can be set up, this function returns; otherwise,
    it displays an error message and exits.
    """
    # If we already have the proper environment variables, nothing to do here.
    try:
        env_DevEnvDir = os.environ['DevEnvDir']
        return  # found it, so we are done
    except KeyError:
        pass # go on and run the rest of this function

    print ('\nCould not find Visual Studio environment variables.'
           '\nPerhaps you have not yet run vcvars32.bat as described at'
           '\nhttp://msdn.microsoft.com/en-us/library/f2ccy3wt.aspx ?')
    found_path = None
    try:
        possible_path = os.path.abspath(os.path.join(
            os.environ['VS100COMNTOOLS'], os.path.pardir, os.path.pardir,
            'VC', 'bin', 'vcvars32.bat'))
        if os.path.exists(possible_path):
            found_path = possible_path
    except KeyError:
        pass
    if found_path:
        print '\nIt looks like you can run that script at:\n%s' % found_path
    else:
        print '\nUnable to find vcvars32.bat on your system.'
    sys.exit(1)

def MakeWindows(targets):
    """For Windows: build as appropriate for the command line arguments.

    parameters:
        targets: build targets as a list of strings
    """
    CheckWindowsEnvironment()

    # Run gyp_skia to prepare Visual Studio projects.
    cd(SCRIPT_DIR)
    runcommand('python gyp_skia')

    # Prepare final output dir into which we will copy all binaries.
    msbuild_working_dir = os.path.join(SCRIPT_DIR, OUT_SUBDIR, GYP_SUBDIR)
    msbuild_output_dir = os.path.join(msbuild_working_dir, BUILDTYPE)
    final_output_dir = os.path.join(SCRIPT_DIR, OUT_SUBDIR, BUILDTYPE)
    mkdirs(final_output_dir)

    for target in targets:
        cd(msbuild_working_dir)
        runcommand(
            ('msbuild /nologo /property:Configuration=%s'
            ' /target:%s /verbosity:minimal %s.sln') % (
                BUILDTYPE, target, target))
        runcommand('xcopy /y %s\* %s' % (
            msbuild_output_dir, final_output_dir))

def Make(args):
    """Main function.

    parameters:
        args: command line arguments as a list of strings
    """
    # handle any variable-setting parameters or special targets
    global BUILDTYPE
    targets = []
    for arg in args:
        if arg == TARGET_ALL:
            targets.extend(LIST_OF_ALL_TARGETS)
        elif arg == TARGET_CLEAN:
            MakeClean()
        elif arg.startswith('BUILDTYPE='):
            BUILDTYPE = arg[10:]
        elif arg.startswith('GYP_DEFINES='):
            os.environ['GYP_DEFINES'] = arg[12:]
        else:
            targets.append(arg)

    # if there are no remaining targets, we're done
    if not targets:
        sys.exit(0)

    # dispatch to appropriate Make<Platform>() variant.
    if os.name == 'nt':
        MakeWindows(targets)
        sys.exit(0)
    elif os.name == 'posix':
        if sys.platform == 'darwin':
            print 'Mac developers should not run this script; see ' \
                'http://code.google.com/p/skia/wiki/GettingStartedOnMac'
            sys.exit(1)
        elif sys.platform == 'cygwin':
            print 'Windows development on Cygwin is not currently supported; ' \
                'see http://code.google.com/p/skia/wiki/GettingStartedOnWindows'
            sys.exit(1)
        else:
            print 'Unix developers should not run this script; see ' \
                'http://code.google.com/p/skia/wiki/GettingStartedOnLinux'
            sys.exit(1)
    else:
        print 'unknown platform (os.name=%s, sys.platform=%s); see %s' % (
            os.name, sys.platform, 'http://code.google.com/p/skia/wiki/DocRoot')
        sys.exit(1)
    sys.exit(0)

# main()
Make(sys.argv[1:])

<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import sys
import json
import jinja2
import yaml
import server

def append_path(filename, file_path):
    ''' If a filename starts with './' then it is relative to the config.yml path.
    '''
    if filename.startswith('./'):
        filename = os.path.join(file_path, filename)
    else:
        filename = os.path.join(SDK_PATH, filename)

    return filename

def load_config(config_filename):
    ''' Get the config dictionary from the file 'config.yml' '''

    with open(config_filename) as f:
        config = yaml.load(f)

    return config

def parse_brackets(string):
    ''' ex: 'pwm', '4' = parse_brackets('pwm[4]') '''
    start, end = map(lambda char : string.find(char), ('[', ']'))
    if start >= 0 and end >= 0:
        return string[0 : start], string[start + 1 : end]
    else:
        return string, '1'

def read_parameters(string, parameters):

    string, parameter = parse_brackets(string)

    if parameter.isdigit():
        parameter = int(parameter)
    else:
        assert parameter in parameters
        parameter = parameters[parameter]

    return string, parameter

def build_memory(memory, parameters):

    for address in memory:

        address['name'], address['n_blocks'] = read_parameters(address['name'], parameters)
        assert (address['n_blocks'] > 0)

        # Protection
        if not 'protection' in address:
            address['prot_flag'] = 'PROT_READ|PROT_WRITE'
        elif address['protection'] == 'read':
            address['prot_flag'] = 'PROT_READ'
        elif address['protection'] == 'write':
            address['prot_flag'] = 'PROT_WRITE'

    return memory

def build_registers(registers, parameters):

    new_registers = []

    for register in registers:
        register, parameter = read_parameters(register, parameters)

        if parameter == 1:
            new_registers.append(register)
        else:
            for i in range(parameter):
                new_registers.append(register+str(i))

    registers = new_registers

    return registers

def build_json(dict):
    dict_json = json.dumps(dict, separators=(',', ':')).replace('"', '\\"')
    return dict_json

def dump_if_changed(filename, new_dict):
    changed = False
    if os.path.isfile(filename):
        with open(filename, 'r') as yml_file:
            old_dict = yaml.load(yml_file)
            if old_dict != new_dict:
               changed = True

    if not os.path.isfile(filename) or changed:
        with open(filename, 'w') as yml_file:
            yaml.dump(new_dict, yml_file)

#########################
# Jinja2 template engine
#########################

def get_renderer():
    renderer = jinja2.Environment(
      block_start_string = '{%',
      block_end_string = '%}',
      variable_start_string = '{{',
      variable_end_string = '}}',
      loader = jinja2.FileSystemLoader([os.path.join(SDK_PATH, 'fpga'), os.path.join(SDK_PATH, 'server/templates')])
    )

    def quote(list_):
        return ['"%s"' % element for element in list_]

    def remove_extension(filename):
        toks = filename.split('.')
        return toks[0]

    def replace_KMG(string):
        return string.replace('K', '*1024').replace('M', '*1024*1024').replace('G', '*1024*1024*1024')

    renderer.filters['quote'] = quote
    renderer.filters['remove_extension'] = remove_extension
    renderer.filters['replace_KMG'] = replace_KMG
    return renderer

def fill_template(config, template_filename, output_filename):
    template = get_renderer().get_template(template_filename)
    with open(output_filename, 'w') as output:
        output.write(template.render(config=config))

###################
# Main
###################

SDK_PATH = os.getenv('SDK_PATH', '')

if __name__ == "__main__":

    cmd = sys.argv[1]
    config_filename = sys.argv[2]
    output_filename = sys.argv[3]

    output_dirname = os.path.dirname(output_filename)
    if not os.path.exists(output_dirname):
        os.makedirs(output_dirname)

    config = load_config(config_filename)
    config_path = os.path.dirname(config_filename)

    reload(sys)
    sys.setdefaultencoding('utf-8')

    if cmd == '--name':
        with open(output_filename, 'w') as f:
            f.write(config['name'])

    elif cmd == '--memory_yml':
        for field in ['drivers', 'web', 'cores', 'modules', 'name', 'board']:
            config.pop(field, None)
        dump_if_changed(output_filename, config)

    elif cmd == '--config_tcl':
        parameters = config.get('parameters', {})
        config['memory'] = build_memory(config.get('memory', {}), parameters)
        config['control_registers'] = build_registers(config.get('control_registers', {}), parameters)
        config['status_registers'] = build_registers(config.get('status_registers', {}), parameters)
        fill_template(config, 'config.tcl', output_filename)

    elif cmd == '--start_sh':
        fill_template(config, 'start.sh', output_filename)

    elif cmd == '--cores':

        for module in config.get('modules', []):
            module_path = os.path.dirname(module)
            module = append_path(module, module_path)
            module_config = load_config(module)
            module_cores = module_config.get('cores')
            if module_cores is not None:
                config['cores'].extend(module_cores)
            config['cores'] = list(set(config['cores']))

        for i in range(len(config['cores'])):
            config['cores'][i] = append_path(config['cores'][i], config_path)

        with open(output_filename, 'w') as f:
            f.write(' '.join(config.get('cores', [])))

    elif cmd == '--board':
        config['board'] = append_path(config['board'], config_path)
        with open(output_filename, 'w') as f:
            f.write(config['board'])

    elif cmd == '--drivers':
        for i, path in enumerate(config.get('drivers', [])):
            config['drivers'][i] = append_path(path, config_path)
        with open(output_filename, 'w') as f:
            f.write(' '.join(config.get('drivers', [])))

    elif cmd == '--xdc':
        for i, path in enumerate(config.get('xdc', [])):
            config['xdc'][i] = append_path(path, config_path)
        with open(output_filename, 'w') as f:
            f.write(' '.join(config.get('xdc', [])))

    elif cmd == '--memory_hpp':
        parameters = config.get('parameters', {})
        config['memory'] = build_memory(config.get('memory', {}), parameters)
        config['control_registers'] = build_registers(config.get('control_registers', {}), parameters)
        config['status_registers'] = build_registers(config.get('status_registers', {}), parameters)
        config['json'] = build_json(config)
        fill_template(config, 'memory.hpp', output_filename)

    elif cmd == '--render_template':
        template_filename = sys.argv[4]
        for i in range(len(config['drivers'])):
            config['drivers'][i] = append_path(config['drivers'][i], config_path)
        server.render_template(template_filename, output_filename, server.get_drivers(config['drivers']))

    elif cmd == '--render_interface':
        driver_filename_hpp = sys.argv[4]
        id_ = server.get_driver_id(config['drivers'], driver_filename_hpp)
        server.render_driver(server.get_driver(driver_filename_hpp, id_), output_filename)

    elif cmd == '--web':
        for i, path in enumerate(config.get('web', [])):
            config['web'][i] = append_path(path, config_path)
        with open(output_filename, 'w') as f:
            f.write(' '.join(config.get('web', [])))

    elif cmd == '--version':
        config['version'] = config.get('version', {})
        with open(output_filename, 'w') as f:
            f.write(config['version'])

    else:
        raise ValueError('Unknown command')<commit_msg>fix get version<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import sys
import json
import jinja2
import yaml
import server

def append_path(filename, file_path):
    ''' If a filename starts with './' then it is relative to the config.yml path.
    '''
    if filename.startswith('./'):
        filename = os.path.join(file_path, filename)
    else:
        filename = os.path.join(SDK_PATH, filename)

    return filename

def load_config(config_filename):
    ''' Get the config dictionary from the file 'config.yml' '''

    with open(config_filename) as f:
        config = yaml.load(f)

    return config

def parse_brackets(string):
    ''' ex: 'pwm', '4' = parse_brackets('pwm[4]') '''
    start, end = map(lambda char : string.find(char), ('[', ']'))
    if start >= 0 and end >= 0:
        return string[0 : start], string[start + 1 : end]
    else:
        return string, '1'

def read_parameters(string, parameters):

    string, parameter = parse_brackets(string)

    if parameter.isdigit():
        parameter = int(parameter)
    else:
        assert parameter in parameters
        parameter = parameters[parameter]

    return string, parameter

def build_memory(memory, parameters):

    for address in memory:

        address['name'], address['n_blocks'] = read_parameters(address['name'], parameters)
        assert (address['n_blocks'] > 0)

        # Protection
        if not 'protection' in address:
            address['prot_flag'] = 'PROT_READ|PROT_WRITE'
        elif address['protection'] == 'read':
            address['prot_flag'] = 'PROT_READ'
        elif address['protection'] == 'write':
            address['prot_flag'] = 'PROT_WRITE'

    return memory

def build_registers(registers, parameters):

    new_registers = []

    for register in registers:
        register, parameter = read_parameters(register, parameters)

        if parameter == 1:
            new_registers.append(register)
        else:
            for i in range(parameter):
                new_registers.append(register+str(i))

    registers = new_registers

    return registers

def build_json(dict):
    dict_json = json.dumps(dict, separators=(',', ':')).replace('"', '\\"')
    return dict_json

def dump_if_changed(filename, new_dict):
    changed = False
    if os.path.isfile(filename):
        with open(filename, 'r') as yml_file:
            old_dict = yaml.load(yml_file)
            if old_dict != new_dict:
               changed = True

    if not os.path.isfile(filename) or changed:
        with open(filename, 'w') as yml_file:
            yaml.dump(new_dict, yml_file)

#########################
# Jinja2 template engine
#########################

def get_renderer():
    renderer = jinja2.Environment(
      block_start_string = '{%',
      block_end_string = '%}',
      variable_start_string = '{{',
      variable_end_string = '}}',
      loader = jinja2.FileSystemLoader([os.path.join(SDK_PATH, 'fpga'), os.path.join(SDK_PATH, 'server/templates')])
    )

    def quote(list_):
        return ['"%s"' % element for element in list_]

    def remove_extension(filename):
        toks = filename.split('.')
        return toks[0]

    def replace_KMG(string):
        return string.replace('K', '*1024').replace('M', '*1024*1024').replace('G', '*1024*1024*1024')

    renderer.filters['quote'] = quote
    renderer.filters['remove_extension'] = remove_extension
    renderer.filters['replace_KMG'] = replace_KMG
    return renderer

def fill_template(config, template_filename, output_filename):
    template = get_renderer().get_template(template_filename)
    with open(output_filename, 'w') as output:
        output.write(template.render(config=config))

###################
# Main
###################

SDK_PATH = os.getenv('SDK_PATH', '')

if __name__ == "__main__":

    cmd = sys.argv[1]
    config_filename = sys.argv[2]
    output_filename = sys.argv[3]

    output_dirname = os.path.dirname(output_filename)
    if not os.path.exists(output_dirname):
        os.makedirs(output_dirname)

    config = load_config(config_filename)
    config_path = os.path.dirname(config_filename)

    reload(sys)
    sys.setdefaultencoding('utf-8')

    if cmd == '--name':
        with open(output_filename, 'w') as f:
            f.write(config['name'])

    elif cmd == '--memory_yml':
        for field in ['drivers', 'web', 'cores', 'modules', 'name', 'board']:
            config.pop(field, None)
        dump_if_changed(output_filename, config)

    elif cmd == '--config_tcl':
        parameters = config.get('parameters', {})
        config['memory'] = build_memory(config.get('memory', {}), parameters)
        config['control_registers'] = build_registers(config.get('control_registers', {}), parameters)
        config['status_registers'] = build_registers(config.get('status_registers', {}), parameters)
        fill_template(config, 'config.tcl', output_filename)

    elif cmd == '--start_sh':
        fill_template(config, 'start.sh', output_filename)

    elif cmd == '--cores':

        for module in config.get('modules', []):
            module_path = os.path.dirname(module)
            module = append_path(module, module_path)
            module_config = load_config(module)
            module_cores = module_config.get('cores')
            if module_cores is not None:
                config['cores'].extend(module_cores)
            config['cores'] = list(set(config['cores']))

        for i in range(len(config['cores'])):
            config['cores'][i] = append_path(config['cores'][i], config_path)

        with open(output_filename, 'w') as f:
            f.write(' '.join(config.get('cores', [])))

    elif cmd == '--board':
        config['board'] = append_path(config['board'], config_path)
        with open(output_filename, 'w') as f:
            f.write(config['board'])

    elif cmd == '--drivers':
        for i, path in enumerate(config.get('drivers', [])):
            config['drivers'][i] = append_path(path, config_path)
        with open(output_filename, 'w') as f:
            f.write(' '.join(config.get('drivers', [])))

    elif cmd == '--xdc':
        for i, path in enumerate(config.get('xdc', [])):
            config['xdc'][i] = append_path(path, config_path)
        with open(output_filename, 'w') as f:
            f.write(' '.join(config.get('xdc', [])))

    elif cmd == '--memory_hpp':
        parameters = config.get('parameters', {})
        config['memory'] = build_memory(config.get('memory', {}), parameters)
        config['control_registers'] = build_registers(config.get('control_registers', {}), parameters)
        config['status_registers'] = build_registers(config.get('status_registers', {}), parameters)
        config['json'] = build_json(config)
        fill_template(config, 'memory.hpp', output_filename)

    elif cmd == '--render_template':
        template_filename = sys.argv[4]
        for i in range(len(config['drivers'])):
            config['drivers'][i] = append_path(config['drivers'][i], config_path)
        server.render_template(template_filename, output_filename, server.get_drivers(config['drivers']))

    elif cmd == '--render_interface':
        driver_filename_hpp = sys.argv[4]
        id_ = server.get_driver_id(config['drivers'], driver_filename_hpp)
        server.render_driver(server.get_driver(driver_filename_hpp, id_), output_filename)

    elif cmd == '--web':
        for i, path in enumerate(config.get('web', [])):
            config['web'][i] = append_path(path, config_path)
        with open(output_filename, 'w') as f:
            f.write(' '.join(config.get('web', [])))

    elif cmd == '--version':
        config['version'] = config.get('version', "")
        with open(output_filename, 'w') as f:
            f.write(config['version'])

    else:
        raise ValueError('Unknown command')<|endoftext|>


<commit_before>import subprocess
import os
import logging
from pathlib import Path

def check_direct_include(path: Path):
    if not path.is_file():
        return False
    with path.open("r") as f:
        for line in f:
            line = line.strip().lower()
            if line.startswith("#error"):
                if line.find("do not") >= 0 and \
                                line.find("include") >= 0 and \
                                line.find("directly") >= 0:
                    return False
        return True

class State:
    def __init__(self):
        self.dpdk_path = None
        self.dpdk_headers = None
        self.dpdk_config = None
        self.phase = 1

    def find_dpdk(self):
        if "RTE_SDK" in os.environ:
            path = Path(os.environ["RTE_SDK"])
        else:
            logging.info("RTE_SDK environment variable is not found")
            path = Path(input("{}. Enter DPDK path (install directory): ".format(self.phase)).strip())
            self.phase += 1

        if not path.exists() and not path.is_dir():
            logging.error("Path {} does not exist".format(path))
            return False

        path = path.absolute()
        config_header = path.joinpath("include","rte_config.h")
        if not config_header.exists():
            logging.error("Cannot find rte_config.h")
            return False

        self.dpdk_path = path
        self.dpdk_config = config_header

        logging.info("DPDK is found at {}, config file is {}".format(self.dpdk_path, self.dpdk_config))

        return True

    def make_all_in_one_header(self):
        path = self.dpdk_path
        include_dir = path.joinpath("include")
        headers = set()

        for item in include_dir.iterdir():
            if not item.is_file():
                continue
            if item.suffix != ".h":
                continue
            if item == self.dpdk_config:
                continue
            if not check_direct_include(item):
                continue

            # XXX
            # This should be removed when https://github.com/servo/rust-bindgen/issues/412
            # this issue is fixed.
            if item.name == "rte_thash.h":
                continue
            headers.add(item)

        with open("dpdk.h", "w") as f:
            for header in headers:
                f.write("#include <{}>\n".format(header.name))

        return True

    def generate_rust_def(self):
        rust_src_path = Path("src").joinpath("dpdk.rs")
        dpdk_include_path = self.dpdk_path.joinpath("include")
        try:
            subprocess.check_output(["bindgen", "dpdk.h", "--output", str(rust_src_path),
                                     "--no-unstable-rust",
                                     "--", "-I{}".format(dpdk_include_path), "-imacros", str(self.dpdk_config),
                                     "-march=native"])
        except OSError:
            logging.error("Cannot execute bindgen program")
        except subprocess.CalledProcessError:
            logging.error("bindgen did not exit correctly")

def main():
    state = State()
    if not state.find_dpdk():
        return
    if not state.make_all_in_one_header():
        return
    if not state.generate_rust_def():
        return
    pass

if __name__ == "__main__":
    main()<commit_msg>Works with bindgen 30a4722622883459c87d5de7a5ffae37849805d1<commit_after>import subprocess
import os
import logging
from pathlib import Path

def check_direct_include(path: Path):
    if not path.is_file():
        return False
    with path.open("r") as f:
        for line in f:
            line = line.strip().lower()
            if line.startswith("#error"):
                if line.find("do not") >= 0 and \
                                line.find("include") >= 0 and \
                                line.find("directly") >= 0:
                    return False
        return True

class State:
    def __init__(self):
        self.dpdk_path = None
        self.dpdk_headers = None
        self.dpdk_config = None
        self.phase = 1

    def find_dpdk(self):
        if "RTE_SDK" in os.environ:
            path = Path(os.environ["RTE_SDK"])
        else:
            logging.info("RTE_SDK environment variable is not found")
            path = Path(input("{}. Enter DPDK path (install directory): ".format(self.phase)).strip())
            self.phase += 1

        if not path.exists() and not path.is_dir():
            logging.error("Path {} does not exist".format(path))
            return False

        path = path.absolute()
        config_header = path.joinpath("include","rte_config.h")
        if not config_header.exists():
            logging.error("Cannot find rte_config.h")
            return False

        self.dpdk_path = path
        self.dpdk_config = config_header

        logging.info("DPDK is found at {}, config file is {}".format(self.dpdk_path, self.dpdk_config))

        return True

    def make_all_in_one_header(self):
        path = self.dpdk_path
        include_dir = path.joinpath("include")
        headers = set()

        for item in include_dir.iterdir():
            if not item.is_file():
                continue
            if item.suffix != ".h":
                continue
            if item == self.dpdk_config:
                continue
            if not check_direct_include(item):
                continue
            headers.add(item)

        with open("dpdk.h", "w") as f:
            for header in headers:
                f.write("#include <{}>\n".format(header.name))

        return True

    def generate_rust_def(self):
        rust_src_path = Path("src").joinpath("dpdk.rs")
        dpdk_include_path = self.dpdk_path.joinpath("include")
        try:
            subprocess.check_output(["bindgen", "dpdk.h", "--output", str(rust_src_path),
                                     "--no-unstable-rust",
                                     "--", "-I{}".format(dpdk_include_path), "-imacros", str(self.dpdk_config),
                                     "-march=native"])
        except OSError:
            logging.error("Cannot execute bindgen program")
        except subprocess.CalledProcessError:
            logging.error("bindgen did not exit correctly")

def main():
    state = State()
    if not state.find_dpdk():
        return
    if not state.make_all_in_one_header():
        return
    if not state.generate_rust_def():
        return
    pass

if __name__ == "__main__":
    main()<|endoftext|>


<commit_before>#!/usr/bin/env python
"""Defines the main menu module for a program that inputs a MemberHub directory dump,
a school roster, and a hub map to perform analyses on the MemberHub directory.
"""

import directory_tools
import roster_tools
import hub_map_tools
import import_file_tools
import family
import person

STUDENT_INDICATOR = "+SA/"

def FindMissingEmail(directory):
    """menu.FindMissingEmail
    INPUTS:
    - directory -- list containing the MemberHub directory families
    OUTPUTS:
    Prints to standard output the adults in the directory who do not have an
    email address associated with their entry.
    ASSUMPTIONS:
    None.
    """
    adult_count = no_email_count = 0
    for entry_family in directory:
        for adult in entry_family.adults:
            adult_count += 1
            if adult.DoesNotListEmailAddress():
                print "The entry for this person does not have an email address:",
                adult.Print()
                no_email_count += 1

    print "Found %d out of %d adults with missing email addresses" % \
          (no_email_count, adult_count)

def FindOrphans(directory):
    """menu.FindOrphans
    INPUTS:
    - directory -- list containing the MemberHub directory families
    OUTPUTS:
    Prints to standard output the children in the directory who do not have an
    parent associated with their entry.
    ASSUMPTIONS:
    None.
    """
    family_count = orphan_count = 0

    for entry_family in directory:
        family_count += 1
        if entry_family.IsOrphan():
            print "The entry for this family does not identify parents:",
            entry_family.Print()
            orphan_count += 1

    print "Found %d families without adults out of %d families" % \
          (orphan_count, family_count)

def FindChildless(directory):
    """menu.FindChildless
    INPUTS:
    - directory -- list containing the MemberHub directory families
    OUTPUTS:
    Prints to standard output the adults in the directory who do not have a
    child associated with their entry.
    ASSUMPTIONS:
    None.
    """
    family_count = childless_count = 0

    for entry_family in directory:
        family_count += 1
        if entry_family.IsChildless():
            print "The entry for this family does not identify children:",
            entry_family.Print()
            childless_count += 1

    print "Found %d families without children out of %d families" % \
          (childless_count, family_count)

def FindHubless(arg_list):
    """menu.FindHubless
    INPUTS:
    - directory -- list containing the MemberHub directory families
    - map_d     -- dictionary mapping teacher names to hub IDs
    OUTPUTS:
    Prints to standard output the names in the directory who are not members of
    at least one classroom hub.
    ASSUMPTIONS:
    None.
    """
    directory = arg_list[0]
    map_d     = arg_list[1]
    hubless   = []

    child_count = adult_count = 0

    for directory_family in directory:
        for adult in directory_family.adults:
            if not hub_map_tools.IsAnyHubClassroomHub(map_d, adult.hubs):
                print "Found adult not in a classroom hub.  Current hubs = (%s).  Name = " % adult.hubs,
                adult.Print()
                adult_count += 1
                hubless.append(adult)

        for child in directory_family.children:
            if not hub_map_tools.IsAnyHubClassroomHub(map_d, child.hubs):
                print "Found child not in a classroom hub.  Current hubs =  (%s).  Name = " % child.hubs,
                child.Print()
                child_count += 1
                hubless.append(child)

    print "Found %d children who are not in a classroom hub." % child_count
    print "Found %d adults who are not in at least one classroom hub." % adult_count

    return hubless

def PrintHubless(arg_list):
    discard = FindHubless(arg_list)

def MakeImportForHubless(arg_list):
    """menu.MakeImportForHubless
    INPUTS:
    - directory -- dictionary containing the MemberHub directory
    - roster    -- dictionary containing the school roster
    - map_d     -- dictionary mapping teacher names to hub IDs
    OUTPUTS:
    Prints to standard output the names in the directory who are not members of
    at least one classroom hub.
    Creates a comma-separated text file that can be imported into MemberHub to assign
    hub IDs to existing directory entries.
    ASSUMPTIONS:
    None.
    """
    directory   = arg_list[0]
    map_d       = arg_list[1]
    roster      = arg_list[2]
    hubless     = FindHubless(arg_list)
    update_hubs = []

    hubed_count = hubless_count = 0

    for hubless_person in hubless:
        for roster_family in roster:
            found_person = roster_family.FindPersonInFamily(hubless_person)
            if not found_person == None:
                hubless_person.hubs = found_person.hubs
                update_hubs.append(hubless_person)
                hubed_count += 1
                break
        else:
            print "Did not find match for this person in the roster:",
            hubless_person.Print()
            hubless_count += 1

    print "Processed %d entries that were not in any classroom hub." % len(hubless)
    print "Was able to find classroom hubs for %d entries." % hubed_count
    print "Was not able to find classroom hubs for %d entries." % hubless_count

    import_file_tools.CreateHublessImportFile(update_hubs)

def FindEntriless(arg_list):
    """menu.FindEntriless
    INPUTS:
    - directory -- list containing the MemberHub directory families
    - roster    -- list containing the school roster families
    OUTPUTS:
    - entriless -- returns list of families in the school roster that could not
                   be found in the directory
    Also prints to standard output the names in the school roster who are not in the
    MemberHub directory.
    ASSUMPTIONS:
    None.
    """
    directory = arg_list[0]
    roster    = arg_list[1]
    entriless = []

    for roster_family in roster:

        for directory_family in directory:
            if directory_family.IsSameFamily(roster_family):
                if directory_family.HasNewChildren(roster_family):
                    temp_family = family.Family()
                    temp_family.FormFamilyWithNewChildren(directory_family,roster_family)
                    print "Found family in directory with new child in roster:",
                    temp_family.Print()
                    entriless.append(temp_family)
                break

        else:
            print "Did not find this family from the roster in the directory:",
            roster_family.Print()
            entriless.append(roster_family)

    print "Found %d people on the roster who were not in the directory" % len(entriless)
    return entriless

def PrintNotInDirectory(arg_list):
    discard = FindEntriless(arg_list)

def MakeImportNotInDirectory(arg_list):
    """menu.MakeImportNotInDirectory
    INPUTS:
    - directory -- dictionary containing the MemberHub directory
    - roster    -- dictionary containing the school roster
    - map_d     -- dictionary mapping teacher names to hub IDs
    OUTPUTS:
    Creates a comma-separated text file that can be imported into MemberHub to create
    directory entries for people who are in the roster, but not already in the directory.
    Includes hub ID assignments for these people.
    ASSUMPTIONS:
    None.
    """
    directory = arg_list[0]
    roster    = arg_list[1]
    map_d     = arg_list[2]
    entriless = FindEntriless(arg_list)

    import_file_tools.CreateNewMemberImport(entriless)

def MakeStudentImportFile(arg_list):
    """menu.MakeStudentImportFile
    INPUTS:
    - directory -- dictionary containing the MemberHub directory
    - roster    -- dictionary containing the school roster
    OUTPUTS:
    Creates a comma-separated text file that can be imported into MemberHub to create
    directory entries for people who are in the roster, but not already in the directory.
    Includes hub ID assignments for these people.
    ASSUMPTIONS:
    None.
    """
    directory = arg_list[0]
    roster    = arg_list[1]
    students  = []
    not_found = []

    ## For each family in the roster ...
    for roster_family in roster:
        ## ...find the corresponding family in the directory
        for directory_family in directory:
            if directory_family.IsSameFamily(roster_family):
                ## For each child in the roster family...
                for roster_child in roster_family.children:
                    ## ...find the corresponding child in the directory family
                    directory_child = directory_family.FindChildInFamily(roster_child)
                    if directory_child != None:
                        ## instantiate a new Directory Person object, and copy the directory child into it
                        temp_child = person.DirectoryPerson()
                        temp_child = directory_child
                        ## clear the temporary object's hubs
                        temp_child.hubs = []
                        ## populate the temporary object's hubs with the roster child's hubs
                        ## modified with the student indicator appended
                        ## TBD - is student_hub a necessary step?
                        student_hub = roster_child.hubs[0] + STUDENT_INDICATOR
                        temp_child.hubs.append(student_hub)
                        ## add the temporary child object to the list of students
                        students.append(temp_child)
                    else:
                        print "##################"
                        print "Did not find this child",
                        roster_child.Print()
                        print " in the family: "
                        directory_family.Print()
                        not_found.append(roster_child)
                ## Found the roster family in the directory, so break out of the directory_family loop
                break
        else:
            print "Did not find this family from the roster in the directory:",
            roster_family.Print()
            not_found.append(roster_family.children)

    print "Found %d students on the roster who were in the directory" % len(students)
    print "%d students on the roster could not be matched with the directory" % len(not_found)

    ## Create an import file with all the students
    import_file_tools.CreateHublessImportFile(students)

def MakePrompt(choices):
    choice_list = sorted(choices)
    guts = '\n'.join(['(%s)%s' % (choice[0], choice[1:])
                      for choice in choice_list])
    return 'Choose:\n' + guts + '\nOr press <enter> to quit '

def RunMenu(directory, roster, map_d):
    """Runs the user interface for dictionary manipulation."""
    # The choices dictionary has function names for values.
    choices = {'1 - Find Missing Email':
                    {'Function':FindMissingEmail,'Arg':directory},
               '2 - Find Orphans':
                    {'Function':FindOrphans,'Arg':directory},
               '3 - Find Childless':
                    {'Function':FindChildless,'Arg':directory},
               '4 - Find Not In Classroom Hub':
                    {'Function':PrintHubless,'Arg':[directory,map_d]},
               '5 - Make Import File for Not In Classroom Hub':
                    {'Function':MakeImportForHubless,'Arg':[directory,map_d,roster]},
               '6 - Find Not in Directory':
                    {'Function':PrintNotInDirectory,'Arg':[directory,roster]},
               '7 - Make Import File for Not In Directory':
                    {'Function':MakeImportNotInDirectory,'Arg':[directory,roster,map_d]},
               '8 - Make Student Hub Population Import File':
                    {'Function':MakeStudentImportFile,'Arg':[directory,roster]}}

    prompt = MakePrompt(choices)

    while True:
        raw_choice = raw_input(prompt)
        if not raw_choice:
            break
        given_choice = raw_choice[0].lower()
        for maybe_choice in choices:
            if maybe_choice[0] == given_choice:
                # The appropriate function is called
                # using the dictionary value for the name
                # of the function.
                choices[maybe_choice]['Function'](choices[maybe_choice]['Arg'])
                break
        else:
            print '%s is not an acceptible choice.' % raw_choice

def main():
    directory = directory_tools.ReadDirectory()
    roster    = roster_tools.ReadRoster()
    map_d     = hub_map_tools.ReadMap()
    RunMenu(directory, roster, map_d)

if __name__ == '__main__':
    main()
<commit_msg>remove trailing "/"<commit_after>#!/usr/bin/env python
"""Defines the main menu module for a program that inputs a MemberHub directory dump,
a school roster, and a hub map to perform analyses on the MemberHub directory.
"""

import directory_tools
import roster_tools
import hub_map_tools
import import_file_tools
import family
import person

STUDENT_INDICATOR = "+SA"

def FindMissingEmail(directory):
    """menu.FindMissingEmail
    INPUTS:
    - directory -- list containing the MemberHub directory families
    OUTPUTS:
    Prints to standard output the adults in the directory who do not have an
    email address associated with their entry.
    ASSUMPTIONS:
    None.
    """
    adult_count = no_email_count = 0
    for entry_family in directory:
        for adult in entry_family.adults:
            adult_count += 1
            if adult.DoesNotListEmailAddress():
                print "The entry for this person does not have an email address:",
                adult.Print()
                no_email_count += 1

    print "Found %d out of %d adults with missing email addresses" % \
          (no_email_count, adult_count)

def FindOrphans(directory):
    """menu.FindOrphans
    INPUTS:
    - directory -- list containing the MemberHub directory families
    OUTPUTS:
    Prints to standard output the children in the directory who do not have an
    parent associated with their entry.
    ASSUMPTIONS:
    None.
    """
    family_count = orphan_count = 0

    for entry_family in directory:
        family_count += 1
        if entry_family.IsOrphan():
            print "The entry for this family does not identify parents:",
            entry_family.Print()
            orphan_count += 1

    print "Found %d families without adults out of %d families" % \
          (orphan_count, family_count)

def FindChildless(directory):
    """menu.FindChildless
    INPUTS:
    - directory -- list containing the MemberHub directory families
    OUTPUTS:
    Prints to standard output the adults in the directory who do not have a
    child associated with their entry.
    ASSUMPTIONS:
    None.
    """
    family_count = childless_count = 0

    for entry_family in directory:
        family_count += 1
        if entry_family.IsChildless():
            print "The entry for this family does not identify children:",
            entry_family.Print()
            childless_count += 1

    print "Found %d families without children out of %d families" % \
          (childless_count, family_count)

def FindHubless(arg_list):
    """menu.FindHubless
    INPUTS:
    - directory -- list containing the MemberHub directory families
    - map_d     -- dictionary mapping teacher names to hub IDs
    OUTPUTS:
    Prints to standard output the names in the directory who are not members of
    at least one classroom hub.
    ASSUMPTIONS:
    None.
    """
    directory = arg_list[0]
    map_d     = arg_list[1]
    hubless   = []

    child_count = adult_count = 0

    for directory_family in directory:
        for adult in directory_family.adults:
            if not hub_map_tools.IsAnyHubClassroomHub(map_d, adult.hubs):
                print "Found adult not in a classroom hub.  Current hubs = (%s).  Name = " % adult.hubs,
                adult.Print()
                adult_count += 1
                hubless.append(adult)

        for child in directory_family.children:
            if not hub_map_tools.IsAnyHubClassroomHub(map_d, child.hubs):
                print "Found child not in a classroom hub.  Current hubs =  (%s).  Name = " % child.hubs,
                child.Print()
                child_count += 1
                hubless.append(child)

    print "Found %d children who are not in a classroom hub." % child_count
    print "Found %d adults who are not in at least one classroom hub." % adult_count

    return hubless

def PrintHubless(arg_list):
    discard = FindHubless(arg_list)

def MakeImportForHubless(arg_list):
    """menu.MakeImportForHubless
    INPUTS:
    - directory -- dictionary containing the MemberHub directory
    - roster    -- dictionary containing the school roster
    - map_d     -- dictionary mapping teacher names to hub IDs
    OUTPUTS:
    Prints to standard output the names in the directory who are not members of
    at least one classroom hub.
    Creates a comma-separated text file that can be imported into MemberHub to assign
    hub IDs to existing directory entries.
    ASSUMPTIONS:
    None.
    """
    directory   = arg_list[0]
    map_d       = arg_list[1]
    roster      = arg_list[2]
    hubless     = FindHubless(arg_list)
    update_hubs = []

    hubed_count = hubless_count = 0

    for hubless_person in hubless:
        for roster_family in roster:
            found_person = roster_family.FindPersonInFamily(hubless_person)
            if not found_person == None:
                hubless_person.hubs = found_person.hubs
                update_hubs.append(hubless_person)
                hubed_count += 1
                break
        else:
            print "Did not find match for this person in the roster:",
            hubless_person.Print()
            hubless_count += 1

    print "Processed %d entries that were not in any classroom hub." % len(hubless)
    print "Was able to find classroom hubs for %d entries." % hubed_count
    print "Was not able to find classroom hubs for %d entries." % hubless_count

    import_file_tools.CreateHublessImportFile(update_hubs)

def FindEntriless(arg_list):
    """menu.FindEntriless
    INPUTS:
    - directory -- list containing the MemberHub directory families
    - roster    -- list containing the school roster families
    OUTPUTS:
    - entriless -- returns list of families in the school roster that could not
                   be found in the directory
    Also prints to standard output the names in the school roster who are not in the
    MemberHub directory.
    ASSUMPTIONS:
    None.
    """
    directory = arg_list[0]
    roster    = arg_list[1]
    entriless = []

    for roster_family in roster:

        for directory_family in directory:
            if directory_family.IsSameFamily(roster_family):
                if directory_family.HasNewChildren(roster_family):
                    temp_family = family.Family()
                    temp_family.FormFamilyWithNewChildren(directory_family,roster_family)
                    print "Found family in directory with new child in roster:",
                    temp_family.Print()
                    entriless.append(temp_family)
                break

        else:
            print "Did not find this family from the roster in the directory:",
            roster_family.Print()
            entriless.append(roster_family)

    print "Found %d people on the roster who were not in the directory" % len(entriless)
    return entriless

def PrintNotInDirectory(arg_list):
    discard = FindEntriless(arg_list)

def MakeImportNotInDirectory(arg_list):
    """menu.MakeImportNotInDirectory
    INPUTS:
    - directory -- dictionary containing the MemberHub directory
    - roster    -- dictionary containing the school roster
    - map_d     -- dictionary mapping teacher names to hub IDs
    OUTPUTS:
    Creates a comma-separated text file that can be imported into MemberHub to create
    directory entries for people who are in the roster, but not already in the directory.
    Includes hub ID assignments for these people.
    ASSUMPTIONS:
    None.
    """
    directory = arg_list[0]
    roster    = arg_list[1]
    map_d     = arg_list[2]
    entriless = FindEntriless(arg_list)

    import_file_tools.CreateNewMemberImport(entriless)

def MakeStudentImportFile(arg_list):
    """menu.MakeStudentImportFile
    INPUTS:
    - directory -- dictionary containing the MemberHub directory
    - roster    -- dictionary containing the school roster
    OUTPUTS:
    Creates a comma-separated text file that can be imported into MemberHub to create
    directory entries for people who are in the roster, but not already in the directory.
    Includes hub ID assignments for these people.
    ASSUMPTIONS:
    None.
    """
    directory = arg_list[0]
    roster    = arg_list[1]
    students  = []
    not_found = []

    ## For each family in the roster ...
    for roster_family in roster:
        ## ...find the corresponding family in the directory
        for directory_family in directory:
            if directory_family.IsSameFamily(roster_family):
                ## For each child in the roster family...
                for roster_child in roster_family.children:
                    ## ...find the corresponding child in the directory family
                    directory_child = directory_family.FindChildInFamily(roster_child)
                    if directory_child != None:
                        ## instantiate a new Directory Person object, and copy the directory child into it
                        temp_child = person.DirectoryPerson()
                        temp_child = directory_child
                        ## clear the temporary object's hubs
                        temp_child.hubs = []
                        ## populate the temporary object's hubs with the roster child's hubs
                        ## modified with the student indicator appended
                        ## TBD - is student_hub a necessary step?
                        student_hub = roster_child.hubs[0] + STUDENT_INDICATOR
                        temp_child.hubs.append(student_hub)
                        ## add the temporary child object to the list of students
                        students.append(temp_child)
                    else:
                        print "##################"
                        print "Did not find this child",
                        roster_child.Print()
                        print " in the family: "
                        directory_family.Print()
                        not_found.append(roster_child)
                ## Found the roster family in the directory, so break out of the directory_family loop
                break
        else:
            print "Did not find this family from the roster in the directory:",
            roster_family.Print()
            not_found.append(roster_family.children)

    print "Found %d students on the roster who were in the directory" % len(students)
    print "%d students on the roster could not be matched with the directory" % len(not_found)

    ## Create an import file with all the students
    import_file_tools.CreateHublessImportFile(students)

def MakePrompt(choices):
    choice_list = sorted(choices)
    guts = '\n'.join(['(%s)%s' % (choice[0], choice[1:])
                      for choice in choice_list])
    return 'Choose:\n' + guts + '\nOr press <enter> to quit '

def RunMenu(directory, roster, map_d):
    """Runs the user interface for dictionary manipulation."""
    # The choices dictionary has function names for values.
    choices = {'1 - Find Missing Email':
                    {'Function':FindMissingEmail,'Arg':directory},
               '2 - Find Orphans':
                    {'Function':FindOrphans,'Arg':directory},
               '3 - Find Childless':
                    {'Function':FindChildless,'Arg':directory},
               '4 - Find Not In Classroom Hub':
                    {'Function':PrintHubless,'Arg':[directory,map_d]},
               '5 - Make Import File for Not In Classroom Hub':
                    {'Function':MakeImportForHubless,'Arg':[directory,map_d,roster]},
               '6 - Find Not in Directory':
                    {'Function':PrintNotInDirectory,'Arg':[directory,roster]},
               '7 - Make Import File for Not In Directory':
                    {'Function':MakeImportNotInDirectory,'Arg':[directory,roster,map_d]},
               '8 - Make Student Hub Population Import File':
                    {'Function':MakeStudentImportFile,'Arg':[directory,roster]}}

    prompt = MakePrompt(choices)

    while True:
        raw_choice = raw_input(prompt)
        if not raw_choice:
            break
        given_choice = raw_choice[0].lower()
        for maybe_choice in choices:
            if maybe_choice[0] == given_choice:
                # The appropriate function is called
                # using the dictionary value for the name
                # of the function.
                choices[maybe_choice]['Function'](choices[maybe_choice]['Arg'])
                break
        else:
            print '%s is not an acceptible choice.' % raw_choice

def main():
    directory = directory_tools.ReadDirectory()
    roster    = roster_tools.ReadRoster()
    map_d     = hub_map_tools.ReadMap()
    RunMenu(directory, roster, map_d)

if __name__ == '__main__':
    main()
<|endoftext|>