Exemple #1
0
    def test_sort_query_is_executed(self, mock_query):
        mock_query.return_value = NoneData()
        self.app.get("/foo?sort_by=value:ascending")
        mock_query.assert_called_with(Query.create(sort_by=["value", "ascending"]))

        self.app.get("/foo?sort_by=value:descending")
        mock_query.assert_called_with(Query.create(sort_by=["value", "descending"]))
Exemple #2
0
    def test_sort_query_is_executed(self, mock_query):
        mock_query.return_value = NoneData()
        self.app.get('/foo?sort_by=value:ascending')
        mock_query.assert_called_with(
            Query.create(sort_by=["value", "ascending"]))

        self.app.get('/foo?sort_by=value:descending')
        mock_query.assert_called_with(
            Query.create(sort_by=["value", "descending"]))
    def test_multi_grouping_on_non_existent_keys(self):
        self.setUpPeopleLocationData()

        result1 = self.repo.multi_group("wibble", "wobble", Query.create())
        result2 = self.repo.multi_group("wibble", "person", Query.create())
        result3 = self.repo.multi_group("person", "wibble", Query.create())

        assert_that(result1, is_([]))
        assert_that(result2, is_([]))
        assert_that(result3, is_([]))
    def test_multi_grouping_on_non_existent_keys(self):
        self.setUpPeopleLocationData()

        result1 = self.repo.multi_group("wibble", "wobble", Query.create())
        result2 = self.repo.multi_group("wibble", "person", Query.create())
        result3 = self.repo.multi_group("person", "wibble", Query.create())

        assert_that(result1, is_([]))
        assert_that(result2, is_([]))
        assert_that(result3, is_([]))
Exemple #5
0
    def test_sorted_group_nonsense(self):
        self.setup_playing_cards()

        self.assertRaises(
            InvalidSortError,
            self.repo.group,
            "suite", Query.create(), sort=["suite", "coolness"])
Exemple #6
0
    def test_grouping_by_multiple_keys(self):
        self.setUpPeopleLocationData()

        results = self.repo.multi_group("person", "place", Query.create())

        assert_that(results, has_item({
            "person": "Jack",
            "_count": 1,
            "_group_count": 1,
            "_subgroup": [
                {"place": "Kettering", "_count": 1}
            ]
        }))
        assert_that(results, has_item({
            "person": "Jill",
            "_count": 1,
            "_group_count": 1,
            "_subgroup": [
                {"place": "Kennington", "_count": 1}
            ]
        }))
        assert_that(results, has_item({
            "person": "John",
            "_count": 3,
            "_group_count": 2,
            "_subgroup": [
                {"place": "Kennington", "_count": 1},
                {"place": "Kettering", "_count": 2},
            ]
        }))
Exemple #7
0
def query(bucket_name):
    if request.method == 'OPTIONS':
        # OPTIONS requests are made by XHR as part of the CORS spec
        # if the client uses custom headers
        response = app.make_default_options_response()
        response.headers['Access-Control-Max-Age'] = '86400'
        response.headers['Access-Control-Allow-Headers'] = 'cache-control'
    else:
        result = validate_request_args(request.args,
                                       raw_queries_allowed(bucket_name))

        if not result.is_valid:
            return log_error_and_respond(result.message, 400)

        bucket = Bucket(db, bucket_name)

        try:
            result_data = bucket.query(Query.parse(request.args)).data()
        except InvalidOperationError:
            return log_error_and_respond('invalid collect for that data', 400)

        # Taken from flask.helpers.jsonify to add JSONEncoder
        # NB. this can be removed once fix #471 works it's way into a release
        # https://github.com/mitsuhiko/flask/pull/471
        json_data = json.dumps({"data": result_data}, cls=JsonEncoder,
                               indent=None if request.is_xhr else 2)

        response = app.response_class(json_data, mimetype='application/json')

    # allow requests from any origin
    response.headers['Access-Control-Allow-Origin'] = '*'

    return response
Exemple #8
0
 def test_build_query_with_start_at(self):
     query = Query.create(start_at=d_tz(2013, 3, 18, 18, 10, 05))
     assert_that(
         query.to_mongo_query(),
         is_({"_timestamp": {
             "$gte": d_tz(2013, 03, 18, 18, 10, 05)
         }}))
