Discussion:
[repost] broken QTI package import (and source repository plea)
Cristopher Ewing
2010-04-15 00:12:57 UTC
Permalink
[reposting after fixing my subscription email address, apologies]

Greetings,

Apologies for coming late to this discussion, but I've just gotten a customer who wants to migrate quizzes from their current site into a new site we're building for them in Plone. ECQuiz appears to be the only product out there with the ability to do this easily.

Unfortunately, it appears that the qti import functionality is not working as one might expect. I can upload a zip file as exported from the other system, but the upload does nothing.

I'm currently playing with plone 3.3.5 and ECQuiz 1.2.1b1dev-r158 as found at pypi (installed via buildout as an egg).

Here's what I'm finding:

in Products.ECQuiz.qti.importPackage the list of files in the ZipFile from the form upload is derived like so:

fileNameList = [context.unicodeDecode(f.filename) for f in zipFileObject.filelist]

In my case here, that returns a list of unicode strings something like this:

[u'quiz-arthritis-arthritis_arthritis_-20100414-1221/',
u'quiz-arthritis-arthritis_arthritis_-20100414-1221/imsmanifest.xml',
u'quiz-arthritis-arthritis_arthritis_-20100414-1221/question1.xml',
u'quiz-arthritis-arthritis_arthritis_-20100414-1221/question10.xml',
...]

as you can see, the filenames seen here all include the name of the folder that was first turned into the zipfile archive by the qti exporter in the other system (which I have no control over). When ECQuiz tries to find a manifest for this package, the following code is used:

manifestFnList = [fn for fn in fileNameList if fn.lower() == MANIFEST_FILE_NAME]

where MANIFEST_FILE_NAME is u'imsmanifext.xml'. I'm sure you can see that this is going to fail, since although I do have a manifest in my zipfile archive, its name includes the name of the containing folder. If I change the above to this:

manifestFnList = [fn for fn in fileNameList if MANIFEST_FILE_NAME in fn.lower()]

then I get a manifest and the processing fails a bit further on. The problem at that point is also that the names of the xml files for each resource in my quiz as indexed by the zipfile include the name of the containing folder, whereas the names of the resources as listed in the manifest xml code look like this:

u'./question1.xml'

so when we reach the point where the resources are read from the zip file here in qti.py:

def readFromZip(context, zipFileObject, fileName, errors):
...
contents = None
firstException = None
try:
# Read the resource from the zip file
contents = zipFileObject.read(fileName)
except Exception, e:
firstException = e

I end up with nothing, because the filename passed in is u'./question1.xml', but the file is indexed by the zipfile as uploaded with u'quiz-arthritis-arthritis_arthritis_-20100414-1221/question1.xml'.

I could probably figure out a work-around for this one, too, at which point I suspect the import would work fine, but I'd really like to contribute this fix to the product. Here's where the second part of my subject comes into play.

