Common Library

This part of the documentation describes the common library. All of the components, including the runner, the website, and even the submitted program, can import this module.

Homework Definition

Homework assignments in Railgun are defined by xml files. All the definition xml files along with the resources should be placed in a single directory. You may refer to Homework for more details about how to define a homework assignment.

When the Railgun system is booted, it will scan all the directories under config.HOMEWORK_DIR to load the assignments. Each homework assignment is stored in a Homework. Also, the loaded Homework instances are gathered in a global HwSet instance.

All the classes to represent the homework assignments are defined in this module. The relationships between these classes are:

In addition, the JSON objects carrying the scores for a submission used in the communication between the runner host and the website are also defined in this module. The relationships between these classes are:

You may head over to read more about these classes.

class railgun.common.hw.FileRules[source]

Manage a set of file rules.

A file rule is a 2-element tuple (pattern, action), where pattern determines what files to be ruled, and action determines what operations these files will take.

pattern is a regular expression. It should contain patterns to the relative paths of files.

action may be one of the following operations: ACCEPT, LOCK, HIDE and DENY.

Since the file rules are mainly used to determine what files in a homework pack can be revealed to students, and what files submitted from the students can be received.

You may refer to Archive Packing for more details about these four actions.

ACCEPT = 0

Indicate that the matching files are revealed to students in the homework attachment, and students can overwrite these files in their submissions.

LOCK = 1

Indicate that the matching files are revealed to students in the homework attachment, but the students cannot overwrite these files in their submissions.

HIDE = 2

Indicate that the matching files are NOT revealed to students, NOR should they been overwritten.

DENY = 3

Indicate that the matching files are denied, and the submission containing these files will be REJECTED immediately.

get_action(filename, default_action=1)[source]

Get the action to take on given file.

Parameters:
  • filename (str) – The name of the file.
  • default_action – If no rule in this set is matched, what action should this file take?
Returns:

One action out of (ACCEPT, LOCK, HIDE, DENY).

append_action(action, pattern)[source]

Append a file rule (action, pattern) to the end of rule list.

The rules are matched in list order. If a given file is matched by some rule in the list, all the remaining rules after it will not be checked any longer.

Parameters:
  • action (One action out of (ACCEPT, LOCK, HIDE, DENY)) – The action of the rule.
  • pattern (Regular expression str) – The file name pattern of the rule.
prepend_action(action, pattern)[source]

Prepend a file rule (action, pattern) to the front of rule list.

Parameters:
  • action (One action out of (ACCEPT, LOCK, HIDE, DENY)) – The action of the rule.
  • pattern (Regular expression str) – The file name pattern of the rule.
filter(files, allow_actions, default_action=1)[source]

Return a new iterator on given file iterator, where files not taking operations from allowed_actions should be removed.

Because this method return the new file name iterator, not a new list, you must store the list somewhere if you want to use the result for more than one times, for example:

rules = FileRules()
accepted_files = rules.filter(
    dirtree('.'),
    (FileRules.ACCEPT, FileRules.LOCK),
)
Parameters:
  • files (Iterable file names) – The input file name iterator.
  • allow_actions (set or tuple) – Set of file rules (ACCEPT, LOCK, HIDE, DENY).
  • default_action – If no rule in rule list is matched, what action should a given file take?
Returns:

The new file name iterator.

static parse_xml(xmlnode)[source]

Load file rules from an xml node object.

This method does not care about the tag name of the given node. It only parses the children of given node. Here’s an example of a file rule node:

<rules>
    <accept>.*\.py$</accept>
    <lock>.*\.conf$</lock>
    <hide>.*\.pyc$</hide>
    <deny>.*\.exe$</deny>
<rules>
Parameters:xmlnode (xml.etree.ElementTree.Element) – The xml node object that contains file rules.
class railgun.common.hw.HwInfo(lang, name, desc, solve)[source]

Object to store the homework info (name, description & solution).