Exemple #9
0
    def test_sorted_group_not_enough_args(self):
        self.setup_playing_cards()

        self.assertRaises(
            InvalidSortError,
            self.repo.group,
            "suite", Query.create(), sort=["suite"])
Exemple #10
0
    def test_period_group_query_fails_when_weeks_do_not_start_on_monday(self):
        multi_group_results = [
            {
                "is": "Monday",
                "_subgroup": [
                    {"_week_start_at": d(2013, 4, 1), "_count": 1}
                ]
            },
            {
                "is": "also Monday",
                "_subgroup": [
                    {"_week_start_at": d(2013, 4, 8), "_count": 1}
                ]
            },
            {
                "is": "Tuesday",
                "_subgroup": [
                    {"_week_start_at": d(2013, 4, 9), "_count": 1}
                ]
            },
        ]

        self.mock_repository.multi_group.return_value = \
            multi_group_results

        query = Query.create(period=WEEK, group_by='d')
        assert_raises(ValueError, self.bucket.query, query)
Exemple #11
0
    def test_period_group_query_fails_when_weeks_do_not_start_on_monday(self):
        multi_group_results = [
            {
                "is": "Monday",
                "_subgroup": [
                    {"_week_start_at": d(2013, 4, 1), "_count": 1}
                ]
            },
            {
                "is": "also Monday",
                "_subgroup": [
                    {"_week_start_at": d(2013, 4, 8), "_count": 1}
                ]
            },
            {
                "is": "Tuesday",
                "_subgroup": [
                    {"_week_start_at": d(2013, 4, 9), "_count": 1}
                ]
            },
        ]

        self.mock_repository.multi_group.return_value = \
            multi_group_results

        try:
            self.bucket.query(Query.create(period='week', group_by='d')).data()
            assert_that(False)
        except ValueError as e:
            assert_that(str(e), is_(
                "Weeks MUST start on Monday but got date: 2013-04-09 00:00:00"
            ))
Exemple #12
0
    def test_query_with_start_at_and__end_at(self):
        query = Query.create(end_at=d(2013, 3, 1, 12, 0, 0),
                             start_at=d(2013, 2, 1, 12, 0, 0))
        self.bucket.query(query)

        self.mock_repository.find.assert_called_with(query, sort=None,
                                                     limit=None)
    def test_sorted_group_nonsense(self):
        self.setup_playing_cards()

        self.assertRaises(
            InvalidSortError,
            self.repo.group,
            "suite", Query.create(), sort=["suite", "coolness"])
    def test_sorted_query_nonsense(self):
        self.setup_numeric_values()

        self.assertRaises(
            InvalidSortError,
            self.repo.find,
            Query.create(), sort=["value", "coolness"])
    def test_sorted_query_not_enough_args(self):
        self.setup_numeric_values()

        self.assertRaises(
            InvalidSortError,
            self.repo.find,
            Query.create(), sort=["value"])
    def test_multi_group_with_collect(self):
        self.setUpPeopleLocationData()

        results = self.repo.multi_group(
            "place",
            "_week_start_at",
            Query.create(),
            collect=[("person", "set")]
        )

        assert_that(results, has_item(has_entries({
            "place": "Kettering",
            "person:set": ["Jack", "John"]
        })))

        subgroup_matcher = has_item(
            has_entries({
                "person:set": ["Jack"],
                "_count": 1
            }))

        assert_that(
            results,
            has_item(
                has_entries({
                    "_subgroup": subgroup_matcher
                })
            ))
    def test_sorted_query_nonsense(self):
        self.setup_numeric_values()

        self.assertRaises(InvalidSortError,
                          self.repo.find,
                          Query.create(),
                          sort=["value", "coolness"])
    def test_sorted_query_not_enough_args(self):
        self.setup_numeric_values()

        self.assertRaises(InvalidSortError,
                          self.repo.find,
                          Query.create(),
                          sort=["value"])
    def test_sorted_group_not_enough_args(self):
        self.setup_playing_cards()

        self.assertRaises(
            InvalidSortError,
            self.repo.group,
            "suite", Query.create(), sort=["suite"])
