[docs] Docstrings for system YAQL functions

Change-Id: Idb9036f2a5eed1a9c4960e84bfc92e4cb0573097
This commit is contained in:
Omar Shykhkerimov 2016-06-02 17:53:27 +03:00
parent a7393f446a
commit 855b6839db
1 changed files with 229 additions and 0 deletions

View File

@ -11,6 +11,9 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
The module describes main system functions for working with objects.
"""
import itertools
@ -25,12 +28,38 @@ from yaql.language import yaqltypes
@specs.parameter('name', yaqltypes.StringConstant())
@specs.name('#get_context_data')
def get_context_data(name, context):
""":yaql:getContextData
Returns the context value by its name. This function is system
and can be overridden to change the way of getting context data.
:signature: getContextData(name)
:arg name: value's key name
:argType name: string
:returnType: any (value type)
"""
return context[name]
@specs.parameter('expr', yaqltypes.Lambda(method=True))
@specs.name('#operator_.')
def op_dot(receiver, expr):
""":yaql:operator .
Returns expr evaluated on receiver.
:signature: receiver.expr
:arg receiver: object to evaluate expression
:argType receiver: any
:arg expr: expression
:argType expr: expression that can be evaluated as a method
:returnType: expression result type
.. code::
yaql> [0, 1].select($+1)
[1, 2]
"""
return expr(receiver)
@ -38,6 +67,25 @@ def op_dot(receiver, expr):
@specs.inject('operator', yaqltypes.Delegate('#operator_.'))
@specs.name('#operator_?.')
def elvis_operator(operator, receiver, expr):
""":yaql:operator ?.
Evaluates expr on receiver if receiver isn't null and returns the result.
If receiver is null returns null.
:signature: receiver?.expr
:arg receiver: object to evaluate expression
:argType receiver: any
:arg expr: expression
:argType expr: expression that can be evaluated as a method
:returnType: expression result or null
.. code::
yaql> [0, 1]?.select($+1)
[1, 2]
yaql> null?.select($+1)
null
"""
if receiver is None:
return None
return operator(receiver, expr)
@ -47,6 +95,31 @@ def elvis_operator(operator, receiver, expr):
@specs.parameter('args', yaqltypes.String())
@specs.method
def unpack(sequence, context, *args):
""":yaql:unpack
Returns context object with sequence values unpacked to args.
If args size is equal to sequence size then args get appropriate
sequence values.
If args size is 0 then args are 1-based indexes.
Otherwise ValueError is raised.
:signature: sequence.unpack([args])
:receiverArg sequence: iterable of items to be passed as context values
:argType sequence: iterable
:arg [args]: keys to be associated with sequence items. If args size is
equal to sequence size then args get appropriate sequence items. If
args size is 0 then args are indexed start from 1. Otherwise exception
will be thrown
:argType [args]: chain of strings
:returnType: context object
.. code::
yaql> [1, 2].unpack(a, b) -> $a + $b
3
yaql> [2, 3].unpack() -> $1 + $2
5
"""
lst = tuple(itertools.islice(sequence, len(args) + 1))
if 0 < len(args) != len(lst):
raise ValueError('Cannot unpack {0} elements into {1}'.format(
@ -61,6 +134,20 @@ def unpack(sequence, context, *args):
def with_(context, *args):
""":yaql:with
Returns new context object where args are stored with 1-based indexes.
:signature: with([args])
:arg [args]: values to be stored under appropriate numbers $1, $2, ...
:argType [args]: chain of any values
:returnType: context object
.. code::
yaql> with("ab", "cd") -> $1 + $2
"abcd"
"""
for i, t in enumerate(args, 1):
context[str(i)] = t
return context
@ -68,6 +155,23 @@ def with_(context, *args):
@specs.inject('__context__', yaqltypes.Context())
def let(__context__, *args, **kwargs):
""":yaql:let
Returns context object where args are stored with 1-based indexes
and kwargs values are stored with appropriate keys.
:signature: let([args], {kwargs})
:arg [args]: values to be stored under appropriate numbers $1, $2, ...
:argType [args]: chain of any values
:arg {kwargs}: values to be stored under appropriate keys
:argType {kwargs}: chain of mappings
:returnType: context object
.. code::
yaql> let(1, 2, a => 3, b => 4) -> $1 + $a + $2 + $b
10
"""
for i, value in enumerate(args, 1):
__context__[str(i)] = value
@ -79,6 +183,22 @@ def let(__context__, *args, **kwargs):
@specs.parameter('name', yaqltypes.String())
@specs.parameter('func', yaqltypes.Lambda())
def def_(name, func, context):
""":yaql:def
Returns new context object with function name defined.
:signature: def(name, func)
:arg name: name of function
:argType name: string
:arg func: function to be stored under provided name
:argType func: lambda
:returnType: context object
.. code::
yaql> def(sq, $*$) -> [1, 2, 3].select(sq($))
[1, 4, 9]
"""
@specs.name(name)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
@ -91,6 +211,22 @@ def def_(name, func, context):
@specs.parameter('right', yaqltypes.Lambda(with_context=True))
@specs.name('#operator_->')
def send_context(left, right):
""":yaql:operator ->
Evaluates lambda on provided context and returns the result.
:signature: left -> right
:arg left: context to be used for function
:argType left: context object
:arg right: function
:argType right: lambda
:returnType: any (function return value type)
.. code::
yaql> let(a => 1) -> $a
1
"""
return right(left)
@ -98,6 +234,30 @@ def send_context(left, right):
@specs.parameter('condition', yaqltypes.Lambda())
@specs.parameter('message', yaqltypes.String())
def assert__(engine, obj, condition, message=u'Assertion failed'):
""":yaql:assert
Evaluates condition against object. If it evaluates to true returns the
object, otherwise throws an exception with provided message.
:signature: obj.assert(condition, message => "Assertion failed")
:arg obj: object to evaluate condition on
:argType obj: any
:arg condition: lambda function to be evaluated on obj. If result of
function evaluates to false then trows exception message
:argType condition: lambda
:arg message: message to trow if condition returns false
:argType message: string
:returnType: obj type or message
.. code::
yaql> 12.assert($ < 2)
Execution exception: Assertion failed
yaql> 12.assert($ < 20)
12
yaql> [].assert($, "Failed assertion")
Execution exception: Failed assertion
"""
if utils.is_iterator(obj):
obj = utils.memorize(obj, engine)
if not condition(obj):
@ -109,11 +269,45 @@ def assert__(engine, obj, condition, message=u'Assertion failed'):
@specs.parameter('callable_', yaqltypes.PythonType(
object, False, validators=(six.callable,)))
def call(callable_, *args, **kwargs):
""":yaql:call
Evaluates function with specified args and kwargs and returns the
result.
This function is used to transform expressions like '$foo(args, kwargs)'
to '#call($foo, args, kwargs)'.
Note that to use this functionality 'delegate' mode has to be enabled.
:signature: call(callable, args, kwargs)
:arg callable: callable function
:argType callable: python type
:arg args: sequence of items to be used for calling
:argType args: sequence
:arg kwargs: dictionary with kwargs to be used for calling
:argType kwargs: mapping
:returnType: any (callable return type)
"""
return callable_(*args, **kwargs)
@specs.parameter('func', yaqltypes.Lambda())
def lambda_(func):
""":yaql:lambda
Constructs a new anonymous function
Note that to use this function 'delegate' mode has to be enabled.
:signature: lambda(func)
:arg func: function to be returned
:argType func: lambda
:returnType: obj type or message
.. code::
yaql> let(func => lambda(2 * $)) -> [1, 2, 3].select($func($))
[2, 4, 6]
yaql> [1, 2, 3, 4].where(lambda($ > 3)($ + 1))
[3, 4]
"""
return func
@ -121,6 +315,22 @@ def lambda_(func):
@specs.parameter('name', yaqltypes.Keyword())
@specs.inject('func', yaqltypes.Delegate(use_convention=False))
def get_property(func, obj, name):
""":yaql:operator .
Returns value of 'name' property.
:signature: left.right
:arg left: object
:argType left: any
:arg right: object property name
:argType right: keyword
:returnType: any
.. code::
yaql> now().year
2016
"""
func_name = '#property#{0}'.format(name)
return func(func_name, obj)
@ -130,6 +340,25 @@ def get_property(func, obj, name):
@specs.parameter('args', yaqltypes.Sequence())
@specs.parameter('kwargs', utils.MappingType)
def call_func(context, engine, name, args, kwargs, receiver=utils.NO_VALUE):
""":yaql:call
Evaluates function name with specified args and kwargs and returns the
result.
:signature: call(name, args, kwargs)
:arg name: name of callable
:argType name: string
:arg args: sequence of items to be used for calling
:argType args: sequence
:arg kwargs: dictionary with kwargs to be used for calling
:argType kwargs: mapping
:returnType: any (callable return type)
.. code::
yaql> call(let, [1, 2], {a => 3, b => 4}) -> $1 + $a + $2 + $b
10
"""
return context(name, engine, receiver)(
*args, **utils.filter_parameters_dict(kwargs))