⚙ 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
@plugindecorator.-
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= []¶ ListofQueryPair– Key-value arguments sent as part of theurl’s query string.
-
name= None¶ Optionalstr– Value provided forlocust.clients.HttpSession’s “dynamic”nameparameter. 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.startedDateTimevalue 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:
objectA 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:
objectPython 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
propertyto 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.StatementA 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.StatementA function definition (
def ...).Parameters:
-
class
transformer.python.Decoration(decorator, target, comments=())[source]¶ Bases:
transformer.python.StatementA 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.StatementA class definition.
Parameters:
-
class
transformer.python.Expression[source]¶ Bases:
objectSee the documentation of
Statementfor why Expression is a separate class. An expression is still a statement in Python (e.g. functions can be called anywhere), but thisExpressionclass is not aStatementbecause we can’t attach comments to arbitrary expressions (e.g. between braces). If you need to use anExpressionas aStatement, see theStandalonewrapper class.This class serves as abstract base for all our implementors of
__str__().
-
class
transformer.python.Standalone(expr, comments=())[source]¶ Bases:
transformer.python.StatementWraps an
Expressionso that it can be used as aStatement.Parameters: expr ( Expression) – The wrapped expression.
-
class
transformer.python.Literal(value)[source]¶ Bases:
transformer.python.ExpressionAll literal Python expressions (integers, strings, lists, etc.).
Everything will be serialized using
repr(), exceptExpressionobjects 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.Literalf-strings are strings that capture values from their environment.
They cannot be handled in
Literalbecause they are a “trick” of the Python parser: before the program runs, they lose theirfprefix and their template is evaluated, so whenLiteralis 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}bfor the f-stringf"a{x}b".
-
class
transformer.python.Symbol(name)[source]¶ Bases:
transformer.python.ExpressionThe 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
TypeErrormay 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.ExpressionThe 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.ExpressionThe 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.StatementThe 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.StatementThe 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.StatementThe 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, Yare 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.StatementThe return statement.
-
class
transformer.python.ExpressionView(target, converter, name)[source]¶ Bases:
transformer.python.ExpressionA “proxy” for an object that is not an
Expression.ExpressionViewallows to mix non-Expressionobjects in the syntax tree, along with a function capable of transforming these objects into actualExpressionobjects at any time. This is useful when these objects are easier to manipulate than theirExpressionequivalent.For example: any
Requestobject can be converted into an equivalentExpression, butRequesthas a simpler API thanExpressionfor request-oriented operations like accessing the URL, etc.ExpressionViewcan “wrap” aRequestto pretend that theRequestis anExpression(with all associated benefits of being part of the syntax tree), but still support theRequestAPI.-
target¶ () → T– A function (without parameters) returning the wrapped, non-Expressionobject.The benefit of
targetbeing 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 anExpressionViewwrapping its ownrequestattribute. If the value of that attribute changes, theExpressionViewwill 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 oftargetinto anExpression. The result ofconverteris computed each time thisExpressionViewhas to behave like anExpression, for example when passed as argument tostr.
-
name¶ str– Purely descriptive: makes the inspection of data structures containingExpressionViewobjects more comfortable.
-