Exemple #20
0
    def test_sorted_week_and_group_query_with_limit(self):
        self.mock_repository.multi_group.return_value = [
            {
                "some_group": "val1",
                "_count": 6,
                "_group_count": 2,
                "_subgroup": [
                    {
                        "_week_start_at": d(2013, 1, 7, 0, 0, 0),
                        "_count": 1
                    },
                    {
                        "_week_start_at": d(2013, 1, 14, 0, 0, 0),
                        "_count": 5
                    }
                ]
            }
        ]

        query = Query.create(period="week", group_by="some_group",
                             sort_by=["_count", "descending"], limit=1,
                             collect=[])
        self.bucket.query(query)

        self.mock_repository.multi_group.assert_called_with(
            "some_group",
            "_week_start_at",
            query,
            sort=["_count", "descending"],
            limit=1,
            collect=[])
Exemple #21
0
    def test_query_with_sort(self):
        query = Query.create(sort_by=["keyname", "descending"])
        self.bucket.query(query)

        self.mock_repository.find.assert_called_with(
            query, sort=["keyname", "descending"], limit=None
        )
    def test_count_of_outer_elements_should_be_added(self):
        self.setUpPeopleLocationData()

        results = self.repo.multi_group("_week_start_at", "person",
                                        Query.create())

        assert_that(results, has_item(has_entry("_count", 1)))
Exemple #23
0
    def test_group_by_query_with_collect(self):
        query = Query.create(group_by="name", sort_by=None, limit=None,
                             collect=["key"])
        self.bucket.query(query)

        self.mock_repository.group.assert_called_once_with(
            "name", query, None, None, ["key"])
Exemple #24
0
    def test_sorted_group_by_query_with_limit(self):
        query = Query.create(group_by="name",
                             sort_by=["name", "ascending"], limit=100)
        self.bucket.query(query)

        self.mock_repository.group.assert_called_once_with(
            "name", query, ["name", "ascending"], 100, [])
Exemple #25
0
 def test_group_by_with_period_is_executed(self, mock_query):
     mock_query.return_value = NoneData()
     self.app.get(
         '/foo?period=week&group_by=stuff'
     )
     mock_query.assert_called_with(
         Query.create(period="week", group_by="stuff"))
Exemple #26
0
def query(bucket_name):
    if request.method == 'OPTIONS':
        # OPTIONS requests are made by XHR as part of the CORS spec
        # if the client uses custom headers
        response = app.make_default_options_response()
        response.headers['Access-Control-Max-Age'] = '86400'
        response.headers['Access-Control-Allow-Headers'] = 'cache-control'
    else:
        result = validate_request_args(request.args,
                                       raw_queries_allowed(bucket_name))

        if not result.is_valid:
            return log_error_and_respond(result.message, 400)

        bucket = Bucket(db, bucket_name)

        try:
            result_data = bucket.query(Query.parse(request.args)).data()
        except InvalidOperationError:
            return log_error_and_respond('invalid collect for that data', 400)

        # Taken from flask.helpers.jsonify to add JSONEncoder
        # NB. this can be removed once fix #471 works it's way into a release
        # https://github.com/mitsuhiko/flask/pull/471
        json_data = json.dumps({"data": result_data},
                               cls=JsonEncoder,
                               indent=None if request.is_xhr else 2)

        response = app.response_class(json_data, mimetype='application/json')

    # allow requests from any origin
    response.headers['Access-Control-Allow-Origin'] = '*'

    return response
    def test_grouping_by_multiple_keys(self):
        self.setUpPeopleLocationData()

        results = self.repo.multi_group("person", "place", Query.create())

        assert_that(results, has_item({
            "person": "Jack",
            "_count": 1,
            "_group_count": 1,
            "_subgroup": [
                {"place": "Kettering", "_count": 1}
            ]
        }))
        assert_that(results, has_item({
            "person": "Jill",
            "_count": 1,
            "_group_count": 1,
            "_subgroup": [
                {"place": "Kennington", "_count": 1}
            ]
        }))
        assert_that(results, has_item({
            "person": "John",
            "_count": 3,
            "_group_count": 2,
            "_subgroup": [
                {"place": "Kennington", "_count": 1},
                {"place": "Kettering", "_count": 2},
            ]
        }))
