diff --git a/CHANGES b/CHANGES index 484d1e6..d23d285 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +Release 0.5.2 +------------- +* Add docx table renderer option +* Update django and pyyaml requirements for security patches + Release 0.5.1 ------------- * Update retrieve method to handle export rendering diff --git a/Pipfile b/Pipfile index 55ada50..9bf4f98 100644 --- a/Pipfile +++ b/Pipfile @@ -4,11 +4,11 @@ verify_ssl = true name = "pypi" [packages] -tablib = "*" +tablib = ">=0.13" djangorestframework = "*" -django = "*" +django = ">=2.1.6" "psycopg2-binary" = "*" -openpyxl = "<2.5" # https://github.com/kennethreitz/tablib/issues/331 +openpyxl = "*" reportlab = "*" djangorestframework-csv = "*" python-docx = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 58f4bd6..f6a59b5 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "1880fffec71c206cb723cf13d180f044e453dc9202941ac136634fa8fe2a1d42" + "sha256": "1cbbfead8eaee3738cae5b0a9809e8f1560aeb477d0fddc4a4eb3986b87ee978" }, "pipfile-spec": 6, "requires": { @@ -16,6 +16,13 @@ ] }, "default": { + "backports.csv": { + "hashes": [ + "sha256:1277dfff73130b2e106bf3dd347adb3c5f6c4340882289d88f31240da92cbd6d", + "sha256:21f6e09bab589e6c1f877edbc40277b65e626262a86e69a70137db714eaac5ce" + ], + "version": "==1.0.7" + }, "defusedxml": { "hashes": [ "sha256:24d7f2f94f7f3cb6061acb215685e5125fbcdc40a857eff9de22518820b0a4f4", @@ -25,19 +32,19 @@ }, "django": { "hashes": [ - "sha256:a32c22af23634e1d11425574dce756098e015a165be02e4690179889b207c7a8", - "sha256:d6393918da830530a9516bbbcbf7f1214c3d733738779f06b0f649f49cc698c3" + "sha256:275bec66fd2588dd517ada59b8bfb23d4a9abc5a362349139ddda3c7ff6f5ade", + "sha256:939652e9d34d7d53d74d5d8ef82a19e5f8bb2de75618f7e5360691b6e9667963" ], "index": "pypi", - "version": "==2.1.5" + "version": "==2.1.7" }, "djangorestframework": { "hashes": [ - "sha256:79c6efbb2514bc50cf25906d7c0a5cfead714c7af667ff4bd110312cd380ae66", - "sha256:a4138613b67e3a223be6c97f53b13d759c5b90d2b433bad670b8ebf95402075f" + "sha256:8a435df9007c8b7d8e69a21ef06650e3c0cbe0d4b09e55dd1bd74c89a75a9fcd", + "sha256:f7a266260d656e1cf4ca54d7a7349609dc8af4fe2590edd0ecd7d7643ea94a17" ], "index": "pypi", - "version": "==3.9.1" + "version": "==3.9.2" }, "djangorestframework-csv": { "hashes": [ @@ -61,34 +68,34 @@ }, "lxml": { "hashes": [ - "sha256:0dd6589fa75d369ba06d2b5f38dae107f76ea127f212f6a7bee134f6df2d1d21", - "sha256:1afbac344aa68c29e81ab56c1a9411c3663157b5aee5065b7fa030b398d4f7e0", - "sha256:1baad9d073692421ad5dbbd81430aba6c7f5fdc347f03537ae046ddf2c9b2297", - "sha256:1d8736421a2358becd3edf20260e41a06a0bf08a560480d3a5734a6bcbacf591", - "sha256:1e1d9bddc5afaddf0de76246d3f2152f961697ad7439c559f179002682c45801", - "sha256:1f179dc8b2643715f020f4d119d5529b02cd794c1c8f305868b73b8674d2a03f", - "sha256:241fb7bdf97cb1df1edfa8f0bcdfd80525d4023dac4523a241907c8b2f44e541", - "sha256:2f9765ee5acd3dbdcdc0d0c79309e01f7c16bc8d39b49250bf88de7b46daaf58", - "sha256:312e1e1b1c3ce0c67e0b8105317323e12807955e8186872affb667dbd67971f6", - "sha256:3273db1a8055ca70257fd3691c6d2c216544e1a70b673543e15cc077d8e9c730", - "sha256:34dfaa8c02891f9a246b17a732ca3e99c5e42802416628e740a5d1cb2f50ff49", - "sha256:3aa3f5288af349a0f3a96448ebf2e57e17332d99f4f30b02093b7948bd9f94cc", - "sha256:51102e160b9d83c1cc435162d90b8e3c8c93b28d18d87b60c56522d332d26879", - "sha256:56115fc2e2a4140e8994eb9585119a1ae9223b506826089a3ba753a62bd194a6", - "sha256:69d83de14dbe8fe51dccfd36f88bf0b40f5debeac763edf9f8325180190eba6e", - "sha256:99fdce94aeaa3ccbdfcb1e23b34273605c5853aa92ec23d84c84765178662c6c", - "sha256:a7c0cd5b8a20f3093ee4a67374ccb3b8a126743b15a4d759e2a1bf098faac2b2", - "sha256:abe12886554634ed95416a46701a917784cb2b4c77bfacac6916681d49bbf83d", - "sha256:b4f67b5183bd5f9bafaeb76ad119e977ba570d2b0e61202f534ac9b5c33b4485", - "sha256:bdd7c1658475cc1b867b36d5c4ed4bc316be8d3368abe03d348ba906a1f83b0e", - "sha256:c6f24149a19f611a415a51b9bc5f17b6c2f698e0d6b41ffb3fa9f24d35d05d73", - "sha256:d1e111b3ab98613115a208c1017f266478b0ab224a67bc8eac670fa0bad7d488", - "sha256:d6520aa965773bbab6cb7a791d5895b00d02cf9adc93ac2bf4edb9ac1a6addc5", - "sha256:dd185cde2ccad7b649593b0cda72021bc8a91667417001dbaf24cd746ecb7c11", - "sha256:de2e5b0828a9d285f909b5d2e9d43f1cf6cf21fe65bc7660bdaa1780c7b58298", - "sha256:f726444b8e909c4f41b4fde416e1071cf28fa84634bfb4befdf400933b6463af" - ], - "version": "==4.3.0" + "sha256:0358b9e9642bc7d39aac5cffe9884a99a5ca68e5e2c1b89e570ed60da9139908", + "sha256:091a359c4dafebbecd3959d9013f1b896b5371859165e4e50b01607a98d9e3e2", + "sha256:1998e4e60603c64bcc35af61b4331ab3af087457900d3980e18d190e17c3a697", + "sha256:2000b4088dee9a41f459fddaf6609bba48a435ce6374bb254c5ccdaa8928c5ba", + "sha256:2afb0064780d8aaf165875be5898c1866766e56175714fa5f9d055433e92d41d", + "sha256:2d8f1d9334a4e3ff176d096c14ded3100547d73440683567d85b8842a53180bb", + "sha256:2e38db22f6a3199fd63675e1b4bd795d676d906869047398f29f38ca55cb453a", + "sha256:3181f84649c1a1ca62b19ddf28436b1b2cb05ae6c7d2628f33872e713994c364", + "sha256:37462170dfd88af8431d04de6b236e6e9c06cda71e2ca26d88ef2332fd2a5237", + "sha256:3a9d8521c89bf6f2a929c3d12ad3ad7392c774c327ea809fd08a13be6b3bc05f", + "sha256:3d0bbd2e1a28b4429f24fd63a122a450ce9edb7a8063d070790092d7343a1aa4", + "sha256:483d60585ce3ee71929cea70949059f83850fa5e12deb9c094ed1c8c2ec73cbd", + "sha256:4888be27d5cba55ce94209baef5bcd7bbd7314a3d17021a5fc10000b3a5f737d", + "sha256:64b0d62e4209170a2a0c404c446ab83b941a0003e96604d2e4f4cb735f8a2254", + "sha256:68010900898fdf139ac08549c4dba8206c584070a960ffc530aebf0c6f2794ef", + "sha256:872ecb066de602a0099db98bd9e57f4cfc1d62f6093d94460c787737aa08f39e", + "sha256:88a32b03f2e4cd0e63f154cac76724709f40b3fc2f30139eb5d6f900521b44ed", + "sha256:b1dc7683da4e67ab2bebf266afa68098d681ae02ce570f0d1117312273d2b2ac", + "sha256:b29e27ce9371810250cb1528a771d047a9c7b0f79630dc7dc5815ff828f4273b", + "sha256:ce197559596370d985f1ce6b7051b52126849d8159040293bf8b98cb2b3e1f78", + "sha256:d45cf6daaf22584eff2175f48f82c4aa24d8e72a44913c5aff801819bb73d11f", + "sha256:e2ff9496322b2ce947ba4a7a5eb048158de9d6f3fe9efce29f1e8dd6878561e6", + "sha256:f7b979518ec1f294a41a707c007d54d0f3b3e1fd15d5b26b7e99b62b10d9a72e", + "sha256:f9c7268e9d16e34e50f8246c4f24cf7353764affd2bc971f0379514c246e3f6b", + "sha256:f9c839806089d79de588ee1dde2dae05dc1156d3355dfeb2b51fde84d9c960ad", + "sha256:ff962953e2389226adc4d355e34a98b0b800984399153c6678f2367b11b4d4b8" + ], + "version": "==4.3.2" }, "odfpy": { "hashes": [ @@ -98,10 +105,10 @@ }, "openpyxl": { "hashes": [ - "sha256:626d38647c063d55803ef4971c4d43226538d4e95cb6260c094e363ee33e10c7" + "sha256:9e4db4ee7aadd0ff7a814f7483b2d94e6b8d4f14dff780b023c5bdc94af54dd5" ], "index": "pypi", - "version": "==2.4.11" + "version": "==2.6.1" }, "pillow": { "hashes": [ @@ -190,19 +197,19 @@ }, "pyyaml": { "hashes": [ - "sha256:3d7da3009c0f3e783b2c873687652d83b1bbfd5c88e9813fb7e5b03c0dd3108b", - "sha256:3ef3092145e9b70e3ddd2c7ad59bdd0252a94dfe3949721633e41344de00a6bf", - "sha256:40c71b8e076d0550b2e6380bada1f1cd1017b882f7e16f09a65be98e017f211a", - "sha256:558dd60b890ba8fd982e05941927a3911dc409a63dcb8b634feaa0cda69330d3", - "sha256:a7c28b45d9f99102fa092bb213aa12e0aaf9a6a1f5e395d36166639c1f96c3a1", - "sha256:aa7dd4a6a427aed7df6fb7f08a580d68d9b118d90310374716ae90b710280af1", - "sha256:bc558586e6045763782014934bfaf39d48b8ae85a2713117d16c39864085c613", - "sha256:d46d7982b62e0729ad0175a9bc7e10a566fc07b224d2c79fafb5e032727eaa04", - "sha256:d5eef459e30b09f5a098b9cea68bebfeb268697f78d647bd255a085371ac7f3f", - "sha256:e01d3203230e1786cd91ccfdc8f8454c8069c91bee3962ad93b87a4b2860f537", - "sha256:e170a9e6fcfd19021dd29845af83bb79236068bf5fd4df3327c1be18182b2531" + "sha256:1adecc22f88d38052fb787d959f003811ca858b799590a5eaa70e63dca50308c", + "sha256:436bc774ecf7c103814098159fbb84c2715d25980175292c648f2da143909f95", + "sha256:460a5a4248763f6f37ea225d19d5c205677d8d525f6a83357ca622ed541830c2", + "sha256:5a22a9c84653debfbf198d02fe592c176ea548cccce47553f35f466e15cf2fd4", + "sha256:7a5d3f26b89d688db27822343dfa25c599627bc92093e788956372285c6298ad", + "sha256:9372b04a02080752d9e6f990179a4ab840227c6e2ce15b95e1278456664cf2ba", + "sha256:a5dcbebee834eaddf3fa7366316b880ff4062e4bcc9787b78c7fbb4a26ff2dd1", + "sha256:aee5bab92a176e7cd034e57f46e9df9a9862a71f8f37cad167c6fc74c65f5b4e", + "sha256:c51f642898c0bacd335fc119da60baae0824f2cde95b0330b56c0553439f0673", + "sha256:c68ea4d3ba1705da1e0d85da6684ac657912679a649e8868bd850d2c299cce13", + "sha256:e23d0cc5299223dcc37885dae624f382297717e459ea24053709675a976a3e19" ], - "version": "==3.13" + "version": "==5.1" }, "reportlab": { "hashes": [ @@ -247,10 +254,11 @@ }, "tablib": { "hashes": [ - "sha256:b8cf50a61d66655229993f2ee29220553fb2c80403479f8e6de77c0c24649d87" + "sha256:0f88a9cebdaa1a2cc29ae57387082ee81015d1149ecd34e48a8c8d3b4dd21670", + "sha256:5f33c079b07eb10cf9c4b4696add2ecf32c89db7729240546ecdcd5c92f67e13" ], "index": "pypi", - "version": "==0.12.1" + "version": "==0.13.0" }, "unicodecsv": { "hashes": [ @@ -276,53 +284,60 @@ "develop": { "atomicwrites": { "hashes": [ - "sha256:0312ad34fcad8fac3704d441f7b317e50af620823353ec657a53e981f92920c0", - "sha256:ec9ae8adaae229e4f8446952d204a3e4b5fdd2d099f9be3aaf556120135fb3ee" + "sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", + "sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6" ], - "version": "==1.2.1" + "version": "==1.3.0" }, "attrs": { "hashes": [ - "sha256:10cbf6e27dbce8c30807caf056c8eb50917e0eaafe86347671b57254006c3e69", - "sha256:ca4be454458f9dec299268d472aaa5a11f67a4ff70093396e1ceae9c76cf4bbb" + "sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79", + "sha256:f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399" ], - "version": "==18.2.0" + "version": "==19.1.0" }, "coverage": { "hashes": [ - "sha256:09e47c529ff77bf042ecfe858fb55c3e3eb97aac2c87f0349ab5a7efd6b3939f", - "sha256:0a1f9b0eb3aa15c990c328535655847b3420231af299386cfe5efc98f9c250fe", - "sha256:0cc941b37b8c2ececfed341444a456912e740ecf515d560de58b9a76562d966d", - "sha256:10e8af18d1315de936d67775d3a814cc81d0747a1a0312d84e27ae5610e313b0", - "sha256:1b4276550b86caa60606bd3572b52769860a81a70754a54acc8ba789ce74d607", - "sha256:1e8a2627c48266c7b813975335cfdea58c706fe36f607c97d9392e61502dc79d", - "sha256:2b224052bfd801beb7478b03e8a66f3f25ea56ea488922e98903914ac9ac930b", - "sha256:447c450a093766744ab53bf1e7063ec82866f27bcb4f4c907da25ad293bba7e3", - "sha256:46101fc20c6f6568561cdd15a54018bb42980954b79aa46da8ae6f008066a30e", - "sha256:4710dc676bb4b779c4361b54eb308bc84d64a2fa3d78e5f7228921eccce5d815", - "sha256:510986f9a280cd05189b42eee2b69fecdf5bf9651d4cd315ea21d24a964a3c36", - "sha256:5535dda5739257effef56e49a1c51c71f1d37a6e5607bb25a5eee507c59580d1", - "sha256:5a7524042014642b39b1fcae85fb37556c200e64ec90824ae9ecf7b667ccfc14", - "sha256:5f55028169ef85e1fa8e4b8b1b91c0b3b0fa3297c4fb22990d46ff01d22c2d6c", - "sha256:6694d5573e7790a0e8d3d177d7a416ca5f5c150742ee703f3c18df76260de794", - "sha256:6831e1ac20ac52634da606b658b0b2712d26984999c9d93f0c6e59fe62ca741b", - "sha256:77f0d9fa5e10d03aa4528436e33423bfa3718b86c646615f04616294c935f840", - "sha256:828ad813c7cdc2e71dcf141912c685bfe4b548c0e6d9540db6418b807c345ddd", - "sha256:85a06c61598b14b015d4df233d249cd5abfa61084ef5b9f64a48e997fd829a82", - "sha256:8cb4febad0f0b26c6f62e1628f2053954ad2c555d67660f28dfb1b0496711952", - "sha256:a5c58664b23b248b16b96253880b2868fb34358911400a7ba39d7f6399935389", - "sha256:aaa0f296e503cda4bc07566f592cd7a28779d433f3a23c48082af425d6d5a78f", - "sha256:ab235d9fe64833f12d1334d29b558aacedfbca2356dfb9691f2d0d38a8a7bfb4", - "sha256:b3b0c8f660fae65eac74fbf003f3103769b90012ae7a460863010539bb7a80da", - "sha256:bab8e6d510d2ea0f1d14f12642e3f35cefa47a9b2e4c7cea1852b52bc9c49647", - "sha256:c45297bbdbc8bb79b02cf41417d63352b70bcb76f1bbb1ee7d47b3e89e42f95d", - "sha256:d19bca47c8a01b92640c614a9147b081a1974f69168ecd494687c827109e8f42", - "sha256:d64b4340a0c488a9e79b66ec9f9d77d02b99b772c8b8afd46c1294c1d39ca478", - "sha256:da969da069a82bbb5300b59161d8d7c8d423bc4ccd3b410a9b4d8932aeefc14b", - "sha256:ed02c7539705696ecb7dc9d476d861f3904a8d2b7e894bd418994920935d36bb", - "sha256:ee5b8abc35b549012e03a7b1e86c09491457dba6c94112a2482b18589cc2bdb9" - ], - "version": "==4.5.2" + "sha256:3684fabf6b87a369017756b551cef29e505cb155ddb892a7a29277b978da88b9", + "sha256:39e088da9b284f1bd17c750ac672103779f7954ce6125fd4382134ac8d152d74", + "sha256:3c205bc11cc4fcc57b761c2da73b9b72a59f8d5ca89979afb0c1c6f9e53c7390", + "sha256:465ce53a8c0f3a7950dfb836438442f833cf6663d407f37d8c52fe7b6e56d7e8", + "sha256:48020e343fc40f72a442c8a1334284620f81295256a6b6ca6d8aa1350c763bbe", + "sha256:5296fc86ab612ec12394565c500b412a43b328b3907c0d14358950d06fd83baf", + "sha256:5f61bed2f7d9b6a9ab935150a6b23d7f84b8055524e7be7715b6513f3328138e", + "sha256:68a43a9f9f83693ce0414d17e019daee7ab3f7113a70c79a3dd4c2f704e4d741", + "sha256:6b8033d47fe22506856fe450470ccb1d8ba1ffb8463494a15cfc96392a288c09", + "sha256:7ad7536066b28863e5835e8cfeaa794b7fe352d99a8cded9f43d1161be8e9fbd", + "sha256:7bacb89ccf4bedb30b277e96e4cc68cd1369ca6841bde7b005191b54d3dd1034", + "sha256:839dc7c36501254e14331bcb98b27002aa415e4af7ea039d9009409b9d2d5420", + "sha256:8f9a95b66969cdea53ec992ecea5406c5bd99c9221f539bca1e8406b200ae98c", + "sha256:932c03d2d565f75961ba1d3cec41ddde00e162c5b46d03f7423edcb807734eab", + "sha256:988529edadc49039d205e0aa6ce049c5ccda4acb2d6c3c5c550c17e8c02c05ba", + "sha256:998d7e73548fe395eeb294495a04d38942edb66d1fa61eb70418871bc621227e", + "sha256:9de60893fb447d1e797f6bf08fdf0dbcda0c1e34c1b06c92bd3a363c0ea8c609", + "sha256:9e80d45d0c7fcee54e22771db7f1b0b126fb4a6c0a2e5afa72f66827207ff2f2", + "sha256:a545a3dfe5082dc8e8c3eb7f8a2cf4f2870902ff1860bd99b6198cfd1f9d1f49", + "sha256:a5d8f29e5ec661143621a8f4de51adfb300d7a476224156a39a392254f70687b", + "sha256:aca06bfba4759bbdb09bf52ebb15ae20268ee1f6747417837926fae990ebc41d", + "sha256:bb23b7a6fd666e551a3094ab896a57809e010059540ad20acbeec03a154224ce", + "sha256:bfd1d0ae7e292105f29d7deaa9d8f2916ed8553ab9d5f39ec65bcf5deadff3f9", + "sha256:c62ca0a38958f541a73cf86acdab020c2091631c137bd359c4f5bddde7b75fd4", + "sha256:c709d8bda72cf4cd348ccec2a4881f2c5848fd72903c185f363d361b2737f773", + "sha256:c968a6aa7e0b56ecbd28531ddf439c2ec103610d3e2bf3b75b813304f8cb7723", + "sha256:df785d8cb80539d0b55fd47183264b7002077859028dfe3070cf6359bf8b2d9c", + "sha256:f406628ca51e0ae90ae76ea8398677a921b36f0bd71aab2099dfed08abd0322f", + "sha256:f46087bbd95ebae244a0eda01a618aff11ec7a069b15a3ef8f6b520db523dcf1", + "sha256:f8019c5279eb32360ca03e9fac40a12667715546eed5c5eb59eb381f2f501260", + "sha256:fc5f4d209733750afd2714e9109816a29500718b32dd9a5db01c0cb3a019b96a" + ], + "version": "==4.5.3" + }, + "entrypoints": { + "hashes": [ + "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19", + "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451" + ], + "version": "==0.3" }, "factory-boy": { "hashes": [ @@ -334,10 +349,10 @@ }, "faker": { "hashes": [ - "sha256:16342dca4d92bfc83bab6a7daf6650e0ab087605a66bc38f17523fdb01757910", - "sha256:d871ea315b2dcba9138b8344f2c131a76ac62d6227ca39f69b0c889fec97376c" + "sha256:00b7011757c4907546f17d0e47df098b542ea2b04c966ee0e80a493aae2c13c8", + "sha256:745ac8b9c9526e338696e07b7f2e206e5e317e5744e22fdd7c2894bf19af41f1" ], - "version": "==1.0.2" + "version": "==1.0.4" }, "filelock": { "hashes": [ @@ -348,20 +363,19 @@ }, "flake8": { "hashes": [ - "sha256:6a35f5b8761f45c5513e3405f110a86bea57982c3b75b766ce7b65217abe1670", - "sha256:c01f8a3963b3571a8e6bd7a4063359aff90749e160778e03817cd9b71c9e07d2" + "sha256:859996073f341f2670741b51ec1e67a01da142831aa1fdc6242dbf88dffbe661", + "sha256:a796a115208f5c03b18f332f7c11729812c8c3ded6c46319c59b53efd3819da8" ], "index": "pypi", - "version": "==3.6.0" + "version": "==3.7.7" }, "isort": { "hashes": [ - "sha256:1153601da39a25b14ddc54955dbbacbb6b2d19135386699e2ad58517953b34af", - "sha256:b9c40e9750f3d77e6e4d441d8b0266cf555e7cdabdcff33c4fd06366ca761ef8", - "sha256:ec9ef8f4a9bc6f71eec99e1806bfa2de401650d996c59330782b89a5555c1497" + "sha256:18c796c2cd35eb1a1d3f012a214a542790a1aed95e29768bdcb9f2197eccbd0b", + "sha256:96151fca2c6e736503981896495d344781b60d18bfda78dc11b290c6125ebdb6" ], "index": "pypi", - "version": "==4.3.4" + "version": "==4.3.15" }, "mccabe": { "hashes": [ @@ -372,47 +386,47 @@ }, "more-itertools": { "hashes": [ - "sha256:38a936c0a6d98a38bcc2d03fdaaedaba9f412879461dd2ceff8d37564d6522e4", - "sha256:c0a5785b1109a6bd7fac76d6837fd1feca158e54e521ccd2ae8bfe393cc9d4fc", - "sha256:fe7a7cae1ccb57d33952113ff4fa1bc5f879963600ed74918f1236e212ee50b9" + "sha256:0125e8f60e9e031347105eb1682cef932f5e97d7b9a1a28d9bf00c22a5daef40", + "sha256:590044e3942351a1bdb1de960b739ff4ce277960f2425ad4509446dbace8d9d1" ], - "version": "==5.0.0" + "markers": "python_version > '2.7'", + "version": "==6.0.0" }, "pluggy": { "hashes": [ - "sha256:8ddc32f03971bfdf900a81961a48ccf2fb677cf7715108f85295c67405798616", - "sha256:980710797ff6a041e9a73a5787804f848996ecaa6f8a1b1e08224a5894f2074a" + "sha256:19ecf9ce9db2fce065a7a0586e07cfb4ac8614fe96edf628a264b1c70116cf8f", + "sha256:84d306a647cc805219916e62aab89caa97a33a1dd8c342e87a37f91073cd4746" ], - "version": "==0.8.1" + "version": "==0.9.0" }, "py": { "hashes": [ - "sha256:bf92637198836372b520efcba9e020c330123be8ce527e535d185ed4b6f45694", - "sha256:e76826342cefe3c3d5f7e8ee4316b80d1dd8a300781612ddbc765c17ba25a6c6" + "sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa", + "sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53" ], - "version": "==1.7.0" + "version": "==1.8.0" }, "pycodestyle": { "hashes": [ - "sha256:cbc619d09254895b0d12c2c691e237b2e91e9b2ecf5e84c26b35400f93dcfb83", - "sha256:cbfca99bd594a10f674d0cd97a3d802a1fdef635d4361e1a2658de47ed261e3a" + "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", + "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c" ], - "version": "==2.4.0" + "version": "==2.5.0" }, "pyflakes": { "hashes": [ - "sha256:9a7662ec724d0120012f6e29d6248ae3727d821bba522a0e6b356eff19126a49", - "sha256:f661252913bc1dbe7fcfcbf0af0db3f42ab65aabd1a6ca68fe5d466bace94dae" + "sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0", + "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2" ], - "version": "==2.0.0" + "version": "==2.1.1" }, "pytest": { "hashes": [ - "sha256:41568ea7ecb4a68d7f63837cf65b92ce8d0105e43196ff2b26622995bb3dc4b2", - "sha256:c3c573a29d7c9547fb90217ece8a8843aa0c1328a797e200290dc3d0b4b823be" + "sha256:592eaa2c33fae68c7d75aacf042efc9f77b27c08a6224a4f59beab8d9a420523", + "sha256:ad3ad5c450284819ecde191a654c09b0ec72257a2c711b9633d677c71c9850c4" ], "index": "pypi", - "version": "==4.1.1" + "version": "==4.3.1" }, "pytest-cov": { "hashes": [ @@ -424,11 +438,11 @@ }, "pytest-django": { "hashes": [ - "sha256:1a5d33be930e3172fa238643a380414dc369fe8fa4b3c3de25e59ed142950736", - "sha256:e88e471d3d0f9acfb6293bb03d0ee8a33ed978734e92ea6b5312163a6c9e87cc" + "sha256:30d773f1768e8f214a3106f1090e00300ce6edfcac8c55fd13b675fe1cbd1c85", + "sha256:4d3283e774fe1d40630ee58bf34929b83875e4751b525eeb07a7506996eb42ee" ], "index": "pypi", - "version": "==3.4.5" + "version": "==3.4.8" }, "pytest-echo": { "hashes": [ @@ -446,10 +460,10 @@ }, "python-dateutil": { "hashes": [ - "sha256:063df5763652e21de43de7d9e00ccf239f953a832941e37be541614732cdfc93", - "sha256:88f9287c0174266bb0d8cedd395cfba9c58e87e5ad86b2ce58859bc11be3cf02" + "sha256:7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb", + "sha256:c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e" ], - "version": "==2.7.5" + "version": "==2.8.0" }, "six": { "hashes": [ @@ -482,10 +496,10 @@ }, "virtualenv": { "hashes": [ - "sha256:34b9ae3742abed2f95d3970acf4d80533261d6061b51160b197f84e5b4c98b4c", - "sha256:fa736831a7b18bd2bfeef746beb622a92509e9733d645952da136b0639cd40cd" + "sha256:6aebaf4dd2568a0094225ebbca987859e369e3e5c22dc7d52e5406d504890417", + "sha256:984d7e607b0a5d1329425dd8845bd971b957424b5ba664729fab51ab8c11bc39" ], - "version": "==16.2.0" + "version": "==16.4.3" } } } diff --git a/setup.cfg b/setup.cfg index b5e404c..ae06470 100644 --- a/setup.cfg +++ b/setup.cfg @@ -2,7 +2,7 @@ combine_as_imports = true default_section = THIRDPARTY include_trailing_comma = true -known_first_party = unicef_rest_export +known_first_party = unicef_rest_export,tests multi_line_output = 0 line_length=120 balanced_wrapping = true diff --git a/src/requirements/install.pip b/src/requirements/install.pip index 05f7c76..45f12f1 100644 --- a/src/requirements/install.pip +++ b/src/requirements/install.pip @@ -1,3 +1,4 @@ +backports.csv defusedxml django djangorestframework-csv diff --git a/src/requirements/testing.pip b/src/requirements/testing.pip index 1942687..dac37cd 100644 --- a/src/requirements/testing.pip +++ b/src/requirements/testing.pip @@ -1,6 +1,7 @@ atomicwrites attrs coverage +entrypoints factory-boy faker filelock diff --git a/src/unicef_rest_export/__init__.py b/src/unicef_rest_export/__init__.py index 16ef2ff..bea0191 100644 --- a/src/unicef_rest_export/__init__.py +++ b/src/unicef_rest_export/__init__.py @@ -1,3 +1,3 @@ NAME = 'unicef_rest_export' -VERSION = __version__ = "0.5.1" +VERSION = __version__ = "0.5.2" __author__ = 'UNICEF' diff --git a/src/unicef_rest_export/renderers.py b/src/unicef_rest_export/renderers.py index 41d1981..fd91fcc 100644 --- a/src/unicef_rest_export/renderers.py +++ b/src/unicef_rest_export/renderers.py @@ -277,9 +277,12 @@ def render_dataset(self, data, *args, **kwargs): fp.write(self.export_set(formatted)) -class ExportDocxRenderer(ExportFileRenderer): - """Renders dataset as Doc (.docx)""" +class ExportDocxBaseRenderer(ExportFileRenderer): media_type = "application/vnd.openxmlformats-officedocument.wordprocessingml.document" + + +class ExportDocxRenderer(ExportDocxBaseRenderer): + """Renders dataset as Doc (.docx)""" format = "docx" def export_set(self, formatted): @@ -303,6 +306,40 @@ def render_dataset(self, data, *args, **kwargs): fp.write(self.export_set(formatted)) +class ExportDocxTableRenderer(ExportDocxBaseRenderer): + """Renders dataset as Doc (.docx) in table format""" + format = "docx_table" + + def export_set(self, formatted, headers): + stream = BytesIO() + doc = Document() + + if not headers: + doc.add_paragraph("No data provided.") + else: + table = doc.add_table(rows=1, cols=len(headers)) + + # set heading text + header_cells = table.rows[0].cells + for i, heading in enumerate(headers): + header_cells[i].text = heading + + # set data + for record in formatted: + row = table.add_row().cells + for i, data in enumerate(record): + row[i].text = str(data) + + doc.save(stream) + return stream.getvalue() + + def render_dataset(self, data, *args, **kwargs): + formatted = data._package() + headers = data.headers + with open(self.filename, "wb") as fp: + fp.write(self.export_set(formatted, headers)) + + class FriendlyCSVRenderer(CSVRenderer): def flatten_item(self, item): if isinstance(item, bool): diff --git a/src/unicef_rest_export/views.py b/src/unicef_rest_export/views.py index bacdf16..5d68c7c 100644 --- a/src/unicef_rest_export/views.py +++ b/src/unicef_rest_export/views.py @@ -20,6 +20,7 @@ "unicef_rest_export.renderers.ExportPDFRenderer", "unicef_rest_export.renderers.ExportPDFTableRenderer", "unicef_rest_export.renderers.ExportDocxRenderer", + "unicef_rest_export.renderers.ExportDocxTableRenderer", ) if "unicef_rest_export" in settings.INSTALLED_APPS: DEFAULT_TEMPLATE = True diff --git a/tests/conftest.py b/tests/conftest.py index cb2b1ae..3998e3a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,5 +1,6 @@ import pytest from rest_framework.test import APIClient + from tests import factories diff --git a/tests/test_renderers.py b/tests/test_renderers.py index 12fb2b1..516fb96 100644 --- a/tests/test_renderers.py +++ b/tests/test_renderers.py @@ -2,6 +2,7 @@ from django.urls import reverse from rest_framework.test import APIClient from tablib import Dataset + from tests.factories import BookFactory, UserFactory diff --git a/tests/test_views.py b/tests/test_views.py index 43bb1cf..55d0f8a 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -3,6 +3,7 @@ from django.urls import reverse from rest_framework.test import APIClient from tablib import Dataset + from tests.factories import BookFactory, UserFactory pytestmark = pytest.mark.django_db @@ -134,6 +135,12 @@ def test_export_view_list_docx_empty(api_client): assert response.status_code == 200 +def test_export_view_list_docx_table_empty(api_client): + url = "{}?format=docx_table".format(reverse("sample:author-view")) + response = api_client.get(url) + assert response.status_code == 200 + + def test_export_view_list_pdf(api_client, author): url = "{}?format=pdf".format(reverse("sample:author-view")) response = api_client.get(url) @@ -168,6 +175,12 @@ def test_export_view_list_docx(api_client, author): assert response.status_code == 200 +def test_export_view_list_docx_table(api_client, author): + url = "{}?format=docx_table".format(reverse("sample:author-view")) + response = api_client.get(url) + assert response.status_code == 200 + + def test_export_view_retrieve_docx(api_client, book): url = "{}?format=docx".format( reverse("sample:book-detail", args=[book.pk]) @@ -176,6 +189,14 @@ def test_export_view_retrieve_docx(api_client, book): assert response.status_code == 200 +def test_export_view_retrieve_docx_table(api_client, book): + url = "{}?format=docx_table".format( + reverse("sample:book-detail", args=[book.pk]) + ) + response = api_client.get(url) + assert response.status_code == 200 + + def test_export_view_list_invalid_format(api_client, author): url = "{}?format=wrong".format(reverse("sample:author-view")) response = api_client.get(url) @@ -241,6 +262,14 @@ def test_export_view_foreignkey_list_docx(api_client, book): assert response.status_code == 200 +def test_export_view_foreignkey_list_docx_table(api_client, book): + url = "{}?format=docx_table".format(reverse("sample:book-view")) + response = api_client.get(url) + with open("/tmp/file.docx", "wb") as fp: + fp.write(response.content) + assert response.status_code == 200 + + def test_export_view_list_pdf_text_blob(api_client): BookFactory(description=factory.Faker("sentence", nb_words=800)) url = "{}?format=pdf".format(reverse("sample:book-view")) @@ -262,6 +291,13 @@ def test_export_view_list_docx_text_blob(api_client): assert response.status_code == 200 +def test_export_view_list_docx_table_text_blob(api_client): + BookFactory(description=factory.Faker("sentence", nb_words=800)) + url = "{}?format=docx_table".format(reverse("sample:book-view")) + response = api_client.get(url) + assert response.status_code == 200 + + def test_export_view_list_transform_json(api_client, book): url = "{}?format=json".format(reverse("sample:author-transform")) response = api_client.get(url) @@ -310,6 +346,12 @@ def test_export_view_list_transform_docx(api_client, book): assert response.status_code == 200 +def test_export_view_list_transform_docx_table(api_client, book): + url = "{}?format=docx_table".format(reverse("sample:author-transform")) + response = api_client.get(url) + assert response.status_code == 200 + + def test_export_view_list_invalid(api_client, author): """If list serializer extends ListSerializer instead of ExportSerializer""" url = "{}?format=json".format(reverse("sample:author-invalid"))