1
0
mirror of https://github.com/ilri/dspace-statistics-api.git synced 2025-12-19 19:52:18 +01:00

Compare commits

..

1 Commits
v1.2.0 ... v5_x

Author SHA1 Message Date
963961354b README.md: Use travis-ci.com domain for badge 2020-12-08 09:10:41 +02:00
11 changed files with 156 additions and 192 deletions

View File

@@ -1,6 +1,7 @@
dist: bionic
language: python
python:
- "3.5"
- "3.6"
- "3.7"
- "3.8"

View File

@@ -4,20 +4,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.2.0] - 2020-03-02
## Changed
- Remove Python 3.5 from TravisCI because black requires Python >= 3.6
- Adapt API for DSpace 6+ UUIDs
- This requires droping the statistics database and re-indexing
- Run pipenv update, bringing requests 2.23.0 and pytest 5.3.5
## [1.1.1] - 2019-11-27
### Added
- Configuration for automatic sorting of imports with isort
- Configuration for automatic code formatting with black
### Updated
- Run pipenv update, bringing psycopg2 2.8.4, requests 2.22.0, pytest 5.3.1,
- Run pipenv update, bringing psycogpg 2.8.3, requests 2.22.0, pytest 5.3.1,
and gunicorn 20.0.4
### Changed

View File

@@ -14,8 +14,7 @@ ipython = "*"
"flake8" = "*"
pytest = "*"
isort = "*"
black = "==19.10b0"
pytest-clarity = "==0.3.0a0"
black = "*"
[requires]
python_version = "3.8"

208
Pipfile.lock generated
View File