Exemple #28
0
    def test_month_and_group_query_with_start_and_end_at(self):
        self.mock_repository.multi_group.return_value = [
            {
                "some_group": "val1",
                "_count": 6,
                "_group_count": 2,
                "_subgroup": [
                    {
                        "_month_start_at": d(2013, 1, 1, 0, 0, 0),
                        "_count": 1
                    },
                    {
                        "_month_start_at": d(2013, 2, 1, 0, 0, 0),
                        "_count": 5
                    }
                ]
            },
            {
                "some_group": "val2",
                "_count": 8,
                "_group_count": 2,
                "_subgroup": [
                    {
                        "_month_start_at": d(2013, 3, 1, 0, 0, 0),
                        "_count": 2
                    },
                    {
                        "_month_start_at": d(2013, 4, 1, 0, 0, 0),
                        "_count": 6
                    },
                    {
                        "_month_start_at": d(2013, 7, 1, 0, 0, 0),
                        "_count": 6
                    }
                ]
            }
        ]

        query_result = self.bucket.query(Query.create(period=MONTH,
                                                      group_by="some_group",
                                                      start_at=d(2013, 1, 1),
                                                      end_at=d(2013, 4, 2)))
        data = query_result.data()
        assert_that(data,
                    has_item(has_entries({"values": has_length(4)})))
        assert_that(data,
                    has_item(has_entries({"values": has_length(4)})))

        first_group = data[0]["values"]
        assert_that(first_group, has_item(has_entries({
            "_start_at": d_tz(2013, 3, 1)})))
        assert_that(first_group, has_item(has_entries({
            "_start_at": d_tz(2013, 4, 1)})))

        first_group = data[1]["values"]
        assert_that(first_group, has_item(has_entries({
            "_start_at": d_tz(2013, 1, 1)})))
        assert_that(first_group, has_item(has_entries({
            "_start_at": d_tz(2013, 2, 1)})))
Exemple #29
0
    def test_no_end_at_means_now(self):
        query = Query.create(
            period=Day(),
            duration=3,
        )

        assert_that(query.end_at, is_(
            datetime(2014, 1, 9, 0, 0, 0, tzinfo=pytz.UTC)))
    def test_query_with_limit(self):
        self.mongo_collection.save({"value": 6})
        self.mongo_collection.save({"value": 2})
        self.mongo_collection.save({"value": 9})

        result = self.repo.find(Query.create(), limit=2)

        assert_that(result.count(with_limit_and_skip=True), is_(2))
    def test_should_use_second_key_for_inner_group_name(self):
        self.setUpPeopleLocationData()

        results = self.repo.multi_group("_week_start_at", "person", Query.create())

        assert_that(results, has_item(has_entry(
            "_subgroup", has_item(has_entry("person", "Jill"))
        )))
    def test_sorted_group_by_nonexistent_key(self):
        self.setup_playing_cards()

        self.assertRaises(
            InvalidSortError,
            self.repo.group,
            "suite", Query.create(), sort=["bleh", "ascending"]
        )
    def test_count_of_outer_elements_should_be_added(self):
        self.setUpPeopleLocationData()

        results = self.repo.multi_group("_week_start_at", "person", Query.create())

        assert_that(results, has_item(has_entry(
            "_count", 1
        )))
    def test_sorted_group_by_nonexistent_key(self):
        self.setup_playing_cards()

        self.assertRaises(InvalidSortError,
                          self.repo.group,
                          "suite",
                          Query.create(),
                          sort=["bleh", "ascending"])
    def test_query_with_limit(self):
        self.mongo_collection.save({"value": 6})
        self.mongo_collection.save({"value": 2})
        self.mongo_collection.save({"value": 9})

        result = self.repo.find(Query.create(), limit=2)

        assert_that(result.count(with_limit_and_skip=True), is_(2))
Exemple #36
0
    def test_should_use_second_key_for_inner_group_name(self):
        self.setUpPeopleLocationData()

        results = self.repo.multi_group("_week_start_at", "person", Query.create())

        assert_that(results, has_item(has_entry(
            "_subgroup", has_item(has_entry("person", "Jill"))
        )))
