On this page:
- Description
- Supported Python versions
- Function Point, Quality and Sizing support
- CAST AIP compatibility
- Supported DBMS servers
- Prerequisites
- Dependencies with other extensions
- Download and installation instructions
- Packaging, delivering and analyzing your source code
- What results can you expect?
- Database queries
- File system access functions
- Limitations
Target audience:
Users of the extension providing Python support.
Summary: This document provides basic information about the extension providing Python support.
Description
This extension provides support for Python.
In what situation should you install this extension?
If your application contains Python source code and you want to view these object types and their links with other objects, then you should install this extension.
Supported Python versions
The following table displays the supported versions matrix:
Version | Support |
---|---|
3.x | |
2.x | |
1.x |
- Function Points (transactions): a green tick indicates that OMG Function Point counting and Transaction Risk Index are supported
- Quality and Sizing: a green tick indicates that CAST can measure size and that a minimum set of Quality Rules exist
Function Points (transactions) | Quality and Sizing | Security |
---|---|---|
CAST AIP release | Supported |
---|---|
8.3.x | |
8.2.x | |
8.1.x | |
8.0.x | |
7.3.4 and all higher 7.3.x releases |
Supported DBMS servers
This extension is compatible with the following DBMS servers:
CAST AIP release | CSS | Oracle | Microsoft |
---|---|---|---|
All supported releases |
Prerequisites
An installation of any compatible release of CAST AIP (see table above) |
Dependencies with other extensions
Some CAST extensions require the presence of other CAST extensions in order to function correctly. The Python extension requires that the following other CAST extensions are also installed:
- Web services linker service (internal technical extension)
- CAST AIP Internal extension ((internal technical extension)
Download and installation instructions
Please see:
- http://doc.castsoftware.com/display/EXTEND/Download+an+extension
- http://doc.castsoftware.com/display/EXTEND/Install+an+extension
The latest release status of this extension can be seen when downloading it from the CAST Extend server.
Packaging, delivering and analyzing your source code
Once the extension is installed, no further configuration changes are required before you can package your source code and run an analysis. The process of packaging, delivering and analyzing your source code is as follows:
Packaging and delivery
- You can refer to the existing official CAST documentation for more information about the CAST Delivery Manager Tool packaging and delivery process - see: http://doc.castsoftware.com/display/DOC82/Source+Code+Delivery+Guide+for+Application+Teams.
- Note that the Python extension does not contain any CAST Delivery Manager Tool discoverers or extractors, therefore, no "Python" projects will be detected by the DMT. You therefore need to manually create an Analysis Unit in the CAST Management Studio - this is explained below.
Using the CAST Delivery Manager Tool:
- create a new Version
- create a new Package for your Python source code using the Files on your file system option:
- Define a name for the package and the root folder of your Application source code:
- Run the Package action: the CAST Delivery Manager Tool will not find any "projects" related to the Python application source code - this is the expected behaviour. However, if your Python related source code is part of a larger application, then other projects may be found during the package action.
- Deliver the Version
Analyzing
Using the CAST Management Studio:
- Accept and deploy the Version in the CAST Management Studio. No Analysis Units will be created automatically relating to the Python source code - this is the expected behaviour. However, if your Python related source code is part of a larger application, then other Analysis Units may be created automatically:
- In the Current Version tab, add a new Analysis Unit specifically for your Python source code, selecting the Add new Universal Analysis Unit option:
- Edit the new Analysis Unit and configure in the Source Settings tab:
- a name for the Analysis Unit
- ensure you tick the Python option
- define the location of the deployed Python source code (the CAST Management Studio will locate this automatically in the Deployment folder):
- Run a test analysis on the Analysis Unit before you generate a new snapshot.
Automatic skipping of unit-test code
The analyser skips files that are recognized as forming part of testing code, i.e., in principle code not pertaining to production code. The reason to avoid inclusion of testing code is that many quality rule violations are overrepresented in test code, either because tends to be more sloppy code (certainly not critical) or prevalence of particular testing patterns. Accounting for test code would impact negatively the total score of the project. The heuristics used by the analyser are based on detecting unit-test library imports, and file and path naming conventions as summarized in the table below:
Type | Value | HeaderLines | MinimuCount |
---|---|---|---|
FilePath | **/test_*.py | ||
FilePath | **/*_test.py | ||
FilePath | **/*_test_*.py | ||
FilePath | **/test/*.py | ||
FilePath | **/tests/*.py | ||
FileContent | import unittest | 12 | |
FileContent | from unittest import | 12 | |
FileContent | from nose.tools import | 12 | |
FileContent | self.assert | 2 |
What results can you expect?
Once the analysis/snapshot generation has completed, you can view the results in the normal manner:
Python Class and method example
iOS Front-end connected to a Python Flask Back-end.
Objects
The following specific objects are displayed in CAST Enlighten:
Icon | Description |
---|---|
Python Project, Python External Library | |
Python Module | |
Python Class | |
Python Method | |
Python Script | |
Python Get Urllib, Urllib2, Httplib, Httplib2, aiohttp Service Python Flask, aiohttp Web Service Get Operation | |
Python Post Urllib, Urllib2, Httplib, Httplib2, aiohttp Service Python Flask, aiohttp Web Service Post Operation | |
Python Put Urllib, Httplib, Httplib2, aiohttp Service Python Flask, aiohttp Web Service Put Operation | |
Python Delete Urllib, Httplib, Httplib2, aiohttp Service Python Flask, aiohttp Web Service Delete Operation | |
SQL Named Query |
Links
The following links are constructed :
- call links between methods
- inherit link between classes
- refer link from methods to class (constructor call)
- use link between modules through import
Quality Rules
# | Name (ID) | CISQ | OWASP | Critical |
---|---|---|---|---|
1 | Avoid Artifacts with High Fan-In (7776) | |||
2 | Avoid Artifacts with High Fan-Out (7778) | |||
3 | Avoid Classes with a High Number Of Children (7792) |
Web Service calls and operations support
The following libraries are supported for Web Service operations (left) and Web Service HTTP API calls (right):
Once the Python extension analysis is finished, the analyzer will output the final number of web service call and operation objects created.
requests
Example for GET request:
import requests r = requests.get('https://api.github.com/events')
urllib
Example for GET request:
import urllib.request with urllib.request.urlopen('http://python.org/') as response: html = response.read()
urllib2
Example for GET request:
import urllib2 req = urllib2.Request('http://python.org/') response = urllib2.urlopen(req) the_page = response.read()
Example for POST request.
import urllib2 import urllib values = {'name' : 'Michael Foord', 'location' : 'Northampton', 'language' : 'Python' } data = urllib.urlencode(values) req = urllib2.Request('http://python.org/', data) response = urllib2.urlopen(req) the_page = response.read()
httplib
Example for GET request:
from httplib import HTTPConnection def f(): conn = HTTPConnection("www.python.org") conn.request("GET", "/index.html")
Example link from method "f" to the get httplib service:
http.client
Example for GET request:
from http.client import HTTPConnection def f(): conn = HTTPConnection("www.python.org") conn.request("GET", "/index.html")
In this case a Python Get Httplib Service will be generated (the httplib module from Python 2 has been renamed to http.client in Python 3).
httplib2
The following code will issue a http get to the url 'https://api.github.com/events':
import httplib2 h = httplib2.Http(".cache") (resp, content) = h.request("https://api.github.com/events")
aiohttp
The following code will issue a http get to the url 'https://api.github.com/events':
import aiohttp session = aiohttp.ClientSession() res = session.get('https://api.github.com/events'
The aiohttp module can be also used in server mode, implementing web service operations
from aiohttp import web async def handler(request): return web.Response(text="Welcome in Python") app = web.Application() app.router.add_get('/index', handler) web.run_app(app)
In this case a Web Service Operation object associated to the function (coroutine) handler will be generated similar to the example for flask given below.
flask
Flask route annotations for web service operations (GET, PUT, POST, DELETE) are supported. In particular, any decorator with the format @prefix.route is considered as a flask annotation where prefix can be a Flask application object or blueprint object. In the following example, a default GET operation is ascribed to the function f, and the POST and PUT operations to the upload_file function:
from flask import Flask app = Flask(__name__) @app.route('/') def f(): return 'hello world!' @app.route('/upload', methods=['POST', 'PUT']) def upload_file() if request.method == 'POST': pass # ...
The link between the GET operation named after the routing URL "/" and the called function f is represented by an arrow pointing to the function:
The name of a saved Web Service Operation object will be generated from the routing URL by adding a final slash when not present. In this example the name of the PUT and POST operations is "/upload/" after the routing url "/upload".
URL query parameters such as @app.route('/user/<username>') are supported. In this case the generated Web Service Operation object will be named as /user/{}/, as shown in the example below.
from flask import Flask app = Flask(__name__) @app.route('/user/<username>') def show_user_profile(username): return 'User %s' % username
Similarly double slashes // in flask routing URLs are transformed into /{}/. Additional backslashes inside URL query parameters of type path [ @app.route('/<path:path>') ] are not resolved (which in principle could catch any URL) so the web service will be named as a regular parameter /{}/.
The equivalent alternative to routing annotations using the Flask add_url_rule is also supported.
from flask import Flask app = Flask(__name__) def index(): pass app.add_url_rule('/', 'index')
Database queries
Simple database queries consistent with the Python Database API Specification (PEP 249) are recognized. This allows to support a large number of important libraries interfacing Python and SQL databases (SQLite, MySQL, etc). The analyzer identifies execute method calls as potential database queries and searches for generic SQL statements passed in as an argument ('SELECT ...", "INSERT ...)". In the example below data from the stocks table is retrieved via a SELECT statement passed explicitly by a string to the execute method of a cursor object.
# select.py import sqlite3 conn = sqlite3.connect('example.db') c = conn.cursor() c.execute('SELECT * FROM stocks')
The analyzer creates a SQL Named Query object with name SELECT * FROM stocks (first 4 words are only used as naming convention) representing a call to a database. Provided analysis dependencies between SQL and Python are configured in CAST Management Studio, the analyzer will automatically link this object to the corresponding Table object, in this case stocks, that has been generated by a SQL analysis unit.
File system access functions
Representing end points based on file system access is important to automatically configure transactions. Towards this goal we aim at providing automatic recognition of standard library input/output functions. Currently we provide support for the built-in open function and the most common methods associated to file-like objects write, read, writelines, readline, readlines, and close, as shown in the example below.
# file1.py data = """<html> <header><title>This is title</title></header> <body> Hello world </body> </html> """ f = open('page.html', 'w') f.write(data) f.close()
The objects corresponding to the code of the file1.py file are inside the Universal Directory root object. Additionally the analyser will automatically generate a Python external library object representing the Python Standard Library. Within this, the Python built-in library is abstracted as a Python source code object named builtins.py, with its corresponding open function and file class (abstracting general file-like objects) that contains the above mentioned methods. No differences are considered between Python2 and Python3 built-in functions. Notice the external character of these objects denoted by gray-shaded icons in the left Object Browser panel.
Due to implementation constraints in CAIP versions [7.3.6, 8.1] a spurious link is generated between the Python external library object and a PY File object.
Limitations
CANDIDATE FOR IMPROVEMENT
- Not fully supported Python Decorator function.
- Quality rules do not apply to code inside the class definition (class or "static" variables)
- Limited Python resolution that leads to missing links:
- No support for __all__
- No support for variable of type class, function
- Limited method resolution when used super under multiple inheritance.
- Flask:
- Objects for other web service operations such as PATCH are not generated.
- The endpoint abstraction layer between functions and annotations is not considered. When using add_url_rule the endpoint argument is taken as the calling function name.