Back in January of 2009 a plea was made to move the repository for the eduComponents code to the plone collective (http://listserv.uni-magdeburg.de/pipermail/educomponents/2009-January/000265.html). After a bit of hopeful-looking thread, it came back that that would not happen, and instead a read-only repository was set up (http://listserv.uni-magdeburg.de/pipermail/educomponents/2009-February/000276.html, http://listserv.uni-magdeburg.de/pipermail/educomponents/2009-February/000277.html).

At this point, the package has been turned into an egg, but in addition to the problem above, there are any number of plone2 code ghosts left over that still need to be excised in order for ECQuiz to be truly plone3 compatible (instead of simply plone3 installable as is currently the case). By running a full diff between the current trunk and the released egg in pypi, I can see that someone has changed a few of these, but there are a lot more to go.

Because the code is in a closed repository, there is currently no way for me to directly contribute the fixes I'd like to make. Furthermore, because the closed repository has no browsing capability (at least none that I can find, and no announcement appears to have been made to this list regarding any), I have no way other than laborious manual file diffs to figure out if the problems I'm seeing have been fixed by anyone else and simply have yet to be released or if I really need to spend my time fixing them.

It's fine and good to ask folks to submit patches, but for any sort of reasonable forward motion to occur, this project is going to need to move out in the open. I'd strongly agree with the opinion expressed in this post:

http://listserv.uni-magdeburg.de/pipermail/educomponents/2009-January/000271.html

Limited development resources are certainly best concentrated on a single project rather than spread across forked versions. May I respectfully renew the call for the code for ECQuiz to be released to the collective so that those of us out here in the education community who need a tool like this can push it forward with a sane development workflow model? Submitting patches for problems that may or may not yet have been fixed and hoping they'll eventually make it into a release when the last release was more than a year ago is not healthy to one's sense of enthusiasm.

Thanks for listening this far,

With respect for the work done on this valuable tool

Cris

********************************
Cris Ewing
Webmaster, Lead Developer
Department of Radiology Web Services
University of Washington
School of Medicine
Work Phone: (206) 616-1288
Cell Phone: (206) 708-9083
E-mail: ***@u.washington.edu
Web: http://www.rad.washington.edu
*******************************
Wolfram Fenske
2010-04-20 10:04:28 UTC
Permalink
Post by Cristopher Ewing
[reposting after fixing my subscription email address, apologies]
[...]
Post by Cristopher Ewing
Unfortunately, it appears that the qti import functionality is not
working as one might expect. I can upload a zip file as exported
from the other system, but the upload does nothing.
I'm currently playing with plone 3.3.5 and ECQuiz 1.2.1b1dev-r158 as
found at pypi (installed via buildout as an egg).
in Products.ECQuiz.qti.importPackage the list of files in the
fileNameList = [context.unicodeDecode(f.filename) for f in zipFileObject.filelist]
[u'quiz-arthritis-arthritis_arthritis_-20100414-1221/',
u'quiz-arthritis-arthritis_arthritis_-20100414-1221/imsmanifest.xml',
u'quiz-arthritis-arthritis_arthritis_-20100414-1221/question1.xml',
u'quiz-arthritis-arthritis_arthritis_-20100414-1221/question10.xml',
...]
as you can see, the filenames seen here all include the name of the
folder that was first turned into the zipfile archive by the qti
exporter in the other system (which I have no control over). When
ECQuiz tries to find a manifest for this package, the following code
manifestFnList = [fn for fn in fileNameList if fn.lower() == MANIFEST_FILE_NAME]
where MANIFEST_FILE_NAME is u'imsmanifext.xml'. I'm sure you can
see that this is going to fail, since although I do have a manifest
in my zipfile archive, its name includes the name of the containing
manifestFnList = [fn for fn in fileNameList if MANIFEST_FILE_NAME in fn.lower()]
then I get a manifest and the processing fails a bit further on.
The problem at that point is also that the names of the xml files
for each resource in my quiz as indexed by the zipfile include the
name of the containing folder, whereas the names of the resources as
u'./question1.xml'
[...]

You're right, ECQuiz expects the manifest in the top level directory
of the zip file, and all resource references are expected to be
relative to the top level directory, not relative to the location of
the manifest. Browsing the QTI specification I found no concrete
evidence that this is how packages are supposed to look. So the code
is probably just intolerant/dumb.

One obvious workaround would be to repackage your packages so
everything is contained in the top-level directory, not a sub-folder.

A real fix might be to extend 'readFromZip' so it accepts an
additional directory name, which would be the directory in which the
imsmanifest.xml resides. Every filename that 'readFromZip' is given
would then be expected to be relative to that directory.

Also, the statement

manifestFnList = [fn for fn in fileNameList
if fn.lower() == MANIFEST_FILE_NAME]

would have to become something like

manifestFnList = [fn for fn in fileNameList
if os.path.split(fn)[-1].lower() == MANIFEST_FILE_NAME]
Post by Cristopher Ewing
I could probably figure out a work-around for this one, too, at
which point I suspect the import would work fine, but I'd really
like to contribute this fix to the product. Here's where the second
part of my subject comes into play.
Back in January of 2009 a plea was made to move the repository for
the eduComponents code to the plone collective
(http://listserv.uni-magdeburg.de/pipermail/educomponents/2009-January/000265.html).
After a bit of hopeful-looking thread, it came back that that would
[...]

I'm sorry, but I cannot help you with the second part since I'm not in
a position to do anything about it.
--
Wolfram Fenske

A: Yes.
Post by Cristopher Ewing
Q: Are you sure?
A: Because it reverses the logical flow of conversation.
Q: Why is top posting frowned upon?
Cristopher Ewing
2010-04-20 13:29:11 UTC
Permalink
Post by Wolfram Fenske
I'm sorry, but I cannot help you with the second part since I'm not in
a position to do anything about it.
Thanks for the reply, Wolfram. I understand.

Any thoughts about part two from those who are in such a position? Is
any such person listening?


Cris Ewing
Webmaster, Developer
UW Radiology Web Services
Phone: 206.616.1288
Mobile: 206.708.9083
***@u.washington.edu
http://www.rad.washington.edu
Mario Amelung
2010-04-20 17:16:27 UTC
Permalink
Hi Cris,
Post by Cristopher Ewing
Post by Wolfram Fenske
I'm sorry, but I cannot help you with the second part since I'm not
in a position to do anything about it.
Thanks for the reply, Wolfram. I understand.
Any thoughts about part two from those who are in such a position?
Is any such person listening?
I agree with you that an open eduComponents repository (or move the EC
products to the Plone Collective) seems to be a good idea. We've
discussed this topic several times but always ended up by the following
issue:

- Anyone at any time, along with their own contributions, may decide to
create a new version of ECQuiz.

- The code "forks" as several people create new releases at the same time.

- The ECQuiz community attempts to settle on the best fork to follow.
Perhaps the best fork is widely recognized and quickly selected, perhaps
not.

- Several forks may live in parallel - no one is the clear winner.

- Development continues in this method. Leaders emerge briefly, as they
create a new release or argue for one fork over another.


Please don't misunderstand me, open source projects are an important and
exciting innovation in software engineering. But in my opinion they do
not manage themselves. Successful open source projects are managed by a
single person or small committee.

However, we will give the open repository a try and see how it works.
I've requested so called »commitaccess« to the Plone Collective in order
to check in ECQuiz as a new project (see [1]).

Best wishes,
Mario

Footnotes:
[1] <https://dev.plone.org/plone.org/ticket/1902>
--
Dipl.-Wirtsch.-Inf. Mario Amelung <***@iws.cs.uni-magdeburg.de>
Otto-von-Guericke-University Magdeburg WDOK Research Group
Matthew Wilkes
2010-04-20 17:27:52 UTC
Permalink
Post by Mario Amelung
but always ended up by the following
- Anyone at any time, along with their own contributions, may decide to
create a new version of ECQuiz.
- The code "forks" as several people create new releases at the same time.
Forking is very uncommon in the Plone community, I can only think of a
couple of examples off the top of my head. Forking is much more
likely to happen if people feel they're being excluded from making
contributions. You can still keep control over something in the
collective, you'd be the maintainers and would be free to revert other
people's changes and email them to say why.

Matt
Cristopher Ewing
2010-04-20 17:51:42 UTC
Permalink
Mario,

I'm so glad that you've chosen to put the project out into the collective. I think you'll find that the pace of development will increase with this decision. Speaking for the edu community, there's a great deal of interest in establishing a clear set of well-vetted and high-quality add-on products for the education sector. ECQuiz is a great candidate for this set. I think there are a number of us chomping at the bit out here to get to work on it. At any rate, as Matthey indicates, you can certainly keep as much control as you wish.

Speaking for myself, the chief advantage of having ECQuiz in the collective will be that I can keep track myself of the changes that others have contributed, making it far less likely that I will duplicate efforts that others have already made. That's a great spur to contribution. No-one likes wasting what little time we have re-inventing wheels.

Once again, thanks for choosing to put the ECQuiz product out into the collective.

Yours,

Cris Ewing
Post by Mario Amelung
but always ended up by the following
- Anyone at any time, along with their own contributions, may decide to
create a new version of ECQuiz.
- The code "forks" as several people create new releases at the same time.
Forking is very uncommon in the Plone community, I can only think of a couple of examples off the top of my head. Forking is much more likely to happen if people feel they're being excluded from making contributions. You can still keep control over something in the collective, you'd be the maintainers and would be free to revert other people's changes and email them to say why.
Matt
********************************
Cris Ewing
Webmaster, Lead Developer
Department of Radiology Web Services
University of Washington
School of Medicine
Work Phone: (206) 616-1288
Cell Phone: (206) 708-9083
E-mail: ***@u.washington.edu
Web: http://www.rad.washington.edu
*******************************
Mario Amelung
2010-04-20 18:00:24 UTC
Permalink
Hi Matt,
Post by Matthew Wilkes
Post by Mario Amelung
- Anyone at any time, along with their own contributions, may decide to
create a new version of ECQuiz.
- The code "forks" as several people create new releases at the same time.
Forking is very uncommon in the Plone community, I can only think of a
couple of examples off the top of my head. Forking is much more likely
to happen if people feel they're being excluded from making
contributions. You can still keep control over something in the
collective, you'd be the maintainers and would be free to revert other
people's changes and email them to say why.
Ah, that sounds good. Thank you. Indeed, at the moment we have no idea
how the Plone Collective actually works. Thus it's really interesting
to try it out.

Best wishes,
Mario
--
Dipl.-Wirtsch.-Inf. Mario Amelung <***@iws.cs.uni-magdeburg.de>
Otto-von-Guericke-University Magdeburg WDOK Research Group
Cristopher Ewing
2010-04-28 22:17:48 UTC
Permalink
Post by Wolfram Fenske
Post by Cristopher Ewing
in Products.ECQuiz.qti.importPackage the list of files in the
fileNameList = [context.unicodeDecode(f.filename) for f in zipFileObject.filelist]
[u'quiz-arthritis-arthritis_arthritis_-20100414-1221/',
u'quiz-arthritis-arthritis_arthritis_-20100414-1221/imsmanifest.xml',
u'quiz-arthritis-arthritis_arthritis_-20100414-1221/question1.xml',
u'quiz-arthritis-arthritis_arthritis_-20100414-1221/question10.xml',
...]
as you can see, the filenames seen here all include the name of the
folder that was first turned into the zipfile archive by the qti
exporter in the other system (which I have no control over). When
ECQuiz tries to find a manifest for this package, the following code
manifestFnList = [fn for fn in fileNameList if fn.lower() == MANIFEST_FILE_NAME]
where MANIFEST_FILE_NAME is u'imsmanifext.xml'. I'm sure you can
see that this is going to fail, since although I do have a manifest
in my zipfile archive, its name includes the name of the containing
manifestFnList = [fn for fn in fileNameList if MANIFEST_FILE_NAME in fn.lower()]
then I get a manifest and the processing fails a bit further on.
The problem at that point is also that the names of the xml files
for each resource in my quiz as indexed by the zipfile include the
name of the containing folder, whereas the names of the resources as
u'./question1.xml'
[...]
You're right, ECQuiz expects the manifest in the top level directory
of the zip file, and all resource references are expected to be
relative to the top level directory, not relative to the location of
the manifest. Browsing the QTI specification I found no concrete
evidence that this is how packages are supposed to look. So the code
is probably just intolerant/dumb.
One obvious workaround would be to repackage your packages so
everything is contained in the top-level directory, not a sub-folder.
A real fix might be to extend 'readFromZip' so it accepts an
additional directory name, which would be the directory in which the
imsmanifest.xml resides. Every filename that 'readFromZip' is given
would then be expected to be relative to that directory.
Also, the statement
manifestFnList = [fn for fn in fileNameList
if fn.lower() == MANIFEST_FILE_NAME]
would have to become something like
manifestFnList = [fn for fn in fileNameList
if os.path.split(fn)[-1].lower() == MANIFEST_FILE_NAME]
Now that the ECQuiz product is out in the collective, I've been happily bashing away on this. I've got a branch on which I'm attempting to fix the naive 'readFromZip' method to ensure that deviant cases like mine above work out. I'm also trying to clean up a bit the code meant to account for non-english character sets in both the zip file and the QTI manifest. Here's my branch:

http://dev.plone.org/collective/browser/Products.ECQuiz/branches/cewing_fix_imports

If you look back over the revision history of that branch, I think you'll be able to track my efforts and get a sense of what I'm trying to do.

I'd really appreciate it if someone with a better handle on unicode encoding and decoding would take a look at the work I've done, especially the refactored algorithm for 'readFromZip' in qti.py to verify that I haven't really messed things up. I've got two passing tests that cover importing a QTI package with and without extended pathname information, but neither has any international characters in any of the filenames, and so I'd love to get another eye on this.

Thanks again to all for moving this valuable code out into the open. I'm glad to be contributing code. I hope it's helpful.

c

********************************
Cris Ewing
Webmaster, Lead Developer
Department of Radiology Web Services
University of Washington
School of Medicine
Work Phone: (206) 616-1288
Cell Phone: (206) 708-9083
E-mail: ***@u.washington.edu
Web: http://www.rad.washington.edu
*******************************

Loading...