3.1. IMS Content Packaging (version 1.2)¶
The IMS Content Packaging specification defines methods for packaging and organizing resources and their associated metadata for transmission between systems. There is a small amount of information on Wikipedia about content packaging in general, see http://en.wikipedia.org/wiki/Content_package. The main use of IMS Content Packaging in the market place is through the SCORM profile. Content Packaging is also used as the basis for the new IMS Common Cartridge, and a method of packaging assessment materials using the speicifcation is also described by IMS QTI version 2.1.
Official information about the specification is available from the IMS GLC: http://www.imsglobal.org/content/packaging/index.html
3.1.1. Example¶
The following example script illustrates the use of this module. The script
takes two arguments, a resource file to be packaged (such as an index.html file)
and the path to save the zipped package to. The script creates a new package
containing a single resource with the entry point set to point to the resource
file. It also adds any other files in the same directory as the resource file,
using the python os.walk function to include files in sub-directories too. The
ContentPackage.IgnoreFilePath()
method is used to ensure that hidden
files are not added:
#! /usr/bin/env python
import sys, os, os.path, shutil
from pyslet.imscpv1p2 import ContentPackage, PathInPath
from pyslet.rfc2396 import URIFactory
def main():
if len(sys.argv)!=3:
print "Usage: makecp <resource file> <package file>"
return
resFile=sys.argv[1]
pkgFile=sys.argv[2]
pkg=ContentPackage()
try:
if os.path.isdir(resFile):
print "Resource entry point must be a file, not a directory."
return
resHREF=URI.from_path(resFile)
srcDir,srcFile=os.path.split(resFile)
r=pkg.manifest.root.Resources.add_child(pkg.manifest.root.Resources.ResourceClass)
r.href=str(resHREF.relative(URI.from_path(os.path.join(srcDir,'imsmanifest.xml'))))
r.type=='webcontent'
for dirpath,dirnames,filenames in os.walk(srcDir):
for f in filenames:
srcPath=os.path.join(dirpath,f)
if pkg.IgnoreFilePath(srcPath):
print "Skipping: %s"%srcPath
continue
dstPath=os.path.join(pkg.dPath,PathInPath(srcPath,srcDir))
# copy the file
dname,fName=os.path.split(dstPath)
if not os.path.isdir(dname):
os.makedirs(dname)
print "Copying: %s"%srcPath
shutil.copy(srcPath,dstPath)
pkg.File(r,URI.from_path(dstPath))
if os.path.exists(pkgFile):
if raw_input("Are you sure you want to overwrite %s? (y/n) "%pkgFile).lower()!='y':
return
pkg.manifest.update()
pkg.ExportToPIF(pkgFile)
finally:
pkg.Close()
if __name__ == "__main__":
main()
Note the use of the try:… finally: construct to ensure that the
ContentPackage
object is properly closed when it is finished with.
Note also the correct way to create elements within the manifest, using the
dependency safe *Class attributes:
r=pkg.manifest.root.Resources.add_child(pkg.manifest.root.Resources.ResourceClass)
This line creates a new resource element as a child of the (required) Resources element.
At the end of the script the ManifestDocument
is updated on the disk
using the inherited Update()
method. The package can then be exported to the zip file format.
3.1.2. Reference¶
-
class
pyslet.imscpv1p2.
ContentPackage
(dpath=None)¶ Bases:
pyslet.pep8.MigratedClass
Represents a content package.
When constructed with no arguments a new package is created. A temporary folder to hold the contents of the package is created and will not be cleaned up until the
Close()
method is called.Alternatively, you can pass an operating system or virtual file path to a content package directory, to an imsmanifest.xml file or to a Package Interchange Format file. In the latter case, the file is unzipped into a temporary folder to facilitate manipulation of the package contents.
A new manifest file is created and written to the file system when creating a new package, or if it is missing from an existing package or directory.
-
ManifestDocumentClass
¶ the default class for representing the Manifest file
alias of
ManifestDocument
-
dPath
= None¶ the
VirtualFilePath
to the package’s
-
manifest
= None¶ The
ManifestDocument
object representing the imsmanifest.xml file.The file is read (or created) on construction.
-
fileTable
= None¶ The fileTable is a dictionary that maps package relative file paths to the
File
objects that represent them in the manifest.It is possible for a file to be referenced multiple times (although dependencies were designed to take care of most cases it is still possible for two resources to share a physical file, or even for a resource to contain multiple references to the same file.) Therefore, the dictionary values are lists of
File
objects.If a file path maps to an empty list then a file exists in the package which is not referenced by any resource. In some packages it is common for auxiliary files such as supporting schemas to be included in packages without a corresponding
File
object so an empty list does not indicate that the file can be removed safely. These files are still included when packaging the content package for interchange.Finally, if a file referred to by a
File
object in the manifest is missing an entry is still created in the fileTable. You can walk the keys of the fileTable testing if each file exists to determine if some expected files are missing from the package.The keys in fileTable are VirtualFilePath instances. To convert a string to an appropriate instance use the
FilePath()
method.
-
make_file_path
(*path)¶ Converts a string into a
pyslet.vfs.VirtualFilePath
instance suitable for using as a key into thefileTable
. The conversion is done using the file system of the content package’s directory,dPath
.
-
set_ignore_files
(ignore_files)¶ Sets the regular expression used to determine if a file should be ignored.
Some operating systems and utilities create hidden files or other spurious data inside the content package directory. For example, ‘s OS X creates .DS_Store files and the svn source control utility creates .svn directories. The files shouldn’t generally be included in exported packages as they may confuse the recipient (who may be using a system on which these files and directories are not hidden) and be deemed to violate the specification, not to mention adding unnecessarily to the size of the package and perhaps even leaking information unintentionally.
To help avoid this type of problem the class uses a regular expression to determine if a file should be considered part of the package. When listing directories, the names of the files found are compared against this regular expression and are ignored if they match.
By default, the pattern is set to match all directories and files with names beginning ‘.’ so you will not normally need to call this method.
-
ignore_file
(f)¶ Compares a file or directory name against the pattern set by
set_ignore_files()
.f is a unicode string.
-
ignore_file_path
(fpath)¶ Compares a file path against the pattern set by
set_ignore_files()
The path is normalised before comparison and any segments consisting of the string ‘..’ are skipped. The method returns True if any of the remaining path components matches the ignore pattern. In other words, if the path describes a file that is is in a directory that should be ignored it will also be ignored.
The path can be relative or absolute. Relative paths are not made absolute prior to comparison so this method is not affected by the current directory, even if the current diretory would itself be ignored.
-
AddToZip
(*args, **kwargs)¶ Deprecated equivalent to
add_to_zip()
-
DeleteFile
(*args, **kwargs)¶ Deprecated equivalent to
delete_file()
-
ExpandZip
(*args, **kwargs)¶ Deprecated equivalent to
expand_zip()
-
ExportToPIF
(*args, **kwargs)¶ Deprecated equivalent to
export_to_pif()
-
File
(*args, **kwargs)¶ Deprecated equivalent to
new_file()
-
FileCopy
(*args, **kwargs)¶ Deprecated equivalent to
file_copy()
-
FilePath
(*args, **kwargs)¶ Deprecated equivalent to
make_file_path()
-
FileScanner
(*args, **kwargs)¶ Deprecated equivalent to
file_scanner()
-
GetPackageName
(*args, **kwargs)¶ Deprecated equivalent to
get_package_name()
-
GetUniqueFile
(*args, **kwargs)¶ Deprecated equivalent to
get_unique_path()
-
IgnoreFile
(*args, **kwargs)¶ Deprecated equivalent to
ignore_file()
-
IgnoreFilePath
(*args, **kwargs)¶ Deprecated equivalent to
ignore_file_path()
-
PackagePath
(*args, **kwargs)¶ Deprecated equivalent to
package_path()
-
RebuildFileTable
(*args, **kwargs)¶ Deprecated equivalent to
rebuild_file_table()
-
SetIgnoreFiles
(*args, **kwargs)¶ Deprecated equivalent to
set_ignore_files()
-
package_path
(fpath)¶ Converts an absolute file path into a canonical package-relative path
Returns None if fpath is not inside the package.
-
export_to_pif
(zpath)¶ Exports the content package, saving the zipped package in zpath
zpath is overwritten by this operation.
In order to make content packages more interoperable this method goes beyond the basic zip specification and ensures that pathnames are always UTF-8 encoded when added to the archive. When creating instances of
ContentPackage
from an existing archive the reverse transformation is performed. When exchanging PIF files between systems with different native file path encodings, encoding erros may occur.
-
get_unique_path
(suggested_path)¶ Returns a unique file path suitable for creating a new file in the package.
suggested_path is used to provide a suggested path for the file. This may be relative (to the root and manifest) or absolute but it must resolve to a file (potentially) in the package. The suggested_path should either be a VirtualFilePath (of the same type as the content package’s
dPath
) or a string suitable for conversion to a VirtualFilePath.When suggested_path is relative, it is forced to lower-case. This is consistent with the behaviour of normcase on systems that are case insensitive. The trouble with case insensitive file systems is that it may be impossible to unpack a content package created on a case sensitive system and store it on a case insenstive one. By channelling all file storage through this method (and constructing any URIs after the file has been stored) the resulting packages will be more portable.
If suggested_path already corresponds to a file already in the package, or to a file already referred to in the manifest, then a random string is added to it while preserving the suggested extension in order to make it unique.
The return result is always normalized and returned relative to the package root.
-
new_file
(resource, href)¶ Returns a new
File
object attached to resourcehref is the URI of the file expressed relative to the resource element in the manifest. Although this is normally the same as the URI expressed relative to the package, a resource may have an xml:base attribute that alters the base for resolving relative URIs.
href may of course be an absolute URI to an external resource. If an absolute URI is given to a local file it must be located inside the package.
Attempting to add a
File
object representing the manifest file iteself will raiseCPFilePathError
.The
fileTable
is updated automatically by this method.
-
file_copy
(resource, src_url)¶ Returns a new
File
object copied into the package from src_url, attached to resource.The file is copied to the same directory as the resource’s entry point or to the main package directory if the resource has no entry point.
The
File
object is actually created with theFile()
method.Note that if src_url points to a missing file then no file is copied to the package but the associated
File
is still created. It will point to a missing file.
-
delete_file
(href)¶ Removes the file at href from the file system
This method also removes any file references to it from resources in the manifest. href may be given relative to the package root directory. The entry in
fileTable
is also removed.CPFileTypeError
is raised if the file is not a regular fileCPFilePathError
is raised if the file is anignore_file()
, the manifest itself or outside of the content package.CPProtocolError
is raised if the indicated file is not in the local file system.
-
get_package_name
()¶ Returns a human readable name for the package
The name is determined by the method used to create the object. The purpose is to return a name that would be intuitive to the user if it were to be used as the name of the package directory or the stem of a file name when exporting to a PIF file.
Note that the name is returned as a unicode string suitable for showing to the user and may need to be encoded before being used in file path operations.
-
close
()¶ Closes the content package, removing any temporary files.
This method must be called to clean up any temporary files created when processing the content package. Temporary files are created inside a special temporary directory created using the builtin python tempdir.mkdtemp function. They are not automatically cleaned up when the process exits or when the garbage collector disposes of the object. Use of try:… finally: to clean up the package is recommended. For example:
pkg=ContentPackage("MyPackage.zip") try: # do stuff with the content package here finally: pkg.Close()
-
-
class
pyslet.imscpv1p2.
ManifestDocument
(**args)¶ Bases:
pyslet.xml.namespace.NSDocument
Represents the imsmanifest.xml file itself.
Buildong on
pyslet.xml.namespace.XMLNSDocument
this class is used for parsing and writing manifest files.The constructor defines three additional prefixes using
make_prefix()
, mapping xsi onto XML schema, imsmd onto the IMS LRM namespace and imsqti onto the IMS QTI 2.1 namespace. It also adds a schemaLocation attribute. The elements defined by thepyslet.imsmdv1p2p1
andpyslet.imsqtiv2p1
modules are added to theclassMap
to ensure that metadata from those schemas are bound to the special classes defined there.-
defaultNS
= None¶ the default namespace is set to
IMSCP_NAMESPACE
-
get_element_class
(name)¶ Overrides
pyslet.xml.namespace.XMLNSDocument.get_element_class()
to look up name.The class contains a mapping from (namespace,element name) pairs to class objects representing the elements. Any element not in the class map returns
XMLNSElement()
instead.
-
3.1.2.1. Constants¶
The following constants are used for setting and interpreting XML documents that conform to the Content Packaging specification
-
pyslet.imscpv1p2.
IMSCP_NAMESPACE
= 'http://www.imsglobal.org/xsd/imscp_v1p1'¶ str(object=’‘) -> string
Return a nice string representation of the object. If the argument is a string, the return value is the same object.
-
pyslet.imscpv1p2.
IMSCP_SCHEMALOCATION
= 'http://www.imsglobal.org/xsd/imscp_v1p1.xsd'¶ str(object=’‘) -> string
Return a nice string representation of the object. If the argument is a string, the return value is the same object.
-
pyslet.imscpv1p2.
IMSCPX_NAMESPACE
= 'http://www.imsglobal.org/xsd/imscp_extensionv1p2'¶ str(object=’‘) -> string
Return a nice string representation of the object. If the argument is a string, the return value is the same object.
3.1.2.2. Elements¶
-
class
pyslet.imscpv1p2.
CPElement
(parent, name=None)¶ Bases:
pyslet.xml.namespace.NSElement
Base class for all elements defined by the Content Packaging specification.
-
class
pyslet.imscpv1p2.
Manifest
(parent)¶ Bases:
pyslet.imscpv1p2.CPElement
Represents the manifest element, the root element of the imsmanifest file.
-
OrganizationsClass
¶ the default class to represent the organizations element
alias of
Organizations
-
Metadata
= None¶ the manifest’s metadata element
-
Organizations
= None¶ the organizations element
-
Resources
= None¶ the resources element
-
Manifest
= None¶ a list of child manifest elements
-
-
class
pyslet.imscpv1p2.
Metadata
(parent)¶ Bases:
pyslet.imscpv1p2.CPElement
Represents the Metadata element.
-
SchemaVersionClass
¶ alias of
SchemaVersion
-
Schema
= None¶ the optional schema element
-
SchemaVersion
= None¶ the optional schemaversion element
-
-
class
pyslet.imscpv1p2.
Schema
(parent, name=None)¶ Bases:
pyslet.imscpv1p2.CPElement
Represents the schema element.
-
class
pyslet.imscpv1p2.
SchemaVersion
(parent, name=None)¶ Bases:
pyslet.imscpv1p2.CPElement
Represents the schemaversion element.
-
class
pyslet.imscpv1p2.
Organizations
(parent)¶ Bases:
pyslet.imscpv1p2.CPElement
Represents the organizations element.
-
OrganizationClass
¶ the default class to represent the organization element
alias of
Organization
-
Organization
= None¶ a list of organization elements
-
-
class
pyslet.imscpv1p2.
Organization
(parent, name=None)¶ Bases:
pyslet.imscpv1p2.CPElement
Represents the organization element.
-
class
pyslet.imscpv1p2.
Resources
(parent)¶ Bases:
pyslet.imscpv1p2.CPElement
Represents the resources element.
-
Resource
= None¶ the list of resources in the manifest
-
-
class
pyslet.imscpv1p2.
Resource
(parent)¶ Bases:
pyslet.imscpv1p2.CPElement
Represents the resource element.
-
DependencyClass
¶ the default class to represent the dependency element
alias of
Dependency
-
type
= None¶ the type of the resource
-
href
= None¶ the href pointing at the resource’s entry point
-
Metadata
= None¶ the resource’s optional metadata element
-
File
= None¶ a list of file elements associated with the resource
-
Dependency
= None¶ a list of dependencies of this resource
-
get_entry_point
()¶ Returns the
File
object that is identified as the entry point.If there is no entry point, or no
File
object with a matching href, then None is returned.
-
set_entry_point
(f)¶ Set’s the
File
object that is identified as the resource’s entry point.The File must already exist and be associated with the resource.
-
DeleteDependency
(*args, **kwargs)¶ Deprecated equivalent to
delete_dependency()
-
DeleteFile
(*args, **kwargs)¶ Deprecated equivalent to
delete_file()
-
GetEntryPoint
(*args, **kwargs)¶ Deprecated equivalent to
get_entry_point()
-
SetEntryPoint
(*args, **kwargs)¶ Deprecated equivalent to
set_entry_point()
-
-
class
pyslet.imscpv1p2.
File
(parent)¶ Bases:
pyslet.imscpv1p2.CPElement
Represents the file element.
-
href
= None¶ the href used to locate the file object
-
package_path
(cp)¶ Returns the normalized file path relative to the root of the content package, cp.
If the href does not point to a local file then None is returned. Otherwise, this function calculates an absolute path to the file and then calls the content package’s
ContentPackage.package_path()
method.
-
PackagePath
(*args, **kwargs)¶ Deprecated equivalent to
package_path()
-
-
class
pyslet.imscpv1p2.
Dependency
(parent)¶ Bases:
pyslet.imscpv1p2.CPElement
Represents the dependency element.
-
identifierref
= None¶ the identifier of the resource in this dependency
-