示例#1
0
def create_config_if_needed():
    """
    If no configuration file exists, create the default configuration file.

    Note that this will not download the initial tutorial set.

    """
    from tutorlib.config.configuration import config_exists, save_config
    from tutorlib.config.namespaces import Namespace

    if not config_exists():
        print('Creating default config...', end='', flush=True)

        default_config = Namespace(**DEFAULT_CONFIG)
        save_config(default_config)

        print('done')
示例#2
0
def write_tutorial_hashes(f, path):
    """
    Create the tutorial hashes file for the tutorial package in the given
    destination directory.

    It is assumed that destination_dir contains a valid tutorial package.
    As a result, this function must only be called after the package itself
    has been created.

    Args:
      f (file): The file to write the tutorial hashes data to.
      path (str): The path to the tutorial package.

    """
    options = Namespace(tut_dir=path, ans_dir='/tmp/notreal')
    tutorial_package = TutorialPackage(path, options)

    tutorial_package_name = tutorial_package.name.replace(' ', '_')

    for problem_set in tutorial_package.problem_sets:
        date_obj = datetime.strptime(problem_set.date, INPUT_DATE_FORMAT)
        date_obj = date_obj.replace(hour=DUE_DATE_HOUR)

        date_obj -= TIMEZONE_OFFSET  # reverse timezone offset

        due_date_str = date_obj.strftime(DATE_FORMAT)

        problem_set_name = problem_set.name.replace(' ', '_')

        for tutorial in problem_set:
            b32hash = base64.b32encode(tutorial.hash).decode('utf8')
            tutorial_name = tutorial.name.replace(' ', '_')

            data = [
                b32hash,
                due_date_str,
                tutorial_package_name,
                problem_set_name,
                tutorial_name,
            ]
            f.write(' '.join(data) + '\n')
示例#3
0
def get_tutorial_package(path):
    options = Namespace(tut_dir=path, ans_dir='/tmp/notreal')
    return TutorialPackage(os.path.basename(path), options)
示例#4
0
def load_config():
    """
    Load the MyPyTutor configuration file.

    If the file does not exist, cannot be opened, or cannot be parsed, then
    revert to using default configuration values.

    If the config file can be opened and parsed, but is missing any default
    configuration value, revert to using that value for the relevant key.

    All values will be unwrapped (and so converted to the appropriate format,
    according to the SPECIAL_FORMATS module variable).

    Returns:
      A Namespace mapping configuration sections to a Namespace mapping
      section options to values.

      For example, if the configuration file looks like this:

          [section_name]
          key1 = value

      Then the attribute `result.section_name.key1` will equal `value`.

    """
    # parse the config file
    parser = configparser.ConfigParser()

    try:
        with open(CONFIG_FILE, 'rU') as f:
            parser.read_file(f)
    except (IOError, FileNotFoundError, configparser.ParsingError):
        # ignore parsing errors - we will just revert to defaults
        pass

    # transform this to a more useful format
    # this involves hard-coding the keys, but that would have to happen in some
    # place to *use* them anyway
    defaults = {
        'online': {
            'store_credentials': '1',
            'username': '',
        },
        'resolution': {
            'height': '800',
            'width': '600',
        },
        'tutorials': {
            'names': '',
            'default': '',
        },
    }

    cfg_dict = defaults

    # add in all parsed config values
    for section in parser.sections():
        if section not in defaults:
            defaults[section] = {}

        for option in parser.options(section):
            cfg_dict[section][option] = parser.get(section, option)

    # our final step is 'unwrapping' values
    # this handles non-standard config formats, such as lists
    # (side note: this is why it would have been better to use json)
    cfg_dict = {
        section: {
            option: unwrap_value(section, option, value)
            for option, value in options.items()
        }
        for section, options in cfg_dict.items()
    }

    return Namespace(**cfg_dict)