Exemple #37
0
    def test_period_group_query_adds_missing_periods_in_correct_order(self):
        self.mock_repository.multi_group.return_value = [
            {
                "some_group": "val1",
                "_count": 6,
                "_group_count": 2,
                "_subgroup": [
                    {
                        "_week_start_at": d(2013, 1, 14, 0, 0, 0),
                        "_count": 23
                    },
                    {
                        "_week_start_at": d(2013, 1, 21, 0, 0, 0),
                        "_count": 41
                    }
                ]
            },
            {
                "some_group": "val2",
                "_count": 8,
                "_group_count": 2,
                "_subgroup": [
                    {
                        "_week_start_at": d(2013, 1, 14, 0, 0, 0),
                        "_count": 31
                    },
                    {
                        "_week_start_at": d(2013, 1, 28, 0, 0, 0),
                        "_count": 12
                    }
                ]
            }
        ]

        query_result = self.bucket.query(
            Query.create(period="week", group_by="some_group",
                         start_at=d_tz(2013, 1, 7, 0, 0, 0),
                         end_at=d_tz(2013, 2, 4, 0, 0, 0))).data()

        assert_that(query_result, has_item(has_entries({
            "some_group": "val1",
            "values": contains(
                has_entries({"_start_at": d_tz(2013, 1, 7), "_count": 0}),
                has_entries({"_start_at": d_tz(2013, 1, 14), "_count": 23}),
                has_entries({"_start_at": d_tz(2013, 1, 21), "_count": 41}),
                has_entries({"_start_at": d_tz(2013, 1, 28), "_count": 0}),
            ),
        })))

        assert_that(query_result, has_item(has_entries({
            "some_group": "val2",
            "values": contains(
                has_entries({"_start_at": d_tz(2013, 1, 7), "_count": 0}),
                has_entries({"_start_at": d_tz(2013, 1, 14), "_count": 31}),
                has_entries({"_start_at": d_tz(2013, 1, 21), "_count": 0}),
                has_entries({"_start_at": d_tz(2013, 1, 28), "_count": 12}),
            ),
        })))
Exemple #38
0
    def test_month_query_with_limit(self):
        self.mock_repository.group.return_value = []

        query = Query.create(period='month', limit=1)
        self.bucket.query(query)

        self.mock_repository.group.assert_called_once_with(
            "_month_start_at", query, sort=['_month_start_at', 'ascending'],
            limit=1, collect=[])
    def test_another_grouping_with_collect(self):
        self.setUpPeopleLocationData()

        results = self.repo.group("place", Query.create(), None, None, [("person", "set")])

        assert_that(results, has_item(has_entries({
            "place": "Kettering",
            "person:set": has_items("Jack", "John")
        })))
Exemple #40
0
    def test_another_grouping_with_collect(self):
        self.setUpPeopleLocationData()

        results = self.repo.group("place", Query.create(), None, None, ["person"])

        assert_that(results, has_item(has_entries({
            "place": "Kettering",
            "person": has_items("Jack", "John")
        })))
    def test_sorted_group_by_with_limit(self):
        self.setup_playing_cards()

        result = self.repo.group(
            "suite", Query.create(), sort=["_count", "ascending"], limit=1)

        assert_that(list(result), contains(
            has_entry("suite", "diamonds")
        ))
Exemple #42
0
    def test_find_with_default_sorting(self):
        self.mongo.find.return_value = "a_cursor"

        results = self.repo.find(Query.create(filter_by=[["plays", "guitar"]]))

        self.mongo.find.assert_called_once_with({"plays": "guitar"},
                                                ["_timestamp", "ascending"],
                                                None)
        assert_that(results, is_("a_cursor"))
Exemple #43
0
    def test_find_with_descending_sort(self):
        self.mongo.find.return_value = "a_cursor"

        results = self.repo.find(Query.create(filter_by=[["plays", "guitar"]]),
                                 sort=["name", "descending"])

        self.mongo.find.assert_called_once_with({"plays": "guitar"},
                                                ["name", "descending"], None)
        assert_that(results, is_("a_cursor"))
 def test_period_queries_get_sorted_by__week_start_at(self):
     self.setup__timestamp_data()
     query = Query.create(period="week")
     result = query.execute(self.bucket.repository)
     assert_that(result.data(), contains(
         has_entry('_start_at', d_tz(2012, 12, 31)),
         has_entry('_start_at', d_tz(2013, 1, 28)),
         has_entry('_start_at', d_tz(2013, 2, 25))
     ))
    def test_query_with_limit_and_sort(self):
        self.mongo_collection.save({"value": 6})
        self.mongo_collection.save({"value": 2})
        self.mongo_collection.save({"value": 9})

        result = self.repo.find(Query.create(), sort=["value", "ascending"], limit=1)

        assert_that(result.count(with_limit_and_skip=True), is_(1))
        assert_that(list(result)[0], has_entry('value', 2))
    def test_grouping_with_collect(self):
        self.setUpPeopleLocationData()

        results = self.repo.group("person", Query.create(), None, None, ["place"])

        assert_that(results, has_item(has_entries({
            "person": "John",
            "place": has_items("Kettering", "Kennington")
        })))
