Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
nomad-lab
nomad-FAIR
Commits
b876361a
Commit
b876361a
authored
Mar 26, 2021
by
Markus Scheidgen
Browse files
Added page based pagination to entries query.
parent
d1a9e81b
Pipeline
#96981
passed with stages
in 23 minutes and 51 seconds
Changes
3
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
nomad/app/v1/models.py
View file @
b876361a
...
...
@@ -463,7 +463,7 @@ class Pagination(BaseModel):
the value is omitted when making a request, the response will just give the
first page of results.
The response
should
also contain an attribute `next_after`, which similarly
The response
will
also contain an attribute `next_after`, which similarly
defines the starting position of the next page. Thus, one would normally start
with a request where `after` is omitted, then use the `next_after` value from
the responses as the `after` in the next request, to get the next page of
...
...
@@ -475,16 +475,9 @@ class Pagination(BaseModel):
It might contain an id as *tie breaker*, if `order_by` is not a field with
unique values.
The *tie breaker* will be `:` separated, e.g. `<value>:<id>`.
For simple, index-based pagination,
à
fter` will be the zero-based index of the
For simple, index-based pagination,
a
fter` will be the zero-based index of the
first result in the response.
'''
))
page
:
Optional
[
int
]
=
Field
(
None
,
description
=
strip
(
'''
For simple, index-based pagination, this should contain the number of the
requested page (1-based). When provided in a request, this attribute can be
used instead of `after` to jump to a particular results page. However, if you
specify both `after` *and* `page` in your request, they need to be consistent.
'''
))
@
validator
(
'size'
)
def
validate_size
(
cls
,
size
):
# pylint: disable=no-self-argument
...
...
@@ -507,16 +500,16 @@ class Pagination(BaseModel):
'''
raise
NotImplementedError
(
'Validation of `after` not implemented!'
)
@
validator
(
'page'
)
def
validate_page
(
cls
,
page
,
values
):
# pylint: disable=no-self-argument
if
page
is
not
None
:
# This attribute is not expected unless we are using an IndexBasedPagination
# or in the PaginationResponse of an index-based paginated request.
raise
AssertionError
(
'Value for `page` not permitted'
)
return
page
class
IndexBasedPagination
(
Pagination
):
page
:
Optional
[
int
]
=
Field
(
None
,
description
=
strip
(
'''
For simple, index-based pagination, this should contain the number of the
requested page (1-based). When provided in a request, this attribute can be
used instead of `after` to jump to a particular results page. However, if you
specify both `after` *and* `page` in your request, they need to be consistent.
'''
))
@
validator
(
'after'
)
def
validate_after
(
cls
,
after
,
values
):
# pylint: disable=no-self-argument
# This is validated in the root validator instead
...
...
@@ -581,6 +574,10 @@ class PaginationResponse(Pagination):
None
,
description
=
strip
(
'''
The url to get the next page.
'''
))
page
:
Optional
[
int
]
=
Field
(
None
,
description
=
strip
(
'''
The returned page number. The availability depends on the API method.
'''
))
@
validator
(
'order_by'
)
def
validate_order_by
(
cls
,
order_by
):
# pylint: disable=no-self-argument
...
...
@@ -603,7 +600,7 @@ class PaginationResponse(Pagination):
return
next_after
class
EntryPagination
(
Pagination
):
class
Entry
Based
Pagination
(
Pagination
):
order_by
:
Optional
[
str
]
=
Field
(
calc_id
,
# type: ignore
description
=
strip
(
'''
...
...
@@ -629,11 +626,32 @@ class EntryPagination(Pagination):
return
after
class
EntryPagination
(
EntryBasedPagination
):
page
:
Optional
[
int
]
=
Field
(
None
,
description
=
strip
(
'''
For simple, index-based pagination, this should contain the number of the
requested page (1-based). When provided in a request, this attribute can be
used instead of `after` to jump to a particular results page.
However, you can only retreive up to the 10.000th entry with a page number.
Only one, `after` *or* `page` must be provided.
'''
))
@
validator
(
'page'
)
def
validate_page
(
cls
,
page
,
values
):
# pylint: disable=no-self-argument
if
page
is
not
None
:
assert
values
[
'after'
]
is
None
,
'There can only be one, a page number or an after value.'
assert
page
>
0
,
'Page has to be larger than 1.'
assert
page
*
values
.
get
(
'size'
,
10
)
<
10000
,
'Pagination by page is limited to 10.000 entries.'
return
page
entry_pagination_parameters
=
parameter_dependency_from_model
(
'entry_pagination_parameters'
,
EntryPagination
)
class
AggregationPagination
(
EntryPagination
):
class
AggregationPagination
(
Entry
Based
Pagination
):
order_by
:
Optional
[
str
]
=
Field
(
None
,
# type: ignore
description
=
strip
(
'''
...
...
nomad/search.py
View file @
b876361a
...
...
@@ -1098,6 +1098,9 @@ def search(
if
pagination
.
after
:
search
=
search
.
extra
(
search_after
=
pagination
.
after
.
rsplit
(
':'
,
1
))
if
pagination
.
page
:
search
=
search
[(
pagination
.
page
-
1
)
*
pagination
.
size
:
pagination
.
page
*
pagination
.
size
]
# required
if
required
:
if
required
.
include
is
not
None
and
pagination
.
order_by
not
in
required
.
include
:
...
...
tests/app/v1/routers/test_entries.py
View file @
b876361a
...
...
@@ -870,7 +870,11 @@ def test_entries_owner(
pytest
.
param
({
'order'
:
'misspelled'
},
None
,
422
,
id
=
'bad-order'
),
pytest
.
param
({
'order_by'
:
'misspelled'
},
None
,
422
,
id
=
'bad-order-by'
),
pytest
.
param
({
'order_by'
:
'atoms'
,
'after'
:
'H:id_01'
},
None
,
422
,
id
=
'order-by-list'
),
pytest
.
param
({
'order_by'
:
'n_atoms'
,
'after'
:
'some'
},
None
,
400
,
id
=
'order-by-bad-after'
)
pytest
.
param
({
'order_by'
:
'n_atoms'
,
'after'
:
'some'
},
None
,
400
,
id
=
'order-by-bad-after'
),
pytest
.
param
({
'page'
:
1
,
'size'
:
1
},
{
'total'
:
23
,
'size'
:
1
,
'next_after'
:
'id_02'
,
'page'
:
1
},
200
,
id
=
'page-1'
),
pytest
.
param
({
'page'
:
2
,
'size'
:
1
},
{
'total'
:
23
,
'size'
:
1
,
'next_after'
:
'id_03'
,
'page'
:
2
},
200
,
id
=
'page-2'
),
pytest
.
param
({
'page'
:
1000
,
'size'
:
10
},
None
,
422
,
id
=
'page-too-large'
),
pytest
.
param
({
'page'
:
9999
,
'size'
:
1
},
None
,
200
,
id
=
'page-just-small-enough'
),
])
@
pytest
.
mark
.
parametrize
(
'http_method'
,
[
'post'
,
'get'
])
@
pytest
.
mark
.
parametrize
(
'test_method'
,
[
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment