To receive notifications about scheduled maintenance, please subscribe to the mailing-list gitlab-operations@sympa.ethz.ch. You can subscribe to the mailing-list at https://sympa.ethz.ch

moss.py 4.7 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import mosspy
import argparse
import logging

DEFAULT_USER_ID="3795777", # Malte's Moss ID
DEFAULT_LANGUAGE="cc" # C++
DEFAULT_IGNORE_LIMIT=200 # -m in Moss
DEFAULT_NUMBER_OF_MATCHING_FILES=10 # -n in Moss
DEFAULT_TEMPLATE=None
DEFAULT_FILE_PATTERN="./*/main.cpp"
DEFAULT_REPORT_FILE="moss-report.html"
DEFAULT_REPORT_SUBDIR="_moss-report"
DEFAULT_CONNECTIONS=8
DEFAULT_LOGGING_LEVEL="INFO"

def run_moss(
    user_id=DEFAULT_USER_ID,
    language=DEFAULT_LANGUAGE,
    ignore_limit=DEFAULT_IGNORE_LIMIT,
    number_of_matching_files=DEFAULT_NUMBER_OF_MATCHING_FILES,
    template=DEFAULT_TEMPLATE,
    file_pattern=DEFAULT_FILE_PATTERN,
    report_file=DEFAULT_REPORT_FILE,
    report_subdir=DEFAULT_REPORT_SUBDIR,
    connections=DEFAULT_CONNECTIONS):

27
28
29
  # Get a string representation of all function arguments, for logging purposes
  function_args_string = str(locals())

30
31
32
33
34
35
36
37
38
  # Initialisation
  logging.info("User id: {}".format(user_id))
  logging.info("Language: {}".format(language))

  moss = mosspy.Moss(user_id, language)

  # Configure
  logging.info("Ignore limit: {}".format(ignore_limit))
  logging.info("Matches: {}".format(number_of_matching_files))
39
  logging.info("Comment: {}".format(function_args_string))
40
  
41
42
  moss.setIgnoreLimit(ignore_limit)
  moss.setNumberOfMatchingFiles(number_of_matching_files)
43
  moss.setCommentString(function_args_string)
44
45
46
47

  # Add template file(s)
  logging.info("Template: {}".format(template))

48
49
  if template:
    moss.addBaseFile(template)
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

  # Add submission file
  logging.info("File pattern: {}".format(file_pattern))

  moss.addFilesByWildcard(file_pattern)

  logging.info("Sending files to Moss")
  url = moss.send() # Submission Report URL

  logging.info("Moss report URL: {}".format(url))

  # Save report file
  logging.info("Downloading report to: {}".format(report_file))

  moss.saveWebPage(url, report_file)

  # Download whole report locally including code diff links
  logging.info("Downloading individual report files to: {}".format(report_subdir))

  mosspy.download_report(url, report_subdir, connections=connections)

  # TODO: Transform moss-report.html and replace remote links to match<n>.html
  #       with local ones to _moss-report/match<n>.html.
  #       Check that Mossum still correctly works on the transformed file!

def configure_cli_parser(parser):
  parser.add_argument(
    "-u", "--user-id",
    type=int,
    help="Moss user ID",
    required=True)

  parser.add_argument(
    "-l", "--language",
    type=str,
    default=DEFAULT_LANGUAGE,
    help="Programming language (default: {})".format(DEFAULT_LANGUAGE))

  parser.add_argument(
    "-m", "--ignore-limit",
    type=int,
    default=DEFAULT_IGNORE_LIMIT,
    help="Passages occurring in at least this many submissions is ignored (default: {})".format(DEFAULT_IGNORE_LIMIT))

  parser.add_argument(
    "-n", "--matches",
    type=int,
    default=DEFAULT_NUMBER_OF_MATCHING_FILES,
    help="Number of matches returned from Moss (default: {})".format(DEFAULT_NUMBER_OF_MATCHING_FILES))

  parser.add_argument(
    "-t", "--template",
    type=str,
    default=DEFAULT_TEMPLATE,
    help="Student template (default: {})".format(DEFAULT_TEMPLATE))

  parser.add_argument(
    "-rf", "--report-file",
    type=str,
    default=DEFAULT_REPORT_FILE,
    help="Summary report file (default: {})".format(DEFAULT_REPORT_FILE))

  parser.add_argument(
    "-rd", "--report-dir",
    type=str,
    default=DEFAULT_REPORT_SUBDIR,
    help="Directory for individual report files (default: {})".format(DEFAULT_REPORT_SUBDIR))
  
  parser.add_argument(
    "--log-level",
    type=str,
    choices=("OFF", "DEBUG", "INFO", "WARNING", "ERROR"),
    default=DEFAULT_LOGGING_LEVEL,
    help="Log level (default: {})".format(DEFAULT_LOGGING_LEVEL))

  parser.add_argument(
    "pattern",
    type=str,
    default=DEFAULT_FILE_PATTERN,
    help="Pattern for files to send to Moss (e.g.: {})".format(DEFAULT_FILE_PATTERN))

def main():
  parser = argparse.ArgumentParser()
  configure_cli_parser(parser)
  args = parser.parse_args()

136
  # See https://docs.python.org/3.8/library/logging.html#logging-levels
137
138
139
140
141
  log_levels = {
    "OFF": logging.NOTSET,
    "DEBUG": logging.DEBUG,
    "INFO": logging.INFO,
    "WARNING": logging.WARNING,
142
    "ERROR": logging.ERROR
143
144
  }

145
  log_level = log_levels[args.log_level]
146

147
148
149
150
  # See https://docs.python.org/3.8/library/logging.html#logrecord-attributes
  log_format = "%(message)s"

  logging.basicConfig(level=log_level, format=log_format)
151
152
153
154
155
156
157
158
159
160
161
162
163

  run_moss(
    user_id=args.user_id,
    language=args.language,
    ignore_limit=args.ignore_limit,
    number_of_matching_files=args.matches,
    template=args.template,
    file_pattern=args.pattern,
    report_file=args.report_file,
    report_subdir=args.report_dir)

if __name__ == '__main__':
  main()