diff --git a/README.md b/README.md index 633aa8e..60b541f 100644 --- a/README.md +++ b/README.md @@ -38,12 +38,16 @@ def square(base: int, pow: int) -> int: print(generate_docstring_template(square, output_file=None)) ``` +## OpenAI Dependency: + +`fml_doc_gen` requires an OpenAI API key to generate docstrings. You can set your API key using the `OPENAI_API_KEY` environment variable. Check our our documentation [here](https://readthedocs.org/projects/fml-doc-gen/badge/?version=latest) for more information. + ## Functions Included - **`generate_docstring_template(func: Callable, output_file: str, auto_generate: bool = False) -> str`**: The main end-user function that generates either a docstring template with placeholders or a fully detailed docstring if `auto_generate` is set to `True`. -- **`read_user_function(func: Callable) -> str`**: +- **`read_user_function(func: Callable) -> FunctionDTO`**: Reads and extracts the signature and existing docstring (if any) of a given user-defined function. - **`generate_template(func_signature: str) -> str`**: @@ -62,6 +66,14 @@ If you are aware of a similar tool, feel free to contribute to our documentation Found a bug? or have an idea on how to improve `fml_doc_gen` further? Feel free to open an issue with the appropriate label (bug or features) under the issue section [here](https://github.com/UBC-MDS/fml_doc_gen/issues). +## Running Tests + +To run tests and check code coverage, use the following command in the project root: + +```bash +poetry run pytest --cov=fml_doc_gen --cov-report=term-missing tests/ +``` + ## Contributing Interested in contributing? Check out the contributing guidelines. Please note that this project is released with a Code of Conduct. By contributing to this project, you agree to abide by its terms. diff --git a/docs/doc.txt b/docs/doc.txt index be5c25a..036c4e4 100644 --- a/docs/doc.txt +++ b/docs/doc.txt @@ -5,11 +5,11 @@ Parameters: ---------- - base: int + base: ### INSERT PARAMETER DEFINITION HERE ### - pow: int + pow: ### INSERT PARAMETER DEFINITION HERE ### @@ -17,7 +17,7 @@ Returns: ------- - int + ### INSERT ADDITIONAL FUNCTION OUTPUT INFORMATION HERE ### diff --git a/docs/example.ipynb b/docs/example.ipynb index ef69530..9e7ee6f 100644 --- a/docs/example.ipynb +++ b/docs/example.ipynb @@ -16,7 +16,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -41,14 +41,14 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "0.0.1\n" + "3.0.4\n" ] } ], @@ -68,7 +68,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -82,11 +82,11 @@ " Parameters:\n", " ----------\n", " \n", - " base: int\n", + " base: \n", " ### INSERT PARAMETER DEFINITION HERE ###\n", " \n", "\n", - " pow: int\n", + " pow: \n", " ### INSERT PARAMETER DEFINITION HERE ###\n", " \n", "\n", @@ -94,7 +94,7 @@ " \n", " Returns:\n", " -------\n", - " int\n", + " \n", " ### INSERT ADDITIONAL FUNCTION OUTPUT INFORMATION HERE ###\n", "\n", " \n", @@ -168,7 +168,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -182,11 +182,11 @@ " Parameters:\n", " ----------\n", " \n", - " base: int\n", + " base: \n", " ### INSERT PARAMETER DEFINITION HERE ###\n", " \n", "\n", - " pow: int\n", + " pow: \n", " ### INSERT PARAMETER DEFINITION HERE ###\n", " \n", "\n", @@ -194,7 +194,7 @@ " \n", " Returns:\n", " -------\n", - " int\n", + " \n", " ### INSERT ADDITIONAL FUNCTION OUTPUT INFORMATION HERE ###\n", "\n", " \n", @@ -233,30 +233,97 @@ " Unsure about writing documentation? We’ve got you covered! \n", " \n", "\n", - "Simply pass the `auto_generate` parameter to our function, and we’ll create the documentation for you automatically.\n", + "Follow the steps below to setup openAI.\n", + "\n", + "Then Simply pass the `auto_generate` parameter to our function, and we’ll create the documentation for you automatically.\n", "\n", "\n", - " Note: This feature is currently under development and will be available soon. Stay tuned!\n", + " Note: This feature is currently still under development and may have issues!\n", "\n", "\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Step 1: Create an OpenAI Account** \n", + "\n", + "- Sign up for an OpenAI account if you haven’t already. You can do this here: \n", + "🔗 [OpenAI Sign Up](https://platform.openai.com/signup/)\n", + "\n", + "**Step 2: Obtain Your API Key** \n", + "1. Log in to your OpenAI account. \n", + "2. Navigate to the **API Keys** section. \n", + "3. Generate a new API key. \n", + "4. Copy the key and store it securely. \n", + "\n", + "**Step 3: Store the API Key in a `.env` File** \n", + "1. In your project root directory, create a `.env` file if it doesn’t already exist. \n", + "2. Open the `.env` file and add the following line: \n", + " ```env\n", + " OPENAI_API_KEY=your-api-key-here\n", + " ```\n" + ] + }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 5, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CALL OPEN AI API HERE\n" - ] - } - ], + "outputs": [], "source": [ - "documentation = generate_docstring_template(square, output_file=None, auto_generate=True)\n", - "print(documentation)" + "documentation = generate_docstring_template(square, output_file=None, auto_generate=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```python\n", + "def square(base: int, pow: int) -> int:\n", + " \"\"\"\n", + " Square: \n", + " This function returns the base raised to an integer power.\n", + "\n", + " Parameters:\n", + " ----------\n", + "\n", + " base: \n", + " The base number that would be raised to a certain power. This should be an integer.\n", + "\n", + " pow: \n", + " The power to which the base number would be raised. This should be an integer.\n", + "\n", + "\n", + "\n", + "\n", + " Returns:\n", + " -------\n", + " \n", + " The result is an integer that is the base raised to the specified power.\n", + "\n", + "\n", + "\n", + " Examples:\n", + " --------\n", + " Here are a few examples of function usages:\n", + "\n", + " square(2, 3)\n", + " Returns: 8\n", + " Explanation: 2 raised to the power of 3 equals 8.\n", + "\n", + " square(5, 2)\n", + " Returns: 25\n", + " Explanation: 5 raised to the power of 2 equals 25.\n", + "\n", + " square(3, 0)\n", + " Returns: 1\n", + " Explanation: Any number raised to the power of 0 equals 1.\n", + " \"\"\"\n", + " \n", + " return base ** pow\n", + "```\n", + "\n" ] } ], diff --git a/poetry.lock b/poetry.lock index e39f1d8..597d134 100644 --- a/poetry.lock +++ b/poetry.lock @@ -12,13 +12,25 @@ files = [ {file = "alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e"}, ] +[[package]] +name = "annotated-types" +version = "0.7.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, +] + [[package]] name = "anyio" version = "4.8.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.9" -groups = ["dev"] +groups = ["main", "dev"] files = [ {file = "anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a"}, {file = "anyio-4.8.0.tar.gz", hash = "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a"}, @@ -565,7 +577,6 @@ files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] -markers = {main = "os_name == \"nt\" or sys_platform == \"win32\" or platform_system == \"Windows\"", dev = "sys_platform == \"win32\" or platform_system == \"Windows\""} [[package]] name = "comm" @@ -798,6 +809,18 @@ files = [ {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, ] +[[package]] +name = "distro" +version = "1.9.0" +description = "Distro - an OS platform information API" +optional = false +python-versions = ">=3.6" +groups = ["main"] +files = [ + {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, + {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, +] + [[package]] name = "docutils" version = "0.21.2" @@ -1059,7 +1082,7 @@ version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" optional = false python-versions = ">=3.7" -groups = ["dev"] +groups = ["main", "dev"] files = [ {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, @@ -1071,7 +1094,7 @@ version = "1.0.7" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.8" -groups = ["dev"] +groups = ["main", "dev"] files = [ {file = "httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd"}, {file = "httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c"}, @@ -1093,7 +1116,7 @@ version = "0.28.1" description = "The next generation HTTP client." optional = false python-versions = ">=3.8" -groups = ["dev"] +groups = ["main", "dev"] files = [ {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, @@ -1413,6 +1436,92 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] +[[package]] +name = "jiter" +version = "0.8.2" +description = "Fast iterable JSON parser." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "jiter-0.8.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:ca8577f6a413abe29b079bc30f907894d7eb07a865c4df69475e868d73e71c7b"}, + {file = "jiter-0.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b25bd626bde7fb51534190c7e3cb97cee89ee76b76d7585580e22f34f5e3f393"}, + {file = "jiter-0.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5c826a221851a8dc028eb6d7d6429ba03184fa3c7e83ae01cd6d3bd1d4bd17d"}, + {file = "jiter-0.8.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d35c864c2dff13dfd79fb070fc4fc6235d7b9b359efe340e1261deb21b9fcb66"}, + {file = "jiter-0.8.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f557c55bc2b7676e74d39d19bcb8775ca295c7a028246175d6a8b431e70835e5"}, + {file = "jiter-0.8.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:580ccf358539153db147e40751a0b41688a5ceb275e6f3e93d91c9467f42b2e3"}, + {file = "jiter-0.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af102d3372e917cffce49b521e4c32c497515119dc7bd8a75665e90a718bbf08"}, + {file = "jiter-0.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cadcc978f82397d515bb2683fc0d50103acff2a180552654bb92d6045dec2c49"}, + {file = "jiter-0.8.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ba5bdf56969cad2019d4e8ffd3f879b5fdc792624129741d3d83fc832fef8c7d"}, + {file = "jiter-0.8.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3b94a33a241bee9e34b8481cdcaa3d5c2116f575e0226e421bed3f7a6ea71cff"}, + {file = "jiter-0.8.2-cp310-cp310-win32.whl", hash = "sha256:6e5337bf454abddd91bd048ce0dca5134056fc99ca0205258766db35d0a2ea43"}, + {file = "jiter-0.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:4a9220497ca0cb1fe94e3f334f65b9b5102a0b8147646118f020d8ce1de70105"}, + {file = "jiter-0.8.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:2dd61c5afc88a4fda7d8b2cf03ae5947c6ac7516d32b7a15bf4b49569a5c076b"}, + {file = "jiter-0.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a6c710d657c8d1d2adbbb5c0b0c6bfcec28fd35bd6b5f016395f9ac43e878a15"}, + {file = "jiter-0.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9584de0cd306072635fe4b89742bf26feae858a0683b399ad0c2509011b9dc0"}, + {file = "jiter-0.8.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5a90a923338531b7970abb063cfc087eebae6ef8ec8139762007188f6bc69a9f"}, + {file = "jiter-0.8.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d21974d246ed0181558087cd9f76e84e8321091ebfb3a93d4c341479a736f099"}, + {file = "jiter-0.8.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:32475a42b2ea7b344069dc1e81445cfc00b9d0e3ca837f0523072432332e9f74"}, + {file = "jiter-0.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b9931fd36ee513c26b5bf08c940b0ac875de175341cbdd4fa3be109f0492586"}, + {file = "jiter-0.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ce0820f4a3a59ddced7fce696d86a096d5cc48d32a4183483a17671a61edfddc"}, + {file = "jiter-0.8.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8ffc86ae5e3e6a93765d49d1ab47b6075a9c978a2b3b80f0f32628f39caa0c88"}, + {file = "jiter-0.8.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5127dc1abd809431172bc3fbe8168d6b90556a30bb10acd5ded41c3cfd6f43b6"}, + {file = "jiter-0.8.2-cp311-cp311-win32.whl", hash = "sha256:66227a2c7b575720c1871c8800d3a0122bb8ee94edb43a5685aa9aceb2782d44"}, + {file = "jiter-0.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:cde031d8413842a1e7501e9129b8e676e62a657f8ec8166e18a70d94d4682855"}, + {file = "jiter-0.8.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:e6ec2be506e7d6f9527dae9ff4b7f54e68ea44a0ef6b098256ddf895218a2f8f"}, + {file = "jiter-0.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76e324da7b5da060287c54f2fabd3db5f76468006c811831f051942bf68c9d44"}, + {file = "jiter-0.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:180a8aea058f7535d1c84183c0362c710f4750bef66630c05f40c93c2b152a0f"}, + {file = "jiter-0.8.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:025337859077b41548bdcbabe38698bcd93cfe10b06ff66617a48ff92c9aec60"}, + {file = "jiter-0.8.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ecff0dc14f409599bbcafa7e470c00b80f17abc14d1405d38ab02e4b42e55b57"}, + {file = "jiter-0.8.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffd9fee7d0775ebaba131f7ca2e2d83839a62ad65e8e02fe2bd8fc975cedeb9e"}, + {file = "jiter-0.8.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14601dcac4889e0a1c75ccf6a0e4baf70dbc75041e51bcf8d0e9274519df6887"}, + {file = "jiter-0.8.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:92249669925bc1c54fcd2ec73f70f2c1d6a817928480ee1c65af5f6b81cdf12d"}, + {file = "jiter-0.8.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e725edd0929fa79f8349ab4ec7f81c714df51dc4e991539a578e5018fa4a7152"}, + {file = "jiter-0.8.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bf55846c7b7a680eebaf9c3c48d630e1bf51bdf76c68a5f654b8524335b0ad29"}, + {file = "jiter-0.8.2-cp312-cp312-win32.whl", hash = "sha256:7efe4853ecd3d6110301665a5178b9856be7e2a9485f49d91aa4d737ad2ae49e"}, + {file = "jiter-0.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:83c0efd80b29695058d0fd2fa8a556490dbce9804eac3e281f373bbc99045f6c"}, + {file = "jiter-0.8.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:ca1f08b8e43dc3bd0594c992fb1fd2f7ce87f7bf0d44358198d6da8034afdf84"}, + {file = "jiter-0.8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5672a86d55416ccd214c778efccf3266b84f87b89063b582167d803246354be4"}, + {file = "jiter-0.8.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58dc9bc9767a1101f4e5e22db1b652161a225874d66f0e5cb8e2c7d1c438b587"}, + {file = "jiter-0.8.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:37b2998606d6dadbb5ccda959a33d6a5e853252d921fec1792fc902351bb4e2c"}, + {file = "jiter-0.8.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ab9a87f3784eb0e098f84a32670cfe4a79cb6512fd8f42ae3d0709f06405d18"}, + {file = "jiter-0.8.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:79aec8172b9e3c6d05fd4b219d5de1ac616bd8da934107325a6c0d0e866a21b6"}, + {file = "jiter-0.8.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:711e408732d4e9a0208008e5892c2966b485c783cd2d9a681f3eb147cf36c7ef"}, + {file = "jiter-0.8.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:653cf462db4e8c41995e33d865965e79641ef45369d8a11f54cd30888b7e6ff1"}, + {file = "jiter-0.8.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:9c63eaef32b7bebac8ebebf4dabebdbc6769a09c127294db6babee38e9f405b9"}, + {file = "jiter-0.8.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:eb21aaa9a200d0a80dacc7a81038d2e476ffe473ffdd9c91eb745d623561de05"}, + {file = "jiter-0.8.2-cp313-cp313-win32.whl", hash = "sha256:789361ed945d8d42850f919342a8665d2dc79e7e44ca1c97cc786966a21f627a"}, + {file = "jiter-0.8.2-cp313-cp313-win_amd64.whl", hash = "sha256:ab7f43235d71e03b941c1630f4b6e3055d46b6cb8728a17663eaac9d8e83a865"}, + {file = "jiter-0.8.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b426f72cd77da3fec300ed3bc990895e2dd6b49e3bfe6c438592a3ba660e41ca"}, + {file = "jiter-0.8.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2dd880785088ff2ad21ffee205e58a8c1ddabc63612444ae41e5e4b321b39c0"}, + {file = "jiter-0.8.2-cp313-cp313t-win_amd64.whl", hash = "sha256:3ac9f578c46f22405ff7f8b1f5848fb753cc4b8377fbec8470a7dc3997ca7566"}, + {file = "jiter-0.8.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:9e1fa156ee9454642adb7e7234a383884452532bc9d53d5af2d18d98ada1d79c"}, + {file = "jiter-0.8.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0cf5dfa9956d96ff2efb0f8e9c7d055904012c952539a774305aaaf3abdf3d6c"}, + {file = "jiter-0.8.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e52bf98c7e727dd44f7c4acb980cb988448faeafed8433c867888268899b298b"}, + {file = "jiter-0.8.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a2ecaa3c23e7a7cf86d00eda3390c232f4d533cd9ddea4b04f5d0644faf642c5"}, + {file = "jiter-0.8.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:08d4c92bf480e19fc3f2717c9ce2aa31dceaa9163839a311424b6862252c943e"}, + {file = "jiter-0.8.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99d9a1eded738299ba8e106c6779ce5c3893cffa0e32e4485d680588adae6db8"}, + {file = "jiter-0.8.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d20be8b7f606df096e08b0b1b4a3c6f0515e8dac296881fe7461dfa0fb5ec817"}, + {file = "jiter-0.8.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d33f94615fcaf872f7fd8cd98ac3b429e435c77619777e8a449d9d27e01134d1"}, + {file = "jiter-0.8.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:317b25e98a35ffec5c67efe56a4e9970852632c810d35b34ecdd70cc0e47b3b6"}, + {file = "jiter-0.8.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fc9043259ee430ecd71d178fccabd8c332a3bf1e81e50cae43cc2b28d19e4cb7"}, + {file = "jiter-0.8.2-cp38-cp38-win32.whl", hash = "sha256:fc5adda618205bd4678b146612ce44c3cbfdee9697951f2c0ffdef1f26d72b63"}, + {file = "jiter-0.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:cd646c827b4f85ef4a78e4e58f4f5854fae0caf3db91b59f0d73731448a970c6"}, + {file = "jiter-0.8.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:e41e75344acef3fc59ba4765df29f107f309ca9e8eace5baacabd9217e52a5ee"}, + {file = "jiter-0.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7f22b16b35d5c1df9dfd58843ab2cd25e6bf15191f5a236bed177afade507bfc"}, + {file = "jiter-0.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7200b8f7619d36aa51c803fd52020a2dfbea36ffec1b5e22cab11fd34d95a6d"}, + {file = "jiter-0.8.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:70bf4c43652cc294040dbb62256c83c8718370c8b93dd93d934b9a7bf6c4f53c"}, + {file = "jiter-0.8.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f9d471356dc16f84ed48768b8ee79f29514295c7295cb41e1133ec0b2b8d637d"}, + {file = "jiter-0.8.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:859e8eb3507894093d01929e12e267f83b1d5f6221099d3ec976f0c995cb6bd9"}, + {file = "jiter-0.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaa58399c01db555346647a907b4ef6d4f584b123943be6ed5588c3f2359c9f4"}, + {file = "jiter-0.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8f2d5ed877f089862f4c7aacf3a542627c1496f972a34d0474ce85ee7d939c27"}, + {file = "jiter-0.8.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:03c9df035d4f8d647f8c210ddc2ae0728387275340668fb30d2421e17d9a0841"}, + {file = "jiter-0.8.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8bd2a824d08d8977bb2794ea2682f898ad3d8837932e3a74937e93d62ecbb637"}, + {file = "jiter-0.8.2-cp39-cp39-win32.whl", hash = "sha256:ca29b6371ebc40e496995c94b988a101b9fbbed48a51190a4461fcb0a68b4a36"}, + {file = "jiter-0.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:1c0dfbd1be3cbefc7510102370d86e35d1d53e5a93d48519688b1bf0f761160a"}, + {file = "jiter-0.8.2.tar.gz", hash = "sha256:cd73d3e740666d0e639f678adb176fad25c1bcbdae88d8d7b857e1783bb4212d"}, +] + [[package]] name = "json5" version = "0.10.0" @@ -2251,6 +2360,32 @@ jupyter-server = ">=1.8,<3" [package.extras] test = ["pytest", "pytest-console-scripts", "pytest-jupyter", "pytest-tornasync"] +[[package]] +name = "openai" +version = "1.60.2" +description = "The official Python library for the openai API" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "openai-1.60.2-py3-none-any.whl", hash = "sha256:993bd11b96900b9098179c728026f016b4982ded7ee30dfcf4555eab1171fff9"}, + {file = "openai-1.60.2.tar.gz", hash = "sha256:a8f843e10f2855713007f491d96afb2694b11b5e02cb97c7d01a0be60bc5bb51"}, +] + +[package.dependencies] +anyio = ">=3.5.0,<5" +distro = ">=1.7.0,<2" +httpx = ">=0.23.0,<1" +jiter = ">=0.4.0,<1" +pydantic = ">=1.9.0,<3" +sniffio = "*" +tqdm = ">4" +typing-extensions = ">=4.11,<5" + +[package.extras] +datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] +realtime = ["websockets (>=13,<15)"] + [[package]] name = "overrides" version = "7.7.0" @@ -2515,6 +2650,140 @@ files = [ ] markers = {main = "implementation_name == \"pypy\" or sys_platform == \"darwin\" or (sys_platform == \"linux\" or sys_platform == \"darwin\") and platform_python_implementation != \"PyPy\""} +[[package]] +name = "pydantic" +version = "2.10.6" +description = "Data validation using Python type hints" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"}, + {file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"}, +] + +[package.dependencies] +annotated-types = ">=0.6.0" +pydantic-core = "2.27.2" +typing-extensions = ">=4.12.2" + +[package.extras] +email = ["email-validator (>=2.0.0)"] +timezone = ["tzdata"] + +[[package]] +name = "pydantic-core" +version = "2.27.2" +description = "Core functionality for Pydantic validation and serialization" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"}, + {file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236"}, + {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962"}, + {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9"}, + {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af"}, + {file = "pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4"}, + {file = "pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31"}, + {file = "pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc"}, + {file = "pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d"}, + {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b"}, + {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474"}, + {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6"}, + {file = "pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c"}, + {file = "pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc"}, + {file = "pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4"}, + {file = "pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0"}, + {file = "pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4"}, + {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3"}, + {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4"}, + {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57"}, + {file = "pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc"}, + {file = "pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9"}, + {file = "pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b"}, + {file = "pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b"}, + {file = "pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4"}, + {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27"}, + {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee"}, + {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1"}, + {file = "pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130"}, + {file = "pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee"}, + {file = "pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b"}, + {file = "pydantic_core-2.27.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506"}, + {file = "pydantic_core-2.27.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a"}, + {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d"}, + {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9"}, + {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da"}, + {file = "pydantic_core-2.27.2-cp38-cp38-win32.whl", hash = "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b"}, + {file = "pydantic_core-2.27.2-cp38-cp38-win_amd64.whl", hash = "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad"}, + {file = "pydantic_core-2.27.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993"}, + {file = "pydantic_core-2.27.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54"}, + {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f"}, + {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362"}, + {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96"}, + {file = "pydantic_core-2.27.2-cp39-cp39-win32.whl", hash = "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e"}, + {file = "pydantic_core-2.27.2-cp39-cp39-win_amd64.whl", hash = "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35"}, + {file = "pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" + [[package]] name = "pygments" version = "2.19.1" @@ -2599,6 +2868,21 @@ files = [ [package.dependencies] six = ">=1.5" +[[package]] +name = "python-dotenv" +version = "1.0.1" +description = "Read key-value pairs from a .env file and set them as environment variables" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, + {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + [[package]] name = "python-json-logger" version = "3.2.1" @@ -3238,7 +3522,7 @@ version = "1.3.1" description = "Sniff out which async library your code is running under" optional = false python-versions = ">=3.7" -groups = ["dev"] +groups = ["main", "dev"] files = [ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, @@ -3726,6 +4010,28 @@ files = [ {file = "tornado-6.4.2.tar.gz", hash = "sha256:92bad5b4746e9879fd7bf1eb21dce4e3fc5128d71601f80005afa39237ad620b"}, ] +[[package]] +name = "tqdm" +version = "4.67.1" +description = "Fast, Extensible Progress Meter" +optional = false +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2"}, + {file = "tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[package.extras] +dev = ["nbval", "pytest (>=6)", "pytest-asyncio (>=0.24)", "pytest-cov", "pytest-timeout"] +discord = ["requests"] +notebook = ["ipywidgets (>=6)"] +slack = ["slack-sdk"] +telegram = ["requests"] + [[package]] name = "traitlets" version = "5.14.3" @@ -4007,4 +4313,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<4.0" -content-hash = "9d5b0888c03e458fa059f6fbadb2e7fed0468cfb2a02f425abb4b9186ee6efe0" +content-hash = "2b74d3d5cb5652f6abbbb2da03ff678b5db09798cf2acc3fb4faa8ee2b183f8c" diff --git a/pyproject.toml b/pyproject.toml index d64bf5e..7ccdca1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,6 +11,9 @@ python = ">=3.10,<4.0" poetry = "^2.0.0" myst-nb = "^1.1.2" autoapi = "^2.0.1" +colorama = "^0.4.6" +openai = "^1.60.2" +python-dotenv = "^1.0.1" [tool.poetry.group.dev.dependencies] pytest = "^8.3.4" diff --git a/src/fml_doc_gen/autogen.py b/src/fml_doc_gen/autogen.py new file mode 100644 index 0000000..c4266ea --- /dev/null +++ b/src/fml_doc_gen/autogen.py @@ -0,0 +1,57 @@ +# Credit: Some test cases were auto-generated using Cursor AI. +# Additional modifications and refinements were made for completeness and correctness. + +from openai import OpenAI +from dotenv import load_dotenv +import os + + +def fill_docstring_with_ai(docstring_template: str, function_source: str) -> str: + """ + Generates a detailed docstring for a given function source by filling in a provided template + using OpenAI's language model. + + Args: + docstring_template (str): The docstring template with placeholders for descriptions. + function_source (str): The source code of the function to extract context. + + Returns: + str: The completed docstring with detailed descriptions. + + Raises: + ValueError: If either `docstring_template` or `function_source` is empty. + RuntimeError: If the API request fails or returns an unexpected response. + """ + + if not docstring_template: + raise ValueError("The docstring template cannot be empty.") + + if not function_source: + raise ValueError("The function source cannot be empty.") + + # Load environment variables + load_dotenv() + + # Set OpenAI API key + client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) + + prompt = ( + "You are an expert Python programmer. Given the following function source code and a " + "docstring template, replace the placeholders with appropriate descriptions for parameters, " + "return values, and examples. Follow the NumPy/Google format for writing docstrings.\n\n" + f"Docstring Template:\n{docstring_template}\n\nFunction Source:\n{function_source}" + ) + + try: + response = client.chat.completions.create( + model="gpt-4", + messages=[ + {"role": "system", "content": "You are an expert Python developer writing docstrings."}, + {"role": "user", "content": prompt}, + ] + ) + + return response.choices[0].message.content + + except Exception as e: + raise RuntimeError(f"An unexpected error occurred") \ No newline at end of file diff --git a/src/fml_doc_gen/fml_doc_gen.py b/src/fml_doc_gen/fml_doc_gen.py index ab545eb..40aebb2 100644 --- a/src/fml_doc_gen/fml_doc_gen.py +++ b/src/fml_doc_gen/fml_doc_gen.py @@ -2,9 +2,14 @@ from fml_doc_gen.read_user_function import read_user_function from fml_doc_gen.generate_template import generate_template from fml_doc_gen.write_docstring_to_file import write_docstring_to_file +from fml_doc_gen.autogen import fill_docstring_with_ai -def generate_docstring_template(func: Callable, output_file: Optional[str], auto_generate: Optional[bool] = False) -> str: +def generate_docstring_template( + func: Callable, + output_file: Optional[str] = None, + auto_generate: bool = False +) -> str: """ Generates a docstring template for a given user-defined function. @@ -12,17 +17,21 @@ def generate_docstring_template(func: Callable, output_file: Optional[str], auto ---------- func : Callable The user-defined function for which the docstring template (or full docstring) needs to be generated. - output_file : str - Writes the generated docstring to the given file. Defaults to None. + output_file : str, optional + The file path to write the generated docstring. Defaults to None. auto_generate : bool, optional If True, automatically generates the full docstring using an OpenAI API call. Defaults to False. - Returns ------- str The generated docstring template or complete docstring. + Raises + ------ + ValueError + If `func` is not provided. + Examples -------- >>> def example_func(a, b): @@ -39,13 +48,17 @@ def generate_docstring_template(func: Callable, output_file: Optional[str], auto return_type \"\"\" """ - - f_dto = read_user_function(func) + if func is None: + raise ValueError("The `func` parameter cannot be None.") + + func_dto = read_user_function(func) + template = generate_template(func_dto) + + docstring = template + if auto_generate: + docstring = fill_docstring_with_ai(template, func_dto.src) - # TODO: Call openAI API here one day . . . - docstring = generate_template(f_dto) if not auto_generate else "AUTO GENERATE IS NOT AVAILABLE YET!" - if output_file: - write_docstring_to_file(docstring = docstring, output_file = output_file) - + write_docstring_to_file(docstring=docstring, output_file=output_file) + return docstring \ No newline at end of file diff --git a/src/fml_doc_gen/func_dto.py b/src/fml_doc_gen/func_dto.py index 4cf0855..a2e8d7f 100644 --- a/src/fml_doc_gen/func_dto.py +++ b/src/fml_doc_gen/func_dto.py @@ -2,14 +2,49 @@ class FunctionDTO: - def __init__(self, name: Optional[str] = "", output: Optional[str] = None, inputs: Optional[List[Tuple[str, str]]] = []): + """ + Data Transfer Object (DTO) for function metadata. + + Attributes: + name (Optional[str]): The name of the function. + output_type (Optional[str]): The return type of the function. + inputs (Optional[List[Tuple[str, str]]]): A list of input parameters as (name, type) tuples. + src (Optional[str]): The source code or reference associated with the function. + """ + + def __init__( + self, + name: Optional[str] = "", + output: Optional[str] = None, + inputs: Optional[List[Tuple[str, str]]] = None, + src: Optional[str] = None, + ): + """ + Initializes a FunctionDTO instance. + + Args: + name (Optional[str]): The name of the function. Defaults to an empty string. + output (Optional[str]): The return type of the function. Defaults to None. + inputs (Optional[List[Tuple[str, str]]]): List of input parameters as (name, type) tuples. Defaults to an empty list. + src (Optional[str]): The source code or reference associated with the function. Defaults to None. + """ + if inputs is None: + inputs = [] + self.name = name self.output_type = output self.inputs = [(name, input_type) for (name, input_type) in inputs] + self.src = src + + def __str__(self) -> str: + """ + Returns a string representation of the FunctionDTO instance. - def __str__(self): + Returns: + str: A formatted string containing function name, return type, and inputs. + """ return ( f"Function Name: {self.name}\n" f"Return Type: {self.output_type}\n" f"Input List: {self.inputs}" - ) \ No newline at end of file + ) diff --git a/src/fml_doc_gen/read_user_function.py b/src/fml_doc_gen/read_user_function.py index 25a4547..6146113 100644 --- a/src/fml_doc_gen/read_user_function.py +++ b/src/fml_doc_gen/read_user_function.py @@ -1,7 +1,7 @@ -from typing import Callable -from fml_doc_gen.func_dto import FunctionDTO import inspect +from typing import Callable, Optional +from fml_doc_gen.func_dto import FunctionDTO def read_user_function(func: Callable) -> FunctionDTO: """ @@ -14,34 +14,33 @@ def read_user_function(func: Callable) -> FunctionDTO: Returns ------- - str - The function signature as a string. + FunctionDTO + The function signature as a FunctionDTO object. + Raises + ------ + TypeError + If func is not a callable object. + Examples -------- >>> def example_func(a, b): ... return a + b ... - >>> read_user_function(example_func) - 'example_func(a, b)' + >>> sigDTO = read_user_function(example_func) """ + if not callable(func): + raise TypeError("Expected a callable function") + source_lines = inspect.getsourcelines(func) - function_header = source_lines[0][0].strip() - - name = function_header.split('(')[0].split(' ')[1] - return_type = None - inputs = function_header.split('(')[1].split(')')[0].split(',') - inputs = [ - ( - thing.split(':')[0].strip(), - thing.split(':')[1].strip() if ':' in thing else None - ) for thing in inputs - ] + signature = inspect.signature(func) + name = func.__name__ - if '->' in function_header: - return_type = function_header.split('->')[1].split(':')[0].strip() + return_type = None if signature.return_annotation is inspect.Signature.empty else str(signature.return_annotation) - if len(inputs) == 1 and inputs[0] == ('', None): - inputs = [] + inputs = [] + for param_name, param in signature.parameters.items(): + param_type = None if param.annotation is inspect.Parameter.empty else str(param.annotation) + inputs.append((param_name, param_type)) - return FunctionDTO(name, output = return_type, inputs = inputs) \ No newline at end of file + return FunctionDTO(name=name, output=return_type, inputs=inputs, src=source_lines) diff --git a/tests/test_autogen.py b/tests/test_autogen.py new file mode 100644 index 0000000..945fef7 --- /dev/null +++ b/tests/test_autogen.py @@ -0,0 +1,74 @@ +import pytest +from unittest.mock import patch, MagicMock +from fml_doc_gen.autogen import fill_docstring_with_ai + +def test_empty_template(): + """Test that empty template raises ValueError""" + with pytest.raises(ValueError, match="The docstring template cannot be empty"): + fill_docstring_with_ai("", "def sample_func(): pass") + +def test_empty_source(): + """Test that empty source raises ValueError""" + with pytest.raises(ValueError, match="The function source cannot be empty"): + fill_docstring_with_ai("template", "") + +@patch('fml_doc_gen.autogen.OpenAI') +@patch('fml_doc_gen.autogen.load_dotenv') +def test_successful_api_call(mock_load_dotenv, mock_openai): + """Test successful API call with mocked response""" + # Setup mock response + mock_client = MagicMock() + mock_openai.return_value = mock_client + mock_response = MagicMock() + mock_response.choices[0].message.content = "Generated docstring" + mock_client.chat.completions.create.return_value = mock_response + + template = "Test template" + source = "def test(): pass" + + result = fill_docstring_with_ai(template, source) + + # Verify the result + assert result == "Generated docstring" + mock_load_dotenv.assert_called_once() + mock_client.chat.completions.create.assert_called_once() + +@patch('fml_doc_gen.autogen.OpenAI') +@patch('fml_doc_gen.autogen.load_dotenv') +def test_api_error(mock_load_dotenv, mock_openai): + """Test handling of API error""" + # Setup mock to raise an exception + mock_client = MagicMock() + mock_openai.return_value = mock_client + mock_client.chat.completions.create.side_effect = Exception("API Error") + + template = "Test template" + source = "def test(): pass" + + with pytest.raises(RuntimeError, match="An unexpected error occurred"): + fill_docstring_with_ai(template, source) + +@patch('fml_doc_gen.autogen.OpenAI') +@patch('fml_doc_gen.autogen.load_dotenv') +def test_api_call_content(mock_load_dotenv, mock_openai): + """Test that API is called with correct content""" + # Setup mock + mock_client = MagicMock() + mock_openai.return_value = mock_client + mock_response = MagicMock() + mock_response.choices[0].message.content = "Generated docstring" + mock_client.chat.completions.create.return_value = mock_response + + template = "Test template" + source = "def test(): pass" + + fill_docstring_with_ai(template, source) + + # Verify the API call content + call_args = mock_client.chat.completions.create.call_args[1] + assert call_args['model'] == "gpt-4" + assert len(call_args['messages']) == 2 + assert call_args['messages'][0]['role'] == "system" + assert call_args['messages'][1]['role'] == "user" + assert template in call_args['messages'][1]['content'] + assert source in call_args['messages'][1]['content'] diff --git a/tests/test_fml_doc_gen.py b/tests/test_fml_doc_gen.py index ff7423e..05fa90f 100644 --- a/tests/test_fml_doc_gen.py +++ b/tests/test_fml_doc_gen.py @@ -14,11 +14,11 @@ def valid_docstring(): Parameters: ---------- - base: int + base: ### INSERT PARAMETER DEFINITION HERE ### - pow: int + pow: ### INSERT PARAMETER DEFINITION HERE ### @@ -26,7 +26,7 @@ def valid_docstring(): Returns: ------- - int + ### INSERT ADDITIONAL FUNCTION OUTPUT INFORMATION HERE ### @@ -44,7 +44,7 @@ def square(base: int, pow: int) -> int: file_path = temp_file.name try: - expected = '\n square: \n ### INSERT FUNCTION DEFINITION HERE ###\n \n Parameters:\n ----------\n \n base: int\n ### INSERT PARAMETER DEFINITION HERE ###\n \n\n pow: int\n ### INSERT PARAMETER DEFINITION HERE ###\n \n\n\n \n Returns:\n -------\n int\n ### INSERT ADDITIONAL FUNCTION OUTPUT INFORMATION HERE ###\n\n \n Examples:\n --------\n ### INSERT FUNCTION EXAMPLE USAGES HERE ###\n' + expected = """\n square: \n ### INSERT FUNCTION DEFINITION HERE ###\n \n Parameters:\n ----------\n \n base: \n ### INSERT PARAMETER DEFINITION HERE ###\n \n\n pow: \n ### INSERT PARAMETER DEFINITION HERE ###\n \n\n\n \n Returns:\n -------\n \n ### INSERT ADDITIONAL FUNCTION OUTPUT INFORMATION HERE ###\n\n \n Examples:\n --------\n ### INSERT FUNCTION EXAMPLE USAGES HERE ###\n""" actual = generate_docstring_template(func=square, output_file=file_path, auto_generate=False) assert expected == actual diff --git a/tests/test_read_user_function.py b/tests/test_read_user_function.py index a19f9f5..3ac3a05 100644 --- a/tests/test_read_user_function.py +++ b/tests/test_read_user_function.py @@ -1,8 +1,14 @@ import pytest +from typing import Callable, Optional from fml_doc_gen.func_dto import FunctionDTO from fml_doc_gen.read_user_function import read_user_function +def test_raises_error_unused_argument(): + """Test that function raises error when argument is unused""" + with pytest.raises(TypeError, match="Expected a callable function"): + read_user_function(5) + def test_no_params_no_types_no_return(): """ Test with a function with no input, no defined input type, @@ -41,8 +47,10 @@ def sample_func(a: int): dto = read_user_function(sample_func) assert dto.name == "sample_func" - assert dto.output_type == None - assert dto.inputs == [('a', 'int')] + assert dto.output_type is None + assert dto.inputs == [ + ("a", "") + ] def test_no_params_no_types_return(): """ @@ -53,7 +61,7 @@ def sample_func() -> str: dto = read_user_function(sample_func) assert dto.name == "sample_func" - assert dto.output_type == "str" + assert dto.output_type == "" assert dto.inputs == [] def test_params_no_types_with_return(): @@ -66,7 +74,7 @@ def sample_func(a) -> bool: dto = read_user_function(sample_func) assert dto.name == "sample_func" - assert dto.output_type == "bool" + assert dto.output_type == "" assert dto.inputs == [ ("a", None) ] @@ -81,10 +89,10 @@ def sample_func(a: int, b: str) -> bool: dto = read_user_function(sample_func) assert dto.name == "sample_func" - assert dto.output_type == "bool" + assert dto.output_type == "" assert dto.inputs == [ - ("a", "int"), - ("b", "str") + ("a", ""), + ("b", "") ] def test_params_with_all(): @@ -97,8 +105,54 @@ def sample_func(a: int, b: str) -> bool: dto = read_user_function(sample_func) assert dto.name == "sample_func" - assert dto.output_type == "bool" + assert dto.output_type == "" assert dto.inputs == [ - ("a", "int"), - ("b", "str") - ] \ No newline at end of file + ("a", ""), + ("b", "") + ] + +def test_complex_return_type(): + """Test with a more complex return type annotation""" + def sample_func() -> list[int]: + return [1, 2, 3] + + dto = read_user_function(sample_func) + assert dto.name == "sample_func" + assert dto.output_type == "list[int]" + assert dto.inputs == [] + +def test_default_values(): + """Test with parameters that have default values""" + def sample_func(a: int = 0, b: str = "default"): + pass + + dto = read_user_function(sample_func) + assert dto.name == "sample_func" + assert dto.output_type is None + assert dto.inputs == [ + ("a", ""), + ("b", "") + ] + +def test_none_type(): + """Test with None type annotations""" + def sample_func(a: None) -> None: + pass + + dto = read_user_function(sample_func) + assert dto.name == "sample_func" + assert dto.output_type == "None" + assert dto.inputs == [ + ("a", "None") + ] + +def test_optional_type(): + """Test with Optional type hints""" + + def sample_func(a: Optional[int]) -> Optional[str]: + pass + + dto = read_user_function(sample_func) + assert dto.name == "sample_func" + assert "Optional" in str(dto.output_type) + assert "Optional" in str(dto.inputs[0][1])