diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 6abd35f..bf04ff6 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -11,7 +11,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
+ python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
diff --git a/MANIFEST.in b/MANIFEST.in
index cf221c5..3732228 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,2 +1,9 @@
graft obniz/obniz
graft obniz/parts
+
+# documentation assets under obniz/parts have no runtime purpose --
+# excluding them keeps the wheel small (photos/GIFs alone are ~13MB)
+global-exclude *.jpg *.jpeg *.png *.gif *.fzz
+recursive-exclude obniz/parts index.json
+recursive-exclude obniz/parts README.md README-ja.md
+global-exclude __pycache__ *.py[cod]
diff --git a/Pipfile b/Pipfile
index 79575ba..f935054 100644
--- a/Pipfile
+++ b/Pipfile
@@ -7,15 +7,14 @@ name = "pypi"
test = "pytest -vv"
lint = "sh -c 'flake8 && pipenv run format --check'"
format = "black obniz/ tests/ "
-build = "sh -c 'rm -rf build/ dist/ obniz.egg-info/ && python setup.py sdist bdist_wheel'"
+build = "sh -c 'rm -rf build/ dist/ obniz.egg-info/ && python -m build'"
testsubmit = "twine upload --repository testpypi dist/*"
# no shortcut for production submit for safe
[packages]
-pyee = "==6.0.0"
-websockets = ">=12,<14"
-attrdict3 = "==2.0.2"
-semver = "==2.8.1"
+pyee = "==13.0.1"
+websockets = ">=14.2,<16"
+semver = "==3.0.4"
[dev-packages]
# "black" requires python 3.6+
@@ -30,6 +29,7 @@ pep8-naming = "*"
pytest = "*"
pytest-mock = "*"
pyyaml = "*"
+build = "*"
setuptools = "*"
wheel = "*"
twine = "*"
diff --git a/Pipfile.lock b/Pipfile.lock
index dc05ba8..79a349d 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "8ec6877aaef86f34ec835dfbb181b916c7b85a9a4af47e1a075cdd4c71da536c"
+ "sha256": "f49b86c142c03c44d8ceef2df8f799023058d169b0ab462186cbab59b3fe7935"
},
"pipfile-spec": 6,
"requires": {},
@@ -14,130 +14,107 @@
]
},
"default": {
- "attrdict3": {
- "hashes": [
- "sha256:004c171ca1120cc1755701db99d7fa4944afb1e68950434efdaa542513335fe8",
- "sha256:a98b72de6a3f20b0997cc7efbba3555af6558ed9a97de4468a3f81cac11595dc"
- ],
- "index": "pypi",
- "version": "==2.0.2"
- },
"pyee": {
"hashes": [
- "sha256:a9c9b60e8693a260dd942ef5a71358cfcbba15792d5e72caf0e3c891c4e91c3b",
- "sha256:dbe44f61c40a995d2bdfd83d9fcb87ae025882d2c7f366513325e3daa09d7ede"
+ "sha256:0b931f7c14535667ed4c7e0d531716368715e860b988770fc7eb8578d1f67fc8",
+ "sha256:af2f8fede4171ef667dfded53f96e2ed0d6e6bd7ee3bb46437f77e3b57689228"
],
"index": "pypi",
- "version": "==6.0.0"
+ "markers": "python_version >= '3.8'",
+ "version": "==13.0.1"
},
"semver": {
"hashes": [
- "sha256:41c9aa26c67dc16c54be13074c352ab666bce1fa219c7110e8f03374cd4206b0",
- "sha256:5b09010a66d9a3837211bb7ae5a20d10ba88f8cb49e92cb139a69ef90d5060d8"
+ "sha256:9c824d87ba7f7ab4a1890799cec8596f15c1241cb473404ea1cb0c55e4b04746",
+ "sha256:afc7d8c584a5ed0a11033af086e8af226a9c0b206f313e0301f8dd7b6b589602"
],
"index": "pypi",
- "version": "==2.8.1"
+ "markers": "python_version >= '3.7'",
+ "version": "==3.0.4"
},
- "six": {
+ "typing-extensions": {
"hashes": [
- "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274",
- "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"
+ "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8",
+ "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'",
- "version": "==1.17.0"
+ "markers": "python_version >= '3.9'",
+ "version": "==4.16.0"
},
"websockets": {
"hashes": [
- "sha256:004280a140f220c812e65f36944a9ca92d766b6cc4560be652a0a3883a79ed8a",
- "sha256:035233b7531fb92a76beefcbf479504db8c72eb3bff41da55aecce3a0f729e54",
- "sha256:149e622dc48c10ccc3d2760e5f36753db9cacf3ad7bc7bbbfd7d9c819e286f23",
- "sha256:163e7277e1a0bd9fb3c8842a71661ad19c6aa7bb3d6678dc7f89b17fbcc4aeb7",
- "sha256:18503d2c5f3943e93819238bf20df71982d193f73dcecd26c94514f417f6b135",
- "sha256:1971e62d2caa443e57588e1d82d15f663b29ff9dfe7446d9964a4b6f12c1e700",
- "sha256:204e5107f43095012b00f1451374693267adbb832d29966a01ecc4ce1db26faf",
- "sha256:2510c09d8e8df777177ee3d40cd35450dc169a81e747455cc4197e63f7e7bfe5",
- "sha256:25c35bf84bf7c7369d247f0b8cfa157f989862c49104c5cf85cb5436a641d93e",
- "sha256:2f85cf4f2a1ba8f602298a853cec8526c2ca42a9a4b947ec236eaedb8f2dc80c",
- "sha256:308e20f22c2c77f3f39caca508e765f8725020b84aa963474e18c59accbf4c02",
- "sha256:325b1ccdbf5e5725fdcb1b0e9ad4d2545056479d0eee392c291c1bf76206435a",
- "sha256:327b74e915cf13c5931334c61e1a41040e365d380f812513a255aa804b183418",
- "sha256:346bee67a65f189e0e33f520f253d5147ab76ae42493804319b5716e46dddf0f",
- "sha256:38377f8b0cdeee97c552d20cf1865695fcd56aba155ad1b4ca8779a5b6ef4ac3",
- "sha256:3c78383585f47ccb0fcf186dcb8a43f5438bd7d8f47d69e0b56f71bf431a0a68",
- "sha256:4059f790b6ae8768471cddb65d3c4fe4792b0ab48e154c9f0a04cefaabcd5978",
- "sha256:459bf774c754c35dbb487360b12c5727adab887f1622b8aed5755880a21c4a20",
- "sha256:463e1c6ec853202dd3657f156123d6b4dad0c546ea2e2e38be2b3f7c5b8e7295",
- "sha256:4676df3fe46956fbb0437d8800cd5f2b6d41143b6e7e842e60554398432cf29b",
- "sha256:485307243237328c022bc908b90e4457d0daa8b5cf4b3723fd3c4a8012fce4c6",
- "sha256:48a2ef1381632a2f0cb4efeff34efa97901c9fbc118e01951ad7cfc10601a9bb",
- "sha256:4b889dbd1342820cc210ba44307cf75ae5f2f96226c0038094455a96e64fb07a",
- "sha256:586a356928692c1fed0eca68b4d1c2cbbd1ca2acf2ac7e7ebd3b9052582deefa",
- "sha256:58cf7e75dbf7e566088b07e36ea2e3e2bd5676e22216e4cad108d4df4a7402a0",
- "sha256:5993260f483d05a9737073be197371940c01b257cc45ae3f1d5d7adb371b266a",
- "sha256:5dd6da9bec02735931fccec99d97c29f47cc61f644264eb995ad6c0c27667238",
- "sha256:5f2e75431f8dc4a47f31565a6e1355fb4f2ecaa99d6b89737527ea917066e26c",
- "sha256:5f9fee94ebafbc3117c30be1844ed01a3b177bb6e39088bc6b2fa1dc15572084",
- "sha256:61fc0dfcda609cda0fc9fe7977694c0c59cf9d749fbb17f4e9483929e3c48a19",
- "sha256:624459daabeb310d3815b276c1adef475b3e6804abaf2d9d2c061c319f7f187d",
- "sha256:62d516c325e6540e8a57b94abefc3459d7dab8ce52ac75c96cad5549e187e3a7",
- "sha256:6548f29b0e401eea2b967b2fdc1c7c7b5ebb3eeb470ed23a54cd45ef078a0db9",
- "sha256:6d2aad13a200e5934f5a6767492fb07151e1de1d6079c003ab31e1823733ae79",
- "sha256:6d6855bbe70119872c05107e38fbc7f96b1d8cb047d95c2c50869a46c65a8e96",
- "sha256:70c5be9f416aa72aab7a2a76c90ae0a4fe2755c1816c153c1a2bcc3333ce4ce6",
- "sha256:730f42125ccb14602f455155084f978bd9e8e57e89b569b4d7f0f0c17a448ffe",
- "sha256:7a43cfdcddd07f4ca2b1afb459824dd3c6d53a51410636a2c7fc97b9a8cf4842",
- "sha256:7bd6abf1e070a6b72bfeb71049d6ad286852e285f146682bf30d0296f5fbadfa",
- "sha256:7c1e90228c2f5cdde263253fa5db63e6653f1c00e7ec64108065a0b9713fa1b3",
- "sha256:7c65ffa900e7cc958cd088b9a9157a8141c991f8c53d11087e6fb7277a03f81d",
- "sha256:80c421e07973a89fbdd93e6f2003c17d20b69010458d3a8e37fb47874bd67d51",
- "sha256:82d0ba76371769d6a4e56f7e83bb8e81846d17a6190971e38b5de108bde9b0d7",
- "sha256:83f91d8a9bb404b8c2c41a707ac7f7f75b9442a0a876df295de27251a856ad09",
- "sha256:87c6e35319b46b99e168eb98472d6c7d8634ee37750d7693656dc766395df096",
- "sha256:8d23b88b9388ed85c6faf0e74d8dec4f4d3baf3ecf20a65a47b836d56260d4b9",
- "sha256:9156c45750b37337f7b0b00e6248991a047be4aa44554c9886fe6bdd605aab3b",
- "sha256:91a0fa841646320ec0d3accdff5b757b06e2e5c86ba32af2e0815c96c7a603c5",
- "sha256:95858ca14a9f6fa8413d29e0a585b31b278388aa775b8a81fa24830123874678",
- "sha256:95df24ca1e1bd93bbca51d94dd049a984609687cb2fb08a7f2c56ac84e9816ea",
- "sha256:9b37c184f8b976f0c0a231a5f3d6efe10807d41ccbe4488df8c74174805eea7d",
- "sha256:9b6f347deb3dcfbfde1c20baa21c2ac0751afaa73e64e5b693bb2b848efeaa49",
- "sha256:9d75baf00138f80b48f1eac72ad1535aac0b6461265a0bcad391fc5aba875cfc",
- "sha256:9ef8aa8bdbac47f4968a5d66462a2a0935d044bf35c0e5a8af152d58516dbeb5",
- "sha256:a11e38ad8922c7961447f35c7b17bffa15de4d17c70abd07bfbe12d6faa3e027",
- "sha256:a1b54689e38d1279a51d11e3467dd2f3a50f5f2e879012ce8f2d6943f00e83f0",
- "sha256:a3b3366087c1bc0a2795111edcadddb8b3b59509d5db5d7ea3fdd69f954a8878",
- "sha256:a569eb1b05d72f9bce2ebd28a1ce2054311b66677fcd46cf36204ad23acead8c",
- "sha256:a7affedeb43a70351bb811dadf49493c9cfd1ed94c9c70095fd177e9cc1541fa",
- "sha256:a9a396a6ad26130cdae92ae10c36af09d9bfe6cafe69670fd3b6da9b07b4044f",
- "sha256:a9ab1e71d3d2e54a0aa646ab6d4eebfaa5f416fe78dfe4da2839525dc5d765c6",
- "sha256:a9cd1af7e18e5221d2878378fbc287a14cd527fdd5939ed56a18df8a31136bb2",
- "sha256:a9dcaf8b0cc72a392760bb8755922c03e17a5a54e08cca58e8b74f6902b433cf",
- "sha256:b9d7439d7fab4dce00570bb906875734df13d9faa4b48e261c440a5fec6d9708",
- "sha256:bcc03c8b72267e97b49149e4863d57c2d77f13fae12066622dc78fe322490fe6",
- "sha256:c11d4d16e133f6df8916cc5b7e3e96ee4c44c936717d684a94f48f82edb7c92f",
- "sha256:c1dca61c6db1166c48b95198c0b7d9c990b30c756fc2923cc66f68d17dc558fd",
- "sha256:c518e84bb59c2baae725accd355c8dc517b4a3ed8db88b4bc93c78dae2974bf2",
- "sha256:c7934fd0e920e70468e676fe7f1b7261c1efa0d6c037c6722278ca0228ad9d0d",
- "sha256:c7e72ce6bda6fb9409cc1e8164dd41d7c91466fb599eb047cfda72fe758a34a7",
- "sha256:c90d6dec6be2c7d03378a574de87af9b1efea77d0c52a8301dd831ece938452f",
- "sha256:ceec59f59d092c5007e815def4ebb80c2de330e9588e101cf8bd94c143ec78a5",
- "sha256:cf1781ef73c073e6b0f90af841aaf98501f975d306bbf6221683dd594ccc52b6",
- "sha256:d04f13a1d75cb2b8382bdc16ae6fa58c97337253826dfe136195b7f89f661557",
- "sha256:d6d300f8ec35c24025ceb9b9019ae9040c1ab2f01cddc2bcc0b518af31c75c14",
- "sha256:d8dbb1bf0c0a4ae8b40bdc9be7f644e2f3fb4e8a9aca7145bfa510d4a374eeb7",
- "sha256:de58647e3f9c42f13f90ac7e5f58900c80a39019848c5547bc691693098ae1bd",
- "sha256:deeb929efe52bed518f6eb2ddc00cc496366a14c726005726ad62c2dd9017a3c",
- "sha256:df01aea34b6e9e33572c35cd16bae5a47785e7d5c8cb2b54b2acdb9678315a17",
- "sha256:e2620453c075abeb0daa949a292e19f56de518988e079c36478bacf9546ced23",
- "sha256:e4450fc83a3df53dec45922b576e91e94f5578d06436871dce3a6be38e40f5db",
- "sha256:e54affdeb21026329fb0744ad187cf812f7d3c2aa702a5edb562b325191fcab6",
- "sha256:e9875a0143f07d74dc5e1ded1c4581f0d9f7ab86c78994e2ed9e95050073c94d",
- "sha256:f1c3cf67185543730888b20682fb186fc8d0fa6f07ccc3ef4390831ab4b388d9",
- "sha256:f48c749857f8fb598fb890a75f540e3221d0976ed0bf879cf3c7eef34151acee",
- "sha256:f779498eeec470295a2b1a5d97aa1bc9814ecd25e1eb637bd9d1c73a327387f6"
+ "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2",
+ "sha256:0a34631031a8f05657e8e90903e656959234f3a04552259458aac0b0f9ae6fd9",
+ "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5",
+ "sha256:0c9e74d766f2818bb95f84c25be4dea09841ac0f734d1966f415e4edfc4ef1c3",
+ "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8",
+ "sha256:0fdfe3e2a29e4db3659dbd5bbf04560cea53dd9610273917799f1cde46aa725e",
+ "sha256:1009ee0c7739c08a0cd59de430d6de452a55e42d6b522de7aa15e6f67db0b8e1",
+ "sha256:1234d4ef35db82f5446dca8e35a7da7964d02c127b095e172e54397fb6a6c256",
+ "sha256:16b6c1b3e57799b9d38427dda63edcbe4926352c47cf88588c0be4ace18dac85",
+ "sha256:2034693ad3097d5355bfdacfffcbd3ef5694f9718ab7f29c29689a9eae841880",
+ "sha256:21c1fa28a6a7e3cbdc171c694398b6df4744613ce9b36b1a498e816787e28123",
+ "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375",
+ "sha256:27ccee0071a0e75d22cb35849b1db43f2ecd3e161041ac1ee9d2352ddf72f065",
+ "sha256:363c6f671b761efcb30608d24925a382497c12c506b51661883c3e22337265ed",
+ "sha256:39c1fec2c11dc8d89bba6b2bf1556af381611a173ac2b511cf7231622058af41",
+ "sha256:3b1ac0d3e594bf121308112697cf4b32be538fb1444468fb0a6ae4feebc83411",
+ "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597",
+ "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f",
+ "sha256:3d00075aa65772e7ce9e990cab3ff1de702aa09be3940d1dc88d5abf1ab8a09c",
+ "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3",
+ "sha256:47819cea040f31d670cc8d324bb6435c6f133b8c7a19ec3d61634e62f8d8f9eb",
+ "sha256:47b099e1f4fbc95b701b6e85768e1fcdaf1630f3cbe4765fa216596f12310e2e",
+ "sha256:4a9fac8e469d04ce6c25bb2610dc535235bd4aa14996b4e6dbebf5e007eba5ee",
+ "sha256:4b826973a4a2ae47ba357e4e82fa44a463b8f168e1ca775ac64521442b19e87f",
+ "sha256:4c2529b320eb9e35af0fa3016c187dffb84a3ecc572bcee7c3ce302bfeba52bf",
+ "sha256:54479983bd5fb469c38f2f5c7e3a24f9a4e70594cd68cd1fa6b9340dadaff7cf",
+ "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4",
+ "sha256:5756779642579d902eed757b21b0164cd6fe338506a8083eb58af5c372e39d9a",
+ "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665",
+ "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22",
+ "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675",
+ "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4",
+ "sha256:5df592cd503496351d6dc14f7cdad49f268d8e618f80dce0cd5a36b93c3fc08d",
+ "sha256:5f4c04ead5aed67c8a1a20491d54cdfba5884507a48dd798ecaf13c74c4489f5",
+ "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65",
+ "sha256:66dd88c918e3287efc22409d426c8f729688d89a0c587c88971a0faa2c2f3792",
+ "sha256:678999709e68425ae2593acf2e3ebcbcf2e69885a5ee78f9eb80e6e371f1bf57",
+ "sha256:67f2b6de947f8c757db2db9c71527933ad0019737ec374a8a6be9a956786aaf9",
+ "sha256:693f0192126df6c2327cce3baa7c06f2a117575e32ab2308f7f8216c29d9e2e3",
+ "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151",
+ "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d",
+ "sha256:76d1f20b1c7a2fa82367e04982e708723ba0e7b8d43aa643d3dcd404d74f1475",
+ "sha256:7f493881579c90fc262d9cdbaa05a6b54b3811c2f300766748db79f098db9940",
+ "sha256:823c248b690b2fd9303ba00c4f66cd5e2d8c3ba4aa968b2779be9532a4dad431",
+ "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee",
+ "sha256:8dd8327c795b3e3f219760fa603dcae1dcc148172290a8ab15158cf85a953413",
+ "sha256:8fdc51055e6ff4adeb88d58a11042ec9a5eae317a0a53d12c062c8a8865909e8",
+ "sha256:a625e06551975f4b7ea7102bc43895b90742746797e2e14b70ed61c43a90f09b",
+ "sha256:abdc0c6c8c648b4805c5eacd131910d2a7f6455dfd3becab248ef108e89ab16a",
+ "sha256:ac017dd64572e5c3bd01939121e4d16cf30e5d7e110a119399cf3133b63ad054",
+ "sha256:ac1e5c9054fe23226fb11e05a6e630837f074174c4c2f0fe442996112a6de4fb",
+ "sha256:ac60e3b188ec7574cb761b08d50fcedf9d77f1530352db4eef1707fe9dee7205",
+ "sha256:b359ed09954d7c18bbc1680f380c7301f92c60bf924171629c5db97febb12f04",
+ "sha256:b7643a03db5c95c799b89b31c036d5f27eeb4d259c798e878d6937d71832b1e4",
+ "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa",
+ "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9",
+ "sha256:cad21560da69f4ce7658ca2cb83138fb4cf695a2ba3e475e0559e05991aa8122",
+ "sha256:d08eb4c2b7d6c41da6ca0600c077e93f5adcfd979cd777d747e9ee624556da4b",
+ "sha256:d50fd1ee42388dcfb2b3676132c78116490976f1300da28eb629272d5d93e905",
+ "sha256:d591f8de75824cbb7acad4e05d2d710484f15f29d4a915092675ad3456f11770",
+ "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe",
+ "sha256:d63efaa0cd96cf0c5fe4d581521d9fa87744540d4bc999ae6e08595a1014b45b",
+ "sha256:d99e5546bf73dbad5bf3547174cd6cb8ba7273062a23808ffea025ecb1cf8562",
+ "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561",
+ "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215",
+ "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931",
+ "sha256:f29d80eb9a9263b8d109135351caf568cc3f80b9928bccde535c235de55c22d9",
+ "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f",
+ "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7"
],
"index": "pypi",
- "markers": "python_version >= '3.8'",
- "version": "==13.1"
+ "markers": "python_version >= '3.9'",
+ "version": "==15.0.1"
}
},
"develop": {
@@ -149,13 +126,22 @@
"markers": "python_version >= '3.9'",
"version": "==26.1.0"
},
+ "build": {
+ "hashes": [
+ "sha256:13f3eecb844759ab66efec90ca17639bbf14dc06cb2fdf37a9010322d9c50a6f",
+ "sha256:302c22c3ba2a0fd5f3911918651341ebb3896176cbdec15bd421f80b1afc7647"
+ ],
+ "index": "pypi",
+ "markers": "python_version >= '3.10'",
+ "version": "==1.5.0"
+ },
"cachetools": {
"hashes": [
- "sha256:0def7134eba79e59448edaf5d2e3cc8e49978ab2fd56189c1efd19856b134ab5",
- "sha256:900cda61ff34fafca2b7f78cfd2a91e2d4f9655c19309ef542ce0a04f91e6cd9"
+ "sha256:2c12e255780330af28b91bb7fb96cce4c766f04e38396b9a24510190a5827096",
+ "sha256:c7a79e7f30ba9943c1cefd08cc36f006aaae086e017af9166f1d59d6170c47e1"
],
"markers": "python_version >= '3.10'",
- "version": "==7.1.5"
+ "version": "==7.1.6"
},
"certifi": {
"hashes": [
@@ -515,6 +501,14 @@
"markers": "python_version >= '3.10'",
"version": "==1.11.0"
},
+ "pyproject-hooks": {
+ "hashes": [
+ "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8",
+ "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==1.2.0"
+ },
"pytest": {
"hashes": [
"sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313",
diff --git a/README-ja.md b/README-ja.md
index deda5ca..14c2efd 100644
--- a/README-ja.md
+++ b/README-ja.md
@@ -5,7 +5,7 @@
[obniz](https://obniz.io/)をpythonから操作するためのsdkです。
[obnizBoard](https://obniz.io/ja/doc/obniz_board_hobby_90/hw_overview)と[obnizOS](https://obniz.io/ja/doc/obnizos/os_overview)に対応しています
-**Python 3.8以上**で動作します。
+**Python 3.9以上**で動作します。
diff --git a/README.md b/README.md
index eb3b67f..ed46aac 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@ Control obniz from python.
This sdk works with [obniz api](https://obniz.io/doc/about_obniz_api).
-Compatible with **Python 3.8+**.
+Compatible with **Python 3.9+**.
diff --git a/obniz/obniz/__version__.py b/obniz/obniz/__version__.py
index 49e0fc1..777f190 100644
--- a/obniz/obniz/__version__.py
+++ b/obniz/obniz/__version__.py
@@ -1 +1 @@
-__version__ = "0.7.0"
+__version__ = "0.8.0"
diff --git a/obniz/obniz/libs/embeds/ble/ble_attribute_abstract.py b/obniz/obniz/libs/embeds/ble/ble_attribute_abstract.py
index 05fc3ae..de7fcc8 100644
--- a/obniz/obniz/libs/embeds/ble/ble_attribute_abstract.py
+++ b/obniz/obniz/libs/embeds/ble/ble_attribute_abstract.py
@@ -1,4 +1,4 @@
-from pyee import AsyncIOEventEmitter
+from pyee.asyncio import AsyncIOEventEmitter
from .ble_helper import BleHelper
from ...utils.eventloop import get_event_loop
diff --git a/obniz/obniz/libs/embeds/ble/ble_remote_peripheral.py b/obniz/obniz/libs/embeds/ble/ble_remote_peripheral.py
index d1e7072..221f29b 100644
--- a/obniz/obniz/libs/embeds/ble/ble_remote_peripheral.py
+++ b/obniz/obniz/libs/embeds/ble/ble_remote_peripheral.py
@@ -1,6 +1,6 @@
import json
-from pyee import AsyncIOEventEmitter
+from pyee.asyncio import AsyncIOEventEmitter
from .ble_helper import BleHelper
from .ble_remote_service import BleRemoteService
diff --git a/obniz/obniz/libs/embeds/ble/ble_scan.py b/obniz/obniz/libs/embeds/ble/ble_scan.py
index d139c0c..331f914 100644
--- a/obniz/obniz/libs/embeds/ble/ble_scan.py
+++ b/obniz/obniz/libs/embeds/ble/ble_scan.py
@@ -1,4 +1,4 @@
-from pyee import AsyncIOEventEmitter
+from pyee.asyncio import AsyncIOEventEmitter
from .ble_helper import BleHelper
diff --git a/obniz/obniz/libs/embeds/ble/ble_security.py b/obniz/obniz/libs/embeds/ble/ble_security.py
index aaf6a39..009a25f 100644
--- a/obniz/obniz/libs/embeds/ble/ble_security.py
+++ b/obniz/obniz/libs/embeds/ble/ble_security.py
@@ -1,4 +1,4 @@
-from pyee import AsyncIOEventEmitter
+from pyee.asyncio import AsyncIOEventEmitter
import semver
class BleSecurity:
@@ -51,7 +51,7 @@ def set_mode_level(self, mode, level):
raise Exception(msg)
def check_introduced_firmware(self, introduced_version, function_name):
- res = semver.match(self.obniz.firmware_ver, "<=" + introduced_version)
+ res = semver.Version.parse(self.obniz.firmware_ver).match("<=" + introduced_version)
if res:
msg = (
"{} is available ".format(function_name) +
diff --git a/obniz/obniz/libs/embeds/storage.py b/obniz/obniz/libs/embeds/storage.py
index 3cccb4d..06d3ef8 100644
--- a/obniz/obniz/libs/embeds/storage.py
+++ b/obniz/obniz/libs/embeds/storage.py
@@ -66,7 +66,7 @@ def _require_firmware_major(self, major):
if not fw:
raise Exception("unknown obniz firmware version. connect first")
- if semver.parse_version_info(fw).major < major:
+ if semver.Version.parse(fw).major < major:
raise Exception(
"Please update obniz firmware >= {}.0.0".format(major)
)
diff --git a/obniz/obniz/libs/io_peripherals/spi.py b/obniz/obniz/libs/io_peripherals/spi.py
index a8469e0..0cdbfe4 100644
--- a/obniz/obniz/libs/io_peripherals/spi.py
+++ b/obniz/obniz/libs/io_peripherals/spi.py
@@ -90,7 +90,7 @@ def write_wait(self, data):
if not self.used:
raise Exception("spi{} is not started".format(self.id))
- if semver.match(self.obniz.firmware_ver, "<=1.0.2") and len(data) > 32:
+ if semver.Version.parse(self.obniz.firmware_ver).match("<=1.0.2") and len(data) > 32:
raise Exception(
"with your obniz "
+ self.obniz.firmware_ver
@@ -110,7 +110,7 @@ def write_wait(self, data):
def write(self, data):
if not self.used:
raise Exception("spi{0} is not started".format(self.id))
- if semver.match(self.obniz.firmware_ver, "<=1.0.2") and len(data) > 32:
+ if semver.Version.parse(self.obniz.firmware_ver).match("<=1.0.2") and len(data) > 32:
raise Exception(
"with your obniz {0}. spi max length=32byte but yours {1}. Please update obniz firmware".format(
self.obniz.firmware_ver, len(data)
diff --git a/obniz/obniz/libs/plugin/plugin.py b/obniz/obniz/libs/plugin/plugin.py
index 79f614d..f94609d 100644
--- a/obniz/obniz/libs/plugin/plugin.py
+++ b/obniz/obniz/libs/plugin/plugin.py
@@ -117,14 +117,14 @@ def _require_firmware(self, version):
if not fw:
raise Exception("unknown obniz firmware version. connect first")
- info = semver.parse_version_info(fw)
+ info = semver.Version.parse(fw)
if version == "7.1.0":
# accept prereleases like 7.1.0-beta.0, as obniz.js does
ok = info.major > 7 or (info.major == 7 and info.minor >= 1)
elif version == "7.0.0":
ok = info.major >= 7
else:
- ok = not semver.match(fw, "<" + version)
+ ok = not info.match("<" + version)
if not ok:
raise Exception("Please update obniz firmware >= " + version)
diff --git a/obniz/obniz/libs/utils/attr_default.py b/obniz/obniz/libs/utils/attr_default.py
new file mode 100644
index 0000000..868f9a8
--- /dev/null
+++ b/obniz/obniz/libs/utils/attr_default.py
@@ -0,0 +1,39 @@
+class AttrDefault(dict):
+ """In-repo replacement for the abandoned attrdict package's AttrDefault.
+
+ A dict whose keys are also readable/writable as attributes, and whose
+ missing keys yield default_factory() (stored, like collections.defaultdict)
+ instead of raising. Parts rely on all three behaviors, e.g.
+ ``self.params.mode = self.params.mode or 'master'``.
+ """
+
+ def __init__(self, default_factory=bool, items=None):
+ super().__init__(items if items is not None else {})
+ object.__setattr__(self, "_default_factory", default_factory)
+
+ def __getitem__(self, key):
+ if key not in self:
+ default = self._default_factory()
+ super().__setitem__(key, default)
+ return default
+ return super().__getitem__(key)
+
+ def __getattr__(self, key):
+ if key.startswith("__"):
+ raise AttributeError(key)
+ return self[key]
+
+ def __setattr__(self, key, value):
+ self[key] = value
+
+ def __delattr__(self, key):
+ try:
+ del self[key]
+ except KeyError:
+ raise AttributeError(key)
+
+ def get(self, key, default=None):
+ # do not auto-create on .get(), matching plain dict semantics
+ if key in self:
+ return dict.__getitem__(self, key)
+ return default
diff --git a/obniz/obniz/libs/utils/util.py b/obniz/obniz/libs/utils/util.py
index c976f8d..239e8ad 100644
--- a/obniz/obniz/libs/utils/util.py
+++ b/obniz/obniz/libs/utils/util.py
@@ -1,11 +1,10 @@
import json
-import attrdict
class ObnizUtil:
@classmethod
def _key_filter(cls, params, keys):
filterd_params = {}
- if type(params) not in [dict, attrdict.default.AttrDefault]:
+ if not isinstance(params, dict):
return filterd_params
for key in [key for key in params.keys() if key in keys]:
@@ -15,7 +14,7 @@ def _key_filter(cls, params, keys):
@classmethod
def _required_keys(cls, params, keys):
- if type(params) not in [dict, attrdict.default.AttrDefault]:
+ if not isinstance(params, dict):
return keys[0]
for key in keys:
diff --git a/obniz/obniz/obniz_components.py b/obniz/obniz/obniz_components.py
index 7eaa603..e158ab0 100644
--- a/obniz/obniz/obniz_components.py
+++ b/obniz/obniz/obniz_components.py
@@ -1,3 +1,5 @@
+import asyncio
+
from .libs.embeds.ble.ble import ObnizBLE
from .libs.embeds.display import Display
from .libs.embeds.storage import Storage
@@ -16,9 +18,6 @@
from .obniz_connection import ObnizConnection
from .obniz_parts import ObnizParts
-import attrdict
-import asyncio
-
class ObnizComponents(ObnizParts):
def __init__(self, id, options):
@@ -178,7 +177,7 @@ def get_free_i2c(self):
return self._get_free_peripheral_unit('i2c')
def get_i2c_with_config(self, config):
- if type(config) not in [dict, attrdict.default.AttrDefault]:
+ if not isinstance(config, dict):
raise Exception("get_i2c_with_config need config arg")
if config.get("i2c"):
return config.get("i2c")
@@ -190,7 +189,7 @@ def get_free_spi(self):
return self._get_free_peripheral_unit('spi')
def get_spi_with_config(self, config):
- if type(config) not in [dict, attrdict.default.AttrDefault]:
+ if not isinstance(config, dict):
raise Exception("get_spi_with_config need config arg")
if config.get("spi"):
return config.get("spi")
diff --git a/obniz/obniz/obniz_connection.py b/obniz/obniz/obniz_connection.py
index 88b77c3..4345502 100644
--- a/obniz/obniz/obniz_connection.py
+++ b/obniz/obniz/obniz_connection.py
@@ -1,8 +1,9 @@
import inspect
import json
-from pyee import AsyncIOEventEmitter
+from pyee.asyncio import AsyncIOEventEmitter
import websockets
+from websockets.protocol import State
from .__version__ import __version__
from .libs.utils.eventloop import ensure_future, get_event_loop
@@ -146,7 +147,7 @@ def wsconnect(self, desired_server):
if desired_server:
server = desired_server
- if self.socket and self.socket.open:
+ if self._socket_open(self.socket):
self.close()
url = server + "/obniz/{}/ws/1".format(self.id)
@@ -232,7 +233,7 @@ async def connecting():
def _disconnect_local(self):
if self.socket_local:
- if self.socket.open:
+ if self._socket_open(self.socket):
self.socket_local.close()
self.clear_socket(self.socket_local)
@@ -273,8 +274,12 @@ def clear_socket(self, socket):
# socket.onerror = null
# }
+ @staticmethod
+ def _socket_open(socket):
+ return socket is not None and socket.state is State.OPEN
+
def connect(self):
- if self.socket and self.socket.open:
+ if self._socket_open(self.socket):
return
self.wsconnect()
@@ -283,7 +288,7 @@ def close(self):
# self._drainQueued()
self._disconnect_local()
if self.socket:
- if self.socket.open:
+ if self._socket_open(self.socket):
# Connecting & Connected
self.connection_state = 'closing'
ensure_future(self.socket.close(1000, "close"))
@@ -300,7 +305,7 @@ def _call_on_connect(self):
self._wait_for_local_connect_ready_timer = None
else:
# obniz.js hasn't wait local_connect
- if self.socket_local and self.socket.open:
+ if self.socket_local and self._socket_open(self.socket):
# delayed connect
should_call = False
else:
@@ -358,7 +363,7 @@ def _send_routed(self, data):
)
return
- if self.socket and self.socket.open:
+ if self._socket_open(self.socket):
ensure_future(self.socket.send(data))
# if self.socket.buffered_amount > self.bufferd_amound_warn_bytes:
# self.warning(
diff --git a/obniz/obniz/obniz_parts.py b/obniz/obniz/obniz_parts.py
index b9915a9..a302adf 100644
--- a/obniz/obniz/obniz_parts.py
+++ b/obniz/obniz/obniz_parts.py
@@ -1,7 +1,6 @@
-from attrdict import AttrDefault
-
-from .obniz_connection import ObnizConnection
+from .libs.utils.attr_default import AttrDefault
from .libs.utils.util import ObnizUtil
+from .obniz_connection import ObnizConnection
_parts = {}
diff --git a/obniz/parts/Camera/ArduCAMMini/__init__.py b/obniz/parts/Camera/ArduCAMMini/__init__.py
index e37a4db..ae518ca 100644
--- a/obniz/parts/Camera/ArduCAMMini/__init__.py
+++ b/obniz/parts/Camera/ArduCAMMini/__init__.py
@@ -1,8 +1,8 @@
-from attrdict import AttrDefault
-
import asyncio
import base64
+from obniz.obniz.libs.utils.attr_default import AttrDefault
+
class ArduCAMMini:
def __init__(self):
self.keys = ['cs', 'mosi', 'miso', 'sclk', 'gnd', 'vcc', 'sda', 'scl', 'spi', 'i2c', 'spi_frequency', 'spi_drive']
diff --git a/obniz/parts/DistanceSensor/GP2Y0A21YK0F/__init__.py b/obniz/parts/DistanceSensor/GP2Y0A21YK0F/__init__.py
index c099c0f..f057c76 100644
--- a/obniz/parts/DistanceSensor/GP2Y0A21YK0F/__init__.py
+++ b/obniz/parts/DistanceSensor/GP2Y0A21YK0F/__init__.py
@@ -1,8 +1,8 @@
-from attrdict import AttrDefault
-
import asyncio
import math
+from obniz.obniz.libs.utils.attr_default import AttrDefault
+
class GP2Y0A21YK0F:
def __init__(self):
self.keys = ['vcc', 'gnd', 'signal']
diff --git a/obniz/parts/DistanceSensor/HC-SR04/__init__.py b/obniz/parts/DistanceSensor/HC-SR04/__init__.py
index 6e11537..ea97eb8 100644
--- a/obniz/parts/DistanceSensor/HC-SR04/__init__.py
+++ b/obniz/parts/DistanceSensor/HC-SR04/__init__.py
@@ -1,7 +1,6 @@
import math
-from attrdict import AttrDefault
-
+from obniz.obniz.libs.utils.attr_default import AttrDefault
from obniz.obniz.libs.utils.eventloop import get_event_loop
diff --git a/obniz/parts/Light/LED/__init__.py b/obniz/parts/Light/LED/__init__.py
index 15d3414..1a9ffe7 100644
--- a/obniz/parts/Light/LED/__init__.py
+++ b/obniz/parts/Light/LED/__init__.py
@@ -1,4 +1,4 @@
-from attrdict import AttrDefault
+from obniz.obniz.libs.utils.attr_default import AttrDefault
class LED:
def __init__(self):
diff --git a/obniz/parts/MovementSensor/Button/__init__.py b/obniz/parts/MovementSensor/Button/__init__.py
index c5cd701..76dc935 100644
--- a/obniz/parts/MovementSensor/Button/__init__.py
+++ b/obniz/parts/MovementSensor/Button/__init__.py
@@ -1,5 +1,4 @@
-from attrdict import AttrDefault
-
+from obniz.obniz.libs.utils.attr_default import AttrDefault
from obniz.obniz.libs.utils.eventloop import get_event_loop
diff --git a/obniz/parts/MovementSensor/HC-SR505/__init__.py b/obniz/parts/MovementSensor/HC-SR505/__init__.py
index ef99b14..89940c9 100644
--- a/obniz/parts/MovementSensor/HC-SR505/__init__.py
+++ b/obniz/parts/MovementSensor/HC-SR505/__init__.py
@@ -1,6 +1,7 @@
-from attrdict import AttrDefault
import asyncio
+from obniz.obniz.libs.utils.attr_default import AttrDefault
+
class HCSR505:
def __init__(self):
self.keys = ['vcc', 'gnd', 'signal']
diff --git a/obniz/parts/MovementSensor/JoyStick/__init__.py b/obniz/parts/MovementSensor/JoyStick/__init__.py
index ab8a538..82563f3 100644
--- a/obniz/parts/MovementSensor/JoyStick/__init__.py
+++ b/obniz/parts/MovementSensor/JoyStick/__init__.py
@@ -1,7 +1,7 @@
-from attrdict import AttrDefault
-
import asyncio
+from obniz.obniz.libs.utils.attr_default import AttrDefault
+
class JoyStick:
def __init__(self):
self.keys = ['sw', 'y', 'x', 'vcc', 'gnd', 'i2c']
diff --git a/obniz/parts/MovementSensor/KXR94-2050/__init__.py b/obniz/parts/MovementSensor/KXR94-2050/__init__.py
index 20ebfaa..7439bfa 100644
--- a/obniz/parts/MovementSensor/KXR94-2050/__init__.py
+++ b/obniz/parts/MovementSensor/KXR94-2050/__init__.py
@@ -1,7 +1,7 @@
-from attrdict import AttrDefault
-
import asyncio
+from obniz.obniz.libs.utils.attr_default import AttrDefault
+
class KXR942050:
def __init__(self):
self.keys = ['x', 'y', 'z', 'vcc', 'gnd', 'enable', 'self_test']
diff --git a/obniz/parts/MovementSensor/Potentiometer/__init__.py b/obniz/parts/MovementSensor/Potentiometer/__init__.py
index 4b2a4c8..866ac1f 100644
--- a/obniz/parts/MovementSensor/Potentiometer/__init__.py
+++ b/obniz/parts/MovementSensor/Potentiometer/__init__.py
@@ -1,4 +1,4 @@
-from attrdict import AttrDefault
+from obniz.obniz.libs.utils.attr_default import AttrDefault
class Potentiometer:
def __init__(self):
diff --git a/obniz/parts/Moving/DCMotor/__init__.py b/obniz/parts/Moving/DCMotor/__init__.py
index 89bdec3..e022150 100644
--- a/obniz/parts/Moving/DCMotor/__init__.py
+++ b/obniz/parts/Moving/DCMotor/__init__.py
@@ -1,4 +1,4 @@
-from attrdict import AttrDefault
+from obniz.obniz.libs.utils.attr_default import AttrDefault
class DCMotor:
def __init__(self):
diff --git a/obniz/parts/Moving/ServoMotor/__init__.py b/obniz/parts/Moving/ServoMotor/__init__.py
index 2511359..305b8c6 100644
--- a/obniz/parts/Moving/ServoMotor/__init__.py
+++ b/obniz/parts/Moving/ServoMotor/__init__.py
@@ -1,4 +1,4 @@
-from attrdict import AttrDefault
+from obniz.obniz.libs.utils.attr_default import AttrDefault
class ServoMotor:
def __init__(self):
diff --git a/obniz/parts/Moving/StepperMotor/__init__.py b/obniz/parts/Moving/StepperMotor/__init__.py
index 4ab9025..6be9a16 100644
--- a/obniz/parts/Moving/StepperMotor/__init__.py
+++ b/obniz/parts/Moving/StepperMotor/__init__.py
@@ -1,7 +1,7 @@
-from attrdict import AttrDefault
-
import asyncio
+from obniz.obniz.libs.utils.attr_default import AttrDefault
+
class StepperMotor:
def __init__(self):
self.keys = ['a', 'b', 'aa', 'bb', 'common']
diff --git a/obniz/parts/PressureSensor/FSR-40X/__init__.py b/obniz/parts/PressureSensor/FSR-40X/__init__.py
index dc16c31..f94363a 100644
--- a/obniz/parts/PressureSensor/FSR-40X/__init__.py
+++ b/obniz/parts/PressureSensor/FSR-40X/__init__.py
@@ -1,7 +1,7 @@
-from attrdict import AttrDefault
-
import asyncio
+from obniz.obniz.libs.utils.attr_default import AttrDefault
+
class FSR40X:
def __init__(self):
self.keys = ['pin0', 'pin1']
diff --git a/obniz/parts/TemperatureSensor/analog/LM60/__init__.py b/obniz/parts/TemperatureSensor/analog/LM60/__init__.py
index f9ad449..8c90b48 100644
--- a/obniz/parts/TemperatureSensor/analog/LM60/__init__.py
+++ b/obniz/parts/TemperatureSensor/analog/LM60/__init__.py
@@ -1,5 +1,5 @@
+from obniz.obniz.libs.utils.attr_default import AttrDefault
from .. import AnalogTemplatureSensor
-from attrdict import AttrDefault
class LM60(AnalogTemplatureSensor):
@staticmethod
diff --git a/obniz/parts/TemperatureSensor/i2c/BME280/__init__.py b/obniz/parts/TemperatureSensor/i2c/BME280/__init__.py
index 473bdda..975a021 100644
--- a/obniz/parts/TemperatureSensor/i2c/BME280/__init__.py
+++ b/obniz/parts/TemperatureSensor/i2c/BME280/__init__.py
@@ -1,7 +1,7 @@
import asyncio
import math
-from attrdict import AttrDefault
+from obniz.obniz.libs.utils.attr_default import AttrDefault
class BME280:
def __init__(self):
diff --git a/obniz/parts/TemperatureSensor/i2c/SHT31/__init__.py b/obniz/parts/TemperatureSensor/i2c/SHT31/__init__.py
index 7304210..68b70be 100644
--- a/obniz/parts/TemperatureSensor/i2c/SHT31/__init__.py
+++ b/obniz/parts/TemperatureSensor/i2c/SHT31/__init__.py
@@ -1,7 +1,7 @@
-from attrdict import AttrDefault
-
import asyncio
+from obniz.obniz.libs.utils.attr_default import AttrDefault
+
class SHT31:
def __init__(self):
self.required_keys = ['adr', 'addressmode']
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..e3ed83e
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,39 @@
+[build-system]
+requires = ["setuptools>=64"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "obniz"
+description = "obniz sdk for python"
+readme = "README.md"
+authors = [{ name = "yukisato", email = "yuki@yuki-sato.com" }]
+requires-python = ">=3.9"
+dependencies = [
+ "pyee==13.0.1",
+ "websockets>=14.2,<16",
+ "semver==3.0.4",
+]
+classifiers = [
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3.12",
+ "Programming Language :: Python :: 3.13",
+ "Programming Language :: Python :: 3.14",
+ "Operating System :: OS Independent",
+]
+dynamic = ["version"]
+
+[project.urls]
+Homepage = "https://obniz.io/"
+Repository = "https://github.com/obniz/obniz-python-sdk"
+
+[tool.setuptools.dynamic]
+version = { attr = "obniz.obniz.__version__.__version__" }
+
+[tool.setuptools.packages.find]
+include = ["obniz*"]
+
+[tool.setuptools]
+include-package-data = true
diff --git a/pytest.ini b/pytest.ini
deleted file mode 100644
index 2dd08ee..0000000
--- a/pytest.ini
+++ /dev/null
@@ -1,6 +0,0 @@
-[pytest]
-filterwarnings =
- ; workaround for https://github.com/yaml/pyyaml/issues/202
- ignore:Using or importing the ABCs::yaml.constructor
- ; workaround for https://github.com/aaugustin/websockets/issues/514
- ignore:'with \(yield from lock\)'::websockets.protocol
diff --git a/setup.py b/setup.py
deleted file mode 100644
index 120a83d..0000000
--- a/setup.py
+++ /dev/null
@@ -1,52 +0,0 @@
-import setuptools
-from codecs import open
-from os import path
-import re
-
-package_name = "obniz"
-root_dir = path.abspath(path.dirname(__file__))
-
-with open("README.md", "r") as fh:
- long_description = fh.read()
-
-with open(path.join(root_dir, package_name, '__init__.py')) as f:
- init_text = f.read()
- # license = re.search(r'__license__\s*=\s*[\'\"](.+?)[\'\"]', init_text).group(1)
- author = re.search(r'__author__\s*=\s*[\'\"](.+?)[\'\"]', init_text).group(1)
- author_email = re.search(r'__author_email__\s*=\s*[\'\"](.+?)[\'\"]', init_text).group(1)
- url = re.search(r'__url__\s*=\s*[\'\"](.+?)[\'\"]', init_text).group(1)
-
-with open(path.join(root_dir, package_name, package_name, '__version__.py')) as f:
- init_text = f.read()
- version = re.search(r'__version__\s*=\s*[\'\"](.+?)[\'\"]', init_text).group(1)
-
-setuptools.setup(
- name=package_name,
- version=version,
- author=author,
- author_email=author_email,
- description="obniz sdk for python",
- long_description=long_description,
- long_description_content_type="text/markdown",
- url=url,
- packages=setuptools.find_packages(),
- include_package_data=True,
- install_requires=[
- 'pyee==6.0.0',
- 'websockets>=12,<14',
- 'attrdict3==2.0.2',
- 'semver==2.8.1'
- ],
- python_requires='>=3.8',
- classifiers=[
- "Programming Language :: Python :: 3",
- 'Programming Language :: Python :: 3.8',
- 'Programming Language :: Python :: 3.9',
- 'Programming Language :: Python :: 3.10',
- 'Programming Language :: Python :: 3.11',
- 'Programming Language :: Python :: 3.12',
- 'Programming Language :: Python :: 3.13',
- 'Programming Language :: Python :: 3.14',
- "Operating System :: OS Independent",
- ],
-)
diff --git a/tests/test_init.py b/tests/test_init.py
index a329dbd..b5f9852 100644
--- a/tests/test_init.py
+++ b/tests/test_init.py
@@ -30,7 +30,7 @@ def test_connect(self):
loop = asyncio.get_event_loop()
future = loop.create_future()
- async def on_connection(websocket, path):
+ async def on_connection(websocket):
print("server: connected")
future.set_result(None)
@@ -53,7 +53,7 @@ def test_soft_redirect(self):
loop = asyncio.get_event_loop()
future = loop.create_future()
- async def on_connection(websocket, path):
+ async def on_connection(websocket):
try:
print("server(" + str(port) + "): connected")
future.set_result(websocket)
@@ -79,7 +79,7 @@ async def on_connection(websocket, path):
# expect(server.clients.size, 'before server not connected').to.equal(1)
future2 = loop.create_future()
- async def on_connection2(websocket, path):
+ async def on_connection2(websocket):
try:
print("server(" + str(port2) + "): connected")
future2.set_result(None)
diff --git a/tests/utils.py b/tests/utils.py
index b3f1f6e..eab8448 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -4,6 +4,7 @@
import pytest
import websockets
+from websockets.protocol import State
from obniz import Obniz
from .obniz_json_validator import obniz_json_validator as validator
@@ -13,9 +14,11 @@
def create_server(port, on_connection):
- wss = websockets.serve(on_connection, "localhost", port)
+ async def _start():
+ # websockets>=14 requires a running loop when the server is created
+ return await websockets.serve(on_connection, "localhost", port)
- return asyncio.get_event_loop().run_until_complete(wss)
+ return asyncio.get_event_loop().run_until_complete(_start())
def create_obniz(port, obniz_id):
@@ -25,7 +28,7 @@ def create_obniz(port, obniz_id):
def setup_obniz(mocker):
global server_data_count
- stub = mocker.MagicMock(buffered_amount=0)
+ stub = mocker.MagicMock(buffered_amount=0, state=State.OPEN)
# stub.on = mocker.stub()
stub.send = AsyncMock()
stub.close = AsyncMock()
diff --git a/tox.ini b/tox.ini
index 724f6de..7cd0364 100644
--- a/tox.ini
+++ b/tox.ini
@@ -4,7 +4,7 @@
# and then run "tox" from this directory.
[tox]
-envlist = py38, py39, py310, py311, py312, py313, py314
+envlist = py39, py310, py311, py312, py313, py314
[testenv]
deps =