diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 643aa0698..d57b2e7e5 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -40,7 +40,7 @@ Project maintainers who do not follow or enforce the Code of Conduct in good fai ## Attribution -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4 to remove puritanical language. The original is available at [http://contributor-covenant.org/version/1/4][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/4/ diff --git a/Pipfile b/Pipfile index 95727aeeb..a9331f134 100644 --- a/Pipfile +++ b/Pipfile @@ -4,20 +4,20 @@ verify_ssl = true name = "pypi" [packages] -django = "<2.0,>=1.11" +django = "<2.1,>=2.0" pillow = "*" coveralls = "*" dateparser = "*" +django-cors-headers = "*" django-crispy-forms = "*" django-extensions = "*" django-filter = "*" -django-flat-responsive = "*" djangorestframework = "*" factory-boy = "*" -"flake8" = "*" filemagic = "*" fuzzywuzzy = {extras = ["speedup"], version = "==0.15.0"} gunicorn = "*" +inotify-simple = "*" langdetect = "*" pdftotext = "*" pyocr = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 09cfb8639..614ee0e78 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "70653513e6c80b7e07f8e7fbff7592f2d22749dc5b1d723a04f921242bc9a78f" + "sha256": "e20c2294bcafd346ee57901df94a515a12976ed192dc37df848b39b56bdd1f4b" }, "pipfile-spec": 6, "requires": {}, @@ -19,29 +19,30 @@ "sha256:37228cda29411948b422fae072f57e31d3396d2ee1c9783775980ee9c9990af6", "sha256:58587dd4dc3daefad0487f6d9ae32b4542b185e1c36db6993290e7c41ca2b47c" ], - "markers": "python_version != '3.0.*' and python_version >= '2.7' and python_version != '3.2.*' and python_version != '3.1.*' and python_version != '3.3.*'", + "markers": "python_version >= '2.7' and python_version != '3.0.*' and python_version != '3.3.*' and python_version != '3.2.*' and python_version != '3.1.*'", "version": "==1.5" }, "atomicwrites": { "hashes": [ - "sha256:240831ea22da9ab882b551b31d4225591e5e447a68c5e188db5b89ca1d487585", - "sha256:a24da68318b08ac9c9c45029f4a10371ab5b20e4226738e150e6e7c571630ae6" + "sha256:0312ad34fcad8fac3704d441f7b317e50af620823353ec657a53e981f92920c0", + "sha256:ec9ae8adaae229e4f8446952d204a3e4b5fdd2d099f9be3aaf556120135fb3ee" ], - "version": "==1.1.5" + "markers": "python_version >= '2.7' and python_version != '3.0.*' and python_version != '3.3.*' and python_version != '3.2.*' and python_version != '3.1.*'", + "version": "==1.2.1" }, "attrs": { "hashes": [ - "sha256:4b90b09eeeb9b88c35bc642cbac057e45a5fd85367b985bd2809c62b7b939265", - "sha256:e0d0eb91441a3b53dab4d9b743eafc1ac44476296a2053b6ca3af0b139faf87b" + "sha256:10cbf6e27dbce8c30807caf056c8eb50917e0eaafe86347671b57254006c3e69", + "sha256:ca4be454458f9dec299268d472aaa5a11f67a4ff70093396e1ceae9c76cf4bbb" ], - "version": "==18.1.0" + "version": "==18.2.0" }, "certifi": { "hashes": [ - "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7", - "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0" + "sha256:376690d6f16d32f9d1fe8932551d80b23e9d393a8578c5633a2ed39a64861638", + "sha256:456048c7e371c089d0a77a5212fb37a2c2dce1e24146e3b7e0261736aaeaa22a" ], - "version": "==2018.4.16" + "version": "==2018.8.24" }, "chardet": { "hashes": [ @@ -54,8 +55,11 @@ "hashes": [ "sha256:03481e81d558d30d230bc12999e3edffe392d244349a90f4ef9b88425fac74ba", "sha256:0b136648de27201056c1869a6c0d4e23f464750fd9a9ba9750b8336a244429ed", + "sha256:10a46017fef60e16694a30627319f38a2b9b52e90182dddb6e37dcdab0f4bf95", "sha256:198626739a79b09fa0a2f06e083ffd12eb55449b5f8bfdbeed1df4910b2ca640", + "sha256:23d341cdd4a0371820eb2b0bd6b88f5003a7438bbedb33688cd33b8eae59affd", "sha256:28b2191e7283f4f3568962e373b47ef7f0392993bb6660d079c62bd50fe9d162", + "sha256:2a5b73210bad5279ddb558d9a2bfedc7f4bf6ad7f3c988641d83c40293deaec1", "sha256:2eb564bbf7816a9d68dd3369a510be3327f1c618d2357fa6b1216994c2e3d508", "sha256:337ded681dd2ef9ca04ef5d93cfc87e52e09db2594c296b4a0a3662cb1b41249", "sha256:3a2184c6d797a125dca8367878d3b9a178b6fdd05fdc2d35d758c3006a1cd694", @@ -81,15 +85,16 @@ "sha256:e05cb4d9aad6233d67e0541caa7e511fa4047ed7750ec2510d466e806e0255d6", "sha256:f3f501f345f24383c0000395b26b726e46758b71393267aeae0bd36f8b3ade80" ], + "markers": "python_version >= '2.6' and python_version != '3.0.*' and python_version != '3.2.*' and python_version < '4' and python_version != '3.1.*'", "version": "==4.5.1" }, "coveralls": { "hashes": [ - "sha256:32569a43c9dbc13fa8199247580a4ab182ef439f51f65bb7f8316d377a1340e8", - "sha256:664794748d2e5673e347ec476159a9d87f43e0d2d44950e98ed0e27b98da8346" + "sha256:9dee67e78ec17b36c52b778247762851c8e19a893c9a14e921a2fc37f05fac22", + "sha256:aec5a1f5e34224b9089664a1b62217732381c7de361b6ed1b3c394d7187b352a" ], "index": "pypi", - "version": "==1.3.0" + "version": "==1.5.0" }, "dateparser": { "hashes": [ @@ -101,11 +106,19 @@ }, "django": { "hashes": [ - "sha256:b7f77c0d168de4c4ad30a02ae31b9dca04fb3c10472f04918d5c02b4117bba68", - "sha256:eb9271f0874f53106a2719c0c35ce67631f6cc27cf81a60c6f8c9817b35a3f6e" + "sha256:0c5b65847d00845ee404bbc0b4a85686f15eb3001ffddda3db4e9baa265bf136", + "sha256:68aeea369a8130259354b6ba1fa9babe0c5ee6bced505dea4afcd00f765ae38b" ], "index": "pypi", - "version": "==1.11.14" + "version": "==2.0.8" + }, + "django-cors-headers": { + "hashes": [ + "sha256:5545009c9b233ea7e70da7dbab7cb1c12afa01279895086f98ec243d7eab46fa", + "sha256:c4c2ee97139d18541a1be7d96fe337d1694623816d83f53cb7c00da9b94acae1" + ], + "index": "pypi", + "version": "==2.4.0" }, "django-crispy-forms": { "hashes": [ @@ -117,26 +130,19 @@ }, "django-extensions": { "hashes": [ - "sha256:3be3debf53c77ca795bdf713726c923aa3c3f895e1a42e2e31a68c1a562346a4", - "sha256:94bfac99eb262c5ac27e53eda96925e2e53fe0b331af7dde37012d07639a649c" + "sha256:1f626353a11479014bfe0d77e76d8f866ebca1bb5d595cb57b776230b9e0eb92", + "sha256:f21b898598a1628cb73017fb9672e2c5e624133be9764f0eb138e0abf8a62b62" ], "index": "pypi", - "version": "==2.0.7" + "version": "==2.1.2" }, "django-filter": { "hashes": [ - "sha256:ea204242ea83790e1512c9d0d8255002a652a6f4986e93cee664f28955ba0c22", - "sha256:ec0ef1ba23ef95b1620f5d481334413700fb33f45cd76d56a63f4b0b1d76976a" + "sha256:6f4e4bc1a11151178520567b50320e5c32f8edb552139d93ea3e30613b886f56", + "sha256:86c3925020c27d072cdae7b828aaa5d165c2032a629abbe3c3a1be1edae61c58" ], "index": "pypi", - "version": "==1.1.0" - }, - "django-flat-responsive": { - "hashes": [ - "sha256:451caa2700c541b52fb7ce2d34d3d8dee9e980cf29f5463bc8a8c6256a1a6474" - ], - "index": "pypi", - "version": "==2.0" + "version": "==2.0.0" }, "djangorestframework": { "hashes": [ @@ -157,6 +163,7 @@ "sha256:a7a84d5fa07a089186a329528f127c9d73b9de57f1a1131b82bb5320ee651f6a", "sha256:fc155a6b553c66c838d1a22dba1dc9f5f505c43285a878c6f74a79c024750b83" ], + "markers": "python_version >= '2.7' and python_version != '3.0.*' and python_version != '3.3.*' and python_version != '3.2.*' and python_version != '3.1.*'", "version": "==1.5.0" }, "factory-boy": { @@ -169,10 +176,10 @@ }, "faker": { "hashes": [ - "sha256:04645d946256b835c675c1cef7c03817a164b0c4e452018fd50b212ddff08c22", - "sha256:fe48f35aa3443bc5655b0782d3a2f594bf4882d0e2a947b80207a60494d32907" + "sha256:ea7cfd3aeb1544732d08bd9cfba40c5b78e3a91e17b1a0698ab81bfc5554c628", + "sha256:f6d67f04abfb2b4bea7afc7fa6c18cf4c523a67956e455668be9ae42bccc21ad" ], - "version": "==0.8.16" + "version": "==0.9.0" }, "filemagic": { "hashes": [ @@ -181,14 +188,6 @@ "index": "pypi", "version": "==1.6" }, - "flake8": { - "hashes": [ - "sha256:7253265f7abd8b313e3892944044a365e3f4ac3fcdcfb4298f55ee9ddf188ba0", - "sha256:c7841163e2b576d435799169b78703ad6ac1bbb0f199994fc05f700b2a90ea37" - ], - "index": "pypi", - "version": "==3.5.0" - }, "fuzzywuzzy": { "hashes": [ "sha256:3759bc6859daa0eecef8c82b45404bdac20c23f23136cf4c18b46b426bbc418f", @@ -213,6 +212,13 @@ ], "version": "==2.7" }, + "inotify-simple": { + "hashes": [ + "sha256:fc2c10dd73278a1027d0663f2db51240af5946390f363a154361406ebdddd8dd" + ], + "index": "pypi", + "version": "==1.1.8" + }, "langdetect": { "hashes": [ "sha256:91a170d5f0ade380db809b3ba67f08e95fe6c6c8641f96d67a51ff7e98a9bf30" @@ -220,20 +226,13 @@ "index": "pypi", "version": "==1.0.7" }, - "mccabe": { - "hashes": [ - "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", - "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" - ], - "version": "==0.6.1" - }, "more-itertools": { "hashes": [ - "sha256:2b6b9893337bfd9166bee6a62c2b0c9fe7735dcf85948b387ec8cba30e85d8e8", - "sha256:6703844a52d3588f951883005efcf555e49566a48afd4db4e965d69b883980d3", - "sha256:a18d870ef2ffca2b8463c0070ad17b5978056f403fb64e3f15fe62a52db21cc0" + "sha256:c187a73da93e7a8acc0001572aebc7e3c69daf7bf6881a2cea10650bd4420092", + "sha256:c476b5d3a34e12d40130bc2f935028b5f636df8f372dc2c1c01dc19681b2039e", + "sha256:fcbfeaea0be121980e15bc97b3817b5202ca73d0eae185b4550cbfce2a3ebb3d" ], - "version": "==4.2.0" + "version": "==4.3.0" }, "pdftotext": { "hashes": [ @@ -280,49 +279,42 @@ }, "pluggy": { "hashes": [ - "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff", - "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c", - "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5" + "sha256:6e3836e39f4d36ae72840833db137f7b7d35105079aee6ec4a62d9f80d594dd1", + "sha256:95eb8364a4708392bae89035f45341871286a333f749c3141c20573d2b3876e1" ], - "version": "==0.6.0" + "markers": "python_version >= '2.7' and python_version != '3.0.*' and python_version != '3.3.*' and python_version != '3.2.*' and python_version != '3.1.*'", + "version": "==0.7.1" }, "py": { "hashes": [ - "sha256:3fd59af7435864e1a243790d322d763925431213b6b8529c6ca71081ace3bbf7", - "sha256:e31fb2767eb657cbde86c454f02e99cb846d3cd9d61b318525140214fdc0e98e" + "sha256:06a30435d058473046be836d3fc4f27167fd84c45b99704f2fb5509ef61f9af1", + "sha256:50402e9d1c9005d759426988a492e0edaadb7f4e68bcddfea586bc7432d009c6" ], - "markers": "python_version != '3.0.*' and python_version != '3.3.*' and python_version != '3.1.*' and python_version != '3.2.*' and python_version >= '2.7'", - "version": "==1.5.4" + "markers": "python_version >= '2.7' and python_version != '3.0.*' and python_version != '3.3.*' and python_version != '3.2.*' and python_version != '3.1.*'", + "version": "==1.6.0" }, "pycodestyle": { "hashes": [ - "sha256:682256a5b318149ca0d2a9185d365d8864a768a28db66a84a2ea946bcc426766", - "sha256:6c4245ade1edfad79c3446fadfc96b0de2759662dc29d07d80a6f27ad1ca6ba9" + "sha256:cbc619d09254895b0d12c2c691e237b2e91e9b2ecf5e84c26b35400f93dcfb83", + "sha256:cbfca99bd594a10f674d0cd97a3d802a1fdef635d4361e1a2658de47ed261e3a" ], "index": "pypi", - "version": "==2.3.1" - }, - "pyflakes": { - "hashes": [ - "sha256:08bd6a50edf8cffa9fa09a463063c425ecaaf10d1eb0335a7e8b1401aef89e6f", - "sha256:8d616a382f243dbf19b54743f280b80198be0bca3a5396f1d2e1fca6223e8805" - ], - "version": "==1.6.0" + "version": "==2.4.0" }, "pyocr": { "hashes": [ - "sha256:9ee8b5f38dd966ca531115fc5fe4715f7fa8961a9f14cd5109c2d938c17a2043" + "sha256:bdc4d43bf9b63c2a9a4b2c9a1a623a0e63c8e6600eede5dbe866b31f3a5f2207" ], "index": "pypi", - "version": "==0.5.1" + "version": "==0.5.2" }, "pytest": { "hashes": [ - "sha256:0453c8676c2bee6feb0434748b068d5510273a916295fd61d306c4f22fbfd752", - "sha256:4b208614ae6d98195430ad6bde03641c78553acee7c83cec2e85d613c0cd383d" + "sha256:2d7c49e931316cc7d1638a3e5f54f5d7b4e5225972b3c9838f3584788d27f349", + "sha256:ad0c7db7b5d4081631e0155f5c61b80ad76ce148551aaafe3a718d65a7508b18" ], "index": "pypi", - "version": "==3.6.3" + "version": "==3.7.4" }, "pytest-cov": { "hashes": [ @@ -334,11 +326,11 @@ }, "pytest-django": { "hashes": [ - "sha256:088b66211c57972e7bd072ba73ccec1c3b6f6185f894b3b8eb966d2f3b7d46cb", - "sha256:3fea4d0a84bf3af1f1e82448b9a91b3ddb22b659d802e026ae843040da0c3220" + "sha256:2d2e0a618d91c280d463e90bcbea9b4e417609157f611a79685b1c561c4c0836", + "sha256:59683def396923b78d7e191a7086a48193f8d5db869ace79acb38f906522bc7b" ], "index": "pypi", - "version": "==3.3.2" + "version": "==3.4.2" }, "pytest-env": { "hashes": [ @@ -363,11 +355,11 @@ }, "pytest-xdist": { "hashes": [ - "sha256:be2662264b035920ba740ed6efb1c816a83c8a22253df7766d129f6a7bfdbd35", - "sha256:e8f5744acc270b3e7d915bdb4d5f471670f049b6fbd163d4cbd52203b075d30f" + "sha256:0875deac20f6d96597036bdf63970887a6f36d28289c2f6682faf652dfea687b", + "sha256:28e25e79698b2662b648319d3971c0f9ae0e6500f88258ccb9b153c31110ba9b" ], "index": "pypi", - "version": "==1.22.2" + "version": "==1.23.0" }, "python-dateutil": { "hashes": [ @@ -379,11 +371,11 @@ }, "python-dotenv": { "hashes": [ - "sha256:4965ed170bf51c347a89820e8050655e9c25db3837db6602e906b6d850fad85c", - "sha256:509736185257111613009974e666568a1b031b028b61b500ef1ab4ee780089d5" + "sha256:122290a38ece9fe4f162dc7c95cae3357b983505830a154d3c98ef7f6c6cea77", + "sha256:4a205787bc829233de2a823aa328e44fd9996fedb954989a21f1fc67c13d7a77" ], "index": "pypi", - "version": "==0.8.2" + "version": "==0.9.1" }, "python-gnupg": { "hashes": [ @@ -409,23 +401,23 @@ }, "regex": { "hashes": [ - "sha256:0f935c4b04b60bf3904bcaa11dec702a49de61caff3b09793521759f61bd7585", - "sha256:22a561fce0691e2819f8b4957b0a6a1829ec1df503e93569a015a01c173b401c", - "sha256:2fc09d427dfc7f53ed1261caf357b25932409fd1be4dae3f3bc70e353a7120bb", - "sha256:309f05c0a93a1410d1250f4170257d3f4092a7a4460e46ef47925db7c930b9c6", - "sha256:3e985c6980badbf97497945cd922561639e12e7f4174f735979136c0d81cc1b4", - "sha256:5cdfe2f16d674e2e7b341c0cd0b12cc4644d2adf248ff860c0dc74494397f001", - "sha256:717ed720c872a0c4458d8de81660e1e1e5c9a3f4277b782e01d5df934e50a820", - "sha256:81709bdab6fb5db389a3123f28f7198921372144fbda03b8ab8162ef9688b61c", - "sha256:97d286c501c2007e43003b53a997102d5ca781fd3d9228427f942779ac43b107", - "sha256:a35138a333069cf1d19ec39e1b1aaa868a474cf215303af2bb5d08b747796d9a", - "sha256:b172583f0c5f104e059a30dd6a1f9d20693031b156558590a745d6cc3192e283", - "sha256:b5a739fff4f0bfeba6d889820a14b359f50bcc3466afe00ce616fd5cb9093e25", - "sha256:b65b3a347a33fec024133cd21f926f6bff1fae387ff2f380b8751a8b26a6b92c", - "sha256:c42af0a812c272339ac9602bf10e5d1e022e518e5936c303624b5c11803805e3", - "sha256:d421ee4a55922f2ff2561cae543458f5bff089b5a94c7dfcf60b6bef5721cd0f" + "sha256:22d7ef8c2df344328a8a3c61edade2ee714e5de9360911d22a9213931c769faa", + "sha256:3a699780c6b712c67dc23207b129ccc6a7e1270233f7aadead3ea3f83c893702", + "sha256:42f460d349baebd5faec02a0c920988fb0300b24baf898d9c139886565b66b6c", + "sha256:43bf3d79940cbdf19adda838d8b26b28b47bec793cda46590b5b25703742f440", + "sha256:47d6c7f0588ef33464e00023067c4e7cce68e0d6a686a73c7ee15abfdad503d4", + "sha256:5b879f59f25ed9b91bc8693a9a994014b431f224f492519ad0255ce6b54b83e5", + "sha256:8ba0093c412900f636b0f826c597a0c3ea0e395344bc99894ddefe88b76c9c7e", + "sha256:a4789254a1a0bd7a637036cce0b7ed72d8cc864e93f2e9cfd10ac00ae27bb7b0", + "sha256:b73cea07117dca888b0c3671770b501bef19aac9c45c8ffdb5bea2cca2377b0a", + "sha256:d3eb59fa3e5b5438438ec97acd9dc86f077428e020b015b43987e35bea68ef4c", + "sha256:d51d232b4e2f106deaf286001f563947fee255bc5bd209a696f027e15cf0a1e7", + "sha256:d59b03131a8e35061b47a8f186324a95eaf30d5f6ee9cc0637e7b87d29c7c9b5", + "sha256:dd705df1b47470388fc4630e4df3cbbe7677e2ab80092a1c660cae630a307b2d", + "sha256:e87fffa437a4b00afb17af785da9b01618425d6cd984c677639deb937037d8f2", + "sha256:ed40e0474ab5ab228a8d133759d451b31d3ccdebaff698646e54aff82c3de4f8" ], - "version": "==2018.6.21" + "version": "==2018.8.29" }, "requests": { "hashes": [ @@ -465,6 +457,7 @@ "sha256:a68ac5e15e76e7e5dd2b8f94007233e01effe3e50e8daddf69acfd81cb686baf", "sha256:b5725a0bd4ba422ab0e66e89e030c806576753ea3ee08554382c14e685d117b5" ], + "markers": "python_version >= '2.6' and python_version != '3.3.*' and python_version < '4' and python_version != '3.1.*' and python_version != '3.2.*' and python_version != '3.0.*'", "version": "==1.23" } }, @@ -492,10 +485,10 @@ }, "certifi": { "hashes": [ - "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7", - "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0" + "sha256:376690d6f16d32f9d1fe8932551d80b23e9d393a8578c5633a2ed39a64861638", + "sha256:456048c7e371c089d0a77a5212fb37a2c2dce1e24146e3b7e0261736aaeaa22a" ], - "version": "==2018.4.16" + "version": "==2018.8.24" }, "chardet": { "hashes": [ @@ -535,11 +528,11 @@ }, "ipython": { "hashes": [ - "sha256:a0c96853549b246991046f32d19db7140f5b1a644cc31f0dc1edc86713b7676f", - "sha256:eca537aa61592aca2fef4adea12af8e42f5c335004dfa80c78caf80e8b525e5c" + "sha256:007dcd929c14631f83daff35df0147ea51d1af420da303fd078343878bd5fb62", + "sha256:b0f2ef9eada4a68ef63ee10b6dde4f35c840035c50fd24265f8052c98947d5a4" ], "index": "pypi", - "version": "==6.4.0" + "version": "==6.5.0" }, "ipython-genutils": { "hashes": [ @@ -577,10 +570,10 @@ }, "parso": { "hashes": [ - "sha256:8105449d86d858e53ce3e0044ede9dd3a395b1c9716c696af8aa3787158ab806", - "sha256:d250235e52e8f9fc5a80cc2a5f804c9fefd886b2e67a2b1099cf085f403f8e33" + "sha256:35704a43a3c113cce4de228ddb39aab374b8004f4f2407d070b6a2ca784ce8a2", + "sha256:895c63e93b94ac1e1690f5fdd40b65f07c8171e3e53cbd7793b5b96c0e0a7f24" ], - "version": "==0.3.0" + "version": "==0.3.1" }, "pexpect": { "hashes": [ @@ -663,17 +656,18 @@ }, "sphinx": { "hashes": [ - "sha256:85f7e32c8ef07f4ba5aeca728e0f7717bef0789fba8458b8d9c5c294cad134f3", - "sha256:d45480a229edf70d84ca9fae3784162b1bc75ee47e480ffe04a4b7f21a95d76d" + "sha256:a07050845cc9a2f4026a6035cc8ed795a5ce7be6528bbc82032385c10807dfe7", + "sha256:d719de667218d763e8fd144b7fcfeefd8d434a6201f76bf9f0f0c1fa6f47fcdb" ], "index": "pypi", - "version": "==1.7.5" + "version": "==1.7.8" }, "sphinxcontrib-websupport": { "hashes": [ "sha256:68ca7ff70785cbe1e7bccc71a48b5b6d965d79ca50629606c7861a21b206d9dd", "sha256:9de47f375baf1ea07cdb3436ff39d7a9c76042c10a769c52353ec46e4e8fc3b9" ], + "markers": "python_version != '3.3.*' and python_version >= '2.7' and python_version != '3.1.*' and python_version != '3.2.*' and python_version != '3.0.*'", "version": "==1.1.0" }, "traitlets": { @@ -688,6 +682,7 @@ "sha256:a68ac5e15e76e7e5dd2b8f94007233e01effe3e50e8daddf69acfd81cb686baf", "sha256:b5725a0bd4ba422ab0e66e89e030c806576753ea3ee08554382c14e685d117b5" ], + "markers": "python_version >= '2.6' and python_version != '3.3.*' and python_version < '4' and python_version != '3.1.*' and python_version != '3.2.*' and python_version != '3.0.*'", "version": "==1.23" }, "wcwidth": { diff --git a/docs/changelog.rst b/docs/changelog.rst index 84cc6bae9..f80445dde 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,26 @@ Changelog ######### +2.2.1 +===== + +* `Kyle Lucy`_ reported a bug quickly after the release of 2.2.0 where we broke + the ``DISABLE_LOGIN`` feature: `#392`_. + + +2.2.0 +===== + +* Thanks to `dadosch`_, `Wolfgang Mader`_, and `Tim Brooks`_ this is the first + version of Paperless that supports Django 2.0! As a result of their hard + work, you can now also run Paperless on Python 3.7 as well: `#386`_ & + `#390`_. +* `Stéphane Brunner`_ added a few lines of code that made tagging interface a lot + easier on those of us with lots of different tags: `#391`_. +* `Kilian Koeltzsch`_ noticed a bug in how we capture & automatically create + tags, so that's fixed now too: `#384`_. + + 2.1.0 ===== @@ -451,6 +471,11 @@ bulk of the work on this big change. .. _mcronce: https://github.com/mcronce .. _Enno Lohmeier: https://github.com/elohmeier .. _Mark McFate: https://github.com/SummittDweller +.. _dadosch: https://github.com/dadosch +.. _Wolfgang Mader: https://github.com/wmader +.. _Tim Brooks: https://github.com/brookst +.. _Stéphane Brunner: https://github.com/sbrunner +.. _Kilian Koeltzsch: https://github.com/kiliankoe .. _#20: https://github.com/danielquinn/paperless/issues/20 .. _#44: https://github.com/danielquinn/paperless/issues/44 @@ -525,6 +550,11 @@ bulk of the work on this big change. .. _#374: https://github.com/danielquinn/paperless/pull/374 .. _#375: https://github.com/danielquinn/paperless/pull/375 .. _#376: https://github.com/danielquinn/paperless/pull/376 +.. _#384: https://github.com/danielquinn/paperless/issues/384 +.. _#386: https://github.com/danielquinn/paperless/issues/386 +.. _#391: https://github.com/danielquinn/paperless/pull/391 +.. _#390: https://github.com/danielquinn/paperless/pull/390 +.. _#392: https://github.com/danielquinn/paperless/issues/392 .. _pipenv: https://docs.pipenv.org/ .. _a new home on Docker Hub: https://hub.docker.com/r/danielquinn/paperless/ diff --git a/requirements.txt b/requirements.txt index 125a89ac7..247d9993a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,53 +1,51 @@ -apipkg==1.4 -attrs==18.1.0 -certifi==2018.4.16 +-i https://pypi.python.org/simple +apipkg==1.5; python_version != '3.1.*' +atomicwrites==1.2.1; python_version != '3.1.*' +attrs==18.2.0 +certifi==2018.8.24 chardet==3.0.4 -coverage==4.5.1 -coveralls==1.3.0 +coverage==4.5.1; python_version != '3.1.*' +coveralls==1.5.0 dateparser==0.7.0 django-cors-headers==2.4.0 django-crispy-forms==1.7.2 -django-extensions==2.0.7 -django-filter==1.1.0 -django-flat-responsive==2.0 -django==1.11.13 +django-extensions==2.1.2 +django-filter==2.0.0 +django==2.0.8 djangorestframework==3.8.2 docopt==0.6.2 -execnet==1.5.0 +execnet==1.5.0; python_version != '3.1.*' factory-boy==2.11.1 -faker==0.8.15 +faker==0.9.0 filemagic==1.6 -flake8==3.5.0 fuzzywuzzy==0.15.0 -gunicorn==19.8.1 -idna==2.6 -inotify_simple==1.1.7; sys_platform == 'linux' +gunicorn==19.9.0 +idna==2.7 +inotify-simple==1.1.8 langdetect==1.0.7 -mccabe==0.6.1 -more-itertools==4.1.0 -pdftotext==2.0.2 -pillow==5.1.0 -pluggy==0.6.0 -py==1.5.3 -pycodestyle==2.3.1 -pyflakes==1.6.0 -pyocr==0.5.1 +more-itertools==4.3.0 +pdftotext==2.1.0 +pillow==5.2.0 +pluggy==0.7.1; python_version != '3.1.*' +py==1.6.0; python_version != '3.1.*' +pycodestyle==2.4.0 +pyocr==0.5.2 pytest-cov==2.5.1 -pytest-django==3.2.1 +pytest-django==3.4.2 pytest-env==0.6.2 pytest-forked==0.2 pytest-sugar==0.9.1 -pytest-xdist==1.22.2 -pytest==3.5.1 +pytest-xdist==1.23.0 +pytest==3.7.4 python-dateutil==2.7.3 -python-dotenv==0.8.2 -python-gnupg==0.4.2 +python-dotenv==0.9.1 +python-gnupg==0.4.3 python-levenshtein==0.12.0 -pytz==2018.4 -regex==2018.2.21 -requests==2.18.4 +pytz==2018.5 +regex==2018.8.29 +requests==2.19.1 six==1.11.0 termcolor==1.1.0 text-unidecode==1.2 tzlocal==1.5.1 -urllib3==1.22 +urllib3==1.23; python_version != '3.0.*' diff --git a/src/documents/admin.py b/src/documents/admin.py index 659ad8581..36154b6ba 100644 --- a/src/documents/admin.py +++ b/src/documents/admin.py @@ -3,8 +3,13 @@ from datetime import datetime from django.conf import settings from django.contrib import admin from django.contrib.auth.models import User, Group -from django.core.urlresolvers import reverse +try: + from django.core.urlresolvers import reverse +except ImportError: + from django.urls import reverse from django.templatetags.static import static +from django.utils.safestring import mark_safe +from django.utils.html import format_html, format_html_join from .models import Correspondent, Tag, Document, Log @@ -137,6 +142,7 @@ class DocumentAdmin(CommonAdmin): "tags_") list_filter = ("tags", "correspondent", FinancialYearFilter, MonthListFilter) + filter_horizontal = ("tags",) ordering = ["-created", "correspondent"] @@ -177,7 +183,7 @@ class DocumentAdmin(CommonAdmin): ) } ) - return r + return mark_safe(r) tags_.allow_tags = True def document(self, obj): @@ -197,16 +203,13 @@ class DocumentAdmin(CommonAdmin): @staticmethod def _html_tag(kind, inside=None, **kwargs): - - attributes = [] - for lft, rgt in kwargs.items(): - attributes.append('{}="{}"'.format(lft, rgt)) + attributes = format_html_join(' ', '{}="{}"', kwargs.items()) if inside is not None: - return "<{kind} {attributes}>{inside}".format( - kind=kind, attributes=" ".join(attributes), inside=inside) + return format_html("<{kind} {attributes}>{inside}", + kind=kind, attributes=attributes, inside=inside) - return "<{} {}/>".format(kind, " ".join(attributes)) + return format_html("<{} {}/>", kind, attributes) class LogAdmin(CommonAdmin): diff --git a/src/documents/filters.py b/src/documents/filters.py index 2ed7f29db..68861d967 100644 --- a/src/documents/filters.py +++ b/src/documents/filters.py @@ -5,7 +5,7 @@ from .models import Correspondent, Document, Tag class CorrespondentFilterSet(FilterSet): - class Meta(object): + class Meta: model = Correspondent fields = { "name": [ @@ -18,7 +18,7 @@ class CorrespondentFilterSet(FilterSet): class TagFilterSet(FilterSet): - class Meta(object): + class Meta: model = Tag fields = { "name": [ @@ -42,15 +42,18 @@ class DocumentFilterSet(FilterSet): ) } - correspondent__name = CharFilter(name="correspondent__name", **CHAR_KWARGS) - correspondent__slug = CharFilter(name="correspondent__slug", **CHAR_KWARGS) - tags__name = CharFilter(name="tags__name", **CHAR_KWARGS) - tags__slug = CharFilter(name="tags__slug", **CHAR_KWARGS) - tags__empty = BooleanFilter(name='tags', - lookup_expr='isnull', - distinct=True) + correspondent__name = CharFilter( + field_name="correspondent__name", **CHAR_KWARGS) + correspondent__slug = CharFilter( + field_name="correspondent__slug", **CHAR_KWARGS) + tags__name = CharFilter( + field_name="tags__name", **CHAR_KWARGS) + tags__slug = CharFilter( + field_name="tags__slug", **CHAR_KWARGS) + tags__empty = BooleanFilter( + field_name="tags", lookup_expr="isnull", distinct=True) - class Meta(object): + class Meta: model = Document fields = { "title": [ diff --git a/src/documents/management/commands/document_consumer.py b/src/documents/management/commands/document_consumer.py index 41e5382d5..6f731372f 100644 --- a/src/documents/management/commands/document_consumer.py +++ b/src/documents/management/commands/document_consumer.py @@ -1,7 +1,5 @@ -import datetime import logging import os -import sys import time from django.conf import settings @@ -13,7 +11,7 @@ from ...mail import MailFetcher, MailFetcherError try: from inotify_simple import INotify, flags except ImportError: - pass + INotify = flags = None class Command(BaseCommand): @@ -62,7 +60,8 @@ class Command(BaseCommand): parser.add_argument( "--no-inotify", action="store_true", - help="Don't use inotify, even if it's available." + help="Don't use inotify, even if it's available.", + default=False ) def handle(self, *args, **options): @@ -71,8 +70,7 @@ class Command(BaseCommand): directory = options["directory"] loop_time = options["loop_time"] mail_delta = options["mail_delta"] * 60 - use_inotify = (not options["no_inotify"] - and "inotify_simple" in sys.modules) + use_inotify = INotify is not None and options["no_inotify"] is False try: self.file_consumer = Consumer(consume=directory) diff --git a/src/documents/migrations/0003_sender.py b/src/documents/migrations/0003_sender.py index ce2508994..27eead032 100644 --- a/src/documents/migrations/0003_sender.py +++ b/src/documents/migrations/0003_sender.py @@ -32,7 +32,6 @@ def realign_senders(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('documents', '0002_auto_20151226_1316'), ] diff --git a/src/documents/migrations/0011_auto_20160303_1929.py b/src/documents/migrations/0011_auto_20160303_1929.py index af4ee4c66..7b77a8835 100644 --- a/src/documents/migrations/0011_auto_20160303_1929.py +++ b/src/documents/migrations/0011_auto_20160303_1929.py @@ -6,7 +6,7 @@ from django.db import migrations class Migration(migrations.Migration): - + atomic = False dependencies = [ ('documents', '0010_log'), ] diff --git a/src/documents/migrations/0012_auto_20160305_0040.py b/src/documents/migrations/0012_auto_20160305_0040.py index 5168c9206..a0b4b27af 100644 --- a/src/documents/migrations/0012_auto_20160305_0040.py +++ b/src/documents/migrations/0012_auto_20160305_0040.py @@ -112,7 +112,6 @@ def move_documents_and_create_thumbnails(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('documents', '0011_auto_20160303_1929'), ] diff --git a/src/documents/migrations/0014_document_checksum.py b/src/documents/migrations/0014_document_checksum.py index 167245dea..bc563cf86 100644 --- a/src/documents/migrations/0014_document_checksum.py +++ b/src/documents/migrations/0014_document_checksum.py @@ -128,7 +128,6 @@ def do_nothing(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('documents', '0013_auto_20160325_2111'), ] diff --git a/src/documents/migrations/0019_add_consumer_user.py b/src/documents/migrations/0019_add_consumer_user.py index a3d7d787e..bc52ae7f6 100644 --- a/src/documents/migrations/0019_add_consumer_user.py +++ b/src/documents/migrations/0019_add_consumer_user.py @@ -15,7 +15,6 @@ def reverse_func(apps, schema_editor): class Migration(migrations.Migration): - dependencies = [ ('documents', '0018_auto_20170715_1712'), ] diff --git a/src/documents/migrations/0020_document_added.py b/src/documents/migrations/0020_document_added.py index dbddf80ae..bd3566481 100644 --- a/src/documents/migrations/0020_document_added.py +++ b/src/documents/migrations/0020_document_added.py @@ -11,8 +11,8 @@ def set_added_time_to_created_time(apps, schema_editor): doc.added = doc.created doc.save() -class Migration(migrations.Migration): +class Migration(migrations.Migration): dependencies = [ ('documents', '0019_add_consumer_user'), ] diff --git a/src/documents/models.py b/src/documents/models.py index b97eebc72..39be69d06 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -10,7 +10,10 @@ from collections import OrderedDict from fuzzywuzzy import fuzz from django.conf import settings -from django.core.urlresolvers import reverse +try: + from django.core.urlresolvers import reverse +except ImportError: + from django.urls import reverse from django.db import models from django.template.defaultfilters import slugify from django.utils import timezone @@ -59,6 +62,7 @@ class MatchingModel(models.Model): class Meta: abstract = True + ordering = ("name",) def __str__(self): return self.name @@ -447,8 +451,10 @@ class FileInfo: def _get_tags(cls, tags): r = [] for t in tags.split(","): - r.append( - Tag.objects.get_or_create(slug=t, defaults={"name": t})[0]) + r.append(Tag.objects.get_or_create( + slug=t.lower(), + defaults={"name": t} + )[0]) return tuple(r) @classmethod diff --git a/src/documents/serialisers.py b/src/documents/serialisers.py index 504999276..f71a0c5ab 100644 --- a/src/documents/serialisers.py +++ b/src/documents/serialisers.py @@ -5,14 +5,14 @@ from .models import Correspondent, Tag, Document, Log class CorrespondentSerializer(serializers.HyperlinkedModelSerializer): - class Meta(object): + class Meta: model = Correspondent fields = ("id", "slug", "name") class TagSerializer(serializers.HyperlinkedModelSerializer): - class Meta(object): + class Meta: model = Tag fields = ( "id", "slug", "name", "colour", "match", "matching_algorithm") @@ -34,7 +34,7 @@ class DocumentSerializer(serializers.ModelSerializer): view_name="drf:correspondent-detail", allow_null=True) tags = TagsField(view_name="drf:tag-detail", many=True) - class Meta(object): + class Meta: model = Document fields = ( "id", @@ -57,7 +57,7 @@ class LogSerializer(serializers.ModelSerializer): time = serializers.DateTimeField() messages = serializers.CharField() - class Meta(object): + class Meta: model = Log fields = ( "time", diff --git a/src/documents/tests/test_consumer.py b/src/documents/tests/test_consumer.py index b401f9477..3f5c69774 100644 --- a/src/documents/tests/test_consumer.py +++ b/src/documents/tests/test_consumer.py @@ -3,7 +3,7 @@ from unittest import mock from tempfile import TemporaryDirectory from ..consumer import Consumer -from ..models import FileInfo +from ..models import FileInfo, Tag class TestConsumer(TestCase): @@ -190,6 +190,20 @@ class TestAttributes(TestCase): () ) + def test_case_insensitive_tag_creation(self): + """ + Tags should be detected and created as lower case. + :return: + """ + + path = "Title - Correspondent - tAg1,TAG2.pdf" + self.assertEqual(len(FileInfo.from_path(path).tags), 2) + + path = "Title - Correspondent - tag1,tag2.pdf" + self.assertEqual(len(FileInfo.from_path(path).tags), 2) + + self.assertEqual(Tag.objects.all().count(), 2) + class TestFieldPermutations(TestCase): diff --git a/src/paperless/settings.py b/src/paperless/settings.py index 7fdcfec76..7cb7646c4 100644 --- a/src/paperless/settings.py +++ b/src/paperless/settings.py @@ -69,7 +69,6 @@ INSTALLED_APPS = [ "paperless_tesseract.apps.PaperlessTesseractConfig", "paperless_text.apps.PaperlessTextConfig", - "flat_responsive", # TODO: Remove as of Django 2.x "django.contrib.admin", "rest_framework", @@ -81,16 +80,13 @@ INSTALLED_APPS = [ if os.getenv("PAPERLESS_INSTALLED_APPS"): INSTALLED_APPS += os.getenv("PAPERLESS_INSTALLED_APPS").split(",") - - -MIDDLEWARE_CLASSES = [ +MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] @@ -100,9 +96,8 @@ CORS_ORIGIN_WHITELIST = tuple(os.getenv("PAPERLESS_CORS_ALLOWED_HOSTS", "localho # If auth is disabled, we just use our "bypass" authentication middleware if bool(os.getenv("PAPERLESS_DISABLE_LOGIN", "false").lower() in ("yes", "y", "1", "t", "true")): - _index = MIDDLEWARE_CLASSES.index("django.contrib.auth.middleware.AuthenticationMiddleware") - MIDDLEWARE_CLASSES[_index] = "paperless.middleware.Middleware" - MIDDLEWARE_CLASSES.remove("django.contrib.auth.middleware.SessionAuthenticationMiddleware") + _index = MIDDLEWARE.index("django.contrib.auth.middleware.AuthenticationMiddleware") + MIDDLEWARE[_index] = "paperless.middleware.Middleware" ROOT_URLCONF = 'paperless.urls' diff --git a/src/paperless/urls.py b/src/paperless/urls.py index e5e559f12..f66ce6664 100644 --- a/src/paperless/urls.py +++ b/src/paperless/urls.py @@ -28,9 +28,11 @@ urlpatterns = [ # API url( r"^api/auth/", - include('rest_framework.urls', namespace="rest_framework") + include( + ('rest_framework.urls', 'rest_framework'), + namespace="rest_framework") ), - url(r"^api/", include(router.urls, namespace="drf")), + url(r"^api/", include((router.urls, 'drf'), namespace="drf")), # File downloads url( diff --git a/src/paperless/version.py b/src/paperless/version.py index fc2d6561c..0fbece706 100644 --- a/src/paperless/version.py +++ b/src/paperless/version.py @@ -1 +1 @@ -__version__ = (2, 1, 0) +__version__ = (2, 2, 1) diff --git a/src/reminders/models.py b/src/reminders/models.py index d6fb744f7..77d872afb 100644 --- a/src/reminders/models.py +++ b/src/reminders/models.py @@ -3,6 +3,8 @@ from django.db import models class Reminder(models.Model): - document = models.ForeignKey("documents.Document") + document = models.ForeignKey( + "documents.Document", on_delete=models.PROTECT + ) date = models.DateTimeField() note = models.TextField(blank=True)