diff --git a/Makefile b/Makefile index 0e7f81d93..c242a148e 100644 --- a/Makefile +++ b/Makefile @@ -307,10 +307,9 @@ docserve: gen-docs $(RUN) mkdocs serve -# Regenerate from Google Sheets. Note that this uses a *separate* Pipenv in the -# generators/google-sheets directory, so we have to run pipenv install on it separately. +# Generate LinkML schema from Google Sheet data model using sheet2linkml. generate-model: install install-dev - CDM_GOOGLE_SHEET_ID=$(CDM_GOOGLE_SHEET_ID) $(RUN) python vendor/sheet2linkml/sheet2linkml.py --output model/schema/crdch_model.yaml + CDM_GOOGLE_SHEET_ID=$(CDM_GOOGLE_SHEET_ID) $(RUN) sheet2linkml --output linkml_model/schema/crdch_model.yaml --logging-config ./logging.ini # MAM 20210806 not sure how this fits into the linkml model template's doc building/publsihing approach # Deploy changes to the `dev` version on the gh-pages branch. diff --git a/Pipfile b/Pipfile index aee974e41..2047f78a7 100644 --- a/Pipfile +++ b/Pipfile @@ -7,29 +7,20 @@ name = "pypi" # For LinkML, we use the `ccdh-dev` branch, which we manually keep in sync with LinkML's main branch # as well as some additional changes required for CRDCH generation. linkml = {editable = true, ref = "ccdh-dev", git = "https://github.com/cancerDHC/linkml.git"} - # Since we use the development version of LinkML, we also use the development version of linkml-runtime. # This may sometimes cause issues between this and LinkML. linkml-runtime = {editable = true, git = "https://github.com/linkml/linkml-runtime.git"} - pyparsing = "<=2.4.7" rdflib-pyld-compat = "*" # resinstating after removal by migration to linkml model template +sheet2linkml = ">=1.1.0" # used for converting spreadsheet data model to LinkML schema [dev-packages] pyyaml = "*" # For reading and writing YAML files. - # Packages needed for testing. pytest = "~=6.2.4" tox = "*" typing_extensions = "*" # This is a tox prereq for Python 3.7, but not installed by Pipenv. twine = "*" # should this go in make-venv/Pipfile ? - -# Packages needed by sheet2linkml. -black = "==v21.5b1" # Used for code linting. -requests = "*" # For making HTTP requests. -pygsheets = "*" # For accessing Google Sheets. -python-dotenv = "*" # For reading .env files. - # Packages needed for building and publishing documentation. mike = "*" mkdocs-material = "*" diff --git a/Pipfile.lock b/Pipfile.lock index b361628d3..428f867e4 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "ba64635dea74c3cb803f2ccfbd306c39bb09607a554054885244a0599b31aef1" + "sha256": "5527d8fa26242ea042279593fdeec3088c22fdd38b0b6162b08721910c57afa5" }, "pipfile-spec": 6, "requires": {}, @@ -23,9 +23,9 @@ }, "antlr4-python3-runtime": { "hashes": [ - "sha256:31f5abdc7faf16a1a6e9bf2eb31565d004359b821b09944436a34361929ae85a" + "sha256:f224469b4168294902bb1efa80a8bf7855f24c99aef99cbefc1bcd3cce77881b" ], - "version": "==4.9.2" + "version": "==4.9.3" }, "argparse": { "hashes": [ @@ -50,20 +50,28 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.9.1" }, + "black": { + "hashes": [ + "sha256:6eb7448da9143ee65b856a5f3676b7dda98ad9abe0f87fce8c59291f15e82a5b", + "sha256:a9952229092e325fe5f3dae56d81f639b23f7131eb840781947e4b2886030f33" + ], + "markers": "python_full_version >= '3.6.2'", + "version": "==21.10b0" + }, "cachetools": { "hashes": [ - "sha256:2cc0b89715337ab6dbba85b5b50effe2b0c74e035d83ee8ed637cf52f12ae001", - "sha256:61b5ed1e22a0924aed1d23b478f37e8d52549ff8a961de2909c69bf950020cff" + "sha256:89ea6f1b638d5a73a4f9226be57ac5e4f399d22770b92355f92dcb0f7f001693", + "sha256:92971d3cb7d2a97efff7c7bb1657f21a8f5fb309a37530537c71b1774189f2d1" ], "markers": "python_version ~= '3.5'", - "version": "==4.2.2" + "version": "==4.2.4" }, "certifi": { "hashes": [ - "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee", - "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8" + "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872", + "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569" ], - "version": "==2021.5.30" + "version": "==2021.10.8" }, "cfgraph": { "hashes": [ @@ -73,11 +81,11 @@ }, "charset-normalizer": { "hashes": [ - "sha256:5d209c0a931f215cee683b6445e2d77677e7e75e159f78def0db09d68fafcaa6", - "sha256:5ec46d183433dcbd0ab716f2d7f29d8dee50505b3fdb40c6b985c7c4f5a3591f" + "sha256:e019de665e2bcf9c2b64e2e5aa025fa991da8720daa3c1138cadd2fd1856aed0", + "sha256:f7af805c321bfa1ce6714c51f254e0d5bb5e5834039bc17db7ebe3a4cec9492b" ], "markers": "python_version >= '3'", - "version": "==2.0.6" + "version": "==2.0.7" }, "click": { "hashes": [ @@ -87,6 +95,14 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==7.1.2" }, + "decorator": { + "hashes": [ + "sha256:7b12e7c3c6ab203a29e157335e9122cb03de9ab7264b137594103fd4a683b374", + "sha256:e59913af105b9860aa2c8d3272d9de5a56a4e608db9a2f167a8480b323d529a7" + ], + "markers": "python_version >= '3.5'", + "version": "==5.1.0" + }, "deprecated": { "hashes": [ "sha256:43ac5335da90c31c24ba028af536a91d41d53f9e6901ddb021bcc572ce44e38d", @@ -113,99 +129,154 @@ }, "frozendict": { "hashes": [ - "sha256:3f00de72805cf4c9e81b334f3f04809278b967d2fed84552313a0fcce511beb1", - "sha256:5d3f75832c35d4df041f0e19c268964cbef29c1eb34cd3517cf883f1c2d089b9" + "sha256:a68f609d1af67da80b45519fdcfca2d60249c0a8c96e68279c1b6ddd92128204", + "sha256:d650f9cf3d2c5438b1631488a975a49b3bdd12c7a97eec59b85e57821eebf28a" + ], + "markers": "python_version >= '3.6'", + "version": "==2.0.7" + }, + "google-api-core": { + "hashes": [ + "sha256:97349cc18c2bb2415f64f1353a80273a289a61294ce3eb2f7ce682d251bdd997", + "sha256:e7853735d4f51f4212d6bf9750620d76fc0106c0f271be0c3f43b73501c7ddf9" + ], + "markers": "python_version >= '3.6'", + "version": "==2.2.2" + }, + "google-api-python-client": { + "hashes": [ + "sha256:54e60f20acc3a5ac48e37b3d86bf5191fd6a1acb0f1efe76c47ed6b90f8c5a50", + "sha256:d46418a296f8ee309b2044791aeffae512cb1a9d9bfb3def2bfb37058f01c645" + ], + "markers": "python_version >= '3.6'", + "version": "==2.30.0" + }, + "google-auth": { + "hashes": [ + "sha256:a348a50b027679cb7dae98043ac8dbcc1d7951f06d8387496071a1e05a2465c0", + "sha256:d83570a664c10b97a1dc6f8df87e5fdfff012f48f62be131e449c20dfc32630e" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==2.3.3" + }, + "google-auth-httplib2": { + "hashes": [ + "sha256:31e49c36c6b5643b57e82617cb3e021e3e1d2df9da63af67252c02fa9c1f4a10", + "sha256:a07c39fd632becacd3f07718dfd6021bf396978f03ad3ce4321d060015cc30ac" + ], + "version": "==0.1.0" + }, + "google-auth-oauthlib": { + "hashes": [ + "sha256:3f2a6e802eebbb6fb736a370fbf3b055edcb6b52878bf2f26330b5e041316c73", + "sha256:a90a072f6993f2c327067bf65270046384cda5a8ecb20b94ea9a687f1f233a7a" ], "markers": "python_version >= '3.6'", - "version": "==2.0.6" + "version": "==0.4.6" + }, + "googleapis-common-protos": { + "hashes": [ + "sha256:a88ee8903aa0a81f6c3cec2d5cf62d3c8aa67c06439b0496b49048fb1854ebf4", + "sha256:f6d561ab8fb16b30020b940e2dd01cd80082f4762fa9f3ee670f4419b4b8dbd0" + ], + "markers": "python_version >= '3.6'", + "version": "==1.53.0" }, "graphviz": { "hashes": [ - "sha256:5dadec94046d82adaae6019311a30e0487536d9d5a60d85451f0ba32f9fc6559", - "sha256:ef6e2c5deb9cdcc0c7eece1d89625fd07b0f2208ea2bcb483520907ddf8b4e12" + "sha256:0f04e5f939d3a839b524283d590e941892c56e75e60e0f5238c431264f490022", + "sha256:f8bab3bf3eda40ab259bb96f786811b5dec6fd6957fa70a5b1977534e1ee2a40" ], "markers": "python_version >= '3.6'", - "version": "==0.17" + "version": "==0.18" }, "greenlet": { "hashes": [ - "sha256:04e1849c88aa56584d4a0a6e36af5ec7cc37993fdc1fda72b56aa1394a92ded3", - "sha256:05e72db813c28906cdc59bd0da7c325d9b82aa0b0543014059c34c8c4ad20e16", - "sha256:07e6d88242e09b399682b39f8dfa1e7e6eca66b305de1ff74ed9eb1a7d8e539c", - "sha256:090126004c8ab9cd0787e2acf63d79e80ab41a18f57d6448225bbfcba475034f", - "sha256:1796f2c283faab2b71c67e9b9aefb3f201fdfbee5cb55001f5ffce9125f63a45", - "sha256:2f89d74b4f423e756a018832cd7a0a571e0a31b9ca59323b77ce5f15a437629b", - "sha256:34e6675167a238bede724ee60fe0550709e95adaff6a36bcc97006c365290384", - "sha256:3e594015a2349ec6dcceda9aca29da8dc89e85b56825b7d1f138a3f6bb79dd4c", - "sha256:3f8fc59bc5d64fa41f58b0029794f474223693fd00016b29f4e176b3ee2cfd9f", - "sha256:3fc6a447735749d651d8919da49aab03c434a300e9f0af1c886d560405840fd1", - "sha256:40abb7fec4f6294225d2b5464bb6d9552050ded14a7516588d6f010e7e366dcc", - "sha256:44556302c0ab376e37939fd0058e1f0db2e769580d340fb03b01678d1ff25f68", - "sha256:476ba9435afaead4382fbab8f1882f75e3fb2285c35c9285abb3dd30237f9142", - "sha256:4870b018ca685ff573edd56b93f00a122f279640732bb52ce3a62b73ee5c4a92", - "sha256:4adaf53ace289ced90797d92d767d37e7cdc29f13bd3830c3f0a561277a4ae83", - "sha256:4eae94de9924bbb4d24960185363e614b1b62ff797c23dc3c8a7c75bbb8d187e", - "sha256:5317701c7ce167205c0569c10abc4bd01c7f4cf93f642c39f2ce975fa9b78a3c", - "sha256:5c3b735ccf8fc8048664ee415f8af5a3a018cc92010a0d7195395059b4b39b7d", - "sha256:5cde7ee190196cbdc078511f4df0be367af85636b84d8be32230f4871b960687", - "sha256:655ab836324a473d4cd8cf231a2d6f283ed71ed77037679da554e38e606a7117", - "sha256:6ce9d0784c3c79f3e5c5c9c9517bbb6c7e8aa12372a5ea95197b8a99402aa0e6", - "sha256:6e0696525500bc8aa12eae654095d2260db4dc95d5c35af2b486eae1bf914ccd", - "sha256:75ff270fd05125dce3303e9216ccddc541a9e072d4fc764a9276d44dee87242b", - "sha256:8039f5fe8030c43cd1732d9a234fdcbf4916fcc32e21745ca62e75023e4d4649", - "sha256:84488516639c3c5e5c0e52f311fff94ebc45b56788c2a3bfe9cf8e75670f4de3", - "sha256:84782c80a433d87530ae3f4b9ed58d4a57317d9918dfcc6a59115fa2d8731f2c", - "sha256:8ddb38fb6ad96c2ef7468ff73ba5c6876b63b664eebb2c919c224261ae5e8378", - "sha256:98b491976ed656be9445b79bc57ed21decf08a01aaaf5fdabf07c98c108111f6", - "sha256:990e0f5e64bcbc6bdbd03774ecb72496224d13b664aa03afd1f9b171a3269272", - "sha256:9b02e6039eafd75e029d8c58b7b1f3e450ca563ef1fe21c7e3e40b9936c8d03e", - "sha256:a11b6199a0b9dc868990456a2667167d0ba096c5224f6258e452bfbe5a9742c5", - "sha256:a414f8e14aa7bacfe1578f17c11d977e637d25383b6210587c29210af995ef04", - "sha256:a91ee268f059583176c2c8b012a9fce7e49ca6b333a12bbc2dd01fc1a9783885", - "sha256:ac991947ca6533ada4ce7095f0e28fe25d5b2f3266ad5b983ed4201e61596acf", - "sha256:b050dbb96216db273b56f0e5960959c2b4cb679fe1e58a0c3906fa0a60c00662", - "sha256:b97a807437b81f90f85022a9dcfd527deea38368a3979ccb49d93c9198b2c722", - "sha256:bad269e442f1b7ffa3fa8820b3c3aa66f02a9f9455b5ba2db5a6f9eea96f56de", - "sha256:bf3725d79b1ceb19e83fb1aed44095518c0fcff88fba06a76c0891cfd1f36837", - "sha256:c0f22774cd8294078bdf7392ac73cf00bfa1e5e0ed644bd064fdabc5f2a2f481", - "sha256:c1862f9f1031b1dee3ff00f1027fcd098ffc82120f43041fe67804b464bbd8a7", - "sha256:c8d4ed48eed7414ccb2aaaecbc733ed2a84c299714eae3f0f48db085342d5629", - "sha256:cf31e894dabb077a35bbe6963285d4515a387ff657bd25b0530c7168e48f167f", - "sha256:d15cb6f8706678dc47fb4e4f8b339937b04eda48a0af1cca95f180db552e7663", - "sha256:dfcb5a4056e161307d103bc013478892cfd919f1262c2bb8703220adcb986362", - "sha256:e02780da03f84a671bb4205c5968c120f18df081236d7b5462b380fd4f0b497b", - "sha256:e2002a59453858c7f3404690ae80f10c924a39f45f6095f18a985a1234c37334", - "sha256:e22a82d2b416d9227a500c6860cf13e74060cf10e7daf6695cbf4e6a94e0eee4", - "sha256:e41f72f225192d5d4df81dad2974a8943b0f2d664a2a5cfccdf5a01506f5523c", - "sha256:f253dad38605486a4590f9368ecbace95865fea0f2b66615d121ac91fd1a1563", - "sha256:fddfb31aa2ac550b938d952bca8a87f1db0f8dc930ffa14ce05b5c08d27e7fd1" + "sha256:00e44c8afdbe5467e4f7b5851be223be68adb4272f44696ee71fe46b7036a711", + "sha256:013d61294b6cd8fe3242932c1c5e36e5d1db2c8afb58606c5a67efce62c1f5fd", + "sha256:049fe7579230e44daef03a259faa24511d10ebfa44f69411d99e6a184fe68073", + "sha256:14d4f3cd4e8b524ae9b8aa567858beed70c392fdec26dbdb0a8a418392e71708", + "sha256:166eac03e48784a6a6e0e5f041cfebb1ab400b394db188c48b3a84737f505b67", + "sha256:17ff94e7a83aa8671a25bf5b59326ec26da379ace2ebc4411d690d80a7fbcf23", + "sha256:1e12bdc622676ce47ae9abbf455c189e442afdde8818d9da983085df6312e7a1", + "sha256:21915eb821a6b3d9d8eefdaf57d6c345b970ad722f856cd71739493ce003ad08", + "sha256:288c6a76705dc54fba69fbcb59904ae4ad768b4c768839b8ca5fdadec6dd8cfd", + "sha256:32ca72bbc673adbcfecb935bb3fb1b74e663d10a4b241aaa2f5a75fe1d1f90aa", + "sha256:356b3576ad078c89a6107caa9c50cc14e98e3a6c4874a37c3e0273e4baf33de8", + "sha256:40b951f601af999a8bf2ce8c71e8aaa4e8c6f78ff8afae7b808aae2dc50d4c40", + "sha256:572e1787d1460da79590bf44304abbc0a2da944ea64ec549188fa84d89bba7ab", + "sha256:58df5c2a0e293bf665a51f8a100d3e9956febfbf1d9aaf8c0677cf70218910c6", + "sha256:64e6175c2e53195278d7388c454e0b30997573f3f4bd63697f88d855f7a6a1fc", + "sha256:7227b47e73dedaa513cdebb98469705ef0d66eb5a1250144468e9c3097d6b59b", + "sha256:7418b6bfc7fe3331541b84bb2141c9baf1ec7132a7ecd9f375912eca810e714e", + "sha256:7cbd7574ce8e138bda9df4efc6bf2ab8572c9aff640d8ecfece1b006b68da963", + "sha256:7ff61ff178250f9bb3cd89752df0f1dd0e27316a8bd1465351652b1b4a4cdfd3", + "sha256:833e1551925ed51e6b44c800e71e77dacd7e49181fdc9ac9a0bf3714d515785d", + "sha256:8639cadfda96737427330a094476d4c7a56ac03de7265622fcf4cfe57c8ae18d", + "sha256:8c790abda465726cfb8bb08bd4ca9a5d0a7bd77c7ac1ca1b839ad823b948ea28", + "sha256:8d2f1fb53a421b410751887eb4ff21386d119ef9cde3797bf5e7ed49fb51a3b3", + "sha256:903bbd302a2378f984aef528f76d4c9b1748f318fe1294961c072bdc7f2ffa3e", + "sha256:93f81b134a165cc17123626ab8da2e30c0455441d4ab5576eed73a64c025b25c", + "sha256:95e69877983ea39b7303570fa6760f81a3eec23d0e3ab2021b7144b94d06202d", + "sha256:9633b3034d3d901f0a46b7939f8c4d64427dfba6bbc5a36b1a67364cf148a1b0", + "sha256:97e5306482182170ade15c4b0d8386ded995a07d7cc2ca8f27958d34d6736497", + "sha256:9f3cba480d3deb69f6ee2c1825060177a22c7826431458c697df88e6aeb3caee", + "sha256:aa5b467f15e78b82257319aebc78dd2915e4c1436c3c0d1ad6f53e47ba6e2713", + "sha256:abb7a75ed8b968f3061327c433a0fbd17b729947b400747c334a9c29a9af6c58", + "sha256:aec52725173bd3a7b56fe91bc56eccb26fbdff1386ef123abb63c84c5b43b63a", + "sha256:b11548073a2213d950c3f671aa88e6f83cda6e2fb97a8b6317b1b5b33d850e06", + "sha256:b1692f7d6bc45e3200844be0dba153612103db241691088626a33ff1f24a0d88", + "sha256:b92e29e58bef6d9cfd340c72b04d74c4b4e9f70c9fa7c78b674d1fec18896dc4", + "sha256:be5f425ff1f5f4b3c1e33ad64ab994eed12fc284a6ea71c5243fd564502ecbe5", + "sha256:dd0b1e9e891f69e7675ba5c92e28b90eaa045f6ab134ffe70b52e948aa175b3c", + "sha256:e30f5ea4ae2346e62cedde8794a56858a67b878dd79f7df76a0767e356b1744a", + "sha256:e6a36bb9474218c7a5b27ae476035497a6990e21d04c279884eb10d9b290f1b1", + "sha256:e859fcb4cbe93504ea18008d1df98dee4f7766db66c435e4882ab35cf70cac43", + "sha256:eb6ea6da4c787111adf40f697b4e58732ee0942b5d3bd8f435277643329ba627", + "sha256:ec8c433b3ab0419100bd45b47c9c8551248a5aee30ca5e9d399a0b57ac04651b", + "sha256:eff9d20417ff9dcb0d25e2defc2574d10b491bf2e693b4e491914738b7908168", + "sha256:f0214eb2a23b85528310dad848ad2ac58e735612929c8072f6093f3585fd342d", + "sha256:f276df9830dba7a333544bd41070e8175762a7ac20350786b322b714b0e654f5", + "sha256:f3acda1924472472ddd60c29e5b9db0cec629fbe3c5c5accb74d6d6d14773478", + "sha256:f70a9e237bb792c7cc7e44c531fd48f5897961701cdaa06cf22fc14965c496cf", + "sha256:f9d29ca8a77117315101425ec7ec2a47a22ccf59f5593378fc4077ac5b754fce", + "sha256:fa877ca7f6b48054f847b61d6fa7bed5cebb663ebc55e018fda12db09dcc664c", + "sha256:fdcec0b8399108577ec290f55551d926d9a1fa6cad45882093a7a07ac5ec147b" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==1.1.1" + "version": "==1.1.2" }, "hbreader": { "hashes": [ "sha256:9a6e76c9d1afc1b977374a5dc430a1ebb0ea0488205546d4678d6e31cc5f6801", "sha256:d2c132f8ba6276d794c66224c3297cec25c8079d0a4cf019c061611e0a3b94fa" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==0.9.1" }, + "httplib2": { + "hashes": [ + "sha256:6b937120e7d786482881b44b8eec230c1ee1c5c1d06bce8cc865f25abbbf713b", + "sha256:e404681d2fbcec7506bcb52c503f2b021e95bee0ef7d01e5c221468a2406d8dc" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.20.2" + }, "idna": { "hashes": [ - "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a", - "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3" + "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff", + "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d" ], "markers": "python_version >= '3'", - "version": "==3.2" + "version": "==3.3" }, "imagesize": { "hashes": [ - "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1", - "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1" + "sha256:1db2f82529e53c3e929e8926a1fa9235aa82d0bd0c580359c67ec31b2fddaa8c", + "sha256:cd1750d452385ca327479d45b64d9c7729ecf0b3969a58148298c77092261f9d" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.2.0" + "version": "==1.3.0" }, "isodate": { "hashes": [ @@ -216,18 +287,18 @@ }, "jinja2": { "hashes": [ - "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4", - "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4" + "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8", + "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7" ], "markers": "python_version >= '3.6'", - "version": "==3.0.1" + "version": "==3.0.3" }, "json-flattener": { "hashes": [ "sha256:9a3d7c45e0b3636268efdb1a9d78734f0573e2a05ec4f00b6a677c69a63d1e3f", "sha256:af41c05fb15b6b9881faa95191e942e1387e305574b2269ebbecb4289173395b" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==0.1.7" }, "jsonasobj": { @@ -246,76 +317,121 @@ "markers": "python_version >= '3.6'", "version": "==1.0.4" }, + "jsonpatch": { + "hashes": [ + "sha256:26ac385719ac9f54df8a2f0827bb8253aa3ea8ab7b3368457bcdb8c14595a397", + "sha256:b6ddfe6c3db30d81a96aaeceb6baf916094ffa23d7dd5fa2c13e13f8b6e600c2" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==1.32" + }, + "jsonpath-ng": { + "hashes": [ + "sha256:292a93569d74029ba75ac2dc3d3630fc0e17b2df26119a165fa1d498ca47bf65", + "sha256:a273b182a82c1256daab86a313b937059261b5c5f8c4fa3fc38b882b344dd567", + "sha256:f75b95dbecb8a0f3b86fd2ead21c2b022c3f5770957492b9b6196ecccfeb10aa" + ], + "version": "==1.5.3" + }, + "jsonpointer": { + "hashes": [ + "sha256:26d9a47a72d4dc3e3ae72c4c6cd432afd73c680164cd2540772eab53cb3823b6", + "sha256:f09f8deecaaa5aea65b5eb4f67ca4e54e1a61f7a11c75085e360fe6feb6a48bf" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.2" + }, "jsonschema": { "hashes": [ - "sha256:25ebdfe8a3c40974e318cdc250f2fbd6c9c86336c5a03710bb8256d019bb3630", - "sha256:6016b56a0f26b93162cfe2eb157fff34f46f631395327d7070c5b11162c0fc81" + "sha256:2a0f162822a64d95287990481b45d82f096e99721c86534f48201b64ebca6e8c", + "sha256:390713469ae64b8a58698bb3cbc3859abe6925b565a973f87323ef21b09a27a8" ], - "version": "==4.0.0a6" + "markers": "python_version >= '3.7'", + "version": "==4.2.1" }, "linkml": { "editable": true, "git": "https://github.com/cancerDHC/linkml.git", - "ref": "3087b914a2760a3b90ac858dd21151c8c8fa8f2f" + "ref": "7fa0fb6342851f089a0547ff65b4ca48bce29a81" }, "linkml-runtime": { "editable": true, "git": "https://github.com/linkml/linkml-runtime.git", - "ref": "21ee840532efc05e1184ff1a5f6aabe99bd4af47" + "ref": "97e29ff8b8215a2f1d29176ea0dd5228a8067331" + }, + "linkml-runtime-api": { + "hashes": [ + "sha256:b18541410dabedfe61bb90ad2830e794c72417a4451563a2a02c486783df2ef4", + "sha256:fb619e0e10a878502051eb316af431bd81849dc1966a926ee09c83b90ba24e59" + ], + "markers": "python_version >= '3.7'", + "version": "==0.0.4" }, "lxml": { "hashes": [ - "sha256:079f3ae844f38982d156efce585bc540c16a926d4436712cf4baee0cce487a3d", - "sha256:0fbcf5565ac01dff87cbfc0ff323515c823081c5777a9fc7703ff58388c258c3", - "sha256:122fba10466c7bd4178b07dba427aa516286b846b2cbd6f6169141917283aae2", - "sha256:1b38116b6e628118dea5b2186ee6820ab138dbb1e24a13e478490c7db2f326ae", - "sha256:1b7584d421d254ab86d4f0b13ec662a9014397678a7c4265a02a6d7c2b18a75f", - "sha256:26e761ab5b07adf5f555ee82fb4bfc35bf93750499c6c7614bd64d12aaa67927", - "sha256:289e9ca1a9287f08daaf796d96e06cb2bc2958891d7911ac7cae1c5f9e1e0ee3", - "sha256:2a9d50e69aac3ebee695424f7dbd7b8c6d6eb7de2a2eb6b0f6c7db6aa41e02b7", - "sha256:3082c518be8e97324390614dacd041bb1358c882d77108ca1957ba47738d9d59", - "sha256:33bb934a044cf32157c12bfcfbb6649807da20aa92c062ef51903415c704704f", - "sha256:3439c71103ef0e904ea0a1901611863e51f50b5cd5e8654a151740fde5e1cade", - "sha256:36108c73739985979bf302006527cf8a20515ce444ba916281d1c43938b8bb96", - "sha256:39b78571b3b30645ac77b95f7c69d1bffc4cf8c3b157c435a34da72e78c82468", - "sha256:4289728b5e2000a4ad4ab8da6e1db2e093c63c08bdc0414799ee776a3f78da4b", - "sha256:4bff24dfeea62f2e56f5bab929b4428ae6caba2d1eea0c2d6eb618e30a71e6d4", - "sha256:4c61b3a0db43a1607d6264166b230438f85bfed02e8cff20c22e564d0faff354", - "sha256:542d454665a3e277f76954418124d67516c5f88e51a900365ed54a9806122b83", - "sha256:5a0a14e264069c03e46f926be0d8919f4105c1623d620e7ec0e612a2e9bf1c04", - "sha256:5c8c163396cc0df3fd151b927e74f6e4acd67160d6c33304e805b84293351d16", - "sha256:64812391546a18896adaa86c77c59a4998f33c24788cadc35789e55b727a37f4", - "sha256:66e575c62792c3f9ca47cb8b6fab9e35bab91360c783d1606f758761810c9791", - "sha256:6f12e1427285008fd32a6025e38e977d44d6382cf28e7201ed10d6c1698d2a9a", - "sha256:74f7d8d439b18fa4c385f3f5dfd11144bb87c1da034a466c5b5577d23a1d9b51", - "sha256:7610b8c31688f0b1be0ef882889817939490a36d0ee880ea562a4e1399c447a1", - "sha256:76fa7b1362d19f8fbd3e75fe2fb7c79359b0af8747e6f7141c338f0bee2f871a", - "sha256:7728e05c35412ba36d3e9795ae8995e3c86958179c9770e65558ec3fdfd3724f", - "sha256:8157dadbb09a34a6bd95a50690595e1fa0af1a99445e2744110e3dca7831c4ee", - "sha256:820628b7b3135403540202e60551e741f9b6d3304371712521be939470b454ec", - "sha256:884ab9b29feaca361f7f88d811b1eea9bfca36cf3da27768d28ad45c3ee6f969", - "sha256:89b8b22a5ff72d89d48d0e62abb14340d9e99fd637d046c27b8b257a01ffbe28", - "sha256:92e821e43ad382332eade6812e298dc9701c75fe289f2a2d39c7960b43d1e92a", - "sha256:b007cbb845b28db4fb8b6a5cdcbf65bacb16a8bd328b53cbc0698688a68e1caa", - "sha256:bc4313cbeb0e7a416a488d72f9680fffffc645f8a838bd2193809881c67dd106", - "sha256:bccbfc27563652de7dc9bdc595cb25e90b59c5f8e23e806ed0fd623755b6565d", - "sha256:c1a40c06fd5ba37ad39caa0b3144eb3772e813b5fb5b084198a985431c2f1e8d", - "sha256:c47ff7e0a36d4efac9fd692cfa33fbd0636674c102e9e8d9b26e1b93a94e7617", - "sha256:c4f05c5a7c49d2fb70223d0d5bcfbe474cf928310ac9fa6a7c6dddc831d0b1d4", - "sha256:cdaf11d2bd275bf391b5308f86731e5194a21af45fbaaaf1d9e8147b9160ea92", - "sha256:ce256aaa50f6cc9a649c51be3cd4ff142d67295bfc4f490c9134d0f9f6d58ef0", - "sha256:d2e35d7bf1c1ac8c538f88d26b396e73dd81440d59c1ef8522e1ea77b345ede4", - "sha256:d916d31fd85b2f78c76400d625076d9124de3e4bda8b016d25a050cc7d603f24", - "sha256:df7c53783a46febb0e70f6b05df2ba104610f2fb0d27023409734a3ecbb78fb2", - "sha256:e1cbd3f19a61e27e011e02f9600837b921ac661f0c40560eefb366e4e4fb275e", - "sha256:efac139c3f0bf4f0939f9375af4b02c5ad83a622de52d6dfa8e438e8e01d0eb0", - "sha256:efd7a09678fd8b53117f6bae4fa3825e0a22b03ef0a932e070c0bdbb3a35e654", - "sha256:f2380a6376dfa090227b663f9678150ef27543483055cc327555fb592c5967e2", - "sha256:f8380c03e45cf09f8557bdaa41e1fa7c81f3ae22828e1db470ab2a6c96d8bc23", - "sha256:f90ba11136bfdd25cae3951af8da2e95121c9b9b93727b1b896e3fa105b2f586" + "sha256:08eb9200d88b376a8ed5e50f1dc1d1a45b49305169674002a3b5929943390591", + "sha256:0b12c95542f04d10cba46b3ff28ea52ea56995b78cf918f0b11b05e75812bb79", + "sha256:0c15e1cd55055956e77b0732270f1c6005850696bc3ef3e03d01e78af84eaa42", + "sha256:15d0381feb56f08f78c5cc4fc385ddfe0bde1456e37f54a9322833371aec4060", + "sha256:197b7cb7a753cf553a45115739afd8458464a28913da00f5c525063f94cd3f48", + "sha256:20d7c8d90d449c6a353b15ee0459abae8395dbe59ad01e406ccbf30cd81c6f98", + "sha256:240db6f3228d26e3c6f4fad914b9ddaaf8707254e8b3efd564dc680c8ec3c264", + "sha256:2901625f4a878a055d275beedc20ba9cb359cefc4386a967222fee29eb236038", + "sha256:2b06a91cf7b8acea7793006e4ae50646cef0fe35ce5acd4f5cb1c77eb228e4a1", + "sha256:2eb90f6ec3c236ef2f1bb38aee7c0d23e77d423d395af6326e7cca637519a4cb", + "sha256:351482da8dd028834028537f08724b1de22d40dcf3bb723b469446564f409074", + "sha256:35752ee40f7bbf6adc9ff4e1f4b84794a3593736dcce80db32e3c2aa85e294ac", + "sha256:38b9de0de3aa689fe9fb9877ae1be1e83b8cf9621f7e62049d0436b9ecf4ad64", + "sha256:433df8c7dde0f9e41cbf4f36b0829d50a378116ef5e962ba3881f2f5f025c7be", + "sha256:4341d135f5660db10184963d9c3418c3e28d7f868aaf8b11a323ebf85813f7f4", + "sha256:45fdb2899c755138722797161547a40b3e2a06feda620cc41195ee7e97806d81", + "sha256:4717123f7c11c81e0da69989e5a64079c3f402b0efeb4c6241db6c369d657bd8", + "sha256:47e955112ce64241fdb357acf0216081f9f3255b3ac9c502ca4b3323ec1ca558", + "sha256:48eaac2991b3036175b42ee8d3c23f4cca13f2be8426bf29401a690ab58c88f4", + "sha256:4aa349c5567651f34d4eaae7de6ed5b523f6d70a288f9c6fbac22d13a0784e04", + "sha256:4ba74afe5ee5cb5e28d83b513a6e8f0875fda1dc1a9aea42cc0065f029160d2a", + "sha256:4ec9a80dd5704ecfde54319b6964368daf02848c8954d3bacb9b64d1c7659159", + "sha256:50790313df028aa05cf22be9a8da033b86c42fa32523e4fd944827b482b17bf0", + "sha256:51a0e5d243687596f46e24e464121d4b232ad772e2d1785b2a2c0eb413c285d4", + "sha256:523f195948a1ba4f9f5b7294d83c6cd876547dc741820750a7e5e893a24bbe38", + "sha256:543b239b191bb3b6d9bef5f09f1fb2be5b7eb09ab4d386aa655e4d53fbe9ff47", + "sha256:5ff5bb2a198ea67403bb6818705e9a4f90e0313f2215428ec51001ce56d939fb", + "sha256:601f0ab75538b280aaf1e720eb9d68d4fa104ac274e1e9e6971df488f4dcdb0f", + "sha256:6020c70ff695106bf80651953a23e37718ef1fee9abd060dcad8e32ab2dc13f3", + "sha256:619c6d2b552bba00491e96c0518aad94002651c108a0f7364ff2d7798812c00e", + "sha256:6298f5b42a26581206ef63fffa97c754245d329414108707c525512a5197f2ba", + "sha256:662523cd2a0246740225c7e32531f2e766544122e58bee70e700a024cfc0cf81", + "sha256:6764998345552b1dfc9326a932d2bad6367c6b37a176bb73ada6b9486bf602f7", + "sha256:6d422b3c729737d8a39279a25fa156c983a56458f8b2f97661ee6fb22b80b1d6", + "sha256:72e730d33fe2e302fd07285f14624fca5e5e2fb2bb4fb2c3941e318c41c443d1", + "sha256:75d3c5bbc0ddbad03bb68b9be638599f67e4b98ed3dcd0fec9f6f39e41ee96cb", + "sha256:7ae7089d81fc502df4b217ad77f03c54039fe90dac0acbe70448d7e53bfbc57e", + "sha256:80d10d53d3184837445ff8562021bdd37f57c4cadacbf9d8726cc16220a00d54", + "sha256:877666418598f6cb289546c77ff87590cfd212f903b522b0afa0b9fb73b3ccfb", + "sha256:9b87727561c1150c0cc91c5d9d389448b37a7d15f0ba939ed3d1acb2f11bf6c5", + "sha256:9c91a73971a922c13070fd8fa5a114c858251791ba2122a941e6aa781c713e44", + "sha256:9db24803fa71e3305fe4a7812782b708da21a0b774b130dd1860cf40a6d7a3ee", + "sha256:a75c1ad05eedb1a3ff2a34a52a4f0836cfaa892e12796ba39a7732c82701eff4", + "sha256:a77a3470ba37e11872c75ca95baf9b3312133a3d5a5dc720803b23098c653976", + "sha256:ab6db93a2b6b66cbf62b4e4a7135f476e708e8c5c990d186584142c77d7f975a", + "sha256:afd60230ad9d8bcba005945ec3a343722f09e0b7f8ae804246e5d2cfc6bd71a6", + "sha256:b0ca0ada9d3bc18bd6f611bd001a28abdd49ab9698bd6d717f7f5394c8e94628", + "sha256:b567178a74a2261345890eac66fbf394692a6e002709d329f28a673ca6042473", + "sha256:b667c51682fe9b9788c69465956baa8b6999531876ccedcafc895c74ad716cd8", + "sha256:bbf2dc330bd44bfc0254ab37677ec60f7c7ecea55ad8ba1b8b2ea7bf20c265f5", + "sha256:bdc224f216ead849e902151112efef6e96c41ee1322e15d4e5f7c8a826929aee", + "sha256:cf201bf5594d1aab139fe53e3fca457e4f8204a5bbd65d48ab3b82a16f517868", + "sha256:d43bd68714049c84e297c005456a15ecdec818f7b5aa5868c8b0a865cfb78a44", + "sha256:daf9bd1fee31f1c7a5928b3e1059e09a8d683ea58fb3ffc773b6c88cb8d1399c", + "sha256:e678a643177c0e5ec947b645fa7bc84260dfb9b6bf8fb1fdd83008dfc2ca5928", + "sha256:e91d24623e747eeb2d8121f4a94c6a7ad27dc48e747e2dc95bfe88632bd028a2", + "sha256:e95da348d57eb448d226a44b868ff2ca5786fbcbe417ac99ff62d0a7d724b9c7", + "sha256:ee9e4b07b0eba4b6a521509e9e1877476729c1243246b6959de697ebea739643", + "sha256:f5dd358536b8a964bf6bd48de038754c1609e72e5f17f5d21efe2dda17594dbf", + "sha256:ffd65cfa33fed01735c82aca640fde4cc63f0414775cba11e06f84fae2085a6e" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==4.6.3" + "version": "==4.6.4" }, "markdown-it-py": { "hashes": [ @@ -330,6 +446,7 @@ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298", "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64", "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b", + "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194", "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567", "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff", "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724", @@ -337,6 +454,7 @@ "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646", "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35", "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6", + "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a", "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6", "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad", "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26", @@ -344,27 +462,36 @@ "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac", "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7", "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6", + "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047", "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75", "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f", + "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b", "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135", "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8", "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a", "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a", + "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1", "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9", "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864", "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914", + "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee", + "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f", "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18", "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8", "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2", "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d", "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b", "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b", + "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86", + "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6", "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f", "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb", "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833", "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28", + "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e", "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415", "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902", + "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f", "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d", "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9", "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d", @@ -372,10 +499,14 @@ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066", "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c", "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1", + "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a", + "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207", "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f", "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53", + "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd", "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134", "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85", + "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9", "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5", "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94", "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509", @@ -393,6 +524,13 @@ "markers": "python_version ~= '3.6'", "version": "==0.2.8" }, + "mypy-extensions": { + "hashes": [ + "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", + "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8" + ], + "version": "==0.4.3" + }, "myst-parser": { "hashes": [ "sha256:40124b6f27a4c42ac7f06b385e23a9dcd03d84801e9c7130b59b3729a554b1f9", @@ -401,6 +539,14 @@ "markers": "python_version >= '3.6'", "version": "==0.15.2" }, + "oauthlib": { + "hashes": [ + "sha256:42bf6354c2ed8c6acb54d971fce6f88193d97297e18602a3a886603f9d7730cc", + "sha256:8f0215fcc533dd8dd1bee6f4c412d4f0cd7297307d43ac61666389e3bc3198a3" + ], + "markers": "python_version >= '3.6'", + "version": "==3.1.1" + }, "openpyxl": { "hashes": [ "sha256:40f568b9829bf9e446acfffce30250ac1fa39035124d55fc024025c41481c90f", @@ -411,11 +557,11 @@ }, "packaging": { "hashes": [ - "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7", - "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14" + "sha256:096d689d78ca690e4cd8a89568ba06d07ca097e3306a4381635073ca91479966", + "sha256:14317396d1e8cdb122989b916fa2c7e9ca8e2be9e8060a6eff75b6b7b4d8a7e0" ], "markers": "python_version >= '3.6'", - "version": "==21.0" + "version": "==21.2" }, "parse": { "hashes": [ @@ -423,6 +569,28 @@ ], "version": "==1.19.0" }, + "pathspec": { + "hashes": [ + "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a", + "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1" + ], + "version": "==0.9.0" + }, + "platformdirs": { + "hashes": [ + "sha256:367a5e80b3d04d2428ffa76d33f124cf11e8fff2acdaa9b43d545f5c7d661ef2", + "sha256:8868bbe3c3c80d42f20156f22e7131d2fb321f5bc86a2a345375c6481a67021d" + ], + "markers": "python_version >= '3.6'", + "version": "==2.4.0" + }, + "ply": { + "hashes": [ + "sha256:00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3", + "sha256:096f9b8350b65ebd2fd1346b12452efe5b9607f7482813ffca50c22722a807ce" + ], + "version": "==3.11" + }, "prefixcommons": { "hashes": [ "sha256:2ff99e9f2c27f41e6beb831742ca88ddae129b2de6dcc81b0b27f0de69cb2e8a", @@ -438,6 +606,72 @@ ], "version": "==0.0.6" }, + "protobuf": { + "hashes": [ + "sha256:038daf4fa38a7e818dd61f51f22588d61755160a98db087a046f80d66b855942", + "sha256:28ccea56d4dc38d35cd70c43c2da2f40ac0be0a355ef882242e8586c6d66666f", + "sha256:36d90676d6f426718463fe382ec6274909337ca6319d375eebd2044e6c6ac560", + "sha256:3cd0458870ea7d1c58e948ac8078f6ba8a7ecc44a57e03032ed066c5bb318089", + "sha256:5935c8ce02e3d89c7900140a8a42b35bc037ec07a6aeb61cc108be8d3c9438a6", + "sha256:615b426a177780ce381ecd212edc1e0f70db8557ed72560b82096bd36b01bc04", + "sha256:62a8e4baa9cb9e064eb62d1002eca820857ab2138440cb4b3ea4243830f94ca7", + "sha256:655264ed0d0efe47a523e2255fc1106a22f6faab7cc46cfe99b5bae085c2a13e", + "sha256:6e8ea9173403219239cdfd8d946ed101f2ab6ecc025b0fda0c6c713c35c9981d", + "sha256:71b0250b0cfb738442d60cab68abc166de43411f2a4f791d31378590bfb71bd7", + "sha256:74f33edeb4f3b7ed13d567881da8e5a92a72b36495d57d696c2ea1ae0cfee80c", + "sha256:77d2fadcf369b3f22859ab25bd12bb8e98fb11e05d9ff9b7cd45b711c719c002", + "sha256:8b30a7de128c46b5ecb343917d9fa737612a6e8280f440874e5cc2ba0d79b8f6", + "sha256:8e51561d72efd5bd5c91490af1f13e32bcba8dab4643761eb7de3ce18e64a853", + "sha256:a529e7df52204565bcd33738a7a5f288f3d2d37d86caa5d78c458fa5fabbd54d", + "sha256:b691d996c6d0984947c4cf8b7ae2fe372d99b32821d0584f0b90277aa36982d3", + "sha256:d80f80eb175bf5f1169139c2e0c5ada98b1c098e2b3c3736667f28cbbea39fc8", + "sha256:d83e1ef8cb74009bebee3e61cc84b1c9cd04935b72bca0cbc83217d140424995", + "sha256:d8919368410110633717c406ab5c97e8df5ce93020cfcf3012834f28b1fab1ea", + "sha256:db3532d9f7a6ebbe2392041350437953b6d7a792de10e629c1e4f5a6b1fe1ac6", + "sha256:e7b24c11df36ee8e0c085e5b0dc560289e4b58804746fb487287dda51410f1e2", + "sha256:e7e8d2c20921f8da0dea277dfefc6abac05903ceac8e72839b2da519db69206b", + "sha256:e813b1c9006b6399308e917ac5d298f345d95bb31f46f02b60cd92970a9afa17", + "sha256:fd390367fc211cc0ffcf3a9e149dfeca78fecc62adb911371db0cec5c8b7472d" + ], + "markers": "python_version >= '3.5'", + "version": "==3.19.1" + }, + "pyasn1": { + "hashes": [ + "sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359", + "sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576", + "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf", + "sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7", + "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d", + "sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00", + "sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8", + "sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86", + "sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12", + "sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776", + "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba", + "sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2", + "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3" + ], + "version": "==0.4.8" + }, + "pyasn1-modules": { + "hashes": [ + "sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8", + "sha256:0fe1b68d1e486a1ed5473f1302bd991c1611d319bba158e98b106ff86e1d7199", + "sha256:15b7c67fabc7fc240d87fb9aabf999cf82311a6d6fb2c70d00d3d0604878c811", + "sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed", + "sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4", + "sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e", + "sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74", + "sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb", + "sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45", + "sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd", + "sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0", + "sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d", + "sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405" + ], + "version": "==0.2.8" + }, "pygments": { "hashes": [ "sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380", @@ -446,6 +680,14 @@ "markers": "python_version >= '3.5'", "version": "==2.10.0" }, + "pygsheets": { + "hashes": [ + "sha256:85a4c871ac1d53013e042c13552b07f908b991c3d8c8770b3a68eb3452c8c218", + "sha256:ea6ce75dabd1359e49fd36920ff0d25ff9428ccc3d5d2474bdba80fb8653ad80" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.0.5" + }, "pyjsg": { "hashes": [ "sha256:08d9a80f6996af8862e8a2a4e2d90049af695c4ccd84187e7d7a48f600d37952", @@ -513,7 +755,7 @@ "sha256:6f75e26dfda605c994031a72ca74b2b0079e1f7b12ab713e030078d8fa05dc3a", "sha256:ad83bb2a645f64becbf946d4bd170e35fd9b903616c7ee25d5a4ed188cf2d1dd" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==0.8.3" }, "python-dateutil": { @@ -521,15 +763,22 @@ "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", "version": "==2.8.2" }, + "python-dotenv": { + "hashes": [ + "sha256:0c8d1b80d1a1e91717ea7d526178e3882732420b03f08afea0406db6402e220e", + "sha256:587825ed60b1711daea4832cf37524dfd404325b7db5e25ebe88c495c9f807a0" + ], + "version": "==0.15.0" + }, "pytz": { "hashes": [ - "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da", - "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798" + "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c", + "sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326" ], - "version": "==2021.1" + "version": "==2021.3" }, "pyyaml": { "hashes": [ @@ -571,7 +820,6 @@ "sha256:78149dd49d385efec3b3adfbd61c87afaf1281c30d3fcaf1b323b34f603fb155", "sha256:88208ea971a87886d60ae2b1a4b2cdc263527af0454c422118d43fe64b357877" ], - "markers": "python_full_version >= '3.7.0'", "version": "==5.0.0" }, "rdflib-jsonld": { @@ -596,6 +844,60 @@ ], "version": "==0.1.2" }, + "regex": { + "hashes": [ + "sha256:05b7d6d7e64efe309972adab77fc2af8907bb93217ec60aa9fe12a0dad35874f", + "sha256:0617383e2fe465732af4509e61648b77cbe3aee68b6ac8c0b6fe934db90be5cc", + "sha256:07856afef5ffcc052e7eccf3213317fbb94e4a5cd8177a2caa69c980657b3cb4", + "sha256:162abfd74e88001d20cb73ceaffbfe601469923e875caf9118333b1a4aaafdc4", + "sha256:2207ae4f64ad3af399e2d30dde66f0b36ae5c3129b52885f1bffc2f05ec505c8", + "sha256:30ab804ea73972049b7a2a5c62d97687d69b5a60a67adca07eb73a0ddbc9e29f", + "sha256:3b5df18db1fccd66de15aa59c41e4f853b5df7550723d26aa6cb7f40e5d9da5a", + "sha256:3c5fb32cc6077abad3bbf0323067636d93307c9fa93e072771cf9a64d1c0f3ef", + "sha256:416c5f1a188c91e3eb41e9c8787288e707f7d2ebe66e0a6563af280d9b68478f", + "sha256:432bd15d40ed835a51617521d60d0125867f7b88acf653e4ed994a1f8e4995dc", + "sha256:4aaa4e0705ef2b73dd8e36eeb4c868f80f8393f5f4d855e94025ce7ad8525f50", + "sha256:537ca6a3586931b16a85ac38c08cc48f10fc870a5b25e51794c74df843e9966d", + "sha256:53db2c6be8a2710b359bfd3d3aa17ba38f8aa72a82309a12ae99d3c0c3dcd74d", + "sha256:5537f71b6d646f7f5f340562ec4c77b6e1c915f8baae822ea0b7e46c1f09b733", + "sha256:6650f16365f1924d6014d2ea770bde8555b4a39dc9576abb95e3cd1ff0263b36", + "sha256:666abff54e474d28ff42756d94544cdfd42e2ee97065857413b72e8a2d6a6345", + "sha256:68a067c11463de2a37157930d8b153005085e42bcb7ad9ca562d77ba7d1404e0", + "sha256:780b48456a0f0ba4d390e8b5f7c661fdd218934388cde1a974010a965e200e12", + "sha256:788aef3549f1924d5c38263104dae7395bf020a42776d5ec5ea2b0d3d85d6646", + "sha256:7ee1227cf08b6716c85504aebc49ac827eb88fcc6e51564f010f11a406c0a667", + "sha256:7f301b11b9d214f83ddaf689181051e7f48905568b0c7017c04c06dfd065e244", + "sha256:83ee89483672b11f8952b158640d0c0ff02dc43d9cb1b70c1564b49abe92ce29", + "sha256:85bfa6a5413be0ee6c5c4a663668a2cad2cbecdee367630d097d7823041bdeec", + "sha256:9345b6f7ee578bad8e475129ed40123d265464c4cfead6c261fd60fc9de00bcf", + "sha256:93a5051fcf5fad72de73b96f07d30bc29665697fb8ecdfbc474f3452c78adcf4", + "sha256:962b9a917dd7ceacbe5cd424556914cb0d636001e393b43dc886ba31d2a1e449", + "sha256:98ba568e8ae26beb726aeea2273053c717641933836568c2a0278a84987b2a1a", + "sha256:a3feefd5e95871872673b08636f96b61ebef62971eab044f5124fb4dea39919d", + "sha256:b43c2b8a330a490daaef5a47ab114935002b13b3f9dc5da56d5322ff218eeadb", + "sha256:b483c9d00a565633c87abd0aaf27eb5016de23fed952e054ecc19ce32f6a9e7e", + "sha256:ba05430e819e58544e840a68b03b28b6d328aff2e41579037e8bab7653b37d83", + "sha256:ca5f18a75e1256ce07494e245cdb146f5a9267d3c702ebf9b65c7f8bd843431e", + "sha256:d5ca078bb666c4a9d1287a379fe617a6dccd18c3e8a7e6c7e1eb8974330c626a", + "sha256:da1a90c1ddb7531b1d5ff1e171b4ee61f6345119be7351104b67ff413843fe94", + "sha256:dba70f30fd81f8ce6d32ddeef37d91c8948e5d5a4c63242d16a2b2df8143aafc", + "sha256:dd33eb9bdcfbabab3459c9ee651d94c842bc8a05fabc95edf4ee0c15a072495e", + "sha256:e0538c43565ee6e703d3a7c3bdfe4037a5209250e8502c98f20fea6f5fdf2965", + "sha256:e1f54b9b4b6c53369f40028d2dd07a8c374583417ee6ec0ea304e710a20f80a0", + "sha256:e32d2a2b02ccbef10145df9135751abea1f9f076e67a4e261b05f24b94219e36", + "sha256:e71255ba42567d34a13c03968736c5d39bb4a97ce98188fafb27ce981115beec", + "sha256:ed2e07c6a26ed4bea91b897ee2b0835c21716d9a469a96c3e878dc5f8c55bb23", + "sha256:eef2afb0fd1747f33f1ee3e209bce1ed582d1896b240ccc5e2697e3275f037c7", + "sha256:f23222527b307970e383433daec128d769ff778d9b29343fb3496472dc20dabe", + "sha256:f341ee2df0999bfdf7a95e448075effe0db212a59387de1a70690e4acb03d4c6", + "sha256:f7f325be2804246a75a4f45c72d4ce80d2443ab815063cdf70ee8fb2ca59ee1b", + "sha256:f8af619e3be812a2059b212064ea7a640aff0568d972cd1b9e920837469eb3cb", + "sha256:fa8c626d6441e2d04b6ee703ef2d1e17608ad44c7cb75258c09dd42bacdfc64b", + "sha256:fbb9dc00e39f3e6c0ef48edee202f9520dafb233e8b51b06b8428cfcb92abd30", + "sha256:fff55f3ce50a3ff63ec8e2a8d3dd924f1941b250b0aac3d3d42b687eeff07a8e" + ], + "version": "==2021.11.10" + }, "requests": { "hashes": [ "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24", @@ -604,6 +906,65 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", "version": "==2.26.0" }, + "requests-oauthlib": { + "hashes": [ + "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d", + "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a", + "sha256:fa6c47b933f01060936d87ae9327fead68768b69c6c9ea2109c48be30f2d4dbc" + ], + "version": "==1.3.0" + }, + "rsa": { + "hashes": [ + "sha256:78f9a9bf4e7be0c5ded4583326e7461e3a3c5aae24073648b4bdfa797d78c9d2", + "sha256:9d689e6ca1b3038bc82bf8d23e944b6b6037bc02301a574935b2dd946e0353b9" + ], + "markers": "python_version >= '3.6'", + "version": "==4.7.2" + }, + "ruamel.yaml": { + "hashes": [ + "sha256:9751de4cbb57d4bfbf8fc394e125ed4a2f170fbff3dc3d78abf50be85924f8be", + "sha256:9af3ec5d7f8065582f3aa841305465025d0afd26c5fb54e15b964e11838fc74f" + ], + "markers": "python_version >= '3'", + "version": "==0.17.17" + }, + "ruamel.yaml.clib": { + "hashes": [ + "sha256:0847201b767447fc33b9c235780d3aa90357d20dd6108b92be544427bea197dd", + "sha256:1866cf2c284a03b9524a5cc00daca56d80057c5ce3cdc86a52020f4c720856f0", + "sha256:31ea73e564a7b5fbbe8188ab8b334393e06d997914a4e184975348f204790277", + "sha256:3fb9575a5acd13031c57a62cc7823e5d2ff8bc3835ba4d94b921b4e6ee664104", + "sha256:4ff604ce439abb20794f05613c374759ce10e3595d1867764dd1ae675b85acbd", + "sha256:72a2b8b2ff0a627496aad76f37a652bcef400fd861721744201ef1b45199ab78", + "sha256:78988ed190206672da0f5d50c61afef8f67daa718d614377dcd5e3ed85ab4a99", + "sha256:7b2927e92feb51d830f531de4ccb11b320255ee95e791022555971c466af4527", + "sha256:7f7ecb53ae6848f959db6ae93bdff1740e651809780822270eab111500842a84", + "sha256:825d5fccef6da42f3c8eccd4281af399f21c02b32d98e113dbc631ea6a6ecbc7", + "sha256:846fc8336443106fe23f9b6d6b8c14a53d38cef9a375149d61f99d78782ea468", + "sha256:89221ec6d6026f8ae859c09b9718799fea22c0e8da8b766b0b2c9a9ba2db326b", + "sha256:9efef4aab5353387b07f6b22ace0867032b900d8e91674b5d8ea9150db5cae94", + "sha256:a32f8d81ea0c6173ab1b3da956869114cae53ba1e9f72374032e33ba3118c233", + "sha256:a49e0161897901d1ac9c4a79984b8410f450565bbad64dbfcbf76152743a0cdb", + "sha256:ada3f400d9923a190ea8b59c8f60680c4ef8a4b0dfae134d2f2ff68429adfab5", + "sha256:bf75d28fa071645c529b5474a550a44686821decebdd00e21127ef1fd566eabe", + "sha256:cfdb9389d888c5b74af297e51ce357b800dd844898af9d4a547ffc143fa56751", + "sha256:d67f273097c368265a7b81e152e07fb90ed395df6e552b9fa858c6d2c9f42502", + "sha256:dc6a613d6c74eef5a14a214d433d06291526145431c3b964f5e16529b1842bed", + "sha256:de9c6b8a1ba52919ae919f3ae96abb72b994dd0350226e28f3686cb4f142165c" + ], + "markers": "platform_python_implementation == 'CPython' and python_version < '3.10'", + "version": "==0.2.6" + }, + "sheet2linkml": { + "hashes": [ + "sha256:1f7885036de8124409fb59d3e65a4114d42a19a4ff5f3bd1f93c8e42a06dd451", + "sha256:32160a5dbefe05e95ae9af069ab36cff2bff03855c01049cb61f386c99ecda6b" + ], + "index": "pypi", + "version": "==1.1.0" + }, "shexjsg": { "hashes": [ "sha256:788991c4df2ca9b24258fb68c94107c3e140c70bbe398fb15f00338d2a9155e5", @@ -616,7 +977,7 @@ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", "version": "==1.16.0" }, "snowballstemmer": { @@ -654,11 +1015,11 @@ }, "sphinx-click": { "hashes": [ - "sha256:9b24c46f3b8f25fc639f47c97ac0361d9f80d48c2ed6b3917de2865bbdbe1785", - "sha256:e9ee2237e5a6b6620e9996b8214934afdf8f7f9f9fc082482c77be0e4379038e" + "sha256:29896dd12bfaacb566a8c7af2e2b675d010d69b0c5aad3b52495d4842358b15b", + "sha256:8529a02bea8cd2cd47daba2f71d7935c727c89d70baabec7fca31af49a0c379f" ], "markers": "python_version >= '3.6'", - "version": "==3.0.1" + "version": "==3.0.2" }, "sphinx-rtd-theme": { "hashes": [ @@ -718,46 +1079,76 @@ }, "sqlalchemy": { "hashes": [ - "sha256:0566a6e90951590c0307c75f9176597c88ef4be2724958ca1d28e8ae05ec8822", - "sha256:08d9396a2a38e672133266b31ed39b2b1f2b5ec712b5bff5e08033970563316a", - "sha256:0b08a53e40b34205acfeb5328b832f44437956d673a6c09fce55c66ab0e54916", - "sha256:16ef07e102d2d4f974ba9b0d4ac46345a411ad20ad988b3654d59ff08e553b1c", - "sha256:1adf3d25e2e33afbcd48cfad8076f9378793be43e7fec3e4334306cac6bec138", - "sha256:1b38db2417b9f7005d6ceba7ce2a526bf10e3f6f635c0f163e6ed6a42b5b62b2", - "sha256:1ebd69365717becaa1b618220a3df97f7c08aa68e759491de516d1c3667bba54", - "sha256:26b0cd2d5c7ea96d3230cb20acac3d89de3b593339c1447b4d64bfcf4eac1110", - "sha256:2ed67aae8cde4d32aacbdba4f7f38183d14443b714498eada5e5a7a37769c0b7", - "sha256:33a1e86abad782e90976de36150d910748b58e02cd7d35680d441f9a76806c18", - "sha256:41a916d815a3a23cb7fff8d11ad0c9b93369ac074e91e428075e088fe57d5358", - "sha256:6003771ea597346ab1e97f2f58405c6cacbf6a308af3d28a9201a643c0ac7bb3", - "sha256:6400b22e4e41cc27623a9a75630b7719579cd9a3a2027bcf16ad5aaa9a7806c0", - "sha256:6b602e3351f59f3999e9fb8b87e5b95cb2faab6a6ecdb482382ac6fdfbee5266", - "sha256:75cd5d48389a7635393ff5a9214b90695c06b3d74912109c3b00ce7392b69c6c", - "sha256:7ad59e2e16578b6c1a2873e4888134112365605b08a6067dd91e899e026efa1c", - "sha256:7b7778a205f956755e05721eebf9f11a6ac18b2409bff5db53ce5fe7ede79831", - "sha256:842c49dd584aedd75c2ee05f6c950730c3ffcddd21c5824ed0f820808387e1e3", - "sha256:90fe429285b171bcc252e21515703bdc2a4721008d1f13aa5b7150336f8a8493", - "sha256:91cd87d1de0111eaca11ccc3d31af441c753fa2bc22df72e5009cfb0a1af5b03", - "sha256:9a1df8c93a0dd9cef0839917f0c6c49f46c75810cf8852be49884da4a7de3c59", - "sha256:9ebe49c3960aa2219292ea2e5df6acdc425fc828f2f3d50b4cfae1692bcb5f02", - "sha256:a28fe28c359835f3be20c89efd517b35e8f97dbb2ca09c6cf0d9ac07f62d7ef6", - "sha256:a36ea43919e51b0de0c0bc52bcfdad7683f6ea9fb81b340cdabb9df0e045e0f7", - "sha256:a505ecc0642f52e7c65afb02cc6181377d833b7df0994ecde15943b18d0fa89c", - "sha256:a79abdb404d9256afb8aeaa0d3a4bc7d3b6d8b66103d8b0f2f91febd3909976e", - "sha256:c211e8ec81522ce87b0b39f0cf0712c998d4305a030459a0e115a2b3dc71598f", - "sha256:dd4ed12a775f2cde4519f4267d3601990a97d8ecde5c944ab06bfd6e8e8ea177", - "sha256:e37621b37c73b034997b5116678862f38ee70e5a054821c7b19d0e55df270dec", - "sha256:e93978993a2ad0af43f132be3ea8805f56b2f2cd223403ec28d3e7d5c6d39ed1" + "sha256:07ac4461a1116b317519ddf6f34bcb00b011b5c1370ebeaaf56595504ffc7e84", + "sha256:090536fd23bf49077ee94ff97142bc5ee8bad24294c3d7c8d5284267c885dde7", + "sha256:1dee515578d04bc80c4f9a8c8cfe93f455db725059e885f1b1da174d91c4d077", + "sha256:1ef37c9ec2015ce2f0dc1084514e197f2f199d3dc3514190db7620b78e6004c8", + "sha256:295b90efef1278f27fe27d94a45460ae3c17f5c5c2b32c163e29c359740a1599", + "sha256:2ce42ad1f59eb85c55c44fb505f8854081ee23748f76b62a7f569cfa9b6d0604", + "sha256:2feb028dc75e13ba93456a42ac042b255bf94dbd692bf80b47b22653bb25ccf8", + "sha256:31f4426cfad19b5a50d07153146b2bcb372a279975d5fa39f98883c0ef0f3313", + "sha256:3c0c5f54560a92691d54b0768d67b4d3159e514b426cfcb1258af8c195577e8f", + "sha256:463ef692259ff8189be42223e433542347ae17e33f91c1013e9c5c64e2798088", + "sha256:4a882dedb9dfa6f33524953c3e3d72bcf518a5defd6d5863150a821928b19ad3", + "sha256:4c185c928e2638af9bae13acc3f70e0096eac76471a1101a10f96b80666b8270", + "sha256:5039faa365e7522a8eb4736a54afd24a7e75dcc33b81ab2f0e6c456140f1ad64", + "sha256:5c6774b34782116ad9bdec61c2dbce9faaca4b166a0bc8e7b03c2b870b121d94", + "sha256:6bc7f9d7d90ef55e8c6db1308a8619cd8f40e24a34f759119b95e7284dca351a", + "sha256:7e8ef103eaa72a857746fd57dda5b8b5961e8e82a528a3f8b7e2884d8506f0b7", + "sha256:7ef421c3887b39c6f352e5022a53ac18de8387de331130481cb956b2d029cad6", + "sha256:908fad32c53b17aad12d722379150c3c5317c422437e44032256a77df1746292", + "sha256:91efbda4e6d311812f23996242bad7665c1392209554f8a31ec6db757456db5c", + "sha256:a6506c17b0b6016656783232d0bdd03fd333f1f654d51a14d93223f953903646", + "sha256:a95bf9c725012dcd7ea3cac16bf647054e0d62b31d67467d228338e6a163e4ff", + "sha256:ad7e403fc1e3cb76e802872694e30d6ca6129b9bc6ad4e7caa48ca35f8a144f8", + "sha256:b86f762cee3709722ab4691981958cbec475ea43406a6916a7ec375db9cbd9e9", + "sha256:ba84026e84379326bbf2f0c50792f2ae56ab9c01937df5597b6893810b8ca369", + "sha256:bca660b76672e15d70a7dba5e703e1ce451a0257b6bd2028e62b0487885e8ae9", + "sha256:c24c01dcd03426a5fe5ee7af735906bec6084977b9027a3605d11d949a565c01", + "sha256:c2f2114b0968a280f94deeeaa31cfbac9175e6ac7bd3058b3ce6e054ecd762b3", + "sha256:c46f013ff31b80cbe36410281675e1fb4eaf3e25c284fd8a69981c73f6fa4cb4", + "sha256:c757ba1279b85b3460e72e8b92239dae6f8b060a75fb24b3d9be984dd78cfa55", + "sha256:cc6b21f19bc9d4cd77cbcba5f3b260436ce033f1053cea225b6efea2603d201e", + "sha256:dbf588ab09e522ac2cbd010919a592c6aae2f15ccc3cd9a96d01c42fbc13f63e", + "sha256:de996756d894a2d52c132742e3b6d64ecd37e0919ddadf4dc3981818777c7e67", + "sha256:e700d48056475d077f867e6a36e58546de71bdb6fdc3d34b879e3240827fefab", + "sha256:f1e97c5f36b94542f72917b62f3a2f92be914b2cf33b80fa69cede7529241d2a", + "sha256:fb2aa74a6e3c2cebea38dd21633671841fbe70ea486053cba33d68e3e22ccc0a", + "sha256:ff8f91a7b1c4a1c7772caa9efe640f2768828897044748f2458b708f1026e2d4" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==1.4.25" + "version": "==1.4.26" }, "testfixtures": { "hashes": [ - "sha256:61c25cb0213f68d2dcd2b098d9d2e7f47afc3b4429d66e1cdeb1072be2fcb241", - "sha256:9c2316232de0ef6915d5446dcccaec9c4a6092751ba2ff7d30b9c14a954a90e3" + "sha256:2600100ae96ffd082334b378e355550fef8b4a529a6fa4c34f47130905c7426d", + "sha256:6ddb7f56a123e1a9339f130a200359092bd0a6455e31838d6c477e8729bb7763" + ], + "version": "==6.18.3" + }, + "tomli": { + "hashes": [ + "sha256:c6ce0015eb38820eaf32b5db832dbc26deb3dd427bd5f6556cf0acac2c214fee", + "sha256:f04066f68f5554911363063a30b108d2b5a5b1a010aa8b6132af78489fe3aade" + ], + "markers": "python_version >= '3.6'", + "version": "==1.2.2" + }, + "typing-extensions": { + "hashes": [ + "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e", + "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7", + "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34" ], - "version": "==6.18.2" + "version": "==3.10.0.2" + }, + "uritemplate": { + "hashes": [ + "sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0", + "sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e" + ], + "markers": "python_version >= '3.6'", + "version": "==4.1.1" }, "urllib3": { "hashes": [ @@ -769,93 +1160,92 @@ }, "watchdog": { "hashes": [ - "sha256:28777dbed3bbd95f9c70f461443990a36c07dbf49ae7cd69932cdd1b8fb2850c", - "sha256:41d44ef21a77a32b55ce9bf59b75777063751f688de51098859b7c7f6466589a", - "sha256:43bf728eb7830559f329864ab5da2302c15b2efbac24ad84ccc09949ba753c40", - "sha256:50a7f81f99d238f72185f481b493f9de80096e046935b60ea78e1276f3d76960", - "sha256:51af09ae937ada0e9a10cc16988ec03c649754a91526170b6839b89fc56d6acb", - "sha256:5563b005907613430ef3d4aaac9c78600dd5704e84764cb6deda4b3d72807f09", - "sha256:58ae842300cbfe5e62fb068c83901abe76e4f413234b7bec5446e4275eb1f9cb", - "sha256:59767f476cd1f48531bf378f0300565d879688c82da8369ca8c52f633299523c", - "sha256:5cf78f794c9d7bc64a626ef4f71aff88f57a7ae288e0b359a9c6ea711a41395f", - "sha256:5f57ce4f7e498278fb2a091f39359930144a0f2f90ea8cbf4523c4e25de34028", - "sha256:6f3ad1d973fe8fc8fe64ba38f6a934b74346342fa98ef08ad5da361a05d46044", - "sha256:78b1514067ff4089f4dac930b043a142997a5b98553120919005e97fbaba6546", - "sha256:814d396859c95598f7576d15bc257c3bd3ba61fa4bc1db7dfc18f09070ded7da", - "sha256:8874d5ad6b7f43b18935d9b0183e29727a623a216693d6938d07dfd411ba462f", - "sha256:8b74d0d92a69a7ab5f101f9fe74e44ba017be269efa824337366ccbb4effde85", - "sha256:9391003635aa783957b9b11175d9802d3272ed67e69ef2e3394c0b6d9d24fa9a", - "sha256:a2888a788893c4ef7e562861ec5433875b7915f930a5a7ed3d32c048158f1be5", - "sha256:a7053d4d22dc95c5e0c90aeeae1e4ed5269d2f04001798eec43a654a03008d22", - "sha256:b0cc7d8b7d60da6c313779d85903ce39a63d89d866014b085f720a083d5f3e9a", - "sha256:e40e33a4889382824846b4baa05634e1365b47c6fa40071dc2d06b4d7c715fc1", - "sha256:e60d3bb7166b7cb830b86938d1eb0e6cfe23dfd634cce05c128f8f9967895193", - "sha256:eab14adfc417c2c983fbcb2c73ef3f28ba6990d1fff45d1180bf7e38bda0d98d", - "sha256:ed4ca4351cd2bb0d863ee737a2011ca44d8d8be19b43509bd4507f8a449b376b" + "sha256:25fb5240b195d17de949588628fdf93032ebf163524ef08933db0ea1f99bd685", + "sha256:3386b367e950a11b0568062b70cc026c6f645428a698d33d39e013aaeda4cc04", + "sha256:3becdb380d8916c873ad512f1701f8a92ce79ec6978ffde92919fd18d41da7fb", + "sha256:4ae38bf8ba6f39d5b83f78661273216e7db5b00f08be7592062cb1fc8b8ba542", + "sha256:8047da932432aa32c515ec1447ea79ce578d0559362ca3605f8e9568f844e3c6", + "sha256:8f1c00aa35f504197561060ca4c21d3cc079ba29cf6dd2fe61024c70160c990b", + "sha256:922a69fa533cb0c793b483becaaa0845f655151e7256ec73630a1b2e9ebcb660", + "sha256:9693f35162dc6208d10b10ddf0458cc09ad70c30ba689d9206e02cd836ce28a3", + "sha256:a0f1c7edf116a12f7245be06120b1852275f9506a7d90227648b250755a03923", + "sha256:a36e75df6c767cbf46f61a91c70b3ba71811dfa0aca4a324d9407a06a8b7a2e7", + "sha256:aba5c812f8ee8a3ff3be51887ca2d55fb8e268439ed44110d3846e4229eb0e8b", + "sha256:ad6f1796e37db2223d2a3f302f586f74c72c630b48a9872c1e7ae8e92e0ab669", + "sha256:ae67501c95606072aafa865b6ed47343ac6484472a2f95490ba151f6347acfc2", + "sha256:b2fcf9402fde2672545b139694284dc3b665fd1be660d73eca6805197ef776a3", + "sha256:b52b88021b9541a60531142b0a451baca08d28b74a723d0c99b13c8c8d48d604", + "sha256:b7d336912853d7b77f9b2c24eeed6a5065d0a0cc0d3b6a5a45ad6d1d05fb8cd8", + "sha256:bd9ba4f332cf57b2c1f698be0728c020399ef3040577cde2939f2e045b39c1e5", + "sha256:be9be735f827820a06340dff2ddea1fb7234561fa5e6300a62fe7f54d40546a0", + "sha256:cca7741c0fcc765568350cb139e92b7f9f3c9a08c4f32591d18ab0a6ac9e71b6", + "sha256:d0d19fb2441947b58fbf91336638c2b9f4cc98e05e1045404d7a4cb7cddc7a65", + "sha256:e02794ac791662a5eafc6ffeaf9bcc149035a0e48eb0a9d40a8feb4622605a3d", + "sha256:e0f30db709c939cabf64a6dc5babb276e6d823fd84464ab916f9b9ba5623ca15", + "sha256:e92c2d33858c8f560671b448205a268096e17870dcf60a9bb3ac7bfbafb7f5f9" ], "markers": "python_version >= '3.6'", - "version": "==2.1.5" + "version": "==2.1.6" }, "wrapt": { "hashes": [ - "sha256:0977368a60477690475b64c823a74fc5aaba553aadc1b7aaf9c0f3847fa51b4d", - "sha256:0ed3de6474eb2e390fb4ab42146c2aba2c7b239f94f9f5730481e83bb8307d9a", - "sha256:11b4d21fac4d9eebb9d4dc092858bb9e43dca13738e4a41531f86ba913d25830", - "sha256:148d6660efe876d782a3ae38a6cb501d74a675248b4e2b618c80308c1ee9c521", - "sha256:149b2a2b1dc8d09eb17cbc4a56d30af4f26203a0f177f27d3e12764d7128e0d4", - "sha256:14dcfec369c1de945dbdf80d9c5ff4c45dd2700f5f44ebd5419246856a33ca63", - "sha256:1882e6553e7e16bfa9ab749615d593c22fd9c783b1e288124b9495e9b1bfdb7f", - "sha256:29df7b9e903bba0997198b3bd5aa68411ca47d83d7adf735874e99193cef593e", - "sha256:2d7ae97f13c610042abd3772442ee0946555ccbce53d292b0a9784e39bc4bf12", - "sha256:30f5a4f465375af4108c1d8ea6bec1c0641b57acd01b75d4046ffce66cbb31af", - "sha256:368322e9c42584ab399a460457126f0ef4ba25496480b6bbfc9511db3af69594", - "sha256:448084bc3da81f325980a7499e311e81e6de442cc87d9253b758f75636854e5d", - "sha256:54a207e6c5f594b7b0feff4c7ff9a25325c126d78ee85081f3a43b7d843a9575", - "sha256:5cf7d121a5a7610b554e907e31898ad42d62a2f98364360e4777eeb901e832a1", - "sha256:5ebdb122fbe96f0393c7d3dafe9fecf11bafc5e8b6d18a3fcfb833e8e0a276ec", - "sha256:7476e7bbf9c1d88fc150c77f119581ec02a05e663ff2af585e39392723aa38c2", - "sha256:75d2a7b5fc55211654647972eb7c06b53b3494c6a7b4043bc2180c1f1d9b583e", - "sha256:77503a832ece9d3068c37d2c69cd9046c4b6f244daf6a017b099ea1a1c35543b", - "sha256:7dd7bc9879cf69de61bda7366c82955b57c3182c1b49975ea96288452680f9b5", - "sha256:85395b84e60cc41b98f61258b3a3d469f30b265eb28f56ee6564390321b88913", - "sha256:85aa0beef8193aea3a20f2628d851b94fbcfa11488aabdb86b775e4e468756a2", - "sha256:8717908295b031d5e0ad2bc5dec0959edff4eafa871ea3375e920807514d93aa", - "sha256:881886a8c9a6431c56c17ff654978e681f5c8c77021cdbb5d3e402dec72f1f44", - "sha256:961cde92188e34a3b9d15210df8c382a207b0a798d07dadc8f50ba1ae6239fdc", - "sha256:9c8a6a27b6160b7c1c6c901257434c842b9a54849f4c939b8a3783bef636b810", - "sha256:9f3e23a2724df54584ca5d0c24997efb3bd29a1c66ec7863ff004983d73676e8", - "sha256:a1e462257c7fda7edef613afa6de7ce9b5dec215b9fd41d5e0c424a92b94af35", - "sha256:b123ae57edd6f6dbee58755dd7f7db92607319a6929b79354700450186f4273f", - "sha256:b1c92036e159ddc4a1f6f9e5fbd92289a0953a79a3baffb143ae98c70530b876", - "sha256:b22dae64b5d1bc94b87455febf18f7b84f2c4a4ca671be0db49a87e8e84f13b3", - "sha256:bafafa51acc2143368ff39b994f00472a4b478c9959fbb9ac3a3edd4b2255848", - "sha256:be27bd352bfa23bc634bfdeea58c51773a7877205cf997a89a9ceafa8fb78cd6", - "sha256:bf1665c98bdc407cf5e57c21044542603b08618bac1ba4a5056e01d81e0c5e1a", - "sha256:c0ea863046df494d8bd982a8a4b98e0d7d12398d55e94c26750d88aaeaf98934", - "sha256:ccfa5710b65d3cb06f9ff91fd23d0fa4a8c9bbfee15359063eeaec78cc72cea4", - "sha256:cde98cc650d6c85301838609ee0ccd6b8ced3ed2ff4bdc28d4d6decf03fa9be7", - "sha256:ce26a6947368841837f22686e4e57144fe5d8e5297fea3eb716aa5a284934633", - "sha256:e23381228770eaa81451a5c75268bb40fcf40bb2e74f40d5288b29f1787c8caa", - "sha256:edf79fb41cb4346b5d4e52a18a60db3ab61280e808df1ba2840d06817d02ef19", - "sha256:ee3a5938747e8b9d5b2770decac9ff212770f65b23c6b20d1a1074137f653fb9", - "sha256:efc075c27ef9151eebe421c0cf1786c27afac8653d892ae084d44771da664f4c", - "sha256:f44ced4de15ec5627a7dffb1fdc071381361a99b34c3d59c365df1e1b9aafc06", - "sha256:f92d512e804b109d8af3e2df249bd532ac754bbd35b29c5d665c4694ccb7d0ec", - "sha256:fa0eb9c5a58340c6e3aaaed23c7c95a06754593a1000174771f960eb8e2ceb13", - "sha256:fd5e0f964e0f00f5870cac49de0b645678652d06b54bf4877f4968e58dc622f5" + "sha256:086218a72ec7d986a3eddb7707c8c4526d677c7b35e355875a0fe2918b059179", + "sha256:0877fe981fd76b183711d767500e6b3111378ed2043c145e21816ee589d91096", + "sha256:0a017a667d1f7411816e4bf214646d0ad5b1da2c1ea13dec6c162736ff25a374", + "sha256:0cb23d36ed03bf46b894cfec777eec754146d68429c30431c99ef28482b5c1df", + "sha256:1fea9cd438686e6682271d36f3481a9f3636195578bab9ca3382e2f5f01fc185", + "sha256:220a869982ea9023e163ba915077816ca439489de6d2c09089b219f4e11b6785", + "sha256:25b1b1d5df495d82be1c9d2fad408f7ce5ca8a38085e2da41bb63c914baadff7", + "sha256:2dded5496e8f1592ec27079b28b6ad2a1ef0b9296d270f77b8e4a3a796cf6909", + "sha256:2ebdde19cd3c8cdf8df3fc165bc7827334bc4e353465048b36f7deeae8ee0918", + "sha256:43e69ffe47e3609a6aec0fe723001c60c65305784d964f5007d5b4fb1bc6bf33", + "sha256:46f7f3af321a573fc0c3586612db4decb7eb37172af1bc6173d81f5b66c2e068", + "sha256:47f0a183743e7f71f29e4e21574ad3fa95676136f45b91afcf83f6a050914829", + "sha256:498e6217523111d07cd67e87a791f5e9ee769f9241fcf8a379696e25806965af", + "sha256:4b9c458732450ec42578b5642ac53e312092acf8c0bfce140ada5ca1ac556f79", + "sha256:51799ca950cfee9396a87f4a1240622ac38973b6df5ef7a41e7f0b98797099ce", + "sha256:5601f44a0f38fed36cc07db004f0eedeaadbdcec90e4e90509480e7e6060a5bc", + "sha256:5f223101f21cfd41deec8ce3889dc59f88a59b409db028c469c9b20cfeefbe36", + "sha256:610f5f83dd1e0ad40254c306f4764fcdc846641f120c3cf424ff57a19d5f7ade", + "sha256:6a03d9917aee887690aa3f1747ce634e610f6db6f6b332b35c2dd89412912bca", + "sha256:705e2af1f7be4707e49ced9153f8d72131090e52be9278b5dbb1498c749a1e32", + "sha256:766b32c762e07e26f50d8a3468e3b4228b3736c805018e4b0ec8cc01ecd88125", + "sha256:77416e6b17926d953b5c666a3cb718d5945df63ecf922af0ee576206d7033b5e", + "sha256:778fd096ee96890c10ce96187c76b3e99b2da44e08c9e24d5652f356873f6709", + "sha256:78dea98c81915bbf510eb6a3c9c24915e4660302937b9ae05a0947164248020f", + "sha256:7dd215e4e8514004c8d810a73e342c536547038fb130205ec4bba9f5de35d45b", + "sha256:7dde79d007cd6dfa65afe404766057c2409316135cb892be4b1c768e3f3a11cb", + "sha256:81bd7c90d28a4b2e1df135bfbd7c23aee3050078ca6441bead44c42483f9ebfb", + "sha256:85148f4225287b6a0665eef08a178c15097366d46b210574a658c1ff5b377489", + "sha256:865c0b50003616f05858b22174c40ffc27a38e67359fa1495605f96125f76640", + "sha256:87883690cae293541e08ba2da22cacaae0a092e0ed56bbba8d018cc486fbafbb", + "sha256:8aab36778fa9bba1a8f06a4919556f9f8c7b33102bd71b3ab307bb3fecb21851", + "sha256:8c73c1a2ec7c98d7eaded149f6d225a692caa1bd7b2401a14125446e9e90410d", + "sha256:936503cb0a6ed28dbfa87e8fcd0a56458822144e9d11a49ccee6d9a8adb2ac44", + "sha256:944b180f61f5e36c0634d3202ba8509b986b5fbaf57db3e94df11abee244ba13", + "sha256:96b81ae75591a795d8c90edc0bfaab44d3d41ffc1aae4d994c5aa21d9b8e19a2", + "sha256:981da26722bebb9247a0601e2922cedf8bb7a600e89c852d063313102de6f2cb", + "sha256:ae9de71eb60940e58207f8e71fe113c639da42adb02fb2bcbcaccc1ccecd092b", + "sha256:b73d4b78807bd299b38e4598b8e7bd34ed55d480160d2e7fdaabd9931afa65f9", + "sha256:d4a5f6146cfa5c7ba0134249665acd322a70d1ea61732723c7d3e8cc0fa80755", + "sha256:dd91006848eb55af2159375134d724032a2d1d13bcc6f81cd8d3ed9f2b8e846c", + "sha256:e05e60ff3b2b0342153be4d1b597bbcfd8330890056b9619f4ad6b8d5c96a81a", + "sha256:e6906d6f48437dfd80464f7d7af1740eadc572b9f7a4301e7dd3d65db285cacf", + "sha256:e92d0d4fa68ea0c02d39f1e2f9cb5bc4b4a71e8c442207433d8db47ee79d7aa3", + "sha256:e94b7d9deaa4cc7bac9198a58a7240aaf87fe56c6277ee25fa5b3aa1edebd229", + "sha256:ea3e746e29d4000cd98d572f3ee2a6050a4f784bb536f4ac1f035987fc1ed83e", + "sha256:ec7e20258ecc5174029a0f391e1b948bf2906cd64c198a9b8b281b811cbc04de", + "sha256:ec9465dd69d5657b5d2fa6133b3e1e989ae27d29471a672416fd729b429eb554", + "sha256:f122ccd12fdc69628786d0c947bdd9cb2733be8f800d88b5a37c57f1f1d73c10", + "sha256:f99c0489258086308aad4ae57da9e8ecf9e1f3f30fa35d5e170b4d4896554d80", + "sha256:f9c51d9af9abb899bd34ace878fbec8bf357b3194a10c4e8e0a25512826ef056", + "sha256:fd76c47f20984b43d93de9a82011bb6e5f8325df6c9ed4d8310029a55fa361ea" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.13.0rc3" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==1.13.3" } }, "develop": { - "appdirs": { - "hashes": [ - "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41", - "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128" - ], - "version": "==1.4.4" - }, "attrs": { "hashes": [ "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1", @@ -866,19 +1256,11 @@ }, "backports.entry-points-selectable": { "hashes": [ - "sha256:988468260ec1c196dab6ae1149260e2f5472c9110334e5d51adcb77867361f6a", - "sha256:a6d9a871cde5e15b4c4a53e3d43ba890cc6861ec1332c9c2428c92f977192acc" + "sha256:7fceed9532a7aa2bd888654a7314f864a3c16a4e710b34a58cfc0f08114c663b", + "sha256:914b21a479fde881635f7af5adc7f6e38d6b274be32269070c53b698c60d5386" ], "markers": "python_version >= '2.7'", - "version": "==1.1.0" - }, - "black": { - "hashes": [ - "sha256:23695358dbcb3deafe7f0a3ad89feee5999a46be5fec21f4f1d108be0bcdb3b1", - "sha256:8a60071a0043876a4ae96e6c69bd3a127dad2c1ca7c8083573eb82f92705d008" - ], - "index": "pypi", - "version": "==v21.5b1" + "version": "==1.1.1" }, "bleach": { "hashes": [ @@ -890,18 +1272,18 @@ }, "cachetools": { "hashes": [ - "sha256:2cc0b89715337ab6dbba85b5b50effe2b0c74e035d83ee8ed637cf52f12ae001", - "sha256:61b5ed1e22a0924aed1d23b478f37e8d52549ff8a961de2909c69bf950020cff" + "sha256:89ea6f1b638d5a73a4f9226be57ac5e4f399d22770b92355f92dcb0f7f001693", + "sha256:92971d3cb7d2a97efff7c7bb1657f21a8f5fb309a37530537c71b1774189f2d1" ], "markers": "python_version ~= '3.5'", - "version": "==4.2.2" + "version": "==4.2.4" }, "certifi": { "hashes": [ - "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee", - "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8" + "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872", + "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569" ], - "version": "==2021.5.30" + "version": "==2021.10.8" }, "chardet": { "hashes": [ @@ -913,11 +1295,11 @@ }, "charset-normalizer": { "hashes": [ - "sha256:5d209c0a931f215cee683b6445e2d77677e7e75e159f78def0db09d68fafcaa6", - "sha256:5ec46d183433dcbd0ab716f2d7f29d8dee50505b3fdb40c6b985c7c4f5a3591f" + "sha256:e019de665e2bcf9c2b64e2e5aa025fa991da8720daa3c1138cadd2fd1856aed0", + "sha256:f7af805c321bfa1ce6714c51f254e0d5bb5e5834039bc17db7ebe3a4cec9492b" ], "markers": "python_version >= '3'", - "version": "==2.0.6" + "version": "==2.0.7" }, "click": { "hashes": [ @@ -952,86 +1334,34 @@ }, "filelock": { "hashes": [ - "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59", - "sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836" - ], - "version": "==3.0.12" - }, - "ghp-import": { - "hashes": [ - "sha256:753de2eace6e0f7d4edfb3cce5e3c3b98cd52aadb80163303d1d036bda7b4483" - ], - "version": "==2.0.1" - }, - "google-api-core": { - "hashes": [ - "sha256:b8ad41f72a70dd709dd13a08478936172aecf5f2d34a18ab378efa6d2d6ab575", - "sha256:d6760f21b3a064a8397916b33be7383fc169d1a3c3d7fae7b47eb92bba7892b8" + "sha256:7afc856f74fa7006a289fd10fa840e1eebd8bbff6bffb69c26c54a0512ea8cf8", + "sha256:bb2a1c717df74c48a2d00ed625e5a66f8572a3a30baacb7657add1d7bac4097b" ], "markers": "python_version >= '3.6'", - "version": "==2.0.1" + "version": "==3.3.2" }, - "google-api-python-client": { - "hashes": [ - "sha256:835892df0dcaac64aef20929d817290bc89a671ea3a91b28fb9f9489b12f069f", - "sha256:982c5333e1ad4a083d6723a02a5a89ebf53c2832101180d6f82213e9322251ab" - ], - "markers": "python_version >= '3.6'", - "version": "==2.22.0" - }, - "google-auth": { - "hashes": [ - "sha256:7ae5eda089d393ca01658b550df24913cbbbdd34e9e6dedc1cea747485ae0c04", - "sha256:bde03220ed56e4e147dec92339c90ce95159dce657e2cccd0ac1fe82f6a96284" - ], - "markers": "python_version >= '3.6'", - "version": "==2.1.0" - }, - "google-auth-httplib2": { - "hashes": [ - "sha256:31e49c36c6b5643b57e82617cb3e021e3e1d2df9da63af67252c02fa9c1f4a10", - "sha256:a07c39fd632becacd3f07718dfd6021bf396978f03ad3ce4321d060015cc30ac" - ], - "version": "==0.1.0" - }, - "google-auth-oauthlib": { - "hashes": [ - "sha256:3f2a6e802eebbb6fb736a370fbf3b055edcb6b52878bf2f26330b5e041316c73", - "sha256:a90a072f6993f2c327067bf65270046384cda5a8ecb20b94ea9a687f1f233a7a" - ], - "markers": "python_version >= '3.6'", - "version": "==0.4.6" - }, - "googleapis-common-protos": { - "hashes": [ - "sha256:a88ee8903aa0a81f6c3cec2d5cf62d3c8aa67c06439b0496b49048fb1854ebf4", - "sha256:f6d561ab8fb16b30020b940e2dd01cd80082f4762fa9f3ee670f4419b4b8dbd0" - ], - "markers": "python_version >= '3.6'", - "version": "==1.53.0" - }, - "httplib2": { + "ghp-import": { "hashes": [ - "sha256:0b12617eeca7433d4c396a100eaecfa4b08ee99aa881e6df6e257a7aad5d533d", - "sha256:2ad195faf9faf079723f6714926e9a9061f694d07724b846658ce08d40f522b4" + "sha256:5f8962b30b20652cdffa9c5a9812f7de6bcb56ec475acac579807719bf242c46", + "sha256:947b3771f11be850c852c64b561c600fdddf794bab363060854c1ee7ad05e071" ], - "version": "==0.19.1" + "version": "==2.0.2" }, "idna": { "hashes": [ - "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a", - "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3" + "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff", + "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d" ], "markers": "python_version >= '3'", - "version": "==3.2" + "version": "==3.3" }, "importlib-metadata": { "hashes": [ - "sha256:b618b6d2d5ffa2f16add5697cf57a46c76a56229b0ed1c438322e4e95645bd15", - "sha256:f284b3e11256ad1e5d03ab86bb2ccd6f5339688ff17a4d797a0fe7df326f23b1" + "sha256:53ccfd5c134223e497627b9815d5030edf77d2ed573922f7a0b8f8bb81a1c100", + "sha256:75bdec14c397f528724c1bfd9709d660b33a4d2e77387a3358f20b848bb5e5fb" ], "markers": "python_version >= '3.6'", - "version": "==4.8.1" + "version": "==4.8.2" }, "iniconfig": { "hashes": [ @@ -1042,11 +1372,11 @@ }, "jinja2": { "hashes": [ - "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4", - "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4" + "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8", + "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7" ], "markers": "python_version >= '3.6'", - "version": "==3.0.1" + "version": "==3.0.3" }, "keyring": { "hashes": [ @@ -1069,6 +1399,7 @@ "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298", "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64", "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b", + "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194", "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567", "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff", "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724", @@ -1076,6 +1407,7 @@ "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646", "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35", "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6", + "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a", "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6", "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad", "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26", @@ -1083,27 +1415,36 @@ "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac", "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7", "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6", + "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047", "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75", "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f", + "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b", "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135", "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8", "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a", "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a", + "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1", "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9", "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864", "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914", + "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee", + "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f", "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18", "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8", "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2", "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d", "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b", "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b", + "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86", + "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6", "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f", "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb", "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833", "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28", + "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e", "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415", "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902", + "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f", "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d", "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9", "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d", @@ -1111,10 +1452,14 @@ "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066", "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c", "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1", + "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a", + "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207", "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f", "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53", + "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd", "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134", "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85", + "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9", "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5", "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94", "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509", @@ -1134,27 +1479,27 @@ }, "mike": { "hashes": [ - "sha256:30d221ac6fca3d5820b333103d4086437cf4d16b122c188b3740c3852f3e4e1d", - "sha256:93e0a3a904311ebb432d3210242cca38286fb1ff1944e08bb1e7b46c149ebce1" + "sha256:4c307c28769834d78df10f834f57f810f04ca27d248f80a75f49c6fa2d1527ca", + "sha256:56c3f1794c2d0b5fdccfa9b9487beb013ca813de2e3ad0744724e9d34d40b77b" ], "index": "pypi", - "version": "==1.1.1" + "version": "==1.1.2" }, "mkdocs": { "hashes": [ - "sha256:a334f5bd98ec960638511366eb8c5abc9c99b9083a0ed2401d8791b112d6b078", - "sha256:d019ff8e17ec746afeb54eb9eb4112b5e959597aebc971da46a5c9486137f0ff" + "sha256:89f5a094764381cda656af4298727c9f53dc3e602983087e1fe96ea1df24f4c1", + "sha256:a1fa8c2d0c1305d7fc2b9d9f607c71778572a8b110fb26642aa00296c9e6d072" ], "markers": "python_version >= '3.6'", - "version": "==1.2.2" + "version": "==1.2.3" }, "mkdocs-material": { "hashes": [ - "sha256:07db0580fa96c3473aee99ec3fb4606a1a5a1e4f4467e64c0cd1ba8da5b6476e", - "sha256:b183c27dc0f44e631bbc32c51057f61a3e2ba8b3c1080e59f944167eeba9ff1d" + "sha256:1b1dbd8ef2508b358d93af55a5c5db3f141c95667fad802301ec621c40c7c217", + "sha256:1b6b3e9e09f922c2d7f1160fe15c8f43d4adc0d6fb81aa6ff0cbc7ef5b78ec75" ], "index": "pypi", - "version": "==7.3.0" + "version": "==7.3.6" }, "mkdocs-material-extensions": { "hashes": [ @@ -1164,35 +1509,13 @@ "markers": "python_version >= '3.6'", "version": "==1.0.3" }, - "mypy-extensions": { - "hashes": [ - "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", - "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8" - ], - "version": "==0.4.3" - }, - "oauthlib": { - "hashes": [ - "sha256:42bf6354c2ed8c6acb54d971fce6f88193d97297e18602a3a886603f9d7730cc", - "sha256:8f0215fcc533dd8dd1bee6f4c412d4f0cd7297307d43ac61666389e3bc3198a3" - ], - "markers": "python_version >= '3.6'", - "version": "==3.1.1" - }, "packaging": { "hashes": [ - "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7", - "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14" + "sha256:096d689d78ca690e4cd8a89568ba06d07ca097e3306a4381635073ca91479966", + "sha256:14317396d1e8cdb122989b916fa2c7e9ca8e2be9e8060a6eff75b6b7b4d8a7e0" ], "markers": "python_version >= '3.6'", - "version": "==21.0" - }, - "pathspec": { - "hashes": [ - "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a", - "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1" - ], - "version": "==0.9.0" + "version": "==21.2" }, "pkginfo": { "hashes": [ @@ -1203,11 +1526,11 @@ }, "platformdirs": { "hashes": [ - "sha256:15b056538719b1c94bdaccb29e5f81879c7f7f0f4a153f46086d155dffcd4f0f", - "sha256:8003ac87717ae2c7ee1ea5a84a1a61e87f3fbd16eb5aadba194ea30a9019f648" + "sha256:367a5e80b3d04d2428ffa76d33f124cf11e8fff2acdaa9b43d545f5c7d661ef2", + "sha256:8868bbe3c3c80d42f20156f22e7131d2fb321f5bc86a2a345375c6481a67021d" ], "markers": "python_version >= '3.6'", - "version": "==2.3.0" + "version": "==2.4.0" }, "pluggy": { "hashes": [ @@ -1217,75 +1540,13 @@ "markers": "python_version >= '3.6'", "version": "==1.0.0" }, - "protobuf": { - "hashes": [ - "sha256:0a59ea8da307118372750e2fdfe0961622e675b8dd35e05c42384d618189a938", - "sha256:17181fc0814655812aac108e755bd5185d71aa8d81bd241cec6e232c84097918", - "sha256:18b308946a592e245299391e53c01b5b8efc2794f49986e80f37d7b5e60a270f", - "sha256:1f3ecec3038c2fb4dad952d3d6cb9ca301999903a09e43794fb348da48f7577f", - "sha256:3b5b81bb665aac548b413480f4e0d8c38a74bc4dea57835f288a3ce74f63dfe9", - "sha256:42c04e66ec5a38ad2171639dc9860c2f9594668f709ea3a4a192acf7346853a7", - "sha256:5201333b7aa711965c5769b250f8565a9924e8e27f8b622bbc5e6847aeaab1b1", - "sha256:568c049ff002a7523ed33fb612e6b97da002bf87ffb619a1fc3eadf2257a3b31", - "sha256:5730de255c95b3403eedd1a568eb28203b913b6192ff5a3fdc3ff30f37107a38", - "sha256:615099e52e9fbc9fde00177267a94ca820ecf4e80093e390753568b7d8cb3c1a", - "sha256:7646c20605fbee57e77fdbc4a90175538281b152f46ba17019916593f8062c2a", - "sha256:7e791a94db391ae22b3943fc88f6ba0e1f62b6ad58b33db7517df576c7834d23", - "sha256:80b0a5157f3a53043daf8eb7cfa1220b27a5a63dd6655dbd8e1e6f7b5dcd6347", - "sha256:877664b1b8d1e23553634f625e4e12aae4ff16cbbef473f8118c239d478f422a", - "sha256:9072cb18fca8998b77f969fb74d25a11d7f4a39a8b1ddc3cf76cd5abda8499cb", - "sha256:9147565f93e6699d7512747766598afe63205f226ac7b61f47954974c9aab852", - "sha256:93c077fd83879cf48f327a2491c24da447a09da6a7ab3cc311a6f5a61fcb5de0", - "sha256:d11465040cadcea8ecf5f0b131af5099a9696f9d0bef6f88148b372bacc1c52d", - "sha256:f589346b5b3f702c1d30e2343c9897e6c35e7bd495c10a0e17d11ecb5ee5bd06", - "sha256:f6138462643adce0ed6e49007a63b7fd7dc4fda1ef4e15a70fcebe76c1407a71", - "sha256:f7c8193ec805324ff6024242b00f64a24b94d56b895f62bf28a9d72a228d4fca" - ], - "version": "==3.18.0" - }, "py": { "hashes": [ - "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3", - "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.10.0" - }, - "pyasn1": { - "hashes": [ - "sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359", - "sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576", - "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf", - "sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7", - "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d", - "sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00", - "sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8", - "sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86", - "sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12", - "sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776", - "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba", - "sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2", - "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3" - ], - "version": "==0.4.8" - }, - "pyasn1-modules": { - "hashes": [ - "sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8", - "sha256:0fe1b68d1e486a1ed5473f1302bd991c1611d319bba158e98b106ff86e1d7199", - "sha256:15b7c67fabc7fc240d87fb9aabf999cf82311a6d6fb2c70d00d3d0604878c811", - "sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed", - "sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4", - "sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e", - "sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74", - "sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb", - "sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45", - "sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd", - "sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0", - "sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d", - "sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405" + "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719", + "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378" ], - "version": "==0.2.8" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==1.11.0" }, "pygments": { "hashes": [ @@ -1295,21 +1556,13 @@ "markers": "python_version >= '3.5'", "version": "==2.10.0" }, - "pygsheets": { - "hashes": [ - "sha256:85a4c871ac1d53013e042c13552b07f908b991c3d8c8770b3a68eb3452c8c218", - "sha256:ea6ce75dabd1359e49fd36920ff0d25ff9428ccc3d5d2474bdba80fb8653ad80" - ], - "index": "pypi", - "version": "==2.0.5" - }, "pymdown-extensions": { "hashes": [ - "sha256:141452d8ed61165518f2c923454bf054866b85cf466feedb0eb68f04acdc2560", - "sha256:b6daa94aad9e1310f9c64c8b1f01e4ce82937ab7eb53bfc92876a97aca02a6f4" + "sha256:01e4bec7f4b16beaba0087a74496401cf11afd69e3a11fe95cb593e5c698ef40", + "sha256:430cc2fbb30cef2df70edac0b4f62614a6a4d2b06462e32da4ca96098b7c1dfb" ], "markers": "python_version >= '3.6'", - "version": "==8.2" + "version": "==9.0" }, "pyparsing": { "hashes": [ @@ -1332,17 +1585,9 @@ "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", "version": "==2.8.2" }, - "python-dotenv": { - "hashes": [ - "sha256:aae25dc1ebe97c420f50b81fb0e5c949659af713f31fdb63c749ca68748f34b1", - "sha256:f521bc2ac9a8e03c736f62911605c5d83970021e3fa95b37d769e2bbbe9b6172" - ], - "index": "pypi", - "version": "==0.19.0" - }, "pyyaml": { "hashes": [ "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf", @@ -1388,56 +1633,10 @@ }, "readme-renderer": { "hashes": [ - "sha256:63b4075c6698fcfa78e584930f07f39e05d46f3ec97f65006e430b595ca6348c", - "sha256:92fd5ac2bf8677f310f3303aa4bce5b9d5f9f2094ab98c29f13791d7b805a3db" + "sha256:3286806450d9961d6e3b5f8a59f77e61503799aca5155c8d8d40359b4e1e1adc", + "sha256:8299700d7a910c304072a7601eafada6712a5b011a20139417e1b1e9f04645d8" ], - "version": "==29.0" - }, - "regex": { - "hashes": [ - "sha256:04f6b9749e335bb0d2f68c707f23bb1773c3fb6ecd10edf0f04df12a8920d468", - "sha256:08d74bfaa4c7731b8dac0a992c63673a2782758f7cfad34cf9c1b9184f911354", - "sha256:0fc1f8f06977c2d4f5e3d3f0d4a08089be783973fc6b6e278bde01f0544ff308", - "sha256:121f4b3185feaade3f85f70294aef3f777199e9b5c0c0245c774ae884b110a2d", - "sha256:1413b5022ed6ac0d504ba425ef02549a57d0f4276de58e3ab7e82437892704fc", - "sha256:1743345e30917e8c574f273f51679c294effba6ad372db1967852f12c76759d8", - "sha256:28fc475f560d8f67cc8767b94db4c9440210f6958495aeae70fac8faec631797", - "sha256:31a99a4796bf5aefc8351e98507b09e1b09115574f7c9dbb9cf2111f7220d2e2", - "sha256:328a1fad67445550b982caa2a2a850da5989fd6595e858f02d04636e7f8b0b13", - "sha256:473858730ef6d6ff7f7d5f19452184cd0caa062a20047f6d6f3e135a4648865d", - "sha256:4cde065ab33bcaab774d84096fae266d9301d1a2f5519d7bd58fc55274afbf7a", - "sha256:5f6a808044faae658f546dd5f525e921de9fa409de7a5570865467f03a626fc0", - "sha256:610b690b406653c84b7cb6091facb3033500ee81089867ee7d59e675f9ca2b73", - "sha256:66256b6391c057305e5ae9209941ef63c33a476b73772ca967d4a2df70520ec1", - "sha256:6eebf512aa90751d5ef6a7c2ac9d60113f32e86e5687326a50d7686e309f66ed", - "sha256:79aef6b5cd41feff359acaf98e040844613ff5298d0d19c455b3d9ae0bc8c35a", - "sha256:808ee5834e06f57978da3e003ad9d6292de69d2bf6263662a1a8ae30788e080b", - "sha256:8e44769068d33e0ea6ccdf4b84d80c5afffe5207aa4d1881a629cf0ef3ec398f", - "sha256:999ad08220467b6ad4bd3dd34e65329dd5d0df9b31e47106105e407954965256", - "sha256:9b006628fe43aa69259ec04ca258d88ed19b64791693df59c422b607b6ece8bb", - "sha256:9d05ad5367c90814099000442b2125535e9d77581855b9bee8780f1b41f2b1a2", - "sha256:a577a21de2ef8059b58f79ff76a4da81c45a75fe0bfb09bc8b7bb4293fa18983", - "sha256:a617593aeacc7a691cc4af4a4410031654f2909053bd8c8e7db837f179a630eb", - "sha256:abb48494d88e8a82601af905143e0de838c776c1241d92021e9256d5515b3645", - "sha256:ac88856a8cbccfc14f1b2d0b829af354cc1743cb375e7f04251ae73b2af6adf8", - "sha256:b4c220a1fe0d2c622493b0a1fd48f8f991998fb447d3cd368033a4b86cf1127a", - "sha256:b844fb09bd9936ed158ff9df0ab601e2045b316b17aa8b931857365ea8586906", - "sha256:bdc178caebd0f338d57ae445ef8e9b737ddf8fbc3ea187603f65aec5b041248f", - "sha256:c206587c83e795d417ed3adc8453a791f6d36b67c81416676cad053b4104152c", - "sha256:c61dcc1cf9fd165127a2853e2c31eb4fb961a4f26b394ac9fe5669c7a6592892", - "sha256:c7cb4c512d2d3b0870e00fbbac2f291d4b4bf2634d59a31176a87afe2777c6f0", - "sha256:d4a332404baa6665b54e5d283b4262f41f2103c255897084ec8f5487ce7b9e8e", - "sha256:d5111d4c843d80202e62b4fdbb4920db1dcee4f9366d6b03294f45ed7b18b42e", - "sha256:e1e8406b895aba6caa63d9fd1b6b1700d7e4825f78ccb1e5260551d168db38ed", - "sha256:e8690ed94481f219a7a967c118abaf71ccc440f69acd583cab721b90eeedb77c", - "sha256:ed283ab3a01d8b53de3a05bfdf4473ae24e43caee7dcb5584e86f3f3e5ab4374", - "sha256:ed4b50355b066796dacdd1cf538f2ce57275d001838f9b132fab80b75e8c84dd", - "sha256:ee329d0387b5b41a5dddbb6243a21cb7896587a651bebb957e2d2bb8b63c0791", - "sha256:f3bf1bc02bc421047bfec3343729c4bbbea42605bcfd6d6bfe2c07ade8b12d2a", - "sha256:f585cbbeecb35f35609edccb95efd95a3e35824cd7752b586503f7e6087303f1", - "sha256:f60667673ff9c249709160529ab39667d1ae9fd38634e006bec95611f632e759" - ], - "version": "==2021.8.28" + "version": "==30.0" }, "requests": { "hashes": [ @@ -1447,14 +1646,6 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", "version": "==2.26.0" }, - "requests-oauthlib": { - "hashes": [ - "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d", - "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a", - "sha256:fa6c47b933f01060936d87ae9327fead68768b69c6c9ea2109c48be30f2d4dbc" - ], - "version": "==1.3.0" - }, "requests-toolbelt": { "hashes": [ "sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f", @@ -1469,20 +1660,12 @@ ], "version": "==1.5.0" }, - "rsa": { - "hashes": [ - "sha256:78f9a9bf4e7be0c5ded4583326e7461e3a3c5aae24073648b4bdfa797d78c9d2", - "sha256:9d689e6ca1b3038bc82bf8d23e944b6b6037bc02301a574935b2dd946e0353b9" - ], - "markers": "python_version >= '3.5' and python_version < '4'", - "version": "==4.7.2" - }, "six": { "hashes": [ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", "version": "==1.16.0" }, "toml": { @@ -1490,16 +1673,16 @@ "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" ], - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'", "version": "==0.10.2" }, "tomli": { "hashes": [ - "sha256:8dd0e9524d6f386271a36b41dbf6c57d8e32fd96fd22b6584679dc569d20899f", - "sha256:a5b75cb6f3968abb47af1b40c1819dc519ea82bcc065776a866e8d74c5ca9442" + "sha256:c6ce0015eb38820eaf32b5db832dbc26deb3dd427bd5f6556cf0acac2c214fee", + "sha256:f04066f68f5554911363063a30b108d2b5a5b1a010aa8b6132af78489fe3aade" ], "markers": "python_version >= '3.6'", - "version": "==1.2.1" + "version": "==1.2.2" }, "tox": { "hashes": [ @@ -1519,11 +1702,11 @@ }, "twine": { "hashes": [ - "sha256:087328e9bb405e7ce18527a2dca4042a84c7918658f951110b38bc135acab218", - "sha256:4caec0f1ed78dc4c9b83ad537e453d03ce485725f2aea57f1bb3fdde78dae936" + "sha256:218c42324121d4417cbcbbda59c623b8acc4becfce3daa545e6b6dd48bd21385", + "sha256:3725b79a6f1cfe84a134544ae1894706e60719ab28547cb6c6de781b9f72706d" ], "index": "pypi", - "version": "==3.4.2" + "version": "==3.5.0" }, "typing-extensions": { "hashes": [ @@ -1531,17 +1714,8 @@ "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7", "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34" ], - "index": "pypi", "version": "==3.10.0.2" }, - "uritemplate": { - "hashes": [ - "sha256:07620c3f3f8eed1f12600845892b0e036a2420acf513c53f7de0abd911a5894f", - "sha256:5af8ad10cec94f215e3f48112de2022e1d5a37ed427fbd88652fa908f2ab7cae" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==3.0.1" - }, "urllib3": { "hashes": [ "sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece", @@ -1559,40 +1733,40 @@ }, "virtualenv": { "hashes": [ - "sha256:4da4ac43888e97de9cf4fdd870f48ed864bbfd133d2c46cbdec941fed4a25aef", - "sha256:a4b987ec31c3c9996cf1bc865332f967fe4a0512c41b39652d6224f696e69da5" + "sha256:4b02e52a624336eece99c96e3ab7111f469c24ba226a53ec474e8e787b365814", + "sha256:576d05b46eace16a9c348085f7d0dc8ef28713a2cabaa1cf0aea41e8f12c9218" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==20.8.0" + "version": "==20.10.0" }, "watchdog": { "hashes": [ - "sha256:28777dbed3bbd95f9c70f461443990a36c07dbf49ae7cd69932cdd1b8fb2850c", - "sha256:41d44ef21a77a32b55ce9bf59b75777063751f688de51098859b7c7f6466589a", - "sha256:43bf728eb7830559f329864ab5da2302c15b2efbac24ad84ccc09949ba753c40", - "sha256:50a7f81f99d238f72185f481b493f9de80096e046935b60ea78e1276f3d76960", - "sha256:51af09ae937ada0e9a10cc16988ec03c649754a91526170b6839b89fc56d6acb", - "sha256:5563b005907613430ef3d4aaac9c78600dd5704e84764cb6deda4b3d72807f09", - "sha256:58ae842300cbfe5e62fb068c83901abe76e4f413234b7bec5446e4275eb1f9cb", - "sha256:59767f476cd1f48531bf378f0300565d879688c82da8369ca8c52f633299523c", - "sha256:5cf78f794c9d7bc64a626ef4f71aff88f57a7ae288e0b359a9c6ea711a41395f", - "sha256:5f57ce4f7e498278fb2a091f39359930144a0f2f90ea8cbf4523c4e25de34028", - "sha256:6f3ad1d973fe8fc8fe64ba38f6a934b74346342fa98ef08ad5da361a05d46044", - "sha256:78b1514067ff4089f4dac930b043a142997a5b98553120919005e97fbaba6546", - "sha256:814d396859c95598f7576d15bc257c3bd3ba61fa4bc1db7dfc18f09070ded7da", - "sha256:8874d5ad6b7f43b18935d9b0183e29727a623a216693d6938d07dfd411ba462f", - "sha256:8b74d0d92a69a7ab5f101f9fe74e44ba017be269efa824337366ccbb4effde85", - "sha256:9391003635aa783957b9b11175d9802d3272ed67e69ef2e3394c0b6d9d24fa9a", - "sha256:a2888a788893c4ef7e562861ec5433875b7915f930a5a7ed3d32c048158f1be5", - "sha256:a7053d4d22dc95c5e0c90aeeae1e4ed5269d2f04001798eec43a654a03008d22", - "sha256:b0cc7d8b7d60da6c313779d85903ce39a63d89d866014b085f720a083d5f3e9a", - "sha256:e40e33a4889382824846b4baa05634e1365b47c6fa40071dc2d06b4d7c715fc1", - "sha256:e60d3bb7166b7cb830b86938d1eb0e6cfe23dfd634cce05c128f8f9967895193", - "sha256:eab14adfc417c2c983fbcb2c73ef3f28ba6990d1fff45d1180bf7e38bda0d98d", - "sha256:ed4ca4351cd2bb0d863ee737a2011ca44d8d8be19b43509bd4507f8a449b376b" + "sha256:25fb5240b195d17de949588628fdf93032ebf163524ef08933db0ea1f99bd685", + "sha256:3386b367e950a11b0568062b70cc026c6f645428a698d33d39e013aaeda4cc04", + "sha256:3becdb380d8916c873ad512f1701f8a92ce79ec6978ffde92919fd18d41da7fb", + "sha256:4ae38bf8ba6f39d5b83f78661273216e7db5b00f08be7592062cb1fc8b8ba542", + "sha256:8047da932432aa32c515ec1447ea79ce578d0559362ca3605f8e9568f844e3c6", + "sha256:8f1c00aa35f504197561060ca4c21d3cc079ba29cf6dd2fe61024c70160c990b", + "sha256:922a69fa533cb0c793b483becaaa0845f655151e7256ec73630a1b2e9ebcb660", + "sha256:9693f35162dc6208d10b10ddf0458cc09ad70c30ba689d9206e02cd836ce28a3", + "sha256:a0f1c7edf116a12f7245be06120b1852275f9506a7d90227648b250755a03923", + "sha256:a36e75df6c767cbf46f61a91c70b3ba71811dfa0aca4a324d9407a06a8b7a2e7", + "sha256:aba5c812f8ee8a3ff3be51887ca2d55fb8e268439ed44110d3846e4229eb0e8b", + "sha256:ad6f1796e37db2223d2a3f302f586f74c72c630b48a9872c1e7ae8e92e0ab669", + "sha256:ae67501c95606072aafa865b6ed47343ac6484472a2f95490ba151f6347acfc2", + "sha256:b2fcf9402fde2672545b139694284dc3b665fd1be660d73eca6805197ef776a3", + "sha256:b52b88021b9541a60531142b0a451baca08d28b74a723d0c99b13c8c8d48d604", + "sha256:b7d336912853d7b77f9b2c24eeed6a5065d0a0cc0d3b6a5a45ad6d1d05fb8cd8", + "sha256:bd9ba4f332cf57b2c1f698be0728c020399ef3040577cde2939f2e045b39c1e5", + "sha256:be9be735f827820a06340dff2ddea1fb7234561fa5e6300a62fe7f54d40546a0", + "sha256:cca7741c0fcc765568350cb139e92b7f9f3c9a08c4f32591d18ab0a6ac9e71b6", + "sha256:d0d19fb2441947b58fbf91336638c2b9f4cc98e05e1045404d7a4cb7cddc7a65", + "sha256:e02794ac791662a5eafc6ffeaf9bcc149035a0e48eb0a9d40a8feb4622605a3d", + "sha256:e0f30db709c939cabf64a6dc5babb276e6d823fd84464ab916f9b9ba5623ca15", + "sha256:e92c2d33858c8f560671b448205a268096e17870dcf60a9bb3ac7bfbafb7f5f9" ], "markers": "python_version >= '3.6'", - "version": "==2.1.5" + "version": "==2.1.6" }, "webencodings": { "hashes": [ @@ -1603,11 +1777,11 @@ }, "zipp": { "hashes": [ - "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3", - "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4" + "sha256:71c644c5369f4a6e07636f0aa966270449561fcea2e3d6747b8d23efaa9d7832", + "sha256:9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc" ], "markers": "python_version >= '3.6'", - "version": "==3.5.0" + "version": "==3.6.0" } } } diff --git a/README.md b/README.md index a8496c09a..60995e287 100644 --- a/README.md +++ b/README.md @@ -4,15 +4,14 @@ This repository stores the [LinkML](https://linkml.github.io/) representation of This repository includes [the LinkML model itself](./model/schema/crdch_model.yaml) (in [YAML](https://en.wikipedia.org/wiki/YAML) format) as well as a number of artifacts produced automatically by LinkML, including a JSON Schema, JSON-LD context, a GraphQL description, a CSV description and ShEx validation shapes. -Model documentation in Markdown can also be generated for this repository, and is currently hosted on GitHub Pages at https://cancerdhc.github.io/ccdhmodel/. A set of Python Data Classes can also be generated and are [available for use](./crdch_model/crdch_model.py). Examples of their use are available in the [Example Data](https://github.com/cancerDHC/example-data/) repository. +Model documentation in Markdown can also be generated for this repository, and is currently hosted on [GitHub Pages](https://cancerdhc.github.io/ccdhmodel/). A set of Python Data Classes can also be generated and are [available for use](./crdch_model/crdch_model.py). Examples of their use are available in the [Example Data](https://github.com/cancerDHC/example-data/) repository. ## Setup -### Automated generation of YAML +### Automated generation of LinkML YAML The CRDC-H model is currently in development on [a Google Sheet](https://docs.google.com/spreadsheets/d/1oWS7cao-fgz2MKWtyr8h2dEL9unX__0bJrWKv6mQmM4/). -This repository contains a program in the [`./vendor/sheet2linkml`](./vendor/sheet2linkml) directory -that can read the Google Sheet using the Google Drive API and generate a LinkML representation of the model. +The [sheet2linkml](https://github.com/cancerDHC/sheet2linkml/) package can read the Google Sheet and generate a LinkML representation of the model. In order to run this program, you will need to create and download Google Drive client credentials. First, [enable the Google Drive API](https://developers.google.com/drive/api/v3/enable-drive-api). After the API is enabled, @@ -22,9 +21,15 @@ the root directory of this project. [Detailed instructions and screenshots](http are also available from the [`pygsheets` documentation](https://pygsheets.readthedocs.io/), which is the package we use to access Google Sheets. -Once this is setup, run `make generate-model` to update the schema from Google Sheets. The first time you run this script, +Once this is setup, run from the root of the project: + +``` +make generate-model +``` + +to create the schema from Google Sheet. The first time you run this script, you will see a browser page asking you to log in. Follow the instructions. The script will download a token and store it -locally. You won't need to log in in the future. +locally, so you won't need to login again after that. ### Generation of LinkML artifacts diff --git a/examples-for-discussion/README.md b/examples/README.md similarity index 100% rename from examples-for-discussion/README.md rename to examples/README.md diff --git a/examples-for-discussion/analyte_type_enumeration_examples.yaml b/examples/analyte_type_enumeration_examples.yaml similarity index 100% rename from examples-for-discussion/analyte_type_enumeration_examples.yaml rename to examples/analyte_type_enumeration_examples.yaml diff --git a/examples-for-discussion/harmonized_value_set.yml b/examples/harmonized_value_set.yml similarity index 100% rename from examples-for-discussion/harmonized_value_set.yml rename to examples/harmonized_value_set.yml diff --git a/examples-for-discussion/staging_observation_examples.yaml b/examples/staging_observation_examples.yaml similarity index 100% rename from examples-for-discussion/staging_observation_examples.yaml rename to examples/staging_observation_examples.yaml diff --git a/from_template/MakeConfig b/from_template/MakeConfig deleted file mode 100644 index 7b1c58a73..000000000 --- a/from_template/MakeConfig +++ /dev/null @@ -1,18 +0,0 @@ -# Make file to configure clone of linkml-model-template -VENV = . venv/bin/activate - -all: update - -update: venv - $(VENV) && configure model/CONFIG.yaml - -reset: venv - $(VENV) && configure model/CONFIG.yaml --reset - -venv: - virtualenv venv - $(VENV) && pip install template-configurator - -clean: - rm -rf venv - diff --git a/local/.keep b/local/.keep deleted file mode 100644 index 3c60ca214..000000000 --- a/local/.keep +++ /dev/null @@ -1,2 +0,0 @@ -# this directory is for organizing local scratch files along with this project -# could also be called something like temp \ No newline at end of file diff --git a/vendor/sheet2linkml/.gitignore b/vendor/sheet2linkml/.gitignore deleted file mode 100644 index 4895d451c..000000000 --- a/vendor/sheet2linkml/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Google API credentials -google_api_credentials.json -sheets.googleapis.com-python.json -token.pickle diff --git a/vendor/sheet2linkml/README.md b/vendor/sheet2linkml/README.md deleted file mode 100644 index e247bc2ac..000000000 --- a/vendor/sheet2linkml/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# Google Sheets to LinkML generator for the CRDC-H model - -## Installation - -See the main README file for installation instructions. - -## Synopsis - -Ideally, this program should be run from the root of this project by running: - - $ make generate-model - -However, it can also be run directly via Pipenv: - - $ pipenv install --dev - $ export CDM_GOOGLE_SHEET_ID=1oWS7cao-fgz2MKWtyr8h2dEL9unX__0bJrWKv6mQmM4 - $ pipenv run python vendor/sheet2linkml/sheet2linkml.py --output model/schema/crdch_model.yaml - diff --git a/vendor/sheet2linkml/sheet2linkml.py b/vendor/sheet2linkml/sheet2linkml.py deleted file mode 100644 index 16947f4cc..000000000 --- a/vendor/sheet2linkml/sheet2linkml.py +++ /dev/null @@ -1,8 +0,0 @@ -""" -sheet2linkml.py -A script for converting Google Sheets to a LinkML model. -""" - -from sheet2linkml import cli - -cli.main() diff --git a/vendor/sheet2linkml/sheet2linkml/__init__.py b/vendor/sheet2linkml/sheet2linkml/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/sheet2linkml/sheet2linkml/cli.py b/vendor/sheet2linkml/sheet2linkml/cli.py deleted file mode 100644 index a572436b8..000000000 --- a/vendor/sheet2linkml/sheet2linkml/cli.py +++ /dev/null @@ -1,121 +0,0 @@ -""" -sheet2linkml.py -A script for converting Google Sheets to a LinkML model. -""" - -import sys -import os -import re -import subprocess -import logging -import logging.config -import click -from linkml_runtime.dumpers import yaml_dumper -from dotenv import load_dotenv - -from sheet2linkml.source.gsheetmodel.gsheetmodel import GSheetModel -from sheet2linkml.source.gsheetmodel.mappings import Mappings -from sheet2linkml.terminologies.tccm.api import TCCMService - -@click.command() -@click.option( - "--output", - "-o", - type=click.Path(), - default='model.yaml', - help="The file that the generated LinkML model should be written to.", -) -@click.option( - "--filter-entity", - type=str, - help="The name of a single entity that you would like to extract.", -) -@click.option( - "--logging-config", - type=str, - help="A logging configuration file.", - default='logging.ini', -) -@click.option( - "--write-mappings", - type=click.Path(exists=False), - help="A file to write out mappings to.", -) -@click.option( - "--include-terminologies/--skip-terminologies", - default=True, - help="Controls whether we use the CCDH Terminology Service to add enumerated values for attributes.", -) -def main(output, filter_entity, logging_config, write_mappings, include_terminologies): - # Display INFO log entry and up. - logging.config.fileConfig(logging_config) - - # Load environemental variables from `.env` if one is present. - load_dotenv() - - # Read in Google API credentials. - google_api_credentials = os.getenv('GOOGLE_API_CREDENTIALS', 'google_api_credentials.json') - google_sheet_id = os.getenv('CDM_GOOGLE_SHEET_ID') - - # Arbitrarily set a CRDC-H root URI. - crdch_root = "https://example.org/crdch" - - # Load the Google Sheet model and add the development version number. - model = GSheetModel(google_api_credentials, google_sheet_id) - if include_terminologies: - model.use_terminology_service(TCCMService("https://terminology.ccdh.io")) - logging.info(f"Google Sheet loaded: {model}") - - # Determine the development version number. We can get this from git-describe. - git_describe_result = subprocess.run( - ["git", "describe", "--long", "--dirty"], capture_output=True - ) - if git_describe_result.returncode == 0: - model.development_version = re.sub( - "[^a-zA-Z0-9.\\-]", "_", git_describe_result.stdout.decode("utf8").strip() - ) - - # Setup output filename. - output_filename = click.format_filename(output) - - # We have two operating modes: - # 1. If a `--filter-entity ""` is specified on the command line, - # we generate `output/.yaml` for that entity alone. - # 2. Otherwise, we generate `output/.yaml` for the entire model. - if filter_entity: - # Only extract a single entity. - logging.info(f"Filtering to entity {filter_entity}.") - selected_entities = [ - entity for entity in model.entities() if filter_entity == entity.name - ] - - if not selected_entities: - logging.error( - f"Could not find any entities named {filter_entity}. Please use one of:" - ) - for entity in model.entities(): - logging.error(f" - {entity.name}") - exit(1) - - mappings = list() - - for entity in selected_entities: - logging.info(f"Writing entity {entity.name} to {output_filename}") - yaml_dumper.dump(entity.as_linkml(crdch_root), output_filename) - - if write_mappings: - mappings.extend(entity.mappings.mappings) - - Mappings.write_to_file(mappings, filename=write_mappings, model=model) - - else: - # Convert the entire model into YAML. - logging.info(f"Writing model {model.name} to {output_filename}") - yaml_dumper.dump(model.as_linkml(crdch_root), output_filename) - - if write_mappings: - Mappings.write_to_file(model.mappings, filename=write_mappings, model=model) - - -if __name__ == "__main__": - main() diff --git a/vendor/sheet2linkml/sheet2linkml/model.py b/vendor/sheet2linkml/sheet2linkml/model.py deleted file mode 100644 index 6b2e86eee..000000000 --- a/vendor/sheet2linkml/sheet2linkml/model.py +++ /dev/null @@ -1,55 +0,0 @@ -from abc import ABC, abstractmethod -from linkml_runtime.linkml_model.meta import SchemaDefinition - - -class ModelElement(ABC): - """ - A Model Element represents a model element that can be convert into a LinkML model. - """ - - @property - @abstractmethod - def name(self) -> str: - """ - :return: A name for this model element. - """ - pass - - @property - @abstractmethod - def full_name(self) -> str: - """ - :return: The full name of this model element. - """ - pass - - @abstractmethod - def get_filename(self) -> str: - """ - :return: This model element as a string. - """ - pass - - @abstractmethod - def get_filename(self) -> str: - """ - :return: This model element as a string. - """ - pass - - @abstractmethod - def to_markdown(self) -> str: - """ - :return: A Markdown reference to this model. - """ - pass - - @abstractmethod - def as_linkml(self, root_uri) -> SchemaDefinition: - """ - Return this model element as a LinkML SchemaDefinition. - - :param root_uri: The base URI to use for terms defined in this model. - :return: A LinkML SchemaDefinition for the model described by this Google Sheet. - """ - pass diff --git a/vendor/sheet2linkml/sheet2linkml/source/__init__.py b/vendor/sheet2linkml/sheet2linkml/source/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/sheet2linkml/sheet2linkml/source/gsheetmodel/__init__.py b/vendor/sheet2linkml/sheet2linkml/source/gsheetmodel/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/sheet2linkml/sheet2linkml/source/gsheetmodel/datatype.py b/vendor/sheet2linkml/sheet2linkml/source/gsheetmodel/datatype.py deleted file mode 100644 index 697621541..000000000 --- a/vendor/sheet2linkml/sheet2linkml/source/gsheetmodel/datatype.py +++ /dev/null @@ -1,314 +0,0 @@ -from sheet2linkml.model import ModelElement -from sheet2linkml.source.gsheetmodel.mappings import Mappings, MappingRelations -from pygsheets import worksheet -from linkml_runtime.linkml_model.meta import TypeDefinition -import logging -import re - - -class Datatype(ModelElement): - """ - A datatype defined in the CRDC-H model. This is definitionally the primitive types, since - the complex types are defined as entities. However, if there is some need for complex datatypes - that are not entities, we'll probably implement that here as well. - - The way our model works, we define our own primitive types as well as mappings to the LinkML types along with - other types. Since those are mapped to types in all the output formats (Python, JSON Schema, etc.), eventually - everything should get mapped to right types everywhere.. - """ - - def __init__(self, model, sheet: worksheet, name: str, rows: list[dict[str, str]]): - """ - Create a datatype based on a GSheetModel and a Google Sheet worksheet. - - :param model: The GSheetModel that this entity is a part of. - :param sheet: A Google Sheet worksheet describing this entity. - :param name: The name of this datatype. - :param rows: The rows in the spreadsheet describing this datatype (as dictionaries of str -> str). - For primitives, this should only be a single row. - """ - - self.model = model - self.worksheet = sheet - self.datatype_name = name - self.rows = rows - - @property - def datatype_row(self): - if len(self.rows) == 0: - raise RuntimeError(f"Unexpected lack of rows for {self}") - - if len(self.rows) > 1: - logging.error( - f"Expected exactly one row for {self} but found {len(self.rows)} rows, using first row: {self.rows[0]}" - ) - - return self.rows[0] - - def __str__(self): - """ - :return: A text description of this datatype. - """ - - return f'{self.__class__.__name__} named {self.name} from worksheet "{self.worksheet.title}" containing {len(self.rows)} rows' - - @property - def name(self) -> str: - """ - The name of this datatype. To differentiate it from the LinkML base types, we add `crdch_` as a prefix. - - :return: A name for this datatype. - """ - return f"crdch_{self.datatype_name}" - - @property - def full_name(self) -> str: - """ - :return: The full name of this datatype. - """ - return f"CRDC-H.{self.name}" - - def get_filename(self) -> str: - """ - Return this datatype as a filename, which we calculate by making the datatype name safe for file systems. - - :return: A filename that can be used for this datatype. - """ - - # Taken from https://stackoverflow.com/a/46801075/27310 - name = str(self.name).strip().replace(" ", "_") - return re.sub(r"(?u)[^-\w.]", "", name) - - def to_markdown(self) -> str: - """ - Returns a reference to this entity in Markdown. We include the name, worksheet name and worksheet URL. - - :return: A Markdown representation of this datatype. - """ - - return f"[{self.name} in sheet {self.worksheet.title}]({self.worksheet.url})" - - @property - def linkml_type_mappings(self): - mapping_rows = list( - filter( - lambda r: r is not None, - [row.get(DatatypeWorksheet.COL_EXTERNAL_MAPPINGS) for row in self.rows], - ) - ) - if len(mapping_rows) > 0: - mapping_string = "\n".join(mapping_rows) - else: - mapping_string = "" - - # TODO: parse all external mappings and include them. - linkml_matches = re.findall( - r"LINKML:(\w+)\W", mapping_string, flags=re.IGNORECASE - ) - return linkml_matches - - @property - def mappings(self) -> Mappings: - """ - Returns the list of mappings for this datatype. - """ - mappings = Mappings(self) - mappings.add_mappings( - self.datatype_row.get("External Mapping"), - MappingRelations.SKOS_RELATED_MATCH, - ) - return mappings - - def as_linkml(self, root_uri) -> TypeDefinition: - """ - Returns a LinkML TypeDefinition describing this datatype. - - :param root_uri: The root URI to use for this datatype. - :return: A LinkML TypeDefinition describing this datatype. - """ - logging.info(f"Generating LinkML for {self}") - - # Basic metadata - first_typeof = (self.linkml_type_mappings or ["string"])[0] - typ: TypeDefinition = TypeDefinition( - name=self.name, - description=(self.datatype_row.get("Description") or "").strip(), - typeof=first_typeof.lower(), - ) - - # Additional metadata - - # We add a 'derived from' note to the notes field, which might be - # a string or a list, apparently. - derived_from = f"Derived from {self.to_markdown()}" - if isinstance(typ.notes, list): - typ.notes.append(derived_from) - elif isinstance(typ.notes, str): - typ.notes = typ.notes + f"\n{derived_from}" - else: - typ.notes = derived_from - - # Add mappings. - self.mappings.set_mappings_on_element(typ) - - return typ - - -class DatatypeWorksheet(ModelElement): - """ - A Worksheet represents a single worksheet in a GSheetModel. DatatypeWorksheets contain one or - (more likely) more than one datatype definitions. - """ - - # Some column names. - COL_STATUS = "Status" - COL_DATATYPE_NAME = "Entity" - COL_DESCRIPTION = "Description" - COL_EXTERNAL_MAPPINGS = "External Mappings" - - def is_sheet_datatype(worksheet: worksheet): - """ - Identify worksheets containing datatypes, i.e. those that have: - - COL_STATUS in cell A1, and - - COL_DATATYPE_NAME in cell B1, and - - COL_DESCRIPTION in cell C1. - """ - return worksheet.get_values("A1", "C1") == [ - [ - DatatypeWorksheet.COL_STATUS, - DatatypeWorksheet.COL_DATATYPE_NAME, - DatatypeWorksheet.COL_DESCRIPTION, - ] - ] - - def __init__(self, model, sheet: worksheet): - """ - Create a datatype worksheet based on a GSheetModel and a Google Sheet worksheet. - - :param model: The GSheetModel that this worksheet is a part of. - :param sheet: A Google Sheet worksheet describing this worksheet. - """ - - self.model = model - self.worksheet = sheet - - @property - def rows(self) -> list[dict]: - """ - Returns this datatype worksheet as a list of rows. We use the header row to create these dictionaries. - - :return: A list of the rows in this sheet. - """ - return self.worksheet.get_all_records(empty_value=None) - - @property - def included_rows(self) -> list[dict]: - """ - Returns this datatype worksheet as a list of included rows. - - An included row is one whose COL_STATUS is set to 'include'. - - :return: A list of included rows in this sheet. - """ - return [ - row - for row in self.rows - if row.get(DatatypeWorksheet.COL_STATUS, "") == "include" - ] - - @property - def datatype_names(self) -> list[str]: - """ - Return a list of all the datatype names in this worksheet. - - :return: A list of all the datatype names in this worksheet. - """ - - return [ - (row.get(DatatypeWorksheet.COL_DATATYPE_NAME) or "") - for row in self.included_rows() - ] - - @property - def datatypes_as_included_rows(self) -> dict[str, list[dict]]: - """ - Group the list of rows based on having identical COL_DATATYPE_NAME values. - - :return: A dict with keys of COL_DATATYPE_NAME values and values of included rows having that value. - """ - - result = dict() - - for row in self.included_rows: - datatype_name = row.get(DatatypeWorksheet.COL_DATATYPE_NAME) or "" - if not (datatype_name in result): - result[datatype_name] = list() - - result[datatype_name].append(row) - - return result - - @property - def grouped_datatypes(self) -> dict[str, Datatype]: - """ - Return a list of datatypes in this file, grouped into a dict by key name. - - :return: A dict with keys of COL_ENTITY_NAME values and values of Datatype objects. - """ - - return { - k: Datatype(self.model, self.worksheet, k, v) - for k, v in self.datatypes_as_included_rows.items() - } - - @property - def datatypes(self) -> list[Datatype]: - """ - Return a list of datatypes in this worksheet. - - :return: A list of Datatype objects. - """ - - return list(self.grouped_datatypes.values()) - - @property - def name(self) -> str: - """ - :return: A name for this worksheet. - """ - return self.worksheet.title - - @property - def full_name(self) -> str: - """ - :return: The full name of this worksheet. - """ - return self.worksheet.url - - def get_filename(self) -> str: - """ - Return this worksheet as a filename, which we calculate by making the datatype name safe. - - :return: A filename that could be used for this datatype. - """ - - # Taken from https://stackoverflow.com/a/46801075/27310 - name = str(self.worksheet.title).strip().replace(" ", "_") - return re.sub(r"(?u)[^-\w.]", "", name) - - def to_markdown(self) -> str: - """ - :return: A Markdown representation of this datatype. - """ - - return f"[{self.worksheet.title}]({self.worksheet.url})" - - def as_linkml(self, root_uri) -> list[TypeDefinition]: - """ - Return all LinkML TypeDefinitions in this worksheet. We do this by converting each - Datatype into its LinkML TypeDefinition. - - :param root_uri: The root URI to use for this worksheet. - :return: A list of LinkML TypeDefinitions representing entities in this worksheet. - """ - return [datatype.as_linkml(root_uri) for datatype in self.datatypes.values()] diff --git a/vendor/sheet2linkml/sheet2linkml/source/gsheetmodel/entity.py b/vendor/sheet2linkml/sheet2linkml/source/gsheetmodel/entity.py deleted file mode 100644 index d3e402640..000000000 --- a/vendor/sheet2linkml/sheet2linkml/source/gsheetmodel/entity.py +++ /dev/null @@ -1,636 +0,0 @@ -from functools import cached_property -from sheet2linkml.terminologies.service import TerminologyService -from sheet2linkml.model import ModelElement -from sheet2linkml.source.gsheetmodel.mappings import Mappings, MappingRelations -from sheet2linkml.source.gsheetmodel.enum import Enum -from pygsheets import worksheet -from linkml_runtime.linkml_model.meta import ( - SchemaDefinition, - ClassDefinition, - SlotDefinition, - EnumDefinition, - PermissibleValue, - Example, -) -import logging -import re -import urllib.parse - - -class Entity(ModelElement): - """ - An entity represents a class of data that we need to model. - - It is represented by a single worksheet in a Google Sheet spreadsheet. - """ - - def __init__( - self, - model, - sheet: worksheet, - name: str, - rows: list[dict[str, str]], - terminology_service: TerminologyService, - ): - """ - Create an entity based on a GSheetModel and a Google Sheet worksheet. - - :param model: The GSheetModel that this entity is a part of. - :param sheet: A Google Sheet worksheet describing this entity. - :param name: The name of this entity. - :param rows: The rows in the spreadsheet describing this entity (as dictionaries of str -> str). - :param terminology_service: The TerminologyService to access the codesets we use. - """ - - self.model = model - self.worksheet = sheet - self.entity_name = name - self.rows = rows - self.terminology_service = terminology_service - - @property - def attribute_rows(self) -> list[dict[str, str]]: - """ - Returns this entity as a list of attribute rows. - - An attribute row is one where the COL_ATTRIBUTE_NAME row is not empty. - - :return: A list of named rows in this sheet. - """ - return [ - row - for row in self.rows - if row.get(EntityWorksheet.COL_ATTRIBUTE_NAME) is not None - ] - - @cached_property - def attributes(self): - """ - Returns a list of attributes in this entity. We construct this by wrapping the - attribute rows with Attribute(). - - :return: A list of all the attributes in this entity. - """ - - return [ - Attribute( - self.model, self, dct, terminology_service=self.terminology_service - ) - for dct in self.attribute_rows - ] - - @property - def entity_row(self) -> dict[str, str]: - """ - Returns the "entity row" -- the single row in the spreadsheet that represents this - entity itself. Writes errors in the logs if more than one "entity row" is found (only the - first will be used). - - :return: A dictionary representing a row in the spreadsheet that represents this entity. - """ - - # Find all entity rows - entity_rows = [ - row - for row in self.rows - if row.get(EntityWorksheet.COL_ATTRIBUTE_NAME) is None - ] - - # Report an error if no rows were found. - if not entity_rows: - # raise RuntimeError(f'Entity does not have an entity row: {self}') - logging.error(f"Entity contains no entity row: {self}") - return dict() - - # Report an error if more than one row was found. - if len(entity_rows) > 1: - logging.error( - f'Entity contains more than one "entity row", only the first one will be used: {self}' - ) - for row in entity_rows: - logging.error(f" - Found entity row: {row}") - - return entity_rows[0] - - def __str__(self): - """ - :return: A text description of this entity. - """ - - return f'{self.__class__.__name__} named {self.name} from worksheet "{self.worksheet.title}" containing {len(self.attribute_rows)} attributes' - - @property - def name(self) -> str: - """ - :return: A name for this entity. - """ - return (self.entity_name or "(unnamed entity)").strip() - - @property - def full_name(self) -> str: - """ - :return: The full name of this entity. - """ - return f"CRDC-H.{self.entity_name}" - - def get_filename(self) -> str: - """ - Return this entity as a filename, which we calculate by making the entity name safe for file systems. - - :return: A filename that can be used for this entity. - """ - - # Taken from https://stackoverflow.com/a/46801075/27310 - name = str(self.name).strip().replace(" ", "_") - return re.sub(r"(?u)[^-\w.]", "", name) - - def to_markdown(self) -> str: - """ - Returns a reference to this entity in Markdown. We include the name, worksheet name and worksheet URL. - - :return: A Markdown representation of this entity. - """ - - return f"[{self.name} in sheet {self.worksheet.title}]({self.worksheet.url})" - - @cached_property - def mappings(self) -> Mappings: - """ - Returns the list of mappings for this entity. - """ - mappings = Mappings(self) - mappings.add_mappings( - self.entity_row.get("Source Mapping"), MappingRelations.SKOS_EXACT_MATCH - ) - mappings.add_mappings( - self.entity_row.get("Indirect Source Mapping"), - MappingRelations.SKOS_CLOSE_MATCH, - ) - return mappings - - @property - def mappings_including_attributes(self) -> list[Mappings.Mapping]: - """ - Returns the list of all mappings of this entity as well as all of its attributes. - """ - mappings = list(self.mappings.mappings) - for attr in self.attributes: - mappings.extend(attr.mappings.mappings) - return mappings - - def as_linkml(self, root_uri) -> ClassDefinition: - """ - Returns a LinkML ClassDefinition describing this entity, including attributes. - - :param root_uri: The root URI to use for this entity. - :return: A LinkML ClassDefinition describing this entity. - """ - logging.info(f"Generating LinkML for {self}") - - # Basic metadata - cls: ClassDefinition = ClassDefinition( - name=self.name, - description=(self.entity_row.get("Description") or "").strip(), - comments=self.entity_row.get("Comments"), - ) - - if self.name != "Entity": - cls.is_a = "Entity" - - # Additional metadata - - # We add a 'derived from' note to the notes field, which might be - # a string or a list, apparently. - derived_from = f"Derived from {self.to_markdown()}" - if isinstance(cls.notes, list): - cls.notes.append(derived_from) - elif isinstance(cls.notes, str): - cls.notes = cls.notes + f"\n{derived_from}" - else: - cls.notes = derived_from - - # Add mappings - self.mappings.set_mappings_on_element(cls) - - # Now generate LinkML for all of the attributes. - cls.attributes = { - attribute.name: attribute.as_linkml(root_uri) - for attribute in self.attributes - } - - return cls - - -class Attribute: - """ - An attribute represents a single property within an entity. - - It is represented by a single row in a Google Sheet spreadsheet. - """ - - def __init__( - self, - model, - entity, - row: dict[str, str], - terminology_service: TerminologyService, - ): - """ - Create an attribute based on a GSheetModel and a Google Sheet worksheet. - - :param model: The GSheetModel that this attribute is a part of. - :param entity: The Entity that this attribute is a part of. - :param row: The row describing this attribute (as a dictionary of str -> str). - :param terminology_service: The TerminologyService to use for accessing codeset information. - """ - - self.model = model - self.entity = entity - self.row = row - self.terminology_service = terminology_service - - @property - def name(self): - """ - :return: A name for this attribute. - """ - return ( - self.row.get(EntityWorksheet.COL_ATTRIBUTE_NAME) - or self.row.get("Name") - or self.row.get("name") - ) - - @property - def full_name(self) -> str: - """ - :return: The full name of this attribute. - """ - return f"{self.entity.full_name}.{self.name}" - - def __str__(self): - """ - :return: A text description of this row. - """ - - return f'{self.__class__.__name__} named "{self.name}" containing {len(self.row)} properties' - - def counts(self) -> (int, int): - """ - Returns the minimum and maximum cardinality, determined by parsing the Cardinality column. - If the string is `?..m`, this indicates that there is no maximum cardinality -- which we - report by returning None instead of the maximum cardinality. - - :return: The minimum and maximum cardinality by reading the 'Cardinality' column. - """ - - # A default cardinality to return if none can be parsed. - default = 0, None - - cardinality = self.row.get(EntityWorksheet.COL_CARDINALITY) - if not cardinality: - return default - - # We currently use `1..m` to indicate that there is no maximum cardinality. - # We might eventually need to support `1..*` as well. - m = re.compile("^(\\d+)\\.\\.(\\d+|m)$").match(str(cardinality)) - if not m: - return default - - min_count = int(m.group(1)) - max_count = None - if ( - m.group(2) != "m" - ): # We use '..m' to indicate that there is no maximum value. - max_count = int(m.group(2)) - - return min_count, max_count - - @cached_property - def mappings(self) -> Mappings: - """ - Returns the list of mappings for this attribute. - """ - mappings = Mappings(self) - mappings.add_mappings( - self.row.get("Source Mapping"), MappingRelations.SKOS_EXACT_MATCH - ) - mappings.add_mappings( - self.row.get("Indirect Source Mapping"), MappingRelations.SKOS_CLOSE_MATCH - ) - return mappings - - @property - def range(self): - """ - Return the range of this attribute. - """ - - attribute_range = "string" # Default to linkml:string. - if EntityWorksheet.COL_TYPE in self.row: - attribute_range = self.row.get(EntityWorksheet.COL_TYPE) or "string" - - # For primitive types, we need to add `crdch_` to the start of the type name. - if attribute_range[0].islower(): - attribute_range = f"crdch_{attribute_range}" - - return attribute_range - - @staticmethod - def fix_enum_name(enum_name: str): - """ - Transform enum names so that they can be accessed from Python. - Ideally, these transformations should be done in the LinkML - library somewhere, but for now, we can do that here. - """ - - # The hyphen in 'CRDC-H' doesn't work properly. - fixed_name = re.sub(r"^CRDC-H\.", "CRDCH.", enum_name) - - # The '.'s in the name also mess up the generated Python code. - # But we might as well replace everything that isn't alphanumeric. - fixed_name = re.sub(r"\W", "_", fixed_name).strip("_") - - return fixed_name - - def as_linkml_enum(self) -> EnumDefinition: - """ - If this is an attribute with an enumeration of possible values, - this method will return this enumeration as a LinkML EnumDefinition. - """ - if not self.terminology_service: - return None - - if self.range != EntityWorksheet.ENTITY_CODEABLE_CONCEPT: - return None - - # Look up enumerations on the Terminology Service. - enum_info = self.terminology_service.get_enum_values_for_field(self.full_name) - permissible_values = {} - for pv in enum_info.get("permissible_values", []): - text = pv.get("text") - if text in permissible_values.keys(): - logging.warning( - f"In field '{self.full_name}', found duplicate permissible value text: {text} was previously assigned to {permissible_values[text]}, but will now be replaced with {pv}" - ) - - permissible_values[str(text)] = PermissibleValue( - text=text, description=pv.get("description"), meaning=pv.get("meaning") - ) - - return EnumDefinition( - name=Enum.fix_enum_name(self.full_name), - code_set=f"https://terminology.ccdh.io/enumerations/{urllib.parse.quote_plus(self.full_name)}", - code_set_version=enum_info.get("last_updated", ""), - comments=f'Name according to TCCM: "{enum_info.get("name", "")}"', - description=enum_info.get("description"), - permissible_values=list(permissible_values.values()), - ) - - def as_linkml(self, root_uri) -> SlotDefinition: - """ - Returns this attribute as a LinkML SlotDefinition. - - :param root_uri: The root URI to use for this SlotDefinition. - :return: A LinkML SlotDefinition representing this attribute. - """ - - data = self.row - min_count, max_count = self.counts() - - # Set up some complex fields. - examples = re.split( - r"\s*[\r\n\|]\s*", (data.get("Example Values") or "").strip() - ) - if len(examples) == 0: - examples = [] - else: - examples = [Example(value=example) for example in examples] - - attribute_range = self.range - - slot: SlotDefinition = SlotDefinition( - name=data.get(EntityWorksheet.COL_ATTRIBUTE_NAME) or "", - description=(data.get("Description") or "").strip(), - examples=examples, - comments=data.get("Comments"), - # notes=data.get("Developer Notes"), - required=(min_count > 0), - multivalued=(max_count is None or max_count > 1), - domain=self.entity.name, - range=attribute_range, - ) - - # For CodeableConcepts, we specify that the values should come from an enumeration. - if self.terminology_service and attribute_range == "CodeableConcept": - slot.values_from = f'crdch:{Enum.fix_enum_name(self.full_name)}' - - # Multivalued fields need to be inlined as a list. - # (Eventually, we might want to inline some of these as dicts, but not yet.) - if max_count is None or max_count > 1: - # Except for enumerated fields. - if self.range != EntityWorksheet.ENTITY_CODEABLE_CONCEPT: - slot.inlined_as_list = True - - cardinality = data.get(EntityWorksheet.COL_CARDINALITY) - if cardinality: - slot.notes.append(f"Cardinality: {cardinality}") - - # Add mappings - self.mappings.set_mappings_on_element(slot) - - return slot - - -class EntityWorksheet(ModelElement): - """ - A Worksheet represents a single worksheet in a GSheetModel. A single sheet usually contains - information on a single Entity, but sometimes multiple entities may be described in a single - Worksheet. In that case, this Worksheet will return multiple entities. - """ - - # Some column names. - COL_STATUS = "Status" - COL_ENTITY_NAME = "Entity" - COL_ATTRIBUTE_NAME = "Attribute" - COL_CARDINALITY = "Cardinality" - COL_TYPE = "Type" - - # Some entity names. - ENTITY_CODEABLE_CONCEPT = "CodeableConcept" - - @staticmethod - def is_sheet_entity(worksheet: worksheet): - """Identify worksheets containing entities, i.e. those that have: - - COL_STATUS in cell A1, and - - COL_ENTITY_NAME in cell B1, and - - COL_ATTRIBUTE_NAME in cell C1. - """ - return worksheet.get_values("A1", "C1") == [ - [ - EntityWorksheet.COL_STATUS, - EntityWorksheet.COL_ENTITY_NAME, - EntityWorksheet.COL_ATTRIBUTE_NAME, - ] - ] - - def __init__( - self, model, sheet: worksheet, terminology_service: TerminologyService - ): - """ - Create a worksheet based on a GSheetModel and a Google Sheet worksheet. - - :param model: The GSheetModel that this worksheet is a part of. - :param sheet: A Google Sheet worksheet describing this worksheet. - """ - - self.model = model - self.worksheet = sheet - self.terminology_service = terminology_service - - @property - def rows(self) -> list[dict]: - """ - Returns this entity as a list of rows. We use the header row to create these dictionaries. - - :return: A list of the rows in this sheet. - """ - return self.worksheet.get_all_records(empty_value=None) - - @property - def included_rows(self) -> list[dict]: - """ - Returns this entity as a list of included rows. - - An included row is one whose COL_STATUS is set to 'include'. - - :return: A list of included rows in this sheet. - """ - return [ - row - for row in self.rows - if row.get(EntityWorksheet.COL_STATUS, "") == "include" - ] - - @property - def entity_names(self) -> list[str]: - """ - Return a list of all the entity names in this worksheet. - - :return: A list of all the entity names in this worksheet. - """ - - return [ - (row.get(EntityWorksheet.COL_ENTITY_NAME) or "") - for row in self.included_rows() - ] - - @property - def entities_as_included_rows(self) -> dict[str, list[dict]]: - """ - Group the list of rows based on having identical COL_ENTITY_NAME values. - - :return: A dict with keys of COL_ENTITY_NAME values and values of included rows having that value. - """ - - result = dict() - - for row in self.included_rows: - entity_name = row.get(EntityWorksheet.COL_ENTITY_NAME) or "" - if not (entity_name in result): - result[entity_name] = list() - - result[entity_name].append(row) - - # The Google Sheet might indicate that the entity row (the row without an attribute name) should be excluded. - # If any other rows have been included for this entity, however, they would be used to define the entity, - # even though the intention was to exclude that entity. In order to prevent this, we will check for any included - # rows that don't have an entity row -- such groups will be filtered out here. - filtered = dict() - - for name, rows in result.items(): - if any(row.get(EntityWorksheet.COL_ATTRIBUTE_NAME) is None for row in rows): - filtered[name] = rows - else: - logging.warning( - f"- Ignoring entity {name} in worksheet {self.name} as it does not have an entity row." - ) - - # Make sure that we only have a single entity name in this Worksheet -- the name of the sheet itself. - entity_names = list(filtered.keys()) - if not (len(entity_names) == 1 and entity_names[0] == self.name): - logging.warning( - f"Expected entity worksheet {self.name} to contain a single entity, but found {len(entity_names)}: {', '.join(entity_names)}" - ) - - return filtered - - @property - def grouped_entities(self) -> dict[str, Entity]: - """ - Return a list of entities in this file, grouped into a dict by key name. - - :return: A dict with keys of COL_ENTITY_NAME values and values of Entity objects. - """ - - return { - k: Entity( - self.model, - self.worksheet, - k, - v, - terminology_service=self.terminology_service, - ) - for k, v in self.entities_as_included_rows.items() - } - - @property - def entities(self) -> list[Entity]: - """ - Return a list of entities in this file. - - :return: A list of Entity objects. - """ - - return list(self.grouped_entities.values()) - - @property - def name(self) -> str: - """ - :return: A name for this worksheet. - """ - return self.worksheet.title - - @property - def full_name(self) -> str: - """ - :return: The full name of this worksheet. - """ - return self.worksheet.url - - def get_filename(self) -> str: - """ - Return this worksheet as a filename, which we calculate by making the entity name safe. - - :return: A filename that could be used for this entity. - """ - - # Taken from https://stackoverflow.com/a/46801075/27310 - name = str(self.worksheet.title).strip().replace(" ", "_") - return re.sub(r"(?u)[^-\w.]", "", name) - - def to_markdown(self) -> str: - """ - :return: A Markdown representation of this entity. - """ - - return f"[{self.worksheet.title}]({self.worksheet.url})" - - def as_linkml(self, root_uri) -> list[SchemaDefinition]: - """ - Return all LinkML SchemaDefinitions in this worksheet. We do this by converting each - Entity into its LinkML SchemaDefinition. - - :param root_uri: The root URI to use for this worksheet. - :return: A list of LinkML SchemaDefinitions representing entities in this worksheet. - """ - return [entity.as_linkml(root_uri) for entity in self.entities.values()] diff --git a/vendor/sheet2linkml/sheet2linkml/source/gsheetmodel/enum.py b/vendor/sheet2linkml/sheet2linkml/source/gsheetmodel/enum.py deleted file mode 100644 index 413d61d3d..000000000 --- a/vendor/sheet2linkml/sheet2linkml/source/gsheetmodel/enum.py +++ /dev/null @@ -1,479 +0,0 @@ -import logging -import re -from functools import cached_property - -from linkml_runtime.linkml_model.meta import ( - SchemaDefinition, - EnumDefinition, - PermissibleValue, -) -from pygsheets import worksheet - -from sheet2linkml.model import ModelElement -from sheet2linkml.source.gsheetmodel.mappings import MappingRelations, Mappings - - -class Enum(ModelElement): - """ - An enum represents an enumeration stored in a single worksheet in a Google Sheet spreadsheet. - """ - - def __init__(self, model, sheet: worksheet, name: str, rows: list[dict[str, str]]): - """ - Create an enum based on a GSheetModel and a Google Sheet worksheet. - - :param model: The GSheetModel that this enum is a part of. - :param sheet: A Google Sheet worksheet describing this enum. - :param name: The name of this enum. - :param rows: The rows in the spreadsheet describing this enum (as dictionaries of str -> str). - """ - - self.model = model - self.worksheet = sheet - self.enum_name = name - self.rows = rows - - @property - def value_rows(self) -> list[dict[str, str]]: - """ - Returns this enum as a list of value rows. - - A value row is one where the COL_ENUM_NAME row is not empty. - - :return: A list of named rows in this sheet. - """ - return [ - row - for row in self.rows - if row.get(EnumWorksheet.COL_VALUE_NAME) is not None - ] - - @property - def values(self) -> list: - return [EnumValue(self.model, self, row) for row in self.value_rows] - - @property - def enum_row(self) -> dict[str, str]: - """ - Returns the "enum row" -- the single row in the spreadsheet that represents this - enum itself. Writes errors in the logs if more than one "enum row" is found (only the - first will be used). - - :return: A dictionary representing a row in the spreadsheet that represents this enum. - """ - - # Find all entity rows - enum_rows = [ - row for row in self.rows if row.get(EnumWorksheet.COL_VALUE_NAME) is None - ] - - # Report an error if no rows were found. - if not enum_rows: - # raise RuntimeError(f'Entity does not have an entity row: {self}') - logging.error(f"Enum contains no enum row: {self}") - return dict() - - # Report an error if more than one row was found. - if len(enum_rows) > 1: - logging.error( - f'Enum contains more than one "enum row", only the first one will be used: {self}' - ) - for row in enum_rows: - logging.error(f" - Found enum row: {row}") - - return enum_rows[0] - - def __str__(self): - """ - :return: A text description of this enum. - """ - - return f'{self.__class__.__name__} named {self.name} from worksheet "{self.worksheet.title}" containing {len(self.value_rows)} values' - - @property - def name(self) -> str: - """ - :return: A name for this enum. - """ - return (self.enum_name or "(unnamed enum)").strip() - - @property - def full_name(self) -> str: - """ - :return: The full name of this enum. - """ - return f"CRDC-H.{self.enum_name}" - - @property - def fixed_name(self): - """ - :return: The name of this enum, modified to fit the format we use for other enums. - """ - return Enum.fix_enum_name(self.full_name) - - @staticmethod - def fix_enum_name(enum_name: str): - """ - Transform enum names so that they can be accessed from Python. - Ideally, these transformations should be done in the LinkML - library somewhere, but for now, we can do that here. - """ - - # The hyphen in 'CRDC-H' doesn't work properly. - fixed_name = re.sub(r"^CRDC-H\.", "CRDCH.", enum_name) - - # The '.'s in the name also mess up the generated Python code. - # But we might as well replace everything that isn't alphanumeric. - fixed_name = re.sub(r"\W", "_", fixed_name).strip("_") - - # All enumerations should be prefixed with `enum_` for clarity. - return f"enum_{fixed_name}" - - def get_filename(self) -> str: - """ - Return this entity as a filename, which we calculate by making the enum name safe for file systems. - - :return: A filename that can be used for this enum. - """ - - # Taken from https://stackoverflow.com/a/46801075/27310 - name = str(self.name).strip().replace(" ", "_") - return re.sub(r"(?u)[^-\w.]", "", name) - - def to_markdown(self) -> str: - """ - Returns a reference to this enum in Markdown. We include the name, worksheet name and worksheet URL. - - :return: A Markdown representation of this entity. - """ - - return f"[{self.name} in sheet {self.worksheet.title}]({self.worksheet.url})" - - @cached_property - def mappings(self) -> Mappings: - """ - Returns the list of mappings for this enum. - """ - mappings = Mappings(self) - mappings.add_mappings( - self.enum_row.get("Source Entity"), MappingRelations.SKOS_RELATED_MATCH - ) - mappings.add_mappings( - self.enum_row.get("Source Attribute (Name)"), - MappingRelations.SKOS_RELATED_MATCH, - ) - mappings.add_mappings( - self.enum_row.get("Source Attribute (Values)"), - MappingRelations.SKOS_RELATED_MATCH, - ) - return mappings - - @property - def mappings_including_values(self) -> list[Mappings.Mapping]: - """ - Returns the list of all mappings of this enum as well as all of its values. - """ - mappings = list(self.mappings.mappings) - for attr in self.values: - mappings.extend(attr.mappings.mappings) - return mappings - - def as_linkml(self, root_uri) -> EnumDefinition: - """ - Returns a LinkML EnumDefinition describing this entity, including attributes. - - :param root_uri: The root URI to use for this enum. - :return: A LinkML EnumDefinition describing this enum. - """ - logging.info(f"Generating LinkML for {self}") - - # Basic metadata - enum = EnumDefinition( - name=self.fixed_name, - description=(self.enum_row.get(EnumWorksheet.COL_DEFINITION) or "").strip(), - ) - - # Additional metadata - - # We add a 'derived from' note to the notes field, which might be - # a string or a list, apparently. - derived_from = f"Derived from {self.to_markdown()}" - if isinstance(enum.notes, list): - enum.notes.append(derived_from) - elif isinstance(enum.notes, str): - enum.notes = enum.notes + f"\n{derived_from}" - else: - enum.notes = derived_from - - # Add mappings - self.mappings.set_mappings_on_element(enum) - - # Now generate LinkML for all of the values. - enum.permissible_values = { - str(enum_value.name): enum_value.as_linkml(root_uri) - for enum_value in self.values - } - - return enum - - -class EnumValue: - """ - An EnumValue represents a single value within an enum. - - It is represented by a single row in a Google Sheet spreadsheet. - """ - - def __init__(self, model, enum: Enum, row: dict[str, str]): - """ - Create an enum based on a GSheetModel and a Google Sheet worksheet. - - :param model: The GSheetModel that this enum is a part of. - :param entity: The Enum that this enum value is a part of. - :param row: The row describing this enum value (as a dictionary of str -> str). - """ - - self.model = model - self.enum = enum - self.row = row - - @property - def name(self): - """ - :return: A name for this enum value. - """ - return ( - self.row.get(EnumWorksheet.COL_VALUE_NAME) - or self.row.get("Name") - or self.row.get("name") - ) - - @property - def full_name(self) -> str: - """ - :return: The full name of this enum value. - """ - return f"{self.enum.full_name}.{self.name}" - - def __str__(self): - """ - :return: A text description of this enum value. - """ - - return f'{self.__class__.__name__} named "{self.name}" containing {len(self.row)} properties' - - @cached_property - def mappings(self) -> Mappings: - """ - Returns the list of mappings for this enum value. - """ - mappings = Mappings(self) - mappings.add_mappings( - self.row.get("Source Entity"), MappingRelations.SKOS_RELATED_MATCH - ) - mappings.add_mappings( - self.row.get("Source Attribute (Name)"), MappingRelations.SKOS_RELATED_MATCH - ) - mappings.add_mappings( - self.row.get("Source Attribute (Values)"), - MappingRelations.SKOS_RELATED_MATCH, - ) - return mappings - - def as_linkml(self, root_uri) -> PermissibleValue: - """ - Returns this attribute as a LinkML PermissibleValue. - - :param root_uri: The root URI to use for this PermissibleValue. - :return: A LinkML PermissibleValue representing this attribute. - """ - - data = self.row - - pv = PermissibleValue( - text=data.get(EnumWorksheet.COL_VALUE_NAME) or "", - description=(data.get(EnumWorksheet.COL_DEFINITION) or "").strip(), - comments=data.get("Comments"), - ) - - # Add mappings - # TODO: LinkML doesn't actually support mappings on enum values! - # self.mappings.set_mappings_on_element(pv) - - return pv - - -class EnumWorksheet(ModelElement): - """ - A Worksheet represents a single worksheet in a GSheetModel. A single sheet usually contains - information on a single Entity, but sometimes multiple entities may be described in a single - Worksheet. In that case, this Worksheet will return multiple entities. - """ - - # Some column names. - COL_STATUS = "Status" - COL_ENUM_NAME = "Enumeration Name" - COL_VALUE_NAME = "Value Name" - COL_DEFINITION = "Definition" - - @staticmethod - def is_sheet_entity(worksheet: worksheet): - """Identify worksheets containing enums, i.e. those that have: - - COL_STATUS in cell A1, and - - COL_ENUM_NAME in cell B1, and - - COL_VALUE_NAME in cell C1, and - - COL_DEFINITION in cell D1 - """ - return worksheet.get_values("A1", "D1") == [ - [ - EnumWorksheet.COL_STATUS, - EnumWorksheet.COL_ENUM_NAME, - EnumWorksheet.COL_VALUE_NAME, - EnumWorksheet.COL_DEFINITION, - ] - ] - - def __init__(self, model, sheet: worksheet): - """ - Create a worksheet based on a GSheetModel and a Google Sheet worksheet. - - :param model: The GSheetModel that this worksheet is a part of. - :param sheet: A Google Sheet worksheet describing this worksheet. - """ - - self.model = model - self.worksheet = sheet - - @property - def rows(self) -> list[dict]: - """ - Returns this EnumWorksheet as a list of rows. We use the header row to create these dictionaries. - - :return: A list of the rows in this sheet. - """ - return self.worksheet.get_all_records(empty_value=None) - - @property - def included_rows(self) -> list[dict]: - """ - Returns this entity as a list of included rows. - - An included row is one whose COL_STATUS is set to 'include'. - - :return: A list of included rows in this sheet. - """ - return [ - row - for row in self.rows - if row.get(EnumWorksheet.COL_STATUS, "") == "include" - ] - - @property - def enum_names(self) -> list[str]: - """ - Return a list of all the entity names in this worksheet. - - :return: A list of all the entity names in this worksheet. - """ - - return [ - (row.get(EnumWorksheet.COL_ENUM_NAME) or "") for row in self.included_rows() - ] - - @property - def enums_as_included_rows(self) -> dict[str, list[dict]]: - """ - Group the list of rows based on having identical COL_ENUM_NAME values. - - :return: A dict with keys of COL_ENUM_NAME values and values of included rows having that value. - """ - - result = dict() - - for row in self.included_rows: - enum_name = row.get(EnumWorksheet.COL_ENUM_NAME) or "" - if not (enum_name in result): - result[enum_name] = list() - - result[enum_name].append(row) - - # The Google Sheet might indicate that the enum row (the row without a value name) should be excluded. - # If any other rows have been included for this entity, however, they would be used to define the entity, - # even though the intention was to exclude that entity. In order to prevent this, we will check for any included - # rows that don't have an entity row -- such groups will be filtered out here. - filtered = dict() - - for name, rows in result.items(): - if any(row.get(EnumWorksheet.COL_VALUE_NAME) is None for row in rows): - filtered[name] = rows - else: - logging.warning( - f"- Ignoring enum {name} in worksheet {self.name} as it does not have an enum row." - ) - - return filtered - - @property - def grouped_entities(self) -> dict[str, Enum]: - """ - Return a list of enums in this worksheet, grouped into a dict by enum name. - - :return: A dict with keys of COL_ENTITY_NAME values and values of Enum objects. - """ - - return { - k: Enum(self.model, self.worksheet, k, v) - for k, v in self.enums_as_included_rows.items() - } - - @property - def enums(self) -> list[Enum]: - """ - Return a list of enums in this worksheet. - - :return: A list of Enum objects. - """ - - return list(self.grouped_entities.values()) - - @property - def name(self) -> str: - """ - :return: A name for this worksheet. - """ - return self.worksheet.title - - @property - def full_name(self) -> str: - """ - :return: The full name of this worksheet. - """ - return self.worksheet.url - - def get_filename(self) -> str: - """ - Return this worksheet as a filename, which we calculate by making the entity name safe. - - :return: A filename that could be used for this entity. - """ - - # Taken from https://stackoverflow.com/a/46801075/27310 - name = str(self.worksheet.title).strip().replace(" ", "_") - return re.sub(r"(?u)[^-\w.]", "", name) - - def to_markdown(self) -> str: - """ - :return: A Markdown representation of this entity. - """ - - return f"[{self.worksheet.title}]({self.worksheet.url})" - - def as_linkml(self, root_uri) -> list[SchemaDefinition]: - """ - Return all LinkML SchemaDefinitions in this worksheet. We do this by converting each - Entity into its LinkML SchemaDefinition. - - :param root_uri: The root URI to use for this worksheet. - :return: A list of LinkML SchemaDefinitions representing entities in this worksheet. - """ - return [enum.as_linkml(root_uri) for enum in self.enums.values()] diff --git a/vendor/sheet2linkml/sheet2linkml/source/gsheetmodel/gsheetmodel.py b/vendor/sheet2linkml/sheet2linkml/source/gsheetmodel/gsheetmodel.py deleted file mode 100644 index 9a3e2bb04..000000000 --- a/vendor/sheet2linkml/sheet2linkml/source/gsheetmodel/gsheetmodel.py +++ /dev/null @@ -1,338 +0,0 @@ -from sheet2linkml.model import ModelElement -from sheet2linkml.source.gsheetmodel.mappings import Mappings -from sheet2linkml.source.gsheetmodel.entity import Entity, EntityWorksheet, Attribute -from sheet2linkml.source.gsheetmodel.enum import EnumWorksheet, Enum -from sheet2linkml.source.gsheetmodel.datatype import Datatype, DatatypeWorksheet -from sheet2linkml.terminologies.service import TerminologyService -from linkml_runtime.linkml_model.meta import SchemaDefinition -from functools import cached_property, cache -from datetime import datetime, timezone -import re -import logging -import pygsheets - - -class GSheetModel(ModelElement): - """ - A GSheetModel represents a single, coherent model represented as a series of worksheets - in Google Sheets. This representation is currently being developed by all the CCDH workstreams, - and so it needs to be flexible enough to be modified extensively on the fly. - - If we ever extend sheet2linkml beyond Google Sheets, we should create a top-level Model - class that generically represents a single, coherent model, and then make GSheetModel a - subclass of that. But that's for another day. - """ - - """ The Google API scopes that are necessary to query this sheet. """ - SCOPES = [ - "https://www.googleapis.com/auth/spreadsheets.readonly", - "https://www.googleapis.com/auth/drive.metadata.readonly", - ] - - def __init__(self, google_sheet_oath2_credentials: str, google_sheet_id: str): - """ - Create a new Google Sheet Model. This will create a model that uses the specified - Google Sheet as an input. - - Note that creating a GSheetModel will kick off the Google Sheets authentication - process, which will ask you to visit a website, log in with a Google account, and - then to enter the provided code into this Python script. See - https://pygsheets.readthedocs.io/en/stable/authorization.html for information on - creating and downloading OAuth2 credentials from the Google Developers Console. - Once you authenticate yourself, this script will create a file with your - authentication token in your working directory, so you will not need to log in - again from the same working directory. - - :param google_sheet_oath2_credentials: A file containing OAuth2 credential files. - :param google_sheet_id: The Google Sheet ID containing the model. - """ - - self.client = pygsheets.authorize( - client_secret=google_sheet_oath2_credentials, scopes=self.SCOPES - ) - self.sheet = self.client.open_by_key(google_sheet_id) - - # TODO: at some point, we should read the version number from the Google Sheets document... somehow. - self.release_version = None - - # Set a `development version`. This is initially None, but if set, we add this to the metadata we emit. - self.development_version = None - - # Set the 'last_updated' time to now. - # TODO: we should be able to get this from the Google Sheet, in RFC 3339 format, but this apparently - # requires a different scope than what we currently use. - # return self.sheet.updated - self.last_updated = datetime.now(timezone.utc).isoformat() - - # Set the terminology_service to None, indicating that terminology services shouldn't be used. - self.terminology_service = None - - @property - def version(self): - """ - Return the version of this GSheetModel. - """ - - # TODO: We should read this from the Google Sheet. - if self.release_version: - return self.release_version - else: - return self.development_version - - @staticmethod - def is_sheet_normative(worksheet: pygsheets.worksheet): - """ - Check if a sheet is an informative sheet that does not contain any model information. - There are three types of such sheets: - - O_* tabs are useful tabs that have other non Entity content (exclude) - - X_* tabs are tabs that might be deletable (exclude) - - R_* tabs can be created to hold some sort of reference material that should not be changed. (exclude) - """ - - result = not ( - worksheet.title.startswith("O_") - or worksheet.title.startswith("X_") - or worksheet.title.startswith("R_") - ) - - return result - - @cache - def entity_worksheets(self) -> list[EntityWorksheet]: - """ - A list of worksheets available in this model. - - We identify a worksheet containing entities based on its column header. - - :return: A list of entities available in this model. - """ - - # Identify entity worksheets among the list of all worksheets in this Google Sheets document. - worksheets = self.sheet.worksheets() - - tests_and_errors = { - "excluded by sheet type": GSheetModel.is_sheet_normative, - "not an entity worksheet": EntityWorksheet.is_sheet_entity, - } - - entity_worksheets = list() - for worksheet in worksheets: - flag_skip = False - for test_name, error in tests_and_errors.items(): - if not error(worksheet): - logging.debug(f"Skipping worksheet {worksheet.title}: {test_name}") - flag_skip = True - break - - if not flag_skip: - entity_worksheets.append(worksheet) - - return [ - EntityWorksheet( - self, worksheet, terminology_service=self.terminology_service - ) - for worksheet in entity_worksheets - ] - - @cache - def entities(self) -> list[Entity]: - """ - :return: The list of entities in this model. - """ - result = [] - for worksheet in self.entity_worksheets(): - result.extend(worksheet.entities) - return result - - def datatype_worksheets(self) -> list[DatatypeWorksheet]: - """ - A list of datatype worksheets available in this model. - - We only have a single datatype worksheet: 'Primitives'. So we just return that. - - :return: A list of datatype worksheets available in this model. - """ - - return [DatatypeWorksheet(self, self.sheet.worksheet("title", "Primitives"))] - - def datatypes(self) -> list[Datatype]: - """ - :return: The list of Datatypes in this model. - """ - result = [] - for worksheet in self.datatype_worksheets(): - result.extend(worksheet.datatypes) - return result - - def enum_worksheets(self) -> list[EnumWorksheet]: - """ - A list of enum worksheets available in this model. - - We only have a single enum worksheet: 'O_CCDH Enums'. So we just return that. - """ - return [EnumWorksheet(self, self.sheet.worksheet("title", "O_CCDH Enums"))] - - def enums_from_worksheets(self) -> list[Enum]: - """ - A list of enums available from worksheets in this model. - """ - result = [] - for worksheet in self.enum_worksheets(): - result.extend(worksheet.enums) - return result - - @cached_property - def mappings(self) -> list[Mappings.Mapping]: - """Return a list of all the mappings in this LinkML document.""" - mappings = [ - mapping - for datatype in self.datatypes() - for mapping in datatype.mappings.mappings - ] - mappings.extend( - mapping - for entity in self.entities() - for mapping in entity.mappings_including_attributes - ) - mappings.extend( - mapping - for enum in self.enums_from_worksheets() - for mapping in enum.mappings_including_values - ) - return mappings - - def __str__(self) -> str: - """ - :return: A string representation of this Google Sheet model. - """ - - return f'{self.__class__.__name__} with an underlying Google Sheet titled "{self.sheet.title}" containing {len(self.sheet.worksheets())} worksheets' - - @property - def name(self) -> str: - """ - :return: The name of this model. - """ - return self.sheet.title - - @property - def full_name(self) -> str: - """ - :return: The full name of this model. - """ - return self.sheet.url - - def get_filename(self) -> str: - """ - Return this Google Sheet model as a filename, which we calculate by making the Google Sheet title filesystem-safe. - - :return: A filename that could be used for this model. - """ - - # Taken from https://stackoverflow.com/a/46801075/27310 - filename = str(self.sheet.title).strip().replace(" ", "_") - return re.sub(r"(?u)[^-\w.]", "", filename) - - def to_markdown(self) -> str: - """ - :return: A Markdown representation of this Google Sheet model. - """ - - return f"[{self.sheet.title}]({self.sheet.url})" - - def as_linkml(self, root_uri) -> SchemaDefinition: - """ - Return this Google Sheet model as a LinkML SchemaDefinition. - - :param root_uri: The base URI to use for terms defined in this model. - :return: A LinkML SchemaDefinition for the model described by this Google Sheet. - """ - - logging.info(f"Generating LinkML for {self}") - - # Set up general metadata. - schema: SchemaDefinition = SchemaDefinition(name="CRDC-H", id=f"{root_uri}") - schema.prefixes = { - "linkml": "https://w3id.org/linkml/", - "crdch": f"{root_uri}/", - "NCIT": "http://purl.obolibrary.org/obo/NCIT_", - "GDC": "http://example.org/gdc/", - "PDC": "http://example.org/pdc/", - "ICDC": "http://example.org/icdc/", - "HTAN": "http://example.org/htan/", - } - # TODO: See if we can get by without. - # schema.imports = ['datatypes', 'prefixes'] - schema.imports = ["linkml:types"] - schema.default_prefix = "crdch" - - schema.license = "https://creativecommons.org/publicdomain/zero/1.0/" - schema.notes.append(f"Derived from {self.to_markdown()}") - schema.generation_date = self.last_updated - - schema.version = self.version - - # Generate all the datatypes. - schema_types = { - datatype.name: datatype.as_linkml(root_uri) for datatype in self.datatypes() - } - - # Generate all the entities. - schema_classes = { - entity.name: entity.as_linkml(root_uri) for entity in self.entities() - } - - # Load enums from the attributes themselves -- this will look things up in the terminology service. - schema_enums = { - Enum.fix_enum_name(attribute.full_name): attribute.as_linkml_enum() - for entity in self.entities() - for attribute in entity.attributes - if attribute.as_linkml_enum() is not None - } - - # Add enums from the enum worksheets in this Google Doc. - enum_worksheets = self.enum_worksheets() - for enum_worksheet in enum_worksheets: - for enum in enum_worksheet.enums: - schema_enums[enum.fixed_name] = enum.as_linkml(root_uri) - - # At this point, classes might refer to types that haven't been defined - # yet. So, for fields that refer to other classes in this model, we need to - # go through and: - # - Warn the user about the missing type - # - Replace the type with 'Entity' for now. - valid_types = ( - set(schema_types.keys()) - .union(set(schema_classes.keys())) - .union(set(schema_enums.keys())) - ) - - def fix_type_name(entity, dct, prop): - print(f'fix_type_name({entity}, {dct}, {prop})') - value = dct[prop] - if value is not None and value not in valid_types: - logging.warning( - f"Entity {entity}'s {prop} refers to type {value}, which is not defined." - ) - dct[prop] = "Entity" - - for entity in schema_classes.values(): - fix_type_name(entity.name, entity, "is_a") - for attrName in entity.attributes: - # Ignore attributes that start with `_`. - if not attrName.startswith('_'): - attr = entity.attributes[attrName] - fix_type_name(f"{entity.name}.{attrName}", attr, "range") - - # Write the lists to the schema - schema.types = schema_types - schema.classes = schema_classes - schema.enums = schema_enums - - return schema - - def use_terminology_service(self, terminology_service: TerminologyService): - """ - Activate terminology lookups using the specified base_url (e.g. https://terminology.ccdh.io/enumerations/CRDC-H.Specimen.analyte_type?value_only=false) - """ - self.terminology_service = terminology_service diff --git a/vendor/sheet2linkml/sheet2linkml/source/gsheetmodel/mappings.py b/vendor/sheet2linkml/sheet2linkml/source/gsheetmodel/mappings.py deleted file mode 100644 index 66e668f20..000000000 --- a/vendor/sheet2linkml/sheet2linkml/source/gsheetmodel/mappings.py +++ /dev/null @@ -1,239 +0,0 @@ -from sheet2linkml.model import ModelElement -from linkml_runtime.linkml_model.meta import Element -from linkml_runtime.linkml_model.types import Uriorcurie -import re -import urllib -import csv -import logging -from enum import Enum -from dataclasses import dataclass - - -class MappingRelations(Enum): - SKOS_BROAD_MATCH = "skos:broadMatch" - SKOS_NARROW_MATCH = "skos:narrowMatch" - SKOS_EXACT_MATCH = "skos:exactMatch" - SKOS_CLOSE_MATCH = "skos:closeMatch" - SKOS_RELATED_MATCH = "skos:relatedMatch" - - -class Mappings: - """ - In our Google Sheets document, mappings are stored within a single cell in the following format: - "LINKML:String (exact match) - XML:string (exact match) - JSON:string (exact match) - FHIR:string (does not allow zero-length strings and limits the length of the string to 1024x1024 characters)" - - Thus, each mapping consists of: - - The URI being mapped to - - The relation of the map - - In LinkML, mappings (https://linkml.github.io/linkml-model/docs/mappings/) are of five kinds, all of which are of the - UriORCURIE type and which are subproperties of `mappings` (:B is mapped to :A somehow -- the parent concept of the - other five mappings) - 1. broad mappings (:B is a broader concept than :A) - 2. narrow mappings (:B is a narrower concept than :A) - 3. exact mappings (:B and :A can be used interchangeably across a wide range of information retrieval applications) - 4. close mappings (:B and :A are sufficiently similar that they can be used interchangeably in some applications) - 5. related mapping (:B and :A are related in some way -- "used to state an associative mapping link between two concepts") - - In order to fit the one into the other, things that can have mappings (entities and types, to begin with) will - invoke Mappings() to wrap over their mapping fields. Mappings() can provide a list of individual mappings to various - concepts. However, the most likely way of using this would be to pass it a LinkML Element, to which it will add the - appropriate mappings in the most appropriate category. Since there is no space for metadata in LinkML, we will - necessary lose some information -- however, to reaccess that information, you can iterate over all Mappings() objects, - which can provide a method to create a CSV containing *all* of the mapping information in the original file. - """ - - def __init__(self, mapping_from: ModelElement): - """ - Read sets of mappings from around a single text, presumably from a Google Sheet. - """ - self.source_element = mapping_from - self.mappings = [] - - @dataclass - class Mapping: - """ - An individual mapping represents the mapping between one ModelElement (such as a type or an entity) - and some URIorCURIE, with an enum representating a relation and a textual description of the relationship. - """ - - source: ModelElement - target: Uriorcurie - description: str - relation: MappingRelations - - def add_mappings( - self, - mapping_string: str, - default_relation: MappingRelations = MappingRelations.SKOS_RELATED_MATCH, - ) -> list[Mapping]: - """ - Add mappings from the provided mapping string with the specified default relation. - """ - - if mapping_string is None or len(mapping_string.strip()) == 0: - return - - rows = re.split(r"\s*[\r\n\|]+\s*", mapping_string) - - for row in rows: - # Is the row empty? If so, ignore it. - if row.strip() == "": - continue - - # There are three kinds of rows: - # - [mapping target] - # - [mapping target]([description]) - # - [mapping target]([relation type]) - # We can use regular expression to differentiate between them. - mapping_target = row - description = None - relation = default_relation - - match = re.match(r"^\s*(.*?)\s*\(\s*(.*)\s*\)\s*$", row) - if match: - mapping_target = match.group(1) - description = match.group(2) - - lower_desc = (description or "").lower() - if ( - lower_desc == "skos:exactMatch" - or lower_desc == "exact" - or lower_desc.startswith("exact match") - ): - relation = MappingRelations.SKOS_EXACT_MATCH - elif ( - lower_desc == "skos:closeMatch" - or lower_desc == "close" - or lower_desc.startswith("close match") - ): - relation = MappingRelations.SKOS_CLOSE_MATCH - elif ( - lower_desc == "skos:relatedMatch" - or lower_desc == "related" - or lower_desc.startswith("related match") - ): - relation = MappingRelations.SKOS_RELATED_MATCH - elif ( - lower_desc == "skos:broadMatch" - or lower_desc == "broad" - or lower_desc.startswith("broad match") - ): - relation = MappingRelations.SKOS_BROAD_MATCH - elif ( - lower_desc == "skos:narrowMatch" - or lower_desc == "narrow" - or lower_desc.startswith("narrow match") - ): - relation = MappingRelations.SKOS_NARROW_MATCH - elif lower_desc.strip() == "": - # If no description is given, we'll use the default relation instead. - relation = default_relation - else: - logging.warning( - f"In entity {self.source_element.name}: mapping type '{lower_desc}' could not be mapped to LinkML, " - + "assuming it is a description." - ) - - # TODO: Eventually, we should enforce that the input is already a Uriorcurie. - # But for now, we need to support two formats: - # - (GDC|PDC|ICDC|...).(Entity).(property)... - # - Any other kind of string - # For the former, we will map it to `GDC:(Entity).(property)...`. - # For the latter, we will map it to `example:(URL-encoded string)`. - uri_or_curie = None - match = re.match(r"^([A-Z]+)(?:\.|:)(.*)$", mapping_target) - if match: - # Note that in this case we don't sanitize the CURIE at all -- if there any spaces, they'll remain here! - uri_or_curie = Uriorcurie(f"{match.group(1)}:{match.group(2).strip()}") - else: - uri_or_curie = Uriorcurie( - f"example:{urllib.parse.quote_plus(mapping_target.strip())}" - ) - - self.mappings.append( - Mappings.Mapping( - source=self.source_element, - target=uri_or_curie, - description=description, - relation=relation, - ) - ) - - def set_mappings_on_element(self, element: Element): - """ - This method will append the mappings in this Mappings object to the specified element. - """ - - for mapping in self.mappings: - if mapping.relation == MappingRelations.SKOS_BROAD_MATCH: - element.broad_mappings.append(mapping.target) - elif mapping.relation == MappingRelations.SKOS_NARROW_MATCH: - element.narrow_mappings.append(mapping.target) - elif mapping.relation == MappingRelations.SKOS_EXACT_MATCH: - element.exact_mappings.append(mapping.target) - elif mapping.relation == MappingRelations.SKOS_CLOSE_MATCH: - element.close_mappings.append(mapping.target) - elif mapping.relation == MappingRelations.SKOS_RELATED_MATCH: - element.related_mappings.append(mapping.target) - else: - element.mappings.append(mapping.target) - - @classmethod - def write_to_file(cls, mappings: list[Mapping], filename: str, model): - """ - Write the list of mappings to a filename, provided as a string. - - mapping: A list of Mappings.Mapping objects to write. - filename: A filename to write to. If None, no file will be written. - model: The GSheetModel these mappings are a part of. - """ - if filename is None: - raise RuntimeError( - "Mappings.write_to_file() needs a `filename` parameter with the output file to write." - ) - - if model is None: - raise RuntimeError( - "Mappings.write_to_file() needs a `model` parameter with the GSheetModel being used." - ) - - with open(filename, "w") as csvfile: - writer = csv.writer(csvfile, dialect="excel-tab") - writer.writerow( - [ - "subject_id", - "subject_category", - "predicate_id", - "object_id", - "comment", - "match_type", - "mapping_set_id", - "mapping_set_version", - "creator_id", - "mapping_date", - ] - ) - - for mapping in mappings: - # See if we can figure out the range of this datatype/entity/attribute. - source_range = None - if hasattr(mapping.source, "range"): - source_range = mapping.source.range - - writer.writerow( - [ - mapping.source.full_name, - source_range, - mapping.relation.value, - mapping.target, - mapping.description, - "SSSOMC:HumanCurated", - model.full_name, - model.version, - model.last_updated, - ] - ) diff --git a/vendor/sheet2linkml/sheet2linkml/terminologies/__init__.py b/vendor/sheet2linkml/sheet2linkml/terminologies/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/sheet2linkml/sheet2linkml/terminologies/service.py b/vendor/sheet2linkml/sheet2linkml/terminologies/service.py deleted file mode 100644 index 67a7e398f..000000000 --- a/vendor/sheet2linkml/sheet2linkml/terminologies/service.py +++ /dev/null @@ -1,22 +0,0 @@ -from abc import ABC, abstractmethod - - -class TerminologyService(ABC): - """ - A TerminologyService is a base class for all terminology services. These will usually be APIs, but in some - cases might read enumerations from local resources (such as a Google Sheet worksheet). - """ - - @abstractmethod - def get_enum_values_for_field(self, field_name): - """ - Get the enumerated values for a particular field. - - In the interests of time, this currently returns a custom Python nested dict structure. In future versions, - this will return a list of permissible values or another structured output. - - :param field_name: The name of the field. Should be in the format "Model Name.Entity Name.Attribute Name", - such as `CRDC-H.Specimen.analyte_type`. - """ - - pass diff --git a/vendor/sheet2linkml/sheet2linkml/terminologies/tccm/__init__.py b/vendor/sheet2linkml/sheet2linkml/terminologies/tccm/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/sheet2linkml/sheet2linkml/terminologies/tccm/api.py b/vendor/sheet2linkml/sheet2linkml/terminologies/tccm/api.py deleted file mode 100644 index b29d2df91..000000000 --- a/vendor/sheet2linkml/sheet2linkml/terminologies/tccm/api.py +++ /dev/null @@ -1,52 +0,0 @@ -from sheet2linkml.terminologies.service import TerminologyService - -import requests -from functools import cache -import logging -from datetime import datetime, timezone -import yaml - - -class TCCMService(TerminologyService): - """ - Provides methods for accessing information in a TCCM Terminology Service. - """ - - def __init__(self, base_url: str): - """Set up a TCCM Terminology Service access system based around the provided base_url.""" - self.base_url = base_url - - # This is unlikely to change during a run and is quite expensive (since we download it from the network), so - # we memoize it. - @cache - def get_enum_values_for_field(self, field_name: str): - """ - Returns information on the enum fields for a particular field. - - TODO: This is very vaguely specified right now in the interests of getting stuff out the door; - I'll come back to this and clean this up later and make it a proper API method later. - """ - - # Construct the URL we need to access the enumeration information. - url = f"{self.base_url}/enumerations/{field_name}" - logging.debug(f"Querying TCCM for attribute info: {url}") - - # Query the URL. - # We use ?value_only=false because "the value_only param sets whether the mapped ncit code is used". - time_of_request = datetime.now(timezone.utc).isoformat() - response = requests.get( - url, headers={"accept": "application/x-yaml"}, params={"value_only": "true"} - ) - if not response.ok: - logging.debug(f"Error accessing TCCM Terminology Service: {response}") - return {} - - # The output we receive is currently in YAML, so we need to convert that into Python dicts so we can - # access them. - enum_info = yaml.safe_load(response.text) - - # If there is no 'last_updated' field, assume that it was last updated when we made the request. - if "last_updated" not in enum_info: - enum_info["last_updated"] = time_of_request - - return enum_info