diff --git a/.vscode/settings.json b/.vscode/settings.json index 2b8c92b2..d0a0168e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,7 +8,7 @@ "pygls.server.debug": false, // "pygls.server.debugHost": "localhost", // "pygls.server.debugPort": 5678, - "pygls.server.launchScript": "formatting.py", // This is relative to `pygls.server.cwd` + "pygls.server.launchScript": "code_actions.py", // This is relative to `pygls.server.cwd` "pygls.server.cwd": "${workspaceFolder}/examples/servers", "pygls.trace.server": "off", "pygls.client.documentSelector": [ diff --git a/docs/requirements.txt b/docs/requirements.txt index 2cc6cd45..7fe0f7ab 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,119 +1,137 @@ -alabaster==0.7.13 ; python_full_version >= "3.7.9" and python_version < "4" \ +alabaster==0.7.13 ; python_version >= "3.8" \ --hash=sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3 \ --hash=sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2 -attrs==23.1.0 ; python_full_version >= "3.7.9" and python_version < "4" \ +attrs==23.1.0 ; python_version >= "3.8" \ --hash=sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04 \ --hash=sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015 -babel==2.12.1 ; python_full_version >= "3.7.9" and python_version < "4" \ - --hash=sha256:b4246fb7677d3b98f501a39d43396d3cafdc8eadb045f4a31be01863f655c610 \ - --hash=sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455 -cattrs==23.1.2 ; python_full_version >= "3.7.9" and python_version < "4" \ - --hash=sha256:b2bb14311ac17bed0d58785e5a60f022e5431aca3932e3fc5cc8ed8639de50a4 \ - --hash=sha256:db1c821b8c537382b2c7c66678c3790091ca0275ac486c76f3c8f3920e83c657 -certifi==2023.7.22 ; python_full_version >= "3.7.9" and python_version < "4" \ - --hash=sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082 \ - --hash=sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9 -charset-normalizer==3.2.0 ; python_full_version >= "3.7.9" and python_version < "4" \ - --hash=sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96 \ - --hash=sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c \ - --hash=sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710 \ - --hash=sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706 \ - --hash=sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020 \ - --hash=sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252 \ - --hash=sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad \ - --hash=sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329 \ - --hash=sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a \ - --hash=sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f \ - --hash=sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6 \ - --hash=sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4 \ - --hash=sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a \ - --hash=sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46 \ - --hash=sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2 \ - --hash=sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23 \ - --hash=sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace \ - --hash=sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd \ - --hash=sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982 \ - --hash=sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10 \ - --hash=sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2 \ - --hash=sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea \ - --hash=sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09 \ - --hash=sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5 \ - --hash=sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149 \ - --hash=sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489 \ - --hash=sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9 \ - --hash=sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80 \ - --hash=sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592 \ - --hash=sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3 \ - --hash=sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6 \ - --hash=sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed \ - --hash=sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c \ - --hash=sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200 \ - --hash=sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a \ - --hash=sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e \ - --hash=sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d \ - --hash=sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6 \ - --hash=sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623 \ - --hash=sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669 \ - --hash=sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3 \ - --hash=sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa \ - --hash=sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9 \ - --hash=sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2 \ - --hash=sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f \ - --hash=sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1 \ - --hash=sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4 \ - --hash=sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a \ - --hash=sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8 \ - --hash=sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3 \ - --hash=sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029 \ - --hash=sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f \ - --hash=sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959 \ - --hash=sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22 \ - --hash=sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7 \ - --hash=sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952 \ - --hash=sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346 \ - --hash=sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e \ - --hash=sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d \ - --hash=sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299 \ - --hash=sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd \ - --hash=sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a \ - --hash=sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3 \ - --hash=sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037 \ - --hash=sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94 \ - --hash=sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c \ - --hash=sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858 \ - --hash=sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a \ - --hash=sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449 \ - --hash=sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c \ - --hash=sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918 \ - --hash=sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1 \ - --hash=sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c \ - --hash=sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac \ - --hash=sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa -colorama==0.4.6 ; python_full_version >= "3.7.9" and python_version < "4" and sys_platform == "win32" \ +babel==2.13.1 ; python_version >= "3.8" \ + --hash=sha256:33e0952d7dd6374af8dbf6768cc4ddf3ccfefc244f9986d4074704f2fbd18900 \ + --hash=sha256:7077a4984b02b6727ac10f1f7294484f737443d7e2e66c5e4380e41a3ae0b4ed +cattrs==23.2.2 ; python_version >= "3.8" \ + --hash=sha256:66064e2060ea207c5a48d065ab1910c10bb8108c28f3df8d1a7b1aa6b19d191b \ + --hash=sha256:b790b1c2be1ce042611e33f740e343c2593918bbf3c1cc88cdddac4defc09655 +certifi==2023.11.17 ; python_version >= "3.8" \ + --hash=sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1 \ + --hash=sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474 +charset-normalizer==3.3.2 ; python_version >= "3.8" \ + --hash=sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027 \ + --hash=sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087 \ + --hash=sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786 \ + --hash=sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8 \ + --hash=sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09 \ + --hash=sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185 \ + --hash=sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574 \ + --hash=sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e \ + --hash=sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519 \ + --hash=sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898 \ + --hash=sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269 \ + --hash=sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3 \ + --hash=sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f \ + --hash=sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6 \ + --hash=sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8 \ + --hash=sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a \ + --hash=sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73 \ + --hash=sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc \ + --hash=sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714 \ + --hash=sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2 \ + --hash=sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc \ + --hash=sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce \ + --hash=sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d \ + --hash=sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e \ + --hash=sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6 \ + --hash=sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269 \ + --hash=sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 \ + --hash=sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d \ + --hash=sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a \ + --hash=sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4 \ + --hash=sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 \ + --hash=sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d \ + --hash=sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0 \ + --hash=sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed \ + --hash=sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068 \ + --hash=sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac \ + --hash=sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25 \ + --hash=sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 \ + --hash=sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab \ + --hash=sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26 \ + --hash=sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2 \ + --hash=sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db \ + --hash=sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f \ + --hash=sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5 \ + --hash=sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99 \ + --hash=sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c \ + --hash=sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d \ + --hash=sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811 \ + --hash=sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa \ + --hash=sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a \ + --hash=sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03 \ + --hash=sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b \ + --hash=sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04 \ + --hash=sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c \ + --hash=sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001 \ + --hash=sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458 \ + --hash=sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389 \ + --hash=sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99 \ + --hash=sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985 \ + --hash=sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537 \ + --hash=sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238 \ + --hash=sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f \ + --hash=sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d \ + --hash=sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796 \ + --hash=sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a \ + --hash=sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143 \ + --hash=sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8 \ + --hash=sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c \ + --hash=sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5 \ + --hash=sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5 \ + --hash=sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711 \ + --hash=sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4 \ + --hash=sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6 \ + --hash=sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c \ + --hash=sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7 \ + --hash=sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4 \ + --hash=sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b \ + --hash=sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae \ + --hash=sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12 \ + --hash=sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c \ + --hash=sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae \ + --hash=sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8 \ + --hash=sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887 \ + --hash=sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b \ + --hash=sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4 \ + --hash=sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f \ + --hash=sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5 \ + --hash=sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33 \ + --hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \ + --hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561 +colorama==0.4.6 ; python_version >= "3.8" and sys_platform == "win32" \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 -docutils==0.18.1 ; python_full_version >= "3.7.9" and python_version < "4" \ - --hash=sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c \ - --hash=sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06 -exceptiongroup==1.1.3 ; python_full_version >= "3.7.9" and python_version < "3.11" \ - --hash=sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9 \ - --hash=sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3 -idna==3.4 ; python_full_version >= "3.7.9" and python_version < "4" \ - --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ - --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 -imagesize==1.4.1 ; python_full_version >= "3.7.9" and python_version < "4" \ +docutils==0.20.1 ; python_version >= "3.8" \ + --hash=sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6 \ + --hash=sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b +exceptiongroup==1.2.0 ; python_version < "3.11" and python_version >= "3.8" \ + --hash=sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14 \ + --hash=sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68 +idna==3.6 ; python_version >= "3.8" \ + --hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \ + --hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f +imagesize==1.4.1 ; python_version >= "3.8" \ --hash=sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b \ --hash=sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a -importlib-metadata==6.7.0 ; python_full_version >= "3.7.9" and python_version < "3.10" \ - --hash=sha256:1aaf550d4f73e5d6783e7acb77aec43d49da8017410afae93822cc9cca98c4d4 \ - --hash=sha256:cb52082e659e97afc5dac71e79de97d8681de3aa07ff18578330904a9d18e5b5 -jinja2==3.1.2 ; python_full_version >= "3.7.9" and python_version < "4" \ +importlib-metadata==6.8.0 ; python_version < "3.10" and python_version >= "3.8" \ + --hash=sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb \ + --hash=sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743 +jinja2==3.1.2 ; python_version >= "3.8" \ --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \ --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61 -lsprotocol==2023.0.0a3 ; python_full_version >= "3.7.9" and python_version < "4" \ - --hash=sha256:2896c5a30c34846e3d5687e35715961f49bf7b92a36e4fb2b707ff65f19087f7 \ - --hash=sha256:d704e4e00419f74bece9795de4b34d02aa555fc0131fec49f59ac9eb46816e51 -markupsafe==2.1.3 ; python_full_version >= "3.7.9" and python_version < "4" \ +lsprotocol==2023.0.0 ; python_version >= "3.8" \ + --hash=sha256:c9d92e12a3f4ed9317d3068226592860aab5357d93cf5b2451dc244eee8f35f2 \ + --hash=sha256:e85fc87ee26c816adca9eb497bb3db1a7c79c477a11563626e712eaccf926a05 +markdown-it-py==3.0.0 ; python_version >= "3.8" \ + --hash=sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1 \ + --hash=sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb +markupsafe==2.1.3 ; python_version >= "3.8" \ --hash=sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e \ --hash=sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e \ --hash=sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431 \ @@ -164,57 +182,120 @@ markupsafe==2.1.3 ; python_full_version >= "3.7.9" and python_version < "4" \ --hash=sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57 \ --hash=sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc \ --hash=sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2 -packaging==23.1 ; python_full_version >= "3.7.9" and python_version < "4" \ - --hash=sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61 \ - --hash=sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f -pygments==2.16.1 ; python_full_version >= "3.7.9" and python_version < "4" \ - --hash=sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692 \ - --hash=sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29 -pytz==2023.3 ; python_full_version >= "3.7.9" and python_version < "3.9" \ - --hash=sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588 \ - --hash=sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb -requests==2.31.0 ; python_full_version >= "3.7.9" and python_version < "4" \ +mdit-py-plugins==0.4.0 ; python_version >= "3.8" \ + --hash=sha256:b51b3bb70691f57f974e257e367107857a93b36f322a9e6d44ca5bf28ec2def9 \ + --hash=sha256:d8ab27e9aed6c38aa716819fedfde15ca275715955f8a185a8e1cf90fb1d2c1b +mdurl==0.1.2 ; python_version >= "3.8" \ + --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ + --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba +myst-parser==2.0.0 ; python_version >= "3.8" \ + --hash=sha256:7c36344ae39c8e740dad7fdabf5aa6fc4897a813083c6cc9990044eb93656b14 \ + --hash=sha256:ea929a67a6a0b1683cdbe19b8d2e724cd7643f8aa3e7bb18dd65beac3483bead +packaging==23.2 ; python_version >= "3.8" \ + --hash=sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5 \ + --hash=sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7 +pygments==2.17.2 ; python_version >= "3.8" \ + --hash=sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c \ + --hash=sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367 +pytz==2023.3.post1 ; python_version < "3.9" and python_version >= "3.8" \ + --hash=sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b \ + --hash=sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7 +pyyaml==6.0.1 ; python_version >= "3.8" \ + --hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \ + --hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \ + --hash=sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df \ + --hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \ + --hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \ + --hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \ + --hash=sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595 \ + --hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \ + --hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \ + --hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \ + --hash=sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290 \ + --hash=sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9 \ + --hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \ + --hash=sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6 \ + --hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \ + --hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \ + --hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \ + --hash=sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6 \ + --hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \ + --hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \ + --hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \ + --hash=sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0 \ + --hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \ + --hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \ + --hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \ + --hash=sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28 \ + --hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \ + --hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \ + --hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \ + --hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \ + --hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \ + --hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \ + --hash=sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0 \ + --hash=sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515 \ + --hash=sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c \ + --hash=sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c \ + --hash=sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924 \ + --hash=sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 \ + --hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \ + --hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \ + --hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \ + --hash=sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54 \ + --hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \ + --hash=sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b \ + --hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \ + --hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \ + --hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \ + --hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \ + --hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \ + --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f +requests==2.31.0 ; python_version >= "3.8" \ --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \ --hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1 -snowballstemmer==2.2.0 ; python_full_version >= "3.7.9" and python_version < "4" \ +setuptools==69.0.2 ; python_version >= "3.12" \ + --hash=sha256:1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2 \ + --hash=sha256:735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6 +snowballstemmer==2.2.0 ; python_version >= "3.8" \ --hash=sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1 \ --hash=sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a -sphinx-rtd-theme==1.3.0 ; python_full_version >= "3.7.9" and python_version < "4" \ - --hash=sha256:46ddef89cc2416a81ecfbeaceab1881948c014b1b6e4450b815311a89fb977b0 \ - --hash=sha256:590b030c7abb9cf038ec053b95e5380b5c70d61591eb0b552063fbe7c41f0931 -sphinx==5.3.0 ; python_full_version >= "3.7.9" and python_version < "4" \ - --hash=sha256:060ca5c9f7ba57a08a1219e547b269fadf125ae25b06b9fa7f66768efb652d6d \ - --hash=sha256:51026de0a9ff9fc13c05d74913ad66047e104f56a129ff73e174eb5c3ee794b5 -sphinxcontrib-applehelp==1.0.2 ; python_full_version >= "3.7.9" and python_version < "4" \ - --hash=sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a \ - --hash=sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58 -sphinxcontrib-devhelp==1.0.2 ; python_full_version >= "3.7.9" and python_version < "4" \ +sphinx-design==0.5.0 ; python_version >= "3.8" \ + --hash=sha256:1af1267b4cea2eedd6724614f19dcc88fe2e15aff65d06b2f6252cee9c4f4c1e \ + --hash=sha256:e8e513acea6f92d15c6de3b34e954458f245b8e761b45b63950f65373352ab00 +sphinx-rtd-theme==2.0.0 ; python_version >= "3.8" \ + --hash=sha256:bd5d7b80622406762073a04ef8fadc5f9151261563d47027de09910ce03afe6b \ + --hash=sha256:ec93d0856dc280cf3aee9a4c9807c60e027c7f7b461b77aeffed682e68f0e586 +sphinx==7.1.2 ; python_version >= "3.8" \ + --hash=sha256:780f4d32f1d7d1126576e0e5ecc19dc32ab76cd24e950228dcf7b1f6d3d9e22f \ + --hash=sha256:d170a81825b2fcacb6dfd5a0d7f578a053e45d3f2b153fecc948c37344eb4cbe +sphinxcontrib-applehelp==1.0.4 ; python_version >= "3.8" \ + --hash=sha256:29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228 \ + --hash=sha256:828f867945bbe39817c210a1abfd1bc4895c8b73fcaade56d45357a348a07d7e +sphinxcontrib-devhelp==1.0.2 ; python_version >= "3.8" \ --hash=sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e \ --hash=sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4 -sphinxcontrib-htmlhelp==2.0.0 ; python_full_version >= "3.7.9" and python_version < "4" \ - --hash=sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07 \ - --hash=sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2 -sphinxcontrib-jquery==4.1 ; python_full_version >= "3.7.9" and python_version < "4" \ +sphinxcontrib-htmlhelp==2.0.1 ; python_version >= "3.8" \ + --hash=sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff \ + --hash=sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903 +sphinxcontrib-jquery==4.1 ; python_version >= "3.8" \ --hash=sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a \ --hash=sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae -sphinxcontrib-jsmath==1.0.1 ; python_full_version >= "3.7.9" and python_version < "4" \ +sphinxcontrib-jsmath==1.0.1 ; python_version >= "3.8" \ --hash=sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178 \ --hash=sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8 -sphinxcontrib-qthelp==1.0.3 ; python_full_version >= "3.7.9" and python_version < "4" \ +sphinxcontrib-qthelp==1.0.3 ; python_version >= "3.8" \ --hash=sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72 \ --hash=sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6 -sphinxcontrib-serializinghtml==1.1.5 ; python_full_version >= "3.7.9" and python_version < "4" \ +sphinxcontrib-serializinghtml==1.1.5 ; python_version >= "3.8" \ --hash=sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd \ --hash=sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952 -typeguard==3.0.2 ; python_full_version >= "3.7.9" and python_version < "4" \ - --hash=sha256:bbe993854385284ab42fd5bd3bee6f6556577ce8b50696d6cb956d704f286c8e \ - --hash=sha256:fee5297fdb28f8e9efcb8142b5ee219e02375509cd77ea9d270b5af826358d5a -typing-extensions==4.7.1 ; python_full_version >= "3.7.9" and python_version < "3.11" \ - --hash=sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36 \ - --hash=sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2 -urllib3==2.0.4 ; python_full_version >= "3.7.9" and python_version < "4" \ - --hash=sha256:8d22f86aae8ef5e410d4f539fde9ce6b2113a001bb4d189e0aed70642d602b11 \ - --hash=sha256:de7df1803967d2c2a98e4b11bb7d6bd9210474c46e8a0401514e3a42a75ebde4 -zipp==3.15.0 ; python_full_version >= "3.7.9" and python_version < "3.10" \ - --hash=sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b \ - --hash=sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556 +typing-extensions==4.8.0 ; python_version < "3.11" and python_version >= "3.8" \ + --hash=sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0 \ + --hash=sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef +urllib3==2.1.0 ; python_version >= "3.8" \ + --hash=sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3 \ + --hash=sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54 +zipp==3.17.0 ; python_version < "3.10" and python_version >= "3.8" \ + --hash=sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31 \ + --hash=sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0 diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst new file mode 100644 index 00000000..9f448a2b --- /dev/null +++ b/docs/source/changelog.rst @@ -0,0 +1,2 @@ +.. include:: ../../CHANGELOG.md + :parser: myst_parser.sphinx_ diff --git a/docs/source/conf.py b/docs/source/conf.py index b3b3bfc9..0429f31c 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -12,13 +12,16 @@ # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) import importlib.metadata +import os +import pathlib import re +import sys + from docutils import nodes +sys.path.insert(0, os.path.abspath("./ext")) + # -- Project information ----------------------------------------------------- @@ -45,15 +48,25 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ + # Built-in extensions "sphinx.ext.autodoc", "sphinx.ext.intersphinx", "sphinx.ext.napoleon", + # 3rd party extensions + "myst_parser", + "sphinx_design", + # Local extensions + "examples", ] autodoc_member_order = "groupwise" autodoc_typehints = "description" autodoc_typehints_description_target = "all" +example_server_dir = ( + pathlib.Path(__file__).parent.parent.parent / "examples" / "servers" +) + intersphinx_mapping = { "python": ("https://docs.python.org/3/", None), } diff --git a/docs/source/examples/code-actions.rst b/docs/source/examples/code-actions.rst new file mode 100644 index 00000000..3a6b729c --- /dev/null +++ b/docs/source/examples/code-actions.rst @@ -0,0 +1,6 @@ +Code Actions +============ + +.. example-server:: code_actions.py + :start-at: import re + diff --git a/docs/source/examples/code-lens.rst b/docs/source/examples/code-lens.rst new file mode 100644 index 00000000..074362c0 --- /dev/null +++ b/docs/source/examples/code-lens.rst @@ -0,0 +1,7 @@ +Code Lens +========= + +.. example-server:: code_lens.py + :start-at: import logging + + diff --git a/docs/source/examples/colors.rst b/docs/source/examples/colors.rst new file mode 100644 index 00000000..30e056f7 --- /dev/null +++ b/docs/source/examples/colors.rst @@ -0,0 +1,9 @@ +Document Color +============== + +.. example-server:: colors.py + :start-at: import logging + + + + diff --git a/docs/source/examples/formatting.rst b/docs/source/examples/formatting.rst new file mode 100644 index 00000000..82b715a2 --- /dev/null +++ b/docs/source/examples/formatting.rst @@ -0,0 +1,10 @@ +Document Formatting +=================== + +.. example-server:: formatting.py + :start-at: import logging + + + + + diff --git a/docs/source/examples/goto.rst b/docs/source/examples/goto.rst new file mode 100644 index 00000000..81dfdf1d --- /dev/null +++ b/docs/source/examples/goto.rst @@ -0,0 +1,12 @@ +Goto "X" +======== + +.. example-server:: goto.py + :start-at: import logging + + + + + + + diff --git a/docs/source/examples/hover.rst b/docs/source/examples/hover.rst new file mode 100644 index 00000000..0e535e97 --- /dev/null +++ b/docs/source/examples/hover.rst @@ -0,0 +1,12 @@ +Hover +===== + +.. example-server:: hover.py + :start-at: import logging + + + + + + + diff --git a/docs/source/examples/inlay-hints.rst b/docs/source/examples/inlay-hints.rst new file mode 100644 index 00000000..9b7389a5 --- /dev/null +++ b/docs/source/examples/inlay-hints.rst @@ -0,0 +1,13 @@ +Inlay Hints +=========== + +.. example-server:: inlay_hints.py + :start-at: import re + + + + + + + + diff --git a/docs/source/examples/json-server.rst b/docs/source/examples/json-server.rst new file mode 100644 index 00000000..1c2f4835 --- /dev/null +++ b/docs/source/examples/json-server.rst @@ -0,0 +1,13 @@ +JSON Server +=========== + +.. example-server:: json_server.py + :start-at: import argparse + + + + + + + + diff --git a/docs/source/examples/publish-diagnostics.rst b/docs/source/examples/publish-diagnostics.rst new file mode 100644 index 00000000..81799cea --- /dev/null +++ b/docs/source/examples/publish-diagnostics.rst @@ -0,0 +1,13 @@ +Publish Diagnostics +=================== + +.. example-server:: publish_diagnostics.py + :start-at: import logging + + + + + + + + diff --git a/docs/source/examples/pull-diagnostics.rst b/docs/source/examples/pull-diagnostics.rst new file mode 100644 index 00000000..32a426c1 --- /dev/null +++ b/docs/source/examples/pull-diagnostics.rst @@ -0,0 +1,13 @@ +Pull Diagnostics +================ + +.. example-server:: pull_diagnostics.py + :start-at: import logging + + + + + + + + diff --git a/docs/source/examples/rename.rst b/docs/source/examples/rename.rst new file mode 100644 index 00000000..e0665117 --- /dev/null +++ b/docs/source/examples/rename.rst @@ -0,0 +1,13 @@ +Rename +====== + +.. example-server:: rename.py + :start-at: import logging + + + + + + + + diff --git a/docs/source/ext/examples.py b/docs/source/ext/examples.py new file mode 100644 index 00000000..39da94ec --- /dev/null +++ b/docs/source/ext/examples.py @@ -0,0 +1,85 @@ +"""Documentation for the example servers""" + +from __future__ import annotations + +import importlib.util as imutil +import os +import pathlib +import typing + +from docutils.parsers.rst import directives +from sphinx.util.docutils import SphinxDirective +from sphinx.util.logging import getLogger + +if typing.TYPE_CHECKING: + from sphinx.application import Sphinx + +logger = getLogger(__name__) + + +class ExampleServerDirective(SphinxDirective): + """Automate the process of documenting example servers. + + Currently, this doesn't do *that* much, it + + - Inserts the code using a ``.. literalinclude::`` directive. + - Extracts the server module's docstring and inserts it into the page as nicely + rendered text. + + But perhaps we can do something more interesting in the future! + """ + + required_arguments = 1 + option_spec = { + "start-at": directives.unchanged, + } + + def get_docstring(self, filename: pathlib.Path): + """Given the filepath to a module, return its docstring.""" + + base = filename.stem + spec = imutil.spec_from_file_location(f"examples.{base}", filename) + + try: + module = imutil.module_from_spec(spec) + spec.loader.exec_module(module) + except Exception: + logger.exception("Unable to import example server") + return [] + + if (docstring := module.__doc__) is not None: + return docstring.splitlines() + + return [] + + def run(self): + server_dir = self.config.example_server_dir + name = self.arguments[0] + + if not (filename := pathlib.Path(server_dir, name)).exists(): + raise RuntimeError(f"Unable to find example server: {filename}") + + # Tell Sphinx to rebuild a document if this file changes + self.env.note_dependency(str(filename)) + + # An "absolute" path given to `literalinclude` is actually relative to the + # projects srcdir + relpath = os.path.relpath(str(filename), start=str(self.env.app.srcdir)) + content = [ + f".. literalinclude:: /{relpath}", + " :language: python", + ] + + if (start_at := self.options.get("start-at")) is not None: + content.append(f" :start-at: {start_at}") + + # Confusingly, these are processed in reverse order... + self.state_machine.insert_input(content, "") + self.state_machine.insert_input(self.get_docstring(filename), str(filename)) + + return [] + + +def setup(app: Sphinx): + app.add_config_value("example_server_dir", "", rebuild="env") + app.add_directive("example-server", ExampleServerDirective) diff --git a/docs/source/getting-started.rst b/docs/source/getting-started.rst new file mode 100644 index 00000000..e5d91f92 --- /dev/null +++ b/docs/source/getting-started.rst @@ -0,0 +1,113 @@ +Getting Started +=============== + +.. _example-servers: + +Example Servers +--------------- + +.. toctree:: + :hidden: + :glob: + + examples/* + +.. tip:: + + If you use VSCode, we recommend you try these servers out in the :ref:`pygls-playground ` extension + +Each of the following example servers are focused on implementing a particular subset of the Language Server Protocol. + +.. grid:: 1 2 2 4 + :gutter: 2 + + .. grid-item-card:: Code Actions + :link: /examples/code-actions + :link-type: doc + :text-align: center + + :octicon:`light-bulb` + + .. grid-item-card:: Code Lens + :link: /examples/code-lens + :link-type: doc + :text-align: center + + :octicon:`eye` + + .. grid-item-card:: Colors + :link: /examples/colors + :link-type: doc + :text-align: center + + :octicon:`paintbrush` + + .. grid-item-card:: Formatting + :link: /examples/formatting + :link-type: doc + :text-align: center + + :octicon:`typography` + + .. grid-item-card:: Goto "X" + :link: /examples/goto + :link-type: doc + :text-align: center + + :octicon:`search` + + .. grid-item-card:: Hover + :link: /examples/hover + :link-type: doc + :text-align: center + + :octicon:`book` + + .. grid-item-card:: Inlay Hints + :link: /examples/inlay-hints + :link-type: doc + :text-align: center + + :octicon:`info` + + .. grid-item-card:: Publish Diagnostics + :link: /examples/publish-diagnostics + :link-type: doc + :text-align: center + + :octicon:`alert` + + .. grid-item-card:: Pull Diagnostics + :link: /examples/pull-diagnostics + :link-type: doc + :text-align: center + + :octicon:`alert` + + .. grid-item-card:: Rename + :link: /examples/rename + :link-type: doc + :text-align: center + + :octicon:`pencil` + +These servers are dedicated to demonstrating features of *pygls* itself + +.. grid:: 1 2 2 4 + :gutter: 2 + + .. grid-item-card:: JSON Server + :link: /examples/json-server + :link-type: doc + :text-align: center + + :octicon:`code` + + +Tutorial +-------- + +.. note:: + + Coming soon\ :sup:`TM` + diff --git a/docs/source/history.rst b/docs/source/history.rst new file mode 100644 index 00000000..fdd88a1e --- /dev/null +++ b/docs/source/history.rst @@ -0,0 +1,2 @@ +.. include:: ../../HISTORY.md + :parser: myst_parser.sphinx_ diff --git a/docs/source/howto.rst b/docs/source/howto.rst new file mode 100644 index 00000000..dd539571 --- /dev/null +++ b/docs/source/howto.rst @@ -0,0 +1,9 @@ +How To Guides +============= + +.. toctree:: + :maxdepth: 1 + + Handle Invalid Data + Migrate to v1 + Use the pygls-playground diff --git a/docs/source/howto/handle-invalid-data.rst b/docs/source/howto/handle-invalid-data.rst new file mode 100644 index 00000000..a1d89a50 --- /dev/null +++ b/docs/source/howto/handle-invalid-data.rst @@ -0,0 +1,155 @@ +How To Handle Invalid Data +========================== + +.. highlight:: python + +By default, servers written with *pygls* are quite pedantic and will complain loudly when given data they consider to be invalid + +.. dropdown:: Example Data + :open: + + .. code-block:: json + + { + "jsonrpc": "2.0", + "id": 10, + "method": "textDocument/codeAction", + "params": { + "textDocument": { + "uri": "file:///path/to/file.txt" + }, + "range": { + "start": { "line": 7, "character": 14 }, + "end": { "line": 7, "character": 14 } + }, + "context": { + "diagnostics": [ + { + "range": { + "start": { + "line": null, // Invalid! + "character": 0 + }, + "end":{ + "line": 1, + "character": 65535 + } + }, + "message": "an example message", + "severity": 2, + "source": "example" + } + ] + } + } + } + +.. dropdown:: Example Error + + :: + + ERROR:pygls.protocol:Error receiving data + + Exception Group Traceback (most recent call last): + | ... + | cattrs.errors.ClassValidationError: While structuring TextDocumentCodeActionRequest (1 sub-exception) + +-+---------------- 1 ---------------- + | Exception Group Traceback (most recent call last): + | ... + | cattrs.errors.ClassValidationError: While structuring CodeActionParams (1 sub-exception) + | Structuring class TextDocumentCodeActionRequest @ attribute params + +-+---------------- 1 ---------------- + | Exception Group Traceback (most recent call last): + | ... + | cattrs.errors.ClassValidationError: While structuring CodeActionContext (1 sub-exception) + | Structuring class CodeActionParams @ attribute context + +-+---------------- 1 ---------------- + | Exception Group Traceback (most recent call last): + | ... + | cattrs.errors.IterableValidationError: While structuring typing.List[lsprotocol.types.Diagnostic] (2 sub-exceptions) + | Structuring class CodeActionContext @ attribute diagnostics + +-+---------------- 1 ---------------- + | Exception Group Traceback (most recent call last): + | ... + | cattrs.errors.ClassValidationError: While structuring Diagnostic (1 sub-exception) + | Structuring typing.List[lsprotocol.types.Diagnostic] @ index 0 + +-+---------------- 1 ---------------- + | Exception Group Traceback (most recent call last): + | ... + | cattrs.errors.ClassValidationError: While structuring Range (2 sub-exceptions) + | Structuring class Diagnostic @ attribute range + +-+---------------- 1 ---------------- + | Exception Group Traceback (most recent call last): + | ... + | cattrs.errors.ClassValidationError: While structuring Position (1 sub-exception) + | Structuring class Range @ attribute start + +-+---------------- 1 ---------------- + | Traceback (most recent call last): + | ... + | TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType' + | Structuring class Position @ attribute line + +------------------------------------ + + The above exception was the direct cause of the following exception: + + Traceback (most recent call last): + ... + pygls.exceptions.JsonRpcInvalidParams: Invalid Params + +This is due to the fact ``pygls`` relies on `lsprotocol `__ for all of its type definitions. +``lsprotocol`` in turn builds on `attrs `__ and `cattrs `__ to provide the serialisation and deserialisation of types to/from JSON. + +This is done through a ``converter`` object:: + + >>> from lsprotocol.types import Position + >>> from pygls.protocol import default_converter + + >>> converter = default_converter() + >>> p = converter.structure({"line": 1, "character": 2}, Position) + >>> p.line + 1 + >>> p.character + 2 + +Each language server receives a :func:`~pygls.protocol.default_converter` which is derived from the converter provided by ``lsprotocol``. +This means it will follow the Language Server Protocol exactly. + +Structure Hooks +--------------- + +By registering your own `structure hooks `__ you can take control over how malformed types should be handled. + +Using the example data above, let's define a custom converter which includes a hook to silently ignore any diagnostics that are rejected when parsing the ``context`` field of a :lsp:`textDocument/codeAction` request. + +.. code-block:: python + + from lsprotocol import types + from pygls.protocol import default_converter + + def my_converter_factory(): + converter = default_converter() + + def code_action_context_hook(obj, type_): + diagnostics = [] + raw_diagnostics = obj.get("diagnostics", []) or [] + + for d in raw_diagnostics: + try: + diagnostics.append(converter.structure(d, Diagnostic)) + except Exception: + pass + + return CodeActionContext(diagnostics=diagnostics) + + converter.register_structure_hook(CodeActionContext, code_action_context_hook) + + return converter + +To use this custom converter with a language server set ``my_converter_factory`` as the server's ``converter_factory``. + +.. code-block:: python + + server = LanguageServer( + name="my-language-server", + version="v1.0", + converter_factory=my_converter_factory, + ) diff --git a/docs/source/pages/migrating-to-v1.rst b/docs/source/howto/migrate-to-v1.rst similarity index 99% rename from docs/source/pages/migrating-to-v1.rst rename to docs/source/howto/migrate-to-v1.rst index 527a810d..8833fbe0 100644 --- a/docs/source/pages/migrating-to-v1.rst +++ b/docs/source/howto/migrate-to-v1.rst @@ -1,5 +1,5 @@ -Migrating to v1.0 -================= +How To Migrate to v1.0 +====================== The most notable change of the ``v1.0`` release of ``pygls`` is the removal of its hand written LSP type and method definitions in favour of relying on the types provided by the `lsprotocol`_ library which are automatically generated from the LSP specification. As as side effect this has also meant the removal of `pydantic`_ as a dependency, since ``lsprotocol`` uses `attrs`_ and `cattrs`_ for serialisation and validation. diff --git a/docs/source/howto/use-the-pygls-playground.rst b/docs/source/howto/use-the-pygls-playground.rst new file mode 100644 index 00000000..fd67009e --- /dev/null +++ b/docs/source/howto/use-the-pygls-playground.rst @@ -0,0 +1,204 @@ +.. _howto-use-pygls-playground: + +How To Use the ``pygls-playground`` Extension +============================================= + +.. figure:: https://user-images.githubusercontent.com/2675694/260591942-b7001a7b-3081-439d-b702-5f8a489856db.png + :target: https://user-images.githubusercontent.com/2675694/260591942-b7001a7b-3081-439d-b702-5f8a489856db.png + :align: center + + Screenshot of the pygls-playground extension in action + +The ``pygls-playground`` VSCode extension has two main goals. + +- Provide an environment in which you can easily experiment with the pygls framework by trying some of our example servers - or by writing your own + +- Provide a minimal example of what it takes to integrate a pygls powered language server into VSCode. + +.. tip:: + + For a more complete example of a VSCode client, check out Microsoft's `template extension for Python tools `__. + +Setup +----- + +.. highlight:: none + +Since the ``pygls-playground`` is not a general purpose extension it is distributed as a `local workspace `__ extension. +This does mean, you will have to build the extension yourself before you can use it. + +.. _howto-use-pygls-playground-install-pygls: + +Install *pygls* +^^^^^^^^^^^^^^^ + +#. If you have not done so already, clone the `pygls `__ GitHub repository:: + + $ git clone https://github.com/openlawlibrary/pygls + +#. Open a terminal in the repository's root directory and create a virtual environment:: + + $ python3 -m venv env + +#. Activate the environment:: + + $ source ./env/bin/activate + + +#. Install `pygls`:: + + (env) $ python -m pip install -e . + + +Compile the Extension +^^^^^^^^^^^^^^^^^^^^^ + +.. note:: + + This step requires you to have `Node JS v18+ `__ installed. + +Open terminal in the ``.vscode/extensions/pygls-playground/`` folder and execute following commands + +#. Install dependencies:: + + .vscode/extensions/pygls-playground/ $ npm install --no-save + +#. Compile the extension:: + + .vscode/extensions/pygls-playground/ $ npm run compile + + Alternatively you can run ``npm run watch`` if you are going to be making changes to the extension itself. + +Install the Extension +^^^^^^^^^^^^^^^^^^^^^ + +.. important:: + + In order for VSCode to recognise ``pygls-playground`` as a valid extension, you need to complete the build step above **before** opening the *pygls* repository inside VSCode. + + If you did open VSCode before building the extension, you will have to run the ``Developer: Reload Window`` command through the command palette (:kbd:`Ctrl+Shift+P`) + +The following steps will depend on your VSCode version + +.. tab-set:: + + .. tab-item:: VSCode v1.89+ + + #. Open your copy of the *pygls* repository in VSCode and goto the :guilabel:`Extensions` tab (:kbd:`Ctrl+Shift+X`) + + #. Find the ``pygls-playground`` extension in the :guilabel:`Recommended` section (not by searching in the marketplace!) and click the :guilabel:`Install Workspace Extension` button. + + **If the button only says "Install", you have not found the right version of the extension** + + #. Make sure that VSCode is using the virtual environment you created during the :ref:`howto-use-pygls-playground-install-pygls` step. + + If necessary, the :guilabel:`Python: Select Interpreter` command can be used to pick a different environment. + + Alternatively, you can set the ``pygls.server.pythonPath`` option in the ``.vscode/settings.json`` file in the repository + + .. tab-item:: VSCode v1.88 and older + + #. Open ``.vscode/extensions/vscode-playground/`` directory in VS Code + + #. The ``pygls-playground`` relies on the `Python extension for VSCode`_ for choosing the appropriate Python environment in which to run the example language servers. + + If you haven't already, you will need to install it and reload the window. + + #. Open the Run and Debug view (:kbd:`Ctrl+Shift+D`) + + #. Select :guilabel:`Launch Client` and press :kbd:`F5`, this will open a second VSCode window with the ``pygls-playground`` extension enabled. + + #. You will need to make sure that VSCode is using the virtual environment you created during the :ref:`howto-use-pygls-playground-install-pygls` step. + If necessary, the :guilabel:`Python: Select Interpreter` command can be used to pick a different environment. + + Alternatively, you can set the ``pygls.server.pythonPath`` option in the ``.vscode/settings.json`` file + + +Basic Usage +----------- + +By default, the ``pygls-playground`` extension is configured to run the example ``code_actions.py`` server which you can find in the ``examples/servers`` folder of the *pygls* repository. + +Try opening the ``examples/servers/workspace/sums.txt`` file. + +The playground will automatically start the language server in the background, after a few seconds you should be able to put your cursor on one of the equations and see a code action lightbulb appear. + +Open the ``examples/servers/code_actions.py`` file, make a change to the code and save the file. +The playground will detect that the file was changed and automatically restart the server to apply your changes. + +Accessing the Server's Logs +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can access the logs for both the client and server in the :guilabel:`pygls` Output Channel + +- Run :guilabel:`Output: Show Output Channels...` from the command palette (:kbd:`Ctrl+Shift+P`) +- Select :guilabel:`pygls` from the list + +The :guilabel:`Developer: Set Log Level...` command can be used to adjust the verbosity of the log messages. + +Calling a Custom Command +^^^^^^^^^^^^^^^^^^^^^^^^ + +.. note:: + + The ``pygls-playground`` can only call custom commands that do not require any arguments + +To call a custom :meth:`@server.command ` + +- Run :guilabel:`pygls: Execute command` via the command palette (:kbd:`Ctrl+Shift+P`) + +- Select your command from the list of options + +Configuration +------------- + +The settings defined in the ``.vscode/settings.json`` can control most aspects of the playground's behavior. + +Selecting a server +^^^^^^^^^^^^^^^^^^ + +.. tip:: + + See :ref:`example-servers` for details on the available servers and which files they work best with. + +To select a different server, change the ``pygls.server.launchScript`` setting to the name of the server you wish to run. +This should be a path relative to the ``pygls.server.cwd`` setting. + +If everything works as expected, the ``pygls-playground`` extension will default to using the ``examples/servers/`` folder as its working directory. + +.. tip:: + + Cryptic ``Error: spawn /.../python ENOENT`` messages are often due to the extension using an incorrect working directory. + +Debugging a server +^^^^^^^^^^^^^^^^^^ + +To debug the currently active language server set the ``pygls.server.debug`` option to ``true``. +The server will restart and the debugger connect automatically. + +You can control the host and port that the debugger uses through the ``pygls.server.debugHost`` and ``pygls.server.debugPort`` options. + +Selecting documents +^^^^^^^^^^^^^^^^^^^ + +Language servers typically specialise in a relatively small number of file types, so a client will only ask a server about documents it thinks the server is capable of handling. + +Most of our example servers are designed to work with ``plaintext``. +To use a server with different set of documents you can modify the ``pygls.client.documentSelector`` option + +For example to use a server with ``json`` files + +.. code-block:: json + + "pygls.client.documentSelector": [ + { + "scheme": "file", + "language": "json" + }, + ], + +You can find the full list of known language identifiers `here `__. + +See the `LSP Specification `__ for details on all the available options that can be passed to the ``pygls.client.documentSelector`` option. + +.. _Python extension for VSCode: https://marketplace.visualstudio.com/items?itemName=ms-python.python diff --git a/docs/source/implementations.rst b/docs/source/implementations.rst new file mode 100644 index 00000000..54a2ef23 --- /dev/null +++ b/docs/source/implementations.rst @@ -0,0 +1,2 @@ +.. include:: ../../Implementations.md + :parser: myst_parser.sphinx_ diff --git a/docs/source/index.rst b/docs/source/index.rst index 3fc264cc..e706215c 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,49 +1,66 @@ -.. pygls documentation master file, created by - sphinx-quickstart on Sun Nov 25 16:16:27 2018. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. *pygls* ======= `pygls`_ (pronounced like “pie glass”) is a generic implementation of the `Language Server Protocol`_ written in the Python programming language. It -allows you to write your own `language server`_ in just a few lines of code. +allows you to write your own `language server`_ in just a few lines of code -Features --------- +.. literalinclude:: ../../examples/hello-world/main.py + :language: python -- cross-platform support -- TCP/IP and STDIO communication -- runs in asyncio event loop -- register LSP features and custom commands as: +*pygls* supports - - asynchronous functions (coroutines) - - synchronous functions - - functions that will be executed in separate thread +- Python 3.8+ on Windows, MacOS and Linux +- STDIO, TCP/IP and WEBSOCKET communication +- Both sync and async styles of programming +- Running code in background threads +- Automatic text and notebook document syncronisation -- thread management -- in-memory workspace with *full* and *incremental* document updates -- type-checking -- good test coverage +.. toctree:: + :hidden: + :caption: User Guide -Python Versions ---------------- + getting-started + user-guide + How To + reference -*pygls* works with Python 3.8+. +.. toctree:: + :hidden: + :caption: About -User Guide ----------- + implementations + history + changelog -.. toctree:: - :maxdepth: 2 - - pages/getting_started - pages/tutorial - pages/user-guide - pages/testing - pages/migrating-to-v1 - pages/reference + +The documentation is divided up into the following sections + +.. grid:: 1 2 2 2 + :gutter: 2 + + .. grid-item-card:: Getting Started + :link: /getting-started + :link-type: doc + :text-align: center + + First steps with *pygls*. + + .. grid-item-card:: How To Guides + :link: /howto + :link-type: doc + :text-align: center + + Short, focused articles on how to acheive a particular outcome + + .. grid-item-card:: API Reference + :link: /reference + :link-type: doc + :columns: 12 + :text-align: center + + Comprehensive, detailed documentation on all of the features provided by *pygls*. .. _Language Server Protocol: https://microsoft.github.io/language-server-protocol/specification diff --git a/docs/source/pages/getting_started.rst b/docs/source/pages/getting_started.rst deleted file mode 100644 index e73d20fa..00000000 --- a/docs/source/pages/getting_started.rst +++ /dev/null @@ -1,94 +0,0 @@ -Getting Started -=============== - -This document explains how to install *pygls* and get started writing language -servers that are based on it. - -.. note:: - - Before going any further, if you are not familiar with *language servers* - and *Language Server Protocol*, we recommend reading following articles: - - - `Language Server Protocol Overview `_ - - `Language Server Protocol Specification `_ - - `Language Server Protocol SDKs `_ - - -Installation ------------- - -To get the latest release from *PyPI*, simply run: - -.. code:: console - - pip install pygls - -Alternatively, *pygls* source code can be downloaded from our `GitHub`_ page and installed with following command: - -.. code:: console - - pip install git+https://github.com/openlawlibrary/pygls - -Quick Start ------------ - -Spin the Server Up -~~~~~~~~~~~~~~~~~~ - -*pygls* is a language server that can be started without writing any additional -code: - -.. code:: python - - from pygls.server import LanguageServer - - server = LanguageServer('example-server', 'v0.1') - - server.start_tcp('127.0.0.1', 8080) - -After running the code above, server will start listening for incoming -``Json RPC`` requests on ``http://127.0.0.1:8080``. - -Register Features and Commands -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -*pygls* comes with an API for registering additional features like -``code completion``, ``find all references``, ``go to definition``, etc. - -.. code:: python - - @server.feature(TEXT_DOCUMENT_COMPLETION, CompletionOptions(trigger_characters=[','])) - def completions(params: CompletionParams): - """Returns completion items.""" - return CompletionList( - is_incomplete=False, - items=[ - CompletionItem(label='Item1'), - CompletionItem(label='Item2'), - CompletionItem(label='Item3'), - ] - ) - -… as well as custom commands: - -.. code:: python - - @server.command('myVerySpecialCommandName') - def cmd_return_hello_world(ls, *args): - return 'Hello World!' - -See the :mod:`lsprotocol.types` module for the complete and canonical list of available features. - -Tutorial --------- - -We recommend completing the :ref:`tutorial `, especially if you -haven't worked with language servers before. - -User Guide ----------- - -To reveal the full potential of *pygls* (``thread management``, ``coroutines``, -``multi-root workspace``, ``TCP/STDIO communication``, etc.) keep reading. - -.. _GitHub: https://github.com/openlawlibrary/pygls diff --git a/docs/source/pages/tutorial.rst b/docs/source/pages/tutorial.rst deleted file mode 100644 index 6db7f6c2..00000000 --- a/docs/source/pages/tutorial.rst +++ /dev/null @@ -1,207 +0,0 @@ -.. _tutorial: - -Tutorial -======== - -In order to help you with using *pygls* in VSCode, we have created the `vscode-playground`_ extension. - -.. note:: - - This extension is meant to provide an environment in which you can easily experiment with a *pygls* powered language server. - It is not necessary in order to use *pygls* with other text editors. - - If you decide you want to publish your language server on the VSCode marketplace this - `template extension `__ - from Microsoft a useful starting point. - -Prerequisites -------------- - -In order to setup and run the example VSCode extension, you need following software -installed: - -* `Visual Studio Code `_ editor -* `Python 3.8+ `_ -* `vscode-python `_ extension -* A clone of the `pygls `_ repository - -.. note:: - If you have created virtual environment, make sure that you have *pygls* installed - and `selected appropriate python interpreter `_ - for the *pygls* project. - - -Running the Example -------------------- - -For a step-by-step guide on how to setup and run the example follow `README`_. - -Hacking the Extension ---------------------- - -When you have successfully setup and run the extension, open `server.py`_ and -go through the code. - -We have implemented following capabilities: - -- ``textDocument/completion`` feature -- ``countDownBlocking`` command -- ``countDownNonBlocking`` command -- ``textDocument/didChange`` feature -- ``textDocument/didClose`` feature -- ``textDocument/didOpen`` feature -- ``showConfigurationAsync`` command -- ``showConfigurationCallback`` command -- ``showConfigurationThread`` command - -When running the extension in *debug* mode, you can set breakpoints to see -when each of above mentioned actions gets triggered. - -Visual Studio Code supports *Language Server Protocol*, which means, that every -action on the client-side, will result in sending request or notification to -the server via JSON RPC. - -Debug Code Completions -~~~~~~~~~~~~~~~~~~~~~~ - -Set a breakpoint inside ``completion`` function and go back to opened *json* -file in your editor. Now press ``ctrl + space`` (``control + space`` on mac) to -show completion list and you will hit the breakpoint. When you continue -debugging, the completion list pop-up won't show up because it was closing when -the editor lost focus. - -Similarly, you can debug any feature or command. - -Keep the breakpoint and continue to the next section. - -Blocking Command Test -~~~~~~~~~~~~~~~~~~~~~ - -In order to demonstrate you that blocking the language server will reject other -requests, we have registered a custom command which counts down 10 seconds and -sends notification messages to the client. - -1. Press **F1**, find and run ``Count down 10 seconds [Blocking]`` command. -2. Try to show *code completions* while counter is still ticking. - -Language server is **blocked**, because ``time.sleep`` is a -**blocking** operation. This is why you didn't hit the breakpoint this time. - -.. hint:: - - To make this command **non blocking**, add ``@json_server.thread()`` - decorator, like in code below: - - .. code-block:: python - - @json_server.thread() - @json_server.command(JsonLanguageServer.CMD_COUNT_DOWN_BLOCKING) - def count_down_10_seconds_blocking(ls, *args): - # Omitted - - *pygls* uses a **thread pool** to execute functions that are marked with - a ``thread`` decorator. - - -Non-Blocking Command Test -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Python 3.4 introduced *asyncio* module which allows us to use asynchronous -functions (aka *coroutines*) and do `cooperative multitasking`_. Using the -`await` keyword inside your coroutine will give back control to the -scheduler and won't block the main thread. - -1. Press **F1** and run the ``Count down 10 seconds [Non Blocking]`` command. -2. Try to show *code completions* while counter is still ticking. - -Bingo! We hit the breakpoint! What just happened? - -The language server was **not blocked** because we used ``asyncio.sleep`` this -time. The language server was executing *just* in the *main* thread. - - -Text Document Operations -~~~~~~~~~~~~~~~~~~~~~~~~ - -Opening and closing a JSON file will display appropriate notification message -in the bottom right corner of the window and the file content will be -validated. Validation will be performed on content changes, as well. - -Show Configuration Data -~~~~~~~~~~~~~~~~~~~~~~~ - -There are *three* ways for getting configuration section from the client -settings. - -.. note:: - - *pygls*' built-in coroutines are suffixed with *async* word, which means that - you have to use the *await* keyword in order to get the result (instead of - *asyncio.Future* object). - -- **Get the configuration inside a coroutine** - -.. code-block:: python - - config = await ls.get_configuration_async(ConfigurationParams([ - ConfigurationItem('', JsonLanguageServer.CONFIGURATION_SECTION) - ])) - -- **Get the configuration inside a normal function** - -We already saw that we *don't* want to block the main thread. Sending the -configuration request to the client will result with the response from it, but -we don't know when. You have to pass *callback* function which will be -triggered once response from the client is received. - -.. code-block:: python - - def _config_callback(config): - try: - example_config = config[0].exampleConfiguration - - ls.show_message( - f'jsonServer.exampleConfiguration value: {example_config}' - ) - - except Exception as e: - ls.show_message_log(f'Error ocurred: {e}') - - ls.get_configuration(ConfigurationParams([ - ConfigurationItem('', JsonLanguageServer.CONFIGURATION_SECTION) - ]), _config_callback) - -As you can see, the above code is hard to read. - -- **Get the configuration inside a threaded function** - -Blocking operations such as ``future.result(1)`` should not be used inside -normal functions, but to increase the code readability, you can add the -*thread* decorator to your function to use *pygls*' *thread pool*. - -.. code-block:: python - - @json_server.thread() - @json_server.command(JsonLanguageServer.CMD_SHOW_CONFIGURATION_THREAD) - def show_configuration_thread(ls: JsonLanguageServer, *args): - """Gets exampleConfiguration from the client settings using a thread pool.""" - try: - config = ls.get_configuration(ConfigurationParams([ - ConfigurationItem('', JsonLanguageServer.CONFIGURATION_SECTION) - ])).result(2) - - # ... - -This way you won't block the main thread. *pygls* will start a new thread when -executing the function. - -Modify the Example -~~~~~~~~~~~~~~~~~~ - -We encourage you to continue to :ref:`user guide ` and -modify this example. - -.. _vscode-playground: https://github.com/openlawlibrary/pygls/blob/main/examples/vscode-playground -.. _README: https://github.com/openlawlibrary/pygls/blob/main/examples/vscode-playground/README.md -.. _server.py: https://github.com/openlawlibrary/pygls/blob/main/examples/servers/json_server.py -.. _cooperative multitasking: https://en.wikipedia.org/wiki/Cooperative_multitasking diff --git a/docs/source/pages/reference.rst b/docs/source/reference.rst similarity index 80% rename from docs/source/pages/reference.rst rename to docs/source/reference.rst index 2b0aa56b..04312347 100644 --- a/docs/source/pages/reference.rst +++ b/docs/source/reference.rst @@ -2,7 +2,7 @@ API Reference ============= .. toctree:: + :maxdepth: 1 :glob: - :maxdepth: 2 reference/* diff --git a/docs/source/pages/reference/clients.rst b/docs/source/reference/clients.rst similarity index 100% rename from docs/source/pages/reference/clients.rst rename to docs/source/reference/clients.rst diff --git a/docs/source/pages/reference/protocol.rst b/docs/source/reference/protocol.rst similarity index 100% rename from docs/source/pages/reference/protocol.rst rename to docs/source/reference/protocol.rst diff --git a/docs/source/pages/reference/servers.rst b/docs/source/reference/servers.rst similarity index 100% rename from docs/source/pages/reference/servers.rst rename to docs/source/reference/servers.rst diff --git a/docs/source/pages/reference/types.rst b/docs/source/reference/types.rst similarity index 100% rename from docs/source/pages/reference/types.rst rename to docs/source/reference/types.rst diff --git a/docs/source/pages/reference/workspace.rst b/docs/source/reference/workspace.rst similarity index 100% rename from docs/source/pages/reference/workspace.rst rename to docs/source/reference/workspace.rst diff --git a/docs/source/tutorial.rst b/docs/source/tutorial.rst new file mode 100644 index 00000000..77fdbab0 --- /dev/null +++ b/docs/source/tutorial.rst @@ -0,0 +1,12 @@ +.. _tutorial: + +Tutorial +======== + +Here we have a tutorial + +.. toctree:: + :glob: + :maxdepth: 1 + + tutorial/* diff --git a/docs/source/tutorial/0-setup.rst b/docs/source/tutorial/0-setup.rst new file mode 100644 index 00000000..c2642e0e --- /dev/null +++ b/docs/source/tutorial/0-setup.rst @@ -0,0 +1,16 @@ +Project Setup +============= + +By the end of this stage you will have everything you need setup in order to follow the rest of this tutorial, including a simple "Hello, World" language server. + +**Required Software** + +Before continuing with the setup you need following software installed: + +* `Visual Studio Code `__ +* `Python 3.8+ `__ +* `Node JS 18+ `__ +* `Git `__ + +Your First Language Server +-------------------------- diff --git a/docs/source/pages/testing.rst b/docs/source/tutorial/y-testing.rst similarity index 100% rename from docs/source/pages/testing.rst rename to docs/source/tutorial/y-testing.rst diff --git a/docs/source/tutorial/z-next-steps.rst b/docs/source/tutorial/z-next-steps.rst new file mode 100644 index 00000000..24c599a4 --- /dev/null +++ b/docs/source/tutorial/z-next-steps.rst @@ -0,0 +1,6 @@ +Next Steps +========== + +If you decide you want to publish your language server on the VSCode marketplace this +`template extension `__ +from Microsoft a useful starting point. diff --git a/docs/source/pages/user-guide.rst b/docs/source/user-guide.rst similarity index 100% rename from docs/source/pages/user-guide.rst rename to docs/source/user-guide.rst diff --git a/examples/hello-world/main.py b/examples/hello-world/main.py index cb2c0e4d..340e5611 100644 --- a/examples/hello-world/main.py +++ b/examples/hello-world/main.py @@ -1,28 +1,25 @@ from pygls.server import LanguageServer -from lsprotocol.types import ( - TEXT_DOCUMENT_COMPLETION, - CompletionItem, - CompletionList, - CompletionParams, -) +from lsprotocol import types server = LanguageServer("example-server", "v0.1") -@server.feature(TEXT_DOCUMENT_COMPLETION) -def completions(params: CompletionParams): - items = [] +@server.feature( + types.TEXT_DOCUMENT_COMPLETION, + types.CompletionOptions(trigger_characters=["."]), +) +def completions(params: types.CompletionParams): document = server.workspace.get_document(params.text_document.uri) current_line = document.lines[params.position.line].strip() - if current_line.endswith("hello."): - items = [ - CompletionItem(label="world"), - CompletionItem(label="friend"), - ] - return CompletionList( - is_incomplete=False, - items=items, - ) + + if not current_line.endswith("hello."): + return [] + + return [ + types.CompletionItem(label="world"), + types.CompletionItem(label="friend"), + ] -server.start_io() +if __name__ == "__main__": + server.start_io() diff --git a/examples/servers/code_actions.py b/examples/servers/code_actions.py index ec0382e0..989df818 100644 --- a/examples/servers/code_actions.py +++ b/examples/servers/code_actions.py @@ -14,6 +14,16 @@ # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################ +"""This example server implements the :lsp:`textDocument/codeAction` request. + +`In VSCode `__ code actions are +typically accessed via a small lightbulb placed near the code the action will affect. +Code actions usually modify the code in some way, usually to fix an error or refactor +it. + +This server scans the document for incomplete sums e.g. ``1 + 1 =`` and returns a code +action which, when invoked will fill in the answer. +""" import re from pygls.server import LanguageServer from lsprotocol.types import ( diff --git a/examples/servers/code_lens.py b/examples/servers/code_lens.py index 7a217028..85af5687 100644 --- a/examples/servers/code_lens.py +++ b/examples/servers/code_lens.py @@ -14,6 +14,20 @@ # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################ +"""This implements the :lsp:`textDocument/codeLens` and :lsp:`codeLens/resolve` requests. + +`In VSCode `__ +a code lens is shown as "ghost text" above some line of actual code in your document. +These lenses are typically used to show some contextual information (e.g. number of +references) or provide easy access to some command (e.g. run this test). + +This server scans the document for incomplete sums e.g. ``1 + 1 =`` and returns a code +lens object which, when clicked, will call the ``codeLens.evaluateSum`` command to fill +in the answer. +Note that while we could have easily compute the ``command`` field of the code lens up +front, this example demonstrates how the ``codeLens/resolve`` can be used to defer this +computation until it is actually necessary. +""" import logging import re diff --git a/examples/servers/colors.py b/examples/servers/colors.py index 2ae6a0bc..0e6cc206 100644 --- a/examples/servers/colors.py +++ b/examples/servers/colors.py @@ -14,6 +14,35 @@ # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################ +"""This implements the :lsp:`textDocument/documentColor` and +:lsp:`textDocument/colorPresentation` requests. + +Together these methods allow you to teach a language client how to recognise and +display colors that may appear in your document. +As an example, think of the different ways you can write a color in a CSS file + +- ``black`` +- ``#000`` +- ``#000000`` +- ``rgb(0, 0, 0)`` +- ``hsl(...)`` +- etc. + +By implementing the ``textDocument/documentColor`` request you can tell the client about +all the places within a document that represent a color, and what its equivalent RGBA +value is. +`In VSCode `__ +these locations will be represented by a small colored square next to the color value. + +Some editors (like VSCode) also provide a color picker. +By implementing the ``textDocument/colorPresentation`` request, you provide the +conversion from an RGBA color value into its equivalent representation in your document's +syntax. +This will allow the user to easily choose new color values from within their text editor. + +This server implements the requests defined above for CSS's hex color code syntax +(``#000`` and ``#000000``). +""" import logging import re diff --git a/examples/servers/formatting.py b/examples/servers/formatting.py index 85a3af0b..ee7beffb 100644 --- a/examples/servers/formatting.py +++ b/examples/servers/formatting.py @@ -14,6 +14,25 @@ # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################ +"""This implements the various formatting requests from the specification + +- :lsp:`textDocument/formatting`: format the entire document. +- :lsp:`textDocument/rangeFormatting`: format just the given range within a document. +- :lsp:`textDocument/onTypeFormatting`: format the document while the user is actively + typing. + +These are typically invoked by the client when the user asks their editor to format the +document or as part of automatic triggers (e.g. format on save). +Depending on the client, the user may need to do some additional configuration to enable +some of these methods e.g. setting ``editor.formatOnType`` in VSCode to enable +``textDocument/onTypeFormatting``. + +This server implements basic formatting of Markdown style tables. + +The implementation is a little buggy in that the resulting table might not be what you +expect (fixes welcome!), but it should be enough to demonstrate the expected interaction +between client and server. +""" import logging from typing import Dict from typing import List diff --git a/examples/servers/goto.py b/examples/servers/goto.py index d2548d90..c77d5288 100644 --- a/examples/servers/goto.py +++ b/examples/servers/goto.py @@ -14,6 +14,24 @@ # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################ +"""This implements the various Goto "X" requests from the specification. + +- :lsp:`textDocument/definition` +- :lsp:`textDocument/declaration` +- :lsp:`textDocument/implementation` +- :lsp:`textDocument/typeDefinition` + +Along with the :lsp:`textDocument/references` request. + +As you will see all of these methods are essentially the same, they accept a document +uri and they return zero or more locations (even goto definition can return multiple +results!). +The only difference between them are whatever the semantic differences are between say a +definition and a declaration in your target language. + +This means the choices of what the example server below will return results for are +completely arbitrary. +""" import logging import re diff --git a/examples/servers/hover.py b/examples/servers/hover.py index c6f0e322..fee94d3d 100644 --- a/examples/servers/hover.py +++ b/examples/servers/hover.py @@ -14,6 +14,15 @@ # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################ +"""This implements the :lsp:`textDocument/hover` request. + +Typically this method will be called when the user places their mouse or cursor over a +symbol in a document, allowing you to provide documentation for the selected symbol. + +This server implements `textDocument/hover` for various datetime representations, +displaying a table how the selected date would be formatted in each of the supported +formats. +""" import logging from datetime import datetime diff --git a/examples/servers/inlay_hints.py b/examples/servers/inlay_hints.py index e9924dd7..6c143737 100644 --- a/examples/servers/inlay_hints.py +++ b/examples/servers/inlay_hints.py @@ -14,32 +14,28 @@ # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################ +"""This implements the :lsp:`textDocument/inlayHint` and :lsp:`inlayHint/resolve` +requests. + +In editors +`like VSCode `__ +inlay hints are often rendered as inline "ghost text". +They are typically used to show the types of variables and return values from functions. + +This server implements ``textDocument/inlayHint`` to scan the given document for integer +values and returns the equivalent representation of that number in binary. +While we could easily compute the inlay hint's tooltip in the same method, this example +uses the ``inlayHint/resolve`` to demonstrate how you can defer expensive computations +to when they are required. +""" import re from typing import Optional from lsprotocol import types - from pygls.server import LanguageServer NUMBER = re.compile(r"\d+") -COMMENT = re.compile(r"^#$") - - -server = LanguageServer( - name="inlay-hint-server", - version="v0.1", - notebook_document_sync=types.NotebookDocumentSyncOptions( - notebook_selector=[ - types.NotebookDocumentSyncOptionsNotebookSelectorType2( - cells=[ - types.NotebookDocumentSyncOptionsNotebookSelectorType2CellsType( - language="python" - ) - ] - ) - ] - ), -) +server = LanguageServer("inlay-hint-server", "v1") def parse_int(chars: str) -> Optional[int]: @@ -60,25 +56,6 @@ def inlay_hints(params: types.InlayHintParams): lines = document.lines[start_line : end_line + 1] for lineno, line in enumerate(lines): - match = COMMENT.match(line) - if match is not None: - nb = server.workspace.get_notebook_document(cell_uri=document_uri) - if nb is not None: - idx = 0 - for idx, cell in enumerate(nb.cells): - if cell.document == document_uri: - break - - items.append( - types.InlayHint( - label=f"notebook: {nb.uri}, cell {idx+1}", - kind=types.InlayHintKind.Type, - padding_left=False, - padding_right=True, - position=types.Position(line=lineno, character=match.end()), - ) - ) - for match in NUMBER.finditer(line): if not match: continue diff --git a/examples/servers/json_server.py b/examples/servers/json_server.py index 98905e49..c3827285 100644 --- a/examples/servers/json_server.py +++ b/examples/servers/json_server.py @@ -14,6 +14,22 @@ # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################ +"""In addition to implementing a variety of LSP methods, this larger example +demonstrates a number of pygls' capabilities including + +- Defining custom commands +- Progress updates +- Fetching configuration values from the client +- Running methods in a thread +- Async methods +- Dynamic method (un)registration +- Starting a TCP/WebSocket server. + +This is left over from a time where *pygls* tried to have a single example server to +demonstrate all of its features. +Eventually this example will be broken up in smaller, more focused examples and how to +guides. +""" import argparse import asyncio import json diff --git a/examples/servers/publish_diagnostics.py b/examples/servers/publish_diagnostics.py index b97454da..9e887dbf 100644 --- a/examples/servers/publish_diagnostics.py +++ b/examples/servers/publish_diagnostics.py @@ -14,6 +14,16 @@ # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################ +"""This implements the publish model of diagnostics. + +The original and most widely supported model of diagnostics in LSP, the publish model +allows the server to update the client whenever it is ready. +Unlike the push-model however, there is no way for the client to help the server +prioritize which documents it should be computing the diagnostics for. + +This server scans a document for sums e.g. ``1 + 2 = 3``, highlighting any that are +either missing answers (warnings) or incorrect (errors). +""" import logging import re diff --git a/examples/servers/pull_diagnostics.py b/examples/servers/pull_diagnostics.py index 0c6f1470..637f347f 100644 --- a/examples/servers/pull_diagnostics.py +++ b/examples/servers/pull_diagnostics.py @@ -14,6 +14,18 @@ # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################ +"""This implements the push-model of diagnostics. + +This is a fairly new addition to LSP (v3.17), so not all clients will support this. + +Instead of the server broadcasting updates whenever it feels like, the client explicitly +requests diagnostics for a particular document (:lsp:`textDocument/diagnostic`) or for +the entire workspace (:lsp:`workspace/diagnostic`). +This approach helps guide the server to perform work that's most relevant to the client. + +This server scans a document for sums e.g. ``1 + 2 = 3``, highlighting any that are +either missing answers (warnings) or incorrect (errors). +""" import logging import re @@ -25,8 +37,8 @@ ADDITION = re.compile(r"^\s*(\d+)\s*\+\s*(\d+)\s*=\s*(\d+)?$") -class PublishDiagnosticServer(LanguageServer): - """Language server demonstrating "push-model" diagnostics.""" +class PullDiagnosticServer(LanguageServer): + """Language server demonstrating "pull-model" diagnostics.""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -73,18 +85,18 @@ def parse(self, document: TextDocument): # logging.info("%s", self.diagnostics) -server = PublishDiagnosticServer("diagnostic-server", "v1") +server = PullDiagnosticServer("diagnostic-server", "v1") @server.feature(types.TEXT_DOCUMENT_DID_OPEN) -def did_open(ls: PublishDiagnosticServer, params: types.DidOpenTextDocumentParams): +def did_open(ls: PullDiagnosticServer, params: types.DidOpenTextDocumentParams): """Parse each document when it is opened""" doc = ls.workspace.get_text_document(params.text_document.uri) ls.parse(doc) @server.feature(types.TEXT_DOCUMENT_DID_CHANGE) -def did_change(ls: PublishDiagnosticServer, params: types.DidOpenTextDocumentParams): +def did_change(ls: PullDiagnosticServer, params: types.DidOpenTextDocumentParams): """Parse each document when it is changed""" doc = ls.workspace.get_text_document(params.text_document.uri) ls.parse(doc) @@ -99,7 +111,7 @@ def did_change(ls: PublishDiagnosticServer, params: types.DidOpenTextDocumentPar ), ) def document_diagnostic( - ls: PublishDiagnosticServer, params: types.DocumentDiagnosticParams + ls: PullDiagnosticServer, params: types.DocumentDiagnosticParams ): """Return diagnostics for the requested document""" # logging.info("%s", params) @@ -118,7 +130,7 @@ def document_diagnostic( @server.feature(types.WORKSPACE_DIAGNOSTIC) def workspace_diagnostic( - ls: PublishDiagnosticServer, params: types.WorkspaceDiagnosticParams + ls: PullDiagnosticServer, params: types.WorkspaceDiagnosticParams ): """Return diagnostics for the workspace.""" # logging.info("%s", params) diff --git a/examples/servers/rename.py b/examples/servers/rename.py index b7e34ad7..53d3961a 100644 --- a/examples/servers/rename.py +++ b/examples/servers/rename.py @@ -14,6 +14,21 @@ # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################ +"""This implements :lsp:`textDocument/rename` and :lsp:`textDocument/prepareRename` + +The ``textDocument/rename`` method should return a collection of edits the client should +perform in order to correctly rename all occurances of the given symbol. + +The ``textDocument/prepareRename`` method is used by the client to check that it +actually makes sense to rename the given symbol, giving the server chance to reject the +operation as invalid. + +.. note:: + + This server's rename implementation is no different to a naive find and replace, + a real server would have to check to make sure it only renames symbols in the + relevant scope. +""" import logging import re from typing import List diff --git a/poetry.lock b/poetry.lock index 334493c3..5397bb9c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "alabaster" @@ -504,6 +504,30 @@ files = [ attrs = ">=21.3.0" cattrs = "!=23.2.1" +[[package]] +name = "markdown-it-py" +version = "3.0.0" +description = "Python port of markdown-it. Markdown parsing, done right!" +optional = false +python-versions = ">=3.8" +files = [ + {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, + {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, +] + +[package.dependencies] +mdurl = ">=0.1,<1.0" + +[package.extras] +benchmarking = ["psutil", "pytest", "pytest-benchmark"] +code-style = ["pre-commit (>=3.0,<4.0)"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] +linkify = ["linkify-it-py (>=1,<3)"] +plugins = ["mdit-py-plugins"] +profiling = ["gprof2dot"] +rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + [[package]] name = "markupsafe" version = "2.1.3" @@ -531,16 +555,6 @@ files = [ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, @@ -573,6 +587,36 @@ files = [ {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, ] +[[package]] +name = "mdit-py-plugins" +version = "0.4.0" +description = "Collection of plugins for markdown-it-py" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mdit_py_plugins-0.4.0-py3-none-any.whl", hash = "sha256:b51b3bb70691f57f974e257e367107857a93b36f322a9e6d44ca5bf28ec2def9"}, + {file = "mdit_py_plugins-0.4.0.tar.gz", hash = "sha256:d8ab27e9aed6c38aa716819fedfde15ca275715955f8a185a8e1cf90fb1d2c1b"}, +] + +[package.dependencies] +markdown-it-py = ">=1.0.0,<4.0.0" + +[package.extras] +code-style = ["pre-commit"] +rtd = ["myst-parser", "sphinx-book-theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + +[[package]] +name = "mdurl" +version = "0.1.2" +description = "Markdown URL utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, + {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, +] + [[package]] name = "mypy" version = "1.8.0" @@ -631,6 +675,32 @@ files = [ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] +[[package]] +name = "myst-parser" +version = "2.0.0" +description = "An extended [CommonMark](https://spec.commonmark.org/) compliant parser," +optional = false +python-versions = ">=3.8" +files = [ + {file = "myst_parser-2.0.0-py3-none-any.whl", hash = "sha256:7c36344ae39c8e740dad7fdabf5aa6fc4897a813083c6cc9990044eb93656b14"}, + {file = "myst_parser-2.0.0.tar.gz", hash = "sha256:ea929a67a6a0b1683cdbe19b8d2e724cd7643f8aa3e7bb18dd65beac3483bead"}, +] + +[package.dependencies] +docutils = ">=0.16,<0.21" +jinja2 = "*" +markdown-it-py = ">=3.0,<4.0" +mdit-py-plugins = ">=0.4,<1.0" +pyyaml = "*" +sphinx = ">=6,<8" + +[package.extras] +code-style = ["pre-commit (>=3.0,<4.0)"] +linkify = ["linkify-it-py (>=2.0,<3.0)"] +rtd = ["ipython", "pydata-sphinx-theme (==v0.13.0rc4)", "sphinx-autodoc2 (>=0.4.2,<0.5.0)", "sphinx-book-theme (==1.0.0rc2)", "sphinx-copybutton", "sphinx-design2", "sphinx-pyscript", "sphinx-tippy (>=0.3.1)", "sphinx-togglebutton", "sphinxext-opengraph (>=0.8.2,<0.9.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"] +testing = ["beautifulsoup4", "coverage[toml]", "pytest (>=7,<8)", "pytest-cov", "pytest-param-files (>=0.3.4,<0.4.0)", "pytest-regressions", "sphinx-pytest"] +testing-docutils = ["pygments", "pytest (>=7,<8)", "pytest-param-files (>=0.3.4,<0.4.0)"] + [[package]] name = "outcome" version = "1.3.0.post0" @@ -815,6 +885,65 @@ files = [ {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"}, ] +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + [[package]] name = "requests" version = "2.32.0" @@ -947,6 +1076,29 @@ docs = ["sphinxcontrib-websupport"] lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-simplify", "isort", "mypy (>=0.990)", "ruff", "sphinx-lint", "types-requests"] test = ["cython", "filelock", "html5lib", "pytest (>=4.6)"] +[[package]] +name = "sphinx-design" +version = "0.5.0" +description = "A sphinx extension for designing beautiful, view size responsive web components." +optional = false +python-versions = ">=3.8" +files = [ + {file = "sphinx_design-0.5.0-py3-none-any.whl", hash = "sha256:1af1267b4cea2eedd6724614f19dcc88fe2e15aff65d06b2f6252cee9c4f4c1e"}, + {file = "sphinx_design-0.5.0.tar.gz", hash = "sha256:e8e513acea6f92d15c6de3b34e954458f245b8e761b45b63950f65373352ab00"}, +] + +[package.dependencies] +sphinx = ">=5,<8" + +[package.extras] +code-style = ["pre-commit (>=3,<4)"] +rtd = ["myst-parser (>=1,<3)"] +testing = ["myst-parser (>=1,<3)", "pytest (>=7.1,<8.0)", "pytest-cov", "pytest-regressions"] +theme-furo = ["furo (>=2023.7.0,<2023.8.0)"] +theme-pydata = ["pydata-sphinx-theme (>=0.13.0,<0.14.0)"] +theme-rtd = ["sphinx-rtd-theme (>=1.0,<2.0)"] +theme-sbt = ["sphinx-book-theme (>=1.0,<2.0)"] + [[package]] name = "sphinx-rtd-theme" version = "2.0.0" @@ -1262,4 +1414,4 @@ ws = ["websockets"] [metadata] lock-version = "2.0" python-versions = ">=3.8" -content-hash = "4dd3071d77175310842366457492874d58150b934b5b8f3ec3ef72fc0a8eb73a" +content-hash = "eec147a02d83657b94e955b2692a7bc3954fde03b8115748c73d8dea39f6f001" diff --git a/pyproject.toml b/pyproject.toml index c68da559..24e9090f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,7 +42,9 @@ pytest-asyncio = ">=0.21.0" [tool.poetry.group.docs.dependencies] # TODO `sphinx>=7.26` needs python 3.9 +myst-parser = ">=2.0" sphinx = ">=7.1.2" +sphinx-design = ">=0.5.0" sphinx-rtd-theme = ">=1.3.0" [tool.poetry.group.pyodide.dependencies]