From a755d2909f49bb73ab98cb0829e35000d0b7cf0b Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Tue, 7 Dec 2021 01:12:55 -0500 Subject: [PATCH 01/43] Added authorization instructions for sheet2linkml. --- README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d70cd81..8dbca01 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,16 @@ source .venv/bin/activate python -m pip install sheet2linkml ``` +## Authorization + +sheet2linkml uses the [`pygsheets` library](https://github.com/nithinmurali/pygsheets) in order to access sheets in +Google Drive. To authorize it to access your Google Sheets, 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, +[create and download the client credentials](https://www.iperiusbackup.net/en/how-to-enable-google-drive-api-and-get-client-credentials/) +from the [Google API Console](https://console.developers.google.com/). Save the file as `google_api_credentials.json` in +the root directory of this project. [Detailed instructions and screenshots](https://pygsheets.readthedocs.io/en/stable/authorization.html) +are also available from the [`pygsheets` documentation](https://pygsheets.readthedocs.io/). + ## Command Line Client Usage Identify the Google Sheet that you want to convert to LinkML. Note that sheet2linkml is not currently a general-purpose Google Sheet to LinkML converter. It will only work with Google Sheets that have been written in a particular, currently undefined format. @@ -45,7 +55,7 @@ Contact your CCDH colleagues to obtain the correct sheet ID and assert it either export CDM_GOOGLE_SHEET_ID=WbM2Jr869ofmdcSmhX_1E0aLWvnK2-gr47Mo_tzuQKWy ``` -A `google_api_credentials.json` file is also required in the root of this repo. Documentation is forthcoming. +A `google_api_credentials.json` file is also required in the root of this repo as detailed in the Authorization section above. And the user is responsible for defining - `~/path/to/crdch_model.yaml` From 43a7612efdde7affac39e7ec202948f4afe5585b Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Tue, 7 Dec 2021 01:14:54 -0500 Subject: [PATCH 02/43] Added test to check for google_api_credentials file. --- sheet2linkml/cli.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sheet2linkml/cli.py b/sheet2linkml/cli.py index d2a145e..25b748b 100644 --- a/sheet2linkml/cli.py +++ b/sheet2linkml/cli.py @@ -60,6 +60,10 @@ def main(output, filter_entity, logging_config, write_mappings, include_terminol google_api_credentials = os.getenv( "GOOGLE_API_CREDENTIALS", "google_api_credentials.json" ) + if not os.path.exists(google_api_credentials): + logging.error(f"Google API Credential file '{google_api_credentials}' not found: please see " + + "https://github.com/cancerDHC/sheet2linkml#authorization for information on creating this file.") + exit(1) google_sheet_id = os.getenv("CDM_GOOGLE_SHEET_ID") # Arbitrarily set a CRDC-H root URI. From d28961726cf3da0b4a4334694a38a686584e0480 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Tue, 7 Dec 2021 01:16:57 -0500 Subject: [PATCH 03/43] Cleaned up code with black. --- sheet2linkml/cli.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sheet2linkml/cli.py b/sheet2linkml/cli.py index 25b748b..8fca8da 100644 --- a/sheet2linkml/cli.py +++ b/sheet2linkml/cli.py @@ -61,8 +61,10 @@ def main(output, filter_entity, logging_config, write_mappings, include_terminol "GOOGLE_API_CREDENTIALS", "google_api_credentials.json" ) if not os.path.exists(google_api_credentials): - logging.error(f"Google API Credential file '{google_api_credentials}' not found: please see " + - "https://github.com/cancerDHC/sheet2linkml#authorization for information on creating this file.") + logging.error( + f"Google API Credential file '{google_api_credentials}' not found: please see " + + "https://github.com/cancerDHC/sheet2linkml#authorization for information on creating this file." + ) exit(1) google_sheet_id = os.getenv("CDM_GOOGLE_SHEET_ID") From 66c17418a02536e87086e24edf1cc909077cbedb Mon Sep 17 00:00:00 2001 From: "Mark A. Miller" Date: Thu, 9 Dec 2021 14:27:48 -0500 Subject: [PATCH 04/43] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d70cd81..2e402b3 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ Identify the Google Sheet that you want to convert to LinkML. Note that sheet2li Contact your CCDH colleagues to obtain the correct sheet ID and assert it either in a `.env` file or in the shell, like this: ```shell -export CDM_GOOGLE_SHEET_ID=WbM2Jr869ofmdcSmhX_1E0aLWvnK2-gr47Mo_tzuQKWy +export CDM_GOOGLE_SHEET_ID=1oWS7cao-fgz2MKWtyr8h2dEL9unX__0bJrWKv6mQmM4 ``` A `google_api_credentials.json` file is also required in the root of this repo. Documentation is forthcoming. From f3ca061565769073036281e9f80b0ec4d4d17020 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Tue, 7 Dec 2021 00:49:20 -0500 Subject: [PATCH 05/43] Updated packages with `poetry update`. --- poetry.lock | 149 +++++++++++----------------------------------------- 1 file changed, 32 insertions(+), 117 deletions(-) diff --git a/poetry.lock b/poetry.lock index 9d0e33d..dc580a4 100644 --- a/poetry.lock +++ b/poetry.lock @@ -22,7 +22,7 @@ tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (> [[package]] name = "black" -version = "21.11b1" +version = "21.12b0" description = "The uncompromising code formatter." category = "main" optional = false @@ -33,7 +33,6 @@ click = ">=7.1.2" mypy-extensions = ">=0.4.3" pathspec = ">=0.9.0,<1" platformdirs = ">=2" -regex = ">=2021.4.4" tomli = ">=0.2.6,<2.0.0" typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implementation_name == \"cpython\""} typing-extensions = [ @@ -66,7 +65,7 @@ python-versions = "*" [[package]] name = "charset-normalizer" -version = "2.0.8" +version = "2.0.9" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "main" optional = false @@ -138,7 +137,7 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2)"] [[package]] name = "google-api-python-client" -version = "2.31.0" +version = "2.32.0" description = "Google API Client Library for Python" category = "main" optional = false @@ -336,7 +335,7 @@ format_nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339- [[package]] name = "linkml-runtime" -version = "1.1.7" +version = "1.1.9" description = "LinkML Runtime Environment" category = "main" optional = false @@ -582,14 +581,6 @@ pyldmod = "*" rdflib = ">=4.2.0" testfixtures = "*" -[[package]] -name = "regex" -version = "2021.11.10" -description = "Alternative regular expression module, to replace re." -category = "main" -optional = false -python-versions = "*" - [[package]] name = "requests" version = "2.26.0" @@ -676,7 +667,7 @@ python-versions = ">=3.6" [[package]] name = "typed-ast" -version = "1.5.0" +version = "1.5.1" description = "a fork of Python 2 and 3 ast modules with type comment support" category = "main" optional = false @@ -745,8 +736,8 @@ attrs = [ {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"}, ] black = [ - {file = "black-21.11b1-py3-none-any.whl", hash = "sha256:802c6c30b637b28645b7fde282ed2569c0cd777dbe493a41b6a03c1d903f99ac"}, - {file = "black-21.11b1.tar.gz", hash = "sha256:a042adbb18b3262faad5aff4e834ff186bb893f95ba3a8013f09de1e5569def2"}, + {file = "black-21.12b0-py3-none-any.whl", hash = "sha256:a615e69ae185e08fdd73e4715e260e2479c861b5740057fde6e8b4e3b7dd589f"}, + {file = "black-21.12b0.tar.gz", hash = "sha256:77b80f693a569e2e527958459634f18df9b0ba2625ba4e0c2d5da5be42e6f2b3"}, ] cachetools = [ {file = "cachetools-4.2.4-py3-none-any.whl", hash = "sha256:92971d3cb7d2a97efff7c7bb1657f21a8f5fb309a37530537c71b1774189f2d1"}, @@ -757,8 +748,8 @@ certifi = [ {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, ] charset-normalizer = [ - {file = "charset-normalizer-2.0.8.tar.gz", hash = "sha256:735e240d9a8506778cd7a453d97e817e536bb1fc29f4f6961ce297b9c7a917b0"}, - {file = "charset_normalizer-2.0.8-py3-none-any.whl", hash = "sha256:83fcdeb225499d6344c8f7f34684c2981270beacc32ede2e669e94f7fa544405"}, + {file = "charset-normalizer-2.0.9.tar.gz", hash = "sha256:b0b883e8e874edfdece9c28f314e3dd5badf067342e42fb162203335ae61aa2c"}, + {file = "charset_normalizer-2.0.9-py3-none-any.whl", hash = "sha256:1eecaa09422db5be9e29d7fc65664e6c33bd06f9ced7838578ba40d58bdf3721"}, ] click = [ {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"}, @@ -781,8 +772,8 @@ google-api-core = [ {file = "google_api_core-2.2.2-py2.py3-none-any.whl", hash = "sha256:e7853735d4f51f4212d6bf9750620d76fc0106c0f271be0c3f43b73501c7ddf9"}, ] google-api-python-client = [ - {file = "google-api-python-client-2.31.0.tar.gz", hash = "sha256:3f64a5eee6fa03ab51806dccf48e342fda83fea60c290518c6a2dfdbf2de9efd"}, - {file = "google_api_python_client-2.31.0-py2.py3-none-any.whl", hash = "sha256:d9f1539db48abfea3d7d65e4cfba258a5a95c901e99fb49c7cfe4de99921a757"}, + {file = "google-api-python-client-2.32.0.tar.gz", hash = "sha256:619fe50155e73342c17aba4bbb2a08be8ce6ae00b795af383de7d6616b485c94"}, + {file = "google_api_python_client-2.32.0-py2.py3-none-any.whl", hash = "sha256:1449c6941afabc32a274be54d17f262615e3a970114c386b62986e29618623f3"}, ] google-auth = [ {file = "google-auth-2.3.3.tar.gz", hash = "sha256:d83570a664c10b97a1dc6f8df87e5fdfff012f48f62be131e449c20dfc32630e"}, @@ -841,8 +832,8 @@ jsonschema = [ {file = "jsonschema-4.2.1.tar.gz", hash = "sha256:390713469ae64b8a58698bb3cbc3859abe6925b565a973f87323ef21b09a27a8"}, ] linkml-runtime = [ - {file = "linkml_runtime-1.1.7-py3-none-any.whl", hash = "sha256:67f16cec969456489d025a707456774c163415010fbf7f6568aa783bfc015784"}, - {file = "linkml_runtime-1.1.7.tar.gz", hash = "sha256:d8f4a6ed685b31f1bb8f242a40e890ccd39d049b93b35777a9b3aa1c22c39b36"}, + {file = "linkml_runtime-1.1.9-py3-none-any.whl", hash = "sha256:855056f3381e805a728f348b0db55cb5ee7a0c1f247336afe1b9830dc3a95502"}, + {file = "linkml_runtime-1.1.9.tar.gz", hash = "sha256:9b4717c79e8d43f3d03ea26145205449728b62d284b3ad44fcb4a1fc208a64f1"}, ] lxml = [ {file = "lxml-4.6.4-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:bbf2dc330bd44bfc0254ab37677ec60f7c7ecea55ad8ba1b8b2ea7bf20c265f5"}, @@ -1068,82 +1059,6 @@ rdflib-pyldmod-compat = [ {file = "rdflib-pyldmod-compat-0.1.2.tar.gz", hash = "sha256:bfba0064d8b2584afdbef5d54bac3ac1dd4c13b64aaeba7a43812c2f35ca13c6"}, {file = "rdflib_pyldmod_compat-0.1.2-py3-none-any.whl", hash = "sha256:68aa05d4f4d8f46241e0c37e631b4747f18a356d8accc5bae204350d2f314196"}, ] -regex = [ - {file = "regex-2021.11.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9345b6f7ee578bad8e475129ed40123d265464c4cfead6c261fd60fc9de00bcf"}, - {file = "regex-2021.11.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:416c5f1a188c91e3eb41e9c8787288e707f7d2ebe66e0a6563af280d9b68478f"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0538c43565ee6e703d3a7c3bdfe4037a5209250e8502c98f20fea6f5fdf2965"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee1227cf08b6716c85504aebc49ac827eb88fcc6e51564f010f11a406c0a667"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6650f16365f1924d6014d2ea770bde8555b4a39dc9576abb95e3cd1ff0263b36"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30ab804ea73972049b7a2a5c62d97687d69b5a60a67adca07eb73a0ddbc9e29f"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68a067c11463de2a37157930d8b153005085e42bcb7ad9ca562d77ba7d1404e0"}, - {file = "regex-2021.11.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:162abfd74e88001d20cb73ceaffbfe601469923e875caf9118333b1a4aaafdc4"}, - {file = "regex-2021.11.10-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b9ed0b1e5e0759d6b7f8e2f143894b2a7f3edd313f38cf44e1e15d360e11749b"}, - {file = "regex-2021.11.10-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:473e67837f786404570eae33c3b64a4b9635ae9f00145250851a1292f484c063"}, - {file = "regex-2021.11.10-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2fee3ed82a011184807d2127f1733b4f6b2ff6ec7151d83ef3477f3b96a13d03"}, - {file = "regex-2021.11.10-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d5fd67df77bab0d3f4ea1d7afca9ef15c2ee35dfb348c7b57ffb9782a6e4db6e"}, - {file = "regex-2021.11.10-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5d408a642a5484b9b4d11dea15a489ea0928c7e410c7525cd892f4d04f2f617b"}, - {file = "regex-2021.11.10-cp310-cp310-win32.whl", hash = "sha256:98ba568e8ae26beb726aeea2273053c717641933836568c2a0278a84987b2a1a"}, - {file = "regex-2021.11.10-cp310-cp310-win_amd64.whl", hash = "sha256:780b48456a0f0ba4d390e8b5f7c661fdd218934388cde1a974010a965e200e12"}, - {file = "regex-2021.11.10-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:dba70f30fd81f8ce6d32ddeef37d91c8948e5d5a4c63242d16a2b2df8143aafc"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1f54b9b4b6c53369f40028d2dd07a8c374583417ee6ec0ea304e710a20f80a0"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fbb9dc00e39f3e6c0ef48edee202f9520dafb233e8b51b06b8428cfcb92abd30"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666abff54e474d28ff42756d94544cdfd42e2ee97065857413b72e8a2d6a6345"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5537f71b6d646f7f5f340562ec4c77b6e1c915f8baae822ea0b7e46c1f09b733"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed2e07c6a26ed4bea91b897ee2b0835c21716d9a469a96c3e878dc5f8c55bb23"}, - {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ca5f18a75e1256ce07494e245cdb146f5a9267d3c702ebf9b65c7f8bd843431e"}, - {file = "regex-2021.11.10-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:74cbeac0451f27d4f50e6e8a8f3a52ca074b5e2da9f7b505c4201a57a8ed6286"}, - {file = "regex-2021.11.10-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:3598893bde43091ee5ca0a6ad20f08a0435e93a69255eeb5f81b85e81e329264"}, - {file = "regex-2021.11.10-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:50a7ddf3d131dc5633dccdb51417e2d1910d25cbcf842115a3a5893509140a3a"}, - {file = "regex-2021.11.10-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:61600a7ca4bcf78a96a68a27c2ae9389763b5b94b63943d5158f2a377e09d29a"}, - {file = "regex-2021.11.10-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:563d5f9354e15e048465061509403f68424fef37d5add3064038c2511c8f5e00"}, - {file = "regex-2021.11.10-cp36-cp36m-win32.whl", hash = "sha256:93a5051fcf5fad72de73b96f07d30bc29665697fb8ecdfbc474f3452c78adcf4"}, - {file = "regex-2021.11.10-cp36-cp36m-win_amd64.whl", hash = "sha256:b483c9d00a565633c87abd0aaf27eb5016de23fed952e054ecc19ce32f6a9e7e"}, - {file = "regex-2021.11.10-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fff55f3ce50a3ff63ec8e2a8d3dd924f1941b250b0aac3d3d42b687eeff07a8e"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e32d2a2b02ccbef10145df9135751abea1f9f076e67a4e261b05f24b94219e36"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:53db2c6be8a2710b359bfd3d3aa17ba38f8aa72a82309a12ae99d3c0c3dcd74d"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2207ae4f64ad3af399e2d30dde66f0b36ae5c3129b52885f1bffc2f05ec505c8"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5ca078bb666c4a9d1287a379fe617a6dccd18c3e8a7e6c7e1eb8974330c626a"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd33eb9bdcfbabab3459c9ee651d94c842bc8a05fabc95edf4ee0c15a072495e"}, - {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:05b7d6d7e64efe309972adab77fc2af8907bb93217ec60aa9fe12a0dad35874f"}, - {file = "regex-2021.11.10-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:42b50fa6666b0d50c30a990527127334d6b96dd969011e843e726a64011485da"}, - {file = "regex-2021.11.10-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:6e1d2cc79e8dae442b3fa4a26c5794428b98f81389af90623ffcc650ce9f6732"}, - {file = "regex-2021.11.10-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:0416f7399e918c4b0e074a0f66e5191077ee2ca32a0f99d4c187a62beb47aa05"}, - {file = "regex-2021.11.10-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:ce298e3d0c65bd03fa65ffcc6db0e2b578e8f626d468db64fdf8457731052942"}, - {file = "regex-2021.11.10-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dc07f021ee80510f3cd3af2cad5b6a3b3a10b057521d9e6aaeb621730d320c5a"}, - {file = "regex-2021.11.10-cp37-cp37m-win32.whl", hash = "sha256:e71255ba42567d34a13c03968736c5d39bb4a97ce98188fafb27ce981115beec"}, - {file = "regex-2021.11.10-cp37-cp37m-win_amd64.whl", hash = "sha256:07856afef5ffcc052e7eccf3213317fbb94e4a5cd8177a2caa69c980657b3cb4"}, - {file = "regex-2021.11.10-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba05430e819e58544e840a68b03b28b6d328aff2e41579037e8bab7653b37d83"}, - {file = "regex-2021.11.10-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7f301b11b9d214f83ddaf689181051e7f48905568b0c7017c04c06dfd065e244"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aaa4e0705ef2b73dd8e36eeb4c868f80f8393f5f4d855e94025ce7ad8525f50"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:788aef3549f1924d5c38263104dae7395bf020a42776d5ec5ea2b0d3d85d6646"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f8af619e3be812a2059b212064ea7a640aff0568d972cd1b9e920837469eb3cb"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85bfa6a5413be0ee6c5c4a663668a2cad2cbecdee367630d097d7823041bdeec"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f23222527b307970e383433daec128d769ff778d9b29343fb3496472dc20dabe"}, - {file = "regex-2021.11.10-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:da1a90c1ddb7531b1d5ff1e171b4ee61f6345119be7351104b67ff413843fe94"}, - {file = "regex-2021.11.10-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f5be7805e53dafe94d295399cfbe5227f39995a997f4fd8539bf3cbdc8f47ca8"}, - {file = "regex-2021.11.10-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a955b747d620a50408b7fdf948e04359d6e762ff8a85f5775d907ceced715129"}, - {file = "regex-2021.11.10-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:139a23d1f5d30db2cc6c7fd9c6d6497872a672db22c4ae1910be22d4f4b2068a"}, - {file = "regex-2021.11.10-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:ca49e1ab99593438b204e00f3970e7a5f70d045267051dfa6b5f4304fcfa1dbf"}, - {file = "regex-2021.11.10-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:96fc32c16ea6d60d3ca7f63397bff5c75c5a562f7db6dec7d412f7c4d2e78ec0"}, - {file = "regex-2021.11.10-cp38-cp38-win32.whl", hash = "sha256:0617383e2fe465732af4509e61648b77cbe3aee68b6ac8c0b6fe934db90be5cc"}, - {file = "regex-2021.11.10-cp38-cp38-win_amd64.whl", hash = "sha256:a3feefd5e95871872673b08636f96b61ebef62971eab044f5124fb4dea39919d"}, - {file = "regex-2021.11.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f7f325be2804246a75a4f45c72d4ce80d2443ab815063cdf70ee8fb2ca59ee1b"}, - {file = "regex-2021.11.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:537ca6a3586931b16a85ac38c08cc48f10fc870a5b25e51794c74df843e9966d"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eef2afb0fd1747f33f1ee3e209bce1ed582d1896b240ccc5e2697e3275f037c7"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:432bd15d40ed835a51617521d60d0125867f7b88acf653e4ed994a1f8e4995dc"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b43c2b8a330a490daaef5a47ab114935002b13b3f9dc5da56d5322ff218eeadb"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:962b9a917dd7ceacbe5cd424556914cb0d636001e393b43dc886ba31d2a1e449"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fa8c626d6441e2d04b6ee703ef2d1e17608ad44c7cb75258c09dd42bacdfc64b"}, - {file = "regex-2021.11.10-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3c5fb32cc6077abad3bbf0323067636d93307c9fa93e072771cf9a64d1c0f3ef"}, - {file = "regex-2021.11.10-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:cd410a1cbb2d297c67d8521759ab2ee3f1d66206d2e4328502a487589a2cb21b"}, - {file = "regex-2021.11.10-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e6096b0688e6e14af6a1b10eaad86b4ff17935c49aa774eac7c95a57a4e8c296"}, - {file = "regex-2021.11.10-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:529801a0d58809b60b3531ee804d3e3be4b412c94b5d267daa3de7fadef00f49"}, - {file = "regex-2021.11.10-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0f594b96fe2e0821d026365f72ac7b4f0b487487fb3d4aaf10dd9d97d88a9737"}, - {file = "regex-2021.11.10-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2409b5c9cef7054dde93a9803156b411b677affc84fca69e908b1cb2c540025d"}, - {file = "regex-2021.11.10-cp39-cp39-win32.whl", hash = "sha256:3b5df18db1fccd66de15aa59c41e4f853b5df7550723d26aa6cb7f40e5d9da5a"}, - {file = "regex-2021.11.10-cp39-cp39-win_amd64.whl", hash = "sha256:83ee89483672b11f8952b158640d0c0ff02dc43d9cb1b70c1564b49abe92ce29"}, - {file = "regex-2021.11.10.tar.gz", hash = "sha256:f341ee2df0999bfdf7a95e448075effe0db212a59387de1a70690e4acb03d4c6"}, -] requests = [ {file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"}, {file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"}, @@ -1174,25 +1089,25 @@ tomli = [ {file = "tomli-1.2.2.tar.gz", hash = "sha256:c6ce0015eb38820eaf32b5db832dbc26deb3dd427bd5f6556cf0acac2c214fee"}, ] typed-ast = [ - {file = "typed_ast-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7b310a207ee9fde3f46ba327989e6cba4195bc0c8c70a158456e7b10233e6bed"}, - {file = "typed_ast-1.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52ca2b2b524d770bed7a393371a38e91943f9160a190141e0df911586066ecda"}, - {file = "typed_ast-1.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:14fed8820114a389a2b7e91624db5f85f3f6682fda09fe0268a59aabd28fe5f5"}, - {file = "typed_ast-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:65c81abbabda7d760df7304d843cc9dbe7ef5d485504ca59a46ae2d1731d2428"}, - {file = "typed_ast-1.5.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:37ba2ab65a0028b1a4f2b61a8fe77f12d242731977d274a03d68ebb751271508"}, - {file = "typed_ast-1.5.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:49af5b8f6f03ed1eb89ee06c1d7c2e7c8e743d720c3746a5857609a1abc94c94"}, - {file = "typed_ast-1.5.0-cp36-cp36m-win_amd64.whl", hash = "sha256:e4374a76e61399a173137e7984a1d7e356038cf844f24fd8aea46c8029a2f712"}, - {file = "typed_ast-1.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:ea517c2bb11c5e4ba7a83a91482a2837041181d57d3ed0749a6c382a2b6b7086"}, - {file = "typed_ast-1.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:51040bf45aacefa44fa67fb9ebcd1f2bec73182b99a532c2394eea7dabd18e24"}, - {file = "typed_ast-1.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:806e0c7346b9b4af8c62d9a29053f484599921a4448c37fbbcbbf15c25138570"}, - {file = "typed_ast-1.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a67fd5914603e2165e075f1b12f5a8356bfb9557e8bfb74511108cfbab0f51ed"}, - {file = "typed_ast-1.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:224afecb8b39739f5c9562794a7c98325cb9d972712e1a98b6989a4720219541"}, - {file = "typed_ast-1.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:155b74b078be842d2eb630dd30a280025eca0a5383c7d45853c27afee65f278f"}, - {file = "typed_ast-1.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:361b9e5d27bd8e3ccb6ea6ad6c4f3c0be322a1a0f8177db6d56264fa0ae40410"}, - {file = "typed_ast-1.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:618912cbc7e17b4aeba86ffe071698c6e2d292acbd6d1d5ec1ee724b8c4ae450"}, - {file = "typed_ast-1.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7e6731044f748340ef68dcadb5172a4b1f40847a2983fe3983b2a66445fbc8e6"}, - {file = "typed_ast-1.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e8a9b9c87801cecaad3b4c2b8876387115d1a14caa602c1618cedbb0cb2a14e6"}, - {file = "typed_ast-1.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:ec184dfb5d3d11e82841dbb973e7092b75f306b625fad7b2e665b64c5d60ab3f"}, - {file = "typed_ast-1.5.0.tar.gz", hash = "sha256:ff4ad88271aa7a55f19b6a161ed44e088c393846d954729549e3cde8257747bb"}, + {file = "typed_ast-1.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5d8314c92414ce7481eee7ad42b353943679cf6f30237b5ecbf7d835519e1212"}, + {file = "typed_ast-1.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b53ae5de5500529c76225d18eeb060efbcec90ad5e030713fe8dab0fb4531631"}, + {file = "typed_ast-1.5.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:24058827d8f5d633f97223f5148a7d22628099a3d2efe06654ce872f46f07cdb"}, + {file = "typed_ast-1.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:a6d495c1ef572519a7bac9534dbf6d94c40e5b6a608ef41136133377bba4aa08"}, + {file = "typed_ast-1.5.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:de4ecae89c7d8b56169473e08f6bfd2df7f95015591f43126e4ea7865928677e"}, + {file = "typed_ast-1.5.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:256115a5bc7ea9e665c6314ed6671ee2c08ca380f9d5f130bd4d2c1f5848d695"}, + {file = "typed_ast-1.5.1-cp36-cp36m-win_amd64.whl", hash = "sha256:7c42707ab981b6cf4b73490c16e9d17fcd5227039720ca14abe415d39a173a30"}, + {file = "typed_ast-1.5.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:71dcda943a471d826ea930dd449ac7e76db7be778fcd722deb63642bab32ea3f"}, + {file = "typed_ast-1.5.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4f30a2bcd8e68adbb791ce1567fdb897357506f7ea6716f6bbdd3053ac4d9471"}, + {file = "typed_ast-1.5.1-cp37-cp37m-win_amd64.whl", hash = "sha256:ca9e8300d8ba0b66d140820cf463438c8e7b4cdc6fd710c059bfcfb1531d03fb"}, + {file = "typed_ast-1.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9caaf2b440efb39ecbc45e2fabde809cbe56272719131a6318fd9bf08b58e2cb"}, + {file = "typed_ast-1.5.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c9bcad65d66d594bffab8575f39420fe0ee96f66e23c4d927ebb4e24354ec1af"}, + {file = "typed_ast-1.5.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:591bc04e507595887160ed7aa8d6785867fb86c5793911be79ccede61ae96f4d"}, + {file = "typed_ast-1.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:a80d84f535642420dd17e16ae25bb46c7f4c16ee231105e7f3eb43976a89670a"}, + {file = "typed_ast-1.5.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:38cf5c642fa808300bae1281460d4f9b7617cf864d4e383054a5ef336e344d32"}, + {file = "typed_ast-1.5.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5b6ab14c56bc9c7e3c30228a0a0b54b915b1579613f6e463ba6f4eb1382e7fd4"}, + {file = "typed_ast-1.5.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a2b8d7007f6280e36fa42652df47087ac7b0a7d7f09f9468f07792ba646aac2d"}, + {file = "typed_ast-1.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:b6d17f37f6edd879141e64a5db17b67488cfeffeedad8c5cec0392305e9bc775"}, + {file = "typed_ast-1.5.1.tar.gz", hash = "sha256:484137cab8ecf47e137260daa20bafbba5f4e3ec7fda1c1e69ab299b75fa81c5"}, ] typing-extensions = [ {file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"}, From f33dc72cdcbce299da7b24f3810d75ceb6ffd469 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Tue, 7 Dec 2021 00:50:04 -0500 Subject: [PATCH 06/43] Added `pytest` for testing. --- poetry.lock | 110 ++++++++++++++++++++++++++++++++++++++++++++++++- pyproject.toml | 3 ++ 2 files changed, 112 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index dc580a4..8fb4f8a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -6,6 +6,14 @@ category = "main" optional = false python-versions = "*" +[[package]] +name = "atomicwrites" +version = "1.4.0" +description = "Atomic file writes." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + [[package]] name = "attrs" version = "21.2.0" @@ -270,6 +278,14 @@ zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-black (>=0.3.7)", "pytest-mypy"] +[[package]] +name = "iniconfig" +version = "1.1.1" +description = "iniconfig: brain-dead simple config-ini parsing" +category = "dev" +optional = false +python-versions = "*" + [[package]] name = "isodate" version = "0.6.0" @@ -392,6 +408,17 @@ rsa = ["cryptography (>=3.0.0,<4)"] signals = ["blinker (>=1.4.0)"] signedtoken = ["cryptography (>=3.0.0,<4)", "pyjwt (>=2.0.0,<3)"] +[[package]] +name = "packaging" +version = "21.3" +description = "Core utilities for Python packages" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" + [[package]] name = "pathspec" version = "0.9.0" @@ -412,6 +439,21 @@ python-versions = ">=3.6" docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] +[[package]] +name = "pluggy" +version = "1.0.0" +description = "plugin and hook calling mechanisms for python" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + [[package]] name = "prefixcommons" version = "0.1.9" @@ -435,6 +477,14 @@ category = "main" optional = false python-versions = ">=3.5" +[[package]] +name = "py" +version = "1.11.0" +description = "library with cross-python path, ini-parsing, io, code, log facilities" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + [[package]] name = "pyasn1" version = "0.4.8" @@ -519,6 +569,28 @@ category = "main" optional = false python-versions = ">=3.6" +[[package]] +name = "pytest" +version = "6.2.5" +description = "pytest: simple powerful testing with Python" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} +attrs = ">=19.2.0" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +py = ">=1.8.2" +toml = "*" + +[package.extras] +testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] + [[package]] name = "python-dotenv" version = "0.15.0" @@ -657,6 +729,14 @@ build = ["setuptools-git", "wheel", "twine"] docs = ["sphinx", "zope.component", "sybil", "twisted", "mock", "django (<2)", "django"] test = ["pytest (>=3.6)", "pytest-cov", "pytest-django", "zope.component", "sybil", "twisted", "mock", "django (<2)", "django"] +[[package]] +name = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +category = "dev" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" + [[package]] name = "tomli" version = "1.2.2" @@ -725,12 +805,16 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytes [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "bbd1f751e1d250b71b02e615755ac97c2d72a8beecebf7834eba93567b0b7c44" +content-hash = "635182b39afc44b38ccc38e14202c4d08e5672a6d679452f6fcd8aad8c2979c6" [metadata.files] antlr4-python3-runtime = [ {file = "antlr4-python3-runtime-4.9.3.tar.gz", hash = "sha256:f224469b4168294902bb1efa80a8bf7855f24c99aef99cbefc1bcd3cce77881b"}, ] +atomicwrites = [ + {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, + {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, +] attrs = [ {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"}, {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"}, @@ -811,6 +895,10 @@ importlib-resources = [ {file = "importlib_resources-5.4.0-py3-none-any.whl", hash = "sha256:33a95faed5fc19b4bc16b29a6eeae248a3fe69dd55d4d229d2b480e23eeaad45"}, {file = "importlib_resources-5.4.0.tar.gz", hash = "sha256:d756e2f85dd4de2ba89be0b21dba2a3bbec2e871a42a3a16719258a11f87506b"}, ] +iniconfig = [ + {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, + {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, +] isodate = [ {file = "isodate-0.6.0-py2.py3-none-any.whl", hash = "sha256:aa4d33c06640f5352aca96e4b81afd8ab3b47337cc12089822d6f322ac772c81"}, {file = "isodate-0.6.0.tar.gz", hash = "sha256:2e364a3d5759479cdb2d37cce6b9376ea504db2ff90252a2e5b7cc89cc9ff2d8"}, @@ -905,6 +993,10 @@ oauthlib = [ {file = "oauthlib-3.1.1-py2.py3-none-any.whl", hash = "sha256:42bf6354c2ed8c6acb54d971fce6f88193d97297e18602a3a886603f9d7730cc"}, {file = "oauthlib-3.1.1.tar.gz", hash = "sha256:8f0215fcc533dd8dd1bee6f4c412d4f0cd7297307d43ac61666389e3bc3198a3"}, ] +packaging = [ + {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, + {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, +] pathspec = [ {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, @@ -913,6 +1005,10 @@ platformdirs = [ {file = "platformdirs-2.4.0-py3-none-any.whl", hash = "sha256:8868bbe3c3c80d42f20156f22e7131d2fb321f5bc86a2a345375c6481a67021d"}, {file = "platformdirs-2.4.0.tar.gz", hash = "sha256:367a5e80b3d04d2428ffa76d33f124cf11e8fff2acdaa9b43d545f5c7d661ef2"}, ] +pluggy = [ + {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, + {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, +] prefixcommons = [ {file = "prefixcommons-0.1.9-py3-none-any.whl", hash = "sha256:2ff99e9f2c27f41e6beb831742ca88ddae129b2de6dcc81b0b27f0de69cb2e8a"}, {file = "prefixcommons-0.1.9-py3.8.egg", hash = "sha256:f820dc69f0eba1f6fd80bdb2e78420e4970f20dfb4c307fed77c607198ca69f2"}, @@ -944,6 +1040,10 @@ protobuf = [ {file = "protobuf-3.19.1-py2.py3-none-any.whl", hash = "sha256:e813b1c9006b6399308e917ac5d298f345d95bb31f46f02b60cd92970a9afa17"}, {file = "protobuf-3.19.1.tar.gz", hash = "sha256:62a8e4baa9cb9e064eb62d1002eca820857ab2138440cb4b3ea4243830f94ca7"}, ] +py = [ + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, +] pyasn1 = [ {file = "pyasn1-0.4.8-py2.4.egg", hash = "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3"}, {file = "pyasn1-0.4.8-py2.5.egg", hash = "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf"}, @@ -1012,6 +1112,10 @@ pyrsistent = [ {file = "pyrsistent-0.18.0-cp39-cp39-win_amd64.whl", hash = "sha256:404e1f1d254d314d55adb8d87f4f465c8693d6f902f67eb6ef5b4526dc58e6ea"}, {file = "pyrsistent-0.18.0.tar.gz", hash = "sha256:773c781216f8c2900b42a7b638d5b517bb134ae1acbebe4d1e8f1f41ea60eb4b"}, ] +pytest = [ + {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, + {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, +] python-dotenv = [ {file = "python-dotenv-0.15.0.tar.gz", hash = "sha256:587825ed60b1711daea4832cf37524dfd404325b7db5e25ebe88c495c9f807a0"}, {file = "python_dotenv-0.15.0-py2.py3-none-any.whl", hash = "sha256:0c8d1b80d1a1e91717ea7d526178e3882732420b03f08afea0406db6402e220e"}, @@ -1084,6 +1188,10 @@ testfixtures = [ {file = "testfixtures-6.18.3-py2.py3-none-any.whl", hash = "sha256:6ddb7f56a123e1a9339f130a200359092bd0a6455e31838d6c477e8729bb7763"}, {file = "testfixtures-6.18.3.tar.gz", hash = "sha256:2600100ae96ffd082334b378e355550fef8b4a529a6fa4c34f47130905c7426d"}, ] +toml = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] tomli = [ {file = "tomli-1.2.2-py3-none-any.whl", hash = "sha256:f04066f68f5554911363063a30b108d2b5a5b1a010aa8b6132af78489fe3aade"}, {file = "tomli-1.2.2.tar.gz", hash = "sha256:c6ce0015eb38820eaf32b5db832dbc26deb3dd427bd5f6556cf0acac2c214fee"}, diff --git a/pyproject.toml b/pyproject.toml index ca2ee7c..9ca98ac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,3 +39,6 @@ PyYAML = "^5.4.1" setuptools = "^52.0.0" python-dotenv = "^0.15.0" black = "^21.9b0" + +[tool.poetry.dev-dependencies] +pytest = "^6.2.5" From 20efe9a4ab7b670145761b9d3635f93ffce4bb10 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Tue, 7 Dec 2021 01:29:37 -0500 Subject: [PATCH 07/43] Added a test for `--help` to the command line test. --- tests/test_command_line.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tests/test_command_line.py diff --git a/tests/test_command_line.py b/tests/test_command_line.py new file mode 100644 index 0000000..bcb4a85 --- /dev/null +++ b/tests/test_command_line.py @@ -0,0 +1,35 @@ +""" +test_command_line.py: Test the command line interfaces of this program. +""" + +import subprocess + +def execute_sheet2linkml(args) -> (int, str, str): + """ + Execute sheet2linkml as a command-line tool with the provided arguments. + + :param args: A list of arguments to send to sheet2linkml + :return: A tuple containing the error code, captured STDOUT and captured STDERR respectively + """ + + result = subprocess.run(['sheet2linkml'] + args, capture_output=True, encoding='utf-8') + + return result.returncode, result.stdout, result.stderr + + +class TestCommandLine: + """ + Test execution of the `sheet2linkml` script at the command line. + """ + + def test_help(self): + """ + Test whether sheet2linkml accepts `--help` and provides useful information. + """ + (errno, stdout, stderr) = execute_sheet2linkml(['--help']) + + assert errno == 0 + assert 'Usage: sheet2linkml' in stdout + assert '--help' in stdout + assert 'Show this message and exit.' in stdout + assert 'ERROR' not in stderr From edf356cdbaf2e0f988c6c13f03d198b9c11f4786 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Tue, 7 Dec 2021 01:32:29 -0500 Subject: [PATCH 08/43] Added check for a missing Google Sheet ID. --- sheet2linkml/cli.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sheet2linkml/cli.py b/sheet2linkml/cli.py index 8fca8da..4fe8b01 100644 --- a/sheet2linkml/cli.py +++ b/sheet2linkml/cli.py @@ -67,6 +67,9 @@ def main(output, filter_entity, logging_config, write_mappings, include_terminol ) exit(1) google_sheet_id = os.getenv("CDM_GOOGLE_SHEET_ID") + if not google_sheet_id: + logging.error("A Google Sheet ID is required; please set environmental variable 'CDM_GOOGLE_SHEET_ID' to a Google Sheet ID.") + exit(1) # Arbitrarily set a CRDC-H root URI. crdch_root = "https://example.org/crdch" From 943fe89e6f4035fab3daf6748713fab1eea69559 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Tue, 7 Dec 2021 02:03:13 -0500 Subject: [PATCH 09/43] Added `--google-sheet-id` as a command line argument. --- sheet2linkml/cli.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sheet2linkml/cli.py b/sheet2linkml/cli.py index 4fe8b01..3794a38 100644 --- a/sheet2linkml/cli.py +++ b/sheet2linkml/cli.py @@ -21,6 +21,13 @@ @click.command() +@click.option( + '--google-sheet-id', + '-g', + type=str, + default=os.getenv("CDM_GOOGLE_SHEET_ID"), + help="The Google Sheet ID that should be converted into a LinkML sheet.", +) @click.option( "--output", "-o", @@ -49,7 +56,7 @@ 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): +def main(google_sheet_id, output, filter_entity, logging_config, write_mappings, include_terminologies): # Display INFO log entry and up. logging.config.fileConfig(logging_config) From c4c60aabcf13c1a442b1499b819ed22117c63a2c Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Tue, 7 Dec 2021 02:03:44 -0500 Subject: [PATCH 10/43] Added check for logging_config before using it. --- sheet2linkml/cli.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sheet2linkml/cli.py b/sheet2linkml/cli.py index 3794a38..810f5bc 100644 --- a/sheet2linkml/cli.py +++ b/sheet2linkml/cli.py @@ -58,7 +58,8 @@ ) def main(google_sheet_id, output, filter_entity, logging_config, write_mappings, include_terminologies): # Display INFO log entry and up. - logging.config.fileConfig(logging_config) + if os.path.exists(logging_config): + logging.config.fileConfig(logging_config) # Load environemental variables from `.env` if one is present. load_dotenv() From 3736d8b71c900bc67be667e47e31d4b32494442d Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Tue, 7 Dec 2021 02:04:06 -0500 Subject: [PATCH 11/43] Updated sheet2linkml to explicitly return 0 as an exit code. --- sheet2linkml/cli.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sheet2linkml/cli.py b/sheet2linkml/cli.py index 810f5bc..1a3e784 100644 --- a/sheet2linkml/cli.py +++ b/sheet2linkml/cli.py @@ -138,6 +138,7 @@ def main(google_sheet_id, output, filter_entity, logging_config, write_mappings, if write_mappings: Mappings.write_to_file(model.mappings, filename=write_mappings, model=model) + exit(0) if __name__ == "__main__": main() From 3af8e51afbbea2cce1eda4066f3538fbfed2a159 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Tue, 7 Dec 2021 02:18:20 -0500 Subject: [PATCH 12/43] Added tests for generating a schema from a Google Sheet. --- tests/test_command_line.py | 50 ++ ...vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I.yaml | 550 ++++++++++++++++++ 2 files changed, 600 insertions(+) create mode 100644 tests/testing-schema-on-gsheet/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I.yaml diff --git a/tests/test_command_line.py b/tests/test_command_line.py index bcb4a85..cc258b2 100644 --- a/tests/test_command_line.py +++ b/tests/test_command_line.py @@ -3,6 +3,8 @@ """ import subprocess +import logging +import os def execute_sheet2linkml(args) -> (int, str, str): """ @@ -33,3 +35,51 @@ def test_help(self): assert '--help' in stdout assert 'Show this message and exit.' in stdout assert 'ERROR' not in stderr + + def test_execution(self, tmp_path): + """ + Test whether sheet2linkml can be used to process a particular Google Sheet into LinkML, which is located at + https://docs.google.com/spreadsheets/d/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I/edit?usp=sharing + """ + + output_path = os.path.join(tmp_path, 'schema.yaml') + + print(f"Writing execution test output to '{output_path}'") + + (errno, stdout, stderr) = execute_sheet2linkml([ + '--google-sheet-id', '1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I', + '-o', output_path + ]) + + assert 'INFO: Google Sheet loaded: GSheetModel with an underlying Google Sheet titled "Test schema for sheet2linkml" containing 8 worksheets' in stderr + assert 'INFO: Generating LinkML for GSheetModel with an underlying Google Sheet titled "Test schema for sheet2linkml" containing 8 worksheets' in stderr + assert 'INFO: Generating LinkML for Enum named Subject.breed from worksheet "O_CCDH Enums" containing 8 values' in stderr + + assert stdout == '' + assert errno == 0 + + assert os.path.exists(output_path) + + # Ensure that we get the same output from sheet2linkml as we expected. + def make_schema_comparable(lines): + """ + Some parts of the schema are not comparable, so we remove them before comparing them. + """ + + output = "" + for line in lines: + if line.startswith('generation_date:'): + continue + output += line + '\n' + + return output + + dirname = os.path.dirname(__file__) + with open(os.path.join(dirname, 'testing-schema-on-gsheet/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I.yaml'), 'r') as f: + expected_schema = make_schema_comparable(f.readlines()) + + with open(output_path, 'r') as f: + obtained_schema = make_schema_comparable(f.readlines()) + + assert obtained_schema != '' + assert obtained_schema == expected_schema diff --git a/tests/testing-schema-on-gsheet/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I.yaml b/tests/testing-schema-on-gsheet/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I.yaml new file mode 100644 index 0000000..0ddd6e3 --- /dev/null +++ b/tests/testing-schema-on-gsheet/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I.yaml @@ -0,0 +1,550 @@ +name: CRDC-H +notes: +- Derived from [Test schema for sheet2linkml](https://docs.google.com/spreadsheets/d/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I) +id: https://example.org/crdch +imports: +- linkml:types +license: https://creativecommons.org/publicdomain/zero/1.0/ +prefixes: + linkml: https://w3id.org/linkml/ + crdch: https://example.org/crdch/ + 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/ +default_prefix: crdch +types: + crdch_string: + name: crdch_string + description: A sequence of Unicode characters. There are no limits on the number + of characters in the string. + notes: + - Derived from [crdch_string in sheet Primitives](https://docs.google.com/spreadsheets/d/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I/edit#gid=1915311830) + typeof: string + crdch_integer: + name: crdch_integer + description: An integer number. This data type is based on the decimal type, + but the fractional component is not allowed. There are no restrictions on the + size of the integer. + notes: + - Derived from [crdch_integer in sheet Primitives](https://docs.google.com/spreadsheets/d/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I/edit#gid=1915311830) + typeof: integer + crdch_decimal: + name: crdch_decimal + description: A rational number that has a decimal representation. This data type + does not restrict the size or precision of the number. + notes: + - Derived from [crdch_decimal in sheet Primitives](https://docs.google.com/spreadsheets/d/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I/edit#gid=1915311830) + typeof: decimal + crdch_boolean: + name: crdch_boolean + description: "Value representing either \u201Ctrue\u201D or \u201Cfalse\u201D\ + . Permissible values (case-sensitive) = \u201Ctrue\u201D, \u201Cfalse\u201D\ + , \u201C1\u201D, \u201C0\u201D." + notes: + - Derived from [crdch_boolean in sheet Primitives](https://docs.google.com/spreadsheets/d/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I/edit#gid=1915311830) + typeof: boolean + crdch_dateTime: + name: crdch_dateTime + description: A date and time string specified using a specialized concatenation + of the date and time data types, in the general format YYYY-MM-DDThh:mm:ss+zz:zz. + notes: + - Derived from [crdch_dateTime in sheet Primitives](https://docs.google.com/spreadsheets/d/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I/edit#gid=1915311830) + typeof: datetime + crdch_curie: + name: crdch_curie + description: "A compact URI (CURIE), which is a bipartite identifier of the form\ + \ prefix:reference, in which the prefix is a convenient abbreviation of a URI.\ + \ It is expressed in the format \u201Cprefix:reference\u201D. When a mapping\ + \ of prefix to base URI is provided (external to this data type), a CURIE may\ + \ be mapped to a URI." + notes: + - Derived from [crdch_curie in sheet Primitives](https://docs.google.com/spreadsheets/d/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I/edit#gid=1915311830) + typeof: uriorcurie + crdch_code: + name: crdch_code + description: '' + notes: + - Derived from [crdch_code in sheet Primitives](https://docs.google.com/spreadsheets/d/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I/edit#gid=1915311830) + typeof: string +enums: + enum_CRDCH_Subject_species: + name: enum_CRDCH_Subject_species + comments: + - 'Name according to TCCM: ""' + code_set: https://terminology.ccdh.io/enumerations/CRDC-H.Subject.species + code_set_version: '' + enum_CRDCH_Subject_breed: + name: enum_CRDCH_Subject_breed + description: A label given to a group of animals homogeneous in appearance and + other characteristics that distinguish it from other animals of the same species. + notes: + - Derived from [Subject.breed in sheet O_CCDH Enums](https://docs.google.com/spreadsheets/d/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I/edit#gid=1251633595) + permissible_values: + Akita: + text: Akita + description: '' + American Staffordshire Terrier: + text: American Staffordshire Terrier + description: '' + Australian Shepherd: + text: Australian Shepherd + description: '' + Basset Hound: + text: Basset Hound + description: '' + Beagle: + text: Beagle + description: '' + Belgian Malinois: + text: Belgian Malinois + description: '' + Bernese Mountain Dog: + text: Bernese Mountain Dog + description: '' + Black and Tan Coonhound: + text: Black and Tan Coonhound + description: '' + enum_CRDCH_Subject_sex: + name: enum_CRDCH_Subject_sex + comments: + - 'Name according to TCCM: ""' + code_set: https://terminology.ccdh.io/enumerations/CRDC-H.Subject.sex + code_set_version: '' + enum_CRDCH_Subject_ethnicity: + name: enum_CRDCH_Subject_ethnicity + comments: + - 'Name according to TCCM: ""' + code_set: https://terminology.ccdh.io/enumerations/CRDC-H.Subject.ethnicity + code_set_version: '' + enum_CRDCH_Subject_race: + name: enum_CRDCH_Subject_race + comments: + - 'Name according to TCCM: ""' + code_set: https://terminology.ccdh.io/enumerations/CRDC-H.Subject.race + code_set_version: '' + enum_CRDCH_Subject_vital_status: + name: enum_CRDCH_Subject_vital_status + comments: + - 'Name according to TCCM: ""' + code_set: https://terminology.ccdh.io/enumerations/CRDC-H.Subject.vital_status + code_set_version: '' + enum_CRDCH_Subject_cause_of_death: + name: enum_CRDCH_Subject_cause_of_death + comments: + - 'Name according to TCCM: ""' + code_set: https://terminology.ccdh.io/enumerations/CRDC-H.Subject.cause_of_death + code_set_version: '' +classes: + Subject: + name: Subject + description: Demographics and other administrative information about an individual + or animal receiving care or other health-related services. + notes: + - Derived from [Subject in sheet Subject](https://docs.google.com/spreadsheets/d/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I/edit#gid=79247765) + is_a: Entity + attributes: + id: + name: id + description: The 'logical' identifier of the entity within the system of record. The + simple value of this attribute stands for an identifier of this data object + within the system, it can be used as a reference from other objects within + the same system (i.e. primary and foreign keys), and it should be unique + per type of object. The same data object copied to a different system will + likely have a different "id" in the new system since "id" values are system + specific and do not represent persistent business identifiers. Business + identifiers are assigned outside the information system and are captured + in the "identifier" field. The "id" field is more likely to be a serially + or randomly generated value that is assigned to the data object as it is + created in a system. + notes: + - 'Cardinality: 1..1' + comments: + - 'FHIR naming conventions are followed here, where ''id'' is used for logical + identifiers, and ''identifier'' for business identifiers. The identified + entity may have a different ''id'' in a different system, and have many + external business ''identifiers'' associated with it. If an "id" value can + also be considered to be a business identifier, and should be transmissible + to other systems, it should be duplicated in the "identifier" attribute + along with the additional metadata needed to give context to the value of + "id". An entity in this model that does not have an "id" field is considered + to be an embeddable entity that can not stand on its own. ' + examples: + - value: '' + domain: Subject + multivalued: false + range: crdch_string + required: true + identifier: + name: identifier + exact_mappings: + - ICDC:Case.patient_id + description: A 'business' identifier or accession number for the entity, typically + as provided by an external system or authority, that are globally unique + and persist across implementing systems. Also, since these identifiers are + created outside the information system through a specific business process, + the Identifier type has additional attributes to capture this additional + metadata so the actual identifier values are qualified by the context that + created those values. This additional context allows "identifier" instances + to be transmitted as business data across systems while still being able + to trace them back to the system of origin. + notes: + - 'Cardinality: 0..m' + comments: + - FHIR naming conventions are followed here, where 'id' is used for logical + identifiers which are unique only within a given system, and 'identifier' + for business identifiers, which are used to connect entities or share content + across systems. The complex 'Identifier' data type is used to capture + the identifier itself, along with metadata about its source. + examples: + - value: '' + domain: Subject + multivalued: true + inlined_as_list: true + range: Entity + required: false + species: + name: species + description: The scientific binomial name for the species of the subject (e.g. + Homo sapiens, Mus musculus, etc.) + notes: + - 'Cardinality: 0..1' + examples: + - value: Homo sapiens + - value: Canis familiaris + - value: Mus musculus + values_from: crdch:enum_CRDCH_Subject_species + domain: Subject + multivalued: false + range: CodeableConcept + required: false + breed: + name: breed + exact_mappings: + - ICDC:Demographic.breed + description: A label given to a group of animals homogeneous in appearance + and other characteristics that distinguish it from other animals of the + same species. + notes: + - 'Cardinality: 0..1' + examples: + - value: Affenpinscher + - value: Afghan Hound + - value: Airedale Terrier + - value: Akita + values_from: crdch:enum_CRDCH_Subject_breed + domain: Subject + multivalued: false + range: CodeableConcept + required: false + sex: + name: sex + exact_mappings: + - ICDC:Demographic.sex + - GDC:Demographic.gender + - PDC:Demographic.gender + - HTAN:Demographics.Gender + description: The biologic character or quality that distinguishes male and + female from one another as expressed by analysis of the person's gonadal, + morphologic (internal and external), chromosomal, and hormonal characteristics. + notes: + - 'Cardinality: 0..1' + examples: + - value: Female + - value: Intersex + - value: Male + - value: Not Reported + - value: Unknown + - value: Unspecified + values_from: crdch:enum_CRDCH_Subject_sex + domain: Subject + multivalued: false + range: CodeableConcept + required: false + ethnicity: + name: ethnicity + exact_mappings: + - GDC:Clinical.ethnicity + - GDC:Demographic.ethnicity + - PDC:Demographic.ethnicity + - HTAN:Demographics.Ethnicity + description: An individual's self-described social and cultural grouping, + specifically whether an individual describes themselves as Hispanic or Latino. + The provided values are based on the categories defined by the U.S. Office + of Management and Business and used by the U.S. Census Bureau + notes: + - 'Cardinality: 0..1' + comments: + - Applicable only when Subject.species is Homo Sapiens + examples: + - value: Hispanic or Latino + - value: Not Allowed To Collect + - value: Not Hispanic or Latino + - value: Not Reported + - value: Unknown + values_from: crdch:enum_CRDCH_Subject_ethnicity + domain: Subject + multivalued: false + range: CodeableConcept + required: false + race: + name: race + exact_mappings: + - GDC:Clinical.race + - GDC:Demographic.race + - PDC:Demographic.race + - HTAN:Demographics.Race + description: An arbitrary classification of a taxonomic group that is a division + of a species. It usually arises as a consequence of geographical isolation + within a species and is characterized by shared heredity, physical attributes + and behavior, and in the case of humans, by common history, nationality, + or geographic distribution. The provided values are based on the categories + defined by the U.S. Office of Management and Business and used by the U.S. + Census Bureau. + notes: + - 'Cardinality: 0..m' + examples: + - value: American Indian or Alaska Native + - value: Asian + - value: Black or African American + - value: Native Hawaiian or other Pacific Islander + - value: Not Allowed To Collect + - value: Not Reported + - value: Unknown + - value: White + values_from: crdch:enum_CRDCH_Subject_race + domain: Subject + multivalued: true + range: CodeableConcept + required: false + year_of_birth: + name: year_of_birth + exact_mappings: + - GDC:Demographic.year_of_birth + - PDC:Demographic.year_of_birth + - ICDC:Demographic.date_of_birth + - HTAN:Demographics.YearOfBirth + description: Numeric value to represent the calendar year in which an individual + was born. + notes: + - 'Cardinality: 0..1' + comments: + - Applicable only when Subject.species is Homo Sapiens + examples: + - value: '' + domain: Subject + multivalued: false + range: crdch_integer + required: false + vital_status: + name: vital_status + exact_mappings: + - GDC:Demographic.vital_status + - PDC:Demographic.vital_status + - HTAN:Demographics.VitalStatus + description: Coded value indicating the state or condition of being living + or deceased; also includes the case where the vital status is unknown. + notes: + - 'Cardinality: 0..1' + examples: + - value: Alive + - value: Dead + - value: Unknown + - value: Not Reported + values_from: crdch:enum_CRDCH_Subject_vital_status + domain: Subject + multivalued: false + range: CodeableConcept + required: false + age_at_death: + name: age_at_death + close_mappings: + - GDC:Demographic.days_to_death + - PDC:Demographic.days_to_death + description: The age of an individual at the time of death, expressed in days + since birth + notes: + - 'Cardinality: 0..1' + examples: + - value: '' + domain: Subject + multivalued: false + range: Entity + required: false + year_of_death: + name: year_of_death + exact_mappings: + - GDC:Demographic.year_of_death + - PDC:Demographic.year_of_death + description: Numeric value to represent the calendar year in which an individual + died. + notes: + - 'Cardinality: 0..1' + examples: + - value: '' + domain: Subject + multivalued: false + range: crdch_integer + required: false + cause_of_death: + name: cause_of_death + exact_mappings: + - GDC:Demographic.cause_of_death + - PDC:Demographic.cause_of_death + description: Coded value indicating the circumstance or condition that results + in the death of the subject. + notes: + - 'Cardinality: 0..1' + examples: + - value: Cancer Related + - value: Cardiovascular Disorder, NOS + - value: End-stage Renal Disease + - value: '' + values_from: crdch:enum_CRDCH_Subject_cause_of_death + domain: Subject + multivalued: false + range: CodeableConcept + required: false + CodeableConcept: + name: CodeableConcept + description: A representation of a concept that may be defined by or mapped to + one or more codes in code systems (terminologies, ontologies, dictionaries, + code sets, etc) - but may also be defined by the provision of text. + notes: + - Derived from [CodeableConcept in sheet CodeableConcept](https://docs.google.com/spreadsheets/d/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I/edit#gid=696864465) + comments: + - 'More than one code may be used in CodeableConcept. The concept may be coded + multiple times in different code systems (or even multiple times in the same + code systems, where multiple forms are possible). Each Coding is a representation + of the concept as described above and may have slightly different granularity + due to the differences in the definitions of the underlying codes. There is + no meaning associated with the ordering of Coding within a CodeableConcept. + A typical use of CodeableConcept is to send the local code that the concept + was coded with, and also one or more translations to publicly defined code systems + such as LOINC or SNOMED CT. ' + is_a: Entity + attributes: + coding: + name: coding + description: A reference to a code defined by a terminology system + notes: + - 'Cardinality: 0..m' + examples: + - value: '' + domain: CodeableConcept + multivalued: true + inlined_as_list: true + range: Coding + required: false + text: + name: text + description: A human language representation of the concept represented by + the Coding. + notes: + - 'Cardinality: 0..1' + comments: + - 'The text attribute represents the concept as entered or chosen by the user; + often the value of text is the same as a display of one of the codings. A + concept that does not have an appropriate or known coding can be represented + using free-text in the text attribute. ' + examples: + - value: '' + domain: CodeableConcept + multivalued: false + range: crdch_string + required: false + Coding: + name: Coding + description: A structured representation of a coded/enumerated data value, that + includes additional metadata about the code and code system. + notes: + - Derived from [Coding in sheet Coding](https://docs.google.com/spreadsheets/d/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I/edit#gid=964403102) + is_a: Entity + attributes: + code: + name: code + description: The symbol/value of the code, as defined by the code system. + notes: + - 'Cardinality: 1..1' + examples: + - value: '' + domain: Coding + multivalued: false + range: crdch_string + required: true + label: + name: label + description: A human-readable name for the code, as defined by the code system. + notes: + - 'Cardinality: 0..1' + examples: + - value: '' + domain: Coding + multivalued: false + range: crdch_string + required: false + system: + name: system + description: The URL of the code system where the code is defined. + notes: + - 'Cardinality: 1..1' + examples: + - value: '' + domain: Coding + multivalued: false + range: crdch_string + required: true + system_version: + name: system_version + description: The version of the code system. + notes: + - 'Cardinality: 0..1' + examples: + - value: '' + domain: Coding + multivalued: false + range: crdch_string + required: false + value_set: + name: value_set + description: The identifier of the enumeration / value set that the code is + a part of in the context of this element + notes: + - 'Cardinality: 0..1' + examples: + - value: '' + domain: Coding + multivalued: false + range: crdch_string + required: false + value_set_version: + name: value_set_version + description: The version of the enuemration / value set the code is pulled + from + notes: + - 'Cardinality: 0..1' + examples: + - value: '' + domain: Coding + multivalued: false + range: crdch_string + required: false + tag: + name: tag + description: original value | harmonized value | + notes: + - 'Cardinality: 0..m' + examples: + - value: '' + domain: Coding + multivalued: true + inlined_as_list: true + range: crdch_string + required: false + Entity: + name: Entity + description: Any resource that has its own identifier + notes: + - Derived from [Entity in sheet Entity](https://docs.google.com/spreadsheets/d/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I/edit#gid=1810442705) +generation_date: '2021-12-07T07:17:22.116646+00:00' From 17cbcd7f814e5e46b0de4e3b36c08c963c76c548 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Tue, 7 Dec 2021 02:18:45 -0500 Subject: [PATCH 13/43] Replaced unnecessary print() with logging.debug(). --- sheet2linkml/source/gsheetmodel/gsheetmodel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sheet2linkml/source/gsheetmodel/gsheetmodel.py b/sheet2linkml/source/gsheetmodel/gsheetmodel.py index 791329c..5f27a1b 100644 --- a/sheet2linkml/source/gsheetmodel/gsheetmodel.py +++ b/sheet2linkml/source/gsheetmodel/gsheetmodel.py @@ -314,7 +314,7 @@ def as_linkml(self, root_uri) -> SchemaDefinition: ) def fix_type_name(entity, dct, prop): - print(f"fix_type_name({entity}, {dct}, {prop})") + logging.debug(f"fix_type_name({entity}, {dct}, {prop})") value = dct[prop] if value is not None and value not in valid_types: logging.warning( From 75f9ba9e1b28df896d1cc9d3b69db35e1ad2fa0c Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Tue, 7 Dec 2021 02:25:58 -0500 Subject: [PATCH 14/43] Updated TCCM API and invocation. This is because the CCDH Terminology Service endpoint changed. --- sheet2linkml/source/gsheetmodel/entity.py | 2 +- sheet2linkml/terminologies/tccm/api.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sheet2linkml/source/gsheetmodel/entity.py b/sheet2linkml/source/gsheetmodel/entity.py index 3f32c17..76a1de5 100644 --- a/sheet2linkml/source/gsheetmodel/entity.py +++ b/sheet2linkml/source/gsheetmodel/entity.py @@ -368,7 +368,7 @@ def as_linkml_enum(self) -> EnumDefinition: return None # Look up enumerations on the Terminology Service. - enum_info = self.terminology_service.get_enum_values_for_field(self.full_name) + enum_info = self.terminology_service.get_enum_values_for_field('CRDC-H', self.entity.name, self.name) permissible_values = {} for pv in enum_info.get("permissible_values", []): text = pv.get("text") diff --git a/sheet2linkml/terminologies/tccm/api.py b/sheet2linkml/terminologies/tccm/api.py index 26d115e..2086cee 100644 --- a/sheet2linkml/terminologies/tccm/api.py +++ b/sheet2linkml/terminologies/tccm/api.py @@ -22,7 +22,7 @@ def __init__(self, base_url: str): # This is unlikely to change during a run and is quite expensive (since we download it from the network), so # we memoize it. @lru_cache - def get_enum_values_for_field(self, field_name: str): + def get_enum_values_for_field(self, model: str, entity: str, attribute: str): """ Returns information on the enum fields for a particular field. @@ -31,7 +31,7 @@ def get_enum_values_for_field(self, field_name: str): """ # Construct the URL we need to access the enumeration information. - url = f"{self.base_url}/enumerations/{field_name}" + url = f"{self.base_url}/enumerations/{model}/{entity}/{attribute}" logging.debug(f"Querying TCCM for attribute info: {url}") # Query the URL. From 6b831b15ad684383475595e34fdb4628232e06ed Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Tue, 7 Dec 2021 02:27:08 -0500 Subject: [PATCH 15/43] Updated tests in line with CCDH Terminology Service changes. --- tests/test_command_line.py | 6 +- ...vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I.yaml | 124 ++++++++++++++++-- 2 files changed, 115 insertions(+), 15 deletions(-) diff --git a/tests/test_command_line.py b/tests/test_command_line.py index cc258b2..82f41c0 100644 --- a/tests/test_command_line.py +++ b/tests/test_command_line.py @@ -1,7 +1,7 @@ """ test_command_line.py: Test the command line interfaces of this program. """ - +import re import subprocess import logging import os @@ -70,7 +70,9 @@ def make_schema_comparable(lines): for line in lines: if line.startswith('generation_date:'): continue - output += line + '\n' + if re.match('^\\s*code_set_version: ', line): + continue + output += line return output diff --git a/tests/testing-schema-on-gsheet/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I.yaml b/tests/testing-schema-on-gsheet/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I.yaml index 0ddd6e3..9d321b1 100644 --- a/tests/testing-schema-on-gsheet/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I.yaml +++ b/tests/testing-schema-on-gsheet/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I.yaml @@ -71,10 +71,11 @@ types: enums: enum_CRDCH_Subject_species: name: enum_CRDCH_Subject_species + description: Autogenerated Enumeration for CRDC-H Subject species comments: - - 'Name according to TCCM: ""' + - 'Name according to TCCM: "CRDC-H.Subject.species"' code_set: https://terminology.ccdh.io/enumerations/CRDC-H.Subject.species - code_set_version: '' + code_set_version: '2021-12-07T07:25:24.718897+00:00' enum_CRDCH_Subject_breed: name: enum_CRDCH_Subject_breed description: A label given to a group of animals homogeneous in appearance and @@ -108,34 +109,131 @@ enums: description: '' enum_CRDCH_Subject_sex: name: enum_CRDCH_Subject_sex + description: Autogenerated Enumeration for CRDC-H Subject sex comments: - - 'Name according to TCCM: ""' + - 'Name according to TCCM: "CRDC-H.Subject.sex"' code_set: https://terminology.ccdh.io/enumerations/CRDC-H.Subject.sex - code_set_version: '' + code_set_version: '2021-12-07T07:25:25.116036+00:00' + permissible_values: + unspecified: + text: unspecified + unknown: + text: unknown + female: + text: female + male: + text: male + not reported: + text: not reported enum_CRDCH_Subject_ethnicity: name: enum_CRDCH_Subject_ethnicity + description: Autogenerated Enumeration for CRDC-H Subject ethnicity comments: - - 'Name according to TCCM: ""' + - 'Name according to TCCM: "CRDC-H.Subject.ethnicity"' code_set: https://terminology.ccdh.io/enumerations/CRDC-H.Subject.ethnicity - code_set_version: '' + code_set_version: '2021-12-07T07:25:25.328531+00:00' + permissible_values: + hispanic or latino: + text: hispanic or latino + not reported: + text: not reported + Unknown: + text: Unknown + description: Unknown + not allowed to collect: + text: not allowed to collect + not hispanic or latino: + text: not hispanic or latino + unknown: + text: unknown enum_CRDCH_Subject_race: name: enum_CRDCH_Subject_race + description: Autogenerated Enumeration for CRDC-H Subject race comments: - - 'Name according to TCCM: ""' + - 'Name according to TCCM: "CRDC-H.Subject.race"' code_set: https://terminology.ccdh.io/enumerations/CRDC-H.Subject.race - code_set_version: '' + code_set_version: '2021-12-07T07:25:25.535967+00:00' + permissible_values: + other: + text: other + american indian or alaska native: + text: american indian or alaska native + native hawaiian or other pacific islander: + text: native hawaiian or other pacific islander + asian: + text: asian + not reported: + text: not reported + not allowed to collect: + text: not allowed to collect + white: + text: white + Unknown: + text: Unknown + description: Unknown + black or african american: + text: black or african american + unknown: + text: unknown enum_CRDCH_Subject_vital_status: name: enum_CRDCH_Subject_vital_status + description: Autogenerated Enumeration for CRDC-H Subject vital_status comments: - - 'Name according to TCCM: ""' + - 'Name according to TCCM: "CRDC-H.Subject.vital_status"' code_set: https://terminology.ccdh.io/enumerations/CRDC-H.Subject.vital_status - code_set_version: '' + code_set_version: '2021-12-07T07:25:25.758942+00:00' + permissible_values: + Unknown: + text: Unknown + description: Unknown + Not Reported: + text: Not Reported + description: Not Reported + Alive: + text: Alive + description: ALIVE + Dead: + text: Dead + description: DEAD enum_CRDCH_Subject_cause_of_death: name: enum_CRDCH_Subject_cause_of_death + description: Autogenerated Enumeration for CRDC-H Subject cause_of_death comments: - - 'Name according to TCCM: ""' + - 'Name according to TCCM: "CRDC-H.Subject.cause_of_death"' code_set: https://terminology.ccdh.io/enumerations/CRDC-H.Subject.cause_of_death - code_set_version: '' + code_set_version: '2021-12-07T07:25:25.973650+00:00' + permissible_values: + Spinal Muscular Atrophy: + text: Spinal Muscular Atrophy + description: Spinal Muscular Atrophy + Not Cancer Related: + text: Not Cancer Related + Not Reported: + text: Not Reported + description: Not Reported + Cardiovascular Disorder, NOS: + text: Cardiovascular Disorder, NOS + description: Cardiovascular Disorder, NOS + Renal Disorder, NOS: + text: Renal Disorder, NOS + description: Renal Disorder, NOS + Surgical Complications: + text: Surgical Complications + description: Surgical Procedure Complication + Cancer Related: + text: Cancer Related + End-stage Renal Disease: + text: End-stage Renal Disease + description: Chronic Kidney Disease, Stage 5 + Infection: + text: Infection + description: Infection + Toxicity: + text: Toxicity + description: Toxicity + Unknown: + text: Unknown + description: Unknown classes: Subject: name: Subject @@ -547,4 +645,4 @@ classes: description: Any resource that has its own identifier notes: - Derived from [Entity in sheet Entity](https://docs.google.com/spreadsheets/d/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I/edit#gid=1810442705) -generation_date: '2021-12-07T07:17:22.116646+00:00' +generation_date: '2021-12-07T07:25:23.360980+00:00' From f85927eea587ff743120e6fb312b7bd41d41a4e5 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Tue, 7 Dec 2021 02:36:07 -0500 Subject: [PATCH 16/43] Fixed source code style with black. --- sheet2linkml/cli.py | 18 +++++-- sheet2linkml/source/gsheetmodel/entity.py | 4 +- tests/test_command_line.py | 66 +++++++++++++++-------- 3 files changed, 61 insertions(+), 27 deletions(-) diff --git a/sheet2linkml/cli.py b/sheet2linkml/cli.py index 1a3e784..6d0c9c6 100644 --- a/sheet2linkml/cli.py +++ b/sheet2linkml/cli.py @@ -22,8 +22,8 @@ @click.command() @click.option( - '--google-sheet-id', - '-g', + "--google-sheet-id", + "-g", type=str, default=os.getenv("CDM_GOOGLE_SHEET_ID"), help="The Google Sheet ID that should be converted into a LinkML sheet.", @@ -56,7 +56,14 @@ default=True, help="Controls whether we use the CCDH Terminology Service to add enumerated values for attributes.", ) -def main(google_sheet_id, output, filter_entity, logging_config, write_mappings, include_terminologies): +def main( + google_sheet_id, + output, + filter_entity, + logging_config, + write_mappings, + include_terminologies, +): # Display INFO log entry and up. if os.path.exists(logging_config): logging.config.fileConfig(logging_config) @@ -76,7 +83,9 @@ def main(google_sheet_id, output, filter_entity, logging_config, write_mappings, exit(1) google_sheet_id = os.getenv("CDM_GOOGLE_SHEET_ID") if not google_sheet_id: - logging.error("A Google Sheet ID is required; please set environmental variable 'CDM_GOOGLE_SHEET_ID' to a Google Sheet ID.") + logging.error( + "A Google Sheet ID is required; please set environmental variable 'CDM_GOOGLE_SHEET_ID' to a Google Sheet ID." + ) exit(1) # Arbitrarily set a CRDC-H root URI. @@ -140,5 +149,6 @@ def main(google_sheet_id, output, filter_entity, logging_config, write_mappings, exit(0) + if __name__ == "__main__": main() diff --git a/sheet2linkml/source/gsheetmodel/entity.py b/sheet2linkml/source/gsheetmodel/entity.py index 76a1de5..0cc3ec6 100644 --- a/sheet2linkml/source/gsheetmodel/entity.py +++ b/sheet2linkml/source/gsheetmodel/entity.py @@ -368,7 +368,9 @@ def as_linkml_enum(self) -> EnumDefinition: return None # Look up enumerations on the Terminology Service. - enum_info = self.terminology_service.get_enum_values_for_field('CRDC-H', self.entity.name, self.name) + enum_info = self.terminology_service.get_enum_values_for_field( + "CRDC-H", self.entity.name, self.name + ) permissible_values = {} for pv in enum_info.get("permissible_values", []): text = pv.get("text") diff --git a/tests/test_command_line.py b/tests/test_command_line.py index 82f41c0..c9aa713 100644 --- a/tests/test_command_line.py +++ b/tests/test_command_line.py @@ -6,6 +6,7 @@ import logging import os + def execute_sheet2linkml(args) -> (int, str, str): """ Execute sheet2linkml as a command-line tool with the provided arguments. @@ -14,7 +15,9 @@ def execute_sheet2linkml(args) -> (int, str, str): :return: A tuple containing the error code, captured STDOUT and captured STDERR respectively """ - result = subprocess.run(['sheet2linkml'] + args, capture_output=True, encoding='utf-8') + result = subprocess.run( + ["sheet2linkml"] + args, capture_output=True, encoding="utf-8" + ) return result.returncode, result.stdout, result.stderr @@ -28,13 +31,13 @@ def test_help(self): """ Test whether sheet2linkml accepts `--help` and provides useful information. """ - (errno, stdout, stderr) = execute_sheet2linkml(['--help']) + (errno, stdout, stderr) = execute_sheet2linkml(["--help"]) assert errno == 0 - assert 'Usage: sheet2linkml' in stdout - assert '--help' in stdout - assert 'Show this message and exit.' in stdout - assert 'ERROR' not in stderr + assert "Usage: sheet2linkml" in stdout + assert "--help" in stdout + assert "Show this message and exit." in stdout + assert "ERROR" not in stderr def test_execution(self, tmp_path): """ @@ -42,20 +45,33 @@ def test_execution(self, tmp_path): https://docs.google.com/spreadsheets/d/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I/edit?usp=sharing """ - output_path = os.path.join(tmp_path, 'schema.yaml') + output_path = os.path.join(tmp_path, "schema.yaml") print(f"Writing execution test output to '{output_path}'") - (errno, stdout, stderr) = execute_sheet2linkml([ - '--google-sheet-id', '1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I', - '-o', output_path - ]) - - assert 'INFO: Google Sheet loaded: GSheetModel with an underlying Google Sheet titled "Test schema for sheet2linkml" containing 8 worksheets' in stderr - assert 'INFO: Generating LinkML for GSheetModel with an underlying Google Sheet titled "Test schema for sheet2linkml" containing 8 worksheets' in stderr - assert 'INFO: Generating LinkML for Enum named Subject.breed from worksheet "O_CCDH Enums" containing 8 values' in stderr - - assert stdout == '' + (errno, stdout, stderr) = execute_sheet2linkml( + [ + "--google-sheet-id", + "1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I", + "-o", + output_path, + ] + ) + + assert ( + 'INFO: Google Sheet loaded: GSheetModel with an underlying Google Sheet titled "Test schema for sheet2linkml" containing 8 worksheets' + in stderr + ) + assert ( + 'INFO: Generating LinkML for GSheetModel with an underlying Google Sheet titled "Test schema for sheet2linkml" containing 8 worksheets' + in stderr + ) + assert ( + 'INFO: Generating LinkML for Enum named Subject.breed from worksheet "O_CCDH Enums" containing 8 values' + in stderr + ) + + assert stdout == "" assert errno == 0 assert os.path.exists(output_path) @@ -68,20 +84,26 @@ def make_schema_comparable(lines): output = "" for line in lines: - if line.startswith('generation_date:'): + if line.startswith("generation_date:"): continue - if re.match('^\\s*code_set_version: ', line): + if re.match("^\\s*code_set_version: ", line): continue output += line return output dirname = os.path.dirname(__file__) - with open(os.path.join(dirname, 'testing-schema-on-gsheet/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I.yaml'), 'r') as f: + with open( + os.path.join( + dirname, + "testing-schema-on-gsheet/1HpsF12vl_CeIzV2TEtANeysnh7cy6YOUDdv6fMXT00I.yaml", + ), + "r", + ) as f: expected_schema = make_schema_comparable(f.readlines()) - with open(output_path, 'r') as f: + with open(output_path, "r") as f: obtained_schema = make_schema_comparable(f.readlines()) - assert obtained_schema != '' + assert obtained_schema != "" assert obtained_schema == expected_schema From f0bedd5f41f80dcf081d3bad1f90cf2a93e345eb Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Thu, 2 Dec 2021 23:29:28 -0500 Subject: [PATCH 17/43] Add support for a 404 response from the TCCM Terminology Service. --- sheet2linkml/terminologies/tccm/api.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sheet2linkml/terminologies/tccm/api.py b/sheet2linkml/terminologies/tccm/api.py index 2086cee..337a208 100644 --- a/sheet2linkml/terminologies/tccm/api.py +++ b/sheet2linkml/terminologies/tccm/api.py @@ -40,7 +40,10 @@ def get_enum_values_for_field(self, model: str, entity: str, attribute: str): response = requests.get( url, headers={"accept": "application/x-yaml"}, params={"value_only": "true"} ) - if not response.ok: + if response.status_code == 404: + logging.debug(f"Field not found on TCCM Terminology Service ({field_name}): {response}") + return {} + elif not response.ok: logging.debug(f"Error accessing TCCM Terminology Service: {response}") return {} From 8ae8e25076bfe0bc82333ac705a9e1de4874a81a Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Fri, 3 Dec 2021 10:08:31 -0500 Subject: [PATCH 18/43] Fixed code syntax using black. --- sheet2linkml/terminologies/tccm/api.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sheet2linkml/terminologies/tccm/api.py b/sheet2linkml/terminologies/tccm/api.py index 337a208..d8e23aa 100644 --- a/sheet2linkml/terminologies/tccm/api.py +++ b/sheet2linkml/terminologies/tccm/api.py @@ -41,7 +41,9 @@ def get_enum_values_for_field(self, model: str, entity: str, attribute: str): url, headers={"accept": "application/x-yaml"}, params={"value_only": "true"} ) if response.status_code == 404: - logging.debug(f"Field not found on TCCM Terminology Service ({field_name}): {response}") + logging.debug( + f"Field not found on TCCM Terminology Service ({field_name}): {response}" + ) return {} elif not response.ok: logging.debug(f"Error accessing TCCM Terminology Service: {response}") From 26d64ffb33d28ac792ad75e77350f8bf45785db5 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Sat, 4 Dec 2021 21:08:57 -0500 Subject: [PATCH 19/43] Updated CHANGELOG. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3958ae5..fe8361d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Releases](https://github.com/cancerDHC/sheet2linkml/releases) ## [Unreleased] +* Fixed bug: correctly handle 404 responses from the TCCM Terminology Service ## [v1.2.0] - 2021-11-29 From 6786b4390a9443924208d777907ac61bd7489111 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Thu, 9 Dec 2021 16:54:19 -0500 Subject: [PATCH 20/43] Clarified Poetry installation in GitHub Action. --- .github/workflows/main.yaml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 086b86f..afa992c 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -47,16 +47,9 @@ jobs: key: venv-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }} #---------------------------------------------- - # install dependencies if cache does not exist + # install dependencies #---------------------------------------------- - name: Install dependencies - if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true' - run: poetry install --no-interaction --no-root - - #---------------------------------------------- - # install your root project, if required - #---------------------------------------------- - - name: Install library run: poetry install --no-interaction #---------------------------------------------- From 5423320b4711b58a870f09d1a88b3772abbe8742 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Thu, 9 Dec 2021 16:56:14 -0500 Subject: [PATCH 21/43] Updated pytest.yaml to run pytest. --- .github/workflows/{main.yaml => pytest.yaml} | 6 ++++++ 1 file changed, 6 insertions(+) rename .github/workflows/{main.yaml => pytest.yaml} (90%) diff --git a/.github/workflows/main.yaml b/.github/workflows/pytest.yaml similarity index 90% rename from .github/workflows/main.yaml rename to .github/workflows/pytest.yaml index afa992c..3272a06 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/pytest.yaml @@ -52,6 +52,12 @@ jobs: - name: Install dependencies run: poetry install --no-interaction + #---------------------------------------------- + # install tests + #---------------------------------------------- + - name: Install dependencies + run: poetry run pytest + #---------------------------------------------- # check formatting #---------------------------------------------- From 20894c4b2b2d3021aaa2ff4334903583896a5064 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Thu, 9 Dec 2021 17:19:14 -0500 Subject: [PATCH 22/43] Added support for SHEET2LINKML_GOOGLE_SERVICE_ACCT. This environmental variable can be used to access file (see https://pygsheets.readthedocs.io/en/stable/authorization.html#service-account for details). --- sheet2linkml/cli.py | 40 ++++++++++++------- .../source/gsheetmodel/gsheetmodel.py | 6 +-- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/sheet2linkml/cli.py b/sheet2linkml/cli.py index 6d0c9c6..2e3864e 100644 --- a/sheet2linkml/cli.py +++ b/sheet2linkml/cli.py @@ -18,7 +18,7 @@ from linkml_runtime.dumpers import yaml_dumper from dotenv import load_dotenv - +import pygsheets @click.command() @click.option( @@ -72,27 +72,39 @@ def main( load_dotenv() # Read in Google API credentials. - google_api_credentials = os.getenv( - "GOOGLE_API_CREDENTIALS", "google_api_credentials.json" - ) - if not os.path.exists(google_api_credentials): - logging.error( - f"Google API Credential file '{google_api_credentials}' not found: please see " - + "https://github.com/cancerDHC/sheet2linkml#authorization for information on creating this file." + if 'SHEET2LINKML_GOOGLE_SERVICE_ACCT' in os.environ: + # If an environment variable SHEET2LINKML_GOOGLE_SERVICE_ACCT is set, use it as a + # Service Account (https://pygsheets.readthedocs.io/en/stable/authorization.html#service-account) + pygclient = pygsheets.authorize( + service_account_env_var='SHEET2LINKML_GOOGLE_SERVICE_ACCT', + scopes=GSheetModel.SCOPES ) - exit(1) - google_sheet_id = os.getenv("CDM_GOOGLE_SHEET_ID") + else: + # Otherwise, look for the path to Google API Credentials in google_api_credentials.json. + google_api_credentials = os.getenv( + "GOOGLE_API_CREDENTIALS", "google_api_credentials.json" + ) + if not os.path.exists(google_api_credentials): + logging.error( + f"Google API Credential file '{google_api_credentials}' not found: please see " + + "https://github.com/cancerDHC/sheet2linkml#authorization for information on creating this file." + ) + exit(1) + pygclient = pygsheets.authorize( + client_secret=google_api_credentials, scopes=GSheetModel.SCOPES + ) + + # Arbitrarily set a CRDC-H root URI. + crdch_root = "https://example.org/crdch" + if not google_sheet_id: logging.error( "A Google Sheet ID is required; please set environmental variable 'CDM_GOOGLE_SHEET_ID' to a Google Sheet ID." ) exit(1) - # 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) + model = GSheetModel(pygclient, google_sheet_id) if include_terminologies: model.use_terminology_service(TCCMService("https://terminology.ccdh.io")) logging.info(f"Google Sheet loaded: {model}") diff --git a/sheet2linkml/source/gsheetmodel/gsheetmodel.py b/sheet2linkml/source/gsheetmodel/gsheetmodel.py index 5f27a1b..6e839d4 100644 --- a/sheet2linkml/source/gsheetmodel/gsheetmodel.py +++ b/sheet2linkml/source/gsheetmodel/gsheetmodel.py @@ -34,7 +34,7 @@ class that generically represents a single, coherent model, and then make GSheet "https://www.googleapis.com/auth/drive.metadata.readonly", ] - def __init__(self, google_sheet_oath2_credentials: str, google_sheet_id: str): + def __init__(self, google_sheet_client, google_sheet_id: str): """ Create a new Google Sheet Model. This will create a model that uses the specified Google Sheet as an input. @@ -52,9 +52,7 @@ def __init__(self, google_sheet_oath2_credentials: str, google_sheet_id: str): :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.client = google_sheet_client 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. From f1a395fa195d921da728080bb3b6944761cf82f7 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Thu, 9 Dec 2021 17:24:25 -0500 Subject: [PATCH 23/43] Updated PyTest to use SHEET2LINKML_GOOGLE_SERVICE_ACCT. --- .github/workflows/pytest.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 3272a06..4f48327 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -56,6 +56,8 @@ jobs: # install tests #---------------------------------------------- - name: Install dependencies + env: + SHEET2LINKML_GOOGLE_SERVICE_ACCT: ${{ secrets.Sheet2LinkMLGoogleServiceAcct }} run: poetry run pytest #---------------------------------------------- From 0877d9130117833ec357fcb7e983bc1b29b6723d Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Thu, 9 Dec 2021 17:29:38 -0500 Subject: [PATCH 24/43] Renamed GitHub test and style check workflow. --- .github/workflows/pytest.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 4f48327..46ef4b5 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -1,7 +1,7 @@ # Built from: # https://docs.github.com/en/actions/guides/building-and-testing-python -name: black +name: Test and check code style on: [push, pull_request] From e6f6bb4d4eda2efbb721ece09e46bd453aea6d97 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Thu, 9 Dec 2021 17:30:04 -0500 Subject: [PATCH 25/43] Fixed code style with black. --- sheet2linkml/cli.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sheet2linkml/cli.py b/sheet2linkml/cli.py index 2e3864e..a10f101 100644 --- a/sheet2linkml/cli.py +++ b/sheet2linkml/cli.py @@ -20,6 +20,7 @@ from dotenv import load_dotenv import pygsheets + @click.command() @click.option( "--google-sheet-id", @@ -72,12 +73,12 @@ def main( load_dotenv() # Read in Google API credentials. - if 'SHEET2LINKML_GOOGLE_SERVICE_ACCT' in os.environ: + if "SHEET2LINKML_GOOGLE_SERVICE_ACCT" in os.environ: # If an environment variable SHEET2LINKML_GOOGLE_SERVICE_ACCT is set, use it as a # Service Account (https://pygsheets.readthedocs.io/en/stable/authorization.html#service-account) pygclient = pygsheets.authorize( - service_account_env_var='SHEET2LINKML_GOOGLE_SERVICE_ACCT', - scopes=GSheetModel.SCOPES + service_account_env_var="SHEET2LINKML_GOOGLE_SERVICE_ACCT", + scopes=GSheetModel.SCOPES, ) else: # Otherwise, look for the path to Google API Credentials in google_api_credentials.json. From 2870a01c29925035a5afe462033171fc6f977789 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Thu, 9 Dec 2021 17:30:53 -0500 Subject: [PATCH 26/43] Improved PyTest workflow file. --- .github/workflows/pytest.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 46ef4b5..8de0649 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -6,8 +6,7 @@ name: Test and check code style on: [push, pull_request] jobs: - black: - + test: runs-on: ubuntu-latest strategy: @@ -63,7 +62,7 @@ jobs: #---------------------------------------------- # check formatting #---------------------------------------------- - - name: Code formatting with black + - name: Code style with black run: | # run black in check mode # if files are not formatted correctly, the build will not go through From c59a7e529c12f0af41f809d6c06e0a5cd70024e1 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Thu, 9 Dec 2021 17:41:29 -0500 Subject: [PATCH 27/43] Improved GitHub Action testing workflow. --- .github/workflows/pytest.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 8de0649..48d1d54 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -39,11 +39,11 @@ jobs: # load cached venv if cache exists #---------------------------------------------- - name: Load cached venv - id: cached-poetry-dependencies + id: cache-poetry uses: actions/cache@v2 with: - path: .venv - key: venv-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }} + path: ~/.local + key: ${{ runner.os }}-python-${{ matrix.python-version }}-poetry-${{ hashFiles('**/poetry.lock') }} #---------------------------------------------- # install dependencies @@ -57,7 +57,7 @@ jobs: - name: Install dependencies env: SHEET2LINKML_GOOGLE_SERVICE_ACCT: ${{ secrets.Sheet2LinkMLGoogleServiceAcct }} - run: poetry run pytest + run: poetry run pytest -svvv #---------------------------------------------- # check formatting From 242303cff1ea2d99bb3263fd164d72405523f3a7 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Thu, 9 Dec 2021 17:45:25 -0500 Subject: [PATCH 28/43] Moved `black` to a developmental dependency. --- poetry.lock | 32 ++++++++++++++++---------------- pyproject.toml | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/poetry.lock b/poetry.lock index 8fb4f8a..85389f8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -32,7 +32,7 @@ tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (> name = "black" version = "21.12b0" description = "The uncompromising code formatter." -category = "main" +category = "dev" optional = false python-versions = ">=3.6.2" @@ -126,7 +126,7 @@ python-versions = ">=3.6" [[package]] name = "google-api-core" -version = "2.2.2" +version = "2.3.0" description = "Google API client core library" category = "main" optional = false @@ -145,7 +145,7 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2)"] [[package]] name = "google-api-python-client" -version = "2.32.0" +version = "2.33.0" description = "Google API Client Library for Python" category = "main" optional = false @@ -207,7 +207,7 @@ tool = ["click (>=6.0.0)"] [[package]] name = "googleapis-common-protos" -version = "1.53.0" +version = "1.54.0" description = "Common protobufs used in Google APIs" category = "main" optional = false @@ -391,7 +391,7 @@ source = ["Cython (>=0.29.7)"] name = "mypy-extensions" version = "0.4.3" description = "Experimental type system extensions for programs checked with the mypy typechecker." -category = "main" +category = "dev" optional = false python-versions = "*" @@ -423,7 +423,7 @@ pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" name = "pathspec" version = "0.9.0" description = "Utility library for gitignore style pattern matching of file paths." -category = "main" +category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" @@ -431,7 +431,7 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" name = "platformdirs" version = "2.4.0" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "main" +category = "dev" optional = false python-versions = ">=3.6" @@ -741,7 +741,7 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" name = "tomli" version = "1.2.2" description = "A lil' TOML parser" -category = "main" +category = "dev" optional = false python-versions = ">=3.6" @@ -749,7 +749,7 @@ python-versions = ">=3.6" name = "typed-ast" version = "1.5.1" description = "a fork of Python 2 and 3 ast modules with type comment support" -category = "main" +category = "dev" optional = false python-versions = ">=3.6" @@ -805,7 +805,7 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytes [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "635182b39afc44b38ccc38e14202c4d08e5672a6d679452f6fcd8aad8c2979c6" +content-hash = "8a00e373957ee1850c86fb5dc806ece485e90a52e96bad0edf2057b9d122af87" [metadata.files] antlr4-python3-runtime = [ @@ -852,12 +852,12 @@ frozendict = [ {file = "frozendict-2.1.1.tar.gz", hash = "sha256:655b879217dd445a2023e16154cc231febef802b5c812d5c2e822280ad69e1dc"}, ] google-api-core = [ - {file = "google-api-core-2.2.2.tar.gz", hash = "sha256:97349cc18c2bb2415f64f1353a80273a289a61294ce3eb2f7ce682d251bdd997"}, - {file = "google_api_core-2.2.2-py2.py3-none-any.whl", hash = "sha256:e7853735d4f51f4212d6bf9750620d76fc0106c0f271be0c3f43b73501c7ddf9"}, + {file = "google-api-core-2.3.0.tar.gz", hash = "sha256:538cd927bfe0f7c63bc1eb5fcadeeeb52f90bb29117dea87ae8cae48953d4c60"}, + {file = "google_api_core-2.3.0-py2.py3-none-any.whl", hash = "sha256:65fe1d9d8dde7a5ddc43d5cc134560c2a76b1a26c9f70c3c24f13b7910e89e10"}, ] google-api-python-client = [ - {file = "google-api-python-client-2.32.0.tar.gz", hash = "sha256:619fe50155e73342c17aba4bbb2a08be8ce6ae00b795af383de7d6616b485c94"}, - {file = "google_api_python_client-2.32.0-py2.py3-none-any.whl", hash = "sha256:1449c6941afabc32a274be54d17f262615e3a970114c386b62986e29618623f3"}, + {file = "google-api-python-client-2.33.0.tar.gz", hash = "sha256:38e98611794632a12479fafbabe0b5027e8fcfc412e8375f1b23db0bc0209181"}, + {file = "google_api_python_client-2.33.0-py2.py3-none-any.whl", hash = "sha256:1322d026110bc62eb29a4a25a15895dac51486b30a29b5943bc456318677280b"}, ] google-auth = [ {file = "google-auth-2.3.3.tar.gz", hash = "sha256:d83570a664c10b97a1dc6f8df87e5fdfff012f48f62be131e449c20dfc32630e"}, @@ -872,8 +872,8 @@ google-auth-oauthlib = [ {file = "google_auth_oauthlib-0.4.6-py2.py3-none-any.whl", hash = "sha256:3f2a6e802eebbb6fb736a370fbf3b055edcb6b52878bf2f26330b5e041316c73"}, ] googleapis-common-protos = [ - {file = "googleapis-common-protos-1.53.0.tar.gz", hash = "sha256:a88ee8903aa0a81f6c3cec2d5cf62d3c8aa67c06439b0496b49048fb1854ebf4"}, - {file = "googleapis_common_protos-1.53.0-py2.py3-none-any.whl", hash = "sha256:f6d561ab8fb16b30020b940e2dd01cd80082f4762fa9f3ee670f4419b4b8dbd0"}, + {file = "googleapis-common-protos-1.54.0.tar.gz", hash = "sha256:a4031d6ec6c2b1b6dc3e0be7e10a1bd72fb0b18b07ef9be7b51f2c1004ce2437"}, + {file = "googleapis_common_protos-1.54.0-py2.py3-none-any.whl", hash = "sha256:e54345a2add15dc5e1a7891c27731ff347b4c33765d79b5ed7026a6c0c7cbcae"}, ] hbreader = [ {file = "hbreader-0.9.1-py3-none-any.whl", hash = "sha256:9a6e76c9d1afc1b977374a5dc430a1ebb0ea0488205546d4678d6e31cc5f6801"}, diff --git a/pyproject.toml b/pyproject.toml index 9ca98ac..976e06d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,7 +38,7 @@ pygsheets = "^2.0.4" PyYAML = "^5.4.1" setuptools = "^52.0.0" python-dotenv = "^0.15.0" -black = "^21.9b0" [tool.poetry.dev-dependencies] pytest = "^6.2.5" +black = "^21.9b0" From df5bb02de866f82e75cc9e06b6f972d876d76fa8 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Thu, 9 Dec 2021 17:49:45 -0500 Subject: [PATCH 29/43] Attempt to fix PyTest workflow. --- .github/workflows/pytest.yaml | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 48d1d54..1f08e2b 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -27,24 +27,21 @@ jobs: python-version: ${{ matrix.python-version }} #---------------------------------------------- - # install & configure poetry - #---------------------------------------------- - - name: Install Poetry - uses: snok/install-poetry@v1.1.1 - with: - virtualenvs-create: true - virtualenvs-in-project: true - - #---------------------------------------------- - # load cached venv if cache exists + # Cache Poetry installation #---------------------------------------------- - - name: Load cached venv + - name: Cache Poetry files id: cache-poetry uses: actions/cache@v2 with: path: ~/.local key: ${{ runner.os }}-python-${{ matrix.python-version }}-poetry-${{ hashFiles('**/poetry.lock') }} + #---------------------------------------------- + # install & configure poetry + #---------------------------------------------- + - name: Install Poetry + uses: snok/install-poetry@v1 + #---------------------------------------------- # install dependencies #---------------------------------------------- From 7294901d4b2d347e6a0ffa75bac2250b42828c37 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Thu, 9 Dec 2021 17:52:39 -0500 Subject: [PATCH 30/43] Printed out stderr to debug GitHub Action workflow issue. --- tests/test_command_line.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_command_line.py b/tests/test_command_line.py index c9aa713..7bb6085 100644 --- a/tests/test_command_line.py +++ b/tests/test_command_line.py @@ -33,6 +33,8 @@ def test_help(self): """ (errno, stdout, stderr) = execute_sheet2linkml(["--help"]) + print(stderr) + assert errno == 0 assert "Usage: sheet2linkml" in stdout assert "--help" in stdout @@ -58,6 +60,7 @@ def test_execution(self, tmp_path): ] ) + print(stderr) assert ( 'INFO: Google Sheet loaded: GSheetModel with an underlying Google Sheet titled "Test schema for sheet2linkml" containing 8 worksheets' in stderr From 91f2c417a1c22325e2e30d7bdf4b6ecdf7f9b6d0 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Thu, 9 Dec 2021 18:04:00 -0500 Subject: [PATCH 31/43] Replaced @cached_property with @property @lru_cache. This is because @cached_property isn't supported in Python 3.7, blech. --- sheet2linkml/source/gsheetmodel/entity.py | 11 +++++++---- sheet2linkml/source/gsheetmodel/enum.py | 8 +++++--- sheet2linkml/source/gsheetmodel/gsheetmodel.py | 5 +++-- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/sheet2linkml/source/gsheetmodel/entity.py b/sheet2linkml/source/gsheetmodel/entity.py index 0cc3ec6..3c1ca61 100644 --- a/sheet2linkml/source/gsheetmodel/entity.py +++ b/sheet2linkml/source/gsheetmodel/entity.py @@ -3,7 +3,7 @@ import urllib.parse from typing import List, Dict -from functools import cached_property +from functools import lru_cache from sheet2linkml.terminologies.service import TerminologyService from sheet2linkml.model import ModelElement @@ -67,7 +67,8 @@ def attribute_rows(self) -> List[Dict[str, str]]: if row.get(EntityWorksheet.COL_ATTRIBUTE_NAME) is not None ] - @cached_property + @property + @lru_cache def attributes(self): """ Returns a list of attributes in this entity. We construct this by wrapping the @@ -157,7 +158,8 @@ def to_markdown(self) -> str: return f"[{self.name} in sheet {self.worksheet.title}]({self.worksheet.url})" - @cached_property + @property + @lru_cache def mappings(self) -> Mappings: """ Returns the list of mappings for this entity. @@ -309,7 +311,8 @@ def counts(self) -> (int, int): return min_count, max_count - @cached_property + @property + @lru_cache def mappings(self) -> Mappings: """ Returns the list of mappings for this attribute. diff --git a/sheet2linkml/source/gsheetmodel/enum.py b/sheet2linkml/source/gsheetmodel/enum.py index 7995635..b5f771c 100644 --- a/sheet2linkml/source/gsheetmodel/enum.py +++ b/sheet2linkml/source/gsheetmodel/enum.py @@ -2,7 +2,7 @@ import re from typing import List, Dict -from functools import cached_property +from functools import lru_cache from linkml_runtime.linkml_model.meta import ( SchemaDefinition, @@ -151,7 +151,8 @@ def to_markdown(self) -> str: return f"[{self.name} in sheet {self.worksheet.title}]({self.worksheet.url})" - @cached_property + @property + @lru_cache def mappings(self) -> Mappings: """ Returns the list of mappings for this enum. @@ -264,7 +265,8 @@ def __str__(self): return f'{self.__class__.__name__} named "{self.name}" containing {len(self.row)} properties' - @cached_property + @property + @lru_cache def mappings(self) -> Mappings: """ Returns the list of mappings for this enum value. diff --git a/sheet2linkml/source/gsheetmodel/gsheetmodel.py b/sheet2linkml/source/gsheetmodel/gsheetmodel.py index 6e839d4..0c89db4 100644 --- a/sheet2linkml/source/gsheetmodel/gsheetmodel.py +++ b/sheet2linkml/source/gsheetmodel/gsheetmodel.py @@ -2,7 +2,7 @@ import logging from typing import List, Dict -from functools import cached_property, lru_cache +from functools import lru_cache from datetime import datetime, timezone import pygsheets @@ -185,7 +185,8 @@ def enums_from_worksheets(self) -> List[Enum]: result.extend(worksheet.enums) return result - @cached_property + @property + @lru_cache def mappings(self) -> List[Mappings.Mapping]: """Return a list of all the mappings in this LinkML document.""" mappings = [ From 95d9e6e16783aac66e3f9c63565559c6818e934e Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Thu, 9 Dec 2021 18:12:41 -0500 Subject: [PATCH 32/43] Updated CHANGELOG. --- CHANGELOG.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe8361d..1ec3290 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Releases](https://github.com/cancerDHC/sheet2linkml/releases) ## [Unreleased] -* Fixed bug: correctly handle 404 responses from the TCCM Terminology Service +* Feature: added a dummy Google Sheet, the expected schema, and a test to compare them. +* Feature: cleaned up GitHub Action for style checks and added PyTest. +* Feature: added support for storing Google API credentials in an environmental variable, and added it to + GitHub Actions. +* Feature: added check for Google Sheet ID. +* Feature: updated @cached_property with @property @lru_cache to support Python 3.7. +* Bug: updated CCDH Terminology API endpoint for enumerations. +* Bug: fixed code to correctly handle 404 responses from the TCCM Terminology Service. ## [v1.2.0] - 2021-11-29 From 553d2106e41d6487bd2e9e75a72edbcc143776df Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Thu, 9 Dec 2021 18:12:49 -0500 Subject: [PATCH 33/43] Added explicit maxsize to @lru_cache. --- sheet2linkml/source/gsheetmodel/entity.py | 6 +++--- sheet2linkml/source/gsheetmodel/enum.py | 4 ++-- sheet2linkml/source/gsheetmodel/gsheetmodel.py | 8 +++++--- sheet2linkml/terminologies/tccm/api.py | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/sheet2linkml/source/gsheetmodel/entity.py b/sheet2linkml/source/gsheetmodel/entity.py index 3c1ca61..0835a9a 100644 --- a/sheet2linkml/source/gsheetmodel/entity.py +++ b/sheet2linkml/source/gsheetmodel/entity.py @@ -68,7 +68,7 @@ def attribute_rows(self) -> List[Dict[str, str]]: ] @property - @lru_cache + @lru_cache(128) def attributes(self): """ Returns a list of attributes in this entity. We construct this by wrapping the @@ -159,7 +159,7 @@ def to_markdown(self) -> str: return f"[{self.name} in sheet {self.worksheet.title}]({self.worksheet.url})" @property - @lru_cache + @lru_cache(128) def mappings(self) -> Mappings: """ Returns the list of mappings for this entity. @@ -312,7 +312,7 @@ def counts(self) -> (int, int): return min_count, max_count @property - @lru_cache + @lru_cache(128) def mappings(self) -> Mappings: """ Returns the list of mappings for this attribute. diff --git a/sheet2linkml/source/gsheetmodel/enum.py b/sheet2linkml/source/gsheetmodel/enum.py index b5f771c..c417b9a 100644 --- a/sheet2linkml/source/gsheetmodel/enum.py +++ b/sheet2linkml/source/gsheetmodel/enum.py @@ -152,7 +152,7 @@ def to_markdown(self) -> str: return f"[{self.name} in sheet {self.worksheet.title}]({self.worksheet.url})" @property - @lru_cache + @lru_cache(128) def mappings(self) -> Mappings: """ Returns the list of mappings for this enum. @@ -266,7 +266,7 @@ def __str__(self): return f'{self.__class__.__name__} named "{self.name}" containing {len(self.row)} properties' @property - @lru_cache + @lru_cache(128) def mappings(self) -> Mappings: """ Returns the list of mappings for this enum value. diff --git a/sheet2linkml/source/gsheetmodel/gsheetmodel.py b/sheet2linkml/source/gsheetmodel/gsheetmodel.py index 0c89db4..a05bdca 100644 --- a/sheet2linkml/source/gsheetmodel/gsheetmodel.py +++ b/sheet2linkml/source/gsheetmodel/gsheetmodel.py @@ -101,7 +101,8 @@ def is_sheet_normative(worksheet: pygsheets.worksheet): return result # Decorator that can save time when associated operation is periodically called with the same arguments. - @lru_cache + @property + @lru_cache(128) def entity_worksheets(self) -> List[EntityWorksheet]: """ A list of worksheets available in this model. @@ -138,7 +139,8 @@ def entity_worksheets(self) -> List[EntityWorksheet]: for worksheet in entity_worksheets ] - @lru_cache + @property + @lru_cache(128) def entities(self) -> List[Entity]: """ :return: The list of entities in this model. @@ -186,7 +188,7 @@ def enums_from_worksheets(self) -> List[Enum]: return result @property - @lru_cache + @lru_cache(128) def mappings(self) -> List[Mappings.Mapping]: """Return a list of all the mappings in this LinkML document.""" mappings = [ diff --git a/sheet2linkml/terminologies/tccm/api.py b/sheet2linkml/terminologies/tccm/api.py index d8e23aa..659fa87 100644 --- a/sheet2linkml/terminologies/tccm/api.py +++ b/sheet2linkml/terminologies/tccm/api.py @@ -21,7 +21,7 @@ def __init__(self, base_url: str): # Decorator that can save time when associated operation is periodically called with the same arguments. # This is unlikely to change during a run and is quite expensive (since we download it from the network), so # we memoize it. - @lru_cache + @lru_cache(256) def get_enum_values_for_field(self, model: str, entity: str, attribute: str): """ Returns information on the enum fields for a particular field. From 99143275a3fdac043ee64eb034048c3fb8d4a639 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Thu, 9 Dec 2021 18:16:31 -0500 Subject: [PATCH 34/43] Removed unnecessary @lru_cache annotations. --- sheet2linkml/source/gsheetmodel/entity.py | 3 --- sheet2linkml/source/gsheetmodel/enum.py | 2 -- sheet2linkml/source/gsheetmodel/gsheetmodel.py | 3 --- 3 files changed, 8 deletions(-) diff --git a/sheet2linkml/source/gsheetmodel/entity.py b/sheet2linkml/source/gsheetmodel/entity.py index 0835a9a..902c502 100644 --- a/sheet2linkml/source/gsheetmodel/entity.py +++ b/sheet2linkml/source/gsheetmodel/entity.py @@ -68,7 +68,6 @@ def attribute_rows(self) -> List[Dict[str, str]]: ] @property - @lru_cache(128) def attributes(self): """ Returns a list of attributes in this entity. We construct this by wrapping the @@ -159,7 +158,6 @@ def to_markdown(self) -> str: return f"[{self.name} in sheet {self.worksheet.title}]({self.worksheet.url})" @property - @lru_cache(128) def mappings(self) -> Mappings: """ Returns the list of mappings for this entity. @@ -312,7 +310,6 @@ def counts(self) -> (int, int): return min_count, max_count @property - @lru_cache(128) def mappings(self) -> Mappings: """ Returns the list of mappings for this attribute. diff --git a/sheet2linkml/source/gsheetmodel/enum.py b/sheet2linkml/source/gsheetmodel/enum.py index c417b9a..a83056a 100644 --- a/sheet2linkml/source/gsheetmodel/enum.py +++ b/sheet2linkml/source/gsheetmodel/enum.py @@ -152,7 +152,6 @@ def to_markdown(self) -> str: return f"[{self.name} in sheet {self.worksheet.title}]({self.worksheet.url})" @property - @lru_cache(128) def mappings(self) -> Mappings: """ Returns the list of mappings for this enum. @@ -266,7 +265,6 @@ def __str__(self): return f'{self.__class__.__name__} named "{self.name}" containing {len(self.row)} properties' @property - @lru_cache(128) def mappings(self) -> Mappings: """ Returns the list of mappings for this enum value. diff --git a/sheet2linkml/source/gsheetmodel/gsheetmodel.py b/sheet2linkml/source/gsheetmodel/gsheetmodel.py index a05bdca..a65de14 100644 --- a/sheet2linkml/source/gsheetmodel/gsheetmodel.py +++ b/sheet2linkml/source/gsheetmodel/gsheetmodel.py @@ -102,7 +102,6 @@ def is_sheet_normative(worksheet: pygsheets.worksheet): # Decorator that can save time when associated operation is periodically called with the same arguments. @property - @lru_cache(128) def entity_worksheets(self) -> List[EntityWorksheet]: """ A list of worksheets available in this model. @@ -140,7 +139,6 @@ def entity_worksheets(self) -> List[EntityWorksheet]: ] @property - @lru_cache(128) def entities(self) -> List[Entity]: """ :return: The list of entities in this model. @@ -188,7 +186,6 @@ def enums_from_worksheets(self) -> List[Enum]: return result @property - @lru_cache(128) def mappings(self) -> List[Mappings.Mapping]: """Return a list of all the mappings in this LinkML document.""" mappings = [ From 5f504286fc207ba1c95a0c042e7d1d25cc92ed10 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Thu, 9 Dec 2021 18:18:58 -0500 Subject: [PATCH 35/43] Removed unexpected @property annotation. --- sheet2linkml/source/gsheetmodel/gsheetmodel.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/sheet2linkml/source/gsheetmodel/gsheetmodel.py b/sheet2linkml/source/gsheetmodel/gsheetmodel.py index a65de14..feb4d23 100644 --- a/sheet2linkml/source/gsheetmodel/gsheetmodel.py +++ b/sheet2linkml/source/gsheetmodel/gsheetmodel.py @@ -100,8 +100,6 @@ def is_sheet_normative(worksheet: pygsheets.worksheet): return result - # Decorator that can save time when associated operation is periodically called with the same arguments. - @property def entity_worksheets(self) -> List[EntityWorksheet]: """ A list of worksheets available in this model. From 6ba77e651379d896e4ff59dfaa9e92170ae62e76 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Thu, 9 Dec 2021 18:23:37 -0500 Subject: [PATCH 36/43] Recorded change in CHANGELOG. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ec3290..733b3fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Feature: updated @cached_property with @property @lru_cache to support Python 3.7. * Bug: updated CCDH Terminology API endpoint for enumerations. * Bug: fixed code to correctly handle 404 responses from the TCCM Terminology Service. +* Bug: replaced unnecessary print() in GSheetModel with logging.error(). ## [v1.2.0] - 2021-11-29 From b1a98938306333a0f4d74b8f7cb51f536315f750 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Thu, 9 Dec 2021 18:23:48 -0500 Subject: [PATCH 37/43] Removed incorrect @property. --- sheet2linkml/source/gsheetmodel/gsheetmodel.py | 1 - 1 file changed, 1 deletion(-) diff --git a/sheet2linkml/source/gsheetmodel/gsheetmodel.py b/sheet2linkml/source/gsheetmodel/gsheetmodel.py index feb4d23..eca952e 100644 --- a/sheet2linkml/source/gsheetmodel/gsheetmodel.py +++ b/sheet2linkml/source/gsheetmodel/gsheetmodel.py @@ -136,7 +136,6 @@ def entity_worksheets(self) -> List[EntityWorksheet]: for worksheet in entity_worksheets ] - @property def entities(self) -> List[Entity]: """ :return: The list of entities in this model. From d34b6e9368e822531b384f88b82e72cd9c88f710 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Fri, 10 Dec 2021 00:29:32 -0500 Subject: [PATCH 38/43] Fixed some descriptions in pytest.yaml. --- .github/workflows/pytest.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 1f08e2b..df62bc7 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -16,7 +16,7 @@ jobs: steps: #---------------------------------------------- - # check-out repo and set-up python + # check-out repo and set-up python #---------------------------------------------- - name: Check out repository uses: actions/checkout@v2 @@ -27,7 +27,7 @@ jobs: python-version: ${{ matrix.python-version }} #---------------------------------------------- - # Cache Poetry installation + # cache poetry installation #---------------------------------------------- - name: Cache Poetry files id: cache-poetry @@ -37,7 +37,7 @@ jobs: key: ${{ runner.os }}-python-${{ matrix.python-version }}-poetry-${{ hashFiles('**/poetry.lock') }} #---------------------------------------------- - # install & configure poetry + # install & configure poetry #---------------------------------------------- - name: Install Poetry uses: snok/install-poetry@v1 @@ -49,15 +49,15 @@ jobs: run: poetry install --no-interaction #---------------------------------------------- - # install tests + # run tests #---------------------------------------------- - - name: Install dependencies + - name: Run tests env: SHEET2LINKML_GOOGLE_SERVICE_ACCT: ${{ secrets.Sheet2LinkMLGoogleServiceAcct }} run: poetry run pytest -svvv #---------------------------------------------- - # check formatting + # check formatting #---------------------------------------------- - name: Code style with black run: | From c6f6e30e51a84832caf74f5ac53b5d0090e15a74 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Fri, 10 Dec 2021 00:37:32 -0500 Subject: [PATCH 39/43] Added logging.basicConfig() in case of a missing logging config. --- sheet2linkml/cli.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sheet2linkml/cli.py b/sheet2linkml/cli.py index a10f101..0bc738e 100644 --- a/sheet2linkml/cli.py +++ b/sheet2linkml/cli.py @@ -68,6 +68,8 @@ def main( # Display INFO log entry and up. if os.path.exists(logging_config): logging.config.fileConfig(logging_config) + else: + logging.basicConfig(level=logging.INFO) # Load environemental variables from `.env` if one is present. load_dotenv() From 8ebf86e6db5de39a97f59651be8de0fdce876e46 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Fri, 10 Dec 2021 00:45:14 -0500 Subject: [PATCH 40/43] Replaced exit() with sys.exit(). See https://docs.python.org/3/library/constants.html#exit for recommendation. --- sheet2linkml/cli.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sheet2linkml/cli.py b/sheet2linkml/cli.py index 0bc738e..6dbb735 100644 --- a/sheet2linkml/cli.py +++ b/sheet2linkml/cli.py @@ -92,7 +92,7 @@ def main( f"Google API Credential file '{google_api_credentials}' not found: please see " + "https://github.com/cancerDHC/sheet2linkml#authorization for information on creating this file." ) - exit(1) + sys.exit(1) pygclient = pygsheets.authorize( client_secret=google_api_credentials, scopes=GSheetModel.SCOPES ) @@ -104,7 +104,7 @@ def main( logging.error( "A Google Sheet ID is required; please set environmental variable 'CDM_GOOGLE_SHEET_ID' to a Google Sheet ID." ) - exit(1) + sys.exit(1) # Load the Google Sheet model and add the development version number. model = GSheetModel(pygclient, google_sheet_id) @@ -141,7 +141,7 @@ def main( ) for entity in model.entities(): logging.error(f" - {entity.name}") - exit(1) + sys.exit(1) mappings = list() @@ -162,7 +162,7 @@ def main( if write_mappings: Mappings.write_to_file(model.mappings, filename=write_mappings, model=model) - exit(0) + sys.exit(0) if __name__ == "__main__": From dd03185f76af9f4bbef9d4ff2e16eb76572101bd Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Fri, 10 Dec 2021 00:47:44 -0500 Subject: [PATCH 41/43] Improved logging. --- sheet2linkml/cli.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sheet2linkml/cli.py b/sheet2linkml/cli.py index 6dbb735..79c8117 100644 --- a/sheet2linkml/cli.py +++ b/sheet2linkml/cli.py @@ -78,6 +78,7 @@ def main( if "SHEET2LINKML_GOOGLE_SERVICE_ACCT" in os.environ: # If an environment variable SHEET2LINKML_GOOGLE_SERVICE_ACCT is set, use it as a # Service Account (https://pygsheets.readthedocs.io/en/stable/authorization.html#service-account) + logging.info('Using Google Sheet API credentials from service account environment variable.') pygclient = pygsheets.authorize( service_account_env_var="SHEET2LINKML_GOOGLE_SERVICE_ACCT", scopes=GSheetModel.SCOPES, @@ -93,6 +94,7 @@ def main( + "https://github.com/cancerDHC/sheet2linkml#authorization for information on creating this file." ) sys.exit(1) + logging.info('Using Google Sheet API credentials from credentials file.') pygclient = pygsheets.authorize( client_secret=google_api_credentials, scopes=GSheetModel.SCOPES ) From 162028e0cfdd99d9c6e356dbc818f4a00db8c1f7 Mon Sep 17 00:00:00 2001 From: Gaurav Vaidya Date: Fri, 10 Dec 2021 01:01:20 -0500 Subject: [PATCH 42/43] Reformatted code using black. --- sheet2linkml/cli.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sheet2linkml/cli.py b/sheet2linkml/cli.py index 79c8117..b7da525 100644 --- a/sheet2linkml/cli.py +++ b/sheet2linkml/cli.py @@ -78,7 +78,9 @@ def main( if "SHEET2LINKML_GOOGLE_SERVICE_ACCT" in os.environ: # If an environment variable SHEET2LINKML_GOOGLE_SERVICE_ACCT is set, use it as a # Service Account (https://pygsheets.readthedocs.io/en/stable/authorization.html#service-account) - logging.info('Using Google Sheet API credentials from service account environment variable.') + logging.info( + "Using Google Sheet API credentials from service account environment variable." + ) pygclient = pygsheets.authorize( service_account_env_var="SHEET2LINKML_GOOGLE_SERVICE_ACCT", scopes=GSheetModel.SCOPES, @@ -94,7 +96,7 @@ def main( + "https://github.com/cancerDHC/sheet2linkml#authorization for information on creating this file." ) sys.exit(1) - logging.info('Using Google Sheet API credentials from credentials file.') + logging.info("Using Google Sheet API credentials from credentials file.") pygclient = pygsheets.authorize( client_secret=google_api_credentials, scopes=GSheetModel.SCOPES ) From 96f0c2b2e26a3f465ed30fe6244eee39d6559460 Mon Sep 17 00:00:00 2001 From: Sujay Patil Date: Fri, 10 Dec 2021 15:10:31 -0800 Subject: [PATCH 43/43] pre release changes for v1.3.0 --- CHANGELOG.md | 3 +++ CONTRIBUTING.md | 8 +++++++- pyproject.toml | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 733b3fe..2cd7916 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Releases](https://github.com/cancerDHC/sheet2linkml/releases) ## [Unreleased] +* Bugs or Features yet to be resolved. + +## [v1.3.0] * Feature: added a dummy Google Sheet, the expected schema, and a test to compare them. * Feature: cleaned up GitHub Action for style checks and added PyTest. * Feature: added support for storing Google API credentials in an environmental variable, and added it to diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6afb96b..182d6d1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -68,7 +68,12 @@ git checkout -b release-1.2 develop # Switched to a new branch "release-1.2" # minor bug fixes and preparing metadata for a release # e.g., version number, build dates # commit changes +``` + +Update the version number of the release in [CHANGELOG.md](CHANGELOG.md) and document some of the new changes that will be +part of the release. +``` # merge changes into "main" git checkout main # switched to branch "main" git merge --no-ff release-1.2 # merge into "main" with summary of changes @@ -85,7 +90,8 @@ Once the code has been merged into the `main` branch on this repo, there are two to ensure a release is complete. - You should create a GitHub tag, with the appropriate version number. -- You should push the package to PyPI. +- You should push the package to PyPI. Before pushing the package to PyPI make sure you have updated the version number in the +[pyproject.toml](pyproject.toml) file so that it matches the version number of the release you described in the CHANGELOG. ### Release to Test PyPI _(optional)_ The purpose of this section is to verify that the package looks and works as intended, by viewing it on Test PyPI and diff --git a/pyproject.toml b/pyproject.toml index 976e06d..ce1ee2e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "sheet2linkml" -version = "1.2.0" +version = "1.3.0" description = "Google Sheets to LinkML generator for the CRDC-H model" authors = [ "Gaurav Vaidya "