Esempio n. 1
0
def test_module_name():
    # Supertype
    Point = Record.create_type("Point", "coordinate_x")
    eq_(__name__, Point.__module__)

    # Subtype
    Point3D = Point.extend_type("Point3D", "coordinate_z")
    eq_(__name__, Point3D.__module__)
Esempio n. 2
0
def test_getting_field_names():
    # Supertype
    Point = Record.create_type("Point", "coordinate_x", "coordinate_y")
    eq_(("coordinate_x", "coordinate_y"), Point.field_names)

    # Subtype
    Point3D = Point.extend_type("Point3D", "coordinate_z")
    eq_(("coordinate_x", "coordinate_y", "coordinate_z"), Point3D.field_names)
Esempio n. 3
0
def test_creation_with_duplicated_field_names():
    # Same field duplicated by position
    assert_raises_regexp(
        RecordTypeError,
        "^The following field names are duplicated: coordinate_x$",
        Record.create_type,
        "Point",
        "coordinate_x",
        "coordinate_x",
        )
    
    # Multiple fields duplicated
    assert_raises_regexp(
        RecordTypeError,
        "^The following field names are duplicated: " \
            "coordinate_x, coordinate_y$",
        Record.create_type,
        "Point",
        "coordinate_x",
        "coordinate_y",
        "coordinate_x",
        "coordinate_y",
        )
    
    # Subtype
    Point = Record.create_type("Point", "coordinate_x", "coordinate_y")
    assert_raises_regexp(
        RecordTypeError,
        "^The following field names are duplicated: coordinate_z$",
        Point.extend_type,
        "Point3D",
        "coordinate_z",
        "coordinate_z",
        )
    
    # Subtype redefining field in supertype
    Point = Record.create_type("Point", "coordinate_x", "coordinate_y")
    assert_raises_regexp(
        RecordTypeError,
        "^The following field names are duplicated: coordinate_x$",
        Point.extend_type,
        "Point3D",
        "coordinate_z",
        "coordinate_x",
        )
Esempio n. 4
0
 def test_different_type_and_same_field_values(self):
     point = Point(2, 4)
     
     AlternativePoint = Record.create_type(
         "AlternativePoint",
         "coordinate_x",
         "coordinate_y",
         )
     alternative_point = AlternativePoint(2, 4)
     
     self.assert_not_equals(point, alternative_point)
Esempio n. 5
0
def test_creation_with_ilegal_type_name():
    # Supertype
    assert_raises_string(
        RecordTypeError,
        "'Invalid-Name' is not a valid identifier for a record type",
        Record.create_type,
        "Invalid-Name",
        )

    # Subtype
    Point = Record.create_type("Point", "coordinate_x", "coordinate_y")
    assert_raises_string(
        RecordTypeError,
        "'Invalid-Name' is not a valid identifier for a record type",
        Point.extend_type,
        "Invalid-Name",
        )
Esempio n. 6
0
def test_creation_with_ilegal_field_name():
    # Supertype
    assert_raises_string(
        RecordTypeError,
        "'coordinate-x' is not a valid field name",
        Record.create_type,
        "Point",
        "coordinate-x",
        )

    # Subtype
    Point = Record.create_type("Point", "coordinate_x", "coordinate_y")
    assert_raises_string(
        RecordTypeError,
        "'Invalid-Field' is not a valid field name",
        Point.extend_type,
        "Point3D",
        "Invalid-Field",
        )
Esempio n. 7
0
def test_default_value_for_undefined_field():
    # Supertype
    assert_raises_string(
        RecordTypeError,
        'Unknown field "weight"',
        Record.create_type,
        "Point",
        "coordinate_x",
        weight=3,
        )

    # Subtype
    Point = Record.create_type("Point", "coordinate_x", "coordinate_y")
    assert_raises_string(
        RecordTypeError,
        'Unknown field "weight"',
        Point.extend_type,
        "Point3D",
        "coordinate_z",
        weight=3,
        )
from six import text_type
from voluptuous import Optional
from voluptuous import Schema
from six import text_type

from hubspot.contacts._constants import CONTACTS_API_SCRIPT_NAME
from hubspot.contacts._schemas.properties import \
    PROPERTY_RESPONSE_SCHEMA_DEFINITION
from hubspot.contacts.properties import _build_property_from_data
from hubspot.contacts.request_data_formatters.property_groups import \
    format_data_for_property_group

PropertyGroup = Record.create_type(
    'PropertyGroup',
    'name',
    'display_name',
    'properties',
    display_name=None,
    properties=(),
)

_PROPERTY_GROUP_CREATION_SCHEMA = Schema(
    {'name': text_type, 'displayName': text_type},
    required=True,
    extra=True,
)

_PROPERTY_GROUPS_RETRIEVAL_SCHEMA = Schema(
    [{
        'name': text_type,
        'displayName': text_type,
        Optional('properties'): [PROPERTY_RESPONSE_SCHEMA_DEFINITION],
Esempio n. 9
0
from pyrecord import Record
from voluptuous import Optional
from voluptuous import Schema

from hubspot.contacts._constants import CONTACTS_API_SCRIPT_NAME
from hubspot.contacts._schemas.properties import \
    PROPERTY_RESPONSE_SCHEMA_DEFINITION
from hubspot.contacts.properties import _build_property_from_data
from hubspot.contacts.request_data_formatters.property_groups import \
    format_data_for_property_group

PropertyGroup = Record.create_type(
    'PropertyGroup',
    'name',
    'display_name',
    'properties',
    display_name=None,
    properties=(),
)

_PROPERTY_GROUP_CREATION_SCHEMA = Schema(
    {
        'name': str,
        'displayName': str
    },
    required=True,
    extra=True,
)

_PROPERTY_GROUPS_RETRIEVAL_SCHEMA = Schema(
    [{
Esempio n. 10
0
from itertools import chain

from pyrecord import Record

from hubspot.contacts._constants import BATCH_SAVING_SIZE_LIMIT
from hubspot.contacts._constants import CONTACTS_API_SCRIPT_NAME, COMPANIES_API_SCRIPT_NAME
from hubspot.contacts._property_utils import get_property_type_by_property_name, get_property_type_by_property_name_companies
from hubspot.contacts.generic_utils import ipaginate
from hubspot.contacts.request_data_formatters.contacts import \
    format_contact_data_for_saving, format_contacts_data_for_saving, \
    format_contact_properties_for_saving, format_company_data_for_saving

Contact = Record.create_type(
    'Contact',
    'vid',
    'email_address',
    'properties',
    'related_contact_vids',
    related_contact_vids=(),
)

Company = Record.create_type(
    'Company',
    'properties',
)

_CONTACTS_SAVING_URL_PATH = CONTACTS_API_SCRIPT_NAME + '/contact/batch/'
_CONTACT_CREATING_URL_PATH = CONTACTS_API_SCRIPT_NAME + '/contact/'
_CONTACT_UPDATING_URL_TEMPLATE = CONTACTS_API_SCRIPT_NAME + '/contact/vid/{contact_id}/profile'

_COMPANY_CREATING_URL_PATH = COMPANIES_API_SCRIPT_NAME + '/companies/'
# license should accompany this distribution. THIS SOFTWARE IS PROVIDED "AS IS"
# AND ANY AND ALL EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT
# NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST
# INFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE.
#
##############################################################################

from pyrecord import Record

from hubspot.contacts._constants import CONTACTS_API_SCRIPT_NAME


Property = Record.create_type(
    'Property',
    'name',
    'label',
    'description',
    'group_name',
    'field_widget',
    )

BooleanProperty = Property.extend_type(
    'BooleanProperty',
    'true_label',
    'false_label',
    true_label='Yes',
    false_label='No',
    )

DateProperty = Property.extend_type('DateProperty')

DatetimeProperty = Property.extend_type('DatetimeProperty')
Esempio n. 12
0
 def test_overriding_default_field_value(self):
     Point = Record.create_type("Point", "coordinate_x", coordinate_x=2)
     my_point = Point(1)
     eq_(my_point.coordinate_x, 1)
Esempio n. 13
0
from nose.tools import assert_false
from nose.tools import assert_not_in
from nose.tools import assert_raises_regexp
from nose.tools import eq_
from nose.tools import ok_

from pyrecord import Record
from pyrecord.exceptions import RecordInstanceError


Point = Record.create_type("Point", "coordinate_x", "coordinate_y")
Point3D = Point.extend_type("Point3D", "coordinate_z")


class TestInitialization(object):
    
    def test_initialization(self):
        my_point = Point(1, 3)
        ok_(isinstance(my_point, Point))
        eq_(my_point.coordinate_x, 1)
        eq_(my_point.coordinate_y, 3)
    
    def test_initialization_by_name(self):
        my_point = Point(coordinate_x=1, coordinate_y=3)
        eq_(my_point.coordinate_x, 1)
        eq_(my_point.coordinate_y, 3)
    
    def test_subtype(self):
        my_point_3d = Point3D(1, 3, 5)
        eq_(my_point_3d.coordinate_x, 1)
        eq_(my_point_3d.coordinate_y, 3)
# AND ANY AND ALL EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT
# NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST
# INFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE.
#
##############################################################################

from copy import deepcopy

from pyrecord import Record


APICall = Record.create_type(
    'APICall',
    'url_path',
    'http_method',
    'query_string_args',
    'request_body_deserialization',
    query_string_args=None,
    request_body_deserialization=None,
    )


SuccessfulAPICall = APICall.extend_type(
    'SuccessfulAPICall',
    'response_body_deserialization',
    )


UnsuccessfulAPICall = APICall.extend_type('UnsuccessfulAPICall', 'exception')

Esempio n. 15
0
def test_subtype_creation():
    Point = Record.create_type("Point", "coordinate_x", "coordinate_y")
    Point3D = Point.extend_type("Point3D", "coordinate_z")
    eq_("Point3D", Point3D.__name__)
    ok_(issubclass(Point3D, Point))
    assert_not_equals(Point3D, Point)
Esempio n. 16
0
def test_creation():
    Point = Record.create_type("Point", "coordinate_x", "coordinate_y")
    eq_("Point", Point.__name__)
    ok_(issubclass(Point, Record))
    assert_not_equals(Point, Record)
# license should accompany this distribution. THIS SOFTWARE IS PROVIDED "AS IS"
# AND ANY AND ALL EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT
# NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST
# INFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE.
#
##############################################################################
from builtins import str as text
from copy import deepcopy

from pyrecord import Record

APICall = Record.create_type(
    'APICall',
    'url_path',
    'http_method',
    'query_string_args',
    'request_body_deserialization',
    query_string_args=None,
    request_body_deserialization=None,
)

SuccessfulAPICall = APICall.extend_type(
    'SuccessfulAPICall',
    'response_body_deserialization',
)

UnsuccessfulAPICall = APICall.extend_type('UnsuccessfulAPICall', 'exception')


class MockPortalConnection(object):
    """
Esempio n. 18
0
from rest_framework.exceptions import PermissionDenied
from rest_framework.routers import DefaultRouter
from rest_framework.status import HTTP_401_UNAUTHORIZED
from rest_framework.status import HTTP_200_OK
from rest_framework.status import HTTP_404_NOT_FOUND
from rest_framework.status import HTTP_403_FORBIDDEN

from drf_nested_resources import DETAIL_VIEW_NAME_SUFFIX
from drf_nested_resources import LIST_VIEW_NAME_SUFFIX
from drf_nested_resources._forged_request import RequestForger


Resource = Record.create_type(
    'Resource',
    'name',
    'collection_name',
    'viewset',
    'sub_resources',
    sub_resources=(),
    )


NestedResource = Resource.extend_type(
    'NestedResource',
    'parent_field_lookup',
    )


_RelationalRoute = Record.create_type(
    'RelationalRoute',
    'name',
    'collection_name',
from pyrecord import Record

DarkSkyRequest = Record.create_type("DarkSkyrequest",
                                    "latitude",
                                    "longitude",
                                    latitude=None,
                                    longitude=None)
Esempio n. 20
0

_PROPERTY_VALUE_CONVERTER_BY_PROPERTY_TYPE = defaultdict(
    lambda: unicode,
    {
        BooleanProperty: json_deserialize,
        DateProperty: convert_timestamp_in_milliseconds_to_date,
        DatetimeProperty: convert_timestamp_in_milliseconds_to_datetime,
        NumberProperty: Decimal,
        },
    )


ContactList = Record.create_type(
    'ContactList',
    'id',
    'name',
    'is_dynamic',
    )


def create_static_contact_list(contact_list_name, connection):
    """
    Create a static contact list named ``contact_list_name``.
    
    :param basestring contact_list_name:
    :return ContactList: The resulting list as created by HubSpot
    :raises hubspot.connection.exc.HubspotException:
    
    """
    contact_list_data = connection.send_post_request(
        _CONTACT_LIST_COLLECTION_URL_PATH,
Esempio n. 21
0
from itertools import chain

from pyrecord import Record
from voluptuous import Any, REMOVE_EXTRA
from voluptuous import Schema


BATCH_RETRIEVAL_SIZE_LIMIT = 200


User = Record.create_type(
    'User',
    'id',
    'full_name',
    'email_address',
    'organization_name',
    'job_title',
    'url',
    )


Group = Record.create_type('Group', 'id')


_USER_DATA_SCHEMA = Schema(
    {
        'id': int,
        'full_name': str,
        'email_address': str,
        'organization_name': str,
Esempio n. 22
0
from itertools import chain

from pyrecord import Record

from hubspot.contacts._constants import BATCH_SAVING_SIZE_LIMIT
from hubspot.contacts._constants import CONTACTS_API_SCRIPT_NAME
from hubspot.contacts._property_utils import get_property_type_by_property_name
from hubspot.contacts.generic_utils import ipaginate
from hubspot.contacts.request_data_formatters.contacts import \
    format_contacts_data_for_saving


Contact = Record.create_type(
    'Contact',
    'vid',
    'email_address',
    'properties',
    'related_contact_vids',
    related_contact_vids=(),
    )


_CONTACTS_SAVING_URL_PATH = CONTACTS_API_SCRIPT_NAME + '/contact/batch/'


def save_contacts(contacts, connection):
    """
    Request the creation and/or update of the ``contacts``.
    
    :param iterable contacts: The contacts to be created/updated
    :return: ``None``
    :raises hubspot.connection.exc.HubspotException:
Esempio n. 23
0
            raise HubspotUnsupportedResponseError(exception_message)

        content_type = content_type_header_value.split(';')[0].lower()
        if content_type != 'application/json':
            exception_message = \
                'Unsupported response content type {}'.format(content_type)
            raise HubspotUnsupportedResponseError(exception_message)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        self._session.close()


_AuthenticationKey = Record.create_type('_AuthenticationKey', 'key_value')

OAuthKey = _AuthenticationKey.extend_type('OAuthKey')

APIKey = _AuthenticationKey.extend_type('APIKey')


class _QueryStringAuthenticationHandler(AuthBase):

    _KEY_NAME_BY_AUTHN_TYPE = {
        OAuthKey: 'access_token',
        APIKey: 'hapikey',
        }

    def __init__(self, authentication_key, *args, **kwargs):
        super(_QueryStringAuthenticationHandler, self).__init__(*args, **kwargs)
Esempio n. 24
0
            raise HubspotUnsupportedResponseError(exception_message)

        content_type = content_type_header_value.split(';')[0].lower()
        if content_type != 'application/json':
            exception_message = \
                'Unsupported response content type {}'.format(content_type)
            raise HubspotUnsupportedResponseError(exception_message)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        self._session.close()


_AuthenticationKey = Record.create_type('_AuthenticationKey', 'key_value')

OAuthKey = _AuthenticationKey.extend_type('OAuthKey')

APIKey = _AuthenticationKey.extend_type('APIKey')


class _QueryStringAuthenticationHandler(AuthBase):

    _KEY_NAME_BY_AUTHN_TYPE = {
        OAuthKey: 'access_token',
        APIKey: 'hapikey',
    }

    def __init__(self, authentication_key, *args, **kwargs):
        super(_QueryStringAuthenticationHandler,
Esempio n. 25
0
        return total_cost

    def _total_item(self, item_id, count):
        item = self._stock_by_id[item_id]
        if item.discount:
            discounts_qualified, items_unqualified_for_discount = divmod(
                count, item.discount.items)
            items_qualified_for_discount = item.discount.items * discounts_qualified
            discounted_item_cost = item.cost * (100 -
                                                item.discount.rate) / 100.0
            total_item_cost = item.cost * items_unqualified_for_discount + discounted_item_cost * items_qualified_for_discount
        else:
            total_item_cost = item.cost * count

        return total_item_cost


CheckoutItem = Record.create_type(
    'CheckoutItem',
    'id',
    'label',
    'cost',
    'discount',
    discount=None,
)

ItemDiscount = Record.create_type('ItemDiscount', 'items', 'rate')

ThresholdDiscount = Record.create_type('ThresholdDiscount', 'threshold',
                                       'rate')
Esempio n. 26
0
from typing import List, Union
from pyrecord import Record

Layer = Record.create_type("Layer", "weights", "activation", "bias")
Landscape = Record.create_type("Landscape", "position", "value")

Vector = List[float]
Data = Union[Vector, List[Vector]]
import numpy as np
from pyrecord import Record

#Arrays, List, Tuples, Records
#array - Need external library to get true arrays

# array
Animals = ["Dragon", "Lion", "Trex"]
# or use numpy
AnimalNp = np.array(["Dragon", "Lion", "Trex"])
# list
NaturePlaces = ["Jungle", "Savana", "Mountains"]
# tuples
tup = ("Fishing 101", "Hunting 101", "Gathering 101")
# records
Person = Record.create_type("Person", "name", "email_address")
Student = Person.extend_type("Student", "courses_read", "graduation_date", graduation_date=None)
karan_student = Student("Karan Sahu", "*****@*****.**", ["Calculus", "Comsci"])

# [::-1]
print("::-1 example:")
print(NaturePlaces[::-1])

# range and xrange
print("xrange example:")
for x in range(1, 3, 1):
    print(x)

for x in xrange(1, 3, 1):
    print(x)
# append
Esempio n. 28
0
 def test_skipping_field_with_default_value(self):
     Point = Record.create_type("Point", "coordinate_x", coordinate_x=2)
     my_point = Point()
     eq_(my_point.coordinate_x, 2)
Esempio n. 29
0
import threading
from rpyc.utils.server import ThreadedServer

import config
import rpcSend
import rpcReceive
import calibration
import watchDog


######################################################
# this task can run as a slave (controlled by rpc commands) or standAlone
######################################################
standAloneMode = False

point = Record.create_type('point', 'x', 'y')

markerType = Record.create_type('markerType', 'type', 'length', 'separation', 'orthoStopDist', 'allowedIds')
# adapt length to get a correct distance
# include distance of cart front to center (330) for the orthoStopDist
markerTypes = [markerType('dockingMarker', 100, 0.5, 600, [10]),
               markerType('dockingDetail', 60, 0.5, 0, [11]),
               markerType('objectMarker', 100, 1, 600, [0,1,2])]


# ARUCO_PORT = 20001
DOCKING_MARKER_ID = 10
DOCKING_DETAIL_ID = 11

DISTANCE_CART_CENTER_CAM = 330  # mm
MARKER_XOFFSET_CORRECTION = -22
Esempio n. 30
0
_CONTACT_LIST_COLLECTION_URL_PATH = CONTACTS_API_SCRIPT_NAME + '/lists'

_PROPERTY_VALUE_CONVERTER_BY_PROPERTY_TYPE = defaultdict(
    lambda: text_type,
    {
        BooleanProperty: json_deserialize,
        DateProperty: convert_timestamp_in_milliseconds_to_date,
        DatetimeProperty: convert_timestamp_in_milliseconds_to_datetime,
        NumberProperty: Decimal,
    },
)

ContactList = Record.create_type(
    'ContactList',
    'id',
    'name',
    'is_dynamic',
)


def create_static_contact_list(contact_list_name, connection):
    """
    Create a static contact list named ``contact_list_name``.
    
    :param basestring contact_list_name:
    :return ContactList: The resulting list as created by HubSpot
    :raises hubspot.connection.exc.HubspotException:
    
    """
    contact_list_data = connection.send_post_request(
        _CONTACT_LIST_COLLECTION_URL_PATH,
Esempio n. 31
0
from parse import parse

# number of possible orientations of tiles
NUM_ORIENTS = 8

# border index mapping: left, right, up, down
BORDER_INDEXES = {(-1, 0): 0, (1, 0): 1, (0, -1): 2, (0, 1): 3}
OPPOSING_BORDER_INDEXES = {0: 1, 1: 0, 2: 3, 3: 2}

# the sea monster
SEA_MONSTER = [
    "                  # ", "#    ##    ##    ###", " #  #  #  #  #  #   "
]

# stores a bit of hashed metadata for each tile
HashTile = Record.create_type("HashTile", "tile", "edges", "plugs",
                              "neighbours")
TilePlacement = Record.create_type("TilePlacement", "orient", "dx", "dy")
Placement = Record.create_type("Placement", "positions", "orients")


@print_calls
def part1(tiles):
    tiles = preprocess(tiles)

    # multiply the ids of the corner pieces
    result = reduce(mul, corners(tiles), 1)
    return result


@print_calls
def part2(tiles):
Esempio n. 32
0
# <http://dev.2degreesnetwork.com/p/2degrees-license.html>. A copy of the
# license should accompany this distribution. THIS SOFTWARE IS PROVIDED "AS IS"
# AND ANY AND ALL EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT
# NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST
# INFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE.
#
##############################################################################

from pyrecord import Record

from hubspot.contacts._constants import CONTACTS_API_SCRIPT_NAME

Property = Record.create_type(
    'Property',
    'name',
    'label',
    'description',
    'group_name',
    'field_widget',
)

BooleanProperty = Property.extend_type(
    'BooleanProperty',
    'true_label',
    'false_label',
    true_label='Yes',
    false_label='No',
)

DateProperty = Property.extend_type('DateProperty')

DatetimeProperty = Property.extend_type('DatetimeProperty')
Esempio n. 33
0
# define the appropraite models realted to weather data here
from pyrecord import Record

WeatherRequestModel = Record.create_type("WeatherRequestModel",
                                         "address",
                                         "latitude",
                                         "longitude",
                                         "language_flag",
                                         address=None,
                                         latitude=None,
                                         longitude=None,
                                         language_flag=None)

WeatherResponseModel = Record.create_type("WeatherResponseModel",
                                          "current_temp",
                                          "latitude",
                                          "longitude",
                                          "min_temps",
                                          "max_temps",
                                          "time",
                                          "units",
                                          "wind_speeds",
                                          current_temp=None,
                                          latitude=None,
                                          longitude=None,
                                          min_temps=None,
                                          max_temps=None,
                                          time=None,
                                          units=None,
                                          wind_speeds=None)
Esempio n. 34
0
from pyrecord import Record

View = Record.create_type("View", "status", "headers", "body")
Esempio n. 35
0
# Advent of Code 2020, Day 19
# (c) blu3r4y

import re

from typing import Union

from aocd.models import Puzzle
from funcy import print_calls, lmap
from pyrecord import Record

Data = Record.create_type("Data", "rules", "messages")

# Terminal: match the symbol exactly
Terminal = Record.create_type("Terminal", "symbol")
# disjunction: match any of the children
Disjunction = Record.create_type("Disjunction", "children")
# sequence: match the children in order
Sequence = Record.create_type("Sequence", "children")
# at least once: match the children one or multiple times
AtLeastOnce = Record.create_type("AtLeastOnce", "children")


@print_calls
def part1(data):
    regex = regex_transform(data.rules)
    matches = [regex.match(msg) is not None for msg in data.messages]
    return sum(matches)


@print_calls