The description and the solution should be written in Markdown syntax. There are some extensions to the original Markdown standard. Refer to Writing Description for more details.

Parameters:
  • lang (str) – The language for name, description and solution.
  • name (str) – The homework name.
  • desc (str) – The homework description (Markdown source code).
  • solve (str) – The homework solution (Markdown source code).
format_markdown(hwslug)[source]

Generate html description and solution from Markdown source code.

After this method is called, formatted_desc and formatted_solve will be set.

Parameters:hwslug (str) – The slug of owner homework. Necessary when formatting markdown sources.
desc = None

The description of the homework (Markdown source code).

formatted_desc = None

The formatted description of this homework. Homework will call format_markdown to set this field, so you may use it for free.

formatted_solve = None

The formatted solution of this homework. Homework will call format_markdown to set this field, so you may use it for free.

lang = None

The language name of this info object, should be compatible with request.accept_languages.

name = None

The name of the homework.

solve = None

The solution of this homework (Markdown source code).

class railgun.common.hw.HwScorerSetting(detail=None)[source]

Store the settings for a particular scorer in code.xml.

This class is a component in HwCode. Different programming languages may carry different scorers, and may reveal different level of program output to the students.

Parameters:detail – Whether this scorer should show detail reports?
static parse_xml(xmlnode)[source]

Get scorer settings from given xml node object.

An xml node to configure a particular scorer may be like this:

<scorer name="CodeStyleScorer" detail="true" />
Parameters:xmlnode (xml.etree.ElementTree.Element) – Xml node object holding the settings.
detail = None

Whether or not to display the detail of this scorer? If None, Railgun will use HwCode.reportRuntime as value.

class railgun.common.hw.HwCode(path, lang)[source]

Store the definition of a particular programming language in a homework assignment.

The Railgun system is designed to allow the students to choose their preferred programming language the finish their homework. Because of these, each homework should contain seperated code files for each individual language.

HwCode is the class to store language definitions and settings. The settings may include compiler parameters, runner parameters and verbosity of output messages.

All the configurations are loaded from code.xml. Refer to File Structure to see how code.xml is organized.

Parameters:
  • path (str) – The root path of the code package.
  • lang (str) – The name of programming language.
get_scorer(typeName)[source]

Get the settings of a particular scorer.

Parameters:typeName (str) –

The scorer type name. It may be the full name of the scorer, or a partial name that matches the last part of the type name. For example, if we call get_scorer with:

  • common.scorers.BaseScorer
  • BaseScorer

We will both get the common.scorers.BaseScorer.

Returns:The scorer setting object if found, or None otherwise.
Return type:HwScorerSetting or None
static load(path)[source]

Load the definitions as a code package under path.

This method will create a HwCode object that loads settings from [path]/code.xml, of which the programming language will be set to os.path.split(path)[1].

Parameters:path (str) – The root directory of the code package.
Returns:A HwCode object.
compiler_params = None

An xml node object that stores the compiler parameters. Let the runner host to parse the parameters.

file_rules = None

The file match rules of this code package.

has_attach = None

Whether or not students can download an attachment for this programming language?

lang = None

The programming language of this code package.

path = None

The root path of code package, should be [hw.path]/code/[lang].

reportCompile = None

Whether the compiler messages should be revealed to students? Default value is True.

reportRuntime = None

Whether the runtime messages should be revealed to students? Default value is False.

runner_params = None

An xml node object that stores the runner parameters. Let the runner host to parse the parameters.

scorers = None

A dict (“Scorer’s Type Name” -> HwScorerSetting). Store the specialized settings for various scorers.

class railgun.common.hw.Homework[source]

Store the definition of a homework assignment.

The constructor of this class will only create an empty Homework object. You may use Homework.load(path) to construct the instance according to external homework definition files.

count_attach()[source]

Count the number of HwCode objects with attachment.

get_code(lang)[source]

Get the HwCode object whose programming language is lang.

