Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
32a8ed7b
Commit
32a8ed7b
authored
Oct 31, 2012
by
Vik Paruchuri
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
adding in self assessment grader
parent
b74a484f
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
91 additions
and
216 deletions
+91
-216
common/lib/xmodule/xmodule/capa_module.py
+57
-57
common/lib/xmodule/xmodule/js/src/selfassessment/display.coffee
+0
-24
common/lib/xmodule/xmodule/self_assessment_module.py
+34
-135
No files found.
common/lib/xmodule/xmodule/capa_module.py
View file @
32a8ed7b
...
@@ -29,10 +29,10 @@ TIMEDELTA_REGEX = re.compile(r'^((?P<days>\d+?) day(?:s?))?(\s)?((?P<hours>\d+?)
...
@@ -29,10 +29,10 @@ TIMEDELTA_REGEX = re.compile(r'^((?P<days>\d+?) day(?:s?))?(\s)?((?P<hours>\d+?)
def
only_one
(
lst
,
default
=
""
,
process
=
lambda
x
:
x
):
def
only_one
(
lst
,
default
=
""
,
process
=
lambda
x
:
x
):
"""
"""
If lst is empty, returns default
If lst is empty, returns default
If lst has a single element, applies process to that element and returns it
If lst has a single element, applies process to that element and returns it
Otherwise, raises an exeception
Otherwise, raises an exeception
"""
"""
if
len
(
lst
)
==
0
:
if
len
(
lst
)
==
0
:
return
default
return
default
elif
len
(
lst
)
==
1
:
elif
len
(
lst
)
==
1
:
...
@@ -43,14 +43,14 @@ Otherwise, raises an exeception
...
@@ -43,14 +43,14 @@ Otherwise, raises an exeception
def
parse_timedelta
(
time_str
):
def
parse_timedelta
(
time_str
):
"""
"""
time_str: A string with the following components:
time_str: A string with the following components:
<D> day[s] (optional)
<D> day[s] (optional)
<H> hour[s] (optional)
<H> hour[s] (optional)
<M> minute[s] (optional)
<M> minute[s] (optional)
<S> second[s] (optional)
<S> second[s] (optional)
Returns a datetime.timedelta parsed from the string
Returns a datetime.timedelta parsed from the string
"""
"""
parts
=
TIMEDELTA_REGEX
.
match
(
time_str
)
parts
=
TIMEDELTA_REGEX
.
match
(
time_str
)
if
not
parts
:
if
not
parts
:
return
return
...
@@ -71,9 +71,9 @@ class ComplexEncoder(json.JSONEncoder):
...
@@ -71,9 +71,9 @@ class ComplexEncoder(json.JSONEncoder):
class
CapaModule
(
XModule
):
class
CapaModule
(
XModule
):
'''
'''
An XModule implementing LonCapa format problems, implemented by way of
An XModule implementing LonCapa format problems, implemented by way of
capa.capa_problem.LoncapaProblem
capa.capa_problem.LoncapaProblem
'''
'''
icon_class
=
'problem'
icon_class
=
'problem'
js
=
{
'coffee'
:
[
resource_string
(
__name__
,
'js/src/capa/display.coffee'
),
js
=
{
'coffee'
:
[
resource_string
(
__name__
,
'js/src/capa/display.coffee'
),
...
@@ -175,9 +175,9 @@ capa.capa_problem.LoncapaProblem
...
@@ -175,9 +175,9 @@ capa.capa_problem.LoncapaProblem
@property
@property
def
rerandomize
(
self
):
def
rerandomize
(
self
):
"""
"""
Property accessor that returns self.metadata['rerandomize'] in a
Property accessor that returns self.metadata['rerandomize'] in a
canonical form
canonical form
"""
"""
rerandomize
=
self
.
metadata
.
get
(
'rerandomize'
,
'always'
)
rerandomize
=
self
.
metadata
.
get
(
'rerandomize'
,
'always'
)
if
rerandomize
in
(
""
,
"always"
,
"true"
):
if
rerandomize
in
(
""
,
"always"
,
"true"
):
return
"always"
return
"always"
...
@@ -203,7 +203,7 @@ canonical form
...
@@ -203,7 +203,7 @@ canonical form
def
get_progress
(
self
):
def
get_progress
(
self
):
''' For now, just return score / max_score
''' For now, just return score / max_score
'''
'''
d
=
self
.
get_score
()
d
=
self
.
get_score
()
score
=
d
[
'score'
]
score
=
d
[
'score'
]
total
=
d
[
'total'
]
total
=
d
[
'total'
]
...
@@ -224,7 +224,7 @@ canonical form
...
@@ -224,7 +224,7 @@ canonical form
def
get_problem_html
(
self
,
encapsulate
=
True
):
def
get_problem_html
(
self
,
encapsulate
=
True
):
'''Return html for the problem. Adds check, reset, save buttons
'''Return html for the problem. Adds check, reset, save buttons
as necessary based on the problem config and state.'''
as necessary based on the problem config and state.'''
try
:
try
:
html
=
self
.
lcp
.
get_html
()
html
=
self
.
lcp
.
get_html
()
...
@@ -358,14 +358,14 @@ as necessary based on the problem config and state.'''
...
@@ -358,14 +358,14 @@ as necessary based on the problem config and state.'''
def
handle_ajax
(
self
,
dispatch
,
get
):
def
handle_ajax
(
self
,
dispatch
,
get
):
'''
'''
This is called by courseware.module_render, to handle an AJAX call.
This is called by courseware.module_render, to handle an AJAX call.
"get" is request.POST.
"get" is request.POST.
Returns a json dictionary:
Returns a json dictionary:
{ 'progress_changed' : True/False,
{ 'progress_changed' : True/False,
'progress' : 'none'/'in_progress'/'done',
'progress' : 'none'/'in_progress'/'done',
<other request-specific values here > }
<other request-specific values here > }
'''
'''
handlers
=
{
handlers
=
{
'problem_get'
:
self
.
get_problem
,
'problem_get'
:
self
.
get_problem
,
'problem_check'
:
self
.
check_problem
,
'problem_check'
:
self
.
check_problem
,
...
@@ -398,7 +398,7 @@ Returns a json dictionary:
...
@@ -398,7 +398,7 @@ Returns a json dictionary:
def
answer_available
(
self
):
def
answer_available
(
self
):
''' Is the user allowed to see an answer?
''' Is the user allowed to see an answer?
'''
'''
if
self
.
show_answer
==
''
:
if
self
.
show_answer
==
''
:
return
False
return
False
...
@@ -425,14 +425,14 @@ Returns a json dictionary:
...
@@ -425,14 +425,14 @@ Returns a json dictionary:
def
update_score
(
self
,
get
):
def
update_score
(
self
,
get
):
"""
"""
Delivers grading response (e.g. from asynchronous code checking) to
Delivers grading response (e.g. from asynchronous code checking) to
the capa problem, so its score can be updated
the capa problem, so its score can be updated
'get' must have a field 'response' which is a string that contains the
'get' must have a field 'response' which is a string that contains the
grader's response
grader's response
No ajax return is needed. Return empty dict.
No ajax return is needed. Return empty dict.
"""
"""
queuekey
=
get
[
'queuekey'
]
queuekey
=
get
[
'queuekey'
]
score_msg
=
get
[
'xqueue_body'
]
score_msg
=
get
[
'xqueue_body'
]
self
.
lcp
.
update_score
(
score_msg
,
queuekey
)
self
.
lcp
.
update_score
(
score_msg
,
queuekey
)
...
@@ -441,10 +441,10 @@ No ajax return is needed. Return empty dict.
...
@@ -441,10 +441,10 @@ No ajax return is needed. Return empty dict.
def
get_answer
(
self
,
get
):
def
get_answer
(
self
,
get
):
'''
'''
For the "show answer" button.
For the "show answer" button.
Returns the answers: {'answers' : answers}
Returns the answers: {'answers' : answers}
'''
'''
event_info
=
dict
()
event_info
=
dict
()
event_info
[
'problem_id'
]
=
self
.
location
.
url
()
event_info
[
'problem_id'
]
=
self
.
location
.
url
()
self
.
system
.
track_function
(
'show_answer'
,
event_info
)
self
.
system
.
track_function
(
'show_answer'
,
event_info
)
...
@@ -469,18 +469,18 @@ Returns the answers: {'answers' : answers}
...
@@ -469,18 +469,18 @@ Returns the answers: {'answers' : answers}
# Figure out if we should move these to capa_problem?
# Figure out if we should move these to capa_problem?
def
get_problem
(
self
,
get
):
def
get_problem
(
self
,
get
):
''' Return results of get_problem_html, as a simple dict for json-ing.
''' Return results of get_problem_html, as a simple dict for json-ing.
{ 'html': <the-html> }
{ 'html': <the-html> }
Used if we want to reconfirm we have the right thing e.g. after
Used if we want to reconfirm we have the right thing e.g. after
several AJAX calls.
several AJAX calls.
'''
'''
return
{
'html'
:
self
.
get_problem_html
(
encapsulate
=
False
)}
return
{
'html'
:
self
.
get_problem_html
(
encapsulate
=
False
)}
@staticmethod
@staticmethod
def
make_dict_of_responses
(
get
):
def
make_dict_of_responses
(
get
):
'''Make dictionary of student responses (aka "answers")
'''Make dictionary of student responses (aka "answers")
get is POST dictionary.
get is POST dictionary.
'''
'''
answers
=
dict
()
answers
=
dict
()
for
key
in
get
:
for
key
in
get
:
# e.g. input_resistor_1 ==> resistor_1
# e.g. input_resistor_1 ==> resistor_1
...
@@ -500,11 +500,11 @@ get is POST dictionary.
...
@@ -500,11 +500,11 @@ get is POST dictionary.
def
check_problem
(
self
,
get
):
def
check_problem
(
self
,
get
):
''' Checks whether answers to a problem are correct, and
''' Checks whether answers to a problem are correct, and
returns a map of correct/incorrect answers:
returns a map of correct/incorrect answers:
{'success' : bool,
{'success' : bool,
'contents' : html}
'contents' : html}
'''
'''
event_info
=
dict
()
event_info
=
dict
()
event_info
[
'state'
]
=
self
.
lcp
.
get_state
()
event_info
[
'state'
]
=
self
.
lcp
.
get_state
()
event_info
[
'problem_id'
]
=
self
.
location
.
url
()
event_info
[
'problem_id'
]
=
self
.
location
.
url
()
...
@@ -567,16 +567,16 @@ returns a map of correct/incorrect answers:
...
@@ -567,16 +567,16 @@ returns a map of correct/incorrect answers:
# 'success' will always be incorrect
# 'success' will always be incorrect
event_info
[
'correct_map'
]
=
correct_map
.
get_dict
()
event_info
[
'correct_map'
]
=
correct_map
.
get_dict
()
event_info
[
'success'
]
=
success
event_info
[
'success'
]
=
success
event_info
[
'attempts'
]
=
self
.
attempts
event_info
[
'attempts'
]
=
self
.
attempts
self
.
system
.
track_function
(
'save_problem_check'
,
event_info
)
self
.
system
.
track_function
(
'save_problem_check'
,
event_info
)
if
hasattr
(
self
.
system
,
'psychometrics_handler'
):
# update PsychometricsData using callback
if
hasattr
(
self
.
system
,
'psychometrics_handler'
):
# update PsychometricsData using callback
self
.
system
.
psychometrics_handler
(
self
.
get_instance_state
())
self
.
system
.
psychometrics_handler
(
self
.
get_instance_state
())
# render problem into HTML
# render problem into HTML
html
=
self
.
get_problem_html
(
encapsulate
=
False
)
html
=
self
.
get_problem_html
(
encapsulate
=
False
)
return
{
'success'
:
success
,
return
{
'success'
:
success
,
'contents'
:
html
,
'contents'
:
html
,
}
}
...
@@ -654,9 +654,9 @@ def reset_problem(self, get):
...
@@ -654,9 +654,9 @@ def reset_problem(self, get):
class
CapaDescriptor
(
RawDescriptor
):
class
CapaDescriptor
(
RawDescriptor
):
"""
"""
Module implementing problems in the LON-CAPA format,
Module implementing problems in the LON-CAPA format,
as implemented by capa.capa_problem
as implemented by capa.capa_problem
"""
"""
module_class
=
CapaModule
module_class
=
CapaModule
...
...
common/lib/xmodule/xmodule/js/src/selfassessment/display.coffee
View file @
32a8ed7b
...
@@ -125,30 +125,6 @@ class @Problem
...
@@ -125,30 +125,6 @@ class @Problem
@
gentle_alert
saveMessage
@
gentle_alert
saveMessage
@
updateProgress
response
@
updateProgress
response
refreshMath
:
(
event
,
element
)
=>
element
=
event
.
target
unless
element
elid
=
element
.
id
.
replace
(
/^input_/
,
''
)
target
=
"display_"
+
elid
# MathJax preprocessor is loaded by 'setupInputTypes'
preprocessor_tag
=
"inputtype_"
+
elid
mathjax_preprocessor
=
@
inputtypeDisplays
[
preprocessor_tag
]
if
jax
=
MathJax
.
Hub
.
getAllJax
(
target
)[
0
]
eqn
=
$
(
element
).
val
()
if
mathjax_preprocessor
eqn
=
mathjax_preprocessor
(
eqn
)
MathJax
.
Hub
.
Queue
([
'Text'
,
jax
,
eqn
],
[
@
updateMathML
,
jax
,
element
])
return
# Explicit return for CoffeeScript
updateMathML
:
(
jax
,
element
)
=>
try
$
(
"#
#{
element
.
id
}
_dynamath"
).
val
(
jax
.
root
.
toMathML
''
)
catch
exception
throw
exception
unless
exception
.
restart
MathJax
.
Callback
.
After
[
@
refreshMath
,
jax
],
exception
.
restart
refreshAnswers
:
=>
refreshAnswers
:
=>
@
$
(
'input.schematic'
).
each
(
index
,
element
)
->
@
$
(
'input.schematic'
).
each
(
index
,
element
)
->
element
.
schematic
.
update_value
()
element
.
schematic
.
update_value
()
...
...
common/lib/xmodule/xmodule/self_assessment_module.py
View file @
32a8ed7b
...
@@ -57,9 +57,10 @@ class SelfAssessmentModule(XModule):
...
@@ -57,9 +57,10 @@ class SelfAssessmentModule(XModule):
dom2
=
etree
.
fromstring
(
definition
[
'data'
])
dom2
=
etree
.
fromstring
(
definition
[
'data'
])
self
.
attempts
=
0
self
.
attempts
=
0
self
.
max_attempts
=
None
self
.
max_attempts
=
1
self
.
max_attempts
=
self
.
metadata
.
get
(
'attempts'
,
None
)
self
.
max_attempts
=
self
.
metadata
.
get
(
'attempts'
,
None
)
if
self
.
max_attempts
is
not
None
:
if
self
.
max_attempts
is
not
None
:
self
.
max_attempts
=
int
(
self
.
max_attempts
)
self
.
max_attempts
=
int
(
self
.
max_attempts
)
...
@@ -70,7 +71,7 @@ class SelfAssessmentModule(XModule):
...
@@ -70,7 +71,7 @@ class SelfAssessmentModule(XModule):
self
.
name
=
only_one
(
dom2
.
xpath
(
'/problem/@name'
))
self
.
name
=
only_one
(
dom2
.
xpath
(
'/problem/@name'
))
self
.
rubric
=
etree
.
tostring
(
only_one
(
dom2
.
xpath
(
"/rubric"
)))
self
.
rubric
=
etree
.
tostring
(
only_one
(
dom2
.
xpath
(
"/rubric
/html
"
)))
self
.
problem
=
etree
.
tostring
(
only_one
(
dom2
.
xpath
(
"/problem"
)))
self
.
problem
=
etree
.
tostring
(
only_one
(
dom2
.
xpath
(
"/problem"
)))
self
.
lcp
=
LoncapaProblem
(
self
.
problem
,
self
.
location
.
html_id
(),
self
.
lcp
=
LoncapaProblem
(
self
.
problem
,
self
.
location
.
html_id
(),
...
@@ -255,10 +256,7 @@ class SelfAssessmentModule(XModule):
...
@@ -255,10 +256,7 @@ class SelfAssessmentModule(XModule):
handlers
=
{
handlers
=
{
'problem_get'
:
self
.
get_problem
,
'problem_get'
:
self
.
get_problem
,
'problem_check'
:
self
.
check_problem
,
'problem_check'
:
self
.
check_problem
,
'problem_reset'
:
self
.
reset_problem
,
'problem_save'
:
self
.
save_problem
,
'problem_save'
:
self
.
save_problem
,
'problem_show'
:
self
.
get_answer
,
'score_update'
:
self
.
update_score
,
}
}
if
dispatch
not
in
handlers
:
if
dispatch
not
in
handlers
:
...
@@ -321,7 +319,8 @@ class SelfAssessmentModule(XModule):
...
@@ -321,7 +319,8 @@ class SelfAssessmentModule(XModule):
@staticmethod
@staticmethod
def
make_dict_of_responses
(
get
):
def
make_dict_of_responses
(
get
):
'''Make dictionary of student responses (aka "answers")
'''
Make dictionary of student responses (aka "answers")
get is POST dictionary.
get is POST dictionary.
'''
'''
answers
=
dict
()
answers
=
dict
()
...
@@ -355,9 +354,9 @@ class SelfAssessmentModule(XModule):
...
@@ -355,9 +354,9 @@ class SelfAssessmentModule(XModule):
answers
=
self
.
make_dict_of_responses
(
get
)
answers
=
self
.
make_dict_of_responses
(
get
)
event_info
[
'answers'
]
=
convert_files_to_filenames
(
answers
)
event_info
[
'answers'
]
=
convert_files_to_filenames
(
answers
)
parsed_answer
=
False
parsed_answer
=
"incorrect"
if
(
answer
[
answers
.
keys
()[
0
]]
==
"True
"
):
if
(
answer
[
answers
.
keys
()[
1
]]
==
"Correct
"
):
parsed_answer
=
True
parsed_answer
=
"correct"
# Too late. Cannot submit
# Too late. Cannot submit
if
self
.
closed
():
if
self
.
closed
():
...
@@ -445,137 +444,36 @@ class SelfAssessmentModule(XModule):
...
@@ -445,137 +444,36 @@ class SelfAssessmentModule(XModule):
return
{
'success'
:
True
}
return
{
'success'
:
True
}
class
SelfAssessmentDescriptor
(
XmlDescriptor
,
Editing
Descriptor
):
class
SelfAssessmentDescriptor
(
Raw
Descriptor
):
"""
"""
Module for putting raw html in a course
Module for putting raw html in a course
"""
"""
mako_template
=
"widgets/html-edit.html"
module_class
=
SelfAssessmentModule
module_class
=
HtmlModule
filename_extension
=
"xml"
template_dir_name
=
"html"
stores_state
=
True
has_score
=
True
js
=
{
'coffee'
:
[
resource_string
(
__name__
,
'js/src/selfassessment/edit.coffee'
)]}
js_module_name
=
"HTMLEditingDescriptor"
# VS[compat] TODO (cpennington): Delete this method once all fall 2012 course
# are being edited in the cms
@classmethod
def
backcompat_paths
(
cls
,
path
):
if
path
.
endswith
(
'.html.xml'
):
path
=
path
[:
-
9
]
+
'.html'
# backcompat--look for html instead of xml
if
path
.
endswith
(
'.html.html'
):
path
=
path
[:
-
5
]
# some people like to include .html in filenames..
candidates
=
[]
while
os
.
sep
in
path
:
candidates
.
append
(
path
)
_
,
_
,
path
=
path
.
partition
(
os
.
sep
)
# also look for .html versions instead of .xml
nc
=
[]
for
candidate
in
candidates
:
if
candidate
.
endswith
(
'.xml'
):
nc
.
append
(
candidate
[:
-
4
]
+
'.html'
)
return
candidates
+
nc
# NOTE: html descriptors are special. We do not want to parse and
# export them ourselves, because that can break things (e.g. lxml
# adds body tags when it exports, but they should just be html
# snippets that will be included in the middle of pages.
@classmethod
def
load_definition
(
cls
,
xml_object
,
system
,
location
):
'''Load a descriptor from the specified xml_object:
If there is a filename attribute, load it as a string, and
log a warning if it is not parseable by etree.HTMLParser.
If there is not a filename attribute, the definition is the body
of the xml_object, without the root tag (do not want <html> in the
middle of a page)
'''
filename
=
xml_object
.
get
(
'filename'
)
if
filename
is
None
:
definition_xml
=
copy
.
deepcopy
(
xml_object
)
cls
.
clean_metadata_from_xml
(
definition_xml
)
return
{
'data'
:
stringify_children
(
definition_xml
)}
else
:
# html is special. cls.filename_extension is 'xml', but
# if 'filename' is in the definition, that means to load
# from .html
# 'filename' in html pointers is a relative path
# (not same as 'html/blah.html' when the pointer is in a directory itself)
pointer_path
=
"{category}/{url_path}"
.
format
(
category
=
'html'
,
url_path
=
name_to_pathname
(
location
.
name
))
base
=
path
(
pointer_path
)
.
dirname
()
#log.debug("base = {0}, base.dirname={1}, filename={2}".format(base, base.dirname(), filename))
filepath
=
"{base}/{name}.html"
.
format
(
base
=
base
,
name
=
filename
)
#log.debug("looking for html file for {0} at {1}".format(location, filepath))
stores_state
=
True
has_score
=
True
template_dir_name
=
'selfassessment'
# Capa modules have some additional metadata:
# TODO (vshnayder): do problems have any other metadata? Do they
# actually use type and points?
metadata_attributes
=
RawDescriptor
.
metadata_attributes
+
(
'type'
,
'points'
)
# VS[compat]
# VS[compat]
# TODO (cpennington): If the file doesn't exist at the right path,
# TODO (cpennington): Delete this method once all fall 2012 course are being
# give the class a chance to fix it up. The file will be written out
# edited in the cms
# again in the correct format. This should go away once the CMS is
@classmethod
# online and has imported all current (fall 2012) courses from xml
def
backcompat_paths
(
cls
,
path
):
if
not
system
.
resources_fs
.
exists
(
filepath
):
return
[
candidates
=
cls
.
backcompat_paths
(
filepath
)
'problems/'
+
path
[
8
:],
#log.debug("candidates = {0}".format(candidates))
path
[
8
:],
for
candidate
in
candidates
:
]
if
system
.
resources_fs
.
exists
(
candidate
):
filepath
=
candidate
break
try
:
def
__init__
(
self
,
*
args
,
**
kwargs
):
with
system
.
resources_fs
.
open
(
filepath
)
as
file
:
super
(
CapaDescriptor
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
html
=
file
.
read
()
# Log a warning if we can't parse the file, but don't error
weight_string
=
self
.
metadata
.
get
(
'weight'
,
None
)
if
not
check_html
(
html
):
if
weight_string
:
msg
=
"Couldn't parse html in {0}."
.
format
(
filepath
)
self
.
weight
=
float
(
weight_string
)
log
.
warning
(
msg
)
else
:
system
.
error_tracker
(
"Warning: "
+
msg
)
self
.
weight
=
None
\ No newline at end of file
definition
=
{
'data'
:
html
}
# TODO (ichuang): remove this after migration
# for Fall 2012 LMS migration: keep filename (and unmangled filename)
definition
[
'filename'
]
=
[
filepath
,
filename
]
return
definition
except
(
ResourceNotFoundError
)
as
err
:
msg
=
'Unable to load file contents at path {0}: {1} '
.
format
(
filepath
,
err
)
# add more info and re-raise
raise
Exception
(
msg
),
None
,
sys
.
exc_info
()[
2
]
# TODO (vshnayder): make export put things in the right places.
def
definition_to_xml
(
self
,
resource_fs
):
'''If the contents are valid xml, write them to filename.xml. Otherwise,
write just <html filename="" [meta-attrs="..."]> to filename.xml, and the html
string to filename.html.
'''
try
:
return
etree
.
fromstring
(
self
.
definition
[
'data'
])
except
etree
.
XMLSyntaxError
:
pass
# Not proper format. Write html to file, return an empty tag
pathname
=
name_to_pathname
(
self
.
url_name
)
pathdir
=
path
(
pathname
)
.
dirname
()
filepath
=
u'{category}/{pathname}.html'
.
format
(
category
=
self
.
category
,
pathname
=
pathname
)
resource_fs
.
makedir
(
os
.
path
.
dirname
(
filepath
),
allow_recreate
=
True
)
with
resource_fs
.
open
(
filepath
,
'w'
)
as
file
:
file
.
write
(
self
.
definition
[
'data'
])
# write out the relative name
relname
=
path
(
pathname
)
.
basename
()
elt
=
etree
.
Element
(
'html'
)
elt
.
set
(
"filename"
,
relname
)
return
elt
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment