API¶
If you are looking for information on a specific function, class or method, this part of the documentation is for you.
This API documentation is generated using autodoc module of sphinx and curated documentation within source files. It is intented for developers to want to use classes and methods of worksheet.cc project. See Tutorial for an examples of usage.
Library¶
- class wklib.Exercise(content: str)¶
This class models an exercise which might depend on some parameters. This exercise can be
evaluated
to produce an specific result which anyone could use as an usual exercise in classrooms.To create an instance, you need to pass some text as its content:
>>> import wklib >>> e = wklib.Exercise("Calculate 2 + 2")
In that example, the exercise does not depend on anything. But this could depend on some parameters. By convention, the parameters are put in
parameters
field in YAML-headers. Thus>>> import wklib >>> e2 = wklib.Exercise(""" ... --- ... parameters: ... a: '6' ... --- ... ... Calculate {{ params['a'] }} + 2 ... """)
creates an instance of exercise to depend on parameter \(a\). Note that for accessing to the evaluation of the parameters, we use
params
hash.Every exercise has associated a date of creation which is the date of instance creation. This can be accessed with
self.creation
. This is a string with ISO 8601 format.Users can access to the content of the exercise using
wklib.Exercise.text()
method. In previous examples:>>> e.text 'Calculate 2 + 2' >>> e2.text 'Calculate {{ params['a'] }} + 2'
You can use also
self.content
, but it includes YAML headers, instead of previous method:>>> e.content 'Calculate 2 + 2' >>> e2.content '\n---\nparameters:\n a : '6'\n---\n\nCalculate {{ params['a'] }} + 2\n'
Both methods return raw content, without parameters being interpreted. Also notice that you can use simply
print(e)
because we overwrite__repr__
.To access to YAML-headers, you can use any method of
frontmatter.Post
, which can be accessed withself.post
. For example, if you want to access to all keys from YAML header, you can type:>>> sorted(e.post.keys()) [] >>> sorted(e2.post.keys()) ['parameters']
If you want to evaluated the exercise, that is, obtain an exercise with specific values of the
parameters
, then you need to usewklib.Exercise.value()
method:>>> e.value 'Calculate 2 + 2' >>> e2.value "\n---\nparameters:\n a: '6'\n---\n\nCalculate 6 + 2" >>> print(e2.value) --- parameters: a: '6' --- Calculate 6 + 2
- Parameters:
content (str) – The content of the exercise. Just a string with optional YAML headers, delimited by
---
lines at the very beginning of the text and just before the rest of the text.
- __init__(content: str)¶
Creates an
Exercise
form a content string, which has an optional YAML-header.The exercise consists of three variables:
self.content
which is a copy of
content
.self.post
which is a
frontmatter.Post
builtfrom
thecontent
. It allows to manage easyly the optional YAML block.self.creation
The time of creation:
datetime.datetime.now()
represented asdatetime.datetime.isoformat()
.
- Parameters:
content (str) – The content of the exercise. Just a string with optional YAML headers
- __repr__()¶
Returns
self.content
of the exercise. This includes YAML header, if any.
- property text: str¶
Returns the text of the exercise without YAML header, if any.
>>> import wklib >>> e = wklib.Exercise(""" ... --- ... solution: 4 ... resolution: 2 + 2 = (1 +1) + (1 + 1) = 1 + 1 + 1 + 1 = 4 ... --- ... ... Calculate 2 + 2 ... """) >>> e.text 'Calculate 2 + 2'
- Returns:
returns the content of the exercise, that is
self.post.content
- Return type:
- property solution¶
Returns the solution of the exercise, that is
solution
if YAML header contains it as field.>>> import wklib >>> e = wklib.Exercise(""" ... --- ... solution: 4 ... resolution: 2 + 2 = (1 +1) + (1 + 1) = 1 + 1 + 1 + 1 = 4 ... --- ... ... Calculate 2 + 2 ... """) >>> e.solution 4
- Returns:
solution
header ifsolution
is present in YAML header andNone
otherwise.- Return type:
Union(str, None)
- property resolution¶
Returns the resolution of the exercise, that is
resolution
if YAML header contains it as field.>>> import wklib >>> e = wklib.Exercise(""" ... --- ... solution: 4 ... resolution: 2 + 2 = (1 +1) + (1 + 1) = 1 + 1 + 1 + 1 = 4 ... --- ... ... Calculate 2 + 2 ... """) >>> e.resolution '2 + 2 = (1 + 1) + (1 + 1) = 1 + 1 + 1 + 1'
- Returns:
resolution
header ofresolution
is present in YAML header andNone
otherwise.- Return type:
Union(str, None)
- property id: str¶
Returns a unique hash identification. This is mainly for reference purposes.
>>> import wklib >>> e = wklib.Exercise("Calculate 2 + 2") >>> e.id '496c889309ba0f695582a4968466685173e9c7f823d7f81dc416412216f738a5' # The previous string depends on the moment of instance creation # It is different each time
- Returns:
the
hashlib.sha3_256()
ofself.content
concatenated toself.creation
- Return type:
- property params: dict¶
Returns the evaluated parameters. It evaluates the
self.post['parameters']
present in the YAML headers of the exercise. If it is not present, it returns{}
.>>> import wklib >>> e = wklib.Exercise(""" ... --- ... parameters: ... a: random.randint(1,100) ... --- ... ... Calculate {{ params['a'] }} + 2 ... """) >>> e.params {'a': 92}
- Returns:
the evaluation of
parameters
present in YAML headers- Return type:
- property value: str¶
It applies the Jinja templating system in the whole exercise. It uses
wklib.Exercise.params()
to evaluate the rest of the content of the exercise, that is, it renders the exercise as Jinja template with hashparams = self.params
.>>> import wklib >>> e = wklib.Exercise(""" ... --- ... parameters: ... a: random.randint(1,100) ... --- ... ... Calculate {{ params['a'] }} + 2 ... """) >>> print(e.value) --- parameters: a: random.randint(1,100) --- Calculate 26 + 2
- Returns:
The evaluation of
self.content
usingself.params()
as hash- Return type:
- __weakref__¶
list of weak references to the object
- class wklib.Collection(mylist, multiplicity={})¶
Just a set of
exercises
.>>> a = wklib.Exercise("Calculate 2 + 2") >>> b = wklib.Exercise("Calculate 3 + 4") >>> c = wklib.Collection([a, b])
The set of exercises is accessed with
self.exercises
:>>> c.exercises [Calculate 2 + 2, Calculate 3 + 4]
You can use parameter
multiplicity
to repeat exercises:>>> c.wklib.Collection([a, b], {0:3, 1:2}] >>> c.exercises [Calculate 2 + 2, Calculate 2 + 2, Calculate 2 + 2, Calculate 3 + 4, Calculate 3 + 4]
- __init__(mylist, multiplicity={})¶
Creates a list of exercises. It stores that in
self.exercises
. Ifmultiplicity
is set, then the number of instances of certain elements ofmylist
is repeated accordingly.- Parameters:
multiplicity (dict) –
the multiplicity (number of occurrences) of specific elements of
mylist
. The format of multiplicity is{ position of element(i) -> number of occurrences }
.Example: if
mylist = [a, b, c]
andmultiplicity = {0: 3}
, then this function creates a collection of[a, a, a, b, c]
.Attention
Note that the
multiplicity
begins from index 0.
- __repr__()¶
Returns the representation of Collection as string. It just prints the comma-separated list of
self.exercises
- value(mytemplate, myhash={}) str ¶
Evaluates all exercises in
self.exercises
and passes tomytemplate
with optionalmyhash
dict.Specifically, it applies the Jinja templating system to all exercises and passes the result to
mytemplate
.For example:
>>> import wklib >>> a = wklib.Exercise("Calculate 2 + 2") >>> b = wklib.Exercise("Calculate 3 + 4") >>> c = wklib.Collection([a, b]) >>> t = "Worksheet: {% for e in exercises %}{{e}}|{% endfor %}" >>> c.value(t) 'Worksheet: Calculate 2 + 2|Calculate 3 + 4|'
If we want to have
title
variable, we can pass its value in the hash:>>> import wklib >>> a = wklib.Exercise("Calculate 2 + 2") >>> b = wklib.Exercise("Calculate 3 + 4") >>> c = wklib.Collection([a, b]) >>> t = "Worksheet: {{title}} {% for e in exercises %}{{e}}|{% endfor %}" >>> c.value(t, {'title': "This is my title"}) 'Worksheet: This is my title Calculate 2 + 2|Calculate 3 + 4|'
- Parameters:
mytemplate (str) –
The template to which all data is passed.
Attention
Note that the syntax of the template is specific to Jinja. If someday, in a hypothetical future, the template system engine were to be changed, then the syntax of the templates would have to change as well (see #17).
myhash (dict) – Extra variables to pass to
mytemplate
- Returns:
The evaluation of
mytemplate
withself.exercises
evaluated andmyhash
- Return type:
- __weakref__¶
list of weak references to the object
- wklib.extract_assignments(listofwords: List[str] | None, splitter: str = '=') dict ¶
From a list of words separated by spaces, extracts assignments of values to variables. This function is mainly used in Terminal User Interface to extract optional metadata (with
--metadata
argument)Example:
>>> splitter = ':' >>> listofwords = "date:2022-04-02 title:'this is a title'" >>> extract_assignments(listofwords, splitter) {'date': '2022-04-22', 'title': 'this is a title'}
Note we just split once. So,
>>> splitter = ':' >>> listofwords = "date:foo:bar" >>> extract_assignments(listofwords, splitter) {'date': 'foo:bar'}
Note that words without splitter will be ignored.
>>> splitter = ':' >>> listofwords == "foo date:2022-04-02" >>> extract_assignments(listofwords, splitter) {'date': '2022-04-22'} # 'foo' is ignored because it lacks splitter
- Parameters:
- Returns:
The hash which contains the assignments of variables and their values.
- Return type:
- wklib.evaluate_assignments(assignments: dict | None, evals: list | None) dict ¶
Evaluates the assignments of values to variables from
assignments
which appear inevals
list. This function is used mainly in Terminal User Interface to evaluate the optional metadata (with--evals
argument)Example:
>>> assignments == {'revision': '1'} >>> evals = ['revision'] >>> evaluate_assignments(assignments, evals) {'revision': 1}
If the cast is not possible, it casts the variable as
str
and not returning any error; just prints a warning message.
- wklib.save(filename: str, content: str)¶
Saves
content
to file which is calledfilename
. It is mainly used in Terminal User Interface>>> save('foo.txt', "This is a test")
- wklib.run_process(command: str, filename: str, options: str = '', repetitions=1)¶
Runs
command
tofilename
. It is used mainly in Terminal User Interface to run postprocess (see--postprocess
argument)Example:
# The file 'foo.txt' has the content 'This is a test' >>> run_process("cat", "foo.txt") 'This is a test'
- wklib.shortcut_run_process(command: str, filename: str, options: str = '')¶
Runs usual commands using shortcuts of
run_process()
.It is mainly used in Terminal User Interface to run common postprocessing tasks like LaTeX compilation.
>>> shortcut_run_process("pdflatex", "mydocument.tex") # It complies "mydocument.tex" using pdflatex (producing "mydocument.pdf")
- class wklib.Worksheet(template: str, exercises: List[str], multiplicity: Mapping[int, int] | None = {})¶
This class implements the concept of worksheet, that is, a collection of exercises.
In our case, the exercises are evaluated and passed to template. It produces an string outcome, which could be saved in a file and, optionally, process it to produce another file. Typically, a worksheet could be a PDF with several exercises which depend on some parameters that are evaluated to concrete exercises.
This class consists of:
a template, which can be accessed via
self.template
a
collection
of exercises, which can be accessed viaself.exercises
.
- __init__(template: str, exercises: List[str], multiplicity: Mapping[int, int] | None = {})¶
It creates a
worksheet
with given template and exercises files. The main purpose of the parametermultiplicity
is to repeat specific exercises avoiding to repeat them inexercise
list.Example:
>>> import wklib >>> w = wklib.Worksheet("template.txt", ["exercise-1.txt", "exercise-2.txt"])
- Parameters:
template (str) – The template written in Jinja syntax which we pass evaluated files
exercises (List[str]) – A non-empty list of exercise files to render before pass them to template file
multiplicity (Optional[dict[int, int]]) –
The multiplicity of each file of
exercises
in the form{position in the list mylist: its multiplicity}
.Example:
{0: 2, 3:5}
which means that exercise inexercises
at position 0 has multiplicity 2 and exercise at poaition 3 has multiplicity 5.
- Returns:
A worksheet of exercises and template.
- Return type:
- __repr__()¶
Returns the representation as string of Worksheet. It just prints out the template file and the list of exercises.
- value(metadata, savingfile: str = None, postprocess: str = None)¶
Returns the numerical value of the worksheet, that is the evaluated exercises passed to template.
metadata
argument is a hash with extra metada pass toself.template
.If
savingfile
is notNone
, then the result is saved, also, in a file specified in that name.If
postprocess
is notNone
, then the result is saved insavingfile
and then processed with command specified withpostprocess
. Several output files could be generated as a result of this processing.Example:
$ cat template.txt Worksheet: {% for e in exercises %} -{{e}} {% endfor %} $ cat exercise-1.txt Calculate 2 + 2 $ cat exercise-2.txt Calculate 3 + 4
# in the same path of previous files >>> import wklib >>> w = wklib.Worksheet('template.txt', ['exercise-1.txt', 'exercise-2.txt']) >>> print(w.value({})) Worksheet: -Calculate 2 + 2 -Calculate 3 + 4
A more complex example is this:
# In 'src/' directory, we run python >>> import wklib >>> w = wklib.Worksheet("templates/exercise.midsize.context", ["exercises/pythagorean-theorem.calculate-hypotenuse.ca.md", "exercises/pythagorean-theorem.calculate-cathetus.ca.md"]) >>> w.value({'lang': 'ca'}, 'test.context', postprocess='context') # test.context is saved in 'src' directory # test.pdf is generated in 'src' directory.
- Parameters:
metadata (dict) – A hash to pass to the template an extra information.
savingfile (str) – The filename to save the output.
postprocess (str) – The postprocess to run against
savingfile
. It is not arbitrary command: just a few predefined commands:lualatex
,pdflatex
andcontext
for running LuaLaTeX, PDFLaTeX and ConTeXt, respectively.
- Returns:
A string which represents the numerical value of the worksheet.
- Return type:
- __weakref__¶
list of weak references to the object
Terminal User Interface¶
This covers the functions to implement the terminal user interface wk.py
(see Usage).
- wk.cast_multiplicity(multiplicity: dict = {})¶
We cast
multiplicity
to a hash of typeint:int
.>>> m = {'0': '1', '1': '3'} >>> cast_multiplicity(m) {0: 1, 1: 3}
It is mainly used to eval the
--multiplicity
option in Terminal User Interface (without having to use--evals
which would imply more complexity for end users).