Returns:The requested HwCode object.
Raises:KeyError if given language is not found.
get_code_languages()[source]

Get the programming language names of all HwCode objects.

Returns:list of all programming language names.
get_last_deadline()[source]

Get the final deadline of this homework.

Returns:A tuple of (deadline datetime, score scale) if the final deadline exists, or None if the homework has already expired.
get_name_locales()[source]

Get the locale names of all HwInfo objects.

Returns:list of all locale names.
get_next_deadline()[source]

Get the next deadline of this homework.

Returns:A tuple of (deadline datetime, score scale) if the next deadline exists, or None if the homework has already expired.
list_files(lang)[source]

List all runtime files for given programming language.

This method is typically called when you want to get the list of files that will be copied to runtime directory when executing a submission in the given programming language.

Note

Some files in the result of this method should not be revealed to students in a downloadable attachment! Use with caution!

Parameters:lang (str) – The programming language name.
Returns:An iterable object of file names.
static load(path)[source]

Load the definitions of homework under path.

This method will load the settings from [path]/hw.xml, and create all HwInfo and HwCode objects according to the sub-directories.

Also, the descriptions and solutions in every locale will be formatted from Markdown source code to html display text. You may get the html from the formatted_desc and formatted_solve attribute of HwInfo.

Parameters:path (str) – The root directory of homework.
Returns:A Homework object.
Raises:ValueError if the homework definition is wrong.
pack_assignment(lang, filename)[source]

Pack the attachment for given programming language into filename.

All the code and resource files will be packed into a new zip archive file. This behaviour is controlled by FileRules in the Homework and the HwCode objects. You may refer to Archive Packing for more details.

Parameters:
  • lang (str) – The programming language name.
  • filename (str) – The zip attachment file path.
codes = None

HwCode objects for different programming languages.

deadlines = None

List of (deadline datetime, scale factor).

file_rules = None

The file matching rules that affects all programming languages.

info = None

HwInfo objects for different speaking languages.

path = None

The root directory of this homework assignment.

slug = None

The url slug of this homework assignment.

uuid = None

Unique id of this homework. The submissions and final scores are associated with homework according to uuid.

class railgun.common.hw.HwSet(hwdir)[source]

Collection of Homework definition objects.

Given the root directory of all homework definitions, HwSet will discover and load all homework assignments under that directory.

Parameters:hwdir (str) – The root directory of all homework definitions.
get_by_slug(slug)[source]

Get the Homework object with given slug.

get_by_uuid(uuid)[source]

Get the Homework object with given uuid.

get_uuid_list()[source]

Get the list of uuid of all Homework objects.

reload()[source]

Reload the homeworks under root directory.

You may manually call this method to reload the definitions. HwSet will not monitor the file changes.

hwdir = None

The root directory of all homework definitions.

items = None

Homework objects in the order of slug.

class railgun.common.hw.HwPartialScore(scorer_name, scorer_type_name, score, weight, time, brief_report, detail_report)[source]

A serializable partial score object.

The final score of a submission is a combinition of all scorers. The scores from every scorer are multiplied with a given weight, and sumed up to form the final score. A HwPartialScore is the score of one scorer.

You may refer to HwPartialScore for more details about the JSON format.

Parameters:
static from_plain(obj)[source]

Make a HwPartialScore object from a plain object.

Raises:TypeError or KeyError if the given plain object does not represent a valid HwScore object.
to_plain()[source]

Convert this partial score object to a plain object that can be serialized in JSON message.

Returns:A plain object that is composed only with dict, list, str, bool and numeric types.
brief = None

The brief output message of this scorer. (railgun.common.lazy_i18n.GetTextString)

detail = None

The detailed output messages of this scorer. (class:list of railgun.common.lazy_i18n.GetTextString)

get_time[source]

Get the running time of this scorer.

Returns:A datetime.timedelta object, or None if timing is not performed.
name = None

The human readable name of this scorer. (railgun.common.lazy_i18n.GetTextString)

