Source code for inginious.common.base

# -*- coding: utf-8 -*-
#
# This file is part of INGInious. See the LICENSE and the COPYRIGHTS files for
# more information about the licensing of this file.

""" Basic dependencies for every modules that uses INGInious """
import codecs
import json
import os.path
import hashlib
import re

import inginious.common.custom_yaml
from collections import OrderedDict


[docs]def id_checker(id_to_test): """Checks if a id is correct""" return bool(re.match(r'[a-z0-9\-\._]+$', id_to_test, re.IGNORECASE))
[docs]def id_checker_tests(id_to_test): """Checks if a id is correct""" return bool(re.match(r'[a-z0-9\-\._*]+$', id_to_test, re.IGNORECASE))
[docs]def load_json_or_yaml(file_path): """ Load JSON or YAML depending on the file extension. Returns a dict """ with open(file_path, "r") as f: if os.path.splitext(file_path)[1] == ".json": return json.load(f) else: return inginious.common.custom_yaml.load(f)
[docs]def loads_json_or_yaml(file_path, content): """ Load JSON or YAML depending on the file extension. Returns a dict """ if os.path.splitext(file_path)[1] == ".json": return json.loads(content) else: return inginious.common.custom_yaml.load(content)
[docs]def write_json_or_yaml(file_path, content): """ Write JSON or YAML depending on the file extension. """ with codecs.open(file_path, "w", "utf-8") as f: f.write(get_json_or_yaml(file_path, content))
[docs]def get_json_or_yaml(file_path, content): """ Generate JSON or YAML depending on the file extension. """ if os.path.splitext(file_path)[1] == ".json": return json.dumps(content, sort_keys=False, indent=4, separators=(',', ': ')) else: return inginious.common.custom_yaml.dump(content)
[docs]def hash_file(fileobj): """ :param fileobj: a file object :return: a hash of the file content """ hasher = hashlib.md5() buf = fileobj.read(65536) while len(buf) > 0: hasher.update(buf) buf = fileobj.read(65536) return hasher.hexdigest()
[docs]def directory_content_with_hash(directory): """ :param directory: directory in which the function list the files :return: dict in the form {file: (hash of the file, stat of the file)} """ output = {} for root, _, filenames in os.walk(directory): for filename in filenames: p = os.path.join(root, filename) file_stat = os.stat(p) with open(p, 'rb') as f: output[os.path.relpath(p, directory)] = (hash_file(f), file_stat.st_mode) return output
[docs]def directory_compare_from_hash(from_directory, to_directory): """ :param from_directory: dict in the form {file: (hash of the file, stat of the file)} from directory_content_with_hash :param to_directory: dict in the form {file: (hash of the file, stat of the file)} from directory_content_with_hash :return: a tuple containing two list: the files that should be uploaded to "to_directory" and the files that should be removed from "to_directory" """ from_directory = dict( [(os.path.normpath(path), (filehash, stat)) for path, (filehash, stat) in from_directory.items()]) to_directory = dict([(os.path.normpath(path), (filehash, stat)) for path, (filehash, stat) in to_directory.items()]) to_upload = [] to_delete = [] for path, (filehash, stat) in from_directory.items(): if not path in to_directory or to_directory[path] != (filehash, stat): to_upload.append(path) for path in to_directory: if path not in from_directory: to_delete.append(path) return (to_upload, to_delete)
[docs]def dict_from_prefix(prefix, dictionary): """ >>> from collections import OrderedDict >>> od = OrderedDict() >>> od["problem[q0][a]"]=1 >>> od["problem[q0][b][c]"]=2 >>> od["problem[q1][first]"]=1 >>> od["problem[q1][second]"]=2 >>> dict_from_prefix("problem",od) OrderedDict([('q0', OrderedDict([('a', 1), ('b', OrderedDict([('c', 2)]))])), ('q1', OrderedDict([('first', 1), ('second', 2)]))]) """ o_dictionary = OrderedDict() for key, val in dictionary.items(): if key.startswith(prefix): o_dictionary[key[len(prefix):].strip()] = val dictionary = o_dictionary if len(dictionary) == 0: return None elif len(dictionary) == 1 and "" in dictionary: return dictionary[""] else: return_dict = OrderedDict() for key, val in dictionary.items(): ret = re.search(r"^\[([^\]]+)\](.*)$", key) if ret is None: continue return_dict[ret.group(1)] = dict_from_prefix("[{}]".format(ret.group(1)), dictionary) return return_dict