diff --git a/Pipfile b/Pipfile index 634da15..be29ec4 100644 --- a/Pipfile +++ b/Pipfile @@ -8,6 +8,8 @@ logzero = "*" lxml = "*" python-docx = "*" htmldocx = "*" +html2text = "*" +rich = "*" [dev-packages] diff --git a/Pipfile.lock b/Pipfile.lock index 255b4a3..6861b90 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "c632d0ae9023f9ba1b1cd223ed1f86ee067789909994b00e65aac91579cbaaf6" + "sha256": "0307894f03d442e3d9de912eabf19fe5fcb605628748a5e19a53bded87055f6e" }, "pipfile-spec": 6, "requires": { @@ -18,85 +18,192 @@ "default": { "beautifulsoup4": { "hashes": [ - "sha256:4c98143716ef1cb40bf7f39a8e3eec8f8b009509e74904ba3a7b315431577e35", - "sha256:84729e322ad1d5b4d25f805bfa05b902dd96450f43842c4e99067d5e1369eb25", - "sha256:fff47e031e34ec82bf17e00da8f592fe7de69aeea38be00523c04623c04fb666" + "sha256:492bbc69dca35d12daac71c4db1bfff0c876c00ef4a2ffacce226d4638eb72da", + "sha256:bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a" ], - "version": "==4.9.3" + "markers": "python_full_version >= '3.6.0'", + "version": "==4.12.2" + }, + "html2text": { + "hashes": [ + "sha256:c7c629882da0cf377d66f073329ccf34a12ed2adf0169b9285ae4e63ef54c82b", + "sha256:e296318e16b059ddb97f7a8a1d6a5c1d7af4544049a01e261731d2d5cc277bbb" + ], + "index": "pypi", + "markers": "python_version >= '3.5'", + "version": "==2020.1.16" }, "htmldocx": { "hashes": [ - "sha256:959408f72ed0298606a7d14e12f8959e98b71e8a3ddb680f516b8608cad7e1ca", - "sha256:dc458c1dbab38833a90d496b039f599131172406eeb51010948029b4119a9505" + "sha256:adf5e95ad8ba8121e606cf138c614de13327a1192a5782acdb4a0abdc23db1b7", + "sha256:b4bcec895f86d7a50ffc7133ca24d85c24f3614db2b37d33a30d9d04654a5486" ], "index": "pypi", - "version": "==0.0.4" + "markers": "python_version >= '3.6'", + "version": "==0.0.6" }, "logzero": { "hashes": [ - "sha256:1435284574e409b8ec8b680f276bca04cab41f93d6eff4dc8348b7630cddf560", - "sha256:1b84ee4c8fdabf7023877ff17cb456d82564097704eb6c4ee37952bd8ce0800f" + "sha256:23eb1f717a2736f9ab91ca0d43160fd2c996ad49ae6bad34652d47aba908769d", + "sha256:7f73ddd3ae393457236f081ffebd044a3aa2e423a47ae6ddb5179ab90d0ad082" ], "index": "pypi", - "version": "==1.6.3" + "version": "==1.7.0" }, "lxml": { "hashes": [ - "sha256:0448576c148c129594d890265b1a83b9cd76fd1f0a6a04620753d9a6bcfd0a4d", - "sha256:127f76864468d6630e1b453d3ffbbd04b024c674f55cf0a30dc2595137892d37", - "sha256:1471cee35eba321827d7d53d104e7b8c593ea3ad376aa2df89533ce8e1b24a01", - "sha256:2363c35637d2d9d6f26f60a208819e7eafc4305ce39dc1d5005eccc4593331c2", - "sha256:2e5cc908fe43fe1aa299e58046ad66981131a66aea3129aac7770c37f590a644", - "sha256:2e6fd1b8acd005bd71e6c94f30c055594bbd0aa02ef51a22bbfa961ab63b2d75", - "sha256:366cb750140f221523fa062d641393092813b81e15d0e25d9f7c6025f910ee80", - "sha256:42ebca24ba2a21065fb546f3e6bd0c58c3fe9ac298f3a320147029a4850f51a2", - "sha256:4e751e77006da34643ab782e4a5cc21ea7b755551db202bc4d3a423b307db780", - "sha256:4fb85c447e288df535b17ebdebf0ec1cf3a3f1a8eba7e79169f4f37af43c6b98", - "sha256:50c348995b47b5a4e330362cf39fc503b4a43b14a91c34c83b955e1805c8e308", - "sha256:535332fe9d00c3cd455bd3dd7d4bacab86e2d564bdf7606079160fa6251caacf", - "sha256:535f067002b0fd1a4e5296a8f1bf88193080ff992a195e66964ef2a6cfec5388", - "sha256:5be4a2e212bb6aa045e37f7d48e3e1e4b6fd259882ed5a00786f82e8c37ce77d", - "sha256:60a20bfc3bd234d54d49c388950195d23a5583d4108e1a1d47c9eef8d8c042b3", - "sha256:648914abafe67f11be7d93c1a546068f8eff3c5fa938e1f94509e4a5d682b2d8", - "sha256:681d75e1a38a69f1e64ab82fe4b1ed3fd758717bed735fb9aeaa124143f051af", - "sha256:68a5d77e440df94011214b7db907ec8f19e439507a70c958f750c18d88f995d2", - "sha256:69a63f83e88138ab7642d8f61418cf3180a4d8cd13995df87725cb8b893e950e", - "sha256:6e4183800f16f3679076dfa8abf2db3083919d7e30764a069fb66b2b9eff9939", - "sha256:6fd8d5903c2e53f49e99359b063df27fdf7acb89a52b6a12494208bf61345a03", - "sha256:791394449e98243839fa822a637177dd42a95f4883ad3dec2a0ce6ac99fb0a9d", - "sha256:7a7669ff50f41225ca5d6ee0a1ec8413f3a0d8aa2b109f86d540887b7ec0d72a", - "sha256:7e9eac1e526386df7c70ef253b792a0a12dd86d833b1d329e038c7a235dfceb5", - "sha256:7ee8af0b9f7de635c61cdd5b8534b76c52cd03536f29f51151b377f76e214a1a", - "sha256:8246f30ca34dc712ab07e51dc34fea883c00b7ccb0e614651e49da2c49a30711", - "sha256:8c88b599e226994ad4db29d93bc149aa1aff3dc3a4355dd5757569ba78632bdf", - "sha256:923963e989ffbceaa210ac37afc9b906acebe945d2723e9679b643513837b089", - "sha256:94d55bd03d8671686e3f012577d9caa5421a07286dd351dfef64791cf7c6c505", - "sha256:97db258793d193c7b62d4e2586c6ed98d51086e93f9a3af2b2034af01450a74b", - "sha256:a9d6bc8642e2c67db33f1247a77c53476f3a166e09067c0474facb045756087f", - "sha256:cd11c7e8d21af997ee8079037fff88f16fda188a9776eb4b81c7e4c9c0a7d7fc", - "sha256:d8d3d4713f0c28bdc6c806a278d998546e8efc3498949e3ace6e117462ac0a5e", - "sha256:e0bfe9bb028974a481410432dbe1b182e8191d5d40382e5b8ff39cdd2e5c5931", - "sha256:f4822c0660c3754f1a41a655e37cb4dbbc9be3d35b125a37fab6f82d47674ebc", - "sha256:f83d281bb2a6217cd806f4cf0ddded436790e66f393e124dfe9731f6b3fb9afe", - "sha256:fc37870d6716b137e80d19241d0e2cff7a7643b925dfa49b4c8ebd1295eb506e" + "sha256:05186a0f1346ae12553d66df1cfce6f251589fea3ad3da4f3ef4e34b2d58c6a3", + "sha256:075b731ddd9e7f68ad24c635374211376aa05a281673ede86cbe1d1b3455279d", + "sha256:081d32421db5df44c41b7f08a334a090a545c54ba977e47fd7cc2deece78809a", + "sha256:0a3d3487f07c1d7f150894c238299934a2a074ef590b583103a45002035be120", + "sha256:0bfd0767c5c1de2551a120673b72e5d4b628737cb05414f03c3277bf9bed3305", + "sha256:0c0850c8b02c298d3c7006b23e98249515ac57430e16a166873fc47a5d549287", + "sha256:0e2cb47860da1f7e9a5256254b74ae331687b9672dfa780eed355c4c9c3dbd23", + "sha256:120fa9349a24c7043854c53cae8cec227e1f79195a7493e09e0c12e29f918e52", + "sha256:1247694b26342a7bf47c02e513d32225ededd18045264d40758abeb3c838a51f", + "sha256:141f1d1a9b663c679dc524af3ea1773e618907e96075262726c7612c02b149a4", + "sha256:14e019fd83b831b2e61baed40cab76222139926b1fb5ed0e79225bc0cae14584", + "sha256:1509dd12b773c02acd154582088820893109f6ca27ef7291b003d0e81666109f", + "sha256:17a753023436a18e27dd7769e798ce302963c236bc4114ceee5b25c18c52c693", + "sha256:1e224d5755dba2f4a9498e150c43792392ac9b5380aa1b845f98a1618c94eeef", + "sha256:1f447ea5429b54f9582d4b955f5f1985f278ce5cf169f72eea8afd9502973dd5", + "sha256:23eed6d7b1a3336ad92d8e39d4bfe09073c31bfe502f20ca5116b2a334f8ec02", + "sha256:25f32acefac14ef7bd53e4218fe93b804ef6f6b92ffdb4322bb6d49d94cad2bc", + "sha256:2c74524e179f2ad6d2a4f7caf70e2d96639c0954c943ad601a9e146c76408ed7", + "sha256:303bf1edce6ced16bf67a18a1cf8339d0db79577eec5d9a6d4a80f0fb10aa2da", + "sha256:3331bece23c9ee066e0fb3f96c61322b9e0f54d775fccefff4c38ca488de283a", + "sha256:3e9bdd30efde2b9ccfa9cb5768ba04fe71b018a25ea093379c857c9dad262c40", + "sha256:411007c0d88188d9f621b11d252cce90c4a2d1a49db6c068e3c16422f306eab8", + "sha256:42871176e7896d5d45138f6d28751053c711ed4d48d8e30b498da155af39aebd", + "sha256:46f409a2d60f634fe550f7133ed30ad5321ae2e6630f13657fb9479506b00601", + "sha256:48628bd53a426c9eb9bc066a923acaa0878d1e86129fd5359aee99285f4eed9c", + "sha256:48d6ed886b343d11493129e019da91d4039826794a3e3027321c56d9e71505be", + "sha256:4930be26af26ac545c3dffb662521d4e6268352866956672231887d18f0eaab2", + "sha256:4aec80cde9197340bc353d2768e2a75f5f60bacda2bab72ab1dc499589b3878c", + "sha256:4c28a9144688aef80d6ea666c809b4b0e50010a2aca784c97f5e6bf143d9f129", + "sha256:4d2d1edbca80b510443f51afd8496be95529db04a509bc8faee49c7b0fb6d2cc", + "sha256:4dd9a263e845a72eacb60d12401e37c616438ea2e5442885f65082c276dfb2b2", + "sha256:4f1026bc732b6a7f96369f7bfe1a4f2290fb34dce00d8644bc3036fb351a4ca1", + "sha256:4fb960a632a49f2f089d522f70496640fdf1218f1243889da3822e0a9f5f3ba7", + "sha256:50670615eaf97227d5dc60de2dc99fb134a7130d310d783314e7724bf163f75d", + "sha256:50baa9c1c47efcaef189f31e3d00d697c6d4afda5c3cde0302d063492ff9b477", + "sha256:53ace1c1fd5a74ef662f844a0413446c0629d151055340e9893da958a374f70d", + "sha256:5515edd2a6d1a5a70bfcdee23b42ec33425e405c5b351478ab7dc9347228f96e", + "sha256:56dc1f1ebccc656d1b3ed288f11e27172a01503fc016bcabdcbc0978b19352b7", + "sha256:578695735c5a3f51569810dfebd05dd6f888147a34f0f98d4bb27e92b76e05c2", + "sha256:57aba1bbdf450b726d58b2aea5fe47c7875f5afb2c4a23784ed78f19a0462574", + "sha256:57d6ba0ca2b0c462f339640d22882acc711de224d769edf29962b09f77129cbf", + "sha256:5c245b783db29c4e4fbbbfc9c5a78be496c9fea25517f90606aa1f6b2b3d5f7b", + "sha256:5c31c7462abdf8f2ac0577d9f05279727e698f97ecbb02f17939ea99ae8daa98", + "sha256:64f479d719dc9f4c813ad9bb6b28f8390360660b73b2e4beb4cb0ae7104f1c12", + "sha256:65299ea57d82fb91c7f019300d24050c4ddeb7c5a190e076b5f48a2b43d19c42", + "sha256:6689a3d7fd13dc687e9102a27e98ef33730ac4fe37795d5036d18b4d527abd35", + "sha256:690dafd0b187ed38583a648076865d8c229661ed20e48f2335d68e2cf7dc829d", + "sha256:6fc3c450eaa0b56f815c7b62f2b7fba7266c4779adcf1cece9e6deb1de7305ce", + "sha256:704f61ba8c1283c71b16135caf697557f5ecf3e74d9e453233e4771d68a1f42d", + "sha256:71c52db65e4b56b8ddc5bb89fb2e66c558ed9d1a74a45ceb7dcb20c191c3df2f", + "sha256:71d66ee82e7417828af6ecd7db817913cb0cf9d4e61aa0ac1fde0583d84358db", + "sha256:7d298a1bd60c067ea75d9f684f5f3992c9d6766fadbc0bcedd39750bf344c2f4", + "sha256:8b77946fd508cbf0fccd8e400a7f71d4ac0e1595812e66025bac475a8e811694", + "sha256:8d7e43bd40f65f7d97ad8ef5c9b1778943d02f04febef12def25f7583d19baac", + "sha256:8df133a2ea5e74eef5e8fc6f19b9e085f758768a16e9877a60aec455ed2609b2", + "sha256:8ed74706b26ad100433da4b9d807eae371efaa266ffc3e9191ea436087a9d6a7", + "sha256:92af161ecbdb2883c4593d5ed4815ea71b31fafd7fd05789b23100d081ecac96", + "sha256:97047f0d25cd4bcae81f9ec9dc290ca3e15927c192df17331b53bebe0e3ff96d", + "sha256:9719fe17307a9e814580af1f5c6e05ca593b12fb7e44fe62450a5384dbf61b4b", + "sha256:9767e79108424fb6c3edf8f81e6730666a50feb01a328f4a016464a5893f835a", + "sha256:9a92d3faef50658dd2c5470af249985782bf754c4e18e15afb67d3ab06233f13", + "sha256:9bb6ad405121241e99a86efff22d3ef469024ce22875a7ae045896ad23ba2340", + "sha256:9e28c51fa0ce5674be9f560c6761c1b441631901993f76700b1b30ca6c8378d6", + "sha256:aca086dc5f9ef98c512bac8efea4483eb84abbf926eaeedf7b91479feb092458", + "sha256:ae8b9c6deb1e634ba4f1930eb67ef6e6bf6a44b6eb5ad605642b2d6d5ed9ce3c", + "sha256:b0a545b46b526d418eb91754565ba5b63b1c0b12f9bd2f808c852d9b4b2f9b5c", + "sha256:b4e4bc18382088514ebde9328da057775055940a1f2e18f6ad2d78aa0f3ec5b9", + "sha256:b6420a005548ad52154c8ceab4a1290ff78d757f9e5cbc68f8c77089acd3c432", + "sha256:b86164d2cff4d3aaa1f04a14685cbc072efd0b4f99ca5708b2ad1b9b5988a991", + "sha256:bb3bb49c7a6ad9d981d734ef7c7193bc349ac338776a0360cc671eaee89bcf69", + "sha256:bef4e656f7d98aaa3486d2627e7d2df1157d7e88e7efd43a65aa5dd4714916cf", + "sha256:c0781a98ff5e6586926293e59480b64ddd46282953203c76ae15dbbbf302e8bb", + "sha256:c2006f5c8d28dee289f7020f721354362fa304acbaaf9745751ac4006650254b", + "sha256:c41bfca0bd3532d53d16fd34d20806d5c2b1ace22a2f2e4c0008570bf2c58833", + "sha256:cd47b4a0d41d2afa3e58e5bf1f62069255aa2fd6ff5ee41604418ca925911d76", + "sha256:cdb650fc86227eba20de1a29d4b2c1bfe139dc75a0669270033cb2ea3d391b85", + "sha256:cef2502e7e8a96fe5ad686d60b49e1ab03e438bd9123987994528febd569868e", + "sha256:d27be7405547d1f958b60837dc4c1007da90b8b23f54ba1f8b728c78fdb19d50", + "sha256:d37017287a7adb6ab77e1c5bee9bcf9660f90ff445042b790402a654d2ad81d8", + "sha256:d3ff32724f98fbbbfa9f49d82852b159e9784d6094983d9a8b7f2ddaebb063d4", + "sha256:d73d8ecf8ecf10a3bd007f2192725a34bd62898e8da27eb9d32a58084f93962b", + "sha256:dd708cf4ee4408cf46a48b108fb9427bfa00b9b85812a9262b5c668af2533ea5", + "sha256:e3cd95e10c2610c360154afdc2f1480aea394f4a4f1ea0a5eacce49640c9b190", + "sha256:e4da8ca0c0c0aea88fd46be8e44bd49716772358d648cce45fe387f7b92374a7", + "sha256:eadfbbbfb41b44034a4c757fd5d70baccd43296fb894dba0295606a7cf3124aa", + "sha256:ed667f49b11360951e201453fc3967344d0d0263aa415e1619e85ae7fd17b4e0", + "sha256:f3df3db1d336b9356dd3112eae5f5c2b8b377f3bc826848567f10bfddfee77e9", + "sha256:f6bdac493b949141b733c5345b6ba8f87a226029cbabc7e9e121a413e49441e0", + "sha256:fbf521479bcac1e25a663df882c46a641a9bff6b56dc8b0fafaebd2f66fb231b", + "sha256:fc9b106a1bf918db68619fdcd6d5ad4f972fdd19c01d19bdb6bf63f3589a9ec5", + "sha256:fcdd00edfd0a3001e0181eab3e63bd5c74ad3e67152c84f93f13769a40e073a7", + "sha256:fe4bda6bd4340caa6e5cf95e73f8fea5c4bfc55763dd42f1b50a94c1b4a2fbd4" ], "index": "pypi", - "version": "==4.6.2" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==4.9.3" + }, + "markdown-it-py": { + "hashes": [ + "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", + "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb" + ], + "markers": "python_version >= '3.8'", + "version": "==3.0.0" + }, + "mdurl": { + "hashes": [ + "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", + "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba" + ], + "markers": "python_version >= '3.7'", + "version": "==0.1.2" + }, + "pygments": { + "hashes": [ + "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692", + "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29" + ], + "markers": "python_version >= '3.7'", + "version": "==2.16.1" }, "python-docx": { "hashes": [ - "sha256:bc76ecac6b2d00ce6442a69d03a6f35c71cd72293cd8405a7472dfe317920024" + "sha256:1105d233a0956dd8dd1e710d20b159e2d72ac3c301041b95f4d4ceb3e0ebebc4" ], "index": "pypi", - "version": "==0.8.10" + "version": "==0.8.11" + }, + "rich": { + "hashes": [ + "sha256:87b43e0543149efa1253f485cd845bb7ee54df16c9617b8a893650ab84b4acb6", + "sha256:9257b468badc3d347e146a4faa268ff229039d4c2d176ab0cffb4c4fbc73d5d9" + ], + "index": "pypi", + "markers": "python_full_version >= '3.7.0'", + "version": "==13.5.3" }, "soupsieve": { "hashes": [ - "sha256:4bb21a6ee4707bf43b61230e80740e71bfe56e55d1f1f50924b087bb2975c851", - "sha256:6dc52924dc0bc710a5d16794e6b3480b2c7c08b07729505feab2b2c16661ff6e" + "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690", + "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7" + ], + "markers": "python_version >= '3.8'", + "version": "==2.5" + }, + "typing-extensions": { + "hashes": [ + "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0", + "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef" ], - "markers": "python_version >= '3.0'", - "version": "==2.1" + "markers": "python_version < '3.9'", + "version": "==4.8.0" } }, "develop": {} diff --git a/src/formats/__init__.py b/src/formats/__init__.py index 0f32238..4115cf8 100644 --- a/src/formats/__init__.py +++ b/src/formats/__init__.py @@ -3,3 +3,4 @@ """ from . import docx +from . import md \ No newline at end of file diff --git a/src/formats/md.py b/src/formats/md.py new file mode 100644 index 0000000..4a88604 --- /dev/null +++ b/src/formats/md.py @@ -0,0 +1,168 @@ +""" +Markdown format +""" + +import re +import string +import json + +import html2text +from logzero import logger +from rich import print as rprint + +import config + + +def write_file(data, outfile): + markdown_list = [] + text_maker = html2text.HTML2Text() + + for assessment in data['assessment']: + # Adding Title + assessment_title = f"# {assessment['metadata']['title']}\n" + logger.info(f"Writing assessment: {repr(assessment_title)}") + markdown_list.append(assessment_title) + + # Adding Description + description = assessment['metadata'].get('description') or '' + + if description: + description = text_maker.handle(description).rstrip('\n') + " \n" + logger.info(f" with description: {repr(description)}") + markdown_list.append(description) + else: + logger.debug(" with no description") + + # with open('questions.py', 'w') as f: + # f.write(json.dumps(assessment['question'], indent=4)) + + # rprint(assessment['question']) + # [ + # { + # 'id': 'gf56cf4328c0179fdd7419b86337a9551', + # 'title': 'Question', + # 'question_type': 'multiple_choice_question', + # 'points_possible': '1.0', + # 'text': '
Which code example is an expression?
', + # 'answer': [ + # {'id': '4346', 'text': '# calculate area', 'correct': False, 'display': True}, + # {'id': '3471', 'text': 'area = pi * (radius ** 2)', 'correct': False, 'display': True}, + # {'id': '1385', 'text': 'print(area)', 'correct': False, 'display': True}, + # {'id': '8820', 'text': 'input("what is the radius?")', 'correct': True, 'display': True} + # ] + # }, + # ... + # ] + + for q_num, question in enumerate(assessment['question']): + # Adding Question Title + if 'title' in question: + question_title = f"\n## {question['title']} {q_num+1}\n\n" + logger.info(f"Writing question titled: {repr(question_title)}") + markdown_list.append(question_title) + else: + logger.debug(f"No title in question {q_num+1}") + + # Adding Images + if 'image' in question: + logger.info(f"Adding images to question {q_num+1}") + for img in question['image']: + markdown_list.append(f"![Image]({img['href'].replace('%20', ' ')})") + else: + logger.debug(f"No images in question {q_num+1}") + + # Adding Text + if 'text' in question and question['text'] is not None: + this_question_text = re.sub('', '', question['text']) # See https://github.com/pqzx/html2docx/issues/1 + handled_text = text_maker.handle(this_question_text).strip() + "\n\n" + logger.info(f"Adding text to question {q_num+1}: {repr(handled_text)}") + markdown_list.append(handled_text) + else: + logger.debug(f"No text in question {q_num+1}") + + if 'answer' in question: + if question['question_type'] in ["multiple_dropdowns_question", "matching_question", "calculated_question"]: + logger.warning(f"Question type {question['question_type']} not yet supported") + else: + logger.info(f"Adding answers to question {q_num+1}, type: {question['question_type']}") + for index, answer in enumerate(question['answer']): + if answer['display']: + # For displaying the index and images in Markdown + if 'image' in answer: + logger.debug(f"Adding images to answer {index+1}") + for img in answer['image']: + # Assuming that img['href'] contains the link to the image + markdown_list.append(f"{index+1}. \n![Image]({img['href'].replace('%20', ' ')})") + else: + logger.debug(f"No images in answer {index+1}") + + # For displaying the index and text in Markdown + if 'text' in answer and answer['text'] is not None: + alphabet_index = string.ascii_lowercase[index] + text = answer['text'] + logger.info(f"Answer text: {repr(text)}") + + handled_text = text_maker.handle(text).strip() + logger.info(f"Handled text: {repr(handled_text)}") + + code_block_pattern = r'`([\s\S]*?)`' + cleaned_text = re.sub(code_block_pattern, lambda m: '`' + m.group(1).strip() + '`', handled_text) + " \n" + logger.info(f"Cleaned text added: {alphabet_index}: {repr(cleaned_text)}") + markdown_list.append(f"{alphabet_index}. {cleaned_text}") + else: + logger.warning(f"No text in answer {alphabet_index}") + + else: + markdown_list.append(config.blanks_replace_str * config.blanks_answer_n) + + # rprint(markdown_list) + + # Writing the Generated Markdown to a File + with open(outfile, 'w') as md_file: + md_file.write(''.join(markdown_list)) + + print("wrote markdown") + + return + for assessment in data['assessment']: + doc.add_heading(assessment['metadata']['title'], 0) + for question in assessment['question']: + if 'answer' in question: + if question['question_type'] == "multiple_dropdowns_question": + for aindex, group in enumerate(question['answer']): + options = [] + for option in group['options']: + if option['display']: + if 'text' in answer and option['text'] != None: + options.append(option['text']) + else: + options.append("---") + doc.add_paragraph(str(aindex+1) + ": " + ", ".join(map(str, options))) + elif question['question_type'] == "matching_question": + table = doc.add_table(rows=1, cols=2) + for index, answer in enumerate(question['answer']): + cell_0 = table.cell(0, 0) + if 'image' in answer: + for img in answer['image']: + cell_0.add_picture(img['href'].replace("%20", " "), height=Mm(10)) + if 'text' in answer and answer['text'] != None: + cell_0.text = cell_0.text + ("\n" if cell_0.text != "" else "") + answer['text'] + if index == 0: + cell_1 = table.cell(0, 1) + for option in answer['options']: + if 'image' in option: + for img in option['image']: + cell_1.add_picture(img['href'].replace("%20", " "), height=Mm(10)) + if 'text' in option and option['text'] != None: + cell_1.text = cell_1.text + ("\n" if cell_1.text != "" else "") + option['text'] + elif question['question_type'] == "calculated_question": + if config.calculated_display_var_set_in_text: + doc.add_paragraph(config.blanks_replace_str * config.blanks_answer_n) + else: + for index, answer in enumerate(question['answer']): + if answer['display'] and 'text' in answer and answer['text'] != None: + html_parser.add_html_to_document("

" + str(index+1) + ". " + answer['text'] + ": " + config.blanks_replace_str * 20 + "

", doc) + + doc.add_page_break() + + doc.save(outfile) diff --git a/src/main.py b/src/main.py index 9948688..af77097 100755 --- a/src/main.py +++ b/src/main.py @@ -9,6 +9,7 @@ import re from pathlib import Path +import logzero from logzero import logger from lxml import etree @@ -21,6 +22,13 @@ __license__ = config.__license__ __version__ = config.__version__ +log_file = Path("qti_convert.log") +if log_file.exists(): + log_file.unlink() + +logzero.logfile(log_file, maxBytes=1e6, backupCount=3, disableStderrLogger=True) +logzero.loglevel(logzero.INFO) +logger.info("Logging to file: " + str(log_file)) def main(args): logger.info(__description__) @@ -73,6 +81,14 @@ def main(args): logger.info("Writing DOCX to '" + outfile + "'...") formats.docx.write_file(qti_resource, outfile) + elif args.format.lower() == "md": + if args.output: + outfile = args.output + else: + outfile = "output.md" + logger.info("Writing Markdown to '" + outfile + "'...") + formats.md.write_file(qti_resource, outfile) + elif args.format.lower() == "pdf": logger.error("Format not supported yet: " + args.format)