score = None

The final score, range in [0, 100].

time = None

The running time of this scorer (in seconds).

typeName = None

The type name of this scorer.

weight = None

The weight of this scorer.

class railgun.common.hw.HwScore(accepted, result=None, compile_error=None, partials=None)[source]

A serializable final score object. You may refer to HwScore for more details about the JSON format.

Parameters:
add_partial(partial)[source]

Add a HwPartialScore object.

static from_plain(obj)[source]

Make a HwScore object from a plain object.

Raises:TypeError or KeyError if the given plain object does not represent a valid HwScore object.
get_score()[source]

Sum up the final score.

to_plain()[source]

Convert this partial score object to a plain object that can be serialized in JSON message.

Returns:A plain object that is composed only with dict, list, str, bool and numeric types.
compile_error = None

The compiler error message. (railgun.common.lazy_i18n.GetTextString or basestring)

partials = None

The HwPartialScore objects. (list of HwPartialScore)

result = None

A brief comment on the submission. (railgun.common.lazy_i18n.GetTextString)

railgun.common.hw.parse_bool(s)[source]

Convert a string literal into its boolean value.

Parameters:s (str) – The string literal that represents a boolean value.
Returns:True if s.lower() is one of (true, on, 1, yes), False otherwise.

AES Encryption

class railgun.common.crypto.AESCipher(key)[source]

Wrap the AES encryption algorithm so that you can use secret keys in any size to encrypt a plain text in any length, and decrypt it backwards.

The technical parameters of this AES cipher is:

Parameter Description
BlockSize 16
IVSize Equal to BlockSize.
KeySize 32

Since AES cipher is a block cipher, the size of plain text must be a multiple of BlockSize bytes. AESCipher would pad the input text to a multiple of KeySize bytes by following method:

  • Calculate the count of padded bytes: KeySize - len(data) % KeySize. We mark this count as padsize.
  • Append chr(padsize) * padsize (padsize of chr(padsize) characters) to the tail of input text.
  • Encrypt on such input text. We mark this ciphertext.

AES cipher relies on not only the key to decrypt a cipher text, but also the initial vector to do the decryption. So we must prepend IV to the front of cipher text. Thus the final encrypted text should be:

`initial vector` (`IVSize` bytes) + `ciphertext` (padded)

Any implementation of AES cipher in the runner hosts must be compatible with this method.

Parameters:key (str) – Encryption and decryption key for AES algorithm. If len(key) != 32, it will be padded or truncated.
decrypt(enc)[source]

Decrypt the enc text.

Parameters:enc (str) – Cipher text to be decrypted.
encrypt(raw)[source]

Encrypt the raw text.

Parameters:raw (str) – Plain text to be encrypted.
railgun.common.crypto.EncryptMessage(s, key)[source]

Convenient method to decrypt s with key.

Parameters:
  • s (str) – Plain text to be encrypted.
  • key (str) – Key to be used in AES algorithm.
railgun.common.crypto.DecryptMessage(s, key)[source]

Convenient method to encrypt s with key.

Parameters:
  • s (str) – Cipher text to be decrypted.
  • key (str) – Key to be used in AES algorithm.

CSV Object Parser

Utilities to load objects from csv file.

Suppose you are given csv data like this:

You may derive an object schema from CsvSchema, giving the names and types of the columns:

class MyObjectSchema(CsvSchema):

    name = CsvString()
    stdno = CsvString(name='student-number')
    year = CsvInteger()
    registered = CsvBoolean()

Then you may get the objects by:

with open('data.csv', 'rb') as f:
    for obj in CsvSchema.LoadCSV(MyObjectSchema, f):
        print obj

Note

The first row in csv file must be the column names! However, they may not be at the same order as defined in schema. CsvSchema uses this row to detect the order.

class railgun.common.csvdata.CsvField(**kwargs)[source]

Define a column in csv file.

This is the base class for all types of columns. You may inherit this class to provide your own field type, for example:

import json

class CsvJsonField(object):

    def fromString(self, value):
        return json.loads(value)

    def toString(self, value):
        return json.dumps(value)
Parameters:
  • name (str) – Give the name of column. If not given, use the attribute name in CsvSchema.
  • default – Give the default value of this column. If given, this value will be used if such column does not exist. If not given, KeyError will be raised if not exist.
fromString(value)[source]

Convert value from str to field type.

Derived classes should overwrite this. You may raise any exceptions as you need.

Returns:Converted object.
toString(value)[source]

Convert value from field type to str.

You must return such string representations that fromString can convert it back.

Returns:Converted str.
class railgun.common.csvdata.CsvInteger(**kwargs)[source]

Define an integral field in csv file.

class railgun.common.csvdata.CsvString(**kwargs)[source]

Define a string field in csv file.

class railgun.common.csvdata.CsvFloat(**kwargs)[source]

Define a float field in csv file.

class railgun.common.csvdata.CsvBoolean(**kwargs)[source]

Define a boolean field in csv file.

String literals will be converted according to the following table:

Value Literals (Case Insensitive)
True ‘true’, ‘on’, ‘1’, ‘yes’
False ‘false’, ‘off’, ‘0’, ‘no’
ValueError Any other literal
class railgun.common.csvdata.CsvSchema[source]

Represent a data schema on CSV file.

static LoadCSV(iterable)[source]

Get iterable objects from given line iterable object.

DateTime Utility

Utilities for conversions between plain datetime, localized datetime and UTC datetime. These three types are all datetime.datetime objects, while the only difference is their tzinfo property. tzinfo is the timezone information attached to datetime.datetime.

Type Description
plain tzinfo is None, which means no timezone is attached. Only (year, month, day, hour, min, sec, ms) tuple of such datetime objects are meaningful.
UTC tzinfo is pytz.UTC, which means the time tuple represents a datetime in UTC timezone.
localized tzinfo neither None, nor pytz.UTC, representing a datetime in given timezone.

Be careful that some timezone, such as Asia/Shanghai, is not on the exact boundary of hours (Asia/Shanghai is +08:06). Others may carry DST data. So you SHOULD ONLY use the methods provided in this module to do datetime conversions.

railgun.common.dateutil.from_plain_date(dt, tz)[source]

Attach timezone to a plain datetime object.

This method only attaches the timezone data to dt, with no adjust performed on time data. This method will ensure that the tzinfo attached to plain datetime object is on the exact boundary of hours.

Parameters:
Returns:

a localized datetime object.

railgun.common.dateutil.from_utc_date(dt, tz)[source]

Convert a UTC datetime object to localized one.

This method will adjust the time data, to make sure the conversion from UTC to localized timezone is correct.

Parameters:
Returns:

a localized datetime object.

railgun.common.dateutil.to_plain_date(dt)[source]

Strip timezone from a localized or UTC datetime object.

This method only strips the timezone data from dt, with no adjust performed on time data.

Parameters:dt (datetime.datetime) – the localized or UTC datetime object.
Returns:a plain datetime object.
railgun.common.dateutil.to_utc_date(dt)[source]

Convert a localized datetime object to UTC one.

This method will adjust the time data, to make sure the conversion from localized timezone to UTC is correct.

Parameters:dt (datetime.datetime) – a localized datetime object.
Returns:a UTC datetime object.
railgun.common.dateutil.utc_now()[source]

Get the current UTC datetime object.

FileSystem and Path Utility

class railgun.common.fileutil.Extractor(fobj)[source]

The unique interface for archive file extractors.

Railgun system can extract various types of archive files. This class provides a unique interface to create an extractor on given archive file. The format of archive will be recognized according to file extension, For examples:

>>> Extractor.open('a.zip')
<ZipExtractor instance>
>>> Extractor.open('a.rar')
<RarExtractor instance>

Also, the Extractor objects implements context manager, for example:

