⚙ Technical documentation¶
transformer
– Main APItransformer.plugins
– Plugin Systemtransformer.request
– HTTP requests read from HARtransformer.task
– HTTP requests and related processingtransformer.scenario
– Grouping related tasks into scenariostransformer.python
– Python Syntax Tree
transformer
– Main API¶
This module exports the functions that should cover most use-cases of any Transformer user.
-
transformer.
dumps
(scenario_paths, plugins=(), with_default_plugins=True)[source]¶ Transforms the provided scenario_paths using the provided plugins, and returns the resulting locustfile code as a string.
See also:
dump()
Parameters: Return type:
-
transformer.
dump
(file, scenario_paths, plugins=(), with_default_plugins=True)[source]¶ Transforms the provided scenario_paths using the provided plugins, and writes the resulting locustfile code in the provided file.
See also:
dumps()
Parameters: - file (
Textio
) – an object with a writelines method (as specified by io.TextIOBase), e.g. sys.stdout or the result of open. - scenario_paths (
Iterable
[Union
[str
,Path
]]) – paths to scenario files (HAR) or directories. - plugins (
Sequence
[str
]) – names of plugins to use. - with_default_plugins (
bool
) – whether the default plugins should be used in addition to those provided (recommended: True).
Return type: None
- file (
transformer.plugins
– Plugin System¶
This module exposes the API needed to create your own Transformer plugins.
See also
- 🚀 Writing plugins
- The rationale for contracts, and a description of the most important ones.
-
@
transformer.plugins.
plugin
(contract)[source]¶ Associates a function to a
Contract
, making that function a Transformer plugin that will be detected as such byresolve
.Parameters: contract (Contract) – the contract to associate to the decorated function. Raises: InvalidContractError – if contract is not a valid Contract
.
-
class
transformer.plugins.
Contract
[source]¶ Enumeration of all supported plugin contracts. Each specific contract defines a way for plugins to be used in Transformer.
Any Python function may become a Transformer plugin by announcing that it implements at least one contract, using the
@plugin
decorator.-
OnScenario
= 2¶ The OnScenario contract.
-
OnPythonProgram
= 4¶ The OnPythonProgram contract.
-
OnTaskSequence
= 8¶ Deprecated.
-
transformer.request
– HTTP requests read from HAR¶
Representation of HAR Request objects.
-
class
transformer.request.
HttpMethod
[source]¶ Enumeration of supported HTTP method types.
-
DELETE
= 5¶ DELETE
-
GET
= 1¶ GET
-
OPTIONS
= 4¶ OPTIONS
-
PATCH
= 6¶ PATCH
-
POST
= 2¶ POST
-
PUT
= 3¶ PUT
-
-
class
transformer.request.
QueryPair
(name, value)[source]¶ A pair of query parameters, as recorded in a HAR file (queryString).
-
class
transformer.request.
Request
(timestamp, method, url, har_entry, headers=mappingproxy({}), post_data=None, query=(), name=None)[source]¶ An HTTP request, as recorded in a HAR file (request).
Note that post_data, if present, will be a dict of the same format as recorded in the HAR file (postData – although it is not consistently followed by HAR generators).
-
method
¶ HttpMethod
– HTTP method of the request.
-
url
¶ urllib.parse.SplitResult
– URL targeted by the request.
-
har_entry
¶ dict
– A single record from entries as recorded in a HAR file corresponding to the request, provided for read-only access.
-
query
= []¶ List
ofQueryPair
– Key-value arguments sent as part of theurl
’s query string.
-
name
= None¶ Optional
str
– Value provided forlocust.clients.HttpSession
’s “dynamic”name
parameter. See Grouping requests to URLs with dynamic parameters for details.
-
classmethod
all_from_har
(har)[source]¶ Generates requests for all entries in a given HAR top-level object.
Return type: Iterator
[Request
]
-
classmethod
from_har_entry
(entry)[source]¶ Creates a request from a HAR entry.
Raises: - KeyError – if entry is not a valid HAR “entry” object.
- ValueError – if the
request.startedDateTime
value cannot be interpreted as a timestamp.
Return type:
-
transformer.python
– Python Syntax Tree¶
Transformer’s Python Syntax Tree framework allows you to create and manipulate Python source code without bothering with irrelevant, style-related details.
It is the main API for writing OnPythonProgram plugins.
A non-goal of this framework is customization of style: users should rely on an external tool (such as black) if they need style customization of their generated locustfile.
See also
- Syntax tree
- High-level description of Transformer’s “syntax tree” internal object.
-
class
transformer.python.
Line
(text, indent_level=0)[source]¶ Bases:
object
A line of text and its associated indentation level.
This class allows not to constantly copy strings to add a new indentation level at every scope of the syntax tree.
-
class
transformer.python.
Statement
(comments=())[source]¶ Bases:
object
Python distinguishes between statements and expressions: basically, statements cannot be assigned to a variable, whereas expressions can.
For our purpose, another distinction is important: statements may span over multiple lines (and not just for style), whereas all expressions can be expressed in a single line.
This class serves as abstract base for all implementors of
lines()
and handles comment processing for them.Parameters: comments ( Sequence
[str
]) – Comment lines attached to this statement.-
comments
¶ Comment lines attached to this statement.
This is a
property
to ensure that modifications of this list preserve the invariant “one element = one line”.Return type: List
[str
]
-
lines
(indent_level=0, comments=True)[source]¶ All Line objects necessary to represent this Statement, along with the appropriate indentation level.
Parameters: Return type:
-
-
class
transformer.python.
OpaqueBlock
(block, comments=())[source]¶ Bases:
transformer.python.Statement
A block of code already represented as a string. This helps moving existing code (e.g. in plugins) from our ad-hoc “blocks of code” framework to the syntax tree framework defined in this module. It also allows to express Python constructs that would otherwise not yet be representable with this AST framework.
Parameters: block ( str
) – String representing a block of Python code.
-
class
transformer.python.
Function
(name, params, statements, comments=())[source]¶ Bases:
transformer.python.Statement
A function definition (
def ...
).Parameters:
-
class
transformer.python.
Decoration
(decorator, target, comments=())[source]¶ Bases:
transformer.python.Statement
A function or class definition to which is applied a decorator (e.g.
@task
).Parameters:
-
class
transformer.python.
Class
(name, statements, superclasses=(), comments=())[source]¶ Bases:
transformer.python.Statement
A class definition.
Parameters:
-
class
transformer.python.
Expression
[source]¶ Bases:
object
See the documentation of
Statement
for why Expression is a separate class. An expression is still a statement in Python (e.g. functions can be called anywhere), but thisExpression
class is not aStatement
because we can’t attach comments to arbitrary expressions (e.g. between braces). If you need to use anExpression
as aStatement
, see theStandalone
wrapper class.This class serves as abstract base for all our implementors of
__str__()
.
-
class
transformer.python.
Standalone
(expr, comments=())[source]¶ Bases:
transformer.python.Statement
Wraps an
Expression
so that it can be used as aStatement
.Parameters: expr ( Expression
) – The wrapped expression.
-
class
transformer.python.
Literal
(value)[source]¶ Bases:
transformer.python.Expression
All literal Python expressions (integers, strings, lists, etc.).
Everything will be serialized using
repr()
, exceptExpression
objects that could be contained in a composite value likelist
: they will be serialized withstr()
, as is probably expected. Thus:>>> str(Literal([1, {"a": FString("-{x}")}])) "[1, {'a': f'-{x}'}]"
instead of something like
[1, {'a': FString('-{x}')}]
.See also
Parameters: value ( Any
) – The Python literal represented by this node.
-
class
transformer.python.
FString
(s)[source]¶ Bases:
transformer.python.Literal
f-strings are strings that capture values from their environment.
They cannot be handled in
Literal
because they are a “trick” of the Python parser: before the program runs, they lose theirf
prefix and their template is evaluated, so whenLiteral
is instantiated, they are only a normal string that tried to capture values from Transformer’s context (instead of the locustfile’s context).Parameters: s ( str
) – The template of this f-string, for examplea{x}b
for the f-stringf"a{x}b"
.
-
class
transformer.python.
Symbol
(name)[source]¶ Bases:
transformer.python.Expression
The name of something (variable, function, etc.). Avoids any kind of string quoting and escaping that would happen with
Literal
.>>> str(Literal("x")) "'x'" >>> str(Symbol("x")) 'x'
The provided argument’s type is explicitly checked and a
TypeError
may be raised to avoid confusion when a user expects e.g.Symbol(True)
to work likeSymbol("True")
.Parameters: name ( str
) – Textual representation of this symbol. Will be forwarded without modification to the locustfile.
-
class
transformer.python.
FunctionCall
(name, positional_args=(), named_args=mappingproxy({}))[source]¶ Bases:
transformer.python.Expression
The invocation of a function or method.
Parameters: - name (
str
) – Name of the function that is called. - positional_args (
Sequence
[Expression
]) – Positional arguments associated with this call, if any. - named_args (
Mapping
[str
,Expression
]) – Keyword-arguments associated with this call, if any.
- name (
-
class
transformer.python.
BinaryOp
(lhs, op, rhs)[source]¶ Bases:
transformer.python.Expression
The invocation of a binary operator.
To avoid any precedence error in the generated code, operands that are also BinaryOps are always surrounded by braces (even when not necessary, as in “1 + (2 + 3)”, as a more subtle behavior would increase the complexity of the implementation without much benefit.
Parameters: - lhs (
Expression
) – Left-hand side operand of this operation. - op (
str
) – Name of the operator, like+
. - rhs (
Expression
) – Right-hand side operand of this operation.
- lhs (
-
class
transformer.python.
Assignment
(lhs, rhs, comments=())[source]¶ Bases:
transformer.python.Statement
The assignment of a value to a variable.
For our purposes, we don’t treat multiple assignment via tuples differently. We also don’t support chained assignments such as
a = b = 1
.Parameters: - lhs (
str
) – Variable name (or names) the rhs is assigned to. - rhs (
Expression
) – Expression which value is assigned to lhs.
- lhs (
-
class
transformer.python.
IfElse
(condition_blocks, else_block=None, comments=())[source]¶ Bases:
transformer.python.Statement
The if/elif/else construct, where elif and else are optional and elif can be repeated.
Parameters: - condition_blocks (
Sequence
[Tuple
[Expression
,Sequence
[Statement
]]]) – Pairs of condition and statements. Each pair is composed of an expression representing a condition, and a list of statements corresponding to that condition. This represents an if/elif/…/elif sequence, where there is always an “if” clause and an arbitrary number of “elif” clauses. - else_block (
Optional
[Sequence
[Statement
]]) – Statements representing the “else” clause, if any.
Raises: ValueError – If there is not at least one element in condition_blocks.
- condition_blocks (
-
class
transformer.python.
Import
(targets, source=None, alias=None, comments=())[source]¶ Bases:
transformer.python.Statement
The import statement in all its forms:
import X
,import X as A
,from M import X
,from M import X as A
, andfrom M import X, Y
.Combined imports like
from M import X, Y
are split for simplicity.Parameters: Raises: ValueError – If targets is empty, or if alias is specified even though there are multiple targets.
-
class
transformer.python.
Return
(value, comments=())[source]¶ Bases:
transformer.python.Statement
The return statement.
-
class
transformer.python.
ExpressionView
(target, converter, name)[source]¶ Bases:
transformer.python.Expression
A “proxy” for an object that is not an
Expression
.ExpressionView
allows to mix non-Expression
objects in the syntax tree, along with a function capable of transforming these objects into actualExpression
objects at any time. This is useful when these objects are easier to manipulate than theirExpression
equivalent.For example: any
Request
object can be converted into an equivalentExpression
, butRequest
has a simpler API thanExpression
for request-oriented operations like accessing the URL, etc.ExpressionView
can “wrap” aRequest
to pretend that theRequest
is anExpression
(with all associated benefits of being part of the syntax tree), but still support theRequest
API.-
target
¶ () → T
– A function (without parameters) returning the wrapped, non-Expression
object.The benefit of
target
being a function (instead of a direct reference to the wrapped object) is that it allows to specify some mutable field of an object. See for exampleTask2
, which contains anExpressionView
wrapping its ownrequest
attribute. If the value of that attribute changes, theExpressionView
will refer to the new value (found by accessing the attribute via self), not the old value (which would still be referenced by a non-callabletarget
).
-
converter
¶ T →
Expression
– A function capable of transforming the result oftarget
into anExpression
. The result ofconverter
is computed each time thisExpressionView
has to behave like anExpression
, for example when passed as argument tostr
.
-
name
¶ str
– Purely descriptive: makes the inspection of data structures containingExpressionView
objects more comfortable.
-