@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "be968d3927117f9ac14b9a6f60d6147b2d57ce55f694f34ed6e53abcd2197823"
"sha256": "5e3f3e80bd92780ab66a80a83156001e50362a0d6195b1a304a15dc0c645c562"
},
"pipfile-spec": 6,
"requires": {
@@ -18,10 +18,10 @@
"default": {
"certifi": {
"hashes": [
"sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3",
"sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"
"sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50",
"sha256:fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef"
],
"version": "==2019.11.28"
"version": "==2019.9.11"
},
"chardet": {
"hashes": [
@@ -60,10 +60,10 @@
},
"idna": {
"hashes": [
"sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb",
"sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"
"sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",
"sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"
],
"version": "==2.9"
"version": "==2.8"
},
"psycopg2-binary": {
"hashes": [
@@ -105,18 +105,18 @@
},
"requests": {
"hashes": [
"sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee",
"sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"
"sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4",
"sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"
],
"index": "pypi",
"version": "==2.23.0"
"version": "==2.22.0"
},
"urllib3": {
"hashes": [
"sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc",
"sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc"
"sha256:a8a318824cc77d1fd4b2bec2ded92646630d7fe8619497b142c84a9e6f5a7293",
"sha256:f3c5fd51747d450d4dcf6f923c81f78f811aab8205fda64b0aba34a4e48b0745"
],
"version": "==1.25.8"
"version": "==1.25.7"
}
},
"develop": {
@@ -158,10 +158,10 @@
},
"decorator": {
"hashes": [
"sha256:41fa54c2a0cc4ba648be4fd43cff00aedf5b9465c9bf18d64325bc225f08f760",
"sha256:e3a62f0520172440ca0dcc823749319382e377f37f140a0b99ef45fecb84bfe7"
"sha256:54c38050039232e1db4ad7375cfce6748d7b41c29e95a081c8a6d2c30364a2ce",
"sha256:5d19b92a3c8f7f101c8dd86afd86b0f061a8ce4540ab8cd401fa2542756bce6d"
],
"version": "==4.4.2"
"version": "==4.4.1"
},
"entrypoints": {
"hashes": [
@@ -180,11 +180,11 @@
},
"ipython": {
"hashes": [
"sha256:ca478e52ae1f88da0102360e57e528b92f3ae4316aabac80a2cd7f7ab2efb48a",
"sha256:eb8d075de37f678424527b5ef6ea23f7b80240ca031c2dd6de5879d687a65333"
"sha256:dfd303b270b7b5232b3d08bd30ec6fd685d8a58cabd54055e3d69d8f029f7280",
"sha256:ed7ebe1cba899c1c3ccad6f7f1c2d2369464cc77dba8eebc65e2043e19cda995"
],
"index": "pypi",
"version": "==7.13.0"
"version": "==7.9.0"
},
"ipython-genutils": {
"hashes": [
@@ -203,10 +203,10 @@
},
"jedi": {
"hashes": [
"sha256:b4f4052551025c6b0b0b193b29a6ff7bdb74c52450631206c262aef9f7159ad2",
"sha256:d5c871cb9360b414f981e7072c52c33258d598305280fef91c6cae34739d65d5"
"sha256:786b6c3d80e2f06fd77162a07fed81b8baa22dde5d62896a790a331d6ac21a27",
"sha256:ba859c74fa3c966a22f2aeebe1b74ee27e2a462f56d3f5f7ca4a59af61bfe42e"
],
"version": "==0.16.0"
"version": "==0.15.1"
},
"mccabe": {
"hashes": [
@@ -217,39 +217,38 @@
},
"more-itertools": {
"hashes": [
"sha256:5dd8bcf33e5f9513ffa06d5ad33d78f31e1931ac9a18f33d37e77a180d393a7c",
"sha256:b1ddb932186d8a6ac451e1d95844b382f55e12686d51ca0c68b6f61f2ab7a507"
"sha256:409cd48d4db7052af495b09dec721011634af3753ae1ef92d2b32f73a745f832",
"sha256:92b8c4b06dac4f0611c0729b2f2ede52b2e1bac1ab48f089c7ddc12e26bb60c4"
],
"version": "==8.2.0"
"version": "==7.2.0"
},
"packaging": {
"hashes": [
"sha256:170748228214b70b672c581a3dd610ee51f733018650740e98c7df862a583f73",
"sha256:e665345f9eef0c621aa0bf2f8d78cf6d21904eef16a93f020240b704a57f1334"
"sha256:28b924174df7a2fa32c1953825ff29c61e2f5e082343165438812f00d3a7fc47",
"sha256:d9551545c6d761f3def1677baf08ab2a3ca17c56879e70fecba2fc4dde4ed108"
],
"version": "==20.1"
"version": "==19.2"
},
"parso": {
"hashes": [
"sha256:0c5659e0c6eba20636f99a04f469798dca8da279645ce5c387315b2c23912157",
"sha256:8515fc12cfca6ee3aa59138741fc5624d62340c97e401c74875769948d4f2995"
"sha256:63854233e1fadb5da97f2744b6b24346d2750b85965e7e399bec1620232797dc",
"sha256:666b0ee4a7a1220f65d367617f2cd3ffddff3e205f3f16a0284df30e774c2a9c"
],
"version": "==0.6.2"
"version": "==0.5.1"
},
"pathspec": {
"hashes": [
"sha256:163b0632d4e31cef212976cf57b43d9fd6b0bac6e67c26015d611a647d5e7424",
"sha256:562aa70af2e0d434367d9790ad37aed893de47f1693e4201fd1d3dca15d19b96"
"sha256:e285ccc8b0785beadd4c18e5708b12bb8fcf529a1e61215b3feff1d1e559ea5c"
],
"version": "==0.7.0"
"version": "==0.6.0"
},
"pexpect": {
"hashes": [
"sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937",
"sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"
"sha256:2094eefdfcf37a1fdbfb9aa090862c1a4878e5c7e0e7e7088bdb511c558e5cd1",
"sha256:9e2c1fd0e6ee3a49b28f95d4b33bc389c89b20af6a1255906e90ff1262ce62eb"
],
"markers": "sys_platform != 'win32'",
"version": "==4.8.0"
"version": "==4.7.0"
},
"pickleshare": {
"hashes": [
@@ -267,10 +266,11 @@
},
"prompt-toolkit": {
"hashes": [
"sha256:a402e9bf468b63314e37460b68ba68243d55b2f8c4d0192f85a019af3945050e",
"sha256:c93e53af97f630f12f5f62a3274e79527936ed466f038953dfa379d4941f651a"
"sha256:46642344ce457641f28fc9d1c9ca939b63dadf8df128b86f1b9860e59c73a5e4",
"sha256:e7f8af9e3d70f514373bf41aa51bc33af12a6db3f71461ea47fea985defb2c31",
"sha256:f15af68f66e664eaa559d4ac8a928111eebd5feda0c11738b5998045224829db"
],
"version": "==3.0.3"
"version": "==2.0.10"
},
"ptyprocess": {
"hashes": [
@@ -281,10 +281,10 @@
},
"py": {
"hashes": [
"sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa",
"sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0"
"sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa",
"sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53"
],
"version": "==1.8.1"
"version": "==1.8.0"
},
"pycodestyle": {
"hashes": [
@@ -302,71 +302,50 @@
},
"pygments": {
"hashes": [
"sha256:2a3fe295e54a20164a9df49c75fa58526d3be48e14aceba6d6b1e8ac0bfd6f1b",
"sha256:98c8aa5a9f778fcd1026a17361ddaf7330d1b7c62ae97c3bb0ae73e0b9b6b0fe"
"sha256:83ec6c6133ca6b529b7ff5aa826328fd14b5bb02a58c37f4f06384e96a0f94ab",
"sha256:b7949de3d396836085fea596998b135a22610bbcc4f2abfe9e448e44cbc58388"
],
"version": "==2.5.2"
"version": "==2.5.1"
},
"pyparsing": {
"hashes": [
"sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f",
"sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec"
"sha256:20f995ecd72f2a1f4bf6b072b63b22e2eb457836601e76d6e5dfcd75436acc1f",
"sha256:4ca62001be367f01bd3e92ecbb79070272a9d4964dce6a48a82ff0b8bc7e683a"
],
"version": "==2.4.6"
"version": "==2.4.5"
},
"pytest": {
"hashes": [
"sha256:0d5fe9189a148acc3c3eb2ac8e1ac0742cb7618c084f3d228baaec0c254b318d",
"sha256:ff615c761e25eb25df19edddc0b970302d2a9091fbce0e7213298d85fb61fef6"
"sha256:63344a2e3bce2e4d522fd62b4fdebb647c019f1f9e4ca075debbd13219db4418",
"sha256:f67403f33b2b1d25a6756184077394167fe5e2f9d8bdaab30707d19ccec35427"
],
"index": "pypi",
"version": "==5.3.5"
},
"pytest-clarity": {
"hashes": [
"sha256:5cc99e3d9b7969dfe17e5f6072d45a917c59d363b679686d3c958a1ded2e4dcf"
],
"index": "pypi",
"version": "==0.3.0a0"
"version": "==5.3.1"
},
"regex": {
"hashes": [
"sha256:01b2d70cbaed11f72e57c1cfbaca71b02e3b98f739ce33f5f26f71859ad90431",
"sha256:046e83a8b160aff37e7034139a336b660b01dbfe58706f9d73f5cdc6b3460242",
"sha256:113309e819634f499d0006f6200700c8209a2a8bf6bd1bdc863a4d9d6776a5d1",
"sha256:200539b5124bc4721247a823a47d116a7a23e62cc6695744e3eb5454a8888e6d",
"sha256:25f4ce26b68425b80a233ce7b6218743c71cf7297dbe02feab1d711a2bf90045",
"sha256:269f0c5ff23639316b29f31df199f401e4cb87529eafff0c76828071635d417b",
"sha256:5de40649d4f88a15c9489ed37f88f053c15400257eeb18425ac7ed0a4e119400",
"sha256:7f78f963e62a61e294adb6ff5db901b629ef78cb2a1cfce3cf4eeba80c1c67aa",
"sha256:82469a0c1330a4beb3d42568f82dffa32226ced006e0b063719468dcd40ffdf0",
"sha256:8c2b7fa4d72781577ac45ab658da44c7518e6d96e2a50d04ecb0fd8f28b21d69",
"sha256:974535648f31c2b712a6b2595969f8ab370834080e00ab24e5dbb9d19b8bfb74",
"sha256:99272d6b6a68c7ae4391908fc15f6b8c9a6c345a46b632d7fdb7ef6c883a2bbb",
"sha256:9b64a4cc825ec4df262050c17e18f60252cdd94742b4ba1286bcfe481f1c0f26",
"sha256:9e9624440d754733eddbcd4614378c18713d2d9d0dc647cf9c72f64e39671be5",
"sha256:9ff16d994309b26a1cdf666a6309c1ef51ad4f72f99d3392bcd7b7139577a1f2",
"sha256:b33ebcd0222c1d77e61dbcd04a9fd139359bded86803063d3d2d197b796c63ce",
"sha256:bba52d72e16a554d1894a0cc74041da50eea99a8483e591a9edf1025a66843ab",
"sha256:bed7986547ce54d230fd8721aba6fd19459cdc6d315497b98686d0416efaff4e",
"sha256:c7f58a0e0e13fb44623b65b01052dae8e820ed9b8b654bb6296bc9c41f571b70",
"sha256:d58a4fa7910102500722defbde6e2816b0372a4fcc85c7e239323767c74f5cbc",
"sha256:f1ac2dc65105a53c1c2d72b1d3e98c2464a133b4067a51a3d2477b28449709a0"
"sha256:15454b37c5a278f46f7aa2d9339bda450c300617ca2fca6558d05d870245edc7",
"sha256:1ad40708c255943a227e778b022c6497c129ad614bb7a2a2f916e12e8a359ee7",
"sha256:5e00f65cc507d13ab4dfa92c1232d004fa202c1d43a32a13940ab8a5afe2fb96",
"sha256:604dc563a02a74d70ae1f55208ddc9bfb6d9f470f6d1a5054c4bd5ae58744ab1",
"sha256:720e34a539a76a1fedcebe4397290604cc2bdf6f81eca44adb9fb2ea071c0c69",
"sha256:7caf47e4a9ac6ef08cabd3442cc4ca3386db141fb3c8b2a7e202d0470028e910",
"sha256:7faf534c1841c09d8fefa60ccde7b9903c9b528853ecf41628689793290ca143",
"sha256:b4e0406d822aa4993ac45072a584d57aa4931cf8288b5455bbf30c1d59dbad59",
"sha256:c31eaf28c6fe75ea329add0022efeed249e37861c19681960f99bbc7db981fb2",
"sha256:c7393597191fc2043c744db021643549061e12abe0b3ff5c429d806de7b93b66",
"sha256:d2b302f8cdd82c8f48e9de749d1d17f85ce9a0f082880b9a4859f66b07037dc6",
"sha256:e3d8dd0ec0ea280cf89026b0898971f5750a7bd92cb62c51af5a52abd020054a",
"sha256:ec032cbfed59bd5a4b8eab943c310acfaaa81394e14f44454ad5c9eba4f24a74"
],
"version": "==2020.2.20"
"version": "==2019.11.1"
},
"six": {
"hashes": [
"sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a",
"sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"
"sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd",
"sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66"
],
"version": "==1.14.0"
},
"termcolor": {
"hashes": [
"sha256:1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b"
],
"version": "==1.1.0"
"version": "==1.13.0"
},
"toml": {
"hashes": [
@@ -384,36 +363,35 @@
},
"typed-ast": {
"hashes": [
"sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355",
"sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919",
"sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa",
"sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652",
"sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75",
"sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01",
"sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d",
"sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1",
"sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907",
"sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c",
"sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3",
"sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b",
"sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614",
"sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb",
"sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b",
"sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41",
"sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6",
"sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34",
"sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe",
"sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4",
"sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"
"sha256:1170afa46a3799e18b4c977777ce137bb53c7485379d9706af8a59f2ea1aa161",
"sha256:18511a0b3e7922276346bcb47e2ef9f38fb90fd31cb9223eed42c85d1312344e",
"sha256:262c247a82d005e43b5b7f69aff746370538e176131c32dda9cb0f324d27141e",
"sha256:2b907eb046d049bcd9892e3076c7a6456c93a25bebfe554e931620c90e6a25b0",
"sha256:354c16e5babd09f5cb0ee000d54cfa38401d8b8891eefa878ac772f827181a3c",
"sha256:48e5b1e71f25cfdef98b013263a88d7145879fbb2d5185f2a0c79fa7ebbeae47",
"sha256:4e0b70c6fc4d010f8107726af5fd37921b666f5b31d9331f0bd24ad9a088e631",
"sha256:630968c5cdee51a11c05a30453f8cd65e0cc1d2ad0d9192819df9978984529f4",
"sha256:66480f95b8167c9c5c5c87f32cf437d585937970f3fc24386f313a4c97b44e34",
"sha256:71211d26ffd12d63a83e079ff258ac9d56a1376a25bc80b1cdcdf601b855b90b",
"sha256:7954560051331d003b4e2b3eb822d9dd2e376fa4f6d98fee32f452f52dd6ebb2",
"sha256:838997f4310012cf2e1ad3803bce2f3402e9ffb71ded61b5ee22617b3a7f6b6e",
"sha256:95bd11af7eafc16e829af2d3df510cecfd4387f6453355188342c3e79a2ec87a",
"sha256:bc6c7d3fa1325a0c6613512a093bc2a2a15aeec350451cbdf9e1d4bffe3e3233",
"sha256:cc34a6f5b426748a507dd5d1de4c1978f2eb5626d51326e43280941206c209e1",
"sha256:d755f03c1e4a51e9b24d899561fec4ccaf51f210d52abdf8c07ee2849b212a36",
"sha256:d7c45933b1bdfaf9f36c579671fec15d25b06c8398f113dab64c18ed1adda01d",
"sha256:d896919306dd0aa22d0132f62a1b78d11aaf4c9fc5b3410d3c666b818191630a",
"sha256:fdc1c9bbf79510b76408840e009ed65958feba92a88833cdceecff93ae8fff66",
"sha256:ffde2fbfad571af120fcbfbbc61c72469e72f550d676c3342492a9dfdefb8f12"
],
"version": "==1.4.1"
"version": "==1.4.0"
},
"wcwidth": {
"hashes": [
"sha256:8fd29383f539be45b20bd4df0dc29c20ba48654a41e661925e612311e9f3c603",
"sha256:f28b3e8a6483e5d49e7f8949ac1a78314e740333ae305b4ba5defd3e74fb37a8"
"sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e",
"sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c"
],
"version": "==0.1.8"
"version": "==0.1.7"
}
}
}

View File

@@ -1,4 +1,4 @@
# DSpace Statistics API [![Build Status](https://travis-ci.org/ilri/dspace-statistics-api.svg?branch=master)](https://travis-ci.org/ilri/dspace-statistics-api) [![builds.sr.ht status](https://builds.sr.ht/~alanorth/dspace-statistics-api.svg)](https://builds.sr.ht/~alanorth/dspace-statistics-api?)
# DSpace Statistics API [![Build Status](https://travis-ci.com/ilri/dspace-statistics-api.svg?branch=master)](https://travis-ci.com/ilri/dspace-statistics-api) [![builds.sr.ht status](https://builds.sr.ht/~alanorth/dspace-statistics-api.svg)](https://builds.sr.ht/~alanorth/dspace-statistics-api?)
DSpace stores item view and download events in a Solr "statistics" core. This information is available for use in the various DSpace user interfaces, but is not exposed externally via any APIs. The DSpace 4/5 [REST API](https://wiki.duraspace.org/display/DSDOC5x/REST+API), for example, only exposes information about communities, collections, item metadata, and bitstreams.
This project contains an indexer and a [Falcon-based](https://falcon.readthedocs.io/) web application to make the statistics available via a simple REST API. You can read more about the Solr queries used to gather the item view and download statistics on the [DSpace wiki](https://wiki.duraspace.org/display/DSPACE/Solr).

View File

@@ -27,10 +27,11 @@ class AllItemsResource:
cursor.execute("SELECT COUNT(id) FROM items")
pages = round(cursor.fetchone()[0] / limit)
# get statistics and use limit and offset to page through results
# get statistics, ordered by id, and use limit and offset to page through results
cursor.execute(
"SELECT id, views, downloads FROM items LIMIT %s OFFSET %s",
[limit, offset],
"SELECT id, views, downloads FROM items ORDER BY id ASC LIMIT {} OFFSET {}".format(
limit, offset
)
)
# create a list to hold dicts of item stats
@@ -40,7 +41,7 @@ class AllItemsResource:
for item in cursor:
statistics.append(
{
"id": str(item["id"]),
"id": item["id"],
"views": item["views"],
"downloads": item["downloads"],
}
@@ -60,30 +61,26 @@ class ItemResource:
def on_get(self, req, resp, item_id):
"""Handles GET requests"""
import psycopg2.extras
# Adapt Pythons uuid.UUID type to PostgreSQLs uuid
# See: https://www.psycopg.org/docs/extras.html
psycopg2.extras.register_uuid()
with DatabaseManager() as db:
db.set_session(readonly=True)
with db.cursor() as cursor:
cursor = db.cursor()
cursor.execute(
"SELECT views, downloads FROM items WHERE id=%s", [str(item_id)]
"SELECT views, downloads FROM items WHERE id={}".format(item_id)
)
if cursor.rowcount == 0:
raise falcon.HTTPNotFound(
title="Item not found",
description=f'The item with id "{str(item_id)}" was not found.',
description='The item with id "{}" was not found.'.format(
item_id
),
)
else:
results = cursor.fetchone()
statistics = {
"id": str(item_id),
"id": item_id,
"views": results["views"],
"downloads": results["downloads"],
}
@@ -94,6 +91,6 @@ class ItemResource:
api = application = falcon.API()
api.add_route("/", RootResource())
api.add_route("/items", AllItemsResource())
api.add_route("/item/{item_id:uuid}", ItemResource())
api.add_route("/item/{item_id:int}", ItemResource())
# vim: set sw=4 ts=4 expandtab:

View File

@@ -15,7 +15,9 @@ class DatabaseManager:
"""Manage database connection."""
def __init__(self):
self._connection_uri = f"dbname={DATABASE_NAME} user={DATABASE_USER} password={DATABASE_PASS} host={DATABASE_HOST} port={DATABASE_PORT}"
self._connection_uri = "dbname={} user={} password={} host={} port={}".format(
DATABASE_NAME, DATABASE_USER, DATABASE_PASS, DATABASE_HOST, DATABASE_PORT
)
def __enter__(self):
try:

View File

@@ -70,13 +70,13 @@ def get_statistics_shards():
if len(statistics_core_years) > 0:
# Begin building a string of shards starting with the default one
shards = f"{SOLR_SERVER}/statistics"
shards = "{}/statistics".format(SOLR_SERVER)
for core in statistics_core_years:
# Create a comma-separated list of shards to pass to our Solr query
#
# See: https://wiki.apache.org/solr/DistributedSearch
shards += f",{SOLR_SERVER}/{core}"
shards += ",{}/{}".format(SOLR_SERVER, core)
# Return the string of shards, which may actually be empty. Solr doesn't
# seem to mind if the shards query parameter is empty and I haven't seen
@@ -134,7 +134,9 @@ def index_views():
while results_current_page <= results_num_pages:
# "pages" are zero based, but one based is more human readable
print(
f"Indexing item views (page {results_current_page + 1} of {results_num_pages + 1})"
"Indexing item views (page {} of {})".format(
results_current_page + 1, results_num_pages + 1
)
)
solr_query_params = {
@@ -217,7 +219,9 @@ def index_downloads():
while results_current_page <= results_num_pages:
# "pages" are zero based, but one based is more human readable
print(
f"Indexing item downloads (page {results_current_page + 1} of {results_num_pages + 1})"
"Indexing item downloads (page {} of {})".format(
results_current_page + 1, results_num_pages + 1
)
)
solr_query_params = {
@@ -260,7 +264,7 @@ with DatabaseManager() as db:
# create table to store item views and downloads
cursor.execute(
"""CREATE TABLE IF NOT EXISTS items
(id UUID PRIMARY KEY, views INT DEFAULT 0, downloads INT DEFAULT 0)"""
(id INT PRIMARY KEY, views INT DEFAULT 0, downloads INT DEFAULT 0)"""
)
# commit the table creation before closing the database connection

View File

@@ -1,37 +1,27 @@
-i https://pypi.org/simple
appdirs==1.4.3
attrs==19.3.0
backcall==0.1.0
black==19.10b0
click==7.0
decorator==4.4.2
decorator==4.4.1
entrypoints==0.3
flake8==3.7.9
ipython-genutils==0.2.0
ipython==7.13.0
isort==4.3.21
jedi==0.16.0
ipython==7.9.0
jedi==0.15.1
mccabe==0.6.1
more-itertools==8.2.0
packaging==20.1
parso==0.6.2
pathspec==0.7.0
pexpect==4.8.0 ; sys_platform != 'win32'
more-itertools==7.2.0
packaging==19.2
parso==0.5.1
pexpect==4.7.0 ; sys_platform != 'win32'
pickleshare==0.7.5
pluggy==0.13.1
prompt-toolkit==3.0.3
prompt-toolkit==2.0.10
ptyprocess==0.6.0
py==1.8.1
py==1.8.0
pycodestyle==2.5.0
pyflakes==2.1.1
pygments==2.5.2
pyparsing==2.4.6
pytest-clarity==0.3.0a0
pytest==5.3.5
regex==2020.2.20
six==1.14.0
termcolor==1.1.0
toml==0.10.0
pygments==2.5.1
pyparsing==2.4.5
pytest==5.3.1
six==1.13.0
traitlets==4.3.3
typed-ast==1.4.1
wcwidth==0.1.8
wcwidth==0.1.7

View File

@@ -1,9 +1,9 @@
-i https://pypi.org/simple
certifi==2019.11.28
certifi==2019.9.11
chardet==3.0.4
falcon==2.0.0
gunicorn==20.0.4
idna==2.9
idna==2.8
psycopg2-binary==2.8.4
requests==2.23.0
urllib3==1.25.8
requests==2.22.0
urllib3==1.25.7

View File

@@ -11,57 +11,57 @@ def client():
def test_get_docs(client):
"""Test requesting the documentation at the root."""
'''Test requesting the documentation at the root.'''
response = client.simulate_get("/")
response = client.simulate_get('/')
assert isinstance(response.content, bytes)
assert response.status_code == 200
def test_get_item(client):
"""Test requesting a single item."""
'''Test requesting a single item.'''
response = client.simulate_get("/item/c3910974-c3a5-4053-9dce-104aa7bb1621")
response = client.simulate_get('/item/17')
response_doc = json.loads(response.text)
assert isinstance(response_doc["downloads"], int)
assert isinstance(response_doc["id"], str)
assert isinstance(response_doc["views"], int)
assert isinstance(response_doc['downloads'], int)
assert isinstance(response_doc['id'], int)
assert isinstance(response_doc['views'], int)
assert response.status_code == 200
def test_get_missing_item(client):
"""Test requesting a single non-existing item."""
'''Test requesting a single non-existing item.'''
response = client.simulate_get("/item/c3910974-c3a5-4053-9dce-104aa7bb1620")
response = client.simulate_get('/item/1')
assert response.status_code == 404
def test_get_items(client):
"""Test requesting 100 items."""
'''Test requesting 100 items.'''
response = client.simulate_get("/items", query_string="limit=100")
response = client.simulate_get('/items', query_string='limit=100')
response_doc = json.loads(response.text)
assert isinstance(response_doc["currentPage"], int)
assert isinstance(response_doc["totalPages"], int)
assert isinstance(response_doc["statistics"], list)
assert isinstance(response_doc['currentPage'], int)
assert isinstance(response_doc['totalPages'], int)
assert isinstance(response_doc['statistics'], list)
assert response.status_code == 200
def test_get_items_invalid_limit(client):
"""Test requesting 100 items with an invalid limit parameter."""
'''Test requesting 100 items with an invalid limit parameter.'''
response = client.simulate_get("/items", query_string="limit=101")
response = client.simulate_get('/items', query_string='limit=101')
assert response.status_code == 400
def test_get_items_invalid_page(client):
"""Test requesting 100 items with an invalid page parameter."""
'''Test requesting 100 items with an invalid page parameter.'''
response = client.simulate_get("/items", query_string="page=-1")
response = client.simulate_get('/items', query_string='page=-1')
assert response.status_code == 400