with Extractor.open('a.zip') as f:
    for fname, fobj in f:
        print 'the content of %s is:' % fname
        print fobj.read()
countfiles(maxcount=1048576)[source]

Count all files in the archive.

Parameters:maxcount (int) – maximum files to count. If exceeds this limit, the method will be interrupted, and maxcount + 1 will be returned.
Returns:the number of files in this archive.
extract()[source]

Get iterable (fname, fobj) from the archive.

You may simply iterate over a Extractor object, which is same as calling to this method.

Returns:list of tuple (fname, fobj), where fname is a str, and fobj is a file-like object.
filelist()[source]

Get iterable name lists in this archive file.

onedir()[source]

Check whether this archive contains only one top-level directory?

Some students may compress a whole directory. We want to detect such situations.

Note

OS X may add a hidden directory named __MACOSX to zip archives. This method will ignore such directory.

Returns:True if the archive file indeed contains only one top-level directory, while False otherwise.
static open(fpath)[source]

Open an extractor for given archive file.

Parameters:fpath (str) – the path of archive file.
Returns:instance derived from Extractor.
Raises:ValueError if the extension of given file is not supported.
railgun.common.fileutil.dirtree(parent)[source]

Get an iterable object over all relative paths of entities under directory parent.

Returns:iterable object over all relative paths.
Raises:Exception from the system libraries.
railgun.common.fileutil.file_get_contents(path)[source]

Read the file contents of path.

Returns:File content as string, or None if any error occurred.
railgun.common.fileutil.makezip(filename)[source]

Create a new zipfile.ZipFile object.

Parameters:filename (str) – the file system path of created zip file.
Returns:zipfile.ZipFile object.
railgun.common.fileutil.packzip(base_path, files, target, path_prefix='')[source]

Pack all entities in files under base_path into target zipfile.

Parameters:
  • base_path (str) – the base path of all entities.
  • files (object) – iterable object over relative paths of file entities.
  • target (zipfile.ZipFile) – Target zipfile object.
  • path_prefix (str) – prefix of paths to be added into archive file.
Returns:

target

railgun.common.fileutil.remove_firstdir(path)[source]

Remove the first directory of given path and return modified str.

If ‘/’ is not found in path, assume that it does not contain a directory. For examples:

>>> remove_firstdir('/entity')
'entity'
>>> remove_firstdir('top/entity')
'entity'
>>> remove_firstdir('entity')
'entity'
Parameters:path (str) – The input path string.
Returns:Path of which the first directory is removed.

Translation Utility

Utilities for serializable lazy translated strings.

As mentioned in I18n Everywhere, we want our Railgun system to support translations, even for the strings already stored in databases.

We know that a simple solution to the translations in a website system is to use the gettext package. Suppose we’ve created a message category including the translation from “My name is %(name)s.” to “我的姓名是 %(name)s.”, then we may write:

from gettext import gettext

>>> type(gettext('My name is %(name)s.'))
str

>>> print gettext('My name is %(name)s.') % {'name': 'Alice'}
'我的姓名是 Alice.'

The main functionality of gettext is to lookup a translation table, find the suitable translated text for input string, and then return it. However, gettext can only be configured to use a global locale.

To support multi-users in a website environment, we may use the gettext and lazy_gettext method from flask.ext.babel:

from flask.ext.babel import gettext, lazy_gettext

>>> gettext('My name is %(name)s.', name='Alice')
'我的姓名是 Alice.'

>>> type(gettext('My name is %(name)s.', name='Alice'))
:class:`str`

>>> type(lazy_gettext('My name is %(name)s.', name='Alice'))
:class:`speaklater._LazyString`

The gettext from flask.ext.babel will use the locale settings from current request, but it will translate the string at once, so you may not create a global translated text with gettext.

On the other side, the lazy_gettext will store all the arguments and create a speaklater._LazyString instance, and will only do the translation until it is being output. So you can make a global translated text with lazy_gettext.

However, we still have problems. speaklater._LazyString could not be serialized into a JSON message, nor could it be stored into database.

This is why I create my own GetTextString and lazy_gettext() method. However, these utilities do have some limitations:

  • The arguments passed to lazy_gettext() must be “plain” objects, including bool, str, unicode and the numeric types.
  • ngettext, dgettext and ndgettext are not supported.

Note

When to use flask.ext.babel.lazy_gettext() and when to use railgun.common.lazy_i18n.lazy_gettext()? Well, if you want to store the lazy string into database, or if you want to transfer the string over website api, you have to use lazy_gettext() provided by this module. However, if you just want to use it for website display, both can work.

class railgun.common.lazy_i18n.GetTextString(_GetTextString__s, **kwargs)[source]

Make a serializable lazy gettext object.

Parameters:
  • __s (basestring) – The text to be translated.
  • kwargs (dict) – Keyword arguments to be formatted.
render()[source]

Render the lazy gettext object into unicode string.

railgun.common.lazy_i18n.lazy_gettext

alias of GetTextString

railgun.common.lazy_i18n.lazystr_to_plain(s)[source]

Convert a basestring or a GetTextString object to a JSON serializable plain object. You may refer to GetTextString for more details about the JSON format.

Parameters:s – The string object to be converted.
Returns:A plain object that is composed only with dict, list, str, bool and numeric types.
Raises:TypeError if s is not converible.
railgun.common.lazy_i18n.plain_to_lazystr(s)[source]

Convert a plain object to basestring or GetTextString. You may refer to GetTextString for more details about the JSON format.

Parameters:s – The plain object.
Returns:A basestring or a GetTextString object.
Raises:KeyError if s is not converible.

Operation System Utility

exception railgun.common.osutil.ProcessTimeout[source]

Indicate that the timeout was reached when executing a process.

railgun.common.osutil.execute(cmd, timeout=None, **kwargs)[source]

Execute a command, read the output and return it back.

Parameters:
  • cmd (str) – Command to execute.
  • timeout (int) – Process timeout in seconds.
  • kwargs – Named arguments for subprocess.Popen.
Returns:

(stdout, stderr, exit code)

Return type:

tuple

Raises:

OSError on missing command or any other OS errors.

Raises:

ProcessTimeout if a timeout was reached.

railgun.common.osutil.is_running(pid)[source]

Check whether the process with given pid is still running.

Parameters:pid (int) – The process id.
Returns:True if the process is still alive, False otherwise.

Python Language Utility

railgun.common.pyutil.find_object(name)[source]

Find object according to name.

This method will try to import all the intermediate modules to find the requested object.

Examples:

>>> find_object('os')
<module 'os' from '?'>
>>> find_object('os.path')
<module 'posixpath' from '?'>
>>> find_object('os.remove')
<function posix.remove>
>>> find_object('os.path.split')
<function posixpath.split>
>>> find_object('os.path.split.__name__')
'split'
Parameters:name (str) – The name of the object, should contain full path from the global scope.
Returns:The object instance.
Raises:ImportError if object with name cannot be found.

Temporary Directory Utility

class railgun.common.tempdir.TempDir(name=None)[source]

It’s a common requirement to create a temporary directory for some work, and delete it after the work has done. TempDir provides such utility to manage a temporary directory.

All the temporary directories are created under config.TEMPORARY_DIR. You may create a temp directory like this:

with TempDir() as d:
    fpath = d.fullpath('subfile.txt')
    with open(fpath, 'wb') as f:
        f.write('hello, world!')
Parameters:name (str) – The name of this temporary directory. If not given, it will generate a randomized name by uuid.uuid4().get_hex().
chmod(mode, recursive=False)[source]

Change the Unix file system mode of this directory.

Parameters:
  • mode (int) – File system mode number.
  • recursive (bool) – Whether or not to chmod all children?
chown(uid, gid=None, recursive=False)[source]

Change the owner uid and gid of this directory.

Parameters:
  • uid (str or int) – Name or id of owner user.
  • gid – Name or id of owner group. If not given, gid will not be changed.
  • recursive (bool) – Whether or not to chown all children?
close()[source]

Delete the temporary directory recursively.

If the directory does not exist, this method will do nothing.

copyfiles(srcdir, filelist, mode=448)[source]

Copy all files from source directory into this.

Parameters:
  • srcdir (str) – The path of source directory.
  • filelist (iterable object) – Iterable relative paths of file entities.
  • mode (int) – Unix file system mode for all files and directories. This parameter will not affect existing directories. Call chown to ensure it.
extract(extractor, should_skip=None, mode=448)[source]

Extract files into this directory.

Parameters:
  • extractor (railgun.common.fsutil.Extractor) – An extractor object.
  • should_skip (method(fpath) -> bool) – A callback to determine whether a given file should be skipped.
  • mode (int) – Unix file system mode for all new directories and files. This parameter will not affect existing directories. Call chown to ensure it.
fullpath(subpath)[source]

Get the fullpath for child entity.

Parameters:subpath (str) – Relative path for the child entity.
open(mode=448)[source]

Create the temporary directory.

If the directory already exists, this method will do nothing. You may call chown to ensure the mode of this directory.

Parameters:mode (int) – Unix file system mode for this temporary directory.
name = None

Hold the name of this temporary directory.

path = None

Hold the path of this temporary directory.

URL Utility

class railgun.common.url.UrlMatcher(schemas=['http', 'https', 'ftp'])[source]

A useful class to find all the urls from given text, and replace them with a callback function.

For example, if you want to replace all file:/// urls to http:// ones, where all the files are located under /var/www/share/, and all the http urls should start with http://localhost/files/, then we may write:

def ReplaceUrl(url):
    if url.startswith('file:///var/www/share/'):
        return 'http://localhost/files/%s' % url[22:]
    return url

matcher = UrlMatcher(schemas=['file'])
payload = "Here is the movie: " \
    "file:///var/www/share/favourites/Harry-Potter.mov"
print matcher.replace(payload, ReplaceUrl)

Note that we only consider the following characters as components of urls:

A-Z, a-z, 0-9, and any one of "-_.~!*';:@&=+$,/?#"
Parameters:schemas (list) – Interested url schemas.
findall(payload)[source]

Get all matching urls from given payload.

Parameters:payload (str) – Text that may contain urls.
Returns:Iterable urls.
replace(payload, callback)[source]

Replace all matching urls in given payload with callback.

Parameters:
  • payload (str) – Text that may contain urls.
  • callback (method(str) -> str) – Function to generate new urls from old ones.
Returns:

Replaced text.

railgun.common.url.reform_path(path)[source]

Reformat the given path to Unix style.

The given path will be modified according to following rules:

  • “/” is the delimieter among different components of the path.
  • “\” will be treated as “/”.
  • Continous “/” will be considered as one.
  • Component ”.” will be removed from the path.
  • Component ”..” will consume one parent in the path.
  • A leading “/” will be reserved, while a trailing “/” will be removed.
  • Other components will be output without translation.

There’s some special cases:

  • “/” will result in “/”, since the only slash is both a leading and a trailing one.
  • Empty string will remain empty.

Examples:

>>> reform_path('1\\2')
'1/2'
>>> reform_path('////1////2')
'/1/2'
>>> reform_path('/1/2/3/../4/../..')
'/1'
>>> reform_path('/1/..')
'/'
>>> reform_path('../')
Traceback (most recent call last):
  File "a.py", line 63, in <module>
    reform_path('../')
  ...
ValueError: .. out of root
Traceback (most recent call last):
  File "a.py", line 63, in <module>
    reform_path('../')
  ...
ValueError: .. out of root
Parameters:path (str) – Original path string.
Returns:The translated new path.
Raises:ValueError if ”..” could not find any parent to consume.