attempt to merge sofubi/static-type-checking, albeit incompletely

This commit is contained in:
Josh Klar 2021-09-27 15:22:23 -07:00
commit 0d168a06f4
No known key found for this signature in database
GPG Key ID: A4A0C7B4E8EEE222
23 changed files with 1436 additions and 290 deletions

View File

@ -20,3 +20,7 @@ s3cmd = "*"
black = "==21.6b0" black = "==21.6b0"
flake8-quotes = "*" flake8-quotes = "*"
flake8-black = "*" flake8-black = "*"
circuitpython-stubs = "==7.0.0a6.dev195"
pyright = "*"
typing = "*"
mypy = "*"

321
Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "0a04ec24d4aef6828e4f5eefa0a7d2c312f21f2b2f18c42c7004cdbe0c02bd53" "sha256": "cee0eeba8c8dad66dccffe0935656829132f7ca928569e3aa957f278e6e92da6"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": {}, "requires": {},
@ -45,6 +45,13 @@
"index": "pypi", "index": "pypi",
"version": "==21.6b0" "version": "==21.6b0"
}, },
"circuitpython-stubs": {
"hashes": [
"sha256:5963ef6b41b03e97049d48142cb23778f3e4ca841620296d7e13b00025522569"
],
"index": "pypi",
"version": "==7.0.0a6.dev195"
},
"click": { "click": {
"hashes": [ "hashes": [
"sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a", "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a",
@ -71,11 +78,11 @@
}, },
"flake8-black": { "flake8-black": {
"hashes": [ "hashes": [
"sha256:941514149cb8b489cb17a4bb1cf18d84375db3b34381bb018de83509437931a0", "sha256:c199844bc1b559d91195ebe8620216f21ed67f2cc1ff6884294c91a0d2492684",
"sha256:f26651bc10db786c03f4093414f7c9ea982ed8a244cec323c984feeffdf4c118" "sha256:cc080ba5b3773b69ba102b6617a00cc4ecbad8914109690cfda4d565ea435d96"
], ],
"index": "pypi", "index": "pypi",
"version": "==0.2.1" "version": "==0.2.3"
}, },
"flake8-commas": { "flake8-commas": {
"hashes": [ "hashes": [
@ -87,11 +94,11 @@
}, },
"flake8-comprehensions": { "flake8-comprehensions": {
"hashes": [ "hashes": [
"sha256:b07aef3277623db32310aa241a1cec67212b53c1d18e767d7e26d4d83aa05bf7", "sha256:4888de89248b7f7535159189ff693c77f8354f6d37a02619fa28c9921a913aa0",
"sha256:f24be9032587127f7a5bc6d066bf755b6e66834f694383adb8a673e229c1f559" "sha256:e9a010b99aa90c05790d45281ad9953df44a4a08a1a8f6cd41f98b4fc6a268a0"
], ],
"index": "pypi", "index": "pypi",
"version": "==3.5.0" "version": "==3.6.1"
}, },
"flake8-isort": { "flake8-isort": {
"hashes": [ "hashes": [
@ -103,65 +110,66 @@
}, },
"flake8-quotes": { "flake8-quotes": {
"hashes": [ "hashes": [
"sha256:3f1116e985ef437c130431ac92f9b3155f8f652fda7405ac22ffdfd7a9d1055e" "sha256:f1dd87830ed77ff2ce47fc0ee0fd87ae20e8f045355354ffbf4dcaa18d528217"
], ],
"index": "pypi", "index": "pypi",
"version": "==3.2.0" "version": "==3.3.0"
}, },
"greenlet": { "greenlet": {
"hashes": [ "hashes": [
"sha256:03f28a5ea20201e70ab70518d151116ce939b412961c33827519ce620957d44c", "sha256:04e1849c88aa56584d4a0a6e36af5ec7cc37993fdc1fda72b56aa1394a92ded3",
"sha256:06d7ac89e6094a0a8f8dc46aa61898e9e1aec79b0f8b47b2400dd51a44dbc832", "sha256:05e72db813c28906cdc59bd0da7c325d9b82aa0b0543014059c34c8c4ad20e16",
"sha256:06ecb43b04480e6bafc45cb1b4b67c785e183ce12c079473359e04a709333b08", "sha256:07e6d88242e09b399682b39f8dfa1e7e6eca66b305de1ff74ed9eb1a7d8e539c",
"sha256:096cb0217d1505826ba3d723e8981096f2622cde1eb91af9ed89a17c10aa1f3e", "sha256:090126004c8ab9cd0787e2acf63d79e80ab41a18f57d6448225bbfcba475034f",
"sha256:0c557c809eeee215b87e8a7cbfb2d783fb5598a78342c29ade561440abae7d22", "sha256:1796f2c283faab2b71c67e9b9aefb3f201fdfbee5cb55001f5ffce9125f63a45",
"sha256:0de64d419b1cb1bfd4ea544bedea4b535ef3ae1e150b0f2609da14bbf48a4a5f", "sha256:2f89d74b4f423e756a018832cd7a0a571e0a31b9ca59323b77ce5f15a437629b",
"sha256:14927b15c953f8f2d2a8dffa224aa78d7759ef95284d4c39e1745cf36e8cdd2c", "sha256:34e6675167a238bede724ee60fe0550709e95adaff6a36bcc97006c365290384",
"sha256:16183fa53bc1a037c38d75fdc59d6208181fa28024a12a7f64bb0884434c91ea", "sha256:3e594015a2349ec6dcceda9aca29da8dc89e85b56825b7d1f138a3f6bb79dd4c",
"sha256:206295d270f702bc27dbdbd7651e8ebe42d319139e0d90217b2074309a200da8", "sha256:3f8fc59bc5d64fa41f58b0029794f474223693fd00016b29f4e176b3ee2cfd9f",
"sha256:22002259e5b7828b05600a762579fa2f8b33373ad95a0ee57b4d6109d0e589ad", "sha256:3fc6a447735749d651d8919da49aab03c434a300e9f0af1c886d560405840fd1",
"sha256:2325123ff3a8ecc10ca76f062445efef13b6cf5a23389e2df3c02a4a527b89bc", "sha256:40abb7fec4f6294225d2b5464bb6d9552050ded14a7516588d6f010e7e366dcc",
"sha256:258f9612aba0d06785143ee1cbf2d7361801c95489c0bd10c69d163ec5254a16", "sha256:44556302c0ab376e37939fd0058e1f0db2e769580d340fb03b01678d1ff25f68",
"sha256:3096286a6072553b5dbd5efbefc22297e9d06a05ac14ba017233fedaed7584a8", "sha256:476ba9435afaead4382fbab8f1882f75e3fb2285c35c9285abb3dd30237f9142",
"sha256:3d13da093d44dee7535b91049e44dd2b5540c2a0e15df168404d3dd2626e0ec5", "sha256:4870b018ca685ff573edd56b93f00a122f279640732bb52ce3a62b73ee5c4a92",
"sha256:408071b64e52192869129a205e5b463abda36eff0cebb19d6e63369440e4dc99", "sha256:4adaf53ace289ced90797d92d767d37e7cdc29f13bd3830c3f0a561277a4ae83",
"sha256:598bcfd841e0b1d88e32e6a5ea48348a2c726461b05ff057c1b8692be9443c6e", "sha256:4eae94de9924bbb4d24960185363e614b1b62ff797c23dc3c8a7c75bbb8d187e",
"sha256:5d928e2e3c3906e0a29b43dc26d9b3d6e36921eee276786c4e7ad9ff5665c78a", "sha256:5317701c7ce167205c0569c10abc4bd01c7f4cf93f642c39f2ce975fa9b78a3c",
"sha256:5f75e7f237428755d00e7460239a2482fa7e3970db56c8935bd60da3f0733e56", "sha256:5c3b735ccf8fc8048664ee415f8af5a3a018cc92010a0d7195395059b4b39b7d",
"sha256:60848099b76467ef09b62b0f4512e7e6f0a2c977357a036de602b653667f5f4c", "sha256:5cde7ee190196cbdc078511f4df0be367af85636b84d8be32230f4871b960687",
"sha256:6b1d08f2e7f2048d77343279c4d4faa7aef168b3e36039cba1917fffb781a8ed", "sha256:655ab836324a473d4cd8cf231a2d6f283ed71ed77037679da554e38e606a7117",
"sha256:70bd1bb271e9429e2793902dfd194b653221904a07cbf207c3139e2672d17959", "sha256:6ce9d0784c3c79f3e5c5c9c9517bbb6c7e8aa12372a5ea95197b8a99402aa0e6",
"sha256:76ed710b4e953fc31c663b079d317c18f40235ba2e3d55f70ff80794f7b57922", "sha256:6e0696525500bc8aa12eae654095d2260db4dc95d5c35af2b486eae1bf914ccd",
"sha256:7920e3eccd26b7f4c661b746002f5ec5f0928076bd738d38d894bb359ce51927", "sha256:75ff270fd05125dce3303e9216ccddc541a9e072d4fc764a9276d44dee87242b",
"sha256:7db68f15486d412b8e2cfcd584bf3b3a000911d25779d081cbbae76d71bd1a7e", "sha256:8039f5fe8030c43cd1732d9a234fdcbf4916fcc32e21745ca62e75023e4d4649",
"sha256:8833e27949ea32d27f7e96930fa29404dd4f2feb13cce483daf52e8842ec246a", "sha256:84488516639c3c5e5c0e52f311fff94ebc45b56788c2a3bfe9cf8e75670f4de3",
"sha256:944fbdd540712d5377a8795c840a97ff71e7f3221d3fddc98769a15a87b36131", "sha256:84782c80a433d87530ae3f4b9ed58d4a57317d9918dfcc6a59115fa2d8731f2c",
"sha256:9a6b035aa2c5fcf3dbbf0e3a8a5bc75286fc2d4e6f9cfa738788b433ec894919", "sha256:8ddb38fb6ad96c2ef7468ff73ba5c6876b63b664eebb2c919c224261ae5e8378",
"sha256:9bdcff4b9051fb1aa4bba4fceff6a5f770c6be436408efd99b76fc827f2a9319", "sha256:98b491976ed656be9445b79bc57ed21decf08a01aaaf5fdabf07c98c108111f6",
"sha256:a9017ff5fc2522e45562882ff481128631bf35da444775bc2776ac5c61d8bcae", "sha256:990e0f5e64bcbc6bdbd03774ecb72496224d13b664aa03afd1f9b171a3269272",
"sha256:aa4230234d02e6f32f189fd40b59d5a968fe77e80f59c9c933384fe8ba535535", "sha256:9b02e6039eafd75e029d8c58b7b1f3e450ca563ef1fe21c7e3e40b9936c8d03e",
"sha256:ad80bb338cf9f8129c049837a42a43451fc7c8b57ad56f8e6d32e7697b115505", "sha256:a11b6199a0b9dc868990456a2667167d0ba096c5224f6258e452bfbe5a9742c5",
"sha256:adb94a28225005890d4cf73648b5131e885c7b4b17bc762779f061844aabcc11", "sha256:a414f8e14aa7bacfe1578f17c11d977e637d25383b6210587c29210af995ef04",
"sha256:b3090631fecdf7e983d183d0fad7ea72cfb12fa9212461a9b708ff7907ffff47", "sha256:a91ee268f059583176c2c8b012a9fce7e49ca6b333a12bbc2dd01fc1a9783885",
"sha256:b33b51ab057f8a20b497ffafdb1e79256db0c03ef4f5e3d52e7497200e11f821", "sha256:ac991947ca6533ada4ce7095f0e28fe25d5b2f3266ad5b983ed4201e61596acf",
"sha256:b97c9a144bbeec7039cca44df117efcbeed7209543f5695201cacf05ba3b5857", "sha256:b050dbb96216db273b56f0e5960959c2b4cb679fe1e58a0c3906fa0a60c00662",
"sha256:be13a18cec649ebaab835dff269e914679ef329204704869f2f167b2c163a9da", "sha256:b97a807437b81f90f85022a9dcfd527deea38368a3979ccb49d93c9198b2c722",
"sha256:be9768e56f92d1d7cd94185bab5856f3c5589a50d221c166cc2ad5eb134bd1dc", "sha256:bad269e442f1b7ffa3fa8820b3c3aa66f02a9f9455b5ba2db5a6f9eea96f56de",
"sha256:c1580087ab493c6b43e66f2bdd165d9e3c1e86ef83f6c2c44a29f2869d2c5bd5", "sha256:bf3725d79b1ceb19e83fb1aed44095518c0fcff88fba06a76c0891cfd1f36837",
"sha256:c35872b2916ab5a240d52a94314c963476c989814ba9b519bc842e5b61b464bb", "sha256:c0f22774cd8294078bdf7392ac73cf00bfa1e5e0ed644bd064fdabc5f2a2f481",
"sha256:c70c7dd733a4c56838d1f1781e769081a25fade879510c5b5f0df76956abfa05", "sha256:c1862f9f1031b1dee3ff00f1027fcd098ffc82120f43041fe67804b464bbd8a7",
"sha256:c767458511a59f6f597bfb0032a1c82a52c29ae228c2c0a6865cfeaeaac4c5f5", "sha256:c8d4ed48eed7414ccb2aaaecbc733ed2a84c299714eae3f0f48db085342d5629",
"sha256:c87df8ae3f01ffb4483c796fe1b15232ce2b219f0b18126948616224d3f658ee", "sha256:cf31e894dabb077a35bbe6963285d4515a387ff657bd25b0530c7168e48f167f",
"sha256:ca1c4a569232c063615f9e70ff9a1e2fee8c66a6fb5caf0f5e8b21a396deec3e", "sha256:d15cb6f8706678dc47fb4e4f8b339937b04eda48a0af1cca95f180db552e7663",
"sha256:cc407b68e0a874e7ece60f6639df46309376882152345508be94da608cc0b831", "sha256:dfcb5a4056e161307d103bc013478892cfd919f1262c2bb8703220adcb986362",
"sha256:da862b8f7de577bc421323714f63276acb2f759ab8c5e33335509f0b89e06b8f", "sha256:e02780da03f84a671bb4205c5968c120f18df081236d7b5462b380fd4f0b497b",
"sha256:dfe7eac0d253915116ed0cd160a15a88981a1d194c1ef151e862a5c7d2f853d3", "sha256:e2002a59453858c7f3404690ae80f10c924a39f45f6095f18a985a1234c37334",
"sha256:ed1377feed808c9c1139bdb6a61bcbf030c236dd288d6fca71ac26906ab03ba6", "sha256:e22a82d2b416d9227a500c6860cf13e74060cf10e7daf6695cbf4e6a94e0eee4",
"sha256:f42ad188466d946f1b3afc0a9e1a266ac8926461ee0786c06baac6bd71f8a6f3", "sha256:e41f72f225192d5d4df81dad2974a8943b0f2d664a2a5cfccdf5a01506f5523c",
"sha256:f92731609d6625e1cc26ff5757db4d32b6b810d2a3363b0ff94ff573e5901f6f" "sha256:f253dad38605486a4590f9368ecbace95865fea0f2b66615d121ac91fd1a1563",
"sha256:fddfb31aa2ac550b938d952bca8a87f1db0f8dc930ffa14ce05b5c08d27e7fd1"
], ],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
"version": "==1.1.0" "version": "==1.1.1"
}, },
"ipdb": { "ipdb": {
"hashes": [ "hashes": [
@ -172,11 +180,11 @@
}, },
"ipython": { "ipython": {
"hashes": [ "hashes": [
"sha256:9bc24a99f5d19721fb8a2d1408908e9c0520a17fff2233ffe82620847f17f1b6", "sha256:0cff04bb042800129348701f7bd68a430a844e8fb193979c08f6c99f28bb735e",
"sha256:d513e93327cf8657d6467c81f1f894adc125334ffe0e4ddd1abbb1c78d828703" "sha256:892743b65c21ed72b806a3a602cca408520b3200b89d1924f4b3d2cdb3692362"
], ],
"index": "pypi", "index": "pypi",
"version": "==7.24.1" "version": "==7.26.0"
}, },
"ipython-genutils": { "ipython-genutils": {
"hashes": [ "hashes": [
@ -187,11 +195,11 @@
}, },
"isort": { "isort": {
"hashes": [ "hashes": [
"sha256:0a943902919f65c5684ac4e0154b1ad4fac6dcaa5d9f3426b732f1c8b5419be6", "sha256:9c2ea1e62d871267b78307fe511c0838ba0da28698c5732d54e2790bf3ba9899",
"sha256:2bb1680aad211e3c9944dbce1d4ba09a989f04e238296c87fe2139faa26d655d" "sha256:e17d6e2b81095c9db0a03a8025a957f334d6ea30b26f9ec70805411e5c7c81f2"
], ],
"index": "pypi", "index": "pypi",
"version": "==5.8.0" "version": "==5.9.3"
}, },
"jedi": { "jedi": {
"hashes": [ "hashes": [
@ -249,6 +257,35 @@
], ],
"version": "==1.0.2" "version": "==1.0.2"
}, },
"mypy": {
"hashes": [
"sha256:088cd9c7904b4ad80bec811053272986611b84221835e079be5bcad029e79dd9",
"sha256:0aadfb2d3935988ec3815952e44058a3100499f5be5b28c34ac9d79f002a4a9a",
"sha256:119bed3832d961f3a880787bf621634ba042cb8dc850a7429f643508eeac97b9",
"sha256:1a85e280d4d217150ce8cb1a6dddffd14e753a4e0c3cf90baabb32cefa41b59e",
"sha256:3c4b8ca36877fc75339253721f69603a9c7fdb5d4d5a95a1a1b899d8b86a4de2",
"sha256:3e382b29f8e0ccf19a2df2b29a167591245df90c0b5a2542249873b5c1d78212",
"sha256:42c266ced41b65ed40a282c575705325fa7991af370036d3f134518336636f5b",
"sha256:53fd2eb27a8ee2892614370896956af2ff61254c275aaee4c230ae771cadd885",
"sha256:704098302473cb31a218f1775a873b376b30b4c18229421e9e9dc8916fd16150",
"sha256:7df1ead20c81371ccd6091fa3e2878559b5c4d4caadaf1a484cf88d93ca06703",
"sha256:866c41f28cee548475f146aa4d39a51cf3b6a84246969f3759cb3e9c742fc072",
"sha256:a155d80ea6cee511a3694b108c4494a39f42de11ee4e61e72bc424c490e46457",
"sha256:adaeee09bfde366d2c13fe6093a7df5df83c9a2ba98638c7d76b010694db760e",
"sha256:b6fb13123aeef4a3abbcfd7e71773ff3ff1526a7d3dc538f3929a49b42be03f0",
"sha256:b94e4b785e304a04ea0828759172a15add27088520dc7e49ceade7834275bedb",
"sha256:c0df2d30ed496a08de5daed2a9ea807d07c21ae0ab23acf541ab88c24b26ab97",
"sha256:c6c2602dffb74867498f86e6129fd52a2770c48b7cd3ece77ada4fa38f94eba8",
"sha256:ceb6e0a6e27fb364fb3853389607cf7eb3a126ad335790fa1e14ed02fba50811",
"sha256:d9dd839eb0dc1bbe866a288ba3c1afc33a202015d2ad83b31e875b5905a079b6",
"sha256:e4dab234478e3bd3ce83bac4193b2ecd9cf94e720ddd95ce69840273bf44f6de",
"sha256:ec4e0cd079db280b6bdabdc807047ff3e199f334050db5cbb91ba3e959a67504",
"sha256:ecd2c3fe726758037234c93df7e98deb257fd15c24c9180dacf1ef829da5f921",
"sha256:ef565033fa5a958e62796867b1df10c40263ea9ded87164d67572834e57a174d"
],
"index": "pypi",
"version": "==0.910"
},
"mypy-extensions": { "mypy-extensions": {
"hashes": [ "hashes": [
"sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d",
@ -263,6 +300,13 @@
"index": "pypi", "index": "pypi",
"version": "==0.3.1" "version": "==0.3.1"
}, },
"nodeenv": {
"hashes": [
"sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b",
"sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7"
],
"version": "==1.6.0"
},
"parso": { "parso": {
"hashes": [ "hashes": [
"sha256:12b83492c6239ce32ff5eed6d3639d6a536170723c6f3f1506869f1ace413398", "sha256:12b83492c6239ce32ff5eed6d3639d6a536170723c6f3f1506869f1ace413398",
@ -273,10 +317,10 @@
}, },
"pathspec": { "pathspec": {
"hashes": [ "hashes": [
"sha256:86379d6b86d75816baba717e64b1a3a3469deb93bb76d613c9ce79edc5cb68fd", "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a",
"sha256:aa0cb481c4041bf52ffa7b0d8fa6cd3e88a2ca4879c533c9153882ee2556790d" "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"
], ],
"version": "==0.8.1" "version": "==0.9.0"
}, },
"pexpect": { "pexpect": {
"hashes": [ "hashes": [
@ -295,11 +339,11 @@
}, },
"prompt-toolkit": { "prompt-toolkit": {
"hashes": [ "hashes": [
"sha256:08360ee3a3148bdb5163621709ee322ec34fc4375099afa4bbf751e9b7b7fa4f", "sha256:6076e46efae19b1e0ca1ec003ed37a933dc94b4d20f486235d436e64771dcd5c",
"sha256:7089d8d2938043508aa9420ec18ce0922885304cddae87fb96eebca942299f88" "sha256:eb71d5a6b72ce6db177af4a7d4d7085b99756bf656d98ffcc4fecd36850eea6c"
], ],
"markers": "python_full_version >= '3.6.1'", "markers": "python_full_version >= '3.6.2'",
"version": "==3.0.19" "version": "==3.0.20"
}, },
"ptyprocess": { "ptyprocess": {
"hashes": [ "hashes": [
@ -326,11 +370,11 @@
}, },
"pygments": { "pygments": {
"hashes": [ "hashes": [
"sha256:a18f47b506a429f6f4b9df81bb02beab9ca21d0a5fee38ed15aef65f0545519f", "sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380",
"sha256:d66e804411278594d764fc69ec36ec13d9ae9147193a1740cd34d272ca383b8e" "sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6"
], ],
"markers": "python_version >= '3.5'", "markers": "python_version >= '3.5'",
"version": "==2.9.0" "version": "==2.10.0"
}, },
"pynvim": { "pynvim": {
"hashes": [ "hashes": [
@ -338,6 +382,14 @@
], ],
"version": "==0.4.3" "version": "==0.4.3"
}, },
"pyright": {
"hashes": [
"sha256:dd8e18c54321340be44a708b6037c0b967486c32b3f492741fffdc205cb82f15",
"sha256:e2668730cddf580e696d4a11946e740e2f5647df1eb45f7c55b7029376eac5a1"
],
"index": "pypi",
"version": "==0.0.9"
},
"pyserial": { "pyserial": {
"hashes": [ "hashes": [
"sha256:3c77e014170dfffbd816e6ffc205e9842efb10be9f58ec16d3e8675b4925cddb", "sha256:3c77e014170dfffbd816e6ffc205e9842efb10be9f58ec16d3e8675b4925cddb",
@ -347,18 +399,19 @@
}, },
"python-dateutil": { "python-dateutil": {
"hashes": [ "hashes": [
"sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86",
"sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"
], ],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.8.1" "version": "==2.8.2"
}, },
"python-dotenv": { "python-dotenv": {
"hashes": [ "hashes": [
"sha256:dd8fe852847f4fbfadabf6183ddd4c824a9651f02d51714fa075c95561959c7d", "sha256:aae25dc1ebe97c420f50b81fb0e5c949659af713f31fdb63c749ca68748f34b1",
"sha256:effaac3c1e58d89b3ccb4d04a40dc7ad6e0275fda25fd75ae9d323e2465e202d" "sha256:f521bc2ac9a8e03c736f62911605c5d83970021e3fa95b37d769e2bbbe9b6172"
], ],
"version": "==0.18.0" "markers": "python_version >= '3.5'",
"version": "==0.19.0"
}, },
"python-magic": { "python-magic": {
"hashes": [ "hashes": [
@ -370,49 +423,49 @@
}, },
"regex": { "regex": {
"hashes": [ "hashes": [
"sha256:01afaf2ec48e196ba91b37451aa353cb7eda77efe518e481707e0515025f0cd5", "sha256:0696eb934dee723e3292056a2c046ddb1e4dd3887685783a9f4af638e85dee76",
"sha256:11d773d75fa650cd36f68d7ca936e3c7afaae41b863b8c387a22aaa78d3c5c79", "sha256:105122fa63da98d8456d5026bc6ac5a1399fd82fa6bad22c6ea641b1572c9142",
"sha256:18c071c3eb09c30a264879f0d310d37fe5d3a3111662438889ae2eb6fc570c31", "sha256:116c277774f84266044e889501fe79cfd293a8b4336b7a5e89b9f20f1e5a9f21",
"sha256:1e1c20e29358165242928c2de1482fb2cf4ea54a6a6dea2bd7a0e0d8ee321500", "sha256:12eaf0bbe568bd62e6cade7937e0bf01a2a4cef49a82f4fd204401e78409e158",
"sha256:281d2fd05555079448537fe108d79eb031b403dac622621c78944c235f3fcf11", "sha256:1401cfa4320691cbd91191ec678735c727dee674d0997b0902a5a38ad482faf5",
"sha256:314d66636c494ed9c148a42731b3834496cc9a2c4251b1661e40936814542b14", "sha256:19acdb8831a4e3b03b23369db43178d8fee1f17b99c83af6cd907886f76bd9d4",
"sha256:32e65442138b7b76dd8173ffa2cf67356b7bc1768851dded39a7a13bf9223da3", "sha256:208851a2f8dd31e468f0b5aa6c94433975bd67a107a4e7da3bdda947c9f85e25",
"sha256:339456e7d8c06dd36a22e451d58ef72cef293112b559010db3d054d5560ef439", "sha256:24d68499a27b2d93831fde4a9b84ea5b19e0ab141425fbc9ab1e5b4dad179df7",
"sha256:3916d08be28a1149fb97f7728fca1f7c15d309a9f9682d89d79db75d5e52091c", "sha256:2778c6cb379d804e429cc8e627392909e60db5152b42c695c37ae5757aae50ae",
"sha256:3a9cd17e6e5c7eb328517969e0cb0c3d31fd329298dd0c04af99ebf42e904f82", "sha256:2a0a5e323cf86760784ce2b91d8ab5ea09d0865d6ef4da0151e03d15d097b24e",
"sha256:47bf5bf60cf04d72bf6055ae5927a0bd9016096bf3d742fa50d9bf9f45aa0711", "sha256:2d9cbe0c755ab8b6f583169c0783f7278fc6b195e423b09c5a8da6f858025e96",
"sha256:4c46e22a0933dd783467cf32b3516299fb98cfebd895817d685130cc50cd1093", "sha256:2de1429e4eeab799c168a4f6e6eecdf30fcaa389bba4039cc8a065d6b7aad647",
"sha256:4c557a7b470908b1712fe27fb1ef20772b78079808c87d20a90d051660b1d69a", "sha256:32753eda8d413ce4f208cfe01dd61171a78068a6f5d5f38ccd751e00585cdf1d",
"sha256:52ba3d3f9b942c49d7e4bc105bb28551c44065f139a65062ab7912bef10c9afb", "sha256:3ee8ad16a35c45a5bab098e39020ecb6fec3b0e700a9d88983d35cbabcee79c8",
"sha256:563085e55b0d4fb8f746f6a335893bda5c2cef43b2f0258fe1020ab1dd874df8", "sha256:4f03fc0a25122cdcbf39136510d4ea7627f732206892db522adf510bc03b8c67",
"sha256:598585c9f0af8374c28edd609eb291b5726d7cbce16be6a8b95aa074d252ee17", "sha256:4f3e36086d6631ceaf468503f96a3be0d247caef0660c9452fb1b0c055783851",
"sha256:619d71c59a78b84d7f18891fe914446d07edd48dc8328c8e149cbe0929b4e000", "sha256:503c1ba0920a46a1844363725215ef44d59fcac2bd2c03ae3c59aa9d08d29bd6",
"sha256:67bdb9702427ceddc6ef3dc382455e90f785af4c13d495f9626861763ee13f9d", "sha256:507861cf3d97a86fbe26ea6cc04660ae028b9e4080b8290e28b99547b4e15d89",
"sha256:6d1b01031dedf2503631d0903cb563743f397ccaf6607a5e3b19a3d76fc10480", "sha256:56ae6e3cf0506ec0c40b466e31f41ee7a7149a2b505ae0ee50edd9043b423d27",
"sha256:741a9647fcf2e45f3a1cf0e24f5e17febf3efe8d4ba1281dcc3aa0459ef424dc", "sha256:6530b7b9505123cdea40a2301225183ca65f389bc6129f0c225b9b41680268d8",
"sha256:7c2a1af393fcc09e898beba5dd59196edaa3116191cc7257f9224beaed3e1aa0", "sha256:6729914dd73483cd1c8aaace3ac082436fc98b0072743ac136eaea0b3811d42f",
"sha256:7d9884d86dd4dd489e981d94a65cd30d6f07203d90e98f6f657f05170f6324c9", "sha256:7406dd2e44c7cfb4680c0a45a03264381802c67890cf506c147288f04c67177d",
"sha256:90f11ff637fe8798933fb29f5ae1148c978cccb0452005bf4c69e13db951e765", "sha256:7684016b73938ca12d160d2907d141f06b7597bd17d854e32bb7588be01afa1d",
"sha256:919859aa909429fb5aa9cf8807f6045592c85ef56fdd30a9a3747e513db2536e", "sha256:7db58ad61f3f6ea393aaf124d774ee0c58806320bc85c06dc9480f5c7219c250",
"sha256:96fcd1888ab4d03adfc9303a7b3c0bd78c5412b2bfbe76db5b56d9eae004907a", "sha256:83946ca9278b304728b637bc8d8200ab1663a79de85e47724594917aeed0e892",
"sha256:97f29f57d5b84e73fbaf99ab3e26134e6687348e95ef6b48cfd2c06807005a07", "sha256:84057cfae5676f456b03970eb78b7e182fddc80c2daafd83465a3d6ca9ff8dbf",
"sha256:980d7be47c84979d9136328d882f67ec5e50008681d94ecc8afa8a65ed1f4a6f", "sha256:862b6164e9a38b5c495be2c2854e75fd8af12c5be4c61dc9b42d255980d7e907",
"sha256:a91aa8619b23b79bcbeb37abe286f2f408d2f2d6f29a17237afda55bb54e7aac", "sha256:8ddb4f9ce6bb388ecc97b4b3eb37e786f05d7d5815e8822e0d87a3dbd7100649",
"sha256:ade17eb5d643b7fead300a1641e9f45401c98eee23763e9ed66a43f92f20b4a7", "sha256:92eb03f47427fea452ff6956d11f5d5a3f22a048c90a0f34fa223e6badab6c85",
"sha256:b9c3db21af35e3b3c05764461b262d6f05bbca08a71a7849fd79d47ba7bc33ed", "sha256:a5f3bc727fea58f21d99c22e6d4fca652dc11dbc2a1e7cfc4838cd53b2e3691f",
"sha256:bd28bc2e3a772acbb07787c6308e00d9626ff89e3bfcdebe87fa5afbfdedf968", "sha256:a6180dbf5945b27e9420e1b58c3cacfc79ad5278bdad3ea35109f5680fbe16d1",
"sha256:bf5824bfac591ddb2c1f0a5f4ab72da28994548c708d2191e3b87dd207eb3ad7", "sha256:b158f673ae6a6523f13704f70aa7e4ce875f91e379bece4362c89db18db189d5",
"sha256:c0502c0fadef0d23b128605d69b58edb2c681c25d44574fc673b0e52dce71ee2", "sha256:cd45b4542134de63e7b9dd653e0a2d7d47ffed9615e3637c27ca5f6b78ea68bb",
"sha256:c38c71df845e2aabb7fb0b920d11a1b5ac8526005e533a8920aea97efb8ec6a4", "sha256:d2404336fd16788ea757d4218a2580de60adb052d9888031e765320be8884309",
"sha256:ce15b6d103daff8e9fee13cf7f0add05245a05d866e73926c358e871221eae87", "sha256:db888d4fb33a2fd54b57ac55d5015e51fa849f0d8592bd799b4e47f83bd04e00",
"sha256:d3029c340cfbb3ac0a71798100ccc13b97dddf373a4ae56b6a72cf70dfd53bc8", "sha256:dde0ac721c7c5bfa5f9fc285e811274dec3c392f2c1225f7d07ca98a8187ca84",
"sha256:e512d8ef5ad7b898cdb2d8ee1cb09a8339e4f8be706d27eaa180c2f177248a10", "sha256:de0d06ccbc06af5bf93bddec10f4f80275c5d74ea6d28b456931f3955f58bc8c",
"sha256:e8e5b509d5c2ff12f8418006d5a90e9436766133b564db0abaec92fd27fcee29", "sha256:e02dad60e3e8442eefd28095e99b2ac98f2b8667167493ac6a2f3aadb5d84a17",
"sha256:ee54ff27bf0afaf4c3b3a62bcd016c12c3fdb4ec4f413391a90bd38bc3624605", "sha256:e960fe211496333b2f7e36badf4c22a919d740386681f79139ee346b403d1ca1",
"sha256:fa4537fb4a98fe8fde99626e4681cc644bdcf2a795038533f9f711513a862ae6", "sha256:e9700c52749cb3e90c98efd72b730c97b7e4962992fca5fbcaf1363be8e3b849",
"sha256:fd45ff9293d9274c5008a2054ecef86a9bfe819a67c7be1afb65e69b405b3042" "sha256:ee318974a1fdacba1701bc9e552e9015788d6345416364af6fa987424ff8df53"
], ],
"version": "==2021.4.4" "version": "==2021.8.27"
}, },
"s3cmd": { "s3cmd": {
"hashes": [ "hashes": [
@ -432,10 +485,10 @@
}, },
"testfixtures": { "testfixtures": {
"hashes": [ "hashes": [
"sha256:5ec3a0dd6f71cc4c304fbc024a10cc293d3e0b852c868014b9f233203e149bda", "sha256:0a6422737f6d89b45cdef1e2df5576f52ad0f507956002ce1020daa9f44211d6",
"sha256:9ed31e83f59619e2fa17df053b241e16e0608f4580f7b5a9333a0c9bdcc99137" "sha256:486be7b01eb71326029811878a3317b7e7994324621c0ec633c8e24499d8d5b3"
], ],
"version": "==6.17.1" "version": "==6.18.1"
}, },
"toml": { "toml": {
"hashes": [ "hashes": [
@ -453,6 +506,22 @@
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.7'",
"version": "==5.0.5" "version": "==5.0.5"
}, },
"typing": {
"hashes": [
"sha256:1187fb9c82fd670d10aa07bbb6cfcfe4bdda42d6fab8d5134f04e8c4d0b71cc9",
"sha256:283d868f5071ab9ad873e5e52268d611e851c870a2ba354193026f2dfb29d8b5"
],
"index": "pypi",
"version": "==3.7.4.3"
},
"typing-extensions": {
"hashes": [
"sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
"sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
"sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
],
"version": "==3.10.0.0"
},
"wcwidth": { "wcwidth": {
"hashes": [ "hashes": [
"sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784", "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784",

View File

@ -11,3 +11,17 @@ class UnicodeMode:
LINUX = IBUS = const(1) LINUX = IBUS = const(1)
MACOS = OSX = RALT = const(2) MACOS = OSX = RALT = const(2)
WINC = const(3) WINC = const(3)
TYPING_PLATFORMS = [
'linux',
'linux2',
'win32',
'cygwin',
'msys',
'darwin',
'freebsd7',
'freebsd8',
'freebsdN',
'openbsd6',
]

View File

@ -1,16 +1,21 @@
from kmk.kmk_keyboard import KMKKeyboard
class InvalidExtensionEnvironment(Exception): class InvalidExtensionEnvironment(Exception):
pass pass
class Extension: class Extension:
_enabled = True _enabled = True # type: bool
def enable(self, keyboard): def enable(self, keyboard):
# type: (KMKKeyboard) -> None
self._enabled = True self._enabled = True
self.on_runtime_enable(keyboard) self.on_runtime_enable(keyboard)
def disable(self, keyboard): def disable(self, keyboard):
# type (KMKKeyboard) -> None
self._enabled = False self._enabled = False
self.on_runtime_disable(keyboard) self.on_runtime_disable(keyboard)
@ -18,34 +23,43 @@ class Extension:
# The below methods should be implemented by subclasses # The below methods should be implemented by subclasses
def on_runtime_enable(self, keyboard): def on_runtime_enable(self, keyboard):
# type: (KMKKeyboard) -> None
raise NotImplementedError raise NotImplementedError
def on_runtime_disable(self, keyboard): def on_runtime_disable(self, keyboard):
# type: (KMKKeyboard) -> None
raise NotImplementedError raise NotImplementedError
def during_bootup(self, keyboard): def during_bootup(self, keyboard):
# type: (KMKKeyboard) -> None
raise NotImplementedError raise NotImplementedError
def before_matrix_scan(self, keyboard): def before_matrix_scan(self, keyboard):
# type: (KMKKeyboard) -> None
''' '''
Return value will be injected as an extra matrix update Return value will be injected as an extra matrix update
''' '''
raise NotImplementedError raise NotImplementedError
def after_matrix_scan(self, keyboard): def after_matrix_scan(self, keyboard):
# type: (KMKKeyboard) -> None
''' '''
Return value will be replace matrix update if supplied Return value will be replace matrix update if supplied
''' '''
raise NotImplementedError raise NotImplementedError
def before_hid_send(self, keyboard): def before_hid_send(self, keyboard):
# type: (KMKKeyboard) -> None
raise NotImplementedError raise NotImplementedError
def after_hid_send(self, keyboard): def after_hid_send(self, keyboard):
# type: (KMKKeyboard) -> None
raise NotImplementedError raise NotImplementedError
def on_powersave_enable(self, keyboard): def on_powersave_enable(self, keyboard):
# type: (KMKKeyboard) -> None
raise NotImplementedError raise NotImplementedError
def on_powersave_disable(self, keyboard): def on_powersave_disable(self, keyboard):
# type: (KMKKeyboard) -> None
raise NotImplementedError raise NotImplementedError

View File

@ -1,6 +1,7 @@
'''Adds international keys''' '''Adds international keys'''
from kmk.extensions import Extension from kmk.extensions import Extension
from kmk.keys import make_key from kmk.keys import make_key
from kmk.kmk_keyboard import KMKKeyboard
class International(Extension): class International(Extension):
@ -32,28 +33,37 @@ class International(Extension):
make_key(code=152, names=('LANG9',)) make_key(code=152, names=('LANG9',))
def on_runtime_enable(self, sandbox): def on_runtime_enable(self, sandbox):
# type: (KMKKeyboard) -> None
return return
def on_runtime_disable(self, sandbox): def on_runtime_disable(self, sandbox):
# type: (KMKKeyboard) -> None
return return
def during_bootup(self, sandbox): def during_bootup(self, sandbox):
# type: (KMKKeyboard) -> None
return return
def before_matrix_scan(self, sandbox): def before_matrix_scan(self, sandbox):
# type: (KMKKeyboard) -> None
return return
def after_matrix_scan(self, sandbox): def after_matrix_scan(self, sandbox):
# type: (KMKKeyboard) -> None
return return
def before_hid_send(self, sandbox): def before_hid_send(self, sandbox):
# type: (KMKKeyboard) -> None
return return
def after_hid_send(self, sandbox): def after_hid_send(self, sandbox):
# type: (KMKKeyboard) -> None
return return
def on_powersave_enable(self, sandbox): def on_powersave_enable(self, sandbox):
# type: (KMKKeyboard) -> None
return return
def on_powersave_disable(self, sandbox): def on_powersave_disable(self, sandbox):
# type: (KMKKeyboard) -> None
return return

View File

@ -1,11 +1,29 @@
import sys
from time import sleep from time import sleep
from kmk.consts import TYPING_PLATFORMS
if sys.platform in TYPING_PLATFORMS:
from typing import Any, Optional
from kmk.keys import Key, KeyAttrDict
from kmk.kmk_keyboard import KMKKeyboard # Avoid cyclical imports
def passthrough(key, keyboard, *args, **kwargs): def passthrough(key, keyboard, *args, **kwargs):
return keyboard return keyboard
def default_pressed(key, keyboard, KC, coord_int=None, coord_raw=None, *args, **kwargs): def default_pressed(
key, # type: Key
keyboard, # type: KMKKeyboard
KC, # type: KeyAttrDict
coord_int=None, # type: Optional[int]
coord_raw=None, # type: Optional[str]
*args, # type: Any
**kwargs, # type: Any
):
# type: (...) -> KMKKeyboard
keyboard.hid_pending = True keyboard.hid_pending = True
keyboard.keys_pressed.add(key) keyboard.keys_pressed.add(key)
@ -14,8 +32,15 @@ def default_pressed(key, keyboard, KC, coord_int=None, coord_raw=None, *args, **
def default_released( def default_released(
key, keyboard, KC, coord_int=None, coord_raw=None, *args, **kwargs # NOQA key, # type: Key
keyboard, # type: KMKKeyboard
KC, # type: KeyAttrDict
coord_int=None, # type: Optional[int]
coord_raw=None, # type: Optional[str]
*args, # type: Any
**kwargs, # type: Any # NOQA
): ):
# type: (...) -> KMKKeyboard
keyboard.hid_pending = True keyboard.hid_pending = True
keyboard.keys_pressed.discard(key) keyboard.keys_pressed.discard(key)

View File

@ -1,3 +1,6 @@
import sys
from kmk.consts import TYPING_PLATFORMS
from kmk.types import ( from kmk.types import (
KeySeqSleepMeta, KeySeqSleepMeta,
LayerKeyMeta, LayerKeyMeta,
@ -6,12 +9,20 @@ from kmk.types import (
UnicodeModeKeyMeta, UnicodeModeKeyMeta,
) )
if sys.platform in TYPING_PLATFORMS:
from typing import List, Optional
# Avoid cyclical imports
from kmk.keys import Key
def key_seq_sleep_validator(ms): def key_seq_sleep_validator(ms):
# type: (float) -> KeySeqSleepMeta
return KeySeqSleepMeta(ms) return KeySeqSleepMeta(ms)
def layer_key_validator(layer, kc=None): def layer_key_validator(layer, kc=None):
# type: (int, Optional[Key]) -> LayerKeyMeta
''' '''
Validates the syntax (but not semantics) of a layer key call. We won't Validates the syntax (but not semantics) of a layer key call. We won't
have access to the keymap here, so we can't verify much of anything useful have access to the keymap here, so we can't verify much of anything useful
@ -22,7 +33,8 @@ def layer_key_validator(layer, kc=None):
return LayerKeyMeta(layer=layer, kc=kc) return LayerKeyMeta(layer=layer, kc=kc)
def mod_tap_validator(kc, mods=None): def mod_tap_validator(kc, mods):
# type: (Key, Optional[List[Key]]) -> ModTapKeyMeta
''' '''
Validates that mod tap keys are correctly used Validates that mod tap keys are correctly used
''' '''
@ -30,8 +42,10 @@ def mod_tap_validator(kc, mods=None):
def tap_dance_key_validator(*codes): def tap_dance_key_validator(*codes):
# type: (*Key) -> TapDanceKeyMeta
return TapDanceKeyMeta(codes) return TapDanceKeyMeta(codes)
def unicode_mode_key_validator(mode): def unicode_mode_key_validator(mode):
# type: (int) -> UnicodeModeKeyMeta
return UnicodeModeKeyMeta(mode) return UnicodeModeKeyMeta(mode)

View File

@ -1,3 +1,8 @@
from typing import NoReturn
from kmk.kmk_keyboard import KMKKeyboard
class InvalidExtensionEnvironment(Exception): class InvalidExtensionEnvironment(Exception):
pass pass
@ -12,29 +17,29 @@ class Module:
# The below methods should be implemented by subclasses # The below methods should be implemented by subclasses
def during_bootup(self, keyboard): def during_bootup(self, keyboard: KMKKeyboard) -> NoReturn:
raise NotImplementedError raise NotImplementedError
def before_matrix_scan(self, keyboard): def before_matrix_scan(self, keyboard: KMKKeyboard) -> NoReturn:
''' '''
Return value will be injected as an extra matrix update Return value will be injected as an extra matrix update
''' '''
raise NotImplementedError raise NotImplementedError
def after_matrix_scan(self, keyboard): def after_matrix_scan(self, keyboard: KMKKeyboard) -> NoReturn:
''' '''
Return value will be replace matrix update if supplied Return value will be replace matrix update if supplied
''' '''
raise NotImplementedError raise NotImplementedError
def before_hid_send(self, keyboard): def before_hid_send(self, keyboard: KMKKeyboard) -> NoReturn:
raise NotImplementedError raise NotImplementedError
def after_hid_send(self, keyboard): def after_hid_send(self, keyboard: KMKKeyboard) -> NoReturn:
raise NotImplementedError raise NotImplementedError
def on_powersave_enable(self, keyboard): def on_powersave_enable(self, keyboard: KMKKeyboard) -> NoReturn:
raise NotImplementedError raise NotImplementedError
def on_powersave_disable(self, keyboard): def on_powersave_disable(self, keyboard: KMKKeyboard) -> NoReturn:
raise NotImplementedError raise NotImplementedError

View File

@ -1,66 +1,89 @@
import digitalio import digitalio
from supervisor import ticks_ms from supervisor import ticks_ms
from typing import Any, ClassVar, Dict, List, Optional, Tuple, Union
from kmk.keys import Key
from kmk.kmk_keyboard import KMKKeyboard
from kmk.kmktime import ticks_ms
from kmk.modules import Module from kmk.modules import Module
EncoderMap = Tuple[
List[Tuple[Key, Key, int]],
List[Tuple[Key, Key, int]],
List[Tuple[None, None, int]],
]
class EncoderPadState: class EncoderPadState:
OFF = False OFF: bool = False
ON = True ON: bool = True
class EndcoderDirection: class EndcoderDirection:
Left = False Left: bool = False
Right = True Right: bool = True
class Encoder: class Encoder:
def __init__( def __init__(
self, self,
pad_a, pad_a: Any,
pad_b, pad_b: Any,
button_pin=None, button_pin: Optional[Any] = None,
): ) -> None:
self.pad_a = self.PreparePin(pad_a) # board pin for enc pin a self.pad_a: Union[digitalio.DigitalInOut, None] = self.PreparePin(
self.pad_a_state = False pad_a
self.pad_b = self.PreparePin(pad_b) # board pin for enc pin b ) # board pin for enc pin a
self.pad_b_state = False self.pad_a_state: bool = False
self.button_pin = self.PreparePin(button_pin) # board pin for enc btn self.pad_b: Union[digitalio.DigitalInOut, None] = self.PreparePin(
pad_b
) # board pin for enc pin b
self.pad_b_state: bool = False
self.button_pin: Union[digitalio.DigitalInOut, None] = self.PreparePin(
button_pin
) # board pin for enc btn
self.button_state = None # state of pushbutton on encoder if enabled self.button_state = None # state of pushbutton on encoder if enabled
self.encoder_value = 0 # clarify what this value is self.encoder_value: int = 0 # clarify what this value is
self.encoder_state = ( self.encoder_state: Tuple[bool, bool] = (
self.pad_a_state, self.pad_a_state,
self.pad_b_state, self.pad_b_state,
) # quaderature encoder state ) # quaderature encoder state
self.encoder_direction = None # arbitrary, tells direction of knob self.encoder_direction: Optional[
self.last_encoder_state = None # not used yet bool
self.resolution = 2 # number of keys sent per position change ] = None # arbitrary, tells direction of knob
self.revolution_count = 20 # position changes per revolution self.last_encoder_state: Optional[Tuple[bool, bool]] = None # not used yet
self.has_button = False # enable/disable button functionality self.resolution: int = 2 # number of keys sent per position change
self.encoder_data = None # 6tuple containing all encoder data self.revolution_count: int = 20 # position changes per revolution
self.position_change = None # revolution count, inc/dec as knob turns self.has_button: bool = False # enable/disable button functionality
self.last_encoder_value = 0 # not used self.encoder_data: Optional[Tuple] = None # 6tuple containing all encoder data
self.is_inverted = False # switch to invert knob direction self.position_change: Optional[
self.vel_mode = False # enable the velocity output int
self.vel_ts = None # velocity timestamp ] = None # revolution count, inc/dec as knob turns
self.last_vel_ts = 0 # last velocity timestamp self.last_encoder_value: int = 0 # not used
self.encoder_speed = None # ms per position change(4 states) self.is_inverted: bool = False # switch to invert knob direction
self.encoder_map = None self.vel_mode: bool = False # enable the velocity output
self.eps = EncoderPadState() self.vel_ts: Optional[float] = None # velocity timestamp
self.encoder_pad_lookup = { self.last_vel_ts: float = 0 # last velocity timestamp
self.encoder_speed: Optional[float] = None # ms per position change(4 states)
self.encoder_map: Optional[EncoderMap] = None
self.eps: EncoderPadState = EncoderPadState()
self.encoder_pad_lookup: Dict[bool, bool] = {
False: self.eps.OFF, False: self.eps.OFF,
True: self.eps.ON, True: self.eps.ON,
} }
self.edr = EndcoderDirection() # lookup for current encoder direction self.edr: EndcoderDirection = (
self.encoder_dir_lookup = { EndcoderDirection()
) # lookup for current encoder direction
self.encoder_dir_lookup: Dict[bool, bool] = {
False: self.edr.Left, False: self.edr.Left,
True: self.edr.Right, True: self.edr.Right,
} }
def __repr__(self, idx): def __repr__(self, idx: int) -> str:
return 'ENCODER_{}({})'.format(idx, self._to_dict()) return 'ENCODER_{}({})'.format(idx, self._to_dict())
def _to_dict(self): def _to_dict(self) -> Dict[str, Any]:
return { return {
'Encoder_State': self.encoder_state, 'Encoder_State': self.encoder_state,
'Direction': self.encoder_direction, 'Direction': self.encoder_direction,
@ -71,7 +94,7 @@ class Encoder:
} }
# adapted for CircuitPython from raspi # adapted for CircuitPython from raspi
def PreparePin(self, num): def PreparePin(self, num: Union[Any, None]) -> Union[digitalio.DigitalInOut, None]:
if num is not None: if num is not None:
pad = digitalio.DigitalInOut(num) pad = digitalio.DigitalInOut(num)
pad.direction = digitalio.Direction.INPUT pad.direction = digitalio.Direction.INPUT
@ -81,7 +104,7 @@ class Encoder:
return None return None
# checks encoder pins, reports encoder data # checks encoder pins, reports encoder data
def report(self): def report(self) -> Union[int, None]:
new_encoder_state = ( new_encoder_state = (
self.encoder_pad_lookup[int(self.pad_a.value)], self.encoder_pad_lookup[int(self.pad_a.value)],
self.encoder_pad_lookup[int(self.pad_b.value)], self.encoder_pad_lookup[int(self.pad_b.value)],
@ -143,14 +166,14 @@ class Encoder:
return None return None
# invert knob direction if encoder pins are soldered backwards # invert knob direction if encoder pins are soldered backwards
def invert_rotation(self, new, old): def invert_rotation(self, new: int, old: int) -> int:
if self.is_inverted: if self.is_inverted:
return -(new - old) return -(new - old)
else: else:
return new - old return new - old
# returns knob velocity as milliseconds between position changes(detents) # returns knob velocity as milliseconds between position changes(detents)
def vel_report(self): def vel_report(self) -> float:
self.encoder_speed = self.vel_ts - self.last_vel_ts self.encoder_speed = self.vel_ts - self.last_vel_ts
self.last_vel_ts = self.vel_ts self.last_vel_ts = self.vel_ts
return self.encoder_speed return self.encoder_speed
@ -158,50 +181,54 @@ class Encoder:
class EncoderHandler(Module): class EncoderHandler(Module):
encoders = [] encoders: ClassVar[List[Encoder]] = []
debug_enabled = False # not working as inttended, do not use for now debug_enabled: ClassVar[
bool
] = False # not working as inttended, do not use for now
def __init__(self, pad_a, pad_b, encoder_map): def __init__(
self.pad_a = pad_a self, pad_a: List[Any], pad_b: List[Any], encoder_map: EncoderMap
self.pad_b = pad_b ) -> None:
self.encoder_count = len(self.pad_a) self.pad_a: List[Any] = pad_a
self.encoder_map = encoder_map self.pad_b: List[Any] = pad_b
self.encoder_count: int = len(self.pad_a)
self.encoder_map: EncoderMap = encoder_map
self.make_encoders() self.make_encoders()
def on_runtime_enable(self, keyboard): def on_runtime_enable(self, keyboard: KMKKeyboard) -> None:
return return
def on_runtime_disable(self, keyboard): def on_runtime_disable(self, keyboard: KMKKeyboard) -> None:
return return
def during_bootup(self, keyboard): def during_bootup(self, keyboard: KMKKeyboard) -> None:
return return
def before_matrix_scan(self, keyboard): def before_matrix_scan(self, keyboard: KMKKeyboard) -> Union[KMKKeyboard, None]:
''' '''
Return value will be injected as an extra matrix update Return value will be injected as an extra matrix update
''' '''
return self.get_reports(keyboard) return self.get_reports(keyboard)
def after_matrix_scan(self, keyboard): def after_matrix_scan(self, keyboard: KMKKeyboard) -> None:
''' '''
Return value will be replace matrix update if supplied Return value will be replace matrix update if supplied
''' '''
return return
def before_hid_send(self, keyboard): def before_hid_send(self, keyboard: KMKKeyboard) -> None:
return return
def after_hid_send(self, keyboard): def after_hid_send(self, keyboard: KMKKeyboard) -> None:
return return
def on_powersave_enable(self, keyboard): def on_powersave_enable(self, keyboard: KMKKeyboard) -> None:
return return
def on_powersave_disable(self, keyboard): def on_powersave_disable(self, keyboard: KMKKeyboard) -> None:
return return
def make_encoders(self): def make_encoders(self) -> None:
for i in range(self.encoder_count): for i in range(self.encoder_count):
self.encoders.append( self.encoders.append(
Encoder( Encoder(
@ -210,7 +237,9 @@ class EncoderHandler(Module):
) )
) )
def send_encoder_keys(self, keyboard, encoder_key, encoder_idx): def send_encoder_keys(
self, keyboard: KMKKeyboard, encoder_key: int, encoder_idx: int
) -> KMKKeyboard:
# position in the encoder map tuple # position in the encoder map tuple
encoder_resolution = 2 encoder_resolution = 2
for _ in range( for _ in range(
@ -221,7 +250,7 @@ class EncoderHandler(Module):
) )
return keyboard return keyboard
def get_reports(self, keyboard): def get_reports(self, keyboard: KMKKeyboard) -> Union[KMKKeyboard, None]:
for idx in range(self.encoder_count): for idx in range(self.encoder_count):
if self.debug_enabled: # not working as inttended, do not use for now if self.debug_enabled: # not working as inttended, do not use for now
print(self.encoders[idx].__repr__(idx)) print(self.encoders[idx].__repr__(idx))

View File

@ -4,21 +4,24 @@ from supervisor import ticks_ms
from time import sleep from time import sleep
from typing import Any, Dict, Optional
from kmk.handlers.stock import passthrough as handler_passthrough from kmk.handlers.stock import passthrough as handler_passthrough
from kmk.keys import make_key from kmk.keys import Key, make_key
from kmk.kmk_keyboard import KMKKeyboard
from kmk.kmktime import check_deadline from kmk.kmktime import check_deadline
from kmk.modules import Module from kmk.modules import Module
class Power(Module): class Power(Module):
def __init__(self, powersave_pin=None): def __init__(self, powersave_pin: Optional[Any] = None) -> None:
self.enable = False self.enable: bool = False
self.powersave_pin = powersave_pin # Powersave pin board object self.powersave_pin = powersave_pin # Powersave pin board object
self._powersave_start = ticks_ms() self._powersave_start: float = ticks_ms()
self._usb_last_scan = ticks_ms() - 5000 self._usb_last_scan: float = ticks_ms() - 5000
self._psp = None # Powersave pin object self._psp: Optional[digitalio.DigitalInOut] = None # Powersave pin object
self._i2c = 0 self._i2c: int = 0
self._loopcounter = 0 self._loopcounter: int = 0
make_key( make_key(
names=('PS_TOG',), on_press=self._ps_tog, on_release=handler_passthrough names=('PS_TOG',), on_press=self._ps_tog, on_release=handler_passthrough
@ -30,10 +33,10 @@ class Power(Module):
names=('PS_OFF',), on_press=self._ps_disable, on_release=handler_passthrough names=('PS_OFF',), on_press=self._ps_disable, on_release=handler_passthrough
) )
def __repr__(self): def __repr__(self) -> str:
return f'Power({self._to_dict()})' return f'Power({self._to_dict()})'
def _to_dict(self): def _to_dict(self) -> Dict[str, Any]:
return { return {
'enable': self.enable, 'enable': self.enable,
'powersave_pin': self.powersave_pin, 'powersave_pin': self.powersave_pin,
@ -42,24 +45,24 @@ class Power(Module):
'_psp': self._psp, '_psp': self._psp,
} }
def during_bootup(self, keyboard): def during_bootup(self, keyboard: KMKKeyboard) -> None:
self._i2c_scan() self._i2c_scan()
def before_matrix_scan(self, keyboard): def before_matrix_scan(self, keyboard: KMKKeyboard) -> None:
return return
def after_matrix_scan(self, keyboard): def after_matrix_scan(self, keyboard: KMKKeyboard) -> None:
if keyboard.matrix_update or keyboard.secondary_matrix_update: if keyboard.matrix_update or keyboard.secondary_matrix_update:
self.psave_time_reset() self.psave_time_reset()
def before_hid_send(self, keyboard): def before_hid_send(self, keyboard: KMKKeyboard) -> None:
return return
def after_hid_send(self, keyboard): def after_hid_send(self, keyboard: KMKKeyboard) -> None:
if self.enable: if self.enable:
self.psleep() self.psleep()
def on_powersave_enable(self, keyboard): def on_powersave_enable(self, keyboard: KMKKeyboard) -> None:
'''Gives 10 cycles to allow other extensions to clean up before powersave''' '''Gives 10 cycles to allow other extensions to clean up before powersave'''
if self._loopcounter > 10: if self._loopcounter > 10:
self.enable_powersave(keyboard) self.enable_powersave(keyboard)
@ -68,11 +71,11 @@ class Power(Module):
self._loopcounter += 1 self._loopcounter += 1
return return
def on_powersave_disable(self, keyboard): def on_powersave_disable(self, keyboard: KMKKeyboard) -> None:
self.disable_powersave(keyboard) self.disable_powersave(keyboard)
return return
def enable_powersave(self, keyboard): def enable_powersave(self, keyboard: KMKKeyboard) -> None:
'''Enables power saving features''' '''Enables power saving features'''
if keyboard.i2c_deinit_count >= self._i2c and self.powersave_pin: if keyboard.i2c_deinit_count >= self._i2c and self.powersave_pin:
# Allows power save to prevent RGB drain. # Allows power save to prevent RGB drain.
@ -88,7 +91,7 @@ class Power(Module):
keyboard._trigger_powersave_enable = False keyboard._trigger_powersave_enable = False
return return
def disable_powersave(self, keyboard): def disable_powersave(self, keyboard: KMKKeyboard) -> None:
'''Disables power saving features''' '''Disables power saving features'''
if self._psp: if self._psp:
self._psp.value = False self._psp.value = False
@ -99,7 +102,7 @@ class Power(Module):
self.enable = False self.enable = False
return return
def psleep(self): def psleep(self) -> None:
''' '''
Sleeps longer and longer to save power the more time in between updates. Sleeps longer and longer to save power the more time in between updates.
''' '''
@ -109,10 +112,10 @@ class Power(Module):
sleep(180 / 1000) sleep(180 / 1000)
return return
def psave_time_reset(self): def psave_time_reset(self) -> None:
self._powersave_start = ticks_ms() self._powersave_start = ticks_ms()
def _i2c_scan(self): def _i2c_scan(self) -> None:
i2c = board.I2C() i2c = board.I2C()
while not i2c.try_lock(): while not i2c.try_lock():
pass pass
@ -122,28 +125,46 @@ class Power(Module):
i2c.unlock() i2c.unlock()
return return
def usb_rescan_timer(self): def usb_rescan_timer(self) -> bool:
return bool(check_deadline(ticks_ms(), self._usb_last_scan) > 5000) return bool(check_deadline(ticks_ms(), self._usb_last_scan) > 5000)
def usb_time_reset(self): def usb_time_reset(self) -> None:
self._usb_last_scan = ticks_ms() self._usb_last_scan = ticks_ms()
return return
def usb_scan(self): def usb_scan(self) -> bool:
# TODO Add USB detection here. Currently lies that it's connected # TODO Add USB detection here. Currently lies that it's connected
# https://github.com/adafruit/circuitpython/pull/3513 # https://github.com/adafruit/circuitpython/pull/3513
return True return True
def _ps_tog(self, key, keyboard, *args, **kwargs): def _ps_tog(
self,
key: Key,
keyboard: KMKKeyboard,
*args: Any,
**kwargs: Any,
) -> None:
if self.enable: if self.enable:
keyboard._trigger_powersave_disable = True keyboard._trigger_powersave_disable = True
else: else:
keyboard._trigger_powersave_enable = True keyboard._trigger_powersave_enable = True
def _ps_enable(self, key, keyboard, *args, **kwargs): def _ps_enable(
self,
key: Key,
keyboard: KMKKeyboard,
*args: Any,
**kwargs: Any,
) -> None:
if not self.enable: if not self.enable:
keyboard._trigger_powersave_enable = True keyboard._trigger_powersave_enable = True
def _ps_disable(self, key, keyboard, *args, **kwargs): def _ps_disable(
self,
key: Key,
keyboard: KMKKeyboard,
*args: Any,
**kwargs: Any,
) -> None:
if self.enable: if self.enable:
keyboard._trigger_powersave_disable = True keyboard._trigger_powersave_disable = True

View File

@ -4,22 +4,26 @@ from micropython import const
from supervisor import ticks_ms from supervisor import ticks_ms
from storage import getmount from storage import getmount
from typing import Any, List, Optional, Type, Union
from kmk.kmk_keyboard import KMKKeyboard
from kmk.kmktime import check_deadline from kmk.kmktime import check_deadline
from kmk.matrix import intify_coordinate from kmk.matrix import intify_coordinate
from kmk.modules import Module from kmk.modules import Module
UartBuffer = List[Optional[Union[bytes, None]]]
class SplitSide: class SplitSide:
LEFT = const(1) LEFT: int = const(1)
RIGHT = const(2) RIGHT: int = const(2)
class SplitType: class SplitType:
UART = const(1) UART: int = const(1)
I2C = const(2) # unused I2C: int = const(2) # unused
ONEWIRE = const(3) # unused ONEWIRE: int = const(3) # unused
BLE = const(4) BLE: int = const(4)
class Split(Module): class Split(Module):
@ -27,56 +31,58 @@ class Split(Module):
def __init__( def __init__(
self, self,
split_flip=True, split_flip: bool = True,
split_side=None, split_side: Optional[int] = None,
split_type=SplitType.UART, split_type: int = SplitType.UART,
split_target_left=True, split_target_left: bool = True,
uart_interval=20, uart_interval: int = 20,
data_pin=None, data_pin: Optional[Any] = None,
data_pin2=None, data_pin2: Optional[Any] = None,
target_left=True, target_left: bool = True,
uart_flip=True, uart_flip: bool = True,
debug_enabled=False, debug_enabled: bool = False,
): ) -> None:
self._is_target = True self._is_target: bool = True
self._uart_buffer = [] self._uart_buffer: UartBuffer = []
self.split_flip = split_flip self.split_flip: bool = split_flip
self.split_side = split_side self.split_side: Optional[int] = split_side
self.split_type = split_type self.split_type: int = split_type
self.split_target_left = split_target_left self.split_target_left: bool = split_target_left
self.split_offset = None self.split_offset: Optional[int] = None
self.data_pin = data_pin self.data_pin: Optional[Any] = data_pin
self.data_pin2 = data_pin2 self.data_pin2: Optional[Any] = data_pin2
self.target_left = target_left self.target_left: bool = target_left
self.uart_flip = uart_flip self.uart_flip: bool = uart_flip
self._is_target = True self._is_target: bool = True
self._uart = None self._uart: Optional[busio.UART] = None
self._uart_interval = uart_interval self._uart_interval: int = uart_interval
self._debug_enabled = debug_enabled self._debug_enabled: bool = debug_enabled
if self.split_type == SplitType.BLE: if self.split_type == SplitType.BLE:
try: try:
from adafruit_ble import BLERadio from adafruit_ble import BLEConnection, BLERadio
from adafruit_ble.advertising.standard import ( from adafruit_ble.advertising.standard import (
ProvideServicesAdvertisement, ProvideServicesAdvertisement,
) )
from adafruit_ble.services.nordic import UARTService from adafruit_ble.services.nordic import UARTService
self.ProvideServicesAdvertisement = ProvideServicesAdvertisement self.ProvideServicesAdvertisement: Type[
self.UARTService = UARTService ProvideServicesAdvertisement
] = ProvideServicesAdvertisement
self.UARTService: Type[UARTService] = UARTService
except ImportError: except ImportError:
print('BLE Import error') print('BLE Import error')
return # BLE isn't supported on this platform return # BLE isn't supported on this platform
self._ble = BLERadio() self._ble: BLERadio = BLERadio()
self._ble_last_scan = ticks_ms() - 5000 self._ble_last_scan: float = ticks_ms() - 5000
self._connection_count = 0 self._connection_count: int = 0
self._uart_connection = None self._uart_connection: Optional[BLEConnection] = None
self._advertisment = None self._advertisment: Optional[ProvideServicesAdvertisement] = None
self._advertising = False self._advertising: bool = False
self._psave_enable = False self._psave_enable: bool = False
def during_bootup(self, keyboard): def during_bootup(self, keyboard: KMKKeyboard) -> None:
# Set up name for target side detection and BLE advertisment # Set up name for target side detection and BLE advertisment
name = str(getmount('/').label) name: str = str(getmount('/').label)
if self.split_type == SplitType.BLE: if self.split_type == SplitType.BLE:
self._ble.name = name self._ble.name = name
else: else:
@ -128,7 +134,7 @@ class Split(Module):
for cidx in range(cols_to_calc): for cidx in range(cols_to_calc):
keyboard.coord_mapping.append(intify_coordinate(ridx, cidx)) keyboard.coord_mapping.append(intify_coordinate(ridx, cidx))
def before_matrix_scan(self, keyboard): def before_matrix_scan(self, keyboard: KMKKeyboard) -> None:
if self.split_type == SplitType.BLE: if self.split_type == SplitType.BLE:
self._check_all_connections() self._check_all_connections()
self._receive_ble(keyboard) self._receive_ble(keyboard)
@ -139,7 +145,7 @@ class Split(Module):
pass # Protocol needs written pass # Protocol needs written
return return
def after_matrix_scan(self, keyboard): def after_matrix_scan(self, keyboard: KMKKeyboard) -> None:
if keyboard.matrix_update: if keyboard.matrix_update:
if self.split_type == SplitType.UART and self._is_target: if self.split_type == SplitType.UART and self._is_target:
pass # explicit pass just for dev sanity... pass # explicit pass just for dev sanity...
@ -156,28 +162,28 @@ class Split(Module):
return return
def before_hid_send(self, keyboard): def before_hid_send(self, keyboard: KMKKeyboard) -> None:
if not self._is_target: if not self._is_target:
keyboard.hid_pending = False keyboard.hid_pending = False
return return
def after_hid_send(self, keyboard): def after_hid_send(self, keyboard: KMKKeyboard) -> None:
return return
def on_powersave_enable(self, keyboard): def on_powersave_enable(self, keyboard: KMKKeyboard) -> None:
if self.split_type == SplitType.BLE: if self.split_type == SplitType.BLE:
if self._uart_connection and not self._psave_enable: if self._uart_connection and not self._psave_enable:
self._uart_connection.connection_interval = self._uart_interval self._uart_connection.connection_interval = self._uart_interval
self._psave_enable = True self._psave_enable = True
def on_powersave_disable(self, keyboard): def on_powersave_disable(self, keyboard: KMKKeyboard) -> None:
if self.split_type == SplitType.BLE: if self.split_type == SplitType.BLE:
if self._uart_connection and self._psave_enable: if self._uart_connection and self._psave_enable:
self._uart_connection.connection_interval = 11.25 self._uart_connection.connection_interval = 11.25
self._psave_enable = False self._psave_enable = False
def _check_all_connections(self): def _check_all_connections(self) -> None:
'''Validates the correct number of BLE connections''' '''Validates the correct number of BLE connections'''
self._connection_count = len(self._ble.connections) self._connection_count = len(self._ble.connections)
if self._is_target and self._connection_count < 2: if self._is_target and self._connection_count < 2:
@ -185,7 +191,7 @@ class Split(Module):
elif not self._is_target and self._connection_count < 1: elif not self._is_target and self._connection_count < 1:
self._initiator_scan() self._initiator_scan()
def _initiator_scan(self): def _initiator_scan(self) -> None:
'''Scans for target device''' '''Scans for target device'''
self._uart = None self._uart = None
self._uart_connection = None self._uart_connection = None
@ -218,7 +224,7 @@ class Split(Module):
break break
self._ble.stop_scan() self._ble.stop_scan()
def _target_advertise(self): def _target_advertise(self) -> None:
'''Advertises the target for the initiator to find''' '''Advertises the target for the initiator to find'''
self._ble.stop_advertising() self._ble.stop_advertising()
if self._debug_enabled: if self._debug_enabled:
@ -240,15 +246,15 @@ class Split(Module):
break break
self._ble.stop_advertising() self._ble.stop_advertising()
def ble_rescan_timer(self): def ble_rescan_timer(self) -> bool:
'''If true, the rescan timer is up''' '''If true, the rescan timer is up'''
return bool(check_deadline(ticks_ms(), self._ble_last_scan) > 5000) return bool(check_deadline(ticks_ms(), self._ble_last_scan) > 5000)
def ble_time_reset(self): def ble_time_reset(self) -> None:
'''Resets the rescan timer''' '''Resets the rescan timer'''
self._ble_last_scan = ticks_ms() self._ble_last_scan = ticks_ms()
def _send_ble(self, update): def _send_ble(self, update: List) -> None:
if self._uart: if self._uart:
try: try:
if not self._is_target: if not self._is_target:
@ -266,7 +272,7 @@ class Split(Module):
self._uart_connection = None self._uart_connection = None
self._uart = None self._uart = None
def _receive_ble(self, keyboard): def _receive_ble(self, keyboard: KMKKeyboard) -> None:
if self._uart is not None and self._uart.in_waiting > 0 or self._uart_buffer: if self._uart is not None and self._uart.in_waiting > 0 or self._uart_buffer:
while self._uart.in_waiting >= 3: while self._uart.in_waiting >= 3:
self._uart_buffer.append(self._uart.read(3)) self._uart_buffer.append(self._uart.read(3))
@ -274,7 +280,7 @@ class Split(Module):
keyboard.secondary_matrix_update = bytearray(self._uart_buffer.pop(0)) keyboard.secondary_matrix_update = bytearray(self._uart_buffer.pop(0))
return return
def _send_uart(self, update): def _send_uart(self, update: List) -> None:
# Change offsets depending on where the data is going to match the correct # Change offsets depending on where the data is going to match the correct
# matrix location of the receiever # matrix location of the receiever
if self._is_target: if self._is_target:
@ -291,7 +297,7 @@ class Split(Module):
if self._uart is not None: if self._uart is not None:
self._uart.write(update) self._uart.write(update)
def _receive_uart(self, keyboard): def _receive_uart(self, keyboard: KMKKeyboard) -> None:
if self._uart is not None and self._uart.in_waiting > 0 or self._uart_buffer: if self._uart is not None and self._uart.in_waiting > 0 or self._uart_buffer:
if self._uart.in_waiting >= 60: if self._uart.in_waiting >= 60:
# This is a dirty hack to prevent crashes in unrealistic cases # This is a dirty hack to prevent crashes in unrealistic cases

View File

@ -1,3 +1,14 @@
import sys
from kmk.consts import TYPING_PLATFORMS
if sys.platform in TYPING_PLATFORMS:
from typing import List, Optional, Tuple, Union
# Avoid cyclical imports
from kmk.keys import ConsumerKey, Key, ModifierKey
class AttrDict(dict): class AttrDict(dict):
''' '''
Primitive support for accessing dictionary entries in dot notation. Primitive support for accessing dictionary entries in dot notation.
@ -8,36 +19,43 @@ class AttrDict(dict):
''' '''
def __getattr__(self, key): def __getattr__(self, key):
# type: (str) -> Optional[Union[Key, ModifierKey, ConsumerKey]]
return self[key] return self[key]
class LayerKeyMeta: class LayerKeyMeta:
def __init__(self, layer, kc=None): def __init__(self, layer, kc=None):
self.layer = layer # type: (int, Optional[Key]) -> None
self.kc = kc self.layer = layer # type: int
self.kc = kc # type: Optional[Key]
class ModTapKeyMeta: class ModTapKeyMeta:
def __init__(self, kc=None, mods=None): def __init__(self, kc=None, mods=None):
self.mods = mods # type: (Optional[Key], Optional[List[Key]]) -> None
self.kc = kc self.mods = mods # type: Optional[List[Key]]
self.kc = kc # type: Optional[Key]
class KeySequenceMeta: class KeySequenceMeta:
def __init__(self, seq): def __init__(self, seq):
self.seq = seq # type: (List[Key]) -> None
self.seq = seq # type: List[Key]
class KeySeqSleepMeta: class KeySeqSleepMeta:
def __init__(self, ms): def __init__(self, ms):
self.ms = ms # type: (float) -> None
self.ms = ms # type: float
class UnicodeModeKeyMeta: class UnicodeModeKeyMeta:
def __init__(self, mode): def __init__(self, mode):
self.mode = mode # type: (int) -> None
self.mode = mode # type: int
class TapDanceKeyMeta: class TapDanceKeyMeta:
def __init__(self, codes): def __init__(self, codes):
self.codes = codes # type: (Tuple[Key, ...]) -> None
self.codes = codes # type: Tuple[Key, ...]

View File

@ -22,3 +22,27 @@ exclude = '''
| mnt | mnt
)/ )/
''' '''
[tool.pyright]
strict = ["kmk"]
typeCheckingMode = "strict"
include = ["kmk"]
exclude = [
"hardware",
".venv",
"user_keymaps",
"boards",
".git"
]
venvPath = ".venv"
# stops constant reporting of missing board module etc.
reportMissingModuleSource = false
# reports missing typestubs allowing for a code action to
# create new library typestubs
reportMissingTypeStubs = true
pythonVersion = "3.6"
[tool.mypy]
exclude = "boards/|user_keymaps/"
ignore_missing_imports = true
python_version = "3.6"

View File

@ -0,0 +1,208 @@
"""
This type stub file was generated by pyright.
"""
import sys
import _bleio
from .services import Service
from .advertising import Advertisement
"""
This module provides higher-level BLE (Bluetooth Low Energy) functionality,
building on the native `_bleio` module.
"""
if sys.implementation.name == "circuitpython" and sys.implementation.version[0] <= 4:
...
__version__ = ...
__repo__ = ...
class BLEConnection:
"""
Represents a connection to a peer BLE device.
It acts as a map from a `Service` type to a `Service` instance for the connection.
:param bleio_connection _bleio.Connection: the native `_bleio.Connection` object to wrap
"""
def __init__(self, bleio_connection) -> None:
...
def __contains__(self, key): # -> bool:
"""
Allows easy testing for a particular Service class or a particular UUID
associated with this connection.
Example::
if UARTService in connection:
# do something
if StandardUUID(0x1234) in connection:
# do something
"""
...
def __getitem__(self, key): # -> None:
"""Return the Service for the given Service class or uuid, if any."""
...
@property
def connected(self):
"""True if the connection to the peer is still active."""
...
@property
def paired(self):
"""True if the paired to the peer."""
...
@property
def connection_interval(self):
"""Time between transmissions in milliseconds. Will be multiple of 1.25ms. Lower numbers
increase speed and decrease latency but increase power consumption.
When setting connection_interval, the peer may reject the new interval and
`connection_interval` will then remain the same.
Apple has additional guidelines that dictate should be a multiple of 15ms except if HID
is available. When HID is available Apple devices may accept 11.25ms intervals."""
...
@connection_interval.setter
def connection_interval(self, value): # -> None:
...
def pair(self, *, bond=...):
"""Pair to the peer to increase security of the connection."""
...
def disconnect(self): # -> None:
"""Disconnect from peer."""
...
class BLERadio:
"""
BLERadio provides the interfaces for BLE advertising,
scanning for advertisements, and connecting to peers. There may be
multiple connections active at once.
It uses this library's `Advertisement` classes and the `BLEConnection` class."""
def __init__(self, adapter=...) -> None:
"""If no adapter is supplied, use the built-in `_bleio.adapter`.
If no built-in adapter is available, raise `RuntimeError`.
"""
...
def start_advertising(self, advertisement, scan_response=..., interval=..., timeout=...): # -> None:
"""
Starts advertising the given advertisement.
:param buf scan_response: scan response data packet bytes.
If ``None``, a default scan response will be generated that includes
`BLERadio.name` and `BLERadio.tx_power`.
:param float interval: advertising interval, in seconds
:param int timeout: advertising timeout in seconds.
If None, no timeout.
``timeout`` is not available in CircuitPython 5.x and must be `None`.
"""
...
def stop_advertising(self): # -> None:
"""Stops advertising."""
...
def start_scan(self, *advertisement_types, buffer_size=..., extended=..., timeout=..., interval=..., window=..., minimum_rssi=..., active=...): # -> Generator[Advertisement | Unknown, None, None]:
"""
Starts scanning. Returns an iterator of advertisement objects of the types given in
advertisement_types. The iterator will block until an advertisement is heard or the scan
times out.
If any ``advertisement_types`` are given, only Advertisements of those types are produced
by the returned iterator. If none are given then `Advertisement` objects will be
returned.
Advertisements and scan responses are filtered and returned separately.
:param int buffer_size: the maximum number of advertising bytes to buffer.
:param bool extended: When True, support extended advertising packets.
Increasing buffer_size is recommended when this is set.
:param float timeout: the scan timeout in seconds.
If None, will scan until `stop_scan` is called.
:param float interval: the interval (in seconds) between the start
of two consecutive scan windows
Must be in the range 0.0025 - 40.959375 seconds.
:param float window: the duration (in seconds) to scan a single BLE channel.
window must be <= interval.
:param int minimum_rssi: the minimum rssi of entries to return.
:param bool active: request and retrieve scan responses for scannable advertisements.
:return: If any ``advertisement_types`` are given,
only Advertisements of those types are produced by the returned iterator.
If none are given then `Advertisement` objects will be returned.
:rtype: iterable
"""
...
def stop_scan(self): # -> None:
"""Stops any active scan.
The scan results iterator will return any buffered results and then raise StopIteration
once empty."""
...
def connect(self, advertisement, *, timeout=...):
"""
Initiates a `BLEConnection` to the peer that advertised the given advertisement.
:param advertisement Advertisement: An `Advertisement` or a subclass of `Advertisement`
:param timeout float: how long to wait for a connection
:return: the connection to the peer
:rtype: BLEConnection
"""
...
@property
def connected(self): # -> bool:
"""True if any peers are connected."""
...
@property
def connections(self): # -> tuple[None, ...]:
"""A tuple of active `BLEConnection` objects."""
...
@property
def name(self): # -> str:
"""The name for this device. Used in advertisements and
as the Device Name in the Generic Access Service, available to a connected peer.
"""
...
@name.setter
def name(self, value): # -> None:
...
@property
def tx_power(self): # -> Literal[0]:
"""Transmit power, in dBm."""
...
@tx_power.setter
def tx_power(self, value):
...
@property
def address_bytes(self): # -> bytes:
"""The device address, as a ``bytes()`` object of length 6."""
...
@property
def advertising(self): # -> bool:
"""The advertising state"""
...

View File

@ -0,0 +1,173 @@
"""
This type stub file was generated by pyright.
"""
import struct
"""
Advertising is the first phase of BLE where devices can broadcast
"""
def to_hex(seq): # -> str:
"""Pretty prints a byte sequence as hex values."""
...
def to_bytes_literal(seq): # -> str:
"""Prints a byte sequence as a Python bytes literal that only uses hex encoding."""
...
def decode_data(data, *, key_encoding=...): # -> dict[Unknown, Unknown]:
"""Helper which decodes length encoded structures into a dictionary with the given key
encoding."""
...
def compute_length(data_dict, *, key_encoding=...): # -> int:
"""Computes the length of the encoded data dictionary."""
...
def encode_data(data_dict, *, key_encoding=...): # -> bytes:
"""Helper which encodes dictionaries into length encoded structures with the given key
encoding."""
...
class AdvertisingDataField:
"""Top level class for any descriptor classes that live in Advertisement or its subclasses."""
...
class AdvertisingFlag:
"""A single bit flag within an AdvertisingFlags object."""
def __init__(self, bit_position) -> None:
...
def __get__(self, obj, cls): # -> AdvertisingFlag:
...
def __set__(self, obj, value): # -> None:
...
class AdvertisingFlags(AdvertisingDataField):
"""Standard advertising flags"""
limited_discovery = ...
general_discovery = ...
le_only = ...
def __init__(self, advertisement, advertising_data_type) -> None:
...
def __len__(self): # -> Literal[1]:
...
def __bytes__(self): # -> bytes:
...
def __str__(self) -> str:
...
class String(AdvertisingDataField):
"""UTF-8 encoded string in an Advertisement.
Not null terminated once encoded because length is always transmitted."""
def __init__(self, *, advertising_data_type) -> None:
...
def __get__(self, obj, cls): # -> String | str | None:
...
def __set__(self, obj, value): # -> None:
...
class Struct(AdvertisingDataField):
"""`struct` encoded data in an Advertisement."""
def __init__(self, struct_format, *, advertising_data_type) -> None:
...
def __get__(self, obj, cls): # -> Struct | Any | None:
...
def __set__(self, obj, value): # -> None:
...
class LazyObjectField(AdvertisingDataField):
"""Non-data descriptor useful for lazily binding a complex object to an advertisement object."""
def __init__(self, cls, attribute_name, *, advertising_data_type, **kwargs) -> None:
...
def __get__(self, obj, cls): # -> LazyObjectField | None:
...
@property
def advertising_data_type(self):
"""Return the data type value used to indicate this field."""
...
class Advertisement:
"""Core Advertisement type.
The class attribute ``match_prefixes``, if not ``None``, is a tuple of
bytestring prefixes to match against the multiple data structures in the advertisement.
"""
match_prefixes = ...
_prefix_bytes = ...
flags = ...
short_name = ...
complete_name = ...
tx_power = ...
appearance = ...
def __init__(self, *, entry=...) -> None:
"""Create an empty advertising packet or one from a ScanEntry."""
...
@property
def rssi(self): # -> None:
"""Signal strength of the scanned advertisement. Only available on Advertisements returned
from `BLERadio.start_scan()`. (read-only)"""
...
@classmethod
def get_prefix_bytes(cls): # -> bytes | Any:
"""Return a merged version of match_prefixes as a single bytes object,
with length headers.
"""
...
@classmethod
def matches(cls, entry):
"""Returns ``True`` if the given `_bleio.ScanEntry` advertisement fields
matches all of the given prefixes in the `match_prefixes` tuple attribute.
Subclasses may override this to match any instead of all.
"""
...
@classmethod
def matches_prefixes(cls, entry, *, all_):
"""Returns ``True`` if the given `_bleio.ScanEntry` advertisement fields
match any or all of the given prefixes in the `match_prefixes` tuple attribute.
If ``all_`` is ``True``, all the prefixes must match. If ``all_`` is ``False``,
returns ``True`` if at least one of the prefixes match.
"""
...
def __bytes__(self): # -> bytes:
"""The raw packet bytes."""
...
def __str__(self) -> str:
...
def __len__(self): # -> int:
...
def __repr__(self): # -> str:
...

View File

@ -0,0 +1,122 @@
"""
This type stub file was generated by pyright.
"""
from . import Advertisement, AdvertisingDataField
"""
:py:mod:`~adafruit_ble.advertising.standard`
====================================================
This module provides BLE standard defined advertisements. The Advertisements are single purpose
even though multiple purposes may actually be present in a single packet.
"""
__version__ = ...
__repo__ = ...
class BoundServiceList:
"""Sequence-like object of Service UUID objects. It stores both standard and vendor UUIDs."""
def __init__(self, advertisement, *, standard_services, vendor_services) -> None:
...
def __contains__(self, key): # -> bool:
...
def __iter__(self): # -> Iterator[Unknown]:
...
def append(self, service): # -> None:
"""Append a service to the list."""
...
def extend(self, services): # -> None:
"""Appends all services in the iterable to the list."""
...
def __str__(self) -> str:
...
class ServiceList(AdvertisingDataField):
"""Descriptor for a list of Service UUIDs that lazily binds a corresponding BoundServiceList."""
def __init__(self, *, standard_services, vendor_services) -> None:
...
def __get__(self, obj, cls): # -> ServiceList | tuple[()]:
...
class ProvideServicesAdvertisement(Advertisement):
"""Advertise what services that the device makes available upon connection."""
match_prefixes = ...
services = ...
def __init__(self, *services, entry=...) -> None:
...
@classmethod
def matches(cls, entry):
"""Only one kind of service list need be present in a ProvideServicesAdvertisement,
so override the default behavior and match any prefix, not all.
"""
...
class SolicitServicesAdvertisement(Advertisement):
"""Advertise what services the device would like to use over a connection."""
match_prefixes = ...
solicited_services = ...
def __init__(self, *services, entry=...) -> None:
...
class ManufacturerData(AdvertisingDataField):
"""Encapsulates manufacturer specific keyed data bytes. The manufacturer is identified by the
company_id and the data is structured like an advertisement with a configurable key
format. The order of the serialized data is determined by the order that the
`ManufacturerDataField` attributes are set in - this can be useful for
`match_prefixes` in an `Advertisement` sub-class."""
def __init__(self, obj, *, advertising_data_type=..., company_id, key_encoding=...) -> None:
...
def __len__(self): # -> int:
...
def __bytes__(self): # -> bytes:
...
def __str__(self) -> str:
...
class ManufacturerDataField:
"""A single piece of data within the manufacturer specific data. The format can be repeated."""
def __init__(self, key, value_format, field_names=...) -> None:
...
def __get__(self, obj, cls): # -> ManufacturerDataField | mdf_tuple | Any | Tuple[Any, ...] | tuple[None, ...] | None:
...
def __set__(self, obj, value): # -> None:
...
class ServiceData(AdvertisingDataField):
"""Encapsulates service data. It is read as a memoryview which can be manipulated or set as a
bytearray to change the size."""
def __init__(self, service) -> None:
...
def __get__(self, obj, cls): # -> ServiceData | memoryview | None:
...
def __set__(self, obj, value): # -> None:
...

View File

@ -0,0 +1,55 @@
"""
This type stub file was generated by pyright.
"""
import _bleio
"""
:py:mod:`~adafruit_ble.attributes`
====================================================
This module provides definitions common to all kinds of BLE attributes,
specifically characteristics and descriptors.
"""
__version__ = ...
__repo__ = ...
class Attribute:
"""Constants describing security levels.
.. data:: NO_ACCESS
security mode: access not allowed
.. data:: OPEN
security_mode: no security (link is not encrypted)
.. data:: ENCRYPT_NO_MITM
security_mode: unauthenticated encryption, without man-in-the-middle protection
.. data:: ENCRYPT_WITH_MITM
security_mode: authenticated encryption, with man-in-the-middle protection
.. data:: LESC_ENCRYPT_WITH_MITM
security_mode: LESC encryption, with man-in-the-middle protection
.. data:: SIGNED_NO_MITM
security_mode: unauthenticated data signing, without man-in-the-middle protection
.. data:: SIGNED_WITH_MITM
security_mode: authenticated data signing, without man-in-the-middle protection"""
NO_ACCESS = ...
OPEN = ...
ENCRYPT_NO_MITM = ...
ENCRYPT_WITH_MITM = ...
LESC_ENCRYPT_WITH_MITM = ...
SIGNED_NO_MITM = ...
SIGNED_WITH_MITM = ...

View File

@ -0,0 +1,120 @@
"""
This type stub file was generated by pyright.
"""
import struct
import _bleio
from ..attributes import Attribute
"""
This module provides core BLE characteristic classes that are used within Services.
"""
__version__ = ...
__repo__ = ...
class Characteristic:
"""
Top level Characteristic class that does basic binding.
:param UUID uuid: The uuid of the characteristic
:param int properties: The properties of the characteristic,
specified as a bitmask of these values bitwise-or'd together:
`BROADCAST`, `INDICATE`, `NOTIFY`, `READ`, `WRITE`, `WRITE_NO_RESPONSE`.
:param int read_perm: Specifies whether the characteristic can be read by a client,
and if so, which security mode is required.
Must be one of the integer values `Attribute.NO_ACCESS`, `Attribute.OPEN`,
`Attribute.ENCRYPT_NO_MITM`, `Attribute.ENCRYPT_WITH_MITM`,
`Attribute.LESC_ENCRYPT_WITH_MITM`,
`Attribute.SIGNED_NO_MITM`, or `Attribute.SIGNED_WITH_MITM`.
:param int write_perm: Specifies whether the characteristic can be written by a client,
and if so, which security mode is required. Values allowed are the same as ``read_perm``.
:param int max_length: Maximum length in bytes of the characteristic value. The maximum allowed
by the BLE specification is 512. On nRF, if ``fixed_length`` is ``True``, the maximum
is 510. The default value is 20, which is the maximum
number of data bytes that fit in a single BLE 4.x ATT packet.
:param bool fixed_length: True if the characteristic value is of fixed length.
:param buf initial_value: The initial value for this characteristic. If not given, will be
filled with zeros.
.. data:: BROADCAST
property: allowed in advertising packets
.. data:: INDICATE
property: server will indicate to the client when the value is set and wait for a response
.. data:: NOTIFY
property: server will notify the client when the value is set
.. data:: READ
property: clients may read this characteristic
.. data:: WRITE
property: clients may write this characteristic; a response will be sent back
.. data:: WRITE_NO_RESPONSE
property: clients may write this characteristic; no response will be sent back"""
BROADCAST = ...
INDICATE = ...
NOTIFY = ...
READ = ...
WRITE = ...
WRITE_NO_RESPONSE = ...
def __init__(self, *, uuid=..., properties=..., read_perm=..., write_perm=..., max_length=..., fixed_length=..., initial_value=...) -> None:
...
def __get__(self, service, cls=...): # -> Characteristic:
...
def __set__(self, service, value): # -> None:
...
class ComplexCharacteristic:
"""
Characteristic class that does complex binding where the subclass returns a full object for
interacting with the characteristic data. The Characteristic itself will be shadowed once it
has been bound to the corresponding instance attribute.
"""
def __init__(self, *, uuid=..., properties=..., read_perm=..., write_perm=..., max_length=..., fixed_length=..., initial_value=...) -> None:
...
def bind(self, service):
"""Binds the characteristic to the local Service or remote Characteristic object given."""
...
def __get__(self, service, cls=...): # -> ComplexCharacteristic:
...
class StructCharacteristic(Characteristic):
"""
Data descriptor for a structure with a fixed format.
:param struct_format: a `struct` format string describing how to pack multiple values
into the characteristic bytestring
:param UUID uuid: The uuid of the characteristic
:param int properties: see `Characteristic`
:param int read_perm: see `Characteristic`
:param int write_perm: see `Characteristic`
:param buf initial_value: see `Characteristic`
"""
def __init__(self, struct_format, *, uuid=..., properties=..., read_perm=..., write_perm=..., initial_value=...) -> None:
...
def __get__(self, obj, cls=...): # -> StructCharacteristic | Tuple[Any, ...] | None:
...
def __set__(self, obj, value): # -> None:
...

View File

@ -0,0 +1,49 @@
"""
This type stub file was generated by pyright.
"""
from . import ComplexCharacteristic
"""
`stream`
====================================================
This module provides stream characteristics that bind readable or writable objects to the Service
object they are on.
"""
__version__ = ...
__repo__ = ...
class BoundWriteStream:
"""Writes data out to the peer."""
def __init__(self, bound_characteristic) -> None:
...
def write(self, buf): # -> None:
"""Write data from buf out to the peer."""
...
class StreamOut(ComplexCharacteristic):
"""Output stream from the Service server."""
def __init__(self, *, uuid=..., timeout=..., buffer_size=..., properties=..., read_perm=..., write_perm=...) -> None:
...
def bind(self, service): # -> CharacteristicBuffer | BoundWriteStream:
"""Binds the characteristic to the given Service."""
...
class StreamIn(ComplexCharacteristic):
"""Input stream into the Service server."""
def __init__(self, *, uuid=..., timeout=..., buffer_size=..., properties=..., write_perm=...) -> None:
...
def bind(self, service): # -> BoundWriteStream | CharacteristicBuffer:
"""Binds the characteristic to the given Service."""
...

View File

@ -0,0 +1,36 @@
"""
This type stub file was generated by pyright.
"""
import _bleio
from ..characteristics import Characteristic, ComplexCharacteristic
"""
This module provides the top level Service definition.
"""
__version__ = ...
__repo__ = ...
class Service:
"""Top level Service class that handles the hard work of binding to a local or remote service.
Providers of a local service should instantiate their Service with service=None, the default.
The local Service's characteristics will be lazily made available to clients as they are used
locally. In other words, a characteristic won't be available to remote clients until it has
been read or written locally.
To use a remote Service, get the item with the key of the Service type on the
`BLEConnection`. For example, ``connection[UartService]`` will return the UartService
instance for the connection's peer.
"""
def __init__(self, *, service=..., secondary=..., **initial_values) -> None:
...
@property
def remote(self): # -> bool:
"""True if the service is provided by a peer and accessed remotely."""
...

View File

@ -0,0 +1,77 @@
"""
This type stub file was generated by pyright.
"""
from . import Service
"""
`nordic`
====================================================
This module provides Services used by Nordic Semiconductors.
"""
__version__ = ...
__repo__ = ...
class UARTService(Service):
"""
Provide UART-like functionality via the Nordic NUS service.
:param int timeout: the timeout in seconds to wait
for the first character and between subsequent characters.
:param int buffer_size: buffer up to this many bytes.
If more bytes are received, older bytes will be discarded.
See ``examples/ble_uart_echo_test.py`` for a usage example.
"""
uuid = ...
_server_tx = ...
_server_rx = ...
def __init__(self, service=...) -> None:
...
def read(self, nbytes=...):
"""
Read characters. If ``nbytes`` is specified then read at most that many bytes.
Otherwise, read everything that arrives until the connection times out.
Providing the number of bytes expected is highly recommended because it will be faster.
:return: Data read
:rtype: bytes or None
"""
...
def readinto(self, buf, nbytes=...):
"""
Read bytes into the ``buf``. If ``nbytes`` is specified then read at most
that many bytes. Otherwise, read at most ``len(buf)`` bytes.
:return: number of bytes read and stored into ``buf``
:rtype: int or None (on a non-blocking error)
"""
...
def readline(self):
"""
Read a line, ending in a newline character.
:return: the line read
:rtype: bytes or None
"""
...
@property
def in_waiting(self):
"""The number of bytes in the input buffer, available to be read."""
...
def reset_input_buffer(self): # -> None:
"""Discard any unread characters in the input buffer."""
...
def write(self, buf): # -> None:
"""Write a buffer of bytes."""
...

View File

@ -0,0 +1,48 @@
"""
This type stub file was generated by pyright.
"""
import struct
import _bleio
"""
This module provides core Unique ID (UUID) classes.
"""
__version__ = ...
__repo__ = ...
class UUID:
"""Top level UUID"""
def __hash__(self) -> int:
...
def __eq__(self, other) -> bool:
...
def __str__(self) -> str:
...
def __bytes__(self): # -> bytes:
...
def pack_into(self, buffer, offset=...): # -> None:
"""Packs the UUID into the buffer at the given offset."""
...
class StandardUUID(UUID):
"""Standard 16-bit UUID defined by the Bluetooth SIG."""
def __init__(self, uuid16) -> None:
...
class VendorUUID(UUID):
"""Vendor defined, 128-bit UUID."""
def __init__(self, uuid128) -> None:
...

5
typings/micropython.pyi Normal file
View File

@ -0,0 +1,5 @@
from typing import TypeVar
T = TypeVar('T')
def const(x: T) -> T: ...