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.

class symbols.Function

Bases: symbols.FunctionOrProcedure, symbols.SchemaFunctionOrProcedure, symbols.ResolutionScope

type_name = 'SQLScriptFunction'

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