diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..ee690ca --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "cSpell.words": [ + "linkstat", + "pythonpath", + "testpaths" + ] +} \ No newline at end of file diff --git a/CODE_OF_CONDUCT_JP.md b/CODE_OF_CONDUCT_JP.md new file mode 100644 index 0000000..7315b63 --- /dev/null +++ b/CODE_OF_CONDUCT_JP.md @@ -0,0 +1,83 @@ +# コントリビューター行動規範 + +## 私たちの約束 + +メンバー、コントリビューター、およびリーダーとして、年齢、体の大きさ、目に見えるまたは目に見えない障害、民族性、性的特徴、性同一性とジェンダー表現、経験のレベル、教育、社会経済的地位、国籍、人格、人種、カースト、肌の色、宗教、または性的同一性と性的指向に関係なく、コミュニティへの参加をハラスメントのない体験にすることを誓います。 + +私たちは、オープンで親しみやすく、多様で包括的で健全なコミュニティに貢献する方法で行動し、交流することを誓います。 + +## 私たちの標準 + +前向きな環境を作り上げることに貢献する行動の例: + +* 他人への共感と優しさを示す +* 異なる意見、視点、経験を尊重する +* 建設的なフィードバックを与え、礼儀正しく受け入れる +* 私たちの過ちの影響を受けた人々に責任を受け入れ、謝罪し、そしてその経験から学ぶ +* 個人としてだけでなく、コミュニティ全体にとっても最善であることに焦点を当てる + +許容できない行動の例は次のとおりです: + +* 性的な言葉や画像の使用、および性的な注意またはその他あらゆる種類の問題行為 +* トローリング、侮辱的または中傷的なコメント、個人的または政治的攻撃 +* 公的またはプライベートの嫌がらせ +* 明示的な許可なしに、住所や電子メールアドレスなど、他者の個人情報を公開する +* 職業上不適切と合理的に考えられるその他の行為 + +## 執行責任 + +コミュニティリーダーは、許容される行動の基準を明確にし、実施する責任があり、不適切、脅迫的、攻撃的、または有害と見なされる行動に応じて、適切で公正な是正措置を講じます。 + +コミュニティリーダーは、コメント、コミット、コード、wikiの編集、問題、およびこの行動規範に沿っていないその他の貢献を削除、編集、または拒否する権利と責任を持ち、適切な場合はモデレーションの決定の理由を伝えます。 + +## 適用範囲 + +この行動規範は、すべてのコミュニティスペース内で適用され、個人がパブリックスペースでコミュニティを公式に代表している場合にも適用されます。私たちのコミュニティを代表する例には、公式の電子メールアドレスの使用、公式のソーシャルメディアアカウントを介した投稿、オンラインまたはオフラインのイベントでの指定代理人としての行動などがあります。 + +## 執行 + +虐待的、嫌がらせ、またはその他の許容できない行動の事例は、執行を担当するコミュニティリーダーに対してdogfortune.2000+github@gmail.comで報告される場合があります。すべての苦情は迅速かつ公正にレビューおよび調査されます。 + +すべてのコミュニティリーダーは、問題の報告者のプライバシーとセキュリティを尊重する義務があります。 + +## 執行ガイドライン + +コミュニティリーダーは、この行動規範に違反していると見なした行動への帰結を判断する際に、これらのコミュニティガイドラインに従います: + +### 1. 更生 + +**コミュニティへの影響**: コミュニティで専門家にふさわしくない、または歓迎されないと思われる不適切な言葉の使用やその他の不適切な行動をすること。 + +**帰結**: コミュニティリーダーからの非公開の書面による警告。違反の理由を明確にし、行動が不適切だった理由を説明します。公の謝罪が要求される場合があります。 + +### 2. 警告 + +**コミュニティへの影響**: 単一の出来事または一連の動作による違反。 + +**帰結**: 持続的な行動の結果を伴う警告。指定された期間、行動規範の実施者との一方的な対話を含め、関係者との対話はありません。これには、コミュニティスペースやソーシャルメディアなどの外部チャネルでの相互作用の回避が含まれます。これらの条件に違反すると、一時的または永続的に禁止される場合があります。 + +### 3. 一時的な禁止 + +**コミュニティへの影響**: 持続的で不適切な行動を含む、コミュニティ標準の重大な違反。 + +**帰結**: 指定された期間のコミュニティとのあらゆる種類の相互関係または公的なコミュニケーションの一時的な禁止。この期間中、行動規範を実施する人々との一方的な対話を含め、関係する人々との公的または私的な対話は許可されません。これらの条件に違反すると、永久的に禁止される場合があります。 + +### 4. 永久的な禁止 + +**コミュニティへの影響**: 連続的な不適切な行動、個人への嫌がらせ、または個人の集団に対する攻撃または名誉毀損を含む、コミュニティの標準への違反のパターンを示す。 + +**帰結**: コミュニティ内でのあらゆる種類の公的な相互関係の永久的な禁止。 + +## 帰属 + +この行動規範は、[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]で利用可能な[Contributor Covenant][homepage] バージョン 2.1を基に作成されています。 + +コミュニティへの影響ガイドラインは[Mozilla's code of conduct enforcement ladder][Mozilla CoC]に適合しています。 + +この行動規範に関する一般的な質問への回答については、[https://www.contributor-covenant.org/faq][FAQ]のFAQを参照してください。翻訳は[https://www.contributor-covenant.org/translations][translations]で入手できます。 + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations \ No newline at end of file diff --git a/CONTRIBUTING_JP.md b/CONTRIBUTING_JP.md new file mode 100644 index 0000000..8504c40 --- /dev/null +++ b/CONTRIBUTING_JP.md @@ -0,0 +1,11 @@ +# Contribution Guide + +## Pull Request +[行動規範](CODE_OF_CONDUCT_JP.md)を守れる方であればどなたでも歓迎します。 + +## テスト +### コードスタイル +スタイルは`black`に準拠して下さい。リントは`flake8`に準拠して下さい。 + +## パブリッシュ +hatchを使っています。 \ No newline at end of file diff --git a/Pipfile b/Pipfile index ba1021a..8d3369a 100644 --- a/Pipfile +++ b/Pipfile @@ -12,6 +12,8 @@ pytest = "*" flake8 = "*" black = "*" pytest-randomly = "*" +build = "*" +hatch = "*" [requires] python_version = "3.13" @@ -19,3 +21,4 @@ python_version = "3.13" [scripts] lint = "flake8 -v" format = "black ./src/ -v" +build = "python -m build" diff --git a/Pipfile.lock b/Pipfile.lock index 45bb5fc..dab7dd2 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "a2d0cee61c4fa721f0c28a5774070546e974a9bc28d68b59a8e52bff137e588c" + "sha256": "abfbd1f0c8a48d405bf75c514ae132d96e9bde10fb1658471b8b1ea4f8100f2f" }, "pipfile-spec": 6, "requires": { @@ -83,42 +83,71 @@ } }, "develop": { + "anyio": { + "hashes": [ + "sha256:0287e96f4d26d4149305414d4e3bc32f0dcd0862365a4bddea19d7a1ec38c4fc", + "sha256:82a8d0b81e318cc5ce71a5f1f8b5c4e63619620b63141ef8c995fa0db95a57c4" + ], + "markers": "python_version >= '3.9'", + "version": "==4.11.0" + }, "black": { "hashes": [ - "sha256:0172a012f725b792c358d57fe7b6b6e8e67375dd157f64fa7a3097b3ed3e2175", - "sha256:0474bca9a0dd1b51791fcc507a4e02078a1c63f6d4e4ae5544b9848c7adfb619", - "sha256:154b06d618233fe468236ba1f0e40823d4eb08b26f5e9261526fde34916b9140", - "sha256:1b9dc70c21ef8b43248f1d86aedd2aaf75ae110b958a7909ad8463c4aa0880b0", - "sha256:2ab0ce111ef026790e9b13bd216fa7bc48edd934ffc4cbf78808b235793cbc92", - "sha256:3bec74ee60f8dfef564b573a96b8930f7b6a538e846123d5ad77ba14a8d7a64f", - "sha256:456386fe87bad41b806d53c062e2974615825c7a52159cde7ccaeb0695fa28fa", - "sha256:474b34c1342cdc157d307b56c4c65bce916480c4a8f6551fdc6bf9b486a7c4ae", - "sha256:77e7060a00c5ec4b3367c55f39cf9b06e68965a4f2e61cecacd6d0d9b7ec945a", - "sha256:846d58e3ce7879ec1ffe816bb9df6d006cd9590515ed5d17db14e17666b2b357", - "sha256:8e46eecf65a095fa62e53245ae2795c90bdecabd53b50c448d0a8bcd0d2e74c4", - "sha256:9101ee58ddc2442199a25cb648d46ba22cd580b00ca4b44234a324e3ec7a0f7e", - "sha256:a16b14a44c1af60a210d8da28e108e13e75a284bf21a9afa6b4571f96ab8bb9d", - "sha256:aaf319612536d502fdd0e88ce52d8f1352b2c0a955cc2798f79eeca9d3af0608", - "sha256:b756fc75871cb1bcac5499552d771822fd9db5a2bb8db2a7247936ca48f39831", - "sha256:c0372a93e16b3954208417bfe448e09b0de5cc721d521866cd9e0acac3c04a1f", - "sha256:ce41ed2614b706fd55fd0b4a6909d06b5bab344ffbfadc6ef34ae50adba3d4f7", - "sha256:d119957b37cc641596063cd7db2656c5be3752ac17877017b2ffcdb9dfc4d2b1", - "sha256:e3c1f4cd5e93842774d9ee4ef6cd8d17790e65f44f7cdbaab5f2cf8ccf22a823", - "sha256:e593466de7b998374ea2585a471ba90553283fb9beefcfa430d84a2651ed5933", - "sha256:ef69351df3c84485a8beb6f7b8f9721e2009e20ef80a8d619e2d1788b7816d47", - "sha256:f96b6726d690c96c60ba682955199f8c39abc1ae0c3a494a9c62c0184049a713" + "sha256:0a1d40348b6621cc20d3d7530a5b8d67e9714906dfd7346338249ad9c6cedf2b", + "sha256:0c0f7c461df55cf32929b002335883946a4893d759f2df343389c4396f3b6b37", + "sha256:1032639c90208c15711334d681de2e24821af0575573db2810b0763bcd62e0f0", + "sha256:35690a383f22dd3e468c85dc4b915217f87667ad9cce781d7b42678ce63c4170", + "sha256:43945853a31099c7c0ff8dface53b4de56c41294fa6783c0441a8b1d9bf668bc", + "sha256:51c65d7d60bb25429ea2bf0731c32b2a2442eb4bd3b2afcb47830f0b13e58bfd", + "sha256:5bd4a22a0b37401c8e492e994bce79e614f91b14d9ea911f44f36e262195fdda", + "sha256:6cb2d54a39e0ef021d6c5eef442e10fd71fcb491be6413d083a320ee768329dd", + "sha256:6cced12b747c4c76bc09b4db057c319d8545307266f41aaee665540bc0e04e96", + "sha256:7eebd4744dfe92ef1ee349dc532defbf012a88b087bb7ddd688ff59a447b080e", + "sha256:80e7486ad3535636657aa180ad32a7d67d7c273a80e12f1b4bfa0823d54e8fac", + "sha256:895571922a35434a9d8ca67ef926da6bc9ad464522a5fe0db99b394ef1c0675a", + "sha256:92285c37b93a1698dcbc34581867b480f1ba3a7b92acf1fe0467b04d7a4da0dc", + "sha256:936c4dd07669269f40b497440159a221ee435e3fddcf668e0c05244a9be71993", + "sha256:9815ccee1e55717fe9a4b924cae1646ef7f54e0f990da39a34fc7b264fcf80a2", + "sha256:9a323ac32f5dc75ce7470501b887250be5005a01602e931a15e45593f70f6e08", + "sha256:a3bb5ce32daa9ff0605d73b6f19da0b0e6c1f8f2d75594db539fdfed722f2b06", + "sha256:aa211411e94fdf86519996b7f5f05e71ba34835d8f0c0f03c00a26271da02664", + "sha256:ae263af2f496940438e5be1a0c1020e13b09154f3af4df0835ea7f9fe7bfa409", + "sha256:cb4f4b65d717062191bdec8e4a442539a8ea065e6af1c4f4d36f0cdb5f71e170", + "sha256:d81a44cbc7e4f73a9d6ae449ec2317ad81512d1e7dce7d57f6333fd6259737bc", + "sha256:dae49ef7369c6caa1a1833fd5efb7c3024bb7e4499bf64833f65ad27791b1545", + "sha256:e3f562da087791e96cefcd9dda058380a442ab322a02e222add53736451f604b", + "sha256:ec311e22458eec32a807f029b2646f661e6859c3f61bc6d9ffb67958779f392e", + "sha256:f42c0ea7f59994490f4dccd64e6b2dd49ac57c7c84f38b8faab50f8759db245c", + "sha256:f9786c24d8e9bd5f20dc7a7f0cdd742644656987f6ea6947629306f937726c03" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==25.11.0" + }, + "build": { + "hashes": [ + "sha256:698edd0ea270bde950f53aed21f3a0135672206f3911e0176261a31e0e07b397", + "sha256:7145f0b5061ba90a1500d60bd1b13ca0a8a4cebdd0cc16ed8adf1c0e739f43b4" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==25.9.0" + "version": "==1.3.0" + }, + "certifi": { + "hashes": [ + "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", + "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316" + ], + "markers": "python_version >= '3.7'", + "version": "==2025.11.12" }, "click": { "hashes": [ - "sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc", - "sha256:e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4" + "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", + "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6" ], "markers": "python_version >= '3.10'", - "version": "==8.3.0" + "version": "==8.3.1" }, "colorama": { "hashes": [ @@ -128,6 +157,21 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", "version": "==0.4.6" }, + "distlib": { + "hashes": [ + "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", + "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d" + ], + "version": "==0.4.0" + }, + "filelock": { + "hashes": [ + "sha256:339b4732ffda5cd79b13f4e2711a31b0365ce445d95d243bb996273d072546a2", + "sha256:711e943b4ec6be42e1d4e6690b48dc175c822967466bb31c0c293f34334c13f4" + ], + "markers": "python_version >= '3.10'", + "version": "==3.20.0" + }, "flake8": { "hashes": [ "sha256:b9696257b9ce8beb888cdbe31cf885c90d31928fe202be0889a7cdafad32f01e", @@ -137,6 +181,62 @@ "markers": "python_version >= '3.9'", "version": "==7.3.0" }, + "h11": { + "hashes": [ + "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", + "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86" + ], + "markers": "python_version >= '3.8'", + "version": "==0.16.0" + }, + "hatch": { + "hashes": [ + "sha256:444a78123c9837e8c9f5adfbf2b8b0a72139587eb49d6b368038b0521136fc43", + "sha256:99dccb26b00226056142f89d6e286be61e2d7b5b5b4e6178ebbe9298c1bc45d9" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==1.15.1" + }, + "hatchling": { + "hashes": [ + "sha256:971c296d9819abb3811112fc52c7a9751c8d381898f36533bb16f9791e941fd6", + "sha256:d3a2f3567c4f926ea39849cdf924c7e99e6686c9c8e288ae1037c8fa2a5d937b" + ], + "markers": "python_version >= '3.8'", + "version": "==1.27.0" + }, + "httpcore": { + "hashes": [ + "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", + "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8" + ], + "markers": "python_version >= '3.8'", + "version": "==1.0.9" + }, + "httpx": { + "hashes": [ + "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", + "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad" + ], + "markers": "python_version >= '3.8'", + "version": "==0.28.1" + }, + "hyperlink": { + "hashes": [ + "sha256:427af957daa58bc909471c6c40f74c5450fa123dd093fc53efd2e91d2705a56b", + "sha256:e6b14c37ecb73e89c77d78cdb4c2cc8f3fb59a885c5b3f819ff4ed80f25af1b4" + ], + "version": "==21.0.0" + }, + "idna": { + "hashes": [ + "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", + "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902" + ], + "markers": "python_version >= '3.8'", + "version": "==3.11" + }, "iniconfig": { "hashes": [ "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", @@ -145,6 +245,46 @@ "markers": "python_version >= '3.10'", "version": "==2.3.0" }, + "jaraco.classes": { + "hashes": [ + "sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd", + "sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790" + ], + "markers": "python_version >= '3.8'", + "version": "==3.4.0" + }, + "jaraco.context": { + "hashes": [ + "sha256:9bae4ea555cf0b14938dc0aee7c9f32ed303aa20a3b73e7dc80111628792d1b3", + "sha256:f797fc481b490edb305122c9181830a3a5b76d84ef6d1aef2fb9b47ab956f9e4" + ], + "markers": "python_version >= '3.8'", + "version": "==6.0.1" + }, + "jaraco.functools": { + "hashes": [ + "sha256:227ff8ed6f7b8f62c56deff101545fa7543cf2c8e7b82a7c2116e672f29c26e8", + "sha256:cfd13ad0dd2c47a3600b439ef72d8615d482cedcff1632930d6f28924d92f294" + ], + "markers": "python_version >= '3.9'", + "version": "==4.3.0" + }, + "keyring": { + "hashes": [ + "sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f", + "sha256:fe01bd85eb3f8fb3dd0405defdeac9a5b4f6f0439edbb3149577f244a2e8245b" + ], + "markers": "python_version >= '3.9'", + "version": "==25.7.0" + }, + "markdown-it-py": { + "hashes": [ + "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", + "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3" + ], + "markers": "python_version >= '3.10'", + "version": "==4.0.0" + }, "mccabe": { "hashes": [ "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", @@ -153,6 +293,22 @@ "markers": "python_version >= '3.6'", "version": "==0.7.0" }, + "mdurl": { + "hashes": [ + "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", + "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba" + ], + "markers": "python_version >= '3.7'", + "version": "==0.1.2" + }, + "more-itertools": { + "hashes": [ + "sha256:52d4362373dcf7c52546bc4af9a86ee7c4579df9a8dc268be0a2f949d376cc9b", + "sha256:f638ddf8a1a0d134181275fb5d58b086ead7c6a72429ad725c67503f13ba30bd" + ], + "markers": "python_version >= '3.9'", + "version": "==10.8.0" + }, "mypy-extensions": { "hashes": [ "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", @@ -177,13 +333,20 @@ "markers": "python_version >= '3.8'", "version": "==0.12.1" }, + "pexpect": { + "hashes": [ + "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", + "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f" + ], + "version": "==4.9.0" + }, "platformdirs": { "hashes": [ - "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85", - "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf" + "sha256:70ddccdd7c99fc5942e9fc25636a8b34d04c24b335100223152c2803e4063312", + "sha256:e578a81bb873cbb89a41fcc904c7ef523cc18284b7e3b3ccf06aca1403b7ebd3" ], - "markers": "python_version >= '3.9'", - "version": "==4.4.0" + "markers": "python_version >= '3.10'", + "version": "==4.5.0" }, "pluggy": { "hashes": [ @@ -193,6 +356,13 @@ "markers": "python_version >= '3.9'", "version": "==1.6.0" }, + "ptyprocess": { + "hashes": [ + "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", + "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220" + ], + "version": "==0.7.0" + }, "pycodestyle": { "hashes": [ "sha256:c4b5b517d278089ff9d0abdec919cd97262a3367449ea1c8b49b91529167b783", @@ -217,14 +387,22 @@ "markers": "python_version >= '3.8'", "version": "==2.19.2" }, + "pyproject-hooks": { + "hashes": [ + "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8", + "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913" + ], + "markers": "python_version >= '3.7'", + "version": "==1.2.0" + }, "pytest": { "hashes": [ - "sha256:8f44522eafe4137b0f35c9ce3072931a788a21ee40a2ed279e817d3cc16ed21e", - "sha256:e5ccdf10b0bac554970ee88fc1a4ad0ee5d221f8ef22321f9b7e4584e19d7f96" + "sha256:3e9c069ea73583e255c3b21cf46b8d3c56f6e3a1a8f6da94ccb0fcf57b9d73c8", + "sha256:67be0030d194df2dfa7b556f2e56fb3c3315bd5c8822c6951162b92b32ce7dad" ], "index": "pypi", "markers": "python_version >= '3.10'", - "version": "==9.0.0" + "version": "==9.0.1" }, "pytest-randomly": { "hashes": [ @@ -237,11 +415,212 @@ }, "pytokens": { "hashes": [ - "sha256:c9a4bfa0be1d26aebce03e6884ba454e842f186a59ea43a6d3b25af58223c044", - "sha256:db7b72284e480e69fb085d9f251f66b3d2df8b7166059261258ff35f50fb711b" + "sha256:2f932b14ed08de5fcf0b391ace2642f858f1394c0857202959000b68ed7a458a", + "sha256:95b2b5eaf832e469d141a378872480ede3f251a5a5041b8ec6e581d3ac71bbf3" + ], + "markers": "python_version >= '3.8'", + "version": "==0.3.0" + }, + "pywin32-ctypes": { + "hashes": [ + "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", + "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755" + ], + "markers": "python_version >= '3.6'", + "version": "==0.2.3" + }, + "rich": { + "hashes": [ + "sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4", + "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd" + ], + "markers": "python_full_version >= '3.8.0'", + "version": "==14.2.0" + }, + "shellingham": { + "hashes": [ + "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", + "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de" + ], + "markers": "python_version >= '3.7'", + "version": "==1.5.4" + }, + "sniffio": { + "hashes": [ + "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", + "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.1" + }, + "tomli-w": { + "hashes": [ + "sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90", + "sha256:2dd14fac5a47c27be9cd4c976af5a12d87fb1f0b4512f81d69cce3b35ae25021" + ], + "markers": "python_version >= '3.9'", + "version": "==1.2.0" + }, + "tomlkit": { + "hashes": [ + "sha256:430cf247ee57df2b94ee3fbe588e71d362a941ebb545dec29b53961d61add2a1", + "sha256:c89c649d79ee40629a9fda55f8ace8c6a1b42deb912b2a8fd8d942ddadb606b0" ], "markers": "python_version >= '3.8'", - "version": "==0.1.10" + "version": "==0.13.3" + }, + "trove-classifiers": { + "hashes": [ + "sha256:6b60f49d40bbd895bc61d8dc414fc2f2286d70eb72ed23548db8cf94f62804ca", + "sha256:d1dac259c1e908939862e3331177931c6df0a37af2c1a8debcc603d9115fcdd9" + ], + "version": "==2025.11.14.15" + }, + "userpath": { + "hashes": [ + "sha256:2cbf01a23d655a1ff8fc166dfb78da1b641d1ceabf0fe5f970767d380b14e89d", + "sha256:6c52288dab069257cc831846d15d48133522455d4677ee69a9781f11dbefd815" + ], + "markers": "python_version >= '3.7'", + "version": "==1.9.2" + }, + "uv": { + "hashes": [ + "sha256:110fd2062dccc4825f96cef0007f6bbb6f5da117af50415bed6f6dcd5e1e3603", + "sha256:21981bc859802c94d4b8f026b8734d39e8146baac703f1e3eab2e2d87d65ca8c", + "sha256:3c133e34feca0823d952a1d323d1d47f2b35e13154de5ca293d188f5b8792a62", + "sha256:3c2ddc0bca2e4b7e31623a17d60ea5f8d1ee4ff3ee27ddbf884e089e57cd0c93", + "sha256:4e256d3cc542f73435b27a3d0bf2a6b0f9d2dd6dd5c8df1a8028834deb896819", + "sha256:516d1c5549912696ba68376d2652661ed327199a9ec15763f7baa29bc75b35ec", + "sha256:55ecddf19314f7da5b8dea6bcfcc86f5769dd7d22106c731e8e6cfbf3fa6b98d", + "sha256:5e7a86eb5edbb9064b1401522eb10c5bd25ff56c04cd0ed253d0cd088a448bef", + "sha256:763cf33c7c5ab490323fab667b24f66412c3c3ca58e86b56e13fc0109d031a1b", + "sha256:780a7af4a7dfb0894a8d367b5c3a48f926480f465a34aa4a8633d6e4f521e517", + "sha256:84128ca76a665fe0584bff6ef913741d5615a4187c1aaed81739d519e669cfbd", + "sha256:8c8969d54c9f603107445a23f36fba03a0dfa4c75b3ada2faf94ed371f26f3a4", + "sha256:92d4b58ef810eaf5edf95c607d613ff240ab903ee599af1d687f891ab64b4129", + "sha256:9ee9027eb98cf5a99d9a3d5ddab7048745e2e49d572869044f66772e17f57792", + "sha256:a02b27e00afe0d7908fbb9ec61ad5338508e02356138a8a718af239fe773dd2e", + "sha256:b0a0c4594871de9e8b12c9e10982dc83e2414b712a34e84860fac9fbc8510c5a", + "sha256:c9a326f04b670f1af2d9fa90e50af57a9a872a8dc90bb377d0c27b2030438ffc", + "sha256:d4903e73f5e281ce5c3def60014bef93d2d1a148901653e222470ce54987f4a1", + "sha256:dfcc3cd5765158e82a0f52066462e378887aac01b347b588907fe3290af92356" + ], + "markers": "python_version >= '3.8'", + "version": "==0.9.10" + }, + "virtualenv": { + "hashes": [ + "sha256:643d3914d73d3eeb0c552cbb12d7e82adf0e504dbf86a3182f8771a153a1971c", + "sha256:c21c9cede36c9753eeade68ba7d523529f228a403463376cf821eaae2b650f1b" + ], + "markers": "python_version >= '3.8'", + "version": "==20.35.4" + }, + "zstandard": { + "hashes": [ + "sha256:011d388c76b11a0c165374ce660ce2c8efa8e5d87f34996aa80f9c0816698b64", + "sha256:01582723b3ccd6939ab7b3a78622c573799d5d8737b534b86d0e06ac18dbde4a", + "sha256:05353cef599a7b0b98baca9b068dd36810c3ef0f42bf282583f438caf6ddcee3", + "sha256:05df5136bc5a011f33cd25bc9f506e7426c0c9b3f9954f056831ce68f3b6689f", + "sha256:06acb75eebeedb77b69048031282737717a63e71e4ae3f77cc0c3b9508320df6", + "sha256:07b527a69c1e1c8b5ab1ab14e2afe0675614a09182213f21a0717b62027b5936", + "sha256:0bbc9a0c65ce0eea3c34a691e3c4b6889f5f3909ba4822ab385fab9057099431", + "sha256:0be7622c37c183406f3dbf0cba104118eb16a4ea7359eeb5752f0794882fc250", + "sha256:106281ae350e494f4ac8a80470e66d1fe27e497052c8d9c3b95dc4cf1ade81aa", + "sha256:10ef2a79ab8e2974e2075fb984e5b9806c64134810fac21576f0668e7ea19f8f", + "sha256:1673b7199bbe763365b81a4f3252b8e80f44c9e323fc42940dc8843bfeaf9851", + "sha256:172de1f06947577d3a3005416977cce6168f2261284c02080e7ad0185faeced3", + "sha256:181eb40e0b6a29b3cd2849f825e0fa34397f649170673d385f3598ae17cca2e9", + "sha256:1869da9571d5e94a85a5e8d57e4e8807b175c9e4a6294e3b66fa4efb074d90f6", + "sha256:19796b39075201d51d5f5f790bf849221e58b48a39a5fc74837675d8bafc7362", + "sha256:1cd5da4d8e8ee0e88be976c294db744773459d51bb32f707a0f166e5ad5c8649", + "sha256:1f3689581a72eaba9131b1d9bdbfe520ccd169999219b41000ede2fca5c1bfdb", + "sha256:1f830a0dac88719af0ae43b8b2d6aef487d437036468ef3c2ea59c51f9d55fd5", + "sha256:223415140608d0f0da010499eaa8ccdb9af210a543fac54bce15babbcfc78439", + "sha256:22a06c5df3751bb7dc67406f5374734ccee8ed37fc5981bf1ad7041831fa1137", + "sha256:22a086cff1b6ceca18a8dd6096ec631e430e93a8e70a9ca5efa7561a00f826fa", + "sha256:23ebc8f17a03133b4426bcc04aabd68f8236eb78c3760f12783385171b0fd8bd", + "sha256:25f8f3cd45087d089aef5ba3848cd9efe3ad41163d3400862fb42f81a3a46701", + "sha256:2b6bd67528ee8b5c5f10255735abc21aa106931f0dbaf297c7be0c886353c3d0", + "sha256:2e54296a283f3ab5a26fc9b8b5d4978ea0532f37b231644f367aa588930aa043", + "sha256:3756b3e9da9b83da1796f8809dd57cb024f838b9eeafde28f3cb472012797ac1", + "sha256:37daddd452c0ffb65da00620afb8e17abd4adaae6ce6310702841760c2c26860", + "sha256:3a39c94ad7866160a4a46d772e43311a743c316942037671beb264e395bdd611", + "sha256:3b870ce5a02d4b22286cf4944c628e0f0881b11b3f14667c1d62185a99e04f53", + "sha256:3c83b0188c852a47cd13ef3bf9209fb0a77fa5374958b8c53aaa699398c6bd7b", + "sha256:4203ce3b31aec23012d3a4cf4a2ed64d12fea5269c49aed5e4c3611b938e4088", + "sha256:457ed498fc58cdc12fc48f7950e02740d4f7ae9493dd4ab2168a47c93c31298e", + "sha256:474d2596a2dbc241a556e965fb76002c1ce655445e4e3bf38e5477d413165ffa", + "sha256:4b14abacf83dfb5c25eb4e4a79520de9e7e205f72c9ee7702f91233ae57d33a2", + "sha256:4b6d83057e713ff235a12e73916b6d356e3084fd3d14ced499d84240f3eecee0", + "sha256:4d441506e9b372386a5271c64125f72d5df6d2a8e8a2a45a0ae09b03cb781ef7", + "sha256:4f187a0bb61b35119d1926aee039524d1f93aaf38a9916b8c4b78ac8514a0aaf", + "sha256:51526324f1b23229001eb3735bc8c94f9c578b1bd9e867a0a646a3b17109f388", + "sha256:53e08b2445a6bc241261fea89d065536f00a581f02535f8122eba42db9375530", + "sha256:53f94448fe5b10ee75d246497168e5825135d54325458c4bfffbaafabcc0a577", + "sha256:5a56ba0db2d244117ed744dfa8f6f5b366e14148e00de44723413b2f3938a902", + "sha256:5f1ad7bf88535edcf30038f6919abe087f606f62c00a87d7e33e7fc57cb69fcc", + "sha256:5f5e4c2a23ca271c218ac025bd7d635597048b366d6f31f420aaeb715239fc98", + "sha256:6a573a35693e03cf1d67799fd01b50ff578515a8aeadd4595d2a7fa9f3ec002a", + "sha256:6c0e5a65158a7946e7a7affa6418878ef97ab66636f13353b8502d7ea03c8097", + "sha256:6dffecc361d079bb48d7caef5d673c88c8988d3d33fb74ab95b7ee6da42652ea", + "sha256:7030defa83eef3e51ff26f0b7bfb229f0204b66fe18e04359ce3474ac33cbc09", + "sha256:7149623bba7fdf7e7f24312953bcf73cae103db8cae49f8154dd1eadc8a29ecb", + "sha256:72d35d7aa0bba323965da807a462b0966c91608ef3a48ba761678cb20ce5d8b7", + "sha256:75ffc32a569fb049499e63ce68c743155477610532da1eb38e7f24bf7cd29e74", + "sha256:7713e1179d162cf5c7906da876ec2ccb9c3a9dcbdffef0cc7f70c3667a205f0b", + "sha256:78228d8a6a1c177a96b94f7e2e8d012c55f9c760761980da16ae7546a15a8e9b", + "sha256:7b3c3a3ab9daa3eed242d6ecceead93aebbb8f5f84318d82cee643e019c4b73b", + "sha256:809c5bcb2c67cd0ed81e9229d227d4ca28f82d0f778fc5fea624a9def3963f91", + "sha256:81dad8d145d8fd981b2962b686b2241d3a1ea07733e76a2f15435dfb7fb60150", + "sha256:85304a43f4d513f5464ceb938aa02c1e78c2943b29f44a750b48b25ac999a049", + "sha256:89c4b48479a43f820b749df49cd7ba2dbc2b1b78560ecb5ab52985574fd40b27", + "sha256:8e735494da3db08694d26480f1493ad2cf86e99bdd53e8e9771b2752a5c0246a", + "sha256:913cbd31a400febff93b564a23e17c3ed2d56c064006f54efec210d586171c00", + "sha256:9174f4ed06f790a6869b41cba05b43eeb9a35f8993c4422ab853b705e8112bbd", + "sha256:9300d02ea7c6506f00e627e287e0492a5eb0371ec1670ae852fefffa6164b072", + "sha256:933b65d7680ea337180733cf9e87293cc5500cc0eb3fc8769f4d3c88d724ec5c", + "sha256:9654dbc012d8b06fc3d19cc825af3f7bf8ae242226df5f83936cb39f5fdc846c", + "sha256:98750a309eb2f020da61e727de7d7ba3c57c97cf6213f6f6277bb7fb42a8e065", + "sha256:99c0c846e6e61718715a3c9437ccc625de26593fea60189567f0118dc9db7512", + "sha256:a1a4ae2dec3993a32247995bdfe367fc3266da832d82f8438c8570f989753de1", + "sha256:a3f79487c687b1fc69f19e487cd949bf3aae653d181dfb5fde3bf6d18894706f", + "sha256:a4089a10e598eae6393756b036e0f419e8c1d60f44a831520f9af41c14216cf2", + "sha256:a51ff14f8017338e2f2e5dab738ce1ec3b5a851f23b18c1ae1359b1eecbee6df", + "sha256:a5a419712cf88862a45a23def0ae063686db3d324cec7edbe40509d1a79a0aab", + "sha256:a9ec8c642d1ec73287ae3e726792dd86c96f5681eb8df274a757bf62b750eae7", + "sha256:aaf21ba8fb76d102b696781bddaa0954b782536446083ae3fdaa6f16b25a1c4b", + "sha256:ab85470ab54c2cb96e176f40342d9ed41e58ca5733be6a893b730e7af9c40550", + "sha256:b9af1fe743828123e12b41dd8091eca1074d0c1569cc42e6e1eee98027f2bbd0", + "sha256:bfc4e20784722098822e3eee42b8e576b379ed72cca4a7cb856ae733e62192ea", + "sha256:bfd06b1c5584b657a2892a6014c2f4c20e0db0208c159148fa78c65f7e0b0277", + "sha256:c19bcdd826e95671065f8692b5a4aa95c52dc7a02a4c5a0cac46deb879a017a2", + "sha256:c2ba942c94e0691467ab901fc51b6f2085ff48f2eea77b1a48240f011e8247c7", + "sha256:c8e167d5adf59476fa3e37bee730890e389410c354771a62e3c076c86f9f7778", + "sha256:ca54090275939dc8ec5dea2d2afb400e0f83444b2fc24e07df7fdef677110859", + "sha256:d7541afd73985c630bafcd6338d2518ae96060075f9463d7dc14cfb33514383d", + "sha256:d8c56bb4e6c795fc77d74d8e8b80846e1fb8292fc0b5060cd8131d522974b751", + "sha256:da469dc041701583e34de852d8634703550348d5822e66a0c827d39b05365b12", + "sha256:daab68faadb847063d0c56f361a289c4f268706b598afbf9ad113cbe5c38b6b2", + "sha256:e05ab82ea7753354bb054b92e2f288afb750e6b439ff6ca78af52939ebbc476d", + "sha256:e09bb6252b6476d8d56100e8147b803befa9a12cea144bbe629dd508800d1ad0", + "sha256:e29f0cf06974c899b2c188ef7f783607dbef36da4c242eb6c82dcd8b512855e3", + "sha256:e59fdc271772f6686e01e1b3b74537259800f57e24280be3f29c8a0deb1904dd", + "sha256:e7360eae90809efd19b886e59a09dad07da4ca9ba096752e61a2e03c8aca188e", + "sha256:e96594a5537722fdfb79951672a2a63aec5ebfb823e7560586f7484819f2a08f", + "sha256:ea9d54cc3d8064260114a0bbf3479fc4a98b21dffc89b3459edd506b69262f6e", + "sha256:ec996f12524f88e151c339688c3897194821d7f03081ab35d31d1e12ec975e94", + "sha256:f27662e4f7dbf9f9c12391cb37b4c4c3cb90ffbd3b1fb9284dadbbb8935fa708", + "sha256:f373da2c1757bb7f1acaf09369cdc1d51d84131e50d5fa9863982fd626466313", + "sha256:f5aeea11ded7320a84dcdd62a3d95b5186834224a9e55b92ccae35d21a8b63d4", + "sha256:f604efd28f239cc21b3adb53eb061e2a205dc164be408e553b41ba2ffe0ca15c", + "sha256:f67e8f1a324a900e75b5e28ffb152bcac9fbed1cc7b43f99cd90f395c4375344", + "sha256:fd7a5004eb1980d3cefe26b2685bcb0b17989901a70a1040d1ac86f1d898c551", + "sha256:ffef5a74088f1e09947aecf91011136665152e0b4b359c42be3373897fb39b01" + ], + "markers": "python_version >= '3.9'", + "version": "==0.25.0" } } } diff --git a/README.md b/README.md index b96791d..0a69fcd 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ -# LinkWatch +# linkstat diff --git a/README_JP.md b/README_JP.md new file mode 100644 index 0000000..2cc880f --- /dev/null +++ b/README_JP.md @@ -0,0 +1,31 @@ +# linkstat +
+[![test-lint-format](https://github.com/DogFortune/linkstat/actions/workflows/lint-test-format.yml/badge.svg?branch=main)](https://github.com/DogFortune/linkstat/actions) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) +
+ +_linkstat_ はドキュメントに記載されているリンクの疎通確認を行うスクリプトです。リンク切れの早期発見を行う事でドキュメントの健全性を保ちます。 +現在対応しているのはMarkdownファイル(*.md)のみです。 + +## インストール + +```sh +pip install linkstat +``` + +## 使い方 + +```sh +linkstat {source_file_or_directory} +``` + +パスを指定しない場合はカレントディレクトリを検査対象とします。 + +## 出力 +オプションを使用することでJSON形式のレポートを出力できます。 + +```sh +linkstat --report-json {path} {source_file_or_directory} +``` + +## コントリビュート +[ガイドライン](CONTRIBUTING_JP.md) diff --git a/README_jp.md b/README_jp.md deleted file mode 100644 index b96791d..0000000 --- a/README_jp.md +++ /dev/null @@ -1,2 +0,0 @@ -# LinkWatch - diff --git a/THIRD-PARTY-LICENSES.md b/THIRD-PARTY-LICENSES.md new file mode 100644 index 0000000..b4e25cd --- /dev/null +++ b/THIRD-PARTY-LICENSES.md @@ -0,0 +1,41 @@ +# THIRD-PARTY-LICENSES +## pytest +The MIT License (MIT) +Copyright (c) 2004 Holger Krekel and others +https://github.com/pytest-dev/pytest/blob/9913cedb51a39da580d3ef3aff8cff006c3e7fc6/LICENSE + +## pytest-randomly +The MIT License +Copyright (c) 2017 Adam Johnson +https://github.com/pytest-dev/pytest-randomly/blob/5301bcc47efcc5c437cb07656897d0767cd4e5df/LICENSE + +## build +The MIT License (MIT) +Copyright © 2019 Filipe Laíns +https://github.com/pypa/build/blob/48c9d90339f52b8c5e518317c228b4895ac83549/LICENSE + +## hatch +The MIT License +Copyright (c) 2017-present Ofek Lev +https://github.com/pypa/hatch/blob/8695db4ecdb60e48d809c5095358d076dc22ebf2/LICENSE.txt + +## Flake8 +Flake8 License (MIT) +Copyright (C) 2011-2013 Tarek Ziade +Copyright (C) 2012-2016 Ian Cordasco +https://github.com/PyCQA/flake8/blob/ed8ac7bdc2037c2432230bc0ba299d5672905d1d/LICENSE + +## black +The MIT License (MIT) +Copyright (c) 2018 Łukasz Langa +https://github.com/psf/black/blob/43135e9fafccbca723910a45aa62f0f182e85e5f/LICENSE + +## tqdm +MPL v2.0 and MIT +Copyright (c) 2013 noamraph +https://github.com/tqdm/tqdm/blob/0ed5d7f18fa3153834cbac0aa57e8092b217cc16/LICENCE + +## Dataclasses JSON +The MIT License +Copyright (c) 2019 Charles Li and contributors +https://github.com/lidatong/dataclasses-json/blob/dc63902eeb5e1c5ce1ea4e078c50e0eb9bc1a541/LICENSE \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 75ea34b..500e7b3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,16 +1,40 @@ [project] -name = "linkwatch" -authors = [{ name = "DogFortune" }] +name = "linkstat" +authors = [{ name = "DogFortune", email = "dogfortune.2000@gmail.com" }] description = "Perform connectivity checks on URLs listed in the Markdown" license-files = ["LICENSE"] readme = "README.md" requires-python = ">=3.10" -version = "0.0.1" +version = "0.0.2" dependencies = ["tqdm", "dataclasses-json"] +keywords = ["check", "url", "link"] +classifiers = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3 :: Only", + "Topic :: Documentation", + "Topic :: Internet", +] + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" [project.scripts] -linkwatch = "src.app:main" +linkstat = "linkstat.app:main" + +[project.urls] +Repository = "https://github.com/DogFortune/linkstat" +Issues = "https://github.com/DogFortune/linkstat/issues" +Changelog = "https://github.com/DogFortune/linkstat/releases" [tool.pytest.ini_options] pythonpath = "src" testpaths = ["tests"] + +[tool.hatch.build.targets.wheel] +packages = ["src/linkstat"] + +[tool.hatch.publish.index] +disable = true diff --git a/src/__main__.py b/src/linkstat/__main__.py similarity index 100% rename from src/__main__.py rename to src/linkstat/__main__.py diff --git a/src/analyzer.py b/src/linkstat/analyzer.py similarity index 93% rename from src/analyzer.py rename to src/linkstat/analyzer.py index f88d974..5c9667a 100644 --- a/src/analyzer.py +++ b/src/linkstat/analyzer.py @@ -1,8 +1,8 @@ from pathlib import Path from urllib.request import urlopen from urllib.error import HTTPError, URLError -from enums import Result -from reporter import ReportData +from linkstat.enums import Result +from linkstat.reporter import ReportData from dataclasses import dataclass import re from tqdm import tqdm @@ -87,12 +87,14 @@ def search(path: str, filter="*.md") -> list: :rtype: list """ p = Path(path) + if p.is_file(): + return [str(p)] files = [str(item) for item in p.rglob(filter)] return files def extract_url(files: list) -> dict[str, URLInfo]: - """ファイルからURLを抽出します。 + """ファイルからURLを抽出します。重複しているリンクも含まれます。 :param files: _description_ :type files: list diff --git a/src/app.py b/src/linkstat/app.py similarity index 77% rename from src/app.py rename to src/linkstat/app.py index e5f1390..f42781d 100644 --- a/src/app.py +++ b/src/linkstat/app.py @@ -1,9 +1,10 @@ import os -import analyzer -import reporter +from pathlib import Path +from . import analyzer +from . import reporter import argparse -from enums import OutputType -from reporter import ReportData +from .enums import OutputType +from .reporter import ReportData def __output(data: list[ReportData], format: OutputType, args): @@ -25,7 +26,7 @@ def __output(data: list[ReportData], format: OutputType, args): reporter.dump_json(data, output_path) -def __format__setting(args) -> OutputType: +def __format_setting(args) -> OutputType: """結果の出力形式の設定 :param args: Arguments @@ -34,6 +35,10 @@ def __format__setting(args) -> OutputType: :rtype: OutputType """ if args.report_json: + if Path(args.report_json).is_dir(): + raise ValueError( + f"ERROR: --report-path must be a filename, given: {args.report_json}" + ) return OutputType.Json else: return OutputType.Console @@ -52,7 +57,7 @@ def main(args=None): parser = create_parser() parsed_args = parser.parse_args(args) - format = __format__setting(parsed_args) + format = __format_setting(parsed_args) src = parsed_args.src files = analyzer.search(src) diff --git a/src/enums.py b/src/linkstat/enums.py similarity index 100% rename from src/enums.py rename to src/linkstat/enums.py diff --git a/src/reporter.py b/src/linkstat/reporter.py similarity index 100% rename from src/reporter.py rename to src/linkstat/reporter.py diff --git a/tests/test_analyzer.py b/tests/test_analyzer.py index cfbd1ad..bf6bc42 100644 --- a/tests/test_analyzer.py +++ b/tests/test_analyzer.py @@ -1,6 +1,7 @@ +import os import pytest -import analyzer -from reporter import ReportData +from linkstat import analyzer +from linkstat.reporter import ReportData @pytest.mark.parametrize( @@ -26,13 +27,23 @@ def test_request(url: str, expected_result: str, expected_status_code: int): assert res.reason is not None -def test_check_links(): - files = analyzer.search("tests/sample_doc/") +@pytest.mark.parametrize( + ["path", "report_data_count"], + [ + # ディレクトリ指定パターン + pytest.param("tests/sample_doc/", 3), + # 単体ファイル指定パターン + pytest.param("tests/sample_doc/doc1.md", 1), + pytest.param("tests/sample_doc/doc2.md", 3), + ], +) +def test_check_links(path: str, report_data_count: int): + files = analyzer.search(path) links = analyzer.extract_url(files) results_report_data = analyzer.check_links(links) # 重複しているリンクは結果に含まれていない事(ドキュメントに記載されているリンクの数 - 重複しているリンクの数になっている事) - assert len(results_report_data) == 3 + assert len(results_report_data) == report_data_count # 形式チェック for item in results_report_data: @@ -56,26 +67,32 @@ def test_search(path: str): assert len(files) == 2 +def test_search_single_file(): + """単一のファイルを指定した場合、指定したファイルのパスだけが入っているリストが返ってくる事""" + files = analyzer.search("tests/sample_doc/doc1.md") + + assert len(files) == 1 + assert os.path.basename(files[0]) == "doc1.md" + + def test_extract_link(): # ファイルからリンクを抽出するテスト。対象のドキュメントすべてのリンクを抽出する。 # データ構造としてはdictのKeyにファイルのパス、Valueにリンクに関する情報が入っている。 # これは1ファイルの中に大量のリンクがあった時、すべてがフラットなリストだとファイル名を1つ1つ持つ事になるのでデータ量が増えてしまう。ファイル名は値として重複しやすいので、Keyという形で1つにまとめたのが理由。 # 重複リンクにはフラグをつける。2つ目以降はFalseになるのでTrueのものだけリンクチェックすればOK files = analyzer.search("tests/sample_doc/") + links = analyzer.extract_url(files) assert len(links) == 2 - doc1_result = [ item for key, value in links.items() if "doc1.md" in key for item in value ] doc2_result = [ item for key, value in links.items() if "doc2.md" in key for item in value ] - assert len(doc1_result) == 1 assert len(doc2_result) == 4 - # ちゃんと重複判定の数が正しいか、重複と見なしたリンクは想定しているものか duplicated_link_list = [item for item in doc2_result if item.duplicate] assert len(duplicated_link_list) == 2 diff --git a/tests/test_app.py b/tests/test_app.py index 2420a98..4ea939d 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -1,5 +1,6 @@ -import app +from linkstat import app import os +import pytest from tempfile import TemporaryDirectory from pathlib import Path @@ -8,7 +9,7 @@ class TestValid: """正常系""" def test_main_with_minimal_arguments(self): - """環境変数も引数も指定しない場合、コンソールモードで動作する事""" + """環境変数も引数も指定しない一気通貫のテスト""" app.main(["tests/sample_doc/"]) def test_main_with_output_json(self): @@ -18,3 +19,17 @@ def test_main_with_output_json(self): app.main(["tests/sample_doc/", "--report-json", str(output_path)]) assert os.path.isfile(output_path) is True + + def test_main_report_path_directory(self): + """出力パスとしてファイルではなくディレクトリで指定されていた場合、エラーが発生する事 + ERROR: --report-path must be a filename, given: tmp/ + """ + with TemporaryDirectory() as dir: + with pytest.raises( + ValueError, match="ERROR: --report-path must be a filename" + ): + app.main(["tests/sample_doc/", "--report-json", str(dir)]) + + def test_main_single_file(self): + """単体のファイルを指定した場合も正しく動作する事""" + app.main(["tests/sample_doc/doc1.md"]) diff --git a/tests/test_reporter.py b/tests/test_reporter.py index dd7502c..968b849 100644 --- a/tests/test_reporter.py +++ b/tests/test_reporter.py @@ -1,6 +1,6 @@ import pytest -import reporter -import analyzer +from linkstat import reporter +from linkstat import analyzer from tempfile import TemporaryDirectory from pathlib import Path import os