def check_attributes_yml(vctx, repo, path, tree, access_kinds): # type: (ValidationContext, Repo_ish, Text, Any, List[Text]) -> None """ This function reads the .attributes.yml file and checks that each item for each header is a string Example:: # this validates unenrolled: - test1.pdf student: - test2.pdf # this does not validate unenrolled: - test1.pdf student: - test2.pdf - 42 """ from course.content import get_true_repo_and_path true_repo, path = get_true_repo_and_path(repo, path) # {{{ analyze attributes file try: dummy, attr_blob_sha = tree[ATTRIBUTES_FILENAME.encode()] except KeyError: # no .attributes.yml here pass else: from relate.utils import dict_to_struct from yaml import load as load_yaml att_yml = dict_to_struct(load_yaml(true_repo[attr_blob_sha].data)) if path: loc = path + "/" + ATTRIBUTES_FILENAME else: loc = ATTRIBUTES_FILENAME validate_struct(vctx, loc, att_yml, required_attrs=[], allowed_attrs=[(role, list) for role in access_kinds]) if hasattr(att_yml, "public"): vctx.add_warning(loc, _("Access class 'public' is deprecated. Use 'unenrolled' " "instead.")) if hasattr(att_yml, "public") and hasattr(att_yml, "unenrolled"): raise ValidationError( _("%s: access classes 'public' and 'unenrolled' may not " "exist simultaneously.") % (loc)) for access_kind in access_kinds: if hasattr(att_yml, access_kind): for i, l in enumerate(getattr(att_yml, access_kind)): if not isinstance(l, six.string_types): raise ValidationError( "%s: entry %d in '%s' is not a string" % (loc, i+1, access_kind)) # }}} # {{{ analyze gitignore gitignore_lines = [] # type: List[Text] try: dummy, gitignore_sha = tree[b".gitignore"] except KeyError: # no .attributes.yml here pass else: gitignore_lines = true_repo[gitignore_sha].data.decode("utf-8").split("\n") # }}} import stat from fnmatch import fnmatchcase for entry in tree.items(): entry_name = entry.path.decode("utf-8") if any(fnmatchcase(entry_name, line) for line in gitignore_lines): continue if path: subpath = path+"/"+entry_name else: subpath = entry_name if stat.S_ISDIR(entry.mode): dummy, blob_sha = tree[entry.path] subtree = true_repo[blob_sha] check_attributes_yml(vctx, true_repo, subpath, subtree, access_kinds)
def check_attributes_yml(vctx, repo, path, tree): """ This function reads the .attributes.yml file and checks that each item for each header is a string att_roles : list list of acceptable access types Example:: # this validates unenrolled: - test1.pdf student: - test2.pdf # this does not validate unenrolled: - test1.pdf student: - test2.pdf - 42 """ from course.content import get_true_repo_and_path repo, path = get_true_repo_and_path(repo, path) try: dummy, attr_blob_sha = tree[b".attributes.yml"] except KeyError: # no .attributes.yml here pass else: from relate.utils import dict_to_struct from yaml import load as load_yaml att_yml = dict_to_struct(load_yaml(repo[attr_blob_sha].data)) loc = path + "/" + ".attributes.yml" att_roles = ["public", "in_exam", "student", "ta", "unenrolled", "instructor"] validate_struct(vctx, loc, att_yml, required_attrs=[], allowed_attrs=[(role, list) for role in att_roles]) if hasattr(att_yml, "public"): vctx.add_warning(loc, _("Access class 'public' is deprecated. Use 'unenrolled' " "instead.")) if hasattr(att_yml, "public") and hasattr(att_yml, "unenrolled"): raise ValidationError( _("%s: access classes 'public' and 'unenrolled' may not " "exist simultaneously.") % (loc) ) for access_kind in att_roles: if hasattr(att_yml, access_kind): for i, l in enumerate(getattr(att_yml, access_kind)): if not isinstance(l, six.string_types): raise ValidationError("%s: entry %d in '%s' is not a string" % (loc, i + 1, access_kind)) import stat for entry in tree.items(): if stat.S_ISDIR(entry.mode): dummy, blob_sha = tree[entry.path] subtree = repo[blob_sha] check_attributes_yml(vctx, repo, path + "/" + entry.path.decode("utf-8"), subtree)