Exemple #47
0
 def test_period_queries_get_sorted_by__week_start_at(self):
     self.setup__timestamp_data()
     query = Query.create(period="week")
     result = query.execute(self.bucket.repository)
     assert_that(
         result.data(),
         contains(has_entry('_start_at', d_tz(2012, 12, 31)),
                  has_entry('_start_at', d_tz(2013, 1, 28)),
                  has_entry('_start_at', d_tz(2013, 2, 25))))
    def test_sorted_group_by_with_limit(self):
        self.setup_playing_cards()

        result = self.repo.group("suite",
                                 Query.create(),
                                 sort=["_count", "ascending"],
                                 limit=1)

        assert_that(list(result), contains(has_entry("suite", "diamonds")))
Exemple #49
0
    def test_month_and_group_query_with_start_and_end_at(self):
        self.mock_repository.multi_group.return_value = [
            {
                "some_group": "val1",
                "_count": 6,
                "_group_count": 2,
                "_subgroup": [
                    {
                        "_month_start_at": d(2013, 1, 1, 0, 0, 0),
                        "_count": 1
                    },
                    {
                        "_month_start_at": d(2013, 2, 1, 0, 0, 0),
                        "_count": 5
                    }
                ]
            },
            {
                "some_group": "val2",
                "_count": 8,
                "_group_count": 2,
                "_subgroup": [
                    {
                        "_month_start_at": d(2013, 3, 1, 0, 0, 0),
                        "_count": 2
                    },
                    {
                        "_month_start_at": d(2013, 4, 1, 0, 0, 0),
                        "_count": 6
                    },
                    {
                        "_month_start_at": d(2013, 7, 1, 0, 0, 0),
                        "_count": 6
                    }
                ]
            }
        ]

        query_result = self.bucket.query(Query.create(period="month",
                                                      group_by="some_group",
                                                      start_at=d(2013, 1, 1),
                                                      end_at=d(2013, 4, 2)))
        data = query_result.data()
        assert_that(data, has_item(has_entries({"values": has_length(4)})))
        assert_that(data, has_item(has_entries({"values": has_length(4)})))

        first_group = data[0]["values"]
        assert_that(first_group, has_item(has_entries({
            "_start_at": d_tz(2013, 3, 1)})))
        assert_that(first_group, has_item(has_entries({
            "_start_at": d_tz(2013, 4, 1)})))

        first_group = data[1]["values"]
        assert_that(first_group, has_item(has_entries({
            "_start_at": d_tz(2013, 1, 1)})))
        assert_that(first_group, has_item(has_entries({
            "_start_at": d_tz(2013, 2, 1)})))
Exemple #50
0
    def test_query_with_limit_and_sort(self):
        self.mongo_collection.save({"value": 6})
        self.mongo_collection.save({"value": 2})
        self.mongo_collection.save({"value": 9})

        result = self.repo.find(Query.create(), sort=["value", "ascending"], limit=1)

        assert_that(result.count(with_limit_and_skip=True), is_(1))
        assert_that(list(result)[0], has_entry('value', 2))
    def test_period_query_for_data_with_no__week_start_at(self):
        self.mongo_collection.save({
            "_week_start_at": d(2013, 4, 2, 0, 0, 0),
            "foo": "bar"
        })
        self.mongo_collection.save({"foo": "bar2"})

        result = self.repo.group('_week_start_at', Query.create())

        assert_that(result, has_item(has_entry("_count", 1)))
    def test_sorted_query_with_alphanumeric(self):
        self.mongo_collection.save({'val': 'a'})
        self.mongo_collection.save({'val': 'b'})
        self.mongo_collection.save({'val': 'c'})

        result = self.repo.find(Query.create(), sort=['val', 'descending'])
        assert_that(
            list(result),
            contains(has_entry('val', 'c'), has_entry('val', 'b'),
                     has_entry('val', 'a')))