Python Analyser specificities¶
Note
This documentation applies to CAIP >= 8.3.x and com.castsoftware.python >= 1.4.0-beta2.
HowTo¶
Create your own UA extension, then react to the “add_quality_rules” event received from Python extension. With this event, you can send any interpreters of your choice, which will be used by the extension. These interpreters will have “start_XXX” and/or “end_XXX” methods where XXX is the ast node type you are interested in. They can also have also a “finish” method that is called after all python files have been analyzed.
Sample of UA extension code
import cast.analysers.ua
from cast import Event
from cast.analysers import log
from interpreters import Interpreter1, Interpreter2
class CustomPythonDiag(cast.analysers.ua.Extension):
@Event('com.castsoftware.python', 'add_quality_rules')
def add_quality_rules(self, externalQualityRules):
# Add the interpreters
externalQualityRules.add_interpreter(Interpreter1, self.get_plugin())
externalQualityRules.add_interpreter(Interpreter2, self.get_plugin())
...
Sample of a simple interpreter code
class Interpreter:
def __init__(self):
pass
def start_MethodCall(self, ast):
...
def end_MethodCall(self, ast):
...
def start_XXX(self, ast):
...
def end_XXX(self, ast):
...
...
A complete sample is available here: Starter kits.
Python ast node types¶
Here we present the main classes and methods that form the API to exploit the information contained in the abstract syntax tree (AST) of a python file.
Basic elements¶
The AST returned by the Python analyzer is composed of nodes (Node type) and tokens (Token type). Tokens are the most basic elements. All nodes do contain sub-items (other sub-nodes and tokens). In some specific contexts one might not distinguish between nodes and tokens as they are treaded similarly.
All nodes inherit direcly or indirectly from light_parser.Node. Some nodes might inherit from some generic intermediate classes (Statement, BlockStatement, Term) used internally for parsing purposes. The character of the node (expression vs statement) is loosely correlated to the the name of these clases for certain nodes. These intermediate classes do not contribute to the API.
- class light_parser.Token(text=None, type=None)¶
A token with code position.
- get_begin_line()¶
Returns: the ast node begin line Return type: int
- get_begin_column()¶
Returns: the ast node begin column Return type: int
- get_end_line()¶
Returns: the ast node end line Return type: int
- get_end_column()¶
Returns: the ast node end column Return type: int
- get_type()¶
Returns: the name of the token type Return type: str
- get_children()¶
Convenient method to comply with ‘light_parser.Node’ interface.
Returns: empty list
- get_sub_nodes()¶
Convenient method to comply with ‘light_parser.Node’ interface.
Returns: empty list
- __eq__(self, other):
Equality.
Can compare to text directly. (case insensitive).
- class light_parser.Node¶
An AST node
- get_begin_line()¶
Returns: the ast node begin line Return type: int
- get_begin_column()¶
Returns: the ast node begin column Return type: int
- get_end_line()¶
Returns: the ast node end line Return type: int
- get_end_column()¶
Returns: the ast node end column Return type: int
- get_type()¶
Returns: the name of the node Return type: str
- get_children()¶
An iterator on tokens and children that skips whitespaces and comments
- get_sub_nodes()¶
Return sub AST nodes
- print_tree(depth=0)¶
Print as a tree.
The following intermediate classes inherit from Node, but do not contribute to the API.
- class light_parser.Statement¶
- class light_parser.BlockStatement¶
- class light_parser.Term¶
Base classes¶
The classes below conveniently factorize common code among certain type of nodes. These are not explicit nodes of the AST.
Statements¶
Definition statements¶
Simple statements¶
Block statements¶
Statements containing other statements.
Expressions¶
Other structural nodes¶
Symbols¶
Symbols closely represent the structure of metamodel objects, among other functionalities. They are also used for resolution purposes for certain nodes.
Writing tests¶
Sample of a test
import unittest
import cast.analysers.test
import cast.analysers.ua
class Test(unittest.TestCase):
def test_ok1(self):
analysis = cast.analysers.test.UATestAnalysis('PYTHON') # set Python language
analysis.add_selection('test1')
analysis.add_dependency(r'C:\ProgramData\CAST\CAST\Extensions\com.castsoftware.python.1.4.0-beta2')
analysis.run()
f = analysis.get_object_by_name('f', 'CAST_Python_Function')
self.assertTrue(f)
value = f.get_value('CAST_Python_Rule.AvoidUsingInvalidObjectsInAll')
self.assertEqual('1', value)
if __name__ == '__main__':
unittest.main()
Note
You need to add a dependency by absolute path or relative to the folder containing com.castsoftware.python, for example
analysis.add_dependency(r'C:\ProgramData\CAST\CAST\Extensions\com.castsoftware.python.1.4.0-beta2')
For that you need to have downloaded the extension through CAST ExtensionDowloader: see https://doc.castsoftware.com/display/EXTEND/CAST+Extension+Downloader
Categories and types for quality rules¶
For adding a quality rule use the following categories
- Category CAST_Python_Rule (for artifacts), CAST_Python_ClassRule (only for classes).
Quality rule scopes¶
Available basic quality rule scopes are :
| 1021000 | Callable Python artifacts (includes functions methods and modules) |
| 1021008 | Python Functions (includes functions and methods) |
| 1021011 | Python Classes |
| 1021012 | Python Modules |
Python technologies¶
Values for technology to be used in IMPLTechnologies.xml for filter value
| Python | 1021000 |