CAT-SOOP is a flexible, programmable learning management system based on the Python programming language. https://catsoop.mit.edu
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

119 lines
3.6 KiB

  1. # This file is part of CAT-SOOP
  2. # Copyright (c) 2011-2020 by The CAT-SOOP Developers <catsoop-dev@mit.edu>
  3. #
  4. # This program is free software: you can redistribute it and/or modify it under
  5. # the terms of the GNU Affero General Public License as published by the Free
  6. # Software Foundation, either version 3 of the License, or (at your option) any
  7. # later version.
  8. #
  9. # This program is distributed in the hope that it will be useful, but WITHOUT
  10. # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  11. # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  12. # details.
  13. #
  14. # You should have received a copy of the GNU Affero General Public License
  15. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. """
  17. Utility functions related to user management)
  18. """
  19. import os
  20. import sys
  21. import traceback
  22. from . import loader
  23. def _hide(n):
  24. return n[0] in ("_", ".") or not n.endswith(".py")
  25. def users_dir(context, course):
  26. """
  27. Determine the location of the given course's `__USERS__` directory on disk.
  28. **Parameters:**
  29. * `context`: the context associated with this request
  30. * `course`: the name of the course, as a string
  31. **Returns:** a string containing the location of the given course's
  32. `__USERS__` directory.
  33. """
  34. root = context["cs_data_root"]
  35. return os.path.join(root, "courses", course, "__USERS__")
  36. def list_all_users(context, course):
  37. """
  38. List all the users in a course
  39. **Parameters:**
  40. * `context`: the context associated with this request
  41. * `course`: the name of the course, as a string
  42. **Returns:** a list of the usernames of all users in the course
  43. """
  44. usrdir = users_dir(context, course)
  45. return [i.rsplit(".", 1)[0] for i in os.listdir(usrdir) if not _hide(i)]
  46. def read_user_file(context, course, user, default={}):
  47. """
  48. Retrieve the contents of a given user's `__USERS__` file within a course.
  49. **Parameters:**
  50. * `context`: the context associated with this request
  51. * `course`: the name of the course, as a string
  52. * `user: the name of a user, as a string
  53. **Optional Parameters:**
  54. * `default` (default `{}`): values to be included in the returned
  55. dictionary if the given user does not have a
  56. `__USERS__` file
  57. **Returns:** a dictionary containing the variables defined in the given
  58. user's file
  59. """
  60. user_file = os.path.join(users_dir(context, course), "%s.py" % user)
  61. uinfo = dict(default)
  62. try:
  63. with open(user_file) as f:
  64. exec(f.read(), uinfo)
  65. uinfo["username"] = user
  66. uinfo["_load_ok"] = True
  67. except:
  68. uinfo["_load_ok"] = False
  69. uinfo["_load_exception"] = traceback.format_exception(*sys.exc_info())
  70. loader.clean_builtins(uinfo)
  71. return uinfo
  72. def all_users_info(context, course, filter_func=lambda uinfo: True):
  73. """
  74. Return a mapping from usernames to user information
  75. **Parameters:**
  76. * `context`: the context associated with this request
  77. * `course`: the name of the course, as a string
  78. **Optional Parameters:**
  79. * `filter_func` (default `lambda uinfo: True`): a function mapping user
  80. information dictionaries to Booleans; a user is only included in the
  81. output if the function returns `True` when invoked on their user
  82. information dictionary
  83. **Returns:** a dictionary mapping usernames to user information
  84. dictionaries
  85. """
  86. all_users = {
  87. u: read_user_file(context, course, u, {})
  88. for u in list_all_users(context, course)
  89. }
  90. return {k: v for k, v in all_users.items() if filter_func(v)}