More racketizations
This commit is contained in:
parent
d0a2d617c8
commit
d32400dd76
|
@ -1,9 +1,9 @@
|
|||
#lang scheme/base
|
||||
#lang racket/base
|
||||
|
||||
(require (for-syntax scheme/base) "utils.rkt"
|
||||
scheme/file scheme/class mred)
|
||||
(require (for-syntax racket/base) "utils.rkt"
|
||||
racket/file racket/class racket/gui/base)
|
||||
|
||||
(provide (except-out (all-from-out scheme/base) #%module-begin)
|
||||
(provide (except-out (all-from-out racket/base) #%module-begin)
|
||||
(all-from-out "utils.rkt"))
|
||||
|
||||
(provide (rename-out [module-begin~ #%module-begin]))
|
||||
|
@ -93,7 +93,7 @@
|
|||
;; * snip->text is used earlier in the process, where comment-box text is still
|
||||
;; available
|
||||
|
||||
(require framework) ; for drscheme snips, used below
|
||||
(require framework) ; for drracket snips, used below
|
||||
|
||||
;; input-port->text-input-port : input-port (any -> any) -> input-port
|
||||
;; the `filter' function is applied to special values; the filter result is
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#lang racket/base
|
||||
|
||||
(require mzlib/thread
|
||||
scheme/port
|
||||
racket/port
|
||||
openssl
|
||||
scheme/file
|
||||
racket/file
|
||||
"private/logger.rkt"
|
||||
"private/config.rkt"
|
||||
"private/lock.rkt"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#lang scheme/gui
|
||||
#lang racket/gui
|
||||
|
||||
(require htdp/error lang/prim)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#lang scheme/gui
|
||||
#lang racket/gui
|
||||
|
||||
(require htdp/error lang/prim)
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#lang scheme/base
|
||||
#lang racket/base
|
||||
|
||||
(require scheme/file)
|
||||
(require racket/file)
|
||||
|
||||
;; This module should be invoked when we're in the server directory
|
||||
(provide server-dir)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#lang scheme/base
|
||||
#lang racket/base
|
||||
|
||||
(require "config.rkt" "logger.rkt" "reloadable.rkt")
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#lang scheme/base
|
||||
#lang racket/base
|
||||
|
||||
(provide wait-for-lock)
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#lang scheme/base
|
||||
#lang racket/base
|
||||
|
||||
(require "config.rkt" scheme/date scheme/port)
|
||||
(require "config.rkt" racket/date racket/port)
|
||||
|
||||
(provide current-session)
|
||||
(define current-session (make-parameter #f))
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#lang scheme/base
|
||||
(require (prefix-in mz: file/md5))
|
||||
#lang racket/base
|
||||
(require (prefix-in r: file/md5))
|
||||
(define (md5 s)
|
||||
(bytes->string/latin-1 (mz:md5 (string->bytes/utf-8 s))))
|
||||
(bytes->string/latin-1 (r:md5 (string->bytes/utf-8 s))))
|
||||
(provide md5)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#lang scheme/base
|
||||
#lang racket/base
|
||||
|
||||
(require syntax/moddep "logger.rkt")
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
|||
(with-handlers ([exn? (lambda (e)
|
||||
(log-line "error, module not reloaded (~a)"
|
||||
(exn-message e)))])
|
||||
(namespace-require '(only scheme module #%top-interaction))
|
||||
(namespace-require '(only racket module #%top-interaction))
|
||||
(load/use-compiled path)))))
|
||||
|
||||
;; pulls out a value from a module, reloading the module if its source file was
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#lang scheme/base
|
||||
#lang racket/base
|
||||
|
||||
(provide current-run-status-box set-run-status
|
||||
current-messenger message)
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
#lang scheme/base
|
||||
#lang racket/base
|
||||
|
||||
(define default-context-length (error-print-context-length))
|
||||
|
||||
;; This code has parts that are copied from `serve/servlet' in
|
||||
;; "web-server/servlet-env.ss", and parts from `serve/launch/wait' in
|
||||
;; "web-server/servlet-dispatch.ss"
|
||||
;; "web-server/servlet-env.rkt", and parts from `serve/launch/wait' in
|
||||
;; "web-server/servlet-dispatch.rkt"
|
||||
|
||||
(require scheme/unit
|
||||
scheme/async-channel
|
||||
(require racket/unit
|
||||
racket/async-channel
|
||||
web-server/web-server
|
||||
web-server/servlet-dispatch
|
||||
web-server/managers/lru
|
||||
|
@ -106,7 +106,7 @@
|
|||
(* 12 1024 1024))))
|
||||
;; This can be used to serve html content too; doesn't make sense now,
|
||||
;; since the servlet will be used for all requests, and it never calls
|
||||
;; (next-dispatcher). (See "servlet-env.ss" for the needed `require's.)
|
||||
;; (next-dispatcher). (See "servlet-env.rkt" for the needed `require's.)
|
||||
;; (files:make
|
||||
;; #:url->path (fsmap:make-url->path (build-path server-dir "htdocs")))
|
||||
;; (lift:make (send-error "File not found" (lambda () "/")))
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#lang scheme/base
|
||||
(require scheme/sandbox)
|
||||
(provide (all-from-out scheme/sandbox))
|
||||
#lang racket/base
|
||||
(require racket/sandbox)
|
||||
(provide (all-from-out racket/sandbox))
|
||||
|
||||
;; no input/output
|
||||
(sandbox-input #f)
|
||||
|
@ -20,6 +20,7 @@
|
|||
,@(if gui? '(mrlib/cache-image-snip) '()))))
|
||||
|
||||
;; local overrides
|
||||
(require racket/runtime-path)
|
||||
(define-runtime-path overrides "overridden-collects")
|
||||
(sandbox-override-collection-paths
|
||||
(cons (build-path (collection-path "handin-server") "overridden-collects")
|
||||
(sandbox-override-collection-paths)))
|
||||
(cons overrides (sandbox-override-collection-paths)))
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#lang scribble/doc
|
||||
@(require "common.ss")
|
||||
@(require "common.rkt")
|
||||
|
||||
@title[#:style 'toc]{Checker Utilities}
|
||||
|
||||
|
@ -10,20 +10,19 @@ order):
|
|||
|
||||
@itemize[
|
||||
|
||||
@item{@schememodname[scheme/sandbox]: contains basic sandbox
|
||||
evaluation utilities. This is in MzLib since it can be used
|
||||
independently.}
|
||||
@item{@racketmodname[racket/sandbox]: is the basic sandbox
|
||||
evaluation code, which is the basic functionality checkers build on.}
|
||||
|
||||
@item{@schememodname[handin-server/sandbox]: contains a wrapper that
|
||||
configures MzLib's sandbox for the handin server.}
|
||||
@item{@racketmodname[handin-server/sandbox]: contains a wrapper that
|
||||
configures the Racket sandbox for the handin server.}
|
||||
|
||||
@item{@schememodname[handin-server/utils]: contains additional
|
||||
@item{@racketmodname[handin-server/utils]: contains additional
|
||||
utilities for dealing with handin submissions, as well as a few
|
||||
helpers for testing code.}
|
||||
|
||||
@item{@schememodname[handin-server/checker]: automates the task of
|
||||
@item{@racketmodname[handin-server/checker]: automates the task of
|
||||
creating a checker function (in
|
||||
@filepath{<active-assignment>/checker.ss} modules) to cope with
|
||||
@filepath{<active-assignment>/checker.rkt} modules) to cope with
|
||||
common submission situations.}]
|
||||
|
||||
The following sections describe each of these modules.
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
#lang scribble/doc
|
||||
@(require "common.ss")
|
||||
@(require "common.rkt")
|
||||
|
||||
@(define textoption
|
||||
@t{(Effective only when saving a textual version of
|
||||
the submission files: when @scheme[:create-text?] is on.)})
|
||||
the submission files: when @racket[:create-text?] is on.)})
|
||||
|
||||
@title{Checker}
|
||||
|
||||
@defmodulelang[handin-server/checker]{
|
||||
|
||||
The @schememodname[handin-server/checker] module provides a
|
||||
The @racketmodname[handin-server/checker] module provides a
|
||||
higher-level of utilities, helpful in implementing `checker' functions
|
||||
that are intended for a more automated system. This module is a
|
||||
language module---a typical checker that uses it looks like this:
|
||||
|
||||
@schemeblock[
|
||||
@racketblock[
|
||||
(module checker handin-server/checker
|
||||
(check: :language '(special intermediate)
|
||||
:users pairs-or-singles-with-warning
|
||||
|
@ -34,7 +34,7 @@ language module---a typical checker that uses it looks like this:
|
|||
Constructs (and provides) an appropriate checker function, using
|
||||
keywords to customize features that you want it to have. The body of
|
||||
the checker (following the keywords) can contain arbitrary code, using
|
||||
utility functions from @schememodname[handin-server/utils], as well as
|
||||
utility functions from @racketmodname[handin-server/utils], as well as
|
||||
additional ones that are defined below. Submission files are arriving
|
||||
to the handin server in binary form (in the GRacket format that is used
|
||||
to store text and other objects like images), and a number of these
|
||||
|
@ -42,70 +42,70 @@ options involve genrating a textual version of this file. The purpose
|
|||
of these options is to have these text files integrate easily into a
|
||||
course framework for grading, based on these text files.}
|
||||
|
||||
Keywords for configuring @scheme[check:]:
|
||||
Keywords for configuring @racket[check:]:
|
||||
|
||||
@itemize[
|
||||
|
||||
@item{@indexed-scheme[:users]---specification of users that are
|
||||
@item{@indexed-racket[:users]---specification of users that are
|
||||
acceptable for submission. Can be either a list of user lists, each
|
||||
representing a known team, or procedure which will accept a list of
|
||||
users and throw an exception if they are unacceptable. The default
|
||||
is to accept only single-user submissions. The
|
||||
@scheme[pairs-or-singles-with-warning] procedure is a useful value
|
||||
@racket[pairs-or-singles-with-warning] procedure is a useful value
|
||||
for pair submission where the pairs are unknown.}
|
||||
|
||||
@item{@indexed-scheme[:eval?]---whether submissions should be
|
||||
evaluated. Defaults to @scheme[#t]. Note that if it is specified
|
||||
as @scheme[#f], then the checker body will not be able to run any
|
||||
@item{@indexed-racket[:eval?]---whether submissions should be
|
||||
evaluated. Defaults to @racket[#t]. Note that if it is specified
|
||||
as @racket[#f], then the checker body will not be able to run any
|
||||
tests on the code, unless it contains code that performs some
|
||||
evaluation (e.g., using the facilities of
|
||||
@schememodname[handin-server/utils]).}
|
||||
@racketmodname[handin-server/utils]).}
|
||||
|
||||
@item{@indexed-scheme[:language]---the language that is used for
|
||||
evaluating submissions, same as the @scheme[_language] argument for
|
||||
@scheme[make-evaluator] (see @schememodname[handin-server/sandbox]),
|
||||
@item{@indexed-racket[:language]---the language that is used for
|
||||
evaluating submissions, same as the @racket[_language] argument for
|
||||
@racket[make-evaluator] (see @racketmodname[handin-server/sandbox]),
|
||||
except that if the value ls @racket[(list 'module _spec)],
|
||||
then @racket[make-module-evaluator] is used with @racket[_spec]
|
||||
as its @racket[#:language] argument.
|
||||
There is no default for this, so it must be set or an error is
|
||||
raised. (See @scheme[call-with-evaluator/submission] for further
|
||||
raised. (See @racket[call-with-evaluator/submission] for further
|
||||
details.)}
|
||||
|
||||
@item{@indexed-scheme[:requires]---paths for additional libraries to
|
||||
@item{@indexed-racket[:requires]---paths for additional libraries to
|
||||
require for evaluating the submission, same as the
|
||||
@scheme[_requires] argument for @scheme[make-evaluator] (see
|
||||
@schememodname[handin-server/sandbox]). This defaults to null---no
|
||||
@racket[_requires] argument for @racket[make-evaluator] (see
|
||||
@racketmodname[handin-server/sandbox]). This defaults to null---no
|
||||
teachpacks. Note: if a module language is used (See
|
||||
@scheme[call-with-evaluator/submission] for further details), it is
|
||||
passed as the @scheme[_allow-read] argument.}
|
||||
@racket[call-with-evaluator/submission] for further details), it is
|
||||
passed as the @racket[_allow-read] argument.}
|
||||
|
||||
@item{@indexed-scheme[:teachpacks]---an alternative name for
|
||||
@scheme[:requires], kept for legacy checkers.}
|
||||
@item{@indexed-racket[:teachpacks]---an alternative name for
|
||||
@racket[:requires], kept for legacy checkers.}
|
||||
|
||||
@item{@indexed-scheme[:create-text?]---if true, then a textual version
|
||||
of the submission is saved as @filepath{text.scm} in a
|
||||
@item{@indexed-racket[:create-text?]---if true, then a textual version
|
||||
of the submission is saved as @filepath{text.rkt} in a
|
||||
@filepath{grading} subdirectory (or any suffix that is specified by
|
||||
@scheme[:output] below, for example @filepath{hw.java} is converted
|
||||
@racket[:output] below, for example @filepath{hw.java} is converted
|
||||
into a textual @filepath{grading/text.java}). This is intended for
|
||||
printouts and grading, and is in a subdirectory so students will not
|
||||
see it on the status web server. Defaults to @scheme[#t].}
|
||||
see it on the status web server. Defaults to @racket[#t].}
|
||||
|
||||
@item{@indexed-scheme[:textualize?]---if true, then all submissions
|
||||
@item{@indexed-racket[:textualize?]---if true, then all submissions
|
||||
are converted to text, trying to convert objects like images and
|
||||
comment boxes to some form of text. Defaults to @scheme[#f],
|
||||
comment boxes to some form of text. Defaults to @racket[#f],
|
||||
meaning that an exception is raised for submissions that are not all
|
||||
text. @textoption
|
||||
|
||||
This flag is effective only when saving a textual version of the
|
||||
submission files --- when @scheme[:create-text?] is on. The
|
||||
submission files --- when @racket[:create-text?] is on. The
|
||||
possible configurations are:
|
||||
@itemize[
|
||||
@item{@scheme[:create-text?] is on and @scheme[:textualize?] is off
|
||||
@item{@racket[:create-text?] is on and @racket[:textualize?] is off
|
||||
(the default) --- in this case a text version of submissions is
|
||||
created, and submissions must contain only plain text. The text
|
||||
file has the same semantics of the submission and can be used to
|
||||
run student code.}
|
||||
@item{@scheme[:create-text?] is off --- allowing submissions that
|
||||
@item{@racket[:create-text?] is off --- allowing submissions that
|
||||
contain non-textual objects, but no text file is created so
|
||||
grading and testing must be done using DrRacket (because the saved
|
||||
submission is always in binary format).}
|
||||
|
@ -114,81 +114,81 @@ Keywords for configuring @scheme[check:]:
|
|||
usable as code since objects like images cannot be represented in
|
||||
plain text.}]}
|
||||
|
||||
@item{@indexed-scheme[:untabify?]---if true, then tabs are converted
|
||||
@item{@indexed-racket[:untabify?]---if true, then tabs are converted
|
||||
to spaces, assuming a standard tab width of 8 places. This is
|
||||
needed for a correct computation of line lengths, but note that
|
||||
DrRacket does not insert tabs in Scheme mode. Defaults to
|
||||
@scheme[#t]. @textoption}
|
||||
@racket[#t]. @textoption}
|
||||
|
||||
@item{@indexed-scheme[:maxwidth]---a number that specifies maximum
|
||||
@item{@indexed-racket[:maxwidth]---a number that specifies maximum
|
||||
line lengths for submissions (a helpful feature for reading student
|
||||
code). Defaults to 79. This feature can be disabled if set to
|
||||
@scheme[#f]. @textoption}
|
||||
@racket[#f]. @textoption}
|
||||
|
||||
@item{@indexed-scheme[:output]---the name of the original handin file
|
||||
@item{@indexed-racket[:output]---the name of the original handin file
|
||||
(unrelated to the text-converted files). Defaults to
|
||||
@filepath{hw.rkt}. (The suffix changes the defaults of
|
||||
@scheme[:markup-prefix] and @scheme[:prefix-re].) Can be
|
||||
@scheme[#f] for removing the original file after processing. The
|
||||
@racket[:markup-prefix] and @racket[:prefix-re].) Can be
|
||||
@racket[#f] for removing the original file after processing. The
|
||||
file is always stored in GRacket's binary format.}
|
||||
|
||||
@item{@indexed-scheme[:multi-file]---by default, this is set to
|
||||
@scheme[#f], which means that only DrRacket is used to send
|
||||
@item{@indexed-racket[:multi-file]---by default, this is set to
|
||||
@racket[#f], which means that only DrRacket is used to send
|
||||
submissions as usual. See @secref{multi-file} for setting up
|
||||
multi-file submissions.}
|
||||
|
||||
@item{@indexed-scheme[:names-checker]---used for multi-file
|
||||
@item{@indexed-racket[:names-checker]---used for multi-file
|
||||
submissions; see @secref{multi-file} for details.}
|
||||
|
||||
@item{@indexed-scheme[:markup-prefix]---used as the prefix for
|
||||
@scheme[:student-lines] and @scheme[:extra-lines] below. The
|
||||
default is @scheme[";;> "] or @scheme["//> "], depending on the
|
||||
suffix of @scheme[:output] above. Note: if you change this, make
|
||||
sure to change @scheme[:prefix-re] too. @textoption}
|
||||
@item{@indexed-racket[:markup-prefix]---used as the prefix for
|
||||
@racket[:student-lines] and @racket[:extra-lines] below. The
|
||||
default is @racket[";;> "] or @racket["//> "], depending on the
|
||||
suffix of @racket[:output] above. Note: if you change this, make
|
||||
sure to change @racket[:prefix-re] too. @textoption}
|
||||
|
||||
@item{@indexed-scheme[:prefix-re]---used to identify lines with markup
|
||||
(@scheme[";>"] or @scheme["//>"] etc), so students cannot fool the
|
||||
system by writing marked-up code. The default is @scheme[";>"] or
|
||||
@scheme["//>"], depending on the suffix of :output above.
|
||||
@item{@indexed-racket[:prefix-re]---used to identify lines with markup
|
||||
(@racket[";>"] or @racket["//>"] etc), so students cannot fool the
|
||||
system by writing marked-up code. The default is @racket[";>"] or
|
||||
@racket["//>"], depending on the suffix of :output above.
|
||||
@textoption}
|
||||
|
||||
@item{@indexed-scheme[:student-line]---when a submission is converted
|
||||
@item{@indexed-racket[:student-line]---when a submission is converted
|
||||
to text, it begins with lines describing the students that have
|
||||
submitted it; this is used to specify the format of these lines. It
|
||||
is a string with holes that @scheme[user-substs] fills out.
|
||||
The default is @scheme["Student: {username} ({Full Name} <{Email}>)"],
|
||||
which requires @scheme["Full Name"] and @scheme["Email"] entries in
|
||||
is a string with holes that @racket[user-substs] fills out.
|
||||
The default is @racket["Student: {username} ({Full Name} <{Email}>)"],
|
||||
which requires @racket["Full Name"] and @racket["Email"] entries in
|
||||
the server's extra-fields configuration. These lines are prefixed
|
||||
with @scheme[";;> "] or the prefix specified by
|
||||
@scheme[:makup-prefix] above. @textoption}
|
||||
with @racket[";;> "] or the prefix specified by
|
||||
@racket[:makup-prefix] above. @textoption}
|
||||
|
||||
@item{@indexed-scheme[:extra-lines]---a list of lines to add after the
|
||||
student lines, all with a @scheme[";;> "] or :markup-prefix too.
|
||||
@item{@indexed-racket[:extra-lines]---a list of lines to add after the
|
||||
student lines, all with a @racket[";;> "] or :markup-prefix too.
|
||||
Defaults to a single line:
|
||||
@scheme["Maximum points for this assignment: <+100>"]. (Can use
|
||||
@scheme["{submission}"] for the submission directory.) See also
|
||||
@scheme[add-header-line!]. @textoption}
|
||||
@racket["Maximum points for this assignment: <+100>"]. (Can use
|
||||
@racket["{submission}"] for the submission directory.) See also
|
||||
@racket[add-header-line!]. @textoption}
|
||||
|
||||
@item{@indexed-scheme[:user-error-message]---a string that is used to
|
||||
@item{@indexed-racket[:user-error-message]---a string that is used to
|
||||
report an error that occurred during evaluation of the submitted
|
||||
code (not during additional tests). It can be a plain string which
|
||||
will be used as the error message, or a string with single a
|
||||
@scheme["~a"] (or @scheme["~s"], @scheme["~v"], @scheme["~e"],
|
||||
or @scheme["~.a"] etc) that
|
||||
@racket["~a"] (or @racket["~s"], @racket["~v"], @racket["~e"],
|
||||
or @racket["~.a"] etc) that
|
||||
will be used as a format string with the actual error message. The
|
||||
default is @scheme["Error in your code --\n~a"]. Useful examples of
|
||||
default is @racket["Error in your code --\n~a"]. Useful examples of
|
||||
these messages:
|
||||
|
||||
@scheme["There is an error in your program, hit \"Run\" to debug"]
|
||||
@racket["There is an error in your program, hit \"Run\" to debug"]
|
||||
|
||||
@scheme["There is an error in your program:\n----\n~a\n----\nHit \"Run\" and debug your code."]
|
||||
@racket["There is an error in your program:\n----\n~a\n----\nHit \"Run\" and debug your code."]
|
||||
|
||||
Alternatively, the value can be a procedure that will be invoked
|
||||
with the error message. The procedure can do anything it wants, and
|
||||
if it does not raise an exception, then the checker will proceed as
|
||||
usual. For example:
|
||||
|
||||
@schemeblock[
|
||||
@racketblock[
|
||||
(lambda (msg)
|
||||
(add-header-line! "Erroneous submission!")
|
||||
(add-header-line! (format " --> ~a" msg))
|
||||
|
@ -205,42 +205,42 @@ Keywords for configuring @scheme[check:]:
|
|||
(Note that if you do this, then additional tests should be adjusted
|
||||
to not raise an exception too.)}
|
||||
|
||||
@item{@indexed-scheme[:value-printer]---if specified, this will be
|
||||
used for @scheme[current-value-printer].}
|
||||
@item{@indexed-racket[:value-printer]---if specified, this will be
|
||||
used for @racket[current-value-printer].}
|
||||
|
||||
@item{@indexed-scheme[:coverage?]---collect coverage information when
|
||||
@item{@indexed-racket[:coverage?]---collect coverage information when
|
||||
evaluating the submission. This will cause an error if some input
|
||||
is not covered. This check happens after checker tests are run, but
|
||||
the information is collected and stored before, so checker tests do
|
||||
not change the result. Also, you can use the @scheme[!all-covered]
|
||||
not change the result. Also, you can use the @racket[!all-covered]
|
||||
procedure in the checker before other tests, if you want that
|
||||
feedback earlier.}]
|
||||
|
||||
Within the body of @scheme[check:], @scheme[users] and
|
||||
@scheme[submission] will be bound to the checker arguments---a
|
||||
Within the body of @racket[check:], @racket[users] and
|
||||
@racket[submission] will be bound to the checker arguments---a
|
||||
(sorted) list of usernames and the submission as a byte string. In
|
||||
addition to the functionality below, you can use
|
||||
@scheme[(!eval _expr)] (or @scheme[((submission-eval) '_expr)]) to
|
||||
@racket[(!eval _expr)] (or @racket[((submission-eval) '_expr)]) to
|
||||
evaluate expressions in the submitted code context, and you can use
|
||||
@scheme[(with-submission-bindings (id ...) body ...)] to evaluate the
|
||||
body when @scheme[id]'s are bound to their values from the submission
|
||||
@racket[(with-submission-bindings (id ...) body ...)] to evaluate the
|
||||
body when @racket[id]'s are bound to their values from the submission
|
||||
code.}
|
||||
|
||||
@deftogether[(@defform[(pre: body ...)]
|
||||
@defform[(post: body ...)])]{
|
||||
|
||||
These two macros define a pre- and a post-checker. In their bodies,
|
||||
@scheme[_users] and @scheme[_submission] are bound as in
|
||||
@scheme[check:], but there is nothing else special about these. See
|
||||
the description of the @scheme[pre-checker] and
|
||||
@scheme[post-checker] values for what can be done with these, and
|
||||
@racket[_users] and @racket[_submission] are bound as in
|
||||
@racket[check:], but there is nothing else special about these. See
|
||||
the description of the @racket[pre-checker] and
|
||||
@racket[post-checker] values for what can be done with these, and
|
||||
note that the check for valid users is always first. An example for
|
||||
a sophisticated @scheme[post:] block is below---it will first
|
||||
a sophisticated @racket[post:] block is below---it will first
|
||||
disable timeouts for this session, then it will send a email with a
|
||||
submission receipt, with CC to the TA (assuming a single TA), and
|
||||
pop-up a message telling the student about it:
|
||||
|
||||
@schemeblock[
|
||||
@racketblock[
|
||||
(require net/sendmail)
|
||||
(post:
|
||||
(define info
|
||||
|
@ -273,25 +273,25 @@ code.}
|
|||
|
||||
Returns a user information given a username. The returned
|
||||
information is a list of strings that corresponds to the configured
|
||||
@scheme[extra-fields].}
|
||||
@racket[extra-fields].}
|
||||
|
||||
@defproc[(user-substs [user string?] [fmt string?]) string]{
|
||||
|
||||
Uses the mappings in @scheme[user-data] to substitute user
|
||||
Uses the mappings in @racket[user-data] to substitute user
|
||||
information for substrings of the form ``@tt{{some-field-name}}'' in
|
||||
@scheme[fmt]. This procedure signals an error if a field name is
|
||||
@racket[fmt]. This procedure signals an error if a field name is
|
||||
missing in the user data. Also, ``@tt{{username}}'' will always be
|
||||
replaced by the username and ``@tt{{submission}}'' by the current
|
||||
submission directory.
|
||||
|
||||
This is used to process the @scheme[:student-line] value in the
|
||||
This is used to process the @racket[:student-line] value in the
|
||||
checker, but it is provided for additional uses. See the above
|
||||
sample code for @scheme[post:] for using this procedure.}
|
||||
sample code for @racket[post:] for using this procedure.}
|
||||
|
||||
@defproc[(pairs-or-singles-with-warning [users (listof string?)])
|
||||
any]{
|
||||
|
||||
Intended for use as the @scheme[:users] entry in a checker. It will
|
||||
Intended for use as the @racket[:users] entry in a checker. It will
|
||||
do nothing if there are two users, and throw an error if there are
|
||||
more. If there is a single user, then the user will be asked to
|
||||
verify a single submission. If the student cancels, then an
|
||||
|
@ -313,21 +313,21 @@ code.}
|
|||
specified in this file. Furthermore, if this file is modified, the
|
||||
new contents will be used immediately, so there is no need to
|
||||
restart the server of you want to change student teams. (But
|
||||
remember that if you change @scheme[("foo" "bar")] to
|
||||
@scheme[("foo" "baz")], and there is already a @filepath{bar+foo}
|
||||
remember that if you change @racket[("foo" "bar")] to
|
||||
@racket[("foo" "baz")], and there is already a @filepath{bar+foo}
|
||||
submission directory, then the system will not allow ``@tt{foo}'' to
|
||||
submit with ``@tt{bar}''.)}
|
||||
|
||||
@defproc[(add-header-line! [line string?]) void?]{
|
||||
During the checker operation, can be used to add header lines to the
|
||||
text version of the submitted file (in addition to the
|
||||
@scheme[:extra-lines] setting). It will not have an effect if
|
||||
@scheme[:create-text?] is false.}
|
||||
@racket[:extra-lines] setting). It will not have an effect if
|
||||
@racket[:create-text?] is false.}
|
||||
|
||||
@defproc[(procedure/arity? [proc procedure?] [arity number?])
|
||||
boolean?]{
|
||||
Returns @scheme[#t] if @scheme[proc] is a procedure that accepts
|
||||
@scheme[arity] arguments.}
|
||||
Returns @racket[#t] if @racket[proc] is a procedure that accepts
|
||||
@racket[arity] arguments.}
|
||||
|
||||
@defform[(!defined id ...)]{
|
||||
Checks that the given identifiers are defined in the (evaluated)
|
||||
|
@ -340,21 +340,21 @@ code.}
|
|||
identifier is bound to a syntax.}
|
||||
|
||||
@defform[(!syntax id arity)]{
|
||||
Checks that @scheme[id] is defined, and is bound as a macro.}
|
||||
Checks that @racket[id] is defined, and is bound as a macro.}
|
||||
|
||||
@defform[(!procedure id arity)]{
|
||||
Checks that @scheme[id] is defined, and is bound to a procedure.}
|
||||
Checks that @racket[id] is defined, and is bound to a procedure.}
|
||||
|
||||
@defform[(!procedure* expr arity)]{
|
||||
|
||||
Similar to @scheme[!procedure] but omits the defined check, making
|
||||
Similar to @racket[!procedure] but omits the defined check, making
|
||||
it usable with any expression, which is then evaluated in the
|
||||
submission context.}
|
||||
|
||||
@deftogether[(@defform[(!integer id)]
|
||||
@defform[(!integer* expr)])]{
|
||||
|
||||
Similar to @scheme[!procedure] and @scheme[!procedure*] for
|
||||
Similar to @racket[!procedure] and @racket[!procedure*] for
|
||||
integers.}
|
||||
|
||||
@deftogether[(
|
||||
|
@ -364,42 +364,42 @@ code.}
|
|||
@defform[(!test/exn expr)]
|
||||
)]{
|
||||
|
||||
The first @scheme[!test] form checks that the given expression
|
||||
evaluates to a non-@scheme[#f] value in the submission context,
|
||||
The first @racket[!test] form checks that the given expression
|
||||
evaluates to a non-@racket[#f] value in the submission context,
|
||||
throwing an error otherwise. The second form compares the result of
|
||||
evaluation, requiring it to be equal to @scheme[result]. The third
|
||||
allows specifying an equality procedure. The @scheme[!test/exn] form
|
||||
checks that the given expression throws an @scheme[exn:fail?] error,
|
||||
evaluation, requiring it to be equal to @racket[result]. The third
|
||||
allows specifying an equality procedure. The @racket[!test/exn] form
|
||||
checks that the given expression throws an @racket[exn:fail?] error,
|
||||
throwing an error otherwise.
|
||||
|
||||
For the latter two @scheme[!test] forms, note that the
|
||||
@scheme[result] and @scheme[equal?] forms are @italic{not} evaluated
|
||||
For the latter two @racket[!test] forms, note that the
|
||||
@racket[result] and @racket[equal?] forms are @italic{not} evaluated
|
||||
in the submission context.}
|
||||
|
||||
@defform[(!eval expr)]{
|
||||
|
||||
Evaluate an arbitrary expession in the submission context. This is
|
||||
a simple shorthand for @scheme[((submission-eval) `expr)].}
|
||||
a simple shorthand for @racket[((submission-eval) `expr)].}
|
||||
|
||||
@defproc*[([(!all-covered) void?]
|
||||
[(!all-covered [proc (string? . -> . any)]) void?])]{
|
||||
|
||||
When coverage information is enabled (see @scheme[:coverage?]
|
||||
When coverage information is enabled (see @racket[:coverage?]
|
||||
above), checks the collected coverage information and throws an
|
||||
error with source information if some code is left uncovered. If
|
||||
@scheme[proc] is provided, it is applied to a string argument that
|
||||
@racket[proc] is provided, it is applied to a string argument that
|
||||
describes the location of the uncovered expression
|
||||
(@scheme["<line>:<col>"], @scheme["#<char-pos>"], or
|
||||
@scheme["(unknown position)"]) instead of throwing an error. The
|
||||
(@racket["<line>:<col>"], @racket["#<char-pos>"], or
|
||||
@racket["(unknown position)"]) instead of throwing an error. The
|
||||
collected information includes only execution coverage by submission
|
||||
code, excluding additional checker tests. You do not have to call
|
||||
this explicitly---it is called at the end of the process
|
||||
automatically when @scheme[:coverage?] is enabled. It is made
|
||||
automatically when @racket[:coverage?] is enabled. It is made
|
||||
available so you can call it earlier (e.g., before testing) to show
|
||||
clients a coverage error first, or if you want to avoid an error.
|
||||
For example, you can do this:
|
||||
|
||||
@schemeblock[
|
||||
@racketblock[
|
||||
(!all-covered
|
||||
(lambda (where)
|
||||
(case (message (string-append
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#lang scribble/doc
|
||||
@(require "common.ss")
|
||||
@(require "common.rkt")
|
||||
|
||||
@title{Client Customization}
|
||||
|
||||
|
@ -9,10 +9,10 @@ collection directory. The new name should describe your class
|
|||
uniquely. For example, @filepath{uu-cs1410} is a good name for CS
|
||||
1410 at the University of Utah.}
|
||||
|
||||
@item{Edit the first three definitions of @filepath{info.ss} in your
|
||||
@item{Edit the first three definitions of @filepath{info.rkt} in your
|
||||
renamed client collection:
|
||||
@itemize[
|
||||
@item{For @scheme[name], choose a name for the handin tool as it
|
||||
@item{For @racket[name], choose a name for the handin tool as it
|
||||
will appear in DrRacket's interface (e.g., the @onscreen{XXX} for
|
||||
the @onscreen{Manage XXX Handin Account...} menu item). Again,
|
||||
make the name specific to the course, in case a student installs
|
||||
|
@ -20,16 +20,16 @@ uniquely. For example, @filepath{uu-cs1410} is a good name for CS
|
|||
part of the name, since @onscreen{Handin} is always added for
|
||||
button and menu names.}
|
||||
|
||||
@item{Uncomment the definitions of @scheme[tools],
|
||||
@scheme[tool-names], and @scheme[tool-icons]. (But leave the
|
||||
@item{Uncomment the definitions of @racket[tools],
|
||||
@racket[tool-names], and @racket[tool-icons]. (But leave the
|
||||
latter field's definition as @filepath{icon.png}.)}
|
||||
|
||||
@item{For @scheme[server:port], uncomment the line, and use the
|
||||
@item{For @racket[server:port], uncomment the line, and use the
|
||||
hostname and port where the server will be running to accept
|
||||
handin submissions.}]
|
||||
|
||||
Optionally uncomment and edit the next two definitions,
|
||||
@scheme[web-menu-name] and @scheme[web-address], to add an item to
|
||||
@racket[web-menu-name] and @racket[web-address], to add an item to
|
||||
the @onscreen{Help} menu that opens a (course-specific) web page.}
|
||||
|
||||
@item{Replace @filepath{icon.png} in your renamed directory with a new
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
#lang scheme/base
|
||||
#lang racket/base
|
||||
|
||||
(require scheme/require)
|
||||
|
||||
(require scribble/manual
|
||||
(for-label scheme
|
||||
(subtract-in handin-server/checker scheme)
|
||||
;; scheme/sandbox
|
||||
(require racket/require
|
||||
scribble/manual
|
||||
(for-label racket
|
||||
(subtract-in handin-server/checker racket)
|
||||
;; racket/sandbox
|
||||
handin-server/sandbox
|
||||
handin-server/utils
|
||||
mred
|
||||
"hook-dummy.ss"))
|
||||
racket/gui/base
|
||||
"hook-dummy.rkt"))
|
||||
|
||||
(provide (all-from-out scribble/manual)
|
||||
(for-label (all-from-out scheme
|
||||
(for-label (all-from-out racket
|
||||
handin-server/checker
|
||||
handin-server/sandbox
|
||||
handin-server/utils
|
||||
mred
|
||||
"hook-dummy.ss")))
|
||||
racket/gui/base
|
||||
"hook-dummy.rkt")))
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#lang scribble/doc
|
||||
@(require "common.ss")
|
||||
@(require "common.rkt")
|
||||
|
||||
@;{John's comments:
|
||||
- There's no enumerate?
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#lang scheme/base
|
||||
#lang racket/base
|
||||
|
||||
(provide hook)
|
||||
|
||||
(define (hook operation connection-context relevant-info)
|
||||
'bogus-value)
|
||||
|
||||
|
||||
|
|
|
@ -1,43 +1,43 @@
|
|||
#lang scribble/doc
|
||||
@(require "common.ss")
|
||||
@(require "common.rkt")
|
||||
|
||||
@title[#:tag "multi-file"]{Multiple-File Submissions}
|
||||
|
||||
By default, the system is set up for submissions of single a single
|
||||
file, straight fom DrRacket using the handin-client. There is some
|
||||
limited support for multi-file submissions in
|
||||
@schememodname[handin-server/checker] and in the handin-client. It is
|
||||
@racketmodname[handin-server/checker] and in the handin-client. It is
|
||||
possible to submit multiple files, and have the system generate a
|
||||
single file that is the concatenation of all submission files (used
|
||||
only with text files). To set up multi-file submissions, do the
|
||||
following:
|
||||
|
||||
@itemize[
|
||||
@item{Add a @scheme[:multi-file] keyword in @scheme[check:], and as a
|
||||
@item{Add a @racket[:multi-file] keyword in @racket[check:], and as a
|
||||
value, use the suffix that should be used for the single
|
||||
concatenated output file.}
|
||||
|
||||
@item{You can also add a @scheme[:names-checker] keyword--the value
|
||||
@item{You can also add a @racket[:names-checker] keyword--the value
|
||||
can be a regexp that all submitted files must follow (e.g.,
|
||||
@scheme[".*[.]scm$"]), or a list of expected file names.
|
||||
@racket[".*[.]rkt$"]), or a list of expected file names.
|
||||
Alternatively, it can be a 1-argument procedure that will receive
|
||||
the (sorted) list of submitted files and can throw an error if some
|
||||
files are missing or some files are forbidden.}
|
||||
|
||||
@item{Make sure that @scheme[:create-text?] is on if you want the
|
||||
@item{Make sure that @racket[:create-text?] is on if you want the
|
||||
contents of a multi-file submission to be unpacked and filenames
|
||||
checked.}
|
||||
|
||||
@item{In the @filepath{info.ss} file of the handin-client you need to
|
||||
set @scheme[enable-multifile-handin] to @scheme[#t], and adjust
|
||||
@scheme[selection-default] to patterns that are common to your
|
||||
@item{In the @filepath{info.rkt} file of the handin-client you need to
|
||||
set @racket[enable-multifile-handin] to @racket[#t], and adjust
|
||||
@racket[selection-default] to patterns that are common to your
|
||||
course. (It can be a single pattern, or a list of them.)}]
|
||||
|
||||
On the server side, each submission is saved in a file called
|
||||
@filepath{raw}, which contains all submitted files. In the
|
||||
@filepath{grading} directory, you will get a @filepath{text.<sfx>}
|
||||
file (@filepath{<sfx>} is the suffix that is used as a value for
|
||||
@scheme[:multi-file]) that contains all submitted files with clear
|
||||
@racket[:multi-file]) that contains all submitted files with clear
|
||||
separators. A possible confusion is that every submission is a
|
||||
complete set of files that overwrites any existing submission, whereas
|
||||
students may think that the server accumulates incoming files. To
|
||||
|
@ -50,8 +50,8 @@ submission.
|
|||
On the client side, students will have an additional file-menu entry
|
||||
for submitting multiple files, which pops up a dialog that can be used
|
||||
to submit multiple files. In this dialog, students choose their
|
||||
working directory, and the @scheme[selection-default] entry from the
|
||||
@filepath{handin-client/info.ss} file specifies a few patterns that
|
||||
working directory, and the @racket[selection-default] entry from the
|
||||
@filepath{handin-client/info.rkt} file specifies a few patterns that
|
||||
can be used to automatically select files. The dialog provides all
|
||||
handin-related functionality that is available in DrRacket. For
|
||||
further convenience, it can be used as a standalone application: in
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#lang scribble/doc
|
||||
@(require "common.ss")
|
||||
@(require "common.rkt")
|
||||
|
||||
@title{Additional Utilities}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#lang scribble/doc
|
||||
@(require "common.ss")
|
||||
@(require "common.rkt")
|
||||
|
||||
@title{Quick Start for a Test Drive}
|
||||
|
||||
|
@ -19,22 +19,22 @@
|
|||
NOTE: For real use, you need a new key.}
|
||||
|
||||
@item{Create a file @filepath{users.rktd} with the following content:
|
||||
@schemeblock[
|
||||
@racketblock[
|
||||
((tester ("8fe4c11451281c094a6578e6ddbf5eed"
|
||||
"Tester" "1" "test@cs")))]}
|
||||
|
||||
@item{Make a @filepath{test} subdirectory in your new directory.}
|
||||
|
||||
@item{Create a file @filepath{config.rktd} with the following content:
|
||||
@schemeblock[((active-dirs ("test")))]}
|
||||
@racketblock[((active-dirs ("test")))]}
|
||||
|
||||
@item{In your new directory, run
|
||||
@commandline{gracket-text -l handin-server}}
|
||||
|
||||
@item{In the @filepath{handin-client} collection, edit
|
||||
@filepath{info.ss} and uncomment the lines that define
|
||||
@scheme[server:port], @scheme[tools], @scheme[tool-names], and
|
||||
@scheme[tool-icons].}
|
||||
@filepath{info.rkt} and uncomment the lines that define
|
||||
@racket[server:port], @racket[tools], @racket[tool-names], and
|
||||
@racket[tool-icons].}
|
||||
|
||||
@item{Run @commandline{raco setup -l handin-client}
|
||||
|
||||
|
@ -44,7 +44,7 @@
|
|||
@item{Start DrRacket, click @onscreen{Handin} to run the client,
|
||||
submit with username ``@tt{tester}'' and password ``@tt{pw}''.
|
||||
|
||||
The submitted file will be @filepath{.../test/tester/handin.scm}.}
|
||||
The submitted file will be @filepath{.../test/tester/handin.rkt}.}
|
||||
|
||||
@item{Check the status of your submission by pointing a web browser at
|
||||
@tt{https://localhost:7979/}. Note the ``s'' in ``@tt{https}''. Use
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#lang scribble/doc
|
||||
@(require "common.ss")
|
||||
@(require "common.rkt")
|
||||
|
||||
@title{Sandbox}
|
||||
|
||||
@defmodule[handin-server/sandbox]
|
||||
|
||||
This is just a wrapper around the sandbox engine from MzLib. It
|
||||
This is just a wrapper around the Racket sandbox engine. It
|
||||
configures it for use with the handin server.
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#lang scribble/doc
|
||||
@(require "common.ss")
|
||||
@(require "common.rkt")
|
||||
|
||||
@title{Handin-Server and Client}
|
||||
|
||||
The @filepath{handin-server} collection directory contains a server to be run by a
|
||||
course instructor for accepting homework assignments and reporting on
|
||||
submitted assignments.
|
||||
The @filepath{handin-server} collection directory contains a server to
|
||||
be run by a course instructor for accepting homework assignments and
|
||||
reporting on submitted assignments.
|
||||
|
||||
The @filepath{handin-client} collection directory contains a client to be
|
||||
customized then re-distributed to students in the course. The
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#lang scribble/doc
|
||||
@(require "common.ss")
|
||||
@(require "common.rkt")
|
||||
|
||||
@title[#:tag "server-setup"]{Server Setup}
|
||||
|
||||
|
@ -27,102 +27,102 @@ This directory contains the following files and sub-directories:
|
|||
The following keys can be used:
|
||||
|
||||
@itemize[
|
||||
@item{@indexed-scheme[active-dirs] --- a list of directories that
|
||||
@item{@indexed-racket[active-dirs] --- a list of directories that
|
||||
are active submissions, relative to the current directory or
|
||||
absolute; the last path element for each of these (and
|
||||
@schemeid[inactive-dirs] below) should be unique, and is used to
|
||||
@racketid[inactive-dirs] below) should be unique, and is used to
|
||||
identify the submission (for example, in the client's submission
|
||||
dialog and in the status servlet). If a specified directory does
|
||||
not exist, it will be created.}
|
||||
|
||||
@item{@indexed-scheme[inactive-dirs] --- a list of inactive
|
||||
@item{@indexed-racket[inactive-dirs] --- a list of inactive
|
||||
submission directories (see above for details).}
|
||||
|
||||
@item{@indexed-scheme[port-number] --- the port for the main handin
|
||||
@item{@indexed-racket[port-number] --- the port for the main handin
|
||||
server; the default is 7979.}
|
||||
|
||||
@item{@indexed-scheme[use-https] --- determines whether to start an
|
||||
@item{@indexed-racket[use-https] --- determines whether to start an
|
||||
embedded web server for handin status reports; the default is
|
||||
@scheme[#t].}
|
||||
@racket[#t].}
|
||||
|
||||
@item{@indexed-scheme[session-timeout] --- number of seconds before
|
||||
@item{@indexed-racket[session-timeout] --- number of seconds before
|
||||
the session times-out. The client is given this many seconds for
|
||||
the login stage and then starts again so the same number of
|
||||
seconds is given for the submit-validation process; the default is
|
||||
300.}
|
||||
|
||||
@item{@indexed-scheme[session-memory-limit] --- maximum size in
|
||||
@item{@indexed-racket[session-memory-limit] --- maximum size in
|
||||
bytes of memory allowed for per-session computation, if
|
||||
per-session limits are supported (i.e., when using GRacket and
|
||||
Racket with the (default) exact garbage collector and memory
|
||||
accounting); the default is 40000000.}
|
||||
|
||||
@item{@indexed-scheme[default-file-name] --- the default filename
|
||||
@item{@indexed-racket[default-file-name] --- the default filename
|
||||
that will be saved with the submission contents. The default is
|
||||
@filepath{handin.scm}.}
|
||||
@filepath{handin.rkt}.}
|
||||
|
||||
@item{@indexed-scheme[max-upload] --- maximum size in bytes of an
|
||||
@item{@indexed-racket[max-upload] --- maximum size in bytes of an
|
||||
acceptable submission; the default is 500000.}
|
||||
|
||||
@item{@indexed-scheme[max-upload-keep] --- maximum index of
|
||||
@item{@indexed-racket[max-upload-keep] --- maximum index of
|
||||
submissions to keep; the most recent submission is
|
||||
@filepath{handin.scm} (by default), the next oldest is in
|
||||
@filepath{BACKUP-0/handin.scm}, next oldest is
|
||||
@filepath{BACKUP-1/handin.scm}, etc. The default is 9.}
|
||||
@filepath{handin.rkt} (by default), the next oldest is in
|
||||
@filepath{BACKUP-0/handin.rkt}, next oldest is
|
||||
@filepath{BACKUP-1/handin.rkt}, etc. The default is 9.}
|
||||
|
||||
@item{@indexed-scheme[user-regexp] --- a regular expression that is
|
||||
used to validate usernames; alternatively, this can be @scheme[#f]
|
||||
@item{@indexed-racket[user-regexp] --- a regular expression that is
|
||||
used to validate usernames; alternatively, this can be @racket[#f]
|
||||
meaning no restriction, or a list of permitted strings. Young
|
||||
students often choose exotic usernames that are impossible to
|
||||
remember, and forget capitalization, so the default is fairly
|
||||
strict--- @scheme[#rx"^[a-z][a-z0-9]+$"]; a @litchar{+} is always
|
||||
strict--- @racket[#rx"^[a-z][a-z0-9]+$"]; a @litchar{+} is always
|
||||
disallowed in a username, since it is used in a submission username
|
||||
to specify joint work.}
|
||||
|
||||
@item{@indexed-scheme[user-desc] --- a plain-words description of
|
||||
@item{@indexed-racket[user-desc] --- a plain-words description of
|
||||
the acceptable username format (according to user-regexp above);
|
||||
@scheme[#f] stands for no description; the default is
|
||||
@scheme["alphanumeric string"] which matches the default
|
||||
@racket[#f] stands for no description; the default is
|
||||
@racket["alphanumeric string"] which matches the default
|
||||
user-regexp.}
|
||||
|
||||
@item{@indexed-scheme[username-case-sensitive] --- a boolean; when
|
||||
@scheme[#f], usernames are case-folded for all purposes; defaults
|
||||
to @scheme[#f] (note that you should not set this to @scheme[#t]
|
||||
@item{@indexed-racket[username-case-sensitive] --- a boolean; when
|
||||
@racket[#f], usernames are case-folded for all purposes; defaults
|
||||
to @racket[#f] (note that you should not set this to @racket[#t]
|
||||
on Windows or when using other case-insensitive filesystems, since
|
||||
usernames are used as directory names).}
|
||||
|
||||
@item{@indexed-scheme[allow-new-users] --- a boolean indicating
|
||||
@item{@indexed-racket[allow-new-users] --- a boolean indicating
|
||||
whether to allow new-user requests from a client tool; the default
|
||||
is @scheme[#f].}
|
||||
is @racket[#f].}
|
||||
|
||||
@item{@indexed-scheme[allow-change-info] --- a boolean indicating
|
||||
@item{@indexed-racket[allow-change-info] --- a boolean indicating
|
||||
whether to allow changing user information from a client tool
|
||||
(changing passwords is always possible); the default is
|
||||
@scheme[#f].}
|
||||
@racket[#f].}
|
||||
|
||||
@item{@indexed-scheme[master-password] --- a string for an MD5 hash
|
||||
@item{@indexed-racket[master-password] --- a string for an MD5 hash
|
||||
for a password that allows login as any user; the default is
|
||||
@scheme[#f], which disables the password.}
|
||||
@racket[#f], which disables the password.}
|
||||
|
||||
@item{@indexed-scheme[log-output] --- a boolean that controls
|
||||
@item{@indexed-racket[log-output] --- a boolean that controls
|
||||
whether the handin server log is written on the standard output;
|
||||
defaults to @scheme[#t].}
|
||||
defaults to @racket[#t].}
|
||||
|
||||
@item{@indexed-scheme[log-file] --- a path (relative to handin
|
||||
@item{@indexed-racket[log-file] --- a path (relative to handin
|
||||
server directory or absolute) that specifies a filename for the
|
||||
handin server log (possibly combined with the @schemeid[log-output]
|
||||
option), or @scheme[#f] for no log file; defaults to
|
||||
handin server log (possibly combined with the @racketid[log-output]
|
||||
option), or @racket[#f] for no log file; defaults to
|
||||
@filepath{log}.}
|
||||
|
||||
@item{@indexed-scheme[web-log-file] --- a path (relative to handin
|
||||
@item{@indexed-racket[web-log-file] --- a path (relative to handin
|
||||
server directory or absolute) that specifies a filename for
|
||||
logging the internal HTTPS status web server; or @scheme[#f] (the
|
||||
logging the internal HTTPS status web server; or @racket[#f] (the
|
||||
default) to disable this log.}
|
||||
|
||||
@item{@indexed-scheme[extra-fields] --- a list that describes extra
|
||||
@item{@indexed-racket[extra-fields] --- a list that describes extra
|
||||
string fields of information for student records; each element in
|
||||
this list is a list of three values: the name of the field, the
|
||||
regexp (or @scheme[#f], or a list of permitted string values), and
|
||||
regexp (or @racket[#f], or a list of permitted string values), and
|
||||
a string describing acceptable strings. The default is
|
||||
@verbatim[#:indent 2]|{
|
||||
(("Full Name" #f #f)
|
||||
|
@ -148,7 +148,7 @@ This directory contains the following files and sub-directories:
|
|||
@; JBC: a hyperlink here for users.rktd?
|
||||
|
||||
The second item in a field description can also be the symbol
|
||||
@schemeid[-], which marks this field as one that is hidden from the
|
||||
@racketid[-], which marks this field as one that is hidden from the
|
||||
user interface: students will not see it and will not be able to
|
||||
provide or modify it; when a new student creates an account, such
|
||||
fields will be left empty. This is useful for adding information
|
||||
|
@ -157,11 +157,11 @@ This directory contains the following files and sub-directories:
|
|||
@filepath{users.rktd} file and fill in such information. (The third
|
||||
element for such descriptors is ignored.)}
|
||||
|
||||
@item{@indexed-scheme[hook-file] --- a path (relative to handin
|
||||
@item{@indexed-racket[hook-file] --- a path (relative to handin
|
||||
server directory or absolute) that specifies a filename that
|
||||
contains a `hook' module. This is useful as a general device for
|
||||
customizing the server through Scheme code. The file is expected
|
||||
to contain a module that provides a @scheme[hook] function, which
|
||||
customizing the server through Racket code. The file is expected
|
||||
to contain a module that provides a @racket[hook] function, which
|
||||
should be receiving three arguments:
|
||||
|
||||
@defproc[(hook [operation symbol?]
|
||||
|
@ -169,22 +169,22 @@ This directory contains the following files and sub-directories:
|
|||
[relevant-info (listof (list/c symbol? any))])
|
||||
void?]{
|
||||
|
||||
The @scheme[operation] argument indicates the operation that is
|
||||
The @racket[operation] argument indicates the operation that is
|
||||
now taking place. It can be one of the following:
|
||||
@indexed-scheme['server-start], @indexed-scheme['server-connect],
|
||||
@indexed-scheme['user-create], @indexed-scheme['user-change],
|
||||
@indexed-scheme['login], @indexed-scheme['submission-received],
|
||||
@indexed-scheme['submission-committed],
|
||||
@indexed-scheme['submission-retrieved],
|
||||
@indexed-scheme['status-login], or
|
||||
@indexed-scheme['status-file-get].
|
||||
@indexed-racket['server-start], @indexed-racket['server-connect],
|
||||
@indexed-racket['user-create], @indexed-racket['user-change],
|
||||
@indexed-racket['login], @indexed-racket['submission-received],
|
||||
@indexed-racket['submission-committed],
|
||||
@indexed-racket['submission-retrieved],
|
||||
@indexed-racket['status-login], or
|
||||
@indexed-racket['status-file-get].
|
||||
|
||||
The @scheme[connection-context] argument is a datum that specifies
|
||||
The @racket[connection-context] argument is a datum that specifies
|
||||
the connection context (a number for handin connections, a
|
||||
@schemeid[wN] symbol for servlet connections, and @scheme[#f] for
|
||||
@racketid[wN] symbol for servlet connections, and @racket[#f] for
|
||||
other server operations).
|
||||
|
||||
The @scheme[relevant-info] contains an alist of information
|
||||
The @racket[relevant-info] contains an alist of information
|
||||
relevant to this operation. Currently, the hook is used in
|
||||
several places after an operation has completed.
|
||||
|
||||
|
@ -192,8 +192,8 @@ This directory contains the following files and sub-directories:
|
|||
notification messages when users are created or their
|
||||
information has changed:
|
||||
|
||||
@schememod[
|
||||
mzscheme
|
||||
@racketmod[
|
||||
racket/base
|
||||
(provide hook)
|
||||
(require net/sendmail)
|
||||
(define (hook what session alist)
|
||||
|
@ -210,7 +210,7 @@ This directory contains the following files and sub-directories:
|
|||
re-read, and options are reloaded. A few options are fixed at startup
|
||||
time: port numbers and log file specs are fixed as configured at
|
||||
startup. All other options will change the behavior of the running
|
||||
server (but things like @schemeid[username-case-sensitive?] it would
|
||||
server (but things like @racketid[username-case-sensitive?] it would
|
||||
be unwise to do so). (For safety, options are not reloaded until the
|
||||
file parses correctly, but make sure that you don't save a copy that
|
||||
has inconsistent options: it is best to create a new configuration
|
||||
|
@ -221,25 +221,25 @@ This directory contains the following files and sub-directories:
|
|||
@item{@filepath{users.rktd} (created if not present when a user is added):
|
||||
keeps the list of user accounts, along with the associated password
|
||||
(actually the MD5 hash of the password), and extra string fields as
|
||||
specified by the @schemeid[extra-fields] configuration entry (in the
|
||||
specified by the @racketid[extra-fields] configuration entry (in the
|
||||
same order). The file format is
|
||||
@verbatim[#:indent 2]{
|
||||
((<username-sym> (<pw-md5-str> <extra-field> ...))
|
||||
...)}
|
||||
|
||||
For example, the default @schemeid[extra-field] setting will make
|
||||
For example, the default @racketid[extra-field] setting will make
|
||||
this:
|
||||
@verbatim[#:indent 2]{
|
||||
((<username-sym> (<pw-md5-str> <full-name> <id> <email>))
|
||||
...)}
|
||||
|
||||
Usernames that begin with ``solution'' are special. They are used by
|
||||
the HTTPS status server. Independent of the @schemeid[user-regexp]
|
||||
and @schemeid[username-case-sensitive?] configuration items, usernames
|
||||
the HTTPS status server. Independent of the @racketid[user-regexp]
|
||||
and @racketid[username-case-sensitive?] configuration items, usernames
|
||||
are not allowed to contain characters that are illegal in Windows
|
||||
pathnames, and they cannot end or begin in spaces or periods.
|
||||
|
||||
If the @schemeid[allow-new-users] configuration allows new users, the
|
||||
If the @racketid[allow-new-users] configuration allows new users, the
|
||||
@filepath{users.rktd} file can be updated by the server with new users.
|
||||
It can always be updated by the server to change passwords.
|
||||
|
||||
|
@ -247,13 +247,13 @@ This directory contains the following files and sub-directories:
|
|||
@filepath{/etc/passwd} or @filepath{/etc/shadow}), then you can
|
||||
construct a @filepath{users.rktd} file that will allow users to use
|
||||
their normal passwords. To achieve this, use a list with
|
||||
@schemeid[unix] as the first element and the system's encrypted
|
||||
@racketid[unix] as the first element and the system's encrypted
|
||||
password string as the second element. Such passwords can be used,
|
||||
but when users change them, a plain md5 hash will be used.
|
||||
|
||||
You can combine this with other fields from the password file to
|
||||
create your @filepath{users.rktd}, but make sure you have information
|
||||
that matches your @schemeid[extra-fields] specification. For example,
|
||||
that matches your @racketid[extra-fields] specification. For example,
|
||||
given this system file:
|
||||
@verbatim[#:indent 2]|{
|
||||
foo:wRzN1u5q2SqRD:1203:1203:L.E. Foo :/home/foo:/bin/tcsh
|
||||
|
@ -262,7 +262,7 @@ This directory contains the following files and sub-directories:
|
|||
@verbatim[#:indent 2]|{
|
||||
((foo ((unix "wRzN1u5q2SqRD") "L.E. Foo" "?"))
|
||||
(bar ((unix "$1$dKlU0OkJ$t63TzKz") "Bar Z. Lie" "?")))}|
|
||||
which can be combined with this setting for @schemeid[extra-fields] in
|
||||
which can be combined with this setting for @racketid[extra-fields] in
|
||||
your @filepath{config.rktd}:
|
||||
@verbatim[#:indent 2]{
|
||||
...
|
||||
|
@ -274,15 +274,15 @@ This directory contains the following files and sub-directories:
|
|||
their TA name.
|
||||
|
||||
Finally, a password value can be a list that begins with a
|
||||
@schemeid[plaintext] symbol, which will be used without encryption.
|
||||
@racketid[plaintext] symbol, which will be used without encryption.
|
||||
This may be useful for manually resetting a forgotten passwords.}
|
||||
|
||||
@item{@filepath{log} (or any other name that the @schemeid[log-file]
|
||||
@item{@filepath{log} (or any other name that the @racketid[log-file]
|
||||
configuration option specifies (if any), created if not present,
|
||||
appended otherwise): records connections and actions, where each entry
|
||||
is of the form
|
||||
@verbatim{[<id>|<time>] <msg>}
|
||||
where @schemeid[<id>] is an integer representing the connection
|
||||
where @racketid[<id>] is an integer representing the connection
|
||||
(numbered consecutively from 1 when the server starts), ``@tt{-}'' for
|
||||
a message without a connection, and ``@tt{wN}'' for a message from the
|
||||
status servlet.}
|
||||
|
@ -290,11 +290,11 @@ This directory contains the following files and sub-directories:
|
|||
@item{Active and inactive assignment directories (which you can put in
|
||||
a nested directory for convenience, or specify a different absolute
|
||||
directory), as specified by the configuration file using the
|
||||
@schemeid[active-dirs] and @schemeid[inactive-dirs]. A list of active
|
||||
@racketid[active-dirs] and @racketid[inactive-dirs]. A list of active
|
||||
assignment directories (the last path element in each specified path
|
||||
is used as a label) is sent to the client tool when a student clicks
|
||||
@onscreen{Handin}. The assignment labels are ordered in the student's
|
||||
menu using @scheme[string<?], and the first assignment is the default
|
||||
menu using @racket[string<?], and the first assignment is the default
|
||||
selection.
|
||||
|
||||
Within each assignment directory, the student id is used for a
|
||||
|
@ -317,20 +317,20 @@ This directory contains the following files and sub-directories:
|
|||
might not finish. When the server is started, it automatically runs
|
||||
the cleanup process for each student directory.
|
||||
|
||||
Within a student directory, a @filepath{handin.scm} file (or some
|
||||
other name if the @schemeid[default-file-name] option is set) contains
|
||||
the actual submission. A @scheme[checker] procedure can change this
|
||||
Within a student directory, a @filepath{handin.rkt} file (or some
|
||||
other name if the @racketid[default-file-name] option is set) contains
|
||||
the actual submission. A @racket[checker] procedure can change this
|
||||
default file name, and it can create additional files in an
|
||||
@filepath{ATTEMPT} directory (to be copied by the cleanup process);
|
||||
see below for more details on @schememodname[handin-server/checker].
|
||||
see below for more details on @racketmodname[handin-server/checker].
|
||||
|
||||
For submissions from a normal DrRacket frame, a submission file
|
||||
contains a copy of the student's definitions and interactions
|
||||
windows. The file is in a binary format (to support non-text code),
|
||||
and opening the file directly in DrRacket shows the definitions
|
||||
part. To get both the definitions and interactions parts, the file
|
||||
can be parsed with @scheme[unpack-submission] from
|
||||
@schememodname[handin-server/utils].
|
||||
can be parsed with @racket[unpack-submission] from
|
||||
@racketmodname[handin-server/utils].
|
||||
|
||||
To submit an assignment as a group, students use a concatenation of
|
||||
usernames separated by ``@tt{+}'' and any number of spaces (e.g.,
|
||||
|
@ -343,19 +343,19 @@ This directory contains the following files and sub-directories:
|
|||
Inactive assignment directories are used by the HTTPS status web
|
||||
server.}
|
||||
|
||||
@item{@filepath{<active-assignment>/checker.ss} (optional): a module
|
||||
that exports a @scheme[checker] function. This function receives
|
||||
@item{@filepath{<active-assignment>/checker.rkt} (optional): a module
|
||||
that exports a @racket[checker] function. This function receives
|
||||
two
|
||||
@; JBC: use defproc here?
|
||||
arguments: a username list and a submission as a byte string. (See
|
||||
also @scheme[unpack-submission], etc. from
|
||||
@schememodname[handin-server/utils].) To
|
||||
reject the submission, the @scheme[checker] function can raise an
|
||||
also @racket[unpack-submission], etc. from
|
||||
@racketmodname[handin-server/utils].) To
|
||||
reject the submission, the @racket[checker] function can raise an
|
||||
exception; the exception message will be relayed back to the
|
||||
student. The module is loaded when the current directory is the
|
||||
main server directory, so it can read files from there (but note
|
||||
that to read values from @filepath{config.rktd} it is better to use
|
||||
@scheme[get-conf]). Also, the module will be reloaded if the
|
||||
@racket[get-conf]). Also, the module will be reloaded if the
|
||||
checker file is modified; there's no need to restart the server,
|
||||
but make sure that you do not save a broken checker (i.e., do not
|
||||
save in mid-edit).
|
||||
|
@ -365,10 +365,10 @@ This directory contains the following files and sub-directories:
|
|||
the submission username was a concatenation of usernames separated
|
||||
by ``@tt{+}'').
|
||||
|
||||
The @scheme[checker] function is called with the current directory
|
||||
The @racket[checker] function is called with the current directory
|
||||
as @filepath{<active-assignment>/<username(s)>/ATTEMPT}, and the
|
||||
submission is saved in the file @filepath{handin}, and the timeout
|
||||
clock is reset to the value of the @scheme[session-timeout]
|
||||
clock is reset to the value of the @racket[session-timeout]
|
||||
configuration. The checker function can change @filepath{handin},
|
||||
and it can create additional files in this directory. (Extra
|
||||
files in the current directory will be preserved as it is later
|
||||
|
@ -378,12 +378,12 @@ This directory contains the following files and sub-directories:
|
|||
put the files in a subdirectory, it is preserved but hidden from
|
||||
the status interface.
|
||||
|
||||
The checker should return a string, such as @filepath{handin.scm},
|
||||
to use in naming the submission file, or @scheme[#f] to indicate
|
||||
The checker should return a string, such as @filepath{handin.rkt},
|
||||
to use in naming the submission file, or @racket[#f] to indicate
|
||||
that he file should be deleted (e.g., when the checker alrady
|
||||
created the submission file(s) in a different place).
|
||||
|
||||
Alternatively, the module can bind @scheme[checker] to a list of
|
||||
Alternatively, the module can bind @racket[checker] to a list of
|
||||
three procedures: a pre-checker, a checker, and a post-checker.
|
||||
All three are applied in exactly the same way as the checker (same
|
||||
arguments, and always within the submission directory), except
|
||||
|
@ -394,7 +394,7 @@ This directory contains the following files and sub-directories:
|
|||
submission directory does not have a @filepath{SUCCESS-*}
|
||||
directory, then the whole submission directory is removed. This
|
||||
is useful for checking that the user/s are valid; if you allow a
|
||||
submission only when @scheme[users] is @scheme['("foo" "bar")],
|
||||
submission only when @racket[users] is @racket['("foo" "bar")],
|
||||
and ``@tt{foo}'' tries to submit alone, then the submission
|
||||
directory for ``@tt{foo}'' should be removed to allow a proper
|
||||
submission later. Note that the timeout clock is reset only
|
||||
|
@ -406,17 +406,17 @@ This directory contains the following files and sub-directories:
|
|||
considered successful, so this function should avoid throwing an
|
||||
exception (it can, but the submission will still be in place).
|
||||
This is useful for things like notifying the user of the
|
||||
successful submission (see @scheme[message]), or sending a
|
||||
successful submission (see @racket[message]), or sending a
|
||||
``receipt'' email.}]
|
||||
|
||||
To specify only pre/post-checker, use @scheme[#f] for the one you
|
||||
To specify only pre/post-checker, use @racket[#f] for the one you
|
||||
want to omit.}
|
||||
|
||||
@item{@filepath{<[in]active-assignment>/<user(s)>/<filename>} (if
|
||||
submitted): the most recent submission for
|
||||
@tt{<[in]active-assignment>} by @tt{<user(s)>} where <filename> was
|
||||
returned by the checker (or the value of the
|
||||
@schemeid[default-file-name] configuration option if there's no
|
||||
@racketid[default-file-name] configuration option if there's no
|
||||
checker). If the submission is from multiple users, then
|
||||
``@tt{<user(s)>}'' is actually ``@tt{<user1>+<user2>}'' etc. Also, if
|
||||
the cleanup process was interrupted (by a machine failure, etc.), the
|
||||
|
@ -438,8 +438,8 @@ This directory contains the following files and sub-directories:
|
|||
]
|
||||
|
||||
The server can be run within either Racket or GRacket, but
|
||||
@schememodname[handin-server/utils] requires GRacket (which means that
|
||||
@scheme[checker] modules will likely require the server to run under
|
||||
@racketmodname[handin-server/utils] requires GRacket (which means that
|
||||
@racket[checker] modules will likely require the server to run under
|
||||
GRacket). Remember that if you're not using the (default) 3m garbage
|
||||
collector you don't get memory accounting.
|
||||
|
||||
|
@ -471,7 +471,7 @@ the correct assignment in the handin dialog.
|
|||
A student can download his/her own submissions through the handin
|
||||
dialog. This can also be done through a web server that runs
|
||||
concurrently with the handin server (on the same port) if you set the
|
||||
@scheme[use-https] option in the configuration file to @scheme[#t] (the
|
||||
@racket[use-https] option in the configuration file to @racket[#t] (the
|
||||
default). The starting URL is
|
||||
|
||||
@commandline{https://SERVER:PORT/}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#lang scribble/doc
|
||||
@(require "common.ss")
|
||||
@(require "common.rkt")
|
||||
|
||||
@title{Auto-Updater}
|
||||
|
||||
|
@ -9,20 +9,20 @@ additional functionality (collections, teachpacks, language-levels
|
|||
etc), and this functionality can change (or expected to change, for
|
||||
example, distributing per-homework teachpacks).
|
||||
|
||||
To enable this, uncomment the relevant part of the @filepath{info.ss}
|
||||
To enable this, uncomment the relevant part of the @filepath{info.rkt}
|
||||
file in the client code. It has the following three keys:
|
||||
@indexed-scheme[enable-auto-update] that turns this facility on, and
|
||||
@indexed-scheme[version-filename] and
|
||||
@indexed-scheme[package-filename] which are the expected file names of
|
||||
@indexed-racket[enable-auto-update] that turns this facility on, and
|
||||
@indexed-racket[version-filename] and
|
||||
@indexed-racket[package-filename] which are the expected file names of
|
||||
the version file and the @filepath{.plt} file relative to the course
|
||||
web address (the value of the @scheme[web-address] key). Also,
|
||||
web address (the value of the @racket[web-address] key). Also,
|
||||
include in your client collection a @filepath{version} file that
|
||||
contains a single number that is its version. Use a big integer that
|
||||
holds the time of this collection in a @tt{YYYYMMDDHHMM} format.
|
||||
|
||||
When students install the client, every time DrRacket starts, it will
|
||||
automatically check the version from the web page (as specified by the
|
||||
@scheme[web-address] and @scheme[version-filename] keys), and if that
|
||||
@racket[web-address] and @racket[version-filename] keys), and if that
|
||||
contains a bigger number, it will offer the students to download and
|
||||
install the new version. So, every time you want to distribute a new
|
||||
version, you build a new @filepath{.plt} file that contains a new
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#lang scribble/doc
|
||||
@(require "common.ss")
|
||||
@(require "common.rkt")
|
||||
|
||||
@title{Utilities}
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
|||
@defproc[(unpack-submission [submission bytes?])
|
||||
(values (is-a?/c text%) (is-a?/c text%))]{
|
||||
|
||||
Returns two @scheme[text%] objects corresponding to the submitted
|
||||
Returns two @racket[text%] objects corresponding to the submitted
|
||||
definitions and interactions windows.}
|
||||
|
||||
@defproc[(make-evaluator/submission
|
||||
|
@ -27,18 +27,18 @@
|
|||
[content bytes?])
|
||||
(any/c . -> . any)]{
|
||||
|
||||
Like @scheme[make-evaluator], but the definitions content is
|
||||
Like @racket[make-evaluator], but the definitions content is
|
||||
supplied as a submission byte string. The byte string is opened for
|
||||
reading, with line-counting enabled.
|
||||
|
||||
In addition to the language specification for
|
||||
@scheme[make-evaluator], the @scheme[language] argument can be a
|
||||
list that begins with @scheme['module]. In this case,
|
||||
@scheme[make-module-language] is used to create an evaluator, and
|
||||
@racket[make-evaluator], the @racket[language] argument can be a
|
||||
list that begins with @racket['module]. In this case,
|
||||
@racket[make-module-language] is used to create an evaluator, and
|
||||
the module code must be using the specified language in its
|
||||
language position. In this case, the @scheme[requires-paths]
|
||||
language position. In this case, the @racket[requires-paths]
|
||||
argument is used only for paths that are allowed to be accessed (the
|
||||
@scheme[_allow-read] argument to @scheme[make-evaluator], since the
|
||||
@racket[_allow-read] argument to @racket[make-evaluator], since the
|
||||
submission is expected to be a complete submission.)}
|
||||
|
||||
@defproc[(call-with-evaluator
|
||||
|
@ -51,14 +51,14 @@
|
|||
[proc (any/c . -> . any)])
|
||||
any]{
|
||||
|
||||
Calls @scheme[proc] with an evaluator for the given language,
|
||||
Calls @racket[proc] with an evaluator for the given language,
|
||||
teachpack paths, and initial definition content as supplied by
|
||||
@scheme[input-program] (see @scheme[make-evaluator]). It also sets
|
||||
@racket[input-program] (see @racket[make-evaluator]). It also sets
|
||||
the current error-value print handler to print values in a way
|
||||
suitable for @scheme[language], it initializes
|
||||
@scheme[set-run-status] with @scheme["executing your code"], and it
|
||||
suitable for @racket[language], it initializes
|
||||
@racket[set-run-status] with @racket["executing your code"], and it
|
||||
catches all exceptions to re-raise them in a form suitable as a
|
||||
submission error. See @scheme[make-evaluator/submission] for
|
||||
submission error. See @racket[make-evaluator/submission] for
|
||||
further details.}
|
||||
|
||||
@defproc[(call-with-evaluator/submission
|
||||
|
@ -71,23 +71,23 @@
|
|||
[proc (any/c . -> . any)])
|
||||
any]{
|
||||
|
||||
Like @scheme[call-with-evaluator], but the definitions content is
|
||||
Like @racket[call-with-evaluator], but the definitions content is
|
||||
supplied as a byte string. The byte string is opened for reading,
|
||||
with line-counting enabled. See @scheme[call-with-evaluator] and
|
||||
@scheme[make-evaluator/submission] for further details.}
|
||||
with line-counting enabled. See @racket[call-with-evaluator] and
|
||||
@racket[make-evaluator/submission] for further details.}
|
||||
|
||||
@; JBC: this contract is probably wrong
|
||||
@; JBC: does this eval accept an optional namespace?
|
||||
@defproc[(evaluate-all [source any]
|
||||
[input-port port?]
|
||||
[eval (any/c . -> . any)]) any]{
|
||||
Like @scheme[load] on an input port.}
|
||||
Like @racket[load] on an input port.}
|
||||
|
||||
@defproc[(evaluate-submission [submission bytes?]
|
||||
[eval (any/c . -> . any)])
|
||||
any]{
|
||||
|
||||
Like @scheme[load] on a submission byte string.}
|
||||
Like @racket[load] on a submission byte string.}
|
||||
|
||||
@defproc[(check-proc [eval (any/c . -> . any)]
|
||||
[expect-v any/c]
|
||||
|
@ -96,21 +96,21 @@
|
|||
[arg any/c] ...)
|
||||
any]{
|
||||
|
||||
Calls the function named @scheme[proc-name] using the evaluator
|
||||
@scheme[eval], giving it the (unquoted) arguments @scheme[arg ...]
|
||||
Let @scheme[result-v] be the result of the call; unless
|
||||
@scheme[(compare-proc result-v expect-v)] is true, an exception is
|
||||
Calls the function named @racket[proc-name] using the evaluator
|
||||
@racket[eval], giving it the (unquoted) arguments @racket[arg ...]
|
||||
Let @racket[result-v] be the result of the call; unless
|
||||
@racket[(compare-proc result-v expect-v)] is true, an exception is
|
||||
raised.}
|
||||
|
||||
Every exception or result mismatch during the call to
|
||||
@scheme[compare-proc] is phrased suitably for the handin client.
|
||||
@racket[compare-proc] is phrased suitably for the handin client.
|
||||
|
||||
@defproc[(check-defined [eval (any/c . -> . any)]
|
||||
[name symbol?])
|
||||
any]{
|
||||
|
||||
Checks whether @scheme[name] is defined in the evaluator
|
||||
@scheme[eval], and raises an error if not (suitably phrased for the
|
||||
Checks whether @racket[name] is defined in the evaluator
|
||||
@racket[eval], and raises an error if not (suitably phrased for the
|
||||
handin client). If it is defined as non-syntax, its value is
|
||||
returned. Warning: in the beginner language level, procedure
|
||||
definitions are bound as syntax.}
|
||||
|
@ -120,8 +120,8 @@ Every exception or result mismatch during the call to
|
|||
@defproc[(look-for-tests [text (is-a?/c text%)] [name symbol?] [n number?])
|
||||
any]{
|
||||
|
||||
Inspects the given @scheme[text%] object to determine whether it
|
||||
contains at least @scheme[n] tests for the function @scheme[name].
|
||||
Inspects the given @racket[text%] object to determine whether it
|
||||
contains at least @racket[n] tests for the function @racket[name].
|
||||
The tests must be top-level expressions.}
|
||||
|
||||
@defproc[(user-construct [eval (any/c . -> . any)]
|
||||
|
@ -129,7 +129,7 @@ Every exception or result mismatch during the call to
|
|||
[arg any/c] ...)
|
||||
any]{
|
||||
|
||||
Like @scheme[check-proc], but with no result checking. This
|
||||
Like @racket[check-proc], but with no result checking. This
|
||||
function is often useful for calling a student-defined constructor.}
|
||||
|
||||
@defparam[test-history-enabled on? any/c]{
|
||||
|
@ -145,22 +145,22 @@ Every exception or result mismatch during the call to
|
|||
[styles (listof (or/c 'ok 'ok-cancel 'yes-no
|
||||
'caution 'stop))])
|
||||
any])]{
|
||||
The first case of @scheme[message] is intended to update the client on
|
||||
The first case of @racket[message] is intended to update the client on
|
||||
the current activity --- it updates the status line in the submission
|
||||
dialog box on the client. Use it to indicate operations that might
|
||||
take a while and/or indicate progress during these operations.
|
||||
|
||||
In the second case, where @scheme['final] is used as a flag, does not
|
||||
In the second case, where @racket['final] is used as a flag, does not
|
||||
show the text immediately --- instead, it causes it to be displayed in
|
||||
the status line after a successful submission instead of the usual
|
||||
``Handin successful'' message. This is useful for submissions that
|
||||
are accepted but had some problems.
|
||||
|
||||
The third case, when @scheme[styles] is a list of symbols, opens a
|
||||
@scheme[message-box] dialog on the client side, and the resulting
|
||||
value is returned as the result of @scheme[message]. The
|
||||
@scheme[styles] list is passed as the @scheme[style] argument to
|
||||
@scheme[message-box]. You can use this to send warnings to the
|
||||
The third case, when @racket[styles] is a list of symbols, opens a
|
||||
@racket[message-box] dialog on the client side, and the resulting
|
||||
value is returned as the result of @racket[message]. The
|
||||
@racket[styles] list is passed as the @racket[style] argument to
|
||||
@racket[message-box]. You can use this to send warnings to the
|
||||
student or to ask for confirmation, for example, ``your submission
|
||||
does not pass 3 tests, continue?''.}
|
||||
|
||||
|
@ -172,16 +172,16 @@ Every exception or result mismatch during the call to
|
|||
session aborted.}
|
||||
|
||||
@defparam[current-value-printer proc (any/c . -> . string?)]{
|
||||
Controls how values are printed. The @scheme[proc] must be a
|
||||
procedure that expects a Scheme value and returns a string
|
||||
Controls how values are printed. The @racket[proc] must be a
|
||||
procedure that expects a Racket value and returns a string
|
||||
representation for it. The default value printer uses
|
||||
@scheme[pretty-print], with DrRacket-like settings.}
|
||||
@racket[pretty-print], with DrRacket-like settings.}
|
||||
|
||||
@defproc[(reraise-exn-as-submission-problem [thunk (-> any)]) any]{
|
||||
|
||||
Calls @scheme[thunk] in a context that catches exceptions and
|
||||
Calls @racket[thunk] in a context that catches exceptions and
|
||||
re-raises them in a form suitable as a submission error. It returns
|
||||
the value returned by @scheme[thunk] if no exception occurs.}
|
||||
the value returned by @racket[thunk] if no exception occurs.}
|
||||
|
||||
@defproc[(log-line [fmt string?] [args any/c] ...) void?]{
|
||||
Produces a line in the server log file, using the given format
|
||||
|
@ -193,14 +193,14 @@ Every exception or result mismatch during the call to
|
|||
@defproc[(timeout-control [msg string?]) void?]{
|
||||
|
||||
Controls the timeout for this session. The timeout is initialized
|
||||
by the value of the @scheme[session-timeout] configuration entry,
|
||||
by the value of the @racket[session-timeout] configuration entry,
|
||||
and the checker can use this procedure to further control it: if
|
||||
@scheme[msg] is @scheme['reset] the timeout is reset to
|
||||
@scheme[session-timeout] seconds; if @scheme[msg] is a number the
|
||||
@racket[msg] is @racket['reset] the timeout is reset to
|
||||
@racket[session-timeout] seconds; if @racket[msg] is a number the
|
||||
timeout will be set to that many seconds in the future. The timeout
|
||||
can be completely disabled by @scheme[(timeout-control #f)]. (Note
|
||||
can be completely disabled by @racket[(timeout-control #f)]. (Note
|
||||
that before the checker is used (after the pre-checker, if
|
||||
specified), the timer will be reset to the @scheme['session-timeout]
|
||||
specified), the timer will be reset to the @racket['session-timeout]
|
||||
value.)}
|
||||
|
||||
@defthing[server-dir path-string?]{
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#lang scribble/doc
|
||||
@(require "common.ss")
|
||||
@(require "common.rkt")
|
||||
|
||||
@title[#:tag "wheres-the-collection"]{Where is the Collection?}
|
||||
|
||||
If you obtained the server and client by installing a @filepath{.plt}
|
||||
file, then the @filepath{handin-server} and @filepath{handin-client}
|
||||
directories might be in your Racket addon space. Start Racket, and
|
||||
enter @schemeblock[(collection-path "handin-server")]
|
||||
@schemeblock[(collection-path "handin-client")] to find out where
|
||||
enter @racketblock[(collection-path "handin-server")]
|
||||
@racketblock[(collection-path "handin-client")] to find out where
|
||||
these collections are.
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
#lang scheme/base
|
||||
#lang racket/base
|
||||
|
||||
(require scheme/class mred scheme/pretty
|
||||
(require racket/class racket/gui/base racket/pretty
|
||||
(prefix-in pc: mzlib/pconvert)
|
||||
(only-in "main.ss" timeout-control)
|
||||
"private/run-status.ss"
|
||||
"private/config.ss"
|
||||
"private/logger.ss"
|
||||
"sandbox.ss")
|
||||
(only-in "main.rkt" timeout-control)
|
||||
"private/run-status.rkt"
|
||||
"private/config.rkt"
|
||||
"private/logger.rkt"
|
||||
"sandbox.rkt")
|
||||
|
||||
(provide (all-from-out "sandbox.ss")
|
||||
(provide (all-from-out "sandbox.rkt")
|
||||
|
||||
get-conf
|
||||
log-line
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
#lang scheme/base
|
||||
#lang racket/base
|
||||
|
||||
(require scheme/list
|
||||
scheme/path
|
||||
scheme/file
|
||||
scheme/date
|
||||
(require racket/list
|
||||
racket/path
|
||||
racket/file
|
||||
racket/date
|
||||
net/uri-codec
|
||||
web-server/servlet
|
||||
handin-server/private/md5
|
||||
handin-server/private/logger
|
||||
handin-server/private/config
|
||||
handin-server/private/hooker
|
||||
"run-servlet.ss")
|
||||
"run-servlet.rkt")
|
||||
|
||||
(define (aget alist key)
|
||||
(cond [(assq key alist) => cdr] [else #f]))
|
||||
|
@ -182,7 +182,8 @@
|
|||
(let* ([data (file->bytes file)]
|
||||
[html? (regexp-match? #rx"[.]html?$" (string-foldcase tag))]
|
||||
[wxme? (regexp-match?
|
||||
#rx#"^(?:#reader[(]lib\"read.ss\"\"wxme\"[)])?WXME" data)])
|
||||
#rx#"^(?:#reader[(]lib\"read.(?:ss|rkt)\"\"wxme\"[)])?WXME"
|
||||
data)])
|
||||
(make-response/full 200 #"Okay" (current-seconds)
|
||||
(cond [html? #"text/html"]
|
||||
[wxme? #"application/data"]
|
||||
|
|
Loading…
Reference in New Issue
Block a user