The definition of slicing is split into forward and backwards slicing: using both methods together and we get a full slice. Currently only forward slicing is implemented which returns all line numbers depending on the current line number.
Given a simple program:
>>> program = u"""
... def main():
... foo = 1
... bar = 1
... baz = foo + bar
... print(baz)
...
... if __name__ == "__main__":
... main()
... """
To see which lines depend on line 3, use the slice_string() method:
>>> from programslice import slice_string
>>> slice_string('foo', 3, 4, program, 'myprogram')
['foo,3,4', 'foo,5,10', 'baz,5,4', 'baz,6,10']
Sometimes programs use encoding declarations, which need to removed before the program can be parsed. The slicing will not cause an error:
>>> encprogram = u'#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n{program}'.format(program=program)
>>> ignored = slice_string('bar', 4, 4, encprogram, 'myprogram')
>>> encprogram = u'#!/usr/bin/env python\n#\n# vim: set fileencoding=utf-8 :\n{program}'.format(program=program)
>>> ignored = slice_string('baz', 5, 4, encprogram, 'myprogram')
Instead of returning line numbers, we can filter the buffer as well. The slice_string function can be given a custom formatter class. It defaults to LineFormatter to just render the line numbers:
>>> from programslice.formatter import TextOutputFormatter
>>> result = slice_string('bar', 4, 4, program, 'myprogram', formatter=TextOutputFormatter)
>>> print('\n'.join(result))
bar = 1
baz = foo + bar
print(baz)
Command line utility which can slice a given file and return the depending lines.
Returns the slice result formatter given by it’s name.
Slices the given source code from the given currentline.
Parameters: |
|
---|
Deprecated since version 0.3.
Parameters: | invert (bool) – Invert the result and return lines which don’t depend on the currentline. Defaults to False. |
---|
Note: The reason for a self implemented graph and edge is not to be smarter, since there are better modules available for this. It is an educational project for me.
Representing the edge of a graph.
A graph which represents a function visited by a programslice.visitor. The edges of this graph are the line numbers of the parsed function.
Parameters: | name (string) – A name identifying this graph (e.g. function X) |
---|
A visitor which creates a data dependency graph.
Note
Read and Written variables are currently kept track of in a dictionary for each. This may cause wrong results when building the graph. Furthermore, we might want to create a data flow graph and a control flow graph.
Connect reads and writes also by line number.
We can not only connect by name, but also by line number. That ensures, that we connect the variables which are read, to assigned ones in the current line.
Example:
v = a + b
Here we are connecting all variables which are stored with the variables which are read.
For example:
>>> v = 1
>>> b = 1
>>> c = v
writes: v, c
reads: v
visitor visits: v (store) → b (store) → c (store) → v (read)
In order to produce a graph such that: v → v → c we need to check if we can find a read variable which now is written to. Just using the line number is not good enough, because written variables may appear at the end of the function/method, not in the next line.
Visits function and resets writes and reads in order to prevent that current function variables are overwritten.
Note: This currently just resets writes and reads which is used to build the dependency graph. But it should set the writes and reads in such a way, so that we can slice over function boundaries.
A base formatter which outputs a list of linenumbers on call.
Parameters: |
---|
TODO: No checking in place wether source is a unicode object or str.
>>> from programslice.graph import Edge
>>> slice_result = [Edge('foo', 12, 3), Edge('bar', 13, 3)]
>>> formatter = LineFormatter(slice_result, '')
>>> formatter()
[12, 13]