mirror of
https://github.com/fastapi/fastapi.git
synced 2026-01-09 14:40:20 -05:00
Compare commits
42 Commits
dependabot
...
translatio
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
18de676729 | ||
|
|
c7f776407b | ||
|
|
d928bff07f | ||
|
|
cfc9b9430b | ||
|
|
e6a08f313d | ||
|
|
bf8507209a | ||
|
|
9a96763bad | ||
|
|
b08681fafd | ||
|
|
6fcc6054ff | ||
|
|
ce8a5ab91c | ||
|
|
f5112778d0 | ||
|
|
a8bf5871d7 | ||
|
|
5ca9472d8a | ||
|
|
5c50b3dd15 | ||
|
|
8c5f21c83c | ||
|
|
6b987b7262 | ||
|
|
50dd09a7b2 | ||
|
|
e076f651e7 | ||
|
|
badefaba9f | ||
|
|
5b812d4754 | ||
|
|
44b530168e | ||
|
|
6c50c68761 | ||
|
|
c42dd05cb8 | ||
|
|
aba58fc19d | ||
|
|
c70d79afe9 | ||
|
|
44f25ad0ac | ||
|
|
51df013955 | ||
|
|
7ff3dfb4fc | ||
|
|
9aa406d624 | ||
|
|
b3ad074153 | ||
|
|
e7fb2453ea | ||
|
|
f2687dc1bb | ||
|
|
862c3f4f94 | ||
|
|
052d6e86c2 | ||
|
|
31c7ffcdfe | ||
|
|
6854be9ebc | ||
|
|
258deb925d | ||
|
|
beff498743 | ||
|
|
0339277673 | ||
|
|
2c56706505 | ||
|
|
e15cff7376 | ||
|
|
844ded6b43 |
@@ -1,6 +1,6 @@
|
||||
tiangolo:
|
||||
login: tiangolo
|
||||
count: 808
|
||||
count: 857
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
|
||||
url: https://github.com/tiangolo
|
||||
dependabot:
|
||||
@@ -10,7 +10,7 @@ dependabot:
|
||||
url: https://github.com/apps/dependabot
|
||||
alejsdev:
|
||||
login: alejsdev
|
||||
count: 52
|
||||
count: 53
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=85ceac49fb87138aebe8d663912e359447329090&v=4
|
||||
url: https://github.com/alejsdev
|
||||
pre-commit-ci:
|
||||
@@ -18,6 +18,11 @@ pre-commit-ci:
|
||||
count: 50
|
||||
avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4
|
||||
url: https://github.com/apps/pre-commit-ci
|
||||
YuriiMotov:
|
||||
login: YuriiMotov
|
||||
count: 36
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
|
||||
url: https://github.com/YuriiMotov
|
||||
github-actions:
|
||||
login: github-actions
|
||||
count: 26
|
||||
@@ -28,26 +33,21 @@ Kludex:
|
||||
count: 25
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4
|
||||
url: https://github.com/Kludex
|
||||
YuriiMotov:
|
||||
login: YuriiMotov
|
||||
count: 20
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
|
||||
url: https://github.com/YuriiMotov
|
||||
dmontagu:
|
||||
login: dmontagu
|
||||
count: 17
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4
|
||||
url: https://github.com/dmontagu
|
||||
svlandeg:
|
||||
login: svlandeg
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4
|
||||
url: https://github.com/svlandeg
|
||||
nilslindemann:
|
||||
login: nilslindemann
|
||||
count: 15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4
|
||||
url: https://github.com/nilslindemann
|
||||
svlandeg:
|
||||
login: svlandeg
|
||||
count: 14
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4
|
||||
url: https://github.com/svlandeg
|
||||
euri10:
|
||||
login: euri10
|
||||
count: 13
|
||||
@@ -553,6 +553,11 @@ DanielKusyDev:
|
||||
count: 2
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/36250676?u=2ea6114ff751fc48b55f231987a0e2582c6b1bd2&v=4
|
||||
url: https://github.com/DanielKusyDev
|
||||
Viicos:
|
||||
login: Viicos
|
||||
count: 2
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/65306057?u=fcd677dc1b9bef12aa103613e5ccb3f8ce305af9&v=4
|
||||
url: https://github.com/Viicos
|
||||
DanielYang59:
|
||||
login: DanielYang59
|
||||
count: 2
|
||||
|
||||
@@ -2,57 +2,51 @@ sponsors:
|
||||
- - login: renderinc
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/36424661?v=4
|
||||
url: https://github.com/renderinc
|
||||
- login: andrew-propelauth
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/89474256?u=c98993dec8553c09d424ede67bbe86e5c35f48c9&v=4
|
||||
url: https://github.com/andrew-propelauth
|
||||
- login: blockbee-io
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/115143449?u=1b8620c2d6567c4df2111a371b85a51f448f9b85&v=4
|
||||
url: https://github.com/blockbee-io
|
||||
- login: zuplo
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/85497839?v=4
|
||||
url: https://github.com/zuplo
|
||||
- login: coderabbitai
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/132028505?v=4
|
||||
url: https://github.com/coderabbitai
|
||||
- login: greptileai
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/140149887?v=4
|
||||
url: https://github.com/greptileai
|
||||
- login: subtotal
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/176449348?v=4
|
||||
url: https://github.com/subtotal
|
||||
- login: greptileai
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/140149887?v=4
|
||||
url: https://github.com/greptileai
|
||||
- login: coderabbitai
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/132028505?v=4
|
||||
url: https://github.com/coderabbitai
|
||||
- login: zuplo
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/85497839?v=4
|
||||
url: https://github.com/zuplo
|
||||
- login: blockbee-io
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/115143449?u=1b8620c2d6567c4df2111a371b85a51f448f9b85&v=4
|
||||
url: https://github.com/blockbee-io
|
||||
- login: andrew-propelauth
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/89474256?u=c98993dec8553c09d424ede67bbe86e5c35f48c9&v=4
|
||||
url: https://github.com/andrew-propelauth
|
||||
- login: railwayapp
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/66716858?v=4
|
||||
url: https://github.com/railwayapp
|
||||
- - login: dribia
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41189616?v=4
|
||||
url: https://github.com/dribia
|
||||
- login: svix
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/80175132?v=4
|
||||
url: https://github.com/svix
|
||||
- - login: speakeasy-api
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/91446104?v=4
|
||||
url: https://github.com/speakeasy-api
|
||||
- login: stainless-api
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/88061651?v=4
|
||||
url: https://github.com/stainless-api
|
||||
- login: speakeasy-api
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/91446104?v=4
|
||||
url: https://github.com/speakeasy-api
|
||||
- login: databento
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/64141749?v=4
|
||||
url: https://github.com/databento
|
||||
- login: svix
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/80175132?v=4
|
||||
url: https://github.com/svix
|
||||
- login: permitio
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/71775833?v=4
|
||||
url: https://github.com/permitio
|
||||
- - login: Ponte-Energy-Partners
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/114745848?v=4
|
||||
url: https://github.com/Ponte-Energy-Partners
|
||||
- login: LambdaTest-Inc
|
||||
- login: databento
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/64141749?v=4
|
||||
url: https://github.com/databento
|
||||
- - login: LambdaTest-Inc
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/171592363?u=96606606a45fa170427206199014f2a5a2a4920b&v=4
|
||||
url: https://github.com/LambdaTest-Inc
|
||||
- login: Ponte-Energy-Partners
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/114745848?v=4
|
||||
url: https://github.com/Ponte-Energy-Partners
|
||||
- login: BoostryJP
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/57932412?v=4
|
||||
url: https://github.com/BoostryJP
|
||||
- login: requestly
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/12287519?v=4
|
||||
url: https://github.com/requestly
|
||||
- login: acsone
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7601056?v=4
|
||||
url: https://github.com/acsone
|
||||
@@ -68,9 +62,6 @@ sponsors:
|
||||
- login: Doist
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2565372?v=4
|
||||
url: https://github.com/Doist
|
||||
- login: bholagabbar
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11693595?v=4
|
||||
url: https://github.com/bholagabbar
|
||||
- - login: mainframeindustries
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4
|
||||
url: https://github.com/mainframeindustries
|
||||
@@ -86,6 +77,9 @@ sponsors:
|
||||
- login: ChargeStorm
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/26000165?v=4
|
||||
url: https://github.com/ChargeStorm
|
||||
- login: ibrahimpelumi6142
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/113442282?v=4
|
||||
url: https://github.com/ibrahimpelumi6142
|
||||
- login: nilslindemann
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4
|
||||
url: https://github.com/nilslindemann
|
||||
@@ -116,124 +110,127 @@ sponsors:
|
||||
- login: Leay15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32212558?u=c4aa9c1737e515959382a5515381757b1fd86c53&v=4
|
||||
url: https://github.com/Leay15
|
||||
- login: Karine-Bauch
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/90465103?u=7feb1018abb1a5631cfd9a91fea723d1ceb5f49b&v=4
|
||||
url: https://github.com/Karine-Bauch
|
||||
- login: jugeeem
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/116043716?u=ae590d79c38ac79c91b9c5caa6887d061e865a3d&v=4
|
||||
url: https://github.com/jugeeem
|
||||
- login: patsatsia
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/61111267?u=3271b85f7a37b479c8d0ae0a235182e83c166edf&v=4
|
||||
url: https://github.com/patsatsia
|
||||
- login: anthonycepeda
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=60bdf46240cff8fca482ff0fc07d963fd5e1a27c&v=4
|
||||
url: https://github.com/anthonycepeda
|
||||
- login: patricioperezv
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/73832292?u=5f471f156e19ee7920e62ae0f4a47b95580e61cf&v=4
|
||||
url: https://github.com/patricioperezv
|
||||
- login: chickenandstats
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/79477966?u=ae2b894aa954070db1d7830dab99b49eba4e4567&v=4
|
||||
url: https://github.com/chickenandstats
|
||||
- login: Karine-Bauch
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/90465103?u=7feb1018abb1a5631cfd9a91fea723d1ceb5f49b&v=4
|
||||
url: https://github.com/Karine-Bauch
|
||||
- login: kaoru0310
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/80977929?u=1b61d10142b490e56af932ddf08a390fae8ee94f&v=4
|
||||
url: https://github.com/kaoru0310
|
||||
- login: jstanden
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/63288?u=c3658d57d2862c607a0e19c2101c3c51876e36ad&v=4
|
||||
url: https://github.com/jstanden
|
||||
- login: knallgelb
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2358812?u=c48cb6362b309d74cbf144bd6ad3aed3eb443e82&v=4
|
||||
url: https://github.com/knallgelb
|
||||
- login: dblackrun
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3528486?v=4
|
||||
url: https://github.com/dblackrun
|
||||
- login: zsinx6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3532625?u=ba75a5dc744d1116ccfeaaf30d41cb2fe81fe8dd&v=4
|
||||
url: https://github.com/zsinx6
|
||||
- login: kennywakeland
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3631417?u=7c8f743f1ae325dfadea7c62bbf1abd6a824fc55&v=4
|
||||
url: https://github.com/kennywakeland
|
||||
- login: aacayaco
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3634801?u=eaadda178c964178fcb64886f6c732172c8f8219&v=4
|
||||
url: https://github.com/aacayaco
|
||||
- login: anomaly
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3654837?v=4
|
||||
url: https://github.com/anomaly
|
||||
- login: mj0331
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3890353?u=1c627ac1a024515b4871de5c3ebbfaa1a57f65d4&v=4
|
||||
url: https://github.com/mj0331
|
||||
- login: gorhack
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4141690?u=ec119ebc4bdf00a7bc84657a71aa17834f4f27f3&v=4
|
||||
url: https://github.com/gorhack
|
||||
- login: Ryandaydev
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=679ff84cb7b988c5795a5fa583857f574a055763&v=4
|
||||
url: https://github.com/Ryandaydev
|
||||
- login: jaredtrog
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4
|
||||
url: https://github.com/jaredtrog
|
||||
- login: chickenandstats
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/79477966?u=ae2b894aa954070db1d7830dab99b49eba4e4567&v=4
|
||||
url: https://github.com/chickenandstats
|
||||
- login: patricioperezv
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/73832292?u=5f471f156e19ee7920e62ae0f4a47b95580e61cf&v=4
|
||||
url: https://github.com/patricioperezv
|
||||
- login: anthonycepeda
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=60bdf46240cff8fca482ff0fc07d963fd5e1a27c&v=4
|
||||
url: https://github.com/anthonycepeda
|
||||
- login: AalbatrossGuy
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/68378354?u=0bdeea9356d24f638244131f6d8d1e2d2f3601ca&v=4
|
||||
url: https://github.com/AalbatrossGuy
|
||||
- login: patsatsia
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/61111267?u=3271b85f7a37b479c8d0ae0a235182e83c166edf&v=4
|
||||
url: https://github.com/patsatsia
|
||||
- login: oliverxchen
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4
|
||||
url: https://github.com/oliverxchen
|
||||
- login: paulcwatts
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/150269?u=1819e145d573b44f0ad74b87206d21cd60331d4e&v=4
|
||||
url: https://github.com/paulcwatts
|
||||
- login: robintw
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/296686?v=4
|
||||
url: https://github.com/robintw
|
||||
- login: pamelafox
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/297042?v=4
|
||||
url: https://github.com/pamelafox
|
||||
- login: wshayes
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
|
||||
url: https://github.com/wshayes
|
||||
- login: koxudaxi
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/630670?u=507d8577b4b3670546b449c4c2ccbc5af40d72f7&v=4
|
||||
url: https://github.com/koxudaxi
|
||||
- login: falkben
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=ad9838e089058c9e5a0bab94c0eec7cc181e0cd0&v=4
|
||||
url: https://github.com/falkben
|
||||
- login: mintuhouse
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/769950?u=ecfbd79a97d33177e0d093ddb088283cf7fe8444&v=4
|
||||
url: https://github.com/mintuhouse
|
||||
- login: jaredtrog
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4
|
||||
url: https://github.com/jaredtrog
|
||||
- login: Ryandaydev
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=679ff84cb7b988c5795a5fa583857f574a055763&v=4
|
||||
url: https://github.com/Ryandaydev
|
||||
- login: gorhack
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4141690?u=ec119ebc4bdf00a7bc84657a71aa17834f4f27f3&v=4
|
||||
url: https://github.com/gorhack
|
||||
- login: mj0331
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3890353?u=1c627ac1a024515b4871de5c3ebbfaa1a57f65d4&v=4
|
||||
url: https://github.com/mj0331
|
||||
- login: anomaly
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3654837?v=4
|
||||
url: https://github.com/anomaly
|
||||
- login: aacayaco
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3634801?u=eaadda178c964178fcb64886f6c732172c8f8219&v=4
|
||||
url: https://github.com/aacayaco
|
||||
- login: kennywakeland
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3631417?u=7c8f743f1ae325dfadea7c62bbf1abd6a824fc55&v=4
|
||||
url: https://github.com/kennywakeland
|
||||
- login: zsinx6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3532625?u=ba75a5dc744d1116ccfeaaf30d41cb2fe81fe8dd&v=4
|
||||
url: https://github.com/zsinx6
|
||||
- login: dblackrun
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3528486?v=4
|
||||
url: https://github.com/dblackrun
|
||||
- login: knallgelb
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2358812?u=c48cb6362b309d74cbf144bd6ad3aed3eb443e82&v=4
|
||||
url: https://github.com/knallgelb
|
||||
- login: dodo5522
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1362607?u=9bf1e0e520cccc547c046610c468ce6115bbcf9f&v=4
|
||||
url: https://github.com/dodo5522
|
||||
- login: wdwinslow
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=371272f2c69e680e0559a7b0a57385e83a5dc728&v=4
|
||||
url: https://github.com/wdwinslow
|
||||
- login: jsoques
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/12414216?u=620921d94196546cc8b9eae2cc4cbc3f95bab42f&v=4
|
||||
url: https://github.com/jsoques
|
||||
- login: dannywade
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13680237?u=418ee985bd41577b20fde81417fb2d901e875e8a&v=4
|
||||
url: https://github.com/dannywade
|
||||
- login: khadrawy
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13686061?u=59f25ef42ecf04c22657aac4238ce0e2d3d30304&v=4
|
||||
url: https://github.com/khadrawy
|
||||
- login: mjohnsey
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16784016?u=38fad2e6b411244560b3af99c5f5a4751bc81865&v=4
|
||||
url: https://github.com/mjohnsey
|
||||
- login: ashi-agrawal
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/17105294?u=99c7a854035e5398d8e7b674f2d42baae6c957f8&v=4
|
||||
url: https://github.com/ashi-agrawal
|
||||
- login: mintuhouse
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/769950?u=ecfbd79a97d33177e0d093ddb088283cf7fe8444&v=4
|
||||
url: https://github.com/mintuhouse
|
||||
- login: falkben
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=ad9838e089058c9e5a0bab94c0eec7cc181e0cd0&v=4
|
||||
url: https://github.com/falkben
|
||||
- login: koxudaxi
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/630670?u=507d8577b4b3670546b449c4c2ccbc5af40d72f7&v=4
|
||||
url: https://github.com/koxudaxi
|
||||
- login: wshayes
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
|
||||
url: https://github.com/wshayes
|
||||
- login: pamelafox
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/297042?v=4
|
||||
url: https://github.com/pamelafox
|
||||
- login: robintw
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/296686?v=4
|
||||
url: https://github.com/robintw
|
||||
- login: jstanden
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/63288?u=c3658d57d2862c607a0e19c2101c3c51876e36ad&v=4
|
||||
url: https://github.com/jstanden
|
||||
- login: RaamEEIL
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/20320552?v=4
|
||||
url: https://github.com/RaamEEIL
|
||||
- login: ternaus
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5481618?u=513a26b02a39e7a28d587cd37c6cc877ea368e6e&v=4
|
||||
url: https://github.com/ternaus
|
||||
- login: eseglem
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5920492?u=208d419cf667b8ac594c82a8db01932c7e50d057&v=4
|
||||
url: https://github.com/eseglem
|
||||
- login: FernandoCelmer
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6262214?u=58ba6d5888fa7f355934e52db19f950e20b38162&v=4
|
||||
url: https://github.com/FernandoCelmer
|
||||
- login: Rehket
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7015688?u=3afb0ba200feebbc7f958950e92db34df2a3c172&v=4
|
||||
url: https://github.com/Rehket
|
||||
- login: ashi-agrawal
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/17105294?u=99c7a854035e5398d8e7b674f2d42baae6c957f8&v=4
|
||||
url: https://github.com/ashi-agrawal
|
||||
- login: mjohnsey
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16784016?u=38fad2e6b411244560b3af99c5f5a4751bc81865&v=4
|
||||
url: https://github.com/mjohnsey
|
||||
- login: khadrawy
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13686061?u=59f25ef42ecf04c22657aac4238ce0e2d3d30304&v=4
|
||||
url: https://github.com/khadrawy
|
||||
- login: dannywade
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13680237?u=418ee985bd41577b20fde81417fb2d901e875e8a&v=4
|
||||
url: https://github.com/dannywade
|
||||
- login: jsoques
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/12414216?u=620921d94196546cc8b9eae2cc4cbc3f95bab42f&v=4
|
||||
url: https://github.com/jsoques
|
||||
- login: wdwinslow
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=371272f2c69e680e0559a7b0a57385e83a5dc728&v=4
|
||||
url: https://github.com/wdwinslow
|
||||
- login: hiancdtrsnm
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7343177?v=4
|
||||
url: https://github.com/hiancdtrsnm
|
||||
- - login: manoelpqueiroz
|
||||
- login: Rehket
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7015688?u=3afb0ba200feebbc7f958950e92db34df2a3c172&v=4
|
||||
url: https://github.com/Rehket
|
||||
- login: FernandoCelmer
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6262214?u=58ba6d5888fa7f355934e52db19f950e20b38162&v=4
|
||||
url: https://github.com/FernandoCelmer
|
||||
- login: eseglem
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5920492?u=208d419cf667b8ac594c82a8db01932c7e50d057&v=4
|
||||
url: https://github.com/eseglem
|
||||
- login: ternaus
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5481618?u=513a26b02a39e7a28d587cd37c6cc877ea368e6e&v=4
|
||||
url: https://github.com/ternaus
|
||||
- - login: Artur-Galstyan
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/63471891?u=e8691f386037e51a737cc0ba866cd8c89e5cf109&v=4
|
||||
url: https://github.com/Artur-Galstyan
|
||||
- login: manoelpqueiroz
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/23669137?u=b12e84b28a84369ab5b30bd5a79e5788df5a0756&v=4
|
||||
url: https://github.com/manoelpqueiroz
|
||||
- - login: pawamoy
|
||||
@@ -254,9 +251,12 @@ sponsors:
|
||||
- login: hgalytoby
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=6cc9028f3db63f8f60ad21c17b1ce4b88c4e2e60&v=4
|
||||
url: https://github.com/hgalytoby
|
||||
- login: nisutec
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25281462?u=e562484c451fdfc59053163f64405f8eb262b8b0&v=4
|
||||
url: https://github.com/nisutec
|
||||
- login: johnl28
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/54412955?u=47dd06082d1c39caa90c752eb55566e4f3813957&v=4
|
||||
url: https://github.com/johnl28
|
||||
- login: danielunderwood
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4
|
||||
url: https://github.com/danielunderwood
|
||||
- login: hoenie-ams
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25708487?u=cda07434f0509ac728d9edf5e681117c0f6b818b&v=4
|
||||
url: https://github.com/hoenie-ams
|
||||
@@ -267,93 +267,87 @@ sponsors:
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/33275230?u=eb223cad27017bb1e936ee9b429b450d092d0236&v=4
|
||||
url: https://github.com/engineerjoe440
|
||||
- login: bnkc
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/34930566?u=db5e6f4f87836cad26c2aa90ce390ce49041c5a9&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/34930566?u=4771ac4e64066f0847d40e5b29910adabd9b2372&v=4
|
||||
url: https://github.com/bnkc
|
||||
- login: petercool
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37613029?u=75aa8c6729e6e8f85a300561c4dbeef9d65c8797&v=4
|
||||
url: https://github.com/petercool
|
||||
- login: johnl28
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/54412955?u=47dd06082d1c39caa90c752eb55566e4f3813957&v=4
|
||||
url: https://github.com/johnl28
|
||||
- login: PunRabbit
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/70463212?u=1a835cfbc99295a60c8282f6aa6199d1b42241a5&v=4
|
||||
url: https://github.com/PunRabbit
|
||||
- login: PelicanQ
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/77930606?v=4
|
||||
url: https://github.com/PelicanQ
|
||||
- login: WillHogan
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=8a80356e3e7d5a417157aba7ea565dabc8678327&v=4
|
||||
url: https://github.com/WillHogan
|
||||
- login: PunRabbit
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/70463212?u=1a835cfbc99295a60c8282f6aa6199d1b42241a5&v=4
|
||||
url: https://github.com/PunRabbit
|
||||
- login: my3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1825270?v=4
|
||||
url: https://github.com/my3
|
||||
- login: danielunderwood
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4
|
||||
url: https://github.com/danielunderwood
|
||||
- login: ddanier
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/113563?u=ed1dc79de72f93bd78581f88ebc6952b62f472da&v=4
|
||||
url: https://github.com/ddanier
|
||||
- login: bryanculbertson
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/144028?u=defda4f90e93429221cc667500944abde60ebe4a&v=4
|
||||
url: https://github.com/bryanculbertson
|
||||
- login: slafs
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4
|
||||
url: https://github.com/slafs
|
||||
- login: ceb10n
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4
|
||||
url: https://github.com/ceb10n
|
||||
- login: tochikuji
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/851759?v=4
|
||||
url: https://github.com/tochikuji
|
||||
- login: WillHogan
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=8a80356e3e7d5a417157aba7ea565dabc8678327&v=4
|
||||
url: https://github.com/WillHogan
|
||||
- login: miguelgr
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1484589?u=54556072b8136efa12ae3b6902032ea2a39ace4b&v=4
|
||||
url: https://github.com/miguelgr
|
||||
- login: xncbf
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=a80a7bb349555b277645632ed66639ff43400614&v=4
|
||||
url: https://github.com/xncbf
|
||||
- login: DMantis
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9536869?u=652dd0d49717803c0cbcbf44f7740e53cf2d4892&v=4
|
||||
url: https://github.com/DMantis
|
||||
- login: hard-coders
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4
|
||||
url: https://github.com/hard-coders
|
||||
- login: mntolia
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10390224?v=4
|
||||
url: https://github.com/mntolia
|
||||
- login: Zuzah
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10934846?u=1ef43e075ddc87bd1178372bf4d95ee6175cae27&v=4
|
||||
url: https://github.com/Zuzah
|
||||
- login: TheR1D
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16740832?u=b0dfdbdb27b79729430c71c6128962f77b7b53f7&v=4
|
||||
url: https://github.com/TheR1D
|
||||
- login: tochikuji
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/851759?v=4
|
||||
url: https://github.com/tochikuji
|
||||
- login: ceb10n
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4
|
||||
url: https://github.com/ceb10n
|
||||
- login: slafs
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4
|
||||
url: https://github.com/slafs
|
||||
- login: bryanculbertson
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/144028?u=defda4f90e93429221cc667500944abde60ebe4a&v=4
|
||||
url: https://github.com/bryanculbertson
|
||||
- login: ddanier
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/113563?u=ed1dc79de72f93bd78581f88ebc6952b62f472da&v=4
|
||||
url: https://github.com/ddanier
|
||||
- login: nisutec
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25281462?u=e562484c451fdfc59053163f64405f8eb262b8b0&v=4
|
||||
url: https://github.com/nisutec
|
||||
- login: joshuatz
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/17817563?u=f1bf05b690d1fc164218f0b420cdd3acb7913e21&v=4
|
||||
url: https://github.com/joshuatz
|
||||
- login: rangulvers
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5235430?u=e254d4af4ace5a05fa58372ae677c7d26f0d5a53&v=4
|
||||
url: https://github.com/rangulvers
|
||||
- login: sdevkota
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5250987?u=4ed9a120c89805a8aefda1cbdc0cf6512e64d1b4&v=4
|
||||
url: https://github.com/sdevkota
|
||||
- login: Baghdady92
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5708590?v=4
|
||||
url: https://github.com/Baghdady92
|
||||
- login: KentShikama
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6329898?u=8b236810db9b96333230430837e1f021f9246da1&v=4
|
||||
url: https://github.com/KentShikama
|
||||
- login: katnoria
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7674948?u=09767eb13e07e09496c5fee4e5ce21d9eac34a56&v=4
|
||||
url: https://github.com/katnoria
|
||||
- login: harsh183
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7780198?v=4
|
||||
url: https://github.com/harsh183
|
||||
- login: TheR1D
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16740832?u=b0dfdbdb27b79729430c71c6128962f77b7b53f7&v=4
|
||||
url: https://github.com/TheR1D
|
||||
- login: Zuzah
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10934846?u=1ef43e075ddc87bd1178372bf4d95ee6175cae27&v=4
|
||||
url: https://github.com/Zuzah
|
||||
- login: mntolia
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10390224?v=4
|
||||
url: https://github.com/mntolia
|
||||
- login: hard-coders
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=78d12d1acdf853c817700145e73de7fd9e5d068b&v=4
|
||||
url: https://github.com/hard-coders
|
||||
- login: DMantis
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9536869?u=652dd0d49717803c0cbcbf44f7740e53cf2d4892&v=4
|
||||
url: https://github.com/DMantis
|
||||
- login: xncbf
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=a80a7bb349555b277645632ed66639ff43400614&v=4
|
||||
url: https://github.com/xncbf
|
||||
- login: moonape1226
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4
|
||||
url: https://github.com/moonape1226
|
||||
- - login: andrecorumba
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37807517?u=9b9be3b41da9bda60957da9ef37b50dbf65baa61&v=4
|
||||
url: https://github.com/andrecorumba
|
||||
- login: KOZ39
|
||||
- login: harsh183
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7780198?v=4
|
||||
url: https://github.com/harsh183
|
||||
- login: katnoria
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7674948?u=09767eb13e07e09496c5fee4e5ce21d9eac34a56&v=4
|
||||
url: https://github.com/katnoria
|
||||
- login: KentShikama
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6329898?u=8b236810db9b96333230430837e1f021f9246da1&v=4
|
||||
url: https://github.com/KentShikama
|
||||
- login: Baghdady92
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5708590?v=4
|
||||
url: https://github.com/Baghdady92
|
||||
- login: sdevkota
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5250987?u=4ed9a120c89805a8aefda1cbdc0cf6512e64d1b4&v=4
|
||||
url: https://github.com/sdevkota
|
||||
- login: rangulvers
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5235430?u=e254d4af4ace5a05fa58372ae677c7d26f0d5a53&v=4
|
||||
url: https://github.com/rangulvers
|
||||
- - login: KOZ39
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/38822500?u=9dfc0a697df1c9628f08e20dc3fb17b1afc4e5a7&v=4
|
||||
url: https://github.com/KOZ39
|
||||
- login: rwxd
|
||||
@@ -365,27 +359,24 @@ sponsors:
|
||||
- login: Olegt0rr
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25399456?u=3e87b5239a2f4600975ba13be73054f8567c6060&v=4
|
||||
url: https://github.com/Olegt0rr
|
||||
- login: dinoz0rg
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32940067?u=739cda1eb123a2dd5e1db45c361396f239e23f8b&v=4
|
||||
url: https://github.com/dinoz0rg
|
||||
- login: larsyngvelundin
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/34173819?u=74958599695bf83ac9f1addd935a51548a10c6b0&v=4
|
||||
url: https://github.com/larsyngvelundin
|
||||
- login: hippoley
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/135493401?u=1164ef48a645a7c12664fabc1638fbb7e1c459b0&v=4
|
||||
url: https://github.com/hippoley
|
||||
- login: 4anklee
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/144109238?u=a79c0d581b2a3d8f3897e7ef4c012640a6c1eb3a&v=4
|
||||
url: https://github.com/4anklee
|
||||
- login: andrecorumba
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37807517?u=9b9be3b41da9bda60957da9ef37b50dbf65baa61&v=4
|
||||
url: https://github.com/andrecorumba
|
||||
- login: CoderDeltaLAN
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/152043745?u=4ff541efffb7d134e60c5fcf2dd1e343f90bb782&v=4
|
||||
url: https://github.com/CoderDeltaLAN
|
||||
- login: onestn
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62360849?u=746dd21c34e7e06eefb11b03e8bb01aaae3c2a4f&v=4
|
||||
url: https://github.com/onestn
|
||||
- login: hippoley
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/135493401?u=1164ef48a645a7c12664fabc1638fbb7e1c459b0&v=4
|
||||
url: https://github.com/hippoley
|
||||
- login: nayasinghania
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/74111380?u=752e99a5e139389fdc0a0677122adc08438eb076&v=4
|
||||
url: https://github.com/nayasinghania
|
||||
- login: onestn
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62360849?u=746dd21c34e7e06eefb11b03e8bb01aaae3c2a4f&v=4
|
||||
url: https://github.com/onestn
|
||||
- login: Toothwitch
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1710406?u=5eebb23b46cd26e48643b9e5179536cad491c17a&v=4
|
||||
url: https://github.com/Toothwitch
|
||||
|
||||
@@ -1,495 +1,495 @@
|
||||
- name: full-stack-fastapi-template
|
||||
html_url: https://github.com/fastapi/full-stack-fastapi-template
|
||||
stars: 39475
|
||||
stars: 40334
|
||||
owner_login: fastapi
|
||||
owner_html_url: https://github.com/fastapi
|
||||
- name: Hello-Python
|
||||
html_url: https://github.com/mouredev/Hello-Python
|
||||
stars: 33090
|
||||
stars: 33628
|
||||
owner_login: mouredev
|
||||
owner_html_url: https://github.com/mouredev
|
||||
- name: serve
|
||||
html_url: https://github.com/jina-ai/serve
|
||||
stars: 21798
|
||||
stars: 21817
|
||||
owner_login: jina-ai
|
||||
owner_html_url: https://github.com/jina-ai
|
||||
- name: HivisionIDPhotos
|
||||
html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos
|
||||
stars: 20258
|
||||
stars: 20409
|
||||
owner_login: Zeyi-Lin
|
||||
owner_html_url: https://github.com/Zeyi-Lin
|
||||
- name: sqlmodel
|
||||
html_url: https://github.com/fastapi/sqlmodel
|
||||
stars: 17212
|
||||
stars: 17415
|
||||
owner_login: fastapi
|
||||
owner_html_url: https://github.com/fastapi
|
||||
- name: Douyin_TikTok_Download_API
|
||||
html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API
|
||||
stars: 15145
|
||||
owner_login: Evil0ctal
|
||||
owner_html_url: https://github.com/Evil0ctal
|
||||
- name: fastapi-best-practices
|
||||
html_url: https://github.com/zhanymkanov/fastapi-best-practices
|
||||
stars: 14644
|
||||
stars: 15776
|
||||
owner_login: zhanymkanov
|
||||
owner_html_url: https://github.com/zhanymkanov
|
||||
- name: Douyin_TikTok_Download_API
|
||||
html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API
|
||||
stars: 15588
|
||||
owner_login: Evil0ctal
|
||||
owner_html_url: https://github.com/Evil0ctal
|
||||
- name: machine-learning-zoomcamp
|
||||
html_url: https://github.com/DataTalksClub/machine-learning-zoomcamp
|
||||
stars: 12320
|
||||
stars: 12447
|
||||
owner_login: DataTalksClub
|
||||
owner_html_url: https://github.com/DataTalksClub
|
||||
- name: fastapi_mcp
|
||||
html_url: https://github.com/tadata-org/fastapi_mcp
|
||||
stars: 11174
|
||||
owner_login: tadata-org
|
||||
owner_html_url: https://github.com/tadata-org
|
||||
- name: SurfSense
|
||||
html_url: https://github.com/MODSetter/SurfSense
|
||||
stars: 10858
|
||||
stars: 12128
|
||||
owner_login: MODSetter
|
||||
owner_html_url: https://github.com/MODSetter
|
||||
- name: fastapi_mcp
|
||||
html_url: https://github.com/tadata-org/fastapi_mcp
|
||||
stars: 11326
|
||||
owner_login: tadata-org
|
||||
owner_html_url: https://github.com/tadata-org
|
||||
- name: awesome-fastapi
|
||||
html_url: https://github.com/mjhea0/awesome-fastapi
|
||||
stars: 10758
|
||||
stars: 10901
|
||||
owner_login: mjhea0
|
||||
owner_html_url: https://github.com/mjhea0
|
||||
- name: XHS-Downloader
|
||||
html_url: https://github.com/JoeanAmier/XHS-Downloader
|
||||
stars: 9313
|
||||
stars: 9584
|
||||
owner_login: JoeanAmier
|
||||
owner_html_url: https://github.com/JoeanAmier
|
||||
- name: FastUI
|
||||
html_url: https://github.com/pydantic/FastUI
|
||||
stars: 8915
|
||||
owner_login: pydantic
|
||||
owner_html_url: https://github.com/pydantic
|
||||
- name: polar
|
||||
html_url: https://github.com/polarsource/polar
|
||||
stars: 8339
|
||||
stars: 8951
|
||||
owner_login: polarsource
|
||||
owner_html_url: https://github.com/polarsource
|
||||
- name: FastUI
|
||||
html_url: https://github.com/pydantic/FastUI
|
||||
stars: 8934
|
||||
owner_login: pydantic
|
||||
owner_html_url: https://github.com/pydantic
|
||||
- name: FileCodeBox
|
||||
html_url: https://github.com/vastsa/FileCodeBox
|
||||
stars: 7721
|
||||
stars: 7934
|
||||
owner_login: vastsa
|
||||
owner_html_url: https://github.com/vastsa
|
||||
- name: nonebot2
|
||||
html_url: https://github.com/nonebot/nonebot2
|
||||
stars: 7170
|
||||
stars: 7248
|
||||
owner_login: nonebot
|
||||
owner_html_url: https://github.com/nonebot
|
||||
- name: hatchet
|
||||
html_url: https://github.com/hatchet-dev/hatchet
|
||||
stars: 6253
|
||||
stars: 6392
|
||||
owner_login: hatchet-dev
|
||||
owner_html_url: https://github.com/hatchet-dev
|
||||
- name: fastapi-users
|
||||
html_url: https://github.com/fastapi-users/fastapi-users
|
||||
stars: 5849
|
||||
stars: 5899
|
||||
owner_login: fastapi-users
|
||||
owner_html_url: https://github.com/fastapi-users
|
||||
- name: serge
|
||||
html_url: https://github.com/serge-chat/serge
|
||||
stars: 5756
|
||||
stars: 5754
|
||||
owner_login: serge-chat
|
||||
owner_html_url: https://github.com/serge-chat
|
||||
- name: strawberry
|
||||
html_url: https://github.com/strawberry-graphql/strawberry
|
||||
stars: 4569
|
||||
stars: 4577
|
||||
owner_login: strawberry-graphql
|
||||
owner_html_url: https://github.com/strawberry-graphql
|
||||
- name: chatgpt-web-share
|
||||
html_url: https://github.com/chatpire/chatgpt-web-share
|
||||
stars: 4294
|
||||
owner_login: chatpire
|
||||
owner_html_url: https://github.com/chatpire
|
||||
- name: poem
|
||||
html_url: https://github.com/poem-web/poem
|
||||
stars: 4276
|
||||
stars: 4303
|
||||
owner_login: poem-web
|
||||
owner_html_url: https://github.com/poem-web
|
||||
- name: chatgpt-web-share
|
||||
html_url: https://github.com/chatpire/chatgpt-web-share
|
||||
stars: 4287
|
||||
owner_login: chatpire
|
||||
owner_html_url: https://github.com/chatpire
|
||||
- name: dynaconf
|
||||
html_url: https://github.com/dynaconf/dynaconf
|
||||
stars: 4202
|
||||
stars: 4221
|
||||
owner_login: dynaconf
|
||||
owner_html_url: https://github.com/dynaconf
|
||||
- name: atrilabs-engine
|
||||
html_url: https://github.com/Atri-Labs/atrilabs-engine
|
||||
stars: 4093
|
||||
owner_login: Atri-Labs
|
||||
owner_html_url: https://github.com/Atri-Labs
|
||||
- name: Kokoro-FastAPI
|
||||
html_url: https://github.com/remsky/Kokoro-FastAPI
|
||||
stars: 4019
|
||||
stars: 4181
|
||||
owner_login: remsky
|
||||
owner_html_url: https://github.com/remsky
|
||||
- name: atrilabs-engine
|
||||
html_url: https://github.com/Atri-Labs/atrilabs-engine
|
||||
stars: 4090
|
||||
owner_login: Atri-Labs
|
||||
owner_html_url: https://github.com/Atri-Labs
|
||||
- name: devpush
|
||||
html_url: https://github.com/hunvreus/devpush
|
||||
stars: 4037
|
||||
owner_login: hunvreus
|
||||
owner_html_url: https://github.com/hunvreus
|
||||
- name: logfire
|
||||
html_url: https://github.com/pydantic/logfire
|
||||
stars: 3805
|
||||
stars: 3896
|
||||
owner_login: pydantic
|
||||
owner_html_url: https://github.com/pydantic
|
||||
- name: LitServe
|
||||
html_url: https://github.com/Lightning-AI/LitServe
|
||||
stars: 3719
|
||||
stars: 3756
|
||||
owner_login: Lightning-AI
|
||||
owner_html_url: https://github.com/Lightning-AI
|
||||
- name: fastapi-admin
|
||||
html_url: https://github.com/fastapi-admin/fastapi-admin
|
||||
stars: 3632
|
||||
owner_login: fastapi-admin
|
||||
owner_html_url: https://github.com/fastapi-admin
|
||||
- name: datamodel-code-generator
|
||||
html_url: https://github.com/koxudaxi/datamodel-code-generator
|
||||
stars: 3609
|
||||
owner_login: koxudaxi
|
||||
owner_html_url: https://github.com/koxudaxi
|
||||
- name: huma
|
||||
html_url: https://github.com/danielgtaylor/huma
|
||||
stars: 3603
|
||||
stars: 3702
|
||||
owner_login: danielgtaylor
|
||||
owner_html_url: https://github.com/danielgtaylor
|
||||
- name: Yuxi-Know
|
||||
html_url: https://github.com/xerrors/Yuxi-Know
|
||||
stars: 3680
|
||||
owner_login: xerrors
|
||||
owner_html_url: https://github.com/xerrors
|
||||
- name: datamodel-code-generator
|
||||
html_url: https://github.com/koxudaxi/datamodel-code-generator
|
||||
stars: 3675
|
||||
owner_login: koxudaxi
|
||||
owner_html_url: https://github.com/koxudaxi
|
||||
- name: fastapi-admin
|
||||
html_url: https://github.com/fastapi-admin/fastapi-admin
|
||||
stars: 3659
|
||||
owner_login: fastapi-admin
|
||||
owner_html_url: https://github.com/fastapi-admin
|
||||
- name: farfalle
|
||||
html_url: https://github.com/rashadphz/farfalle
|
||||
stars: 3490
|
||||
stars: 3497
|
||||
owner_login: rashadphz
|
||||
owner_html_url: https://github.com/rashadphz
|
||||
- name: tracecat
|
||||
html_url: https://github.com/TracecatHQ/tracecat
|
||||
stars: 3379
|
||||
stars: 3421
|
||||
owner_login: TracecatHQ
|
||||
owner_html_url: https://github.com/TracecatHQ
|
||||
- name: opyrator
|
||||
html_url: https://github.com/ml-tooling/opyrator
|
||||
stars: 3135
|
||||
stars: 3136
|
||||
owner_login: ml-tooling
|
||||
owner_html_url: https://github.com/ml-tooling
|
||||
- name: docarray
|
||||
html_url: https://github.com/docarray/docarray
|
||||
stars: 3114
|
||||
stars: 3111
|
||||
owner_login: docarray
|
||||
owner_html_url: https://github.com/docarray
|
||||
- name: devpush
|
||||
html_url: https://github.com/hunvreus/devpush
|
||||
stars: 3097
|
||||
owner_login: hunvreus
|
||||
owner_html_url: https://github.com/hunvreus
|
||||
- name: fastapi-realworld-example-app
|
||||
html_url: https://github.com/nsidnev/fastapi-realworld-example-app
|
||||
stars: 3050
|
||||
stars: 3051
|
||||
owner_login: nsidnev
|
||||
owner_html_url: https://github.com/nsidnev
|
||||
- name: uvicorn-gunicorn-fastapi-docker
|
||||
html_url: https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker
|
||||
stars: 2911
|
||||
owner_login: tiangolo
|
||||
owner_html_url: https://github.com/tiangolo
|
||||
- name: mcp-context-forge
|
||||
html_url: https://github.com/IBM/mcp-context-forge
|
||||
stars: 2899
|
||||
stars: 3034
|
||||
owner_login: IBM
|
||||
owner_html_url: https://github.com/IBM
|
||||
- name: best-of-web-python
|
||||
html_url: https://github.com/ml-tooling/best-of-web-python
|
||||
stars: 2648
|
||||
owner_login: ml-tooling
|
||||
owner_html_url: https://github.com/ml-tooling
|
||||
- name: uvicorn-gunicorn-fastapi-docker
|
||||
html_url: https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker
|
||||
stars: 2904
|
||||
owner_login: tiangolo
|
||||
owner_html_url: https://github.com/tiangolo
|
||||
- name: FastAPI-template
|
||||
html_url: https://github.com/s3rius/FastAPI-template
|
||||
stars: 2637
|
||||
stars: 2680
|
||||
owner_login: s3rius
|
||||
owner_html_url: https://github.com/s3rius
|
||||
- name: best-of-web-python
|
||||
html_url: https://github.com/ml-tooling/best-of-web-python
|
||||
stars: 2662
|
||||
owner_login: ml-tooling
|
||||
owner_html_url: https://github.com/ml-tooling
|
||||
- name: YC-Killer
|
||||
html_url: https://github.com/sahibzada-allahyar/YC-Killer
|
||||
stars: 2599
|
||||
stars: 2614
|
||||
owner_login: sahibzada-allahyar
|
||||
owner_html_url: https://github.com/sahibzada-allahyar
|
||||
- name: fastapi-react
|
||||
html_url: https://github.com/Buuntu/fastapi-react
|
||||
stars: 2569
|
||||
owner_login: Buuntu
|
||||
owner_html_url: https://github.com/Buuntu
|
||||
- name: Yuxi-Know
|
||||
html_url: https://github.com/xerrors/Yuxi-Know
|
||||
stars: 2563
|
||||
owner_login: xerrors
|
||||
owner_html_url: https://github.com/xerrors
|
||||
- name: sqladmin
|
||||
html_url: https://github.com/aminalaee/sqladmin
|
||||
stars: 2558
|
||||
stars: 2587
|
||||
owner_login: aminalaee
|
||||
owner_html_url: https://github.com/aminalaee
|
||||
- name: fastapi-react
|
||||
html_url: https://github.com/Buuntu/fastapi-react
|
||||
stars: 2566
|
||||
owner_login: Buuntu
|
||||
owner_html_url: https://github.com/Buuntu
|
||||
- name: RasaGPT
|
||||
html_url: https://github.com/paulpierre/RasaGPT
|
||||
stars: 2451
|
||||
stars: 2456
|
||||
owner_login: paulpierre
|
||||
owner_html_url: https://github.com/paulpierre
|
||||
- name: supabase-py
|
||||
html_url: https://github.com/supabase/supabase-py
|
||||
stars: 2344
|
||||
stars: 2394
|
||||
owner_login: supabase
|
||||
owner_html_url: https://github.com/supabase
|
||||
- name: nextpy
|
||||
html_url: https://github.com/dot-agent/nextpy
|
||||
stars: 2335
|
||||
stars: 2338
|
||||
owner_login: dot-agent
|
||||
owner_html_url: https://github.com/dot-agent
|
||||
- name: fastapi-utils
|
||||
html_url: https://github.com/fastapiutils/fastapi-utils
|
||||
stars: 2291
|
||||
stars: 2289
|
||||
owner_login: fastapiutils
|
||||
owner_html_url: https://github.com/fastapiutils
|
||||
- name: 30-Days-of-Python
|
||||
html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python
|
||||
stars: 2220
|
||||
owner_login: codingforentrepreneurs
|
||||
owner_html_url: https://github.com/codingforentrepreneurs
|
||||
- name: langserve
|
||||
html_url: https://github.com/langchain-ai/langserve
|
||||
stars: 2215
|
||||
stars: 2234
|
||||
owner_login: langchain-ai
|
||||
owner_html_url: https://github.com/langchain-ai
|
||||
- name: 30-Days-of-Python
|
||||
html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python
|
||||
stars: 2232
|
||||
owner_login: codingforentrepreneurs
|
||||
owner_html_url: https://github.com/codingforentrepreneurs
|
||||
- name: solara
|
||||
html_url: https://github.com/widgetti/solara
|
||||
stars: 2122
|
||||
stars: 2141
|
||||
owner_login: widgetti
|
||||
owner_html_url: https://github.com/widgetti
|
||||
- name: mangum
|
||||
html_url: https://github.com/Kludex/mangum
|
||||
stars: 2029
|
||||
stars: 2046
|
||||
owner_login: Kludex
|
||||
owner_html_url: https://github.com/Kludex
|
||||
- name: fastapi_best_architecture
|
||||
html_url: https://github.com/fastapi-practices/fastapi_best_architecture
|
||||
stars: 1963
|
||||
owner_login: fastapi-practices
|
||||
owner_html_url: https://github.com/fastapi-practices
|
||||
- name: NoteDiscovery
|
||||
html_url: https://github.com/gamosoft/NoteDiscovery
|
||||
stars: 1943
|
||||
owner_login: gamosoft
|
||||
owner_html_url: https://github.com/gamosoft
|
||||
- name: agentkit
|
||||
html_url: https://github.com/BCG-X-Official/agentkit
|
||||
stars: 1912
|
||||
stars: 1936
|
||||
owner_login: BCG-X-Official
|
||||
owner_html_url: https://github.com/BCG-X-Official
|
||||
- name: vue-fastapi-admin
|
||||
html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin
|
||||
stars: 1909
|
||||
owner_login: mizhexiaoxiao
|
||||
owner_html_url: https://github.com/mizhexiaoxiao
|
||||
- name: manage-fastapi
|
||||
html_url: https://github.com/ycd/manage-fastapi
|
||||
stars: 1885
|
||||
stars: 1887
|
||||
owner_login: ycd
|
||||
owner_html_url: https://github.com/ycd
|
||||
- name: openapi-python-client
|
||||
html_url: https://github.com/openapi-generators/openapi-python-client
|
||||
stars: 1862
|
||||
stars: 1879
|
||||
owner_login: openapi-generators
|
||||
owner_html_url: https://github.com/openapi-generators
|
||||
- name: piccolo
|
||||
html_url: https://github.com/piccolo-orm/piccolo
|
||||
stars: 1836
|
||||
owner_login: piccolo-orm
|
||||
owner_html_url: https://github.com/piccolo-orm
|
||||
- name: vue-fastapi-admin
|
||||
html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin
|
||||
stars: 1831
|
||||
owner_login: mizhexiaoxiao
|
||||
owner_html_url: https://github.com/mizhexiaoxiao
|
||||
- name: python-week-2022
|
||||
html_url: https://github.com/rochacbruno/python-week-2022
|
||||
stars: 1817
|
||||
owner_login: rochacbruno
|
||||
owner_html_url: https://github.com/rochacbruno
|
||||
- name: slowapi
|
||||
html_url: https://github.com/laurentS/slowapi
|
||||
stars: 1798
|
||||
stars: 1845
|
||||
owner_login: laurentS
|
||||
owner_html_url: https://github.com/laurentS
|
||||
- name: piccolo
|
||||
html_url: https://github.com/piccolo-orm/piccolo
|
||||
stars: 1843
|
||||
owner_login: piccolo-orm
|
||||
owner_html_url: https://github.com/piccolo-orm
|
||||
- name: python-week-2022
|
||||
html_url: https://github.com/rochacbruno/python-week-2022
|
||||
stars: 1813
|
||||
owner_login: rochacbruno
|
||||
owner_html_url: https://github.com/rochacbruno
|
||||
- name: fastapi-cache
|
||||
html_url: https://github.com/long2ice/fastapi-cache
|
||||
stars: 1789
|
||||
stars: 1805
|
||||
owner_login: long2ice
|
||||
owner_html_url: https://github.com/long2ice
|
||||
- name: ormar
|
||||
html_url: https://github.com/collerek/ormar
|
||||
stars: 1783
|
||||
stars: 1785
|
||||
owner_login: collerek
|
||||
owner_html_url: https://github.com/collerek
|
||||
- name: termpair
|
||||
html_url: https://github.com/cs01/termpair
|
||||
stars: 1716
|
||||
owner_login: cs01
|
||||
owner_html_url: https://github.com/cs01
|
||||
- name: FastAPI-boilerplate
|
||||
html_url: https://github.com/benavlabs/FastAPI-boilerplate
|
||||
stars: 1660
|
||||
owner_login: benavlabs
|
||||
owner_html_url: https://github.com/benavlabs
|
||||
- name: fastapi-langgraph-agent-production-ready-template
|
||||
html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template
|
||||
stars: 1638
|
||||
stars: 1780
|
||||
owner_login: wassim249
|
||||
owner_html_url: https://github.com/wassim249
|
||||
- name: langchain-serve
|
||||
html_url: https://github.com/jina-ai/langchain-serve
|
||||
stars: 1635
|
||||
owner_login: jina-ai
|
||||
owner_html_url: https://github.com/jina-ai
|
||||
- name: awesome-fastapi-projects
|
||||
html_url: https://github.com/Kludex/awesome-fastapi-projects
|
||||
stars: 1589
|
||||
owner_login: Kludex
|
||||
owner_html_url: https://github.com/Kludex
|
||||
- name: fastapi-pagination
|
||||
html_url: https://github.com/uriyyo/fastapi-pagination
|
||||
stars: 1585
|
||||
owner_login: uriyyo
|
||||
owner_html_url: https://github.com/uriyyo
|
||||
- name: coronavirus-tracker-api
|
||||
html_url: https://github.com/ExpDev07/coronavirus-tracker-api
|
||||
stars: 1574
|
||||
owner_login: ExpDev07
|
||||
owner_html_url: https://github.com/ExpDev07
|
||||
- name: FastAPI-boilerplate
|
||||
html_url: https://github.com/benavlabs/FastAPI-boilerplate
|
||||
stars: 1734
|
||||
owner_login: benavlabs
|
||||
owner_html_url: https://github.com/benavlabs
|
||||
- name: termpair
|
||||
html_url: https://github.com/cs01/termpair
|
||||
stars: 1724
|
||||
owner_login: cs01
|
||||
owner_html_url: https://github.com/cs01
|
||||
- name: fastapi-crudrouter
|
||||
html_url: https://github.com/awtkns/fastapi-crudrouter
|
||||
stars: 1559
|
||||
stars: 1671
|
||||
owner_login: awtkns
|
||||
owner_html_url: https://github.com/awtkns
|
||||
- name: langchain-serve
|
||||
html_url: https://github.com/jina-ai/langchain-serve
|
||||
stars: 1633
|
||||
owner_login: jina-ai
|
||||
owner_html_url: https://github.com/jina-ai
|
||||
- name: fastapi-pagination
|
||||
html_url: https://github.com/uriyyo/fastapi-pagination
|
||||
stars: 1588
|
||||
owner_login: uriyyo
|
||||
owner_html_url: https://github.com/uriyyo
|
||||
- name: awesome-fastapi-projects
|
||||
html_url: https://github.com/Kludex/awesome-fastapi-projects
|
||||
stars: 1583
|
||||
owner_login: Kludex
|
||||
owner_html_url: https://github.com/Kludex
|
||||
- name: coronavirus-tracker-api
|
||||
html_url: https://github.com/ExpDev07/coronavirus-tracker-api
|
||||
stars: 1571
|
||||
owner_login: ExpDev07
|
||||
owner_html_url: https://github.com/ExpDev07
|
||||
- name: bracket
|
||||
html_url: https://github.com/evroon/bracket
|
||||
stars: 1489
|
||||
stars: 1549
|
||||
owner_login: evroon
|
||||
owner_html_url: https://github.com/evroon
|
||||
- name: fastapi-amis-admin
|
||||
html_url: https://github.com/amisadmin/fastapi-amis-admin
|
||||
stars: 1475
|
||||
stars: 1491
|
||||
owner_login: amisadmin
|
||||
owner_html_url: https://github.com/amisadmin
|
||||
- name: fastapi-boilerplate
|
||||
html_url: https://github.com/teamhide/fastapi-boilerplate
|
||||
stars: 1436
|
||||
stars: 1452
|
||||
owner_login: teamhide
|
||||
owner_html_url: https://github.com/teamhide
|
||||
- name: awesome-python-resources
|
||||
html_url: https://github.com/DjangoEx/awesome-python-resources
|
||||
stars: 1426
|
||||
owner_login: DjangoEx
|
||||
owner_html_url: https://github.com/DjangoEx
|
||||
- name: fastcrud
|
||||
html_url: https://github.com/benavlabs/fastcrud
|
||||
stars: 1414
|
||||
stars: 1452
|
||||
owner_login: benavlabs
|
||||
owner_html_url: https://github.com/benavlabs
|
||||
- name: awesome-python-resources
|
||||
html_url: https://github.com/DjangoEx/awesome-python-resources
|
||||
stars: 1430
|
||||
owner_login: DjangoEx
|
||||
owner_html_url: https://github.com/DjangoEx
|
||||
- name: prometheus-fastapi-instrumentator
|
||||
html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator
|
||||
stars: 1388
|
||||
stars: 1399
|
||||
owner_login: trallnag
|
||||
owner_html_url: https://github.com/trallnag
|
||||
- name: fastapi_best_architecture
|
||||
html_url: https://github.com/fastapi-practices/fastapi_best_architecture
|
||||
stars: 1378
|
||||
owner_login: fastapi-practices
|
||||
owner_html_url: https://github.com/fastapi-practices
|
||||
- name: fastapi-code-generator
|
||||
html_url: https://github.com/koxudaxi/fastapi-code-generator
|
||||
stars: 1375
|
||||
stars: 1371
|
||||
owner_login: koxudaxi
|
||||
owner_html_url: https://github.com/koxudaxi
|
||||
- name: fastapi-tutorial
|
||||
html_url: https://github.com/liaogx/fastapi-tutorial
|
||||
stars: 1346
|
||||
owner_login: liaogx
|
||||
owner_html_url: https://github.com/liaogx
|
||||
- name: budgetml
|
||||
html_url: https://github.com/ebhy/budgetml
|
||||
stars: 1345
|
||||
owner_login: ebhy
|
||||
owner_html_url: https://github.com/ebhy
|
||||
- name: fastapi-tutorial
|
||||
html_url: https://github.com/liaogx/fastapi-tutorial
|
||||
stars: 1327
|
||||
owner_login: liaogx
|
||||
owner_html_url: https://github.com/liaogx
|
||||
- name: fastapi-alembic-sqlmodel-async
|
||||
html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async
|
||||
stars: 1259
|
||||
owner_login: jonra1993
|
||||
owner_html_url: https://github.com/jonra1993
|
||||
- name: fastapi-scaff
|
||||
html_url: https://github.com/atpuxiner/fastapi-scaff
|
||||
stars: 1255
|
||||
stars: 1331
|
||||
owner_login: atpuxiner
|
||||
owner_html_url: https://github.com/atpuxiner
|
||||
- name: bedrock-chat
|
||||
html_url: https://github.com/aws-samples/bedrock-chat
|
||||
stars: 1254
|
||||
owner_login: aws-samples
|
||||
owner_html_url: https://github.com/aws-samples
|
||||
- name: bolt-python
|
||||
html_url: https://github.com/slackapi/bolt-python
|
||||
stars: 1253
|
||||
stars: 1266
|
||||
owner_login: slackapi
|
||||
owner_html_url: https://github.com/slackapi
|
||||
- name: bedrock-chat
|
||||
html_url: https://github.com/aws-samples/bedrock-chat
|
||||
stars: 1266
|
||||
owner_login: aws-samples
|
||||
owner_html_url: https://github.com/aws-samples
|
||||
- name: fastapi-alembic-sqlmodel-async
|
||||
html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async
|
||||
stars: 1260
|
||||
owner_login: jonra1993
|
||||
owner_html_url: https://github.com/jonra1993
|
||||
- name: fastapi_production_template
|
||||
html_url: https://github.com/zhanymkanov/fastapi_production_template
|
||||
stars: 1217
|
||||
stars: 1222
|
||||
owner_login: zhanymkanov
|
||||
owner_html_url: https://github.com/zhanymkanov
|
||||
- name: langchain-extract
|
||||
html_url: https://github.com/langchain-ai/langchain-extract
|
||||
stars: 1176
|
||||
stars: 1179
|
||||
owner_login: langchain-ai
|
||||
owner_html_url: https://github.com/langchain-ai
|
||||
- name: restish
|
||||
html_url: https://github.com/rest-sh/restish
|
||||
stars: 1140
|
||||
stars: 1152
|
||||
owner_login: rest-sh
|
||||
owner_html_url: https://github.com/rest-sh
|
||||
- name: odmantic
|
||||
html_url: https://github.com/art049/odmantic
|
||||
stars: 1138
|
||||
stars: 1143
|
||||
owner_login: art049
|
||||
owner_html_url: https://github.com/art049
|
||||
- name: authx
|
||||
html_url: https://github.com/yezz123/authx
|
||||
stars: 1119
|
||||
stars: 1128
|
||||
owner_login: yezz123
|
||||
owner_html_url: https://github.com/yezz123
|
||||
- name: NoteDiscovery
|
||||
html_url: https://github.com/gamosoft/NoteDiscovery
|
||||
stars: 1107
|
||||
owner_login: gamosoft
|
||||
owner_html_url: https://github.com/gamosoft
|
||||
- name: flock
|
||||
html_url: https://github.com/Onelevenvy/flock
|
||||
stars: 1055
|
||||
owner_login: Onelevenvy
|
||||
owner_html_url: https://github.com/Onelevenvy
|
||||
- name: fastapi-observability
|
||||
html_url: https://github.com/blueswen/fastapi-observability
|
||||
stars: 1038
|
||||
owner_login: blueswen
|
||||
owner_html_url: https://github.com/blueswen
|
||||
- name: SAG
|
||||
html_url: https://github.com/Zleap-AI/SAG
|
||||
stars: 1104
|
||||
owner_login: Zleap-AI
|
||||
owner_html_url: https://github.com/Zleap-AI
|
||||
- name: aktools
|
||||
html_url: https://github.com/akfamily/aktools
|
||||
stars: 1027
|
||||
stars: 1072
|
||||
owner_login: akfamily
|
||||
owner_html_url: https://github.com/akfamily
|
||||
- name: RuoYi-Vue3-FastAPI
|
||||
html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI
|
||||
stars: 1016
|
||||
stars: 1063
|
||||
owner_login: insistence
|
||||
owner_html_url: https://github.com/insistence
|
||||
- name: autollm
|
||||
html_url: https://github.com/viddexa/autollm
|
||||
stars: 1002
|
||||
owner_login: viddexa
|
||||
owner_html_url: https://github.com/viddexa
|
||||
- name: titiler
|
||||
html_url: https://github.com/developmentseed/titiler
|
||||
stars: 999
|
||||
owner_login: developmentseed
|
||||
owner_html_url: https://github.com/developmentseed
|
||||
- name: lanarky
|
||||
html_url: https://github.com/ajndkr/lanarky
|
||||
stars: 994
|
||||
owner_login: ajndkr
|
||||
owner_html_url: https://github.com/ajndkr
|
||||
- name: every-pdf
|
||||
html_url: https://github.com/DDULDDUCK/every-pdf
|
||||
stars: 985
|
||||
owner_login: DDULDDUCK
|
||||
owner_html_url: https://github.com/DDULDDUCK
|
||||
- name: flock
|
||||
html_url: https://github.com/Onelevenvy/flock
|
||||
stars: 1059
|
||||
owner_login: Onelevenvy
|
||||
owner_html_url: https://github.com/Onelevenvy
|
||||
- name: fastapi-observability
|
||||
html_url: https://github.com/blueswen/fastapi-observability
|
||||
stars: 1046
|
||||
owner_login: blueswen
|
||||
owner_html_url: https://github.com/blueswen
|
||||
- name: enterprise-deep-research
|
||||
html_url: https://github.com/SalesforceAIResearch/enterprise-deep-research
|
||||
stars: 973
|
||||
stars: 1019
|
||||
owner_login: SalesforceAIResearch
|
||||
owner_html_url: https://github.com/SalesforceAIResearch
|
||||
- name: fastapi-mail
|
||||
html_url: https://github.com/sabuhish/fastapi-mail
|
||||
stars: 964
|
||||
owner_login: sabuhish
|
||||
owner_html_url: https://github.com/sabuhish
|
||||
- name: titiler
|
||||
html_url: https://github.com/developmentseed/titiler
|
||||
stars: 1016
|
||||
owner_login: developmentseed
|
||||
owner_html_url: https://github.com/developmentseed
|
||||
- name: every-pdf
|
||||
html_url: https://github.com/DDULDDUCK/every-pdf
|
||||
stars: 1004
|
||||
owner_login: DDULDDUCK
|
||||
owner_html_url: https://github.com/DDULDDUCK
|
||||
- name: autollm
|
||||
html_url: https://github.com/viddexa/autollm
|
||||
stars: 1003
|
||||
owner_login: viddexa
|
||||
owner_html_url: https://github.com/viddexa
|
||||
- name: lanarky
|
||||
html_url: https://github.com/ajndkr/lanarky
|
||||
stars: 996
|
||||
owner_login: ajndkr
|
||||
owner_html_url: https://github.com/ajndkr
|
||||
|
||||
@@ -15,7 +15,7 @@ sodaMelon:
|
||||
url: https://github.com/sodaMelon
|
||||
ceb10n:
|
||||
login: ceb10n
|
||||
count: 116
|
||||
count: 117
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4
|
||||
url: https://github.com/ceb10n
|
||||
tokusumi:
|
||||
@@ -23,16 +23,16 @@ tokusumi:
|
||||
count: 104
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4
|
||||
url: https://github.com/tokusumi
|
||||
hard-coders:
|
||||
login: hard-coders
|
||||
count: 96
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=78d12d1acdf853c817700145e73de7fd9e5d068b&v=4
|
||||
url: https://github.com/hard-coders
|
||||
hasansezertasan:
|
||||
login: hasansezertasan
|
||||
count: 95
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13135006?u=99f0b0f0fc47e88e8abb337b4447357939ef93e7&v=4
|
||||
url: https://github.com/hasansezertasan
|
||||
hard-coders:
|
||||
login: hard-coders
|
||||
count: 93
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4
|
||||
url: https://github.com/hard-coders
|
||||
alv2017:
|
||||
login: alv2017
|
||||
count: 88
|
||||
@@ -40,7 +40,7 @@ alv2017:
|
||||
url: https://github.com/alv2017
|
||||
nazarepiedady:
|
||||
login: nazarepiedady
|
||||
count: 86
|
||||
count: 87
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31008635?u=f69ddc4ea8bda3bdfac7aa0e2ea38de282e6ee2d&v=4
|
||||
url: https://github.com/nazarepiedady
|
||||
AlertRED:
|
||||
@@ -48,6 +48,11 @@ AlertRED:
|
||||
count: 81
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/15695000?u=f5a4944c6df443030409c88da7d7fa0b7ead985c&v=4
|
||||
url: https://github.com/AlertRED
|
||||
tiangolo:
|
||||
login: tiangolo
|
||||
count: 73
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
|
||||
url: https://github.com/tiangolo
|
||||
Alexandrhub:
|
||||
login: Alexandrhub
|
||||
count: 68
|
||||
@@ -63,21 +68,16 @@ cassiobotaro:
|
||||
count: 62
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=a08022b191ddbd0a6159b2981d9d878b6d5bb71f&v=4
|
||||
url: https://github.com/cassiobotaro
|
||||
mattwang44:
|
||||
login: mattwang44
|
||||
count: 61
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/24987826?u=58e37fb3927b9124b458945ac4c97aa0f1062d85&v=4
|
||||
url: https://github.com/mattwang44
|
||||
nilslindemann:
|
||||
login: nilslindemann
|
||||
count: 59
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4
|
||||
url: https://github.com/nilslindemann
|
||||
mattwang44:
|
||||
login: mattwang44
|
||||
count: 59
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/24987826?u=58e37fb3927b9124b458945ac4c97aa0f1062d85&v=4
|
||||
url: https://github.com/mattwang44
|
||||
tiangolo:
|
||||
login: tiangolo
|
||||
count: 56
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
|
||||
url: https://github.com/tiangolo
|
||||
Laineyzhang55:
|
||||
login: Laineyzhang55
|
||||
count: 48
|
||||
@@ -88,6 +88,11 @@ Kludex:
|
||||
count: 47
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4
|
||||
url: https://github.com/Kludex
|
||||
YuriiMotov:
|
||||
login: YuriiMotov
|
||||
count: 46
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
|
||||
url: https://github.com/YuriiMotov
|
||||
komtaki:
|
||||
login: komtaki
|
||||
count: 45
|
||||
@@ -118,11 +123,6 @@ Winand:
|
||||
count: 40
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/53390?u=bb0e71a2fc3910a8e0ee66da67c33de40ea695f8&v=4
|
||||
url: https://github.com/Winand
|
||||
YuriiMotov:
|
||||
login: YuriiMotov
|
||||
count: 40
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
|
||||
url: https://github.com/YuriiMotov
|
||||
solomein-sv:
|
||||
login: solomein-sv
|
||||
count: 38
|
||||
@@ -138,6 +138,11 @@ alejsdev:
|
||||
count: 37
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=85ceac49fb87138aebe8d663912e359447329090&v=4
|
||||
url: https://github.com/alejsdev
|
||||
mezgoodle:
|
||||
login: mezgoodle
|
||||
count: 37
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41520940?u=4a9c765af688389d54296845d18b8f6cd6ddf09a&v=4
|
||||
url: https://github.com/mezgoodle
|
||||
stlucasgarcia:
|
||||
login: stlucasgarcia
|
||||
count: 36
|
||||
@@ -153,11 +158,6 @@ timothy-jeong:
|
||||
count: 36
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/53824764?u=db3d0cea2f5fab64d810113c5039a369699a2774&v=4
|
||||
url: https://github.com/timothy-jeong
|
||||
mezgoodle:
|
||||
login: mezgoodle
|
||||
count: 35
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41520940?u=4a9c765af688389d54296845d18b8f6cd6ddf09a&v=4
|
||||
url: https://github.com/mezgoodle
|
||||
rjNemo:
|
||||
login: rjNemo
|
||||
count: 34
|
||||
@@ -173,6 +173,11 @@ akarev0:
|
||||
count: 33
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/53393089?u=6e528bb4789d56af887ce6fe237bea4010885406&v=4
|
||||
url: https://github.com/akarev0
|
||||
Vincy1230:
|
||||
login: Vincy1230
|
||||
count: 33
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/81342412?u=ab5e256a4077a4a91f3f9cd2115ba80780454cbe&v=4
|
||||
url: https://github.com/Vincy1230
|
||||
romashevchenko:
|
||||
login: romashevchenko
|
||||
count: 32
|
||||
@@ -183,11 +188,6 @@ LorhanSohaky:
|
||||
count: 30
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16273730?u=095b66f243a2cd6a0aadba9a095009f8aaf18393&v=4
|
||||
url: https://github.com/LorhanSohaky
|
||||
Vincy1230:
|
||||
login: Vincy1230
|
||||
count: 30
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/81342412?u=ab5e256a4077a4a91f3f9cd2115ba80780454cbe&v=4
|
||||
url: https://github.com/Vincy1230
|
||||
black-redoc:
|
||||
login: black-redoc
|
||||
count: 29
|
||||
@@ -250,7 +250,7 @@ mycaule:
|
||||
url: https://github.com/mycaule
|
||||
Aruelius:
|
||||
login: Aruelius
|
||||
count: 24
|
||||
count: 25
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25380989?u=574f8cfcda3ea77a3f81884f6b26a97068e36a9d&v=4
|
||||
url: https://github.com/Aruelius
|
||||
wisderfin:
|
||||
@@ -263,6 +263,11 @@ OzgunCaglarArslan:
|
||||
count: 24
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/86166426?v=4
|
||||
url: https://github.com/OzgunCaglarArslan
|
||||
ycd:
|
||||
login: ycd
|
||||
count: 23
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=f1e7bae394a315da950912c92dc861a8eaf95d4c&v=4
|
||||
url: https://github.com/ycd
|
||||
sh0nk:
|
||||
login: sh0nk
|
||||
count: 23
|
||||
@@ -288,11 +293,6 @@ Attsun1031:
|
||||
count: 20
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1175560?v=4
|
||||
url: https://github.com/Attsun1031
|
||||
ycd:
|
||||
login: ycd
|
||||
count: 20
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=f1e7bae394a315da950912c92dc861a8eaf95d4c&v=4
|
||||
url: https://github.com/ycd
|
||||
delhi09:
|
||||
login: delhi09
|
||||
count: 20
|
||||
@@ -418,6 +418,11 @@ mattkoehne:
|
||||
count: 14
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/80362153?v=4
|
||||
url: https://github.com/mattkoehne
|
||||
maru0123-2004:
|
||||
login: maru0123-2004
|
||||
count: 14
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43961566?u=16ed8603a4d6a4665cb6c53a7aece6f31379b769&v=4
|
||||
url: https://github.com/maru0123-2004
|
||||
jovicon:
|
||||
login: jovicon
|
||||
count: 13
|
||||
@@ -443,6 +448,11 @@ impocode:
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/109408819?u=9cdfc5ccb31a2094c520f41b6087012fa9048982&v=4
|
||||
url: https://github.com/impocode
|
||||
waketzheng:
|
||||
login: waketzheng
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35413830?u=df19e4fd5bb928e7d086e053ef26a46aad23bf84&v=4
|
||||
url: https://github.com/waketzheng
|
||||
wesinalves:
|
||||
login: wesinalves
|
||||
count: 13
|
||||
@@ -538,21 +548,16 @@ Lufa1u:
|
||||
count: 11
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/112495876?u=087658920ed9e74311597bdd921d8d2de939d276&v=4
|
||||
url: https://github.com/Lufa1u
|
||||
waketzheng:
|
||||
login: waketzheng
|
||||
count: 11
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35413830?u=df19e4fd5bb928e7d086e053ef26a46aad23bf84&v=4
|
||||
url: https://github.com/waketzheng
|
||||
KNChiu:
|
||||
login: KNChiu
|
||||
count: 11
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/36751646?v=4
|
||||
url: https://github.com/KNChiu
|
||||
maru0123-2004:
|
||||
login: maru0123-2004
|
||||
Zhongheng-Cheng:
|
||||
login: Zhongheng-Cheng
|
||||
count: 11
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43961566?u=16ed8603a4d6a4665cb6c53a7aece6f31379b769&v=4
|
||||
url: https://github.com/maru0123-2004
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/95612344?u=a0f7730a3cc7486827965e01a119ad610bda4b0a&v=4
|
||||
url: https://github.com/Zhongheng-Cheng
|
||||
mariacamilagl:
|
||||
login: mariacamilagl
|
||||
count: 10
|
||||
@@ -608,16 +613,16 @@ nick-cjyx9:
|
||||
count: 10
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/119087246?u=7227a2de948c68fb8396d5beff1ee5b0e057c42e&v=4
|
||||
url: https://github.com/nick-cjyx9
|
||||
marcelomarkus:
|
||||
login: marcelomarkus
|
||||
count: 10
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/20115018?u=dda090ce9160ef0cd2ff69b1e5ea741283425cba&v=4
|
||||
url: https://github.com/marcelomarkus
|
||||
lucasbalieiro:
|
||||
login: lucasbalieiro
|
||||
count: 10
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37416577?u=dad91601ee4f40458d691774ec439aff308344d7&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37416577?u=d144221c34c08adac8b20e1833d776ffa1c4b1d0&v=4
|
||||
url: https://github.com/lucasbalieiro
|
||||
Zhongheng-Cheng:
|
||||
login: Zhongheng-Cheng
|
||||
count: 10
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/95612344?u=a0f7730a3cc7486827965e01a119ad610bda4b0a&v=4
|
||||
url: https://github.com/Zhongheng-Cheng
|
||||
RunningIkkyu:
|
||||
login: RunningIkkyu
|
||||
count: 9
|
||||
@@ -668,11 +673,6 @@ yodai-yodai:
|
||||
count: 9
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7031039?u=4f3593f5931892b931a745cfab846eff6e9332e7&v=4
|
||||
url: https://github.com/yodai-yodai
|
||||
marcelomarkus:
|
||||
login: marcelomarkus
|
||||
count: 9
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/20115018?u=dda090ce9160ef0cd2ff69b1e5ea741283425cba&v=4
|
||||
url: https://github.com/marcelomarkus
|
||||
JoaoGustavoRogel:
|
||||
login: JoaoGustavoRogel
|
||||
count: 9
|
||||
@@ -683,6 +683,11 @@ Yarous:
|
||||
count: 9
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/61277193?u=5b462347458a373b2d599c6f416d2b75eddbffad&v=4
|
||||
url: https://github.com/Yarous
|
||||
Pyth3rEx:
|
||||
login: Pyth3rEx
|
||||
count: 9
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/26427764?u=087724f74d813c95925d51e354554bd4b6d6bb60&v=4
|
||||
url: https://github.com/Pyth3rEx
|
||||
dimaqq:
|
||||
login: dimaqq
|
||||
count: 8
|
||||
@@ -1023,6 +1028,11 @@ devluisrodrigues:
|
||||
count: 5
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/21125286?v=4
|
||||
url: https://github.com/11kkw
|
||||
EdmilsonRodrigues:
|
||||
login: EdmilsonRodrigues
|
||||
count: 5
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62777025?u=217d6f3cd6cc750bb8818a3af7726c8d74eb7c2d&v=4
|
||||
url: https://github.com/EdmilsonRodrigues
|
||||
lpdswing:
|
||||
login: lpdswing
|
||||
count: 4
|
||||
@@ -1163,6 +1173,11 @@ AbolfazlKameli:
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/120686133?u=af8f025278cce0d489007071254e4055df60b78c&v=4
|
||||
url: https://github.com/AbolfazlKameli
|
||||
SBillion:
|
||||
login: SBillion
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1070649?u=3ab493dfc88b39da0eb1600e3b8e7df1c90a5dee&v=4
|
||||
url: https://github.com/SBillion
|
||||
tyronedamasceno:
|
||||
login: tyronedamasceno
|
||||
count: 3
|
||||
@@ -1211,7 +1226,7 @@ phamquanganh31101998:
|
||||
peebbv6364:
|
||||
login: peebbv6364
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/26784747?u=75583df215ee01a5cd2dc646aecb81e7dbd33d06&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/26784747?u=3bf07017eb4f4fa3639ba8d4ed19980a34bf8f90&v=4
|
||||
url: https://github.com/peebbv6364
|
||||
mrparalon:
|
||||
login: mrparalon
|
||||
@@ -1413,11 +1428,6 @@ Mohammad222PR:
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/116789737?u=25810a5fe049d2f1618e2e7417cea011cc353ce4&v=4
|
||||
url: https://github.com/Mohammad222PR
|
||||
EdmilsonRodrigues:
|
||||
login: EdmilsonRodrigues
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62777025?u=217d6f3cd6cc750bb8818a3af7726c8d74eb7c2d&v=4
|
||||
url: https://github.com/EdmilsonRodrigues
|
||||
blaisep:
|
||||
login: blaisep
|
||||
count: 2
|
||||
@@ -1838,11 +1848,11 @@ NavesSapnis:
|
||||
count: 2
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/79222417?u=b5b10291b8e9130ca84fd20f0a641e04ed94b6b1&v=4
|
||||
url: https://github.com/NavesSapnis
|
||||
eqsdxr:
|
||||
login: eqsdxr
|
||||
isgin01:
|
||||
login: isgin01
|
||||
count: 2
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=7927dc0366995334f9a18c3204a41d3a34d6d96f&v=4
|
||||
url: https://github.com/eqsdxr
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=ddffde10876b50f35dc90d1337f507a630530a6a&v=4
|
||||
url: https://github.com/isgin01
|
||||
syedasamina56:
|
||||
login: syedasamina56
|
||||
count: 2
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
nilslindemann:
|
||||
login: nilslindemann
|
||||
count: 125
|
||||
count: 130
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4
|
||||
url: https://github.com/nilslindemann
|
||||
jaystone776:
|
||||
@@ -28,6 +28,11 @@ SwftAlpc:
|
||||
count: 23
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4
|
||||
url: https://github.com/SwftAlpc
|
||||
tiangolo:
|
||||
login: tiangolo
|
||||
count: 22
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
|
||||
url: https://github.com/tiangolo
|
||||
hasansezertasan:
|
||||
login: hasansezertasan
|
||||
count: 22
|
||||
@@ -46,7 +51,7 @@ AlertRED:
|
||||
hard-coders:
|
||||
login: hard-coders
|
||||
count: 15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=78d12d1acdf853c817700145e73de7fd9e5d068b&v=4
|
||||
url: https://github.com/hard-coders
|
||||
Joao-Pedro-P-Holanda:
|
||||
login: Joao-Pedro-P-Holanda
|
||||
@@ -103,11 +108,6 @@ pablocm83:
|
||||
count: 8
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/28315068?u=3310fbb05bb8bfc50d2c48b6cb64ac9ee4a14549&v=4
|
||||
url: https://github.com/pablocm83
|
||||
tiangolo:
|
||||
login: tiangolo
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
|
||||
url: https://github.com/tiangolo
|
||||
ptt3199:
|
||||
login: ptt3199
|
||||
count: 7
|
||||
@@ -126,13 +126,18 @@ batlopes:
|
||||
lucasbalieiro:
|
||||
login: lucasbalieiro
|
||||
count: 6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37416577?u=dad91601ee4f40458d691774ec439aff308344d7&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37416577?u=d144221c34c08adac8b20e1833d776ffa1c4b1d0&v=4
|
||||
url: https://github.com/lucasbalieiro
|
||||
Alexandrhub:
|
||||
login: Alexandrhub
|
||||
count: 6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/119126536?u=9fc0d48f3307817bafecc5861eb2168401a6cb04&v=4
|
||||
url: https://github.com/Alexandrhub
|
||||
YuriiMotov:
|
||||
login: YuriiMotov
|
||||
count: 6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
|
||||
url: https://github.com/YuriiMotov
|
||||
Serrones:
|
||||
login: Serrones
|
||||
count: 5
|
||||
@@ -358,11 +363,6 @@ ruzia:
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/24503?v=4
|
||||
url: https://github.com/ruzia
|
||||
YuriiMotov:
|
||||
login: YuriiMotov
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
|
||||
url: https://github.com/YuriiMotov
|
||||
izaguerreiro:
|
||||
login: izaguerreiro
|
||||
count: 2
|
||||
|
||||
@@ -15,6 +15,9 @@ hide:
|
||||
|
||||
### Internal
|
||||
|
||||
* 👥 Update FastAPI People - Sponsors. PR [#14626](https://github.com/fastapi/fastapi/pull/14626) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👥 Update FastAPI GitHub topic repositories. PR [#14630](https://github.com/fastapi/fastapi/pull/14630) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👥 Update FastAPI People - Contributors and Translators. PR [#14625](https://github.com/fastapi/fastapi/pull/14625) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🌐 Update translation prompts. PR [#14619](https://github.com/fastapi/fastapi/pull/14619) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔨 Update LLM translation script to guide reviewers to change the prompt. PR [#14614](https://github.com/fastapi/fastapi/pull/14614) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👷 Do not run translations on cron while finishing updating existing languages. PR [#14613](https://github.com/fastapi/fastapi/pull/14613) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
@@ -4,7 +4,7 @@ pytest >=7.1.3,<9.0.0
|
||||
coverage[toml] >= 6.5.0,< 8.0
|
||||
mypy ==1.14.1
|
||||
dirty-equals ==0.9.0
|
||||
sqlmodel==0.0.31
|
||||
sqlmodel==0.0.27
|
||||
flask >=1.1.2,<4.0.0
|
||||
strawberry-graphql >=0.200.0,< 1.0.0
|
||||
anyio[trio] >=3.2.1,<5.0.0
|
||||
|
||||
729
scripts/doc_parsing_utils.py
Normal file
729
scripts/doc_parsing_utils.py
Normal file
@@ -0,0 +1,729 @@
|
||||
import re
|
||||
from typing import TypedDict
|
||||
|
||||
CODE_INCLUDE_RE = re.compile(r"^\{\*\s*(\S+)\s*(.*)\*\}$")
|
||||
CODE_INCLUDE_PLACEHOLDER = "<CODE_INCLUDE>"
|
||||
|
||||
HEADER_WITH_PERMALINK_RE = re.compile(r"^(#{1,6}) (.+?)(\s*\{\s*#.*\s*\})?\s*$")
|
||||
HEADER_LINE_RE = re.compile(r"^(#{1,6}) (.+?)(?:\s*\{\s*(#.*)\s*\})?\s*$")
|
||||
|
||||
TIANGOLO_COM = "https://fastapi.tiangolo.com"
|
||||
ASSETS_URL_PREFIXES = ("/img/", "/css/", "/js/")
|
||||
|
||||
MARKDOWN_LINK_RE = re.compile(
|
||||
r"(?<!\\)(?<!\!)" # not an image ![...] and not escaped \[...]
|
||||
r"\[(?P<text>.*?)\]" # link text (non-greedy)
|
||||
r"\("
|
||||
r"(?P<url>[^)\s]+)" # url (no spaces and `)`)
|
||||
r'(?:\s+["\'](?P<title>.*?)["\'])?' # optional title in "" or ''
|
||||
r"\)"
|
||||
r"(?:\s*\{(?P<attrs>[^}]*)\})?" # optional attributes in {}
|
||||
)
|
||||
|
||||
HTML_LINK_RE = re.compile(r"<a\s+[^>]*>.*?</a>")
|
||||
HTML_LINK_TEXT_RE = re.compile(r"<a\b([^>]*)>(.*?)</a>")
|
||||
HTML_LINK_OPEN_TAG_RE = re.compile(r"<a\b([^>]*)>")
|
||||
HTML_ATTR_RE = re.compile(r'(\w+)\s*=\s*([\'"])(.*?)\2')
|
||||
|
||||
CODE_BLOCK_LANG_RE = re.compile(r"^`{3,4}([\w-]*)", re.MULTILINE)
|
||||
|
||||
SLASHES_COMMENT_RE = re.compile(
|
||||
r"^(?P<code>.*?)(?P<comment>(?:(?<= )// .*)|(?:^// .*))?$"
|
||||
)
|
||||
|
||||
HASH_COMMENT_RE = re.compile(r"^(?P<code>.*?)(?P<comment>(?:(?<= )# .*)|(?:^# .*))?$")
|
||||
|
||||
|
||||
class CodeIncludeInfo(TypedDict):
|
||||
line_no: int
|
||||
line: str
|
||||
|
||||
|
||||
class HeaderPermalinkInfo(TypedDict):
|
||||
line_no: int
|
||||
hashes: str
|
||||
title: str
|
||||
permalink: str
|
||||
|
||||
|
||||
class MarkdownLinkInfo(TypedDict):
|
||||
line_no: int
|
||||
url: str
|
||||
text: str
|
||||
title: str | None
|
||||
attributes: str | None
|
||||
full_match: str
|
||||
|
||||
|
||||
class HTMLLinkAttribute(TypedDict):
|
||||
name: str
|
||||
quote: str
|
||||
value: str
|
||||
|
||||
|
||||
class HtmlLinkInfo(TypedDict):
|
||||
line_no: int
|
||||
full_tag: str
|
||||
attributes: list[HTMLLinkAttribute]
|
||||
text: str
|
||||
|
||||
|
||||
class MultilineCodeBlockInfo(TypedDict):
|
||||
lang: str
|
||||
start_line_no: int
|
||||
content: list[str]
|
||||
|
||||
|
||||
# Code includes
|
||||
# -----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def extract_code_includes(lines: list[str]) -> list[CodeIncludeInfo]:
|
||||
"""
|
||||
Exctract lines that contain code includes.
|
||||
|
||||
Return list of CodeIncludeInfo namedtuples, where each tuple contains:
|
||||
- `line_no` - line number (1-based)
|
||||
- `line` - text of the line
|
||||
"""
|
||||
|
||||
includes: list[CodeIncludeInfo] = []
|
||||
for line_no, line in enumerate(lines, start=1):
|
||||
if CODE_INCLUDE_RE.match(line):
|
||||
includes.append(CodeIncludeInfo(line_no=line_no, line=line))
|
||||
return includes
|
||||
|
||||
|
||||
def replace_code_includes_with_placeholders(text: list[str]) -> list[str]:
|
||||
"""
|
||||
Replace code includes with placeholders.
|
||||
"""
|
||||
|
||||
modified_text = text.copy()
|
||||
includes = extract_code_includes(text)
|
||||
for include in includes:
|
||||
modified_text[include["line_no"] - 1] = CODE_INCLUDE_PLACEHOLDER
|
||||
return modified_text
|
||||
|
||||
|
||||
def replace_placeholders_with_code_includes(
|
||||
text: list[str], original_includes: list[CodeIncludeInfo]
|
||||
) -> list[str]:
|
||||
"""
|
||||
Replace code includes placeholders with actual code includes from the original (English) document.
|
||||
Fail if the number of placeholders does not match the number of original includes.
|
||||
"""
|
||||
|
||||
code_include_lines = [
|
||||
line_no
|
||||
for line_no, line in enumerate(text)
|
||||
if line.strip() == CODE_INCLUDE_PLACEHOLDER
|
||||
]
|
||||
|
||||
if len(code_include_lines) != len(original_includes):
|
||||
raise ValueError(
|
||||
"Number of code include placeholders does not match the number of code includes "
|
||||
"in the original document "
|
||||
f"({len(code_include_lines)} vs {len(original_includes)})"
|
||||
)
|
||||
|
||||
modified_text = text.copy()
|
||||
for i, line_no in enumerate(code_include_lines):
|
||||
modified_text[line_no] = original_includes[i]["line"]
|
||||
|
||||
return modified_text
|
||||
|
||||
|
||||
# Header permalinks
|
||||
# -----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def extract_header_permalinks(lines: list[str]) -> list[HeaderPermalinkInfo]:
|
||||
"""
|
||||
Extract list of header permalinks from the given lines.
|
||||
|
||||
Return list of HeaderPermalinkInfo namedtuples, where each tuple contains:
|
||||
- `line_no` - line number (1-based)
|
||||
- `hashes` - string of hashes representing header level (e.g., "###")
|
||||
- `permalink` - permalink string (e.g., "{#permalink}")
|
||||
"""
|
||||
|
||||
headers: list[HeaderPermalinkInfo] = []
|
||||
in_code_block3 = False
|
||||
in_code_block4 = False
|
||||
|
||||
for line_no, line in enumerate(lines, start=1):
|
||||
if not (in_code_block3 or in_code_block4):
|
||||
if line.startswith("```"):
|
||||
count = len(line) - len(line.lstrip("`"))
|
||||
if count == 3:
|
||||
in_code_block3 = True
|
||||
continue
|
||||
elif count >= 4:
|
||||
in_code_block4 = True
|
||||
continue
|
||||
|
||||
header_match = HEADER_WITH_PERMALINK_RE.match(line)
|
||||
if header_match:
|
||||
hashes, title, permalink = header_match.groups()
|
||||
headers.append(
|
||||
HeaderPermalinkInfo(
|
||||
hashes=hashes, line_no=line_no, permalink=permalink, title=title
|
||||
)
|
||||
)
|
||||
|
||||
elif in_code_block3:
|
||||
if line.startswith("```"):
|
||||
count = len(line) - len(line.lstrip("`"))
|
||||
if count == 3:
|
||||
in_code_block3 = False
|
||||
continue
|
||||
|
||||
elif in_code_block4:
|
||||
if line.startswith("````"):
|
||||
count = len(line) - len(line.lstrip("`"))
|
||||
if count >= 4:
|
||||
in_code_block4 = False
|
||||
continue
|
||||
|
||||
return headers
|
||||
|
||||
|
||||
def remove_header_permalinks(lines: list[str]) -> list[str]:
|
||||
"""
|
||||
Remove permalinks from headers in the given lines.
|
||||
"""
|
||||
|
||||
modified_lines: list[str] = []
|
||||
for line in lines:
|
||||
header_match = HEADER_WITH_PERMALINK_RE.match(line)
|
||||
if header_match:
|
||||
hashes, title, _permalink = header_match.groups()
|
||||
modified_line = f"{hashes} {title}"
|
||||
modified_lines.append(modified_line)
|
||||
else:
|
||||
modified_lines.append(line)
|
||||
return modified_lines
|
||||
|
||||
|
||||
def replace_header_permalinks(
|
||||
text: list[str],
|
||||
header_permalinks: list[HeaderPermalinkInfo],
|
||||
original_header_permalinks: list[HeaderPermalinkInfo],
|
||||
) -> list[str]:
|
||||
"""
|
||||
Replace permalinks in the given text with the permalinks from the original document.
|
||||
|
||||
Fail if the number or level of headers does not match the original.
|
||||
"""
|
||||
|
||||
modified_text: list[str] = text.copy()
|
||||
|
||||
if len(header_permalinks) != len(original_header_permalinks):
|
||||
raise ValueError(
|
||||
"Number of headers with permalinks does not match the number in the "
|
||||
"original document "
|
||||
f"({len(header_permalinks)} vs {len(original_header_permalinks)})"
|
||||
)
|
||||
|
||||
for header_no in range(len(header_permalinks)):
|
||||
header_info = header_permalinks[header_no]
|
||||
original_header_info = original_header_permalinks[header_no]
|
||||
|
||||
if header_info["hashes"] != original_header_info["hashes"]:
|
||||
raise ValueError(
|
||||
"Header levels do not match between document and original document"
|
||||
f" (found {header_info['hashes']}, expected {original_header_info['hashes']})"
|
||||
f" for header №{header_no + 1} in line {header_info['line_no']}"
|
||||
)
|
||||
line_no = header_info["line_no"] - 1
|
||||
hashes = header_info["hashes"]
|
||||
title = header_info["title"]
|
||||
permalink = original_header_info["permalink"]
|
||||
modified_text[line_no] = f"{hashes} {title}{permalink}"
|
||||
|
||||
return modified_text
|
||||
|
||||
|
||||
# Markdown links
|
||||
# -----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def extract_markdown_links(lines: list[str]) -> list[tuple[str, int]]:
|
||||
"""
|
||||
Extract all markdown links from the given lines.
|
||||
|
||||
Return list of MarkdownLinkInfo namedtuples, where each tuple contains:
|
||||
- `line_no` - line number (1-based)
|
||||
- `url` - link URL
|
||||
- `text` - link text
|
||||
- `title` - link title (if any)
|
||||
"""
|
||||
|
||||
links: list[MarkdownLinkInfo] = []
|
||||
for line_no, line in enumerate(lines, start=1):
|
||||
for m in MARKDOWN_LINK_RE.finditer(line):
|
||||
links.append(
|
||||
MarkdownLinkInfo(
|
||||
line_no=line_no,
|
||||
url=m.group("url"),
|
||||
text=m.group("text"),
|
||||
title=m.group("title"),
|
||||
attributes=m.group("attrs"),
|
||||
full_match=m.group(0),
|
||||
)
|
||||
)
|
||||
return links
|
||||
|
||||
|
||||
def _add_lang_code_to_url(url: str, lang_code: str) -> str:
|
||||
if url.startswith(TIANGOLO_COM):
|
||||
rel_url = url[len(TIANGOLO_COM) :]
|
||||
if not rel_url.startswith(ASSETS_URL_PREFIXES):
|
||||
url = url.replace(TIANGOLO_COM, f"{TIANGOLO_COM}/{lang_code}")
|
||||
return url
|
||||
|
||||
|
||||
def _construct_markdown_link(
|
||||
url: str, text: str, title: str | None, attributes: str | None, lang_code: str
|
||||
) -> str:
|
||||
"""
|
||||
Construct a markdown link, adjusting the URL for the given language code if needed.
|
||||
"""
|
||||
url = _add_lang_code_to_url(url, lang_code)
|
||||
|
||||
if title:
|
||||
link = f'[{text}]({url} "{title}")'
|
||||
else:
|
||||
link = f"[{text}]({url})"
|
||||
|
||||
if attributes:
|
||||
link += f"{{{attributes}}}"
|
||||
|
||||
return link
|
||||
|
||||
|
||||
def replace_markdown_links(
|
||||
text: list[str],
|
||||
links: list[MarkdownLinkInfo],
|
||||
original_links: list[MarkdownLinkInfo],
|
||||
lang_code: str,
|
||||
) -> list[str]:
|
||||
"""
|
||||
Replace markdown links in the given text with the original links.
|
||||
|
||||
Fail if the number of links does not match the original.
|
||||
"""
|
||||
|
||||
if len(links) != len(original_links):
|
||||
raise ValueError(
|
||||
"Number of markdown links does not match the number in the "
|
||||
"original document "
|
||||
f"({len(links)} vs {len(original_links)})"
|
||||
)
|
||||
|
||||
modified_text = text.copy()
|
||||
for i, link_info in enumerate(links):
|
||||
link_text = link_info["text"]
|
||||
link_title = link_info["title"]
|
||||
original_link_info = original_links[i]
|
||||
|
||||
# Replace
|
||||
replacement_link = _construct_markdown_link(
|
||||
url=original_link_info["url"],
|
||||
text=link_text,
|
||||
title=link_title,
|
||||
attributes=original_link_info["attributes"],
|
||||
lang_code=lang_code,
|
||||
)
|
||||
line_no = link_info["line_no"] - 1
|
||||
modified_line = modified_text[line_no]
|
||||
modified_line = modified_line.replace(
|
||||
link_info["full_match"], replacement_link, 1
|
||||
)
|
||||
modified_text[line_no] = modified_line
|
||||
|
||||
return modified_text
|
||||
|
||||
|
||||
# HTML links
|
||||
# -----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def extract_html_links(lines: list[str]) -> list[HtmlLinkInfo]:
|
||||
"""
|
||||
Extract all HTML links from the given lines.
|
||||
|
||||
Return list of HtmlLinkInfo namedtuples, where each tuple contains:
|
||||
- `line_no` - line number (1-based)
|
||||
- `full_tag` - full HTML link tag
|
||||
- `attributes` - list of HTMLLinkAttribute namedtuples (name, quote, value)
|
||||
- `text` - link text
|
||||
"""
|
||||
|
||||
links = []
|
||||
for line_no, line in enumerate(lines, start=1):
|
||||
for html_link in HTML_LINK_RE.finditer(line):
|
||||
link_str = html_link.group(0)
|
||||
|
||||
link_text_match = HTML_LINK_TEXT_RE.match(link_str)
|
||||
assert link_text_match is not None
|
||||
link_text = link_text_match.group(2)
|
||||
assert isinstance(link_text, str)
|
||||
|
||||
link_open_tag_match = HTML_LINK_OPEN_TAG_RE.match(link_str)
|
||||
assert link_open_tag_match is not None
|
||||
link_open_tag = link_open_tag_match.group(1)
|
||||
assert isinstance(link_open_tag, str)
|
||||
|
||||
attributes: list[HTMLLinkAttribute] = []
|
||||
for attr_name, attr_quote, attr_value in re.findall(
|
||||
HTML_ATTR_RE, link_open_tag
|
||||
):
|
||||
assert isinstance(attr_name, str)
|
||||
assert isinstance(attr_quote, str)
|
||||
assert isinstance(attr_value, str)
|
||||
attributes.append(
|
||||
HTMLLinkAttribute(
|
||||
name=attr_name, quote=attr_quote, value=attr_value
|
||||
)
|
||||
)
|
||||
links.append(
|
||||
HtmlLinkInfo(
|
||||
line_no=line_no,
|
||||
full_tag=link_str,
|
||||
attributes=attributes,
|
||||
text=link_text,
|
||||
)
|
||||
)
|
||||
return links
|
||||
|
||||
|
||||
def _construct_html_link(
|
||||
link_text: str,
|
||||
attributes: list[HTMLLinkAttribute],
|
||||
lang_code: str,
|
||||
) -> str:
|
||||
"""
|
||||
Reconstruct HTML link, adjusting the URL for the given language code if needed.
|
||||
"""
|
||||
|
||||
attributes_upd: list[HTMLLinkAttribute] = []
|
||||
for attribute in attributes:
|
||||
if attribute["name"] == "href":
|
||||
original_url = attribute["value"]
|
||||
url = _add_lang_code_to_url(original_url, lang_code)
|
||||
attributes_upd.append(
|
||||
HTMLLinkAttribute(name="href", quote=attribute["quote"], value=url)
|
||||
)
|
||||
else:
|
||||
attributes_upd.append(attribute)
|
||||
|
||||
attrs_str = " ".join(
|
||||
f"{attribute['name']}={attribute['quote']}{attribute['value']}{attribute['quote']}"
|
||||
for attribute in attributes_upd
|
||||
)
|
||||
return f"<a {attrs_str}>{link_text}</a>"
|
||||
|
||||
|
||||
def replace_html_links(
|
||||
text: list[str],
|
||||
links: list[HtmlLinkInfo],
|
||||
original_links: list[HtmlLinkInfo],
|
||||
lang_code: str,
|
||||
) -> list[str]:
|
||||
"""
|
||||
Replace HTML links in the given text with the links from the original document.
|
||||
|
||||
Adjust URLs for the given language code.
|
||||
Fail if the number of links does not match the original.
|
||||
"""
|
||||
|
||||
if len(links) != len(original_links):
|
||||
raise ValueError(
|
||||
"Number of HTML links does not match the number in the "
|
||||
"original document "
|
||||
f"({len(links)} vs {len(original_links)})"
|
||||
)
|
||||
|
||||
modified_text = text.copy()
|
||||
for link_index, link in enumerate(links):
|
||||
original_link_info = original_links[link_index]
|
||||
|
||||
# Replace in the document text
|
||||
replacement_link = _construct_html_link(
|
||||
link_text=link["text"],
|
||||
attributes=original_link_info["attributes"],
|
||||
lang_code=lang_code,
|
||||
)
|
||||
line_no = link["line_no"] - 1
|
||||
modified_text[line_no] = modified_text[line_no].replace(
|
||||
link["full_tag"], replacement_link, 1
|
||||
)
|
||||
|
||||
return modified_text
|
||||
|
||||
|
||||
# Multiline code blocks
|
||||
# -----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def get_code_block_lang(line: str) -> str:
|
||||
match = CODE_BLOCK_LANG_RE.match(line)
|
||||
if match:
|
||||
return match.group(1)
|
||||
return ""
|
||||
|
||||
|
||||
def extract_multiline_code_blocks(text: list[str]) -> list[MultilineCodeBlockInfo]:
|
||||
blocks: list[MultilineCodeBlockInfo] = []
|
||||
|
||||
in_code_block3 = False
|
||||
in_code_block4 = False
|
||||
current_block_lang = ""
|
||||
current_block_start_line = -1
|
||||
current_block_lines = []
|
||||
|
||||
for line_no, line in enumerate(text, start=1):
|
||||
stripped = line.lstrip()
|
||||
|
||||
# --- Detect opening fence ---
|
||||
if not (in_code_block3 or in_code_block4):
|
||||
if stripped.startswith("```"):
|
||||
current_block_start_line = line_no
|
||||
count = len(stripped) - len(stripped.lstrip("`"))
|
||||
if count == 3:
|
||||
in_code_block3 = True
|
||||
current_block_lang = get_code_block_lang(stripped)
|
||||
current_block_lines = [line]
|
||||
continue
|
||||
elif count >= 4:
|
||||
in_code_block4 = True
|
||||
current_block_lang = get_code_block_lang(stripped)
|
||||
current_block_lines = [line]
|
||||
continue
|
||||
|
||||
# --- Detect closing fence ---
|
||||
elif in_code_block3:
|
||||
if stripped.startswith("```"):
|
||||
count = len(stripped) - len(stripped.lstrip("`"))
|
||||
if count == 3:
|
||||
current_block_lines.append(line)
|
||||
blocks.append(
|
||||
MultilineCodeBlockInfo(
|
||||
lang=current_block_lang,
|
||||
start_line_no=current_block_start_line,
|
||||
content=current_block_lines,
|
||||
)
|
||||
)
|
||||
in_code_block3 = False
|
||||
current_block_lang = ""
|
||||
current_block_start_line = -1
|
||||
current_block_lines = []
|
||||
continue
|
||||
current_block_lines.append(line)
|
||||
|
||||
elif in_code_block4:
|
||||
if stripped.startswith("````"):
|
||||
count = len(stripped) - len(stripped.lstrip("`"))
|
||||
if count >= 4:
|
||||
current_block_lines.append(line)
|
||||
blocks.append(
|
||||
MultilineCodeBlockInfo(
|
||||
lang=current_block_lang,
|
||||
start_line_no=current_block_start_line,
|
||||
content=current_block_lines,
|
||||
)
|
||||
)
|
||||
in_code_block4 = False
|
||||
current_block_lang = ""
|
||||
current_block_start_line = -1
|
||||
current_block_lines = []
|
||||
continue
|
||||
current_block_lines.append(line)
|
||||
|
||||
return blocks
|
||||
|
||||
|
||||
def _split_hash_comment(line: str) -> tuple[str, str | None]:
|
||||
match = HASH_COMMENT_RE.match(line)
|
||||
if match:
|
||||
code = match.group("code").rstrip()
|
||||
comment = match.group("comment")
|
||||
return code, comment
|
||||
return line.rstrip(), None
|
||||
|
||||
|
||||
def _split_slashes_comment(line: str) -> tuple[str, str | None]:
|
||||
match = SLASHES_COMMENT_RE.match(line)
|
||||
if match:
|
||||
code = match.group("code").rstrip()
|
||||
comment = match.group("comment")
|
||||
return code, comment
|
||||
return line, None
|
||||
|
||||
|
||||
def replace_multiline_code_block(
|
||||
block_a: MultilineCodeBlockInfo, block_b: MultilineCodeBlockInfo
|
||||
) -> list[str]:
|
||||
"""
|
||||
Replace multiline code block `a` with block `b` leaving comments intact.
|
||||
|
||||
Syntax of comments depends on the language of the code block.
|
||||
Raises ValueError if the blocks are not compatible (different languages or different number of lines).
|
||||
"""
|
||||
|
||||
start_line = block_a["start_line_no"]
|
||||
end_line_no = start_line + len(block_a["content"]) - 1
|
||||
|
||||
if block_a["lang"] != block_b["lang"]:
|
||||
raise ValueError(
|
||||
f"Code block (lines {start_line}-{end_line_no}) "
|
||||
"has different language than the original block "
|
||||
f"('{block_a['lang']}' vs '{block_b['lang']}')"
|
||||
)
|
||||
if len(block_a["content"]) != len(block_b["content"]):
|
||||
raise ValueError(
|
||||
f"Code block (lines {start_line}-{end_line_no}) "
|
||||
"has different number of lines than the original block "
|
||||
f"({len(block_a['content'])} vs {len(block_b['content'])})"
|
||||
)
|
||||
|
||||
block_language = block_a["lang"].lower()
|
||||
if block_language in {"mermaid"}:
|
||||
if block_a != block_b:
|
||||
print(
|
||||
f"Skipping mermaid code block replacement (lines {start_line}-{end_line_no}). "
|
||||
"This should be checked manually."
|
||||
)
|
||||
return block_a["content"].copy() # We don't handle mermaid code blocks for now
|
||||
|
||||
code_block: list[str] = []
|
||||
for line_a, line_b in zip(block_a["content"], block_b["content"]):
|
||||
line_a_comment: str | None = None
|
||||
line_b_comment: str | None = None
|
||||
|
||||
# Handle comments based on language
|
||||
if block_language in {
|
||||
"python",
|
||||
"py",
|
||||
"sh",
|
||||
"bash",
|
||||
"dockerfile",
|
||||
"requirements",
|
||||
"gitignore",
|
||||
"toml",
|
||||
"yaml",
|
||||
"yml",
|
||||
"hash-style-comments",
|
||||
}:
|
||||
_line_a_code, line_a_comment = _split_hash_comment(line_a)
|
||||
_line_b_code, line_b_comment = _split_hash_comment(line_b)
|
||||
res_line = line_b
|
||||
if line_b_comment:
|
||||
res_line = res_line.replace(line_b_comment, line_a_comment, 1)
|
||||
code_block.append(res_line)
|
||||
elif block_language in {"console", "json", "slash-style-comments"}:
|
||||
_line_a_code, line_a_comment = _split_slashes_comment(line_a)
|
||||
_line_b_code, line_b_comment = _split_slashes_comment(line_b)
|
||||
res_line = line_b
|
||||
if line_b_comment:
|
||||
res_line = res_line.replace(line_b_comment, line_a_comment, 1)
|
||||
code_block.append(res_line)
|
||||
else:
|
||||
code_block.append(line_b)
|
||||
|
||||
return code_block
|
||||
|
||||
|
||||
def replace_multiline_code_blocks_in_text(
|
||||
text: list[str],
|
||||
code_blocks: list[MultilineCodeBlockInfo],
|
||||
original_code_blocks: list[MultilineCodeBlockInfo],
|
||||
) -> list[MultilineCodeBlockInfo]:
|
||||
"""
|
||||
Update each code block in `text` with the corresponding code block from
|
||||
`original_code_blocks` with comments taken from `code_blocks`.
|
||||
|
||||
Raises ValueError if the number, language, or shape of code blocks do not match.
|
||||
"""
|
||||
|
||||
if len(code_blocks) != len(original_code_blocks):
|
||||
raise ValueError(
|
||||
"Number of code blocks does not match the number in the original document "
|
||||
f"({len(code_blocks)} vs {len(original_code_blocks)})"
|
||||
)
|
||||
|
||||
modified_text = text.copy()
|
||||
for block, original_block in zip(code_blocks, original_code_blocks):
|
||||
updated_content = replace_multiline_code_block(block, original_block)
|
||||
|
||||
start_line_index = block["start_line_no"] - 1
|
||||
for i, updated_line in enumerate(updated_content):
|
||||
modified_text[start_line_index + i] = updated_line
|
||||
|
||||
return modified_text
|
||||
|
||||
|
||||
# All checks
|
||||
# -----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def check_translation(
|
||||
doc_lines: list[str],
|
||||
en_doc_lines: list[str],
|
||||
lang_code: str,
|
||||
auto_fix: bool,
|
||||
path: str,
|
||||
) -> list[str]:
|
||||
# Fix code includes
|
||||
en_code_includes = extract_code_includes(en_doc_lines)
|
||||
doc_lines_with_placeholders = replace_code_includes_with_placeholders(doc_lines)
|
||||
fixed_doc_lines = replace_placeholders_with_code_includes(
|
||||
doc_lines_with_placeholders, en_code_includes
|
||||
)
|
||||
if auto_fix and (fixed_doc_lines != doc_lines):
|
||||
print(f"Fixing code includes in: {path}")
|
||||
doc_lines = fixed_doc_lines
|
||||
|
||||
# Fix permalinks
|
||||
en_permalinks = extract_header_permalinks(en_doc_lines)
|
||||
doc_permalinks = extract_header_permalinks(doc_lines)
|
||||
fixed_doc_lines = replace_header_permalinks(
|
||||
doc_lines, doc_permalinks, en_permalinks
|
||||
)
|
||||
if auto_fix and (fixed_doc_lines != doc_lines):
|
||||
print(f"Fixing header permalinks in: {path}")
|
||||
doc_lines = fixed_doc_lines
|
||||
|
||||
# Fix markdown links
|
||||
en_markdown_links = extract_markdown_links(en_doc_lines)
|
||||
doc_markdown_links = extract_markdown_links(doc_lines)
|
||||
fixed_doc_lines = replace_markdown_links(
|
||||
doc_lines, doc_markdown_links, en_markdown_links, lang_code
|
||||
)
|
||||
if auto_fix and (fixed_doc_lines != doc_lines):
|
||||
print(f"Fixing markdown links in: {path}")
|
||||
doc_lines = fixed_doc_lines
|
||||
|
||||
# Fix HTML links
|
||||
en_html_links = extract_html_links(en_doc_lines)
|
||||
doc_html_links = extract_html_links(doc_lines)
|
||||
fixed_doc_lines = replace_html_links(
|
||||
doc_lines, doc_html_links, en_html_links, lang_code
|
||||
)
|
||||
if auto_fix and (fixed_doc_lines != doc_lines):
|
||||
print(f"Fixing HTML links in: {path}")
|
||||
doc_lines = fixed_doc_lines
|
||||
|
||||
# Fix multiline code blocks
|
||||
en_code_blocks = extract_multiline_code_blocks(en_doc_lines)
|
||||
doc_code_blocks = extract_multiline_code_blocks(doc_lines)
|
||||
fixed_doc_lines = replace_multiline_code_blocks_in_text(
|
||||
doc_lines, doc_code_blocks, en_code_blocks
|
||||
)
|
||||
if auto_fix and (fixed_doc_lines != doc_lines):
|
||||
print(f"Fixing multiline code blocks in: {path}")
|
||||
doc_lines = fixed_doc_lines
|
||||
|
||||
return doc_lines
|
||||
32
scripts/tests/test_translation_fixer/conftest.py
Normal file
32
scripts/tests/test_translation_fixer/conftest.py
Normal file
@@ -0,0 +1,32 @@
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from typer.testing import CliRunner
|
||||
|
||||
|
||||
@pytest.fixture(name="runner")
|
||||
def get_runner():
|
||||
runner = CliRunner()
|
||||
with runner.isolated_filesystem():
|
||||
yield runner
|
||||
|
||||
|
||||
@pytest.fixture(name="root_dir")
|
||||
def prepare_paths(runner):
|
||||
docs_dir = Path("docs")
|
||||
en_docs_dir = docs_dir / "en" / "docs"
|
||||
lang_docs_dir = docs_dir / "lang" / "docs"
|
||||
en_docs_dir.mkdir(parents=True, exist_ok=True)
|
||||
lang_docs_dir.mkdir(parents=True, exist_ok=True)
|
||||
yield Path.cwd()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def copy_test_files(root_dir: Path, request: pytest.FixtureRequest):
|
||||
en_file_path = Path(request.param[0])
|
||||
translation_file_path = Path(request.param[1])
|
||||
shutil.copy(str(en_file_path), str(root_dir / "docs" / "en" / "docs" / "doc.md"))
|
||||
shutil.copy(
|
||||
str(translation_file_path), str(root_dir / "docs" / "lang" / "docs" / "doc.md")
|
||||
)
|
||||
@@ -0,0 +1,44 @@
|
||||
# Code blocks { #code-blocks }
|
||||
|
||||
Some text
|
||||
|
||||
```python
|
||||
# This is a sample Python code block
|
||||
def hello_world():
|
||||
# Comment with indentation
|
||||
print("Hello, world!") # Print greeting
|
||||
```
|
||||
|
||||
Some more text
|
||||
|
||||
```toml
|
||||
# This is a sample TOML code block
|
||||
title = "TOML Example" # Title of the document
|
||||
```
|
||||
|
||||
And more text
|
||||
|
||||
```console
|
||||
// Use the command "live" and pass the language code as a CLI argument
|
||||
$ python ./scripts/docs.py live es
|
||||
|
||||
<span style="color: green;">[INFO]</span> Serving on http://127.0.0.1:8008
|
||||
<span style="color: green;">[INFO]</span> Start watching changes
|
||||
<span style="color: green;">[INFO]</span> Start detecting changes
|
||||
```
|
||||
|
||||
And even more text
|
||||
|
||||
```json
|
||||
{
|
||||
// This is a sample JSON code block
|
||||
"greeting": "Hello, world!" // Greeting
|
||||
}
|
||||
```
|
||||
|
||||
Mermaid diagram
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
stone(philosophers-stone) -->|requires| harry-1[harry v1]
|
||||
```
|
||||
@@ -0,0 +1,45 @@
|
||||
# Code blocks { #code-blocks }
|
||||
|
||||
Some text
|
||||
|
||||
```python
|
||||
# This is a sample Python code block
|
||||
def hello_world():
|
||||
# Comment with indentation
|
||||
print("Hello, world!") # Print greeting
|
||||
```
|
||||
|
||||
Some more text
|
||||
|
||||
```toml
|
||||
# Extra line
|
||||
# This is a sample TOML code block
|
||||
title = "TOML Example" # Title of the document
|
||||
```
|
||||
|
||||
And more text
|
||||
|
||||
```console
|
||||
// Use the command "live" and pass the language code as a CLI argument
|
||||
$ python ./scripts/docs.py live es
|
||||
|
||||
<span style="color: green;">[INFO]</span> Serving on http://127.0.0.1:8008
|
||||
<span style="color: green;">[INFO]</span> Start watching changes
|
||||
<span style="color: green;">[INFO]</span> Start detecting changes
|
||||
```
|
||||
|
||||
And even more text
|
||||
|
||||
```json
|
||||
{
|
||||
// This is a sample JSON code block
|
||||
"greeting": "Hello, world!" // Greeting
|
||||
}
|
||||
```
|
||||
|
||||
Диаграма Mermaid
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
stone(philosophers-stone) -->|requires| harry-1[harry v1]
|
||||
```
|
||||
@@ -0,0 +1,45 @@
|
||||
# Code blocks { #code-blocks }
|
||||
|
||||
Some text
|
||||
|
||||
```python
|
||||
# This is a sample Python code block
|
||||
def hello_world():
|
||||
# Comment with indentation
|
||||
print("Hello, world!") # Print greeting
|
||||
```
|
||||
|
||||
Some more text
|
||||
|
||||
The following block is missing first line:
|
||||
|
||||
```toml
|
||||
title = "TOML Example" # Title of the document
|
||||
```
|
||||
|
||||
And more text
|
||||
|
||||
```console
|
||||
// Use the command "live" and pass the language code as a CLI argument
|
||||
$ python ./scripts/docs.py live es
|
||||
|
||||
<span style="color: green;">[INFO]</span> Serving on http://127.0.0.1:8008
|
||||
<span style="color: green;">[INFO]</span> Start watching changes
|
||||
<span style="color: green;">[INFO]</span> Start detecting changes
|
||||
```
|
||||
|
||||
And even more text
|
||||
|
||||
```json
|
||||
{
|
||||
// This is a sample JSON code block
|
||||
"greeting": "Hello, world!" // Greeting
|
||||
}
|
||||
```
|
||||
|
||||
Диаграма Mermaid
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
stone(philosophers-stone) -->|requires| harry-1[harry v1]
|
||||
```
|
||||
@@ -0,0 +1,44 @@
|
||||
# Code blocks { #code-blocks }
|
||||
|
||||
Some text
|
||||
|
||||
```python
|
||||
# This is a sample Python code block
|
||||
def hello_world():
|
||||
# Comment with indentation
|
||||
print("Hello, world!") # Print greeting
|
||||
```
|
||||
|
||||
Some more text
|
||||
|
||||
```toml
|
||||
# This is a sample TOML code block
|
||||
title = "TOML Example" # Title of the document
|
||||
```
|
||||
|
||||
And more text
|
||||
|
||||
```console
|
||||
// Use the command "live" and pass the language code as a CLI argument
|
||||
$ python ./scripts/docs.py live es
|
||||
|
||||
<span style="color: green;">[INFO]</span> Serving on http://127.0.0.1:8008
|
||||
<span style="color: green;">[INFO]</span> Start watching changes
|
||||
<span style="color: green;">[INFO]</span> Start detecting changes
|
||||
```
|
||||
|
||||
And even more text
|
||||
|
||||
```json
|
||||
{
|
||||
// This is a sample JSON code block
|
||||
"greeting": "Hello, world!" // Greeting
|
||||
}
|
||||
```
|
||||
|
||||
Диаграма Mermaid
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
stone(philosophers-stone) -->|requires| harry-1[harry v1]
|
||||
```
|
||||
@@ -0,0 +1,44 @@
|
||||
# Code blocks { #code-blocks }
|
||||
|
||||
Some text
|
||||
|
||||
```python
|
||||
# This is a sample Python code block
|
||||
def hello_world():
|
||||
# Comment with indentation
|
||||
print("Hello, world!") # Print greeting
|
||||
```
|
||||
|
||||
Some more text
|
||||
|
||||
```toml
|
||||
# This is a sample TOML code block
|
||||
title = "TOML Example" # Title of the document
|
||||
```
|
||||
|
||||
And more text
|
||||
|
||||
```console
|
||||
// Use the command "live" and pass the language code as a CLI argument
|
||||
$ python ./scripts/docs.py live es
|
||||
|
||||
<span style="color: green;">[INFO]</span> Serving on http://127.0.0.1:8008
|
||||
<span style="color: green;">[INFO]</span> Start watching changes
|
||||
<span style="color: green;">[INFO]</span> Start detecting changes
|
||||
```
|
||||
|
||||
And even more text
|
||||
|
||||
```json
|
||||
{
|
||||
// This is a sample JSON code block
|
||||
"greeting": "Hello, world!" // Greeting
|
||||
}
|
||||
```
|
||||
|
||||
Диаграма Mermaid
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
stone(philosophers-stone) -->|требует| harry-1[harry v1]
|
||||
```
|
||||
@@ -0,0 +1,50 @@
|
||||
# Code blocks { #code-blocks }
|
||||
|
||||
Some text
|
||||
|
||||
```python
|
||||
# This is a sample Python code block
|
||||
def hello_world():
|
||||
# Comment with indentation
|
||||
print("Hello, world!") # Print greeting
|
||||
```
|
||||
|
||||
Some more text
|
||||
|
||||
```toml
|
||||
# This is a sample TOML code block
|
||||
title = "TOML Example" # Title of the document
|
||||
```
|
||||
|
||||
Extra code block
|
||||
|
||||
```
|
||||
$ cd my_project
|
||||
```
|
||||
|
||||
And more text
|
||||
|
||||
```console
|
||||
// Use the command "live" and pass the language code as a CLI argument
|
||||
$ python ./scripts/docs.py live es
|
||||
|
||||
<span style="color: green;">[INFO]</span> Serving on http://127.0.0.1:8008
|
||||
<span style="color: green;">[INFO]</span> Start watching changes
|
||||
<span style="color: green;">[INFO]</span> Start detecting changes
|
||||
```
|
||||
|
||||
And even more text
|
||||
|
||||
```json
|
||||
{
|
||||
// This is a sample JSON code block
|
||||
"greeting": "Hello, world!" // Greeting
|
||||
}
|
||||
```
|
||||
|
||||
Диаграма Mermaid
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
stone(philosophers-stone) -->|requires| harry-1[harry v1]
|
||||
```
|
||||
@@ -0,0 +1,41 @@
|
||||
# Code blocks { #code-blocks }
|
||||
|
||||
Some text
|
||||
|
||||
```python
|
||||
# This is a sample Python code block
|
||||
def hello_world():
|
||||
# Comment with indentation
|
||||
print("Hello, world!") # Print greeting
|
||||
```
|
||||
|
||||
Some more text
|
||||
|
||||
Missing code block...
|
||||
|
||||
And more text
|
||||
|
||||
```console
|
||||
// Use the command "live" and pass the language code as a CLI argument
|
||||
$ python ./scripts/docs.py live es
|
||||
|
||||
<span style="color: green;">[INFO]</span> Serving on http://127.0.0.1:8008
|
||||
<span style="color: green;">[INFO]</span> Start watching changes
|
||||
<span style="color: green;">[INFO]</span> Start detecting changes
|
||||
```
|
||||
|
||||
And even more text
|
||||
|
||||
```json
|
||||
{
|
||||
// This is a sample JSON code block
|
||||
"greeting": "Hello, world!" // Greeting
|
||||
}
|
||||
```
|
||||
|
||||
Диаграма Mermaid
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
stone(philosophers-stone) -->|requires| harry-1[harry v1]
|
||||
```
|
||||
@@ -0,0 +1,46 @@
|
||||
# Code blocks { #code-blocks }
|
||||
|
||||
Some text
|
||||
|
||||
```python
|
||||
# This is a sample Python code block
|
||||
def hello_world():
|
||||
# Comment with indentation
|
||||
print("Hello, world!") # Print greeting
|
||||
```
|
||||
|
||||
Some more text
|
||||
|
||||
The following block has wrong language code (should be TOML):
|
||||
|
||||
```yaml
|
||||
# This is a sample TOML code block
|
||||
title = "TOML Example" # Title of the document
|
||||
```
|
||||
|
||||
And more text
|
||||
|
||||
```console
|
||||
// Use the command "live" and pass the language code as a CLI argument
|
||||
$ python ./scripts/docs.py live es
|
||||
|
||||
<span style="color: green;">[INFO]</span> Serving on http://127.0.0.1:8008
|
||||
<span style="color: green;">[INFO]</span> Start watching changes
|
||||
<span style="color: green;">[INFO]</span> Start detecting changes
|
||||
```
|
||||
|
||||
And even more text
|
||||
|
||||
```json
|
||||
{
|
||||
// This is a sample JSON code block
|
||||
"greeting": "Hello, world!" // Greeting
|
||||
}
|
||||
```
|
||||
|
||||
Диаграма Mermaid
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
stone(philosophers-stone) -->|requires| harry-1[harry v1]
|
||||
```
|
||||
@@ -0,0 +1,46 @@
|
||||
# Code blocks { #code-blocks }
|
||||
|
||||
Some text
|
||||
|
||||
```python
|
||||
# This is a sample Python code block
|
||||
def hello_world():
|
||||
# Comment with indentation
|
||||
print("Hello, world!") # Print greeting
|
||||
```
|
||||
|
||||
Some more text
|
||||
|
||||
The following block has wrong language code (should be TOML):
|
||||
|
||||
```
|
||||
# This is a sample TOML code block
|
||||
title = "TOML Example" # Title of the document
|
||||
```
|
||||
|
||||
And more text
|
||||
|
||||
```console
|
||||
// Use the command "live" and pass the language code as a CLI argument
|
||||
$ python ./scripts/docs.py live es
|
||||
|
||||
<span style="color: green;">[INFO]</span> Serving on http://127.0.0.1:8008
|
||||
<span style="color: green;">[INFO]</span> Start watching changes
|
||||
<span style="color: green;">[INFO]</span> Start detecting changes
|
||||
```
|
||||
|
||||
And even more text
|
||||
|
||||
```json
|
||||
{
|
||||
// This is a sample JSON code block
|
||||
"greeting": "Hello, world!" // Greeting
|
||||
}
|
||||
```
|
||||
|
||||
Диаграма Mermaid
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
stone(philosophers-stone) -->|requires| harry-1[harry v1]
|
||||
```
|
||||
@@ -0,0 +1,58 @@
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from typer.testing import CliRunner
|
||||
|
||||
from scripts.translation_fixer import cli
|
||||
|
||||
data_path = Path(
|
||||
"scripts/tests/test_translation_fixer/test_code_blocks/data"
|
||||
).absolute()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"copy_test_files",
|
||||
[(f"{data_path}/en_doc.md", f"{data_path}/translated_doc_lines_number_gt.md")],
|
||||
indirect=True,
|
||||
)
|
||||
def test_gt(runner: CliRunner, root_dir: Path, copy_test_files):
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
["fix-pages", "docs/lang/docs/doc.md"],
|
||||
)
|
||||
assert result.exit_code == 1, result.output
|
||||
|
||||
fixed_content = (root_dir / "docs" / "lang" / "docs" / "doc.md").read_text()
|
||||
expected_content = Path(
|
||||
f"{data_path}/translated_doc_lines_number_gt.md"
|
||||
).read_text()
|
||||
|
||||
assert fixed_content == expected_content # Translated doc remains unchanged
|
||||
assert "Error processing docs/lang/docs/doc.md" in result.output
|
||||
assert (
|
||||
"Code block (lines 14-18) has different number of lines than the original block (5 vs 4)"
|
||||
) in result.output
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"copy_test_files",
|
||||
[(f"{data_path}/en_doc.md", f"{data_path}/translated_doc_lines_number_lt.md")],
|
||||
indirect=True,
|
||||
)
|
||||
def test_lt(runner: CliRunner, root_dir: Path, copy_test_files):
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
["fix-pages", "docs/lang/docs/doc.md"],
|
||||
)
|
||||
# assert result.exit_code == 1, result.output
|
||||
|
||||
fixed_content = (root_dir / "docs" / "lang" / "docs" / "doc.md").read_text()
|
||||
expected_content = Path(
|
||||
f"{data_path}/translated_doc_lines_number_lt.md"
|
||||
).read_text()
|
||||
|
||||
assert fixed_content == expected_content # Translated doc remains unchanged
|
||||
assert "Error processing docs/lang/docs/doc.md" in result.output
|
||||
assert (
|
||||
"Code block (lines 16-18) has different number of lines than the original block (3 vs 4)"
|
||||
) in result.output
|
||||
@@ -0,0 +1,59 @@
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from typer.testing import CliRunner
|
||||
|
||||
from scripts.translation_fixer import cli
|
||||
|
||||
data_path = Path(
|
||||
"scripts/tests/test_translation_fixer/test_code_blocks/data"
|
||||
).absolute()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"copy_test_files",
|
||||
[(f"{data_path}/en_doc.md", f"{data_path}/translated_doc_mermaid_translated.md")],
|
||||
indirect=True,
|
||||
)
|
||||
def test_translated(runner: CliRunner, root_dir: Path, copy_test_files):
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
["fix-pages", "docs/lang/docs/doc.md"],
|
||||
)
|
||||
assert result.exit_code == 0, result.output
|
||||
|
||||
fixed_content = (root_dir / "docs" / "lang" / "docs" / "doc.md").read_text()
|
||||
expected_content = Path(
|
||||
f"{data_path}/translated_doc_mermaid_translated.md"
|
||||
).read_text()
|
||||
|
||||
assert fixed_content == expected_content # Translated doc remains unchanged
|
||||
assert (
|
||||
"Skipping mermaid code block replacement (lines 41-44). This should be checked manually."
|
||||
) in result.output
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"copy_test_files",
|
||||
[
|
||||
(
|
||||
f"{data_path}/en_doc.md",
|
||||
f"{data_path}/translated_doc_mermaid_not_translated.md",
|
||||
)
|
||||
],
|
||||
indirect=True,
|
||||
)
|
||||
def test_not_translated(runner: CliRunner, root_dir: Path, copy_test_files):
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
["fix-pages", "docs/lang/docs/doc.md"],
|
||||
)
|
||||
assert result.exit_code == 0, result.output
|
||||
|
||||
fixed_content = (root_dir / "docs" / "lang" / "docs" / "doc.md").read_text()
|
||||
expected_content = Path(
|
||||
f"{data_path}/translated_doc_mermaid_not_translated.md"
|
||||
).read_text()
|
||||
|
||||
assert fixed_content == expected_content # Translated doc remains unchanged
|
||||
assert ("Skipping mermaid code block replacement") not in result.output
|
||||
@@ -0,0 +1,56 @@
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from typer.testing import CliRunner
|
||||
|
||||
from scripts.translation_fixer import cli
|
||||
|
||||
data_path = Path(
|
||||
"scripts/tests/test_translation_fixer/test_code_blocks/data"
|
||||
).absolute()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"copy_test_files",
|
||||
[(f"{data_path}/en_doc.md", f"{data_path}/translated_doc_number_gt.md")],
|
||||
indirect=True,
|
||||
)
|
||||
def test_gt(runner: CliRunner, root_dir: Path, copy_test_files):
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
["fix-pages", "docs/lang/docs/doc.md"],
|
||||
)
|
||||
assert result.exit_code == 1, result.output
|
||||
|
||||
fixed_content = (root_dir / "docs" / "lang" / "docs" / "doc.md").read_text()
|
||||
expected_content = Path(f"{data_path}/translated_doc_number_gt.md").read_text()
|
||||
|
||||
assert fixed_content == expected_content # Translated doc remains unchanged
|
||||
assert "Error processing docs/lang/docs/doc.md" in result.output
|
||||
assert (
|
||||
"Number of code blocks does not match the number "
|
||||
"in the original document (6 vs 5)"
|
||||
) in result.output
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"copy_test_files",
|
||||
[(f"{data_path}/en_doc.md", f"{data_path}/translated_doc_number_lt.md")],
|
||||
indirect=True,
|
||||
)
|
||||
def test_lt(runner: CliRunner, root_dir: Path, copy_test_files):
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
["fix-pages", "docs/lang/docs/doc.md"],
|
||||
)
|
||||
# assert result.exit_code == 1, result.output
|
||||
|
||||
fixed_content = (root_dir / "docs" / "lang" / "docs" / "doc.md").read_text()
|
||||
expected_content = Path(f"{data_path}/translated_doc_number_lt.md").read_text()
|
||||
|
||||
assert fixed_content == expected_content # Translated doc remains unchanged
|
||||
assert "Error processing docs/lang/docs/doc.md" in result.output
|
||||
assert (
|
||||
"Number of code blocks does not match the number "
|
||||
"in the original document (4 vs 5)"
|
||||
) in result.output
|
||||
@@ -0,0 +1,58 @@
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from typer.testing import CliRunner
|
||||
|
||||
from scripts.translation_fixer import cli
|
||||
|
||||
data_path = Path(
|
||||
"scripts/tests/test_translation_fixer/test_code_blocks/data"
|
||||
).absolute()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"copy_test_files",
|
||||
[(f"{data_path}/en_doc.md", f"{data_path}/translated_doc_wrong_lang_code.md")],
|
||||
indirect=True,
|
||||
)
|
||||
def test_wrong_lang_code_1(runner: CliRunner, root_dir: Path, copy_test_files):
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
["fix-pages", "docs/lang/docs/doc.md"],
|
||||
)
|
||||
assert result.exit_code == 1, result.output
|
||||
|
||||
fixed_content = (root_dir / "docs" / "lang" / "docs" / "doc.md").read_text()
|
||||
expected_content = Path(
|
||||
f"{data_path}/translated_doc_wrong_lang_code.md"
|
||||
).read_text()
|
||||
|
||||
assert fixed_content == expected_content # Translated doc remains unchanged
|
||||
assert "Error processing docs/lang/docs/doc.md" in result.output
|
||||
assert (
|
||||
"Code block (lines 16-19) has different language than the original block ('yaml' vs 'toml')"
|
||||
) in result.output
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"copy_test_files",
|
||||
[(f"{data_path}/en_doc.md", f"{data_path}/translated_doc_wrong_lang_code_2.md")],
|
||||
indirect=True,
|
||||
)
|
||||
def test_wrong_lang_code_2(runner: CliRunner, root_dir: Path, copy_test_files):
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
["fix-pages", "docs/lang/docs/doc.md"],
|
||||
)
|
||||
assert result.exit_code == 1, result.output
|
||||
|
||||
fixed_content = (root_dir / "docs" / "lang" / "docs" / "doc.md").read_text()
|
||||
expected_content = Path(
|
||||
f"{data_path}/translated_doc_wrong_lang_code_2.md"
|
||||
).read_text()
|
||||
|
||||
assert fixed_content == expected_content # Translated doc remains unchanged
|
||||
assert "Error processing docs/lang/docs/doc.md" in result.output
|
||||
assert (
|
||||
"Code block (lines 16-19) has different language than the original block ('' vs 'toml')"
|
||||
) in result.output
|
||||
@@ -0,0 +1,13 @@
|
||||
# Header
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *}
|
||||
|
||||
Some text
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *}
|
||||
|
||||
Some more text
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *}
|
||||
|
||||
And even more text
|
||||
@@ -0,0 +1,15 @@
|
||||
# Header
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *}
|
||||
|
||||
Some text
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *}
|
||||
|
||||
Some more text
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *}
|
||||
|
||||
And even more text
|
||||
|
||||
{* ../../docs_src/python_types/tutorial001_py39.py *}
|
||||
@@ -0,0 +1,13 @@
|
||||
# Header
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *}
|
||||
|
||||
Some text
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *}
|
||||
|
||||
Some more text
|
||||
|
||||
...
|
||||
|
||||
And even more text
|
||||
@@ -0,0 +1,56 @@
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from typer.testing import CliRunner
|
||||
|
||||
from scripts.translation_fixer import cli
|
||||
|
||||
data_path = Path(
|
||||
"scripts/tests/test_translation_fixer/test_code_includes/data"
|
||||
).absolute()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"copy_test_files",
|
||||
[(f"{data_path}/en_doc.md", f"{data_path}/translated_doc_number_gt.md")],
|
||||
indirect=True,
|
||||
)
|
||||
def test_gt(runner: CliRunner, root_dir: Path, copy_test_files):
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
["fix-pages", "docs/lang/docs/doc.md"],
|
||||
)
|
||||
assert result.exit_code == 1
|
||||
|
||||
fixed_content = (root_dir / "docs" / "lang" / "docs" / "doc.md").read_text()
|
||||
expected_content = Path(f"{data_path}/translated_doc_number_gt.md").read_text()
|
||||
|
||||
assert fixed_content == expected_content # Translated doc remains unchanged
|
||||
assert "Error processing docs/lang/docs/doc.md" in result.output
|
||||
assert (
|
||||
"Number of code include placeholders does not match the number of code includes "
|
||||
"in the original document (4 vs 3)"
|
||||
) in result.output
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"copy_test_files",
|
||||
[(f"{data_path}/en_doc.md", f"{data_path}/translated_doc_number_lt.md")],
|
||||
indirect=True,
|
||||
)
|
||||
def test_lt(runner: CliRunner, root_dir: Path, copy_test_files):
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
["fix-pages", "docs/lang/docs/doc.md"],
|
||||
)
|
||||
assert result.exit_code == 1
|
||||
|
||||
fixed_content = (root_dir / "docs" / "lang" / "docs" / "doc.md").read_text()
|
||||
expected_content = Path(f"{data_path}/translated_doc_number_lt.md").read_text()
|
||||
|
||||
assert fixed_content == expected_content # Translated doc remains unchanged
|
||||
assert "Error processing docs/lang/docs/doc.md" in result.output
|
||||
assert (
|
||||
"Number of code include placeholders does not match the number of code includes "
|
||||
"in the original document (2 vs 3)"
|
||||
) in result.output
|
||||
@@ -0,0 +1,244 @@
|
||||
# Test translation fixer tool { #test-translation-fixer }
|
||||
|
||||
## Code blocks with and without comments { #code-blocks-with-and-without-comments }
|
||||
|
||||
This is a test page for the translation fixer tool.
|
||||
|
||||
### Code blocks with comments { #code-blocks-with-comments }
|
||||
|
||||
The following code blocks include comments in different styles.
|
||||
Fixer tool should fix content, but preserve comments correctly.
|
||||
|
||||
```python
|
||||
# This is a sample Python code block
|
||||
def hello_world():
|
||||
# Comment with indentation
|
||||
print("Hello, world!") # Print greeting
|
||||
```
|
||||
|
||||
```toml
|
||||
# This is a sample TOML code block
|
||||
title = "TOML Example" # Title of the document
|
||||
```
|
||||
|
||||
```console
|
||||
// Use the command "live" and pass the language code as a CLI argument
|
||||
$ python ./scripts/docs.py live es
|
||||
|
||||
<span style="color: green;">[INFO]</span> Serving on http://127.0.0.1:8008
|
||||
<span style="color: green;">[INFO]</span> Start watching changes
|
||||
<span style="color: green;">[INFO]</span> Start detecting changes
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
// This is a sample JSON code block
|
||||
"greeting": "Hello, world!" // Greeting
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Code blocks with comments where language uses different comment styles { #code-blocks-with-different-comment-styles }
|
||||
|
||||
The following code blocks include comments in different styles based on the language.
|
||||
Fixer tool will not preserve comments in these blocks.
|
||||
|
||||
```json
|
||||
{
|
||||
# This is a sample JSON code block
|
||||
"greeting": "Hello, world!" # Print greeting
|
||||
}
|
||||
```
|
||||
|
||||
```console
|
||||
# This is a sample console code block
|
||||
$ echo "Hello, world!" # Print greeting
|
||||
```
|
||||
|
||||
```toml
|
||||
// This is a sample TOML code block
|
||||
title = "TOML Example" // Title of the document
|
||||
```
|
||||
|
||||
|
||||
### Code blocks with comments with unsupported languages or without language specified { #code-blocks-with-unsupported-languages }
|
||||
|
||||
The following code blocks use unsupported languages for comment preservation.
|
||||
Fixer tool will not preserve comments in these blocks.
|
||||
|
||||
```javascript
|
||||
// This is a sample JavaScript code block
|
||||
console.log("Hello, world!"); // Print greeting
|
||||
```
|
||||
|
||||
```
|
||||
# This is a sample console code block
|
||||
$ echo "Hello, world!" # Print greeting
|
||||
```
|
||||
|
||||
```
|
||||
// This is a sample console code block
|
||||
$ echo "Hello, world!" // Print greeting
|
||||
```
|
||||
|
||||
|
||||
### Code blocks with comments that don't follow pattern { #code-blocks-with-comments-without-pattern }
|
||||
|
||||
Fixer tool expects comments that follow specific pattern:
|
||||
|
||||
- For hash-style comments: comment starts with `# ` (hash following by whitespace) in the beginning of the string or after a whitespace.
|
||||
- For slash-style comments: comment starts with `// ` (two slashes following by whitespace) in the beginning of the string or after a whitespace.
|
||||
|
||||
If comment doesn't follow this pattern, fixer tool will not preserve it.
|
||||
|
||||
```python
|
||||
#Function declaration
|
||||
def hello_world():# Print greeting
|
||||
print("Hello, world!") #Print greeting without space after hash
|
||||
```
|
||||
|
||||
```console
|
||||
//Function declaration
|
||||
def hello_world():// Print greeting
|
||||
print("Hello, world!") //Print greeting without space after slashes
|
||||
```
|
||||
|
||||
## Code blocks with quadruple backticks { #code-blocks-with-quadruple-backticks }
|
||||
|
||||
The following code block uses quadruple backticks.
|
||||
|
||||
````python
|
||||
# Hello world function
|
||||
def hello_world():
|
||||
print("Hello, world!") # Print greeting
|
||||
````
|
||||
|
||||
### Backticks number mismatch is fixable { #backticks-number-mismatch-is-fixable }
|
||||
|
||||
The following code block has triple backticks in the original document, but quadruple backticks in the translated document.
|
||||
It will be fixed by the fixer tool (will convert to triple backticks).
|
||||
|
||||
```Python
|
||||
# Some Python code
|
||||
```
|
||||
|
||||
### Triple backticks inside quadruple backticks { #triple-backticks-inside-quadruple-backticks }
|
||||
|
||||
Comments inside nested code block will NOT be preserved.
|
||||
|
||||
````
|
||||
Here is a code block with quadruple backticks that contains triple backticks inside:
|
||||
|
||||
```python
|
||||
# This is a sample Python code block
|
||||
def hello_world():
|
||||
print("Hello, world!") # Print greeting
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
# Code includes { #code-includes }
|
||||
|
||||
## Simple code includes { #simple-code-includes }
|
||||
|
||||
{* ../../docs_src/python_types/tutorial001_py39.py *}
|
||||
|
||||
{* ../../docs_src/python_types/tutorial002_py39.py *}
|
||||
|
||||
|
||||
## Code includes with highlighting { #code-includes-with-highlighting }
|
||||
|
||||
{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *}
|
||||
|
||||
{* ../../docs_src/python_types/tutorial006_py39.py hl[10] *}
|
||||
|
||||
|
||||
## Code includes with line ranges { #code-includes-with-line-ranges }
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *}
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] *}
|
||||
|
||||
|
||||
## Code includes with line ranges and highlighting { #code-includes-with-line-ranges-and-highlighting }
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *}
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial015_an_py310.py ln[10:15] hl[12:14] *}
|
||||
|
||||
|
||||
## Code includes qith title { #code-includes-with-title }
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *}
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *}
|
||||
|
||||
## Code includes with unknown attributes { #code-includes-with-unknown-attributes }
|
||||
|
||||
{* ../../docs_src/python_types/tutorial001_py39.py unknown[123] *}
|
||||
|
||||
## Some more code includes to test fixing { #some-more-code-includes-to-test-fixing }
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *}
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *}
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *}
|
||||
|
||||
|
||||
|
||||
# Links { #links }
|
||||
|
||||
## Markdown-style links { #markdown-style-links }
|
||||
|
||||
This is a [Markdown link](https://example.com) to an external site.
|
||||
|
||||
This is a link with attributes: [**FastAPI** Project Generators](project-generation.md){.internal-link target=_blank}
|
||||
|
||||
This is a link to the main FastAPI site: [FastAPI](https://fastapi.tiangolo.com) - tool should add language code to the URL.
|
||||
|
||||
This is a link to one of the pages on FastAPI site: [How to](https://fastapi.tiangolo.com/how-to/) - tool should add language code to the URL.
|
||||
|
||||
Link to test wrong attribute: [**FastAPI** Project Generators](project-generation.md){.internal-link} - tool should fix the attribute.
|
||||
|
||||
Link with a title: [Example](https://example.com "Example site") - URL will be fixed, title preserved.
|
||||
|
||||
### Markdown link to static assets { #markdown-link-to-static-assets }
|
||||
|
||||
These are links to static assets:
|
||||
|
||||
* [FastAPI Logo](https://fastapi.tiangolo.com/img/fastapi-logo.png)
|
||||
* [FastAPI CSS](https://fastapi.tiangolo.com/css/fastapi.css)
|
||||
* [FastAPI JS](https://fastapi.tiangolo.com/js/fastapi.js)
|
||||
|
||||
Tool should NOT add language code to their URLs.
|
||||
|
||||
## HTML-style links { #html-style-links }
|
||||
|
||||
This is an <a href="https://example.com" target="_blank" class="external-link">HTML link</a> to an external site.
|
||||
|
||||
This is an <a href="https://fastapi.tiangolo.com">link to the main FastAPI site</a> - tool should add language code to the URL.
|
||||
|
||||
This is an <a href="https://fastapi.tiangolo.com/how-to/">link to one of the pages on FastAPI site</a> - tool should add language code to the URL.
|
||||
|
||||
Link to test wrong attribute: <a href="project-generation.md" class="internal-link">**FastAPI** Project Generators</a> - tool should fix the attribute.
|
||||
|
||||
### HTML links to static assets { #html-links-to-static-assets }
|
||||
|
||||
These are links to static assets:
|
||||
|
||||
* <a href="https://fastapi.tiangolo.com/img/fastapi-logo.png">FastAPI Logo</a>
|
||||
* <a href="https://fastapi.tiangolo.com/css/fastapi.css">FastAPI CSS</a>
|
||||
* <a href="https://fastapi.tiangolo.com/js/fastapi.js">FastAPI JS</a>
|
||||
|
||||
Tool should NOT add language code to their URLs.
|
||||
|
||||
# Header (with HTML link to <a href="https://tiangolo.com">tiangolo.com</a>) { #header-with-html-link-to-tiangolo-com }
|
||||
|
||||
#Not a header
|
||||
|
||||
```Python
|
||||
# Also not a header
|
||||
```
|
||||
|
||||
Some text
|
||||
@@ -0,0 +1,240 @@
|
||||
# Тестовый инструмент исправления переводов { #test-translation-fixer }
|
||||
|
||||
## Блоки кода с комментариями и без комментариев { #code-blocks-with-and-without-comments }
|
||||
|
||||
Это тестовая страница для инструмента исправления переводов.
|
||||
|
||||
### Блоки кода с комментариями { #code-blocks-with-comments }
|
||||
|
||||
Следующие блоки кода содержат комментарии в разных стилях.
|
||||
Инструмент исправления должен исправлять содержимое, но корректно сохранять комментарии.
|
||||
|
||||
```python
|
||||
# Это пример блока кода на Python
|
||||
def hello_world():
|
||||
# Комментарий с отступом
|
||||
print("Hello, world!") # Печать приветствия
|
||||
```
|
||||
|
||||
```toml
|
||||
# Это пример блока кода на TOML
|
||||
title = "TOML Example" # Заголовок документа
|
||||
```
|
||||
|
||||
```console
|
||||
// Используйте команду "live" и передайте код языка в качестве аргумента CLI
|
||||
$ python ./scripts/docs.py live es
|
||||
|
||||
<span style="color: green;">[INFO]</span> Serving on http://127.0.0.1:8008
|
||||
<span style="color: green;">[INFO]</span> Start watching changes
|
||||
<span style="color: green;">[INFO]</span> Start detecting changes
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
// Это пример блока кода на JSON
|
||||
"greeting": "Hello, world!" // Печать приветствия
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Блоки кода с комментариями, где язык использует другие стили комментариев { #code-blocks-with-different-comment-styles }
|
||||
|
||||
Следующие блоки кода содержат комментарии в разных стилях в зависимости от языка.
|
||||
Инструмент исправления не будет сохранять комментарии в этих блоках.
|
||||
|
||||
```json
|
||||
{
|
||||
# Это пример блока кода на JSON
|
||||
"greeting": "Hello, world!" # Печать приветствия
|
||||
}
|
||||
```
|
||||
|
||||
```console
|
||||
# Это пример блока кода консоли
|
||||
$ echo "Hello, world!" # Печать приветствия
|
||||
```
|
||||
|
||||
```toml
|
||||
// Это пример блока кода на TOML
|
||||
title = "TOML Example" // Заголовок документа
|
||||
```
|
||||
|
||||
### Блоки кода с комментариями на неподдерживаемых языках или без указания языка { #code-blocks-with-unsupported-languages }
|
||||
|
||||
Следующие блоки кода используют неподдерживаемые языки для сохранения комментариев.
|
||||
Инструмент исправления не будет сохранять комментарии в этих блоках.
|
||||
|
||||
```javascript
|
||||
// Это пример блока кода на JavaScript
|
||||
console.log("Hello, world!"); // Печать приветствия
|
||||
```
|
||||
|
||||
```
|
||||
# Это пример блока кода консоли
|
||||
$ echo "Hello, world!" # Печать приветствия
|
||||
```
|
||||
|
||||
```
|
||||
// Это пример блока кода консоли
|
||||
$ echo "Hello, world!" // Печать приветствия
|
||||
```
|
||||
|
||||
### Блоки кода с комментариями, которые не соответствуют шаблону { #code-blocks-with-comments-without-pattern }
|
||||
|
||||
Инструмент исправления ожидает комментарии, которые соответствуют определённому шаблону:
|
||||
|
||||
- Для комментариев в стиле с решёткой: комментарий начинается с `# ` (решётка, затем пробел) в начале строки или после пробела.
|
||||
- Для комментариев в стиле со слешами: комментарий начинается с `// ` (два слеша, затем пробел) в начале строки или после пробела.
|
||||
|
||||
Если комментарий не соответствует этому шаблону, инструмент исправления не будет его сохранять.
|
||||
|
||||
```python
|
||||
#Объявление функции
|
||||
def hello_world():# Печать приветствия
|
||||
print("Hello, world!") #Печать приветствия без пробела после решётки
|
||||
```
|
||||
|
||||
```console
|
||||
//Объявление функции
|
||||
def hello_world():// Печать приветствия
|
||||
print("Hello, world!") //Печать приветствия без пробела после слешей
|
||||
```
|
||||
|
||||
## Блок кода с четырёхкратными обратными кавычками { #code-blocks-with-quadruple-backticks }
|
||||
|
||||
Следующий блок кода содержит четырёхкратные обратные кавычки.
|
||||
|
||||
````python
|
||||
# Функция приветствия
|
||||
def hello_world():
|
||||
print("Hello, world") # Печать приветствия
|
||||
````
|
||||
|
||||
### Несоответствие обратных кавычек фиксится { #backticks-number-mismatch-is-fixable }
|
||||
|
||||
Следующий блок кода имеет тройные обратные кавычки в оригинальном документе, но четырёхкратные обратные кавычки в переведённом документе.
|
||||
Это будет исправлено инструментом исправления (будет преобразовано в тройные обратные кавычки).
|
||||
|
||||
````Python
|
||||
# Немного кода на Python
|
||||
````
|
||||
|
||||
### Блок кода в тройных обратных кавычка внутри блока кода в четырёхкратных обратных кавычках { #triple-backticks-inside-quadruple-backticks }
|
||||
|
||||
Комментарии внутри вложенного блока кода в тройных обратных кавычках НЕ БУДУТ сохранены.
|
||||
|
||||
````
|
||||
Here is a code block with quadruple backticks that contains triple backticks inside:
|
||||
|
||||
```python
|
||||
# Этот комментарий НЕ будет сохранён
|
||||
def hello_world():
|
||||
print("Hello, world") # Как и этот комментарий
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
# Включения кода { #code-includes }
|
||||
|
||||
## Простые включения кода { #simple-code-includes }
|
||||
|
||||
{* ../../docs_src/python_types/tutorial001_py39.py *}
|
||||
|
||||
{* ../../docs_src/python_types/tutorial002_py39.py *}
|
||||
|
||||
|
||||
## Включения кода с подсветкой { #code-includes-with-highlighting }
|
||||
|
||||
{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *}
|
||||
|
||||
{* ../../docs_src/python_types/tutorial006_py39.py hl[10] *}
|
||||
|
||||
|
||||
## Включения кода с диапазонами строк { #code-includes-with-line-ranges }
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *}
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] *}
|
||||
|
||||
|
||||
## Включения кода с диапазонами строк и подсветкой { #code-includes-with-line-ranges-and-highlighting }
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *}
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial015_an_py310.py ln[10:15] hl[12:14] *}
|
||||
|
||||
|
||||
## Включения кода с заголовком { #code-includes-with-title }
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *}
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *}
|
||||
|
||||
## Включения кода с неизвестными атрибутами { #code-includes-with-unknown-attributes }
|
||||
|
||||
{* ../../docs_src/python_types/tutorial001_py39.py unknown[123] *}
|
||||
|
||||
## Ещё включения кода для тестирования исправления { #some-more-code-includes-to-test-fixing }
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19 : 21] *}
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/wrong.py hl[3] title["app/internal/admin.py"] *}
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[1:30] hl[1:10] *}
|
||||
|
||||
# Ссылки { #links }
|
||||
|
||||
## Ссылки в стиле Markdown { #markdown-style-links }
|
||||
|
||||
Это [Markdown-ссылка](https://example.com) на внешний сайт.
|
||||
|
||||
Это ссылка с атрибутами: [**FastAPI** генераторы проектов](project-generation.md){.internal-link target=_blank}
|
||||
|
||||
Это ссылка на основной сайт FastAPI: [FastAPI](https://fastapi.tiangolo.com) — инструмент должен добавить код языка в URL.
|
||||
|
||||
Это ссылка на одну из страниц на сайте FastAPI: [How to](https://fastapi.tiangolo.com/how-to) — инструмент должен добавить код языка в URL.
|
||||
|
||||
Ссылка для тестирования неправильного атрибута: [**FastAPI** генераторы проектов](project-generation.md){.external-link} - инструмент должен исправить атрибут.
|
||||
|
||||
Ссылка с заголовком: [Пример](http://example.com/ "Сайт для примера") - URL будет исправлен инструментом, заголовок сохранится.
|
||||
|
||||
### Markdown ссылки на статические ресурсы { #markdown-link-to-static-assets }
|
||||
|
||||
Это ссылки на статические ресурсы:
|
||||
|
||||
* [FastAPI Logo](https://fastapi.tiangolo.com/img/fastapi-logo.png)
|
||||
* [FastAPI CSS](https://fastapi.tiangolo.com/css/fastapi.css)
|
||||
* [FastAPI JS](https://fastapi.tiangolo.com/js/fastapi.js)
|
||||
|
||||
Инструмент НЕ должен добавлять код языка в их URL.
|
||||
|
||||
## Ссылки в стиле HTML { #html-style-links }
|
||||
|
||||
Это <a href="https://example.com" target="_blank" class="external-link">HTML-ссылка</a> на внешний сайт.
|
||||
|
||||
Это <a href="https://fastapi.tiangolo.com">ссылка на основной сайт FastAPI</a> — инструмент должен добавить код языка в URL.
|
||||
|
||||
Это <a href="https://fastapi.tiangolo.com/how-to/">ссылка на одну из страниц на сайте FastAPI</a> — инструмент должен добавить код языка в URL.
|
||||
|
||||
Ссылка для тестирования неправильного атрибута: <a href="project-generation.md" class="external-link">**FastAPI** генераторы проектов</a> - инструмент должен исправить атрибут.
|
||||
|
||||
### HTML ссылки на статические ресурсы { #html-links-to-static-assets }
|
||||
|
||||
Это ссылки на статические ресурсы:
|
||||
|
||||
* <a href="https://fastapi.tiangolo.com/img/fastapi-logo.png">FastAPI Logo</a>
|
||||
* <a href="https://fastapi.tiangolo.com/css/fastapi.css">FastAPI CSS</a>
|
||||
* <a href="https://fastapi.tiangolo.com/js/fastapi.js">FastAPI JS</a>
|
||||
|
||||
Инструмент НЕ должен добавлять код языка в их URL.
|
||||
|
||||
# Заголовок (с HTML ссылкой на <a href="https://tiangolo.com">tiangolo.com</a>) { #header-5 }
|
||||
|
||||
#Не заголовок
|
||||
|
||||
```Python
|
||||
# Также не заголовок
|
||||
```
|
||||
|
||||
Немного текста
|
||||
@@ -0,0 +1,240 @@
|
||||
# Тестовый инструмент исправления переводов { #test-translation-fixer }
|
||||
|
||||
## Блоки кода с комментариями и без комментариев { #code-blocks-with-and-without-comments }
|
||||
|
||||
Это тестовая страница для инструмента исправления переводов.
|
||||
|
||||
### Блоки кода с комментариями { #code-blocks-with-comments }
|
||||
|
||||
Следующие блоки кода содержат комментарии в разных стилях.
|
||||
Инструмент исправления должен исправлять содержимое, но корректно сохранять комментарии.
|
||||
|
||||
```python
|
||||
# Это пример блока кода на Python
|
||||
def hello_world():
|
||||
# Комментарий с отступом
|
||||
print("Hello, world!") # Печать приветствия
|
||||
```
|
||||
|
||||
```toml
|
||||
# Это пример блока кода на TOML
|
||||
title = "TOML Example" # Заголовок документа
|
||||
```
|
||||
|
||||
```console
|
||||
// Используйте команду "live" и передайте код языка в качестве аргумента CLI
|
||||
$ python ./scripts/docs.py live es
|
||||
|
||||
<span style="color: green;">[INFO]</span> Serving on http://127.0.0.1:8008
|
||||
<span style="color: green;">[INFO]</span> Start watching changes
|
||||
<span style="color: green;">[INFO]</span> Start detecting changes
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
// Это пример блока кода на JSON
|
||||
"greeting": "Hello, world!" // Печать приветствия
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Блоки кода с комментариями, где язык использует другие стили комментариев { #code-blocks-with-different-comment-styles }
|
||||
|
||||
Следующие блоки кода содержат комментарии в разных стилях в зависимости от языка.
|
||||
Инструмент исправления не будет сохранять комментарии в этих блоках.
|
||||
|
||||
```json
|
||||
{
|
||||
# This is a sample JSON code block
|
||||
"greeting": "Hello, world!" # Print greeting
|
||||
}
|
||||
```
|
||||
|
||||
```console
|
||||
# This is a sample console code block
|
||||
$ echo "Hello, world!" # Print greeting
|
||||
```
|
||||
|
||||
```toml
|
||||
// This is a sample TOML code block
|
||||
title = "TOML Example" // Title of the document
|
||||
```
|
||||
|
||||
### Блоки кода с комментариями на неподдерживаемых языках или без указания языка { #code-blocks-with-unsupported-languages }
|
||||
|
||||
Следующие блоки кода используют неподдерживаемые языки для сохранения комментариев.
|
||||
Инструмент исправления не будет сохранять комментарии в этих блоках.
|
||||
|
||||
```javascript
|
||||
// This is a sample JavaScript code block
|
||||
console.log("Hello, world!"); // Print greeting
|
||||
```
|
||||
|
||||
```
|
||||
# This is a sample console code block
|
||||
$ echo "Hello, world!" # Print greeting
|
||||
```
|
||||
|
||||
```
|
||||
// This is a sample console code block
|
||||
$ echo "Hello, world!" // Print greeting
|
||||
```
|
||||
|
||||
### Блоки кода с комментариями, которые не соответствуют шаблону { #code-blocks-with-comments-without-pattern }
|
||||
|
||||
Инструмент исправления ожидает комментарии, которые соответствуют определённому шаблону:
|
||||
|
||||
- Для комментариев в стиле с решёткой: комментарий начинается с `# ` (решётка, затем пробел) в начале строки или после пробела.
|
||||
- Для комментариев в стиле со слешами: комментарий начинается с `// ` (два слеша, затем пробел) в начале строки или после пробела.
|
||||
|
||||
Если комментарий не соответствует этому шаблону, инструмент исправления не будет его сохранять.
|
||||
|
||||
```python
|
||||
#Function declaration
|
||||
def hello_world():# Print greeting
|
||||
print("Hello, world!") #Print greeting without space after hash
|
||||
```
|
||||
|
||||
```console
|
||||
//Function declaration
|
||||
def hello_world():// Print greeting
|
||||
print("Hello, world!") //Print greeting without space after slashes
|
||||
```
|
||||
|
||||
## Блок кода с четырёхкратными обратными кавычками { #code-blocks-with-quadruple-backticks }
|
||||
|
||||
Следующий блок кода содержит четырёхкратные обратные кавычки.
|
||||
|
||||
````python
|
||||
# Функция приветствия
|
||||
def hello_world():
|
||||
print("Hello, world!") # Печать приветствия
|
||||
````
|
||||
|
||||
### Несоответствие обратных кавычек фиксится { #backticks-number-mismatch-is-fixable }
|
||||
|
||||
Следующий блок кода имеет тройные обратные кавычки в оригинальном документе, но четырёхкратные обратные кавычки в переведённом документе.
|
||||
Это будет исправлено инструментом исправления (будет преобразовано в тройные обратные кавычки).
|
||||
|
||||
```Python
|
||||
# Немного кода на Python
|
||||
```
|
||||
|
||||
### Блок кода в тройных обратных кавычка внутри блока кода в четырёхкратных обратных кавычках { #triple-backticks-inside-quadruple-backticks }
|
||||
|
||||
Комментарии внутри вложенного блока кода в тройных обратных кавычках НЕ БУДУТ сохранены.
|
||||
|
||||
````
|
||||
Here is a code block with quadruple backticks that contains triple backticks inside:
|
||||
|
||||
```python
|
||||
# This is a sample Python code block
|
||||
def hello_world():
|
||||
print("Hello, world!") # Print greeting
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
# Включения кода { #code-includes }
|
||||
|
||||
## Простые включения кода { #simple-code-includes }
|
||||
|
||||
{* ../../docs_src/python_types/tutorial001_py39.py *}
|
||||
|
||||
{* ../../docs_src/python_types/tutorial002_py39.py *}
|
||||
|
||||
|
||||
## Включения кода с подсветкой { #code-includes-with-highlighting }
|
||||
|
||||
{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *}
|
||||
|
||||
{* ../../docs_src/python_types/tutorial006_py39.py hl[10] *}
|
||||
|
||||
|
||||
## Включения кода с диапазонами строк { #code-includes-with-line-ranges }
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *}
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] *}
|
||||
|
||||
|
||||
## Включения кода с диапазонами строк и подсветкой { #code-includes-with-line-ranges-and-highlighting }
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *}
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial015_an_py310.py ln[10:15] hl[12:14] *}
|
||||
|
||||
|
||||
## Включения кода с заголовком { #code-includes-with-title }
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *}
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *}
|
||||
|
||||
## Включения кода с неизвестными атрибутами { #code-includes-with-unknown-attributes }
|
||||
|
||||
{* ../../docs_src/python_types/tutorial001_py39.py unknown[123] *}
|
||||
|
||||
## Ещё включения кода для тестирования исправления { #some-more-code-includes-to-test-fixing }
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *}
|
||||
|
||||
{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *}
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *}
|
||||
|
||||
# Ссылки { #links }
|
||||
|
||||
## Ссылки в стиле Markdown { #markdown-style-links }
|
||||
|
||||
Это [Markdown-ссылка](https://example.com) на внешний сайт.
|
||||
|
||||
Это ссылка с атрибутами: [**FastAPI** генераторы проектов](project-generation.md){.internal-link target=_blank}
|
||||
|
||||
Это ссылка на основной сайт FastAPI: [FastAPI](https://fastapi.tiangolo.com/lang) — инструмент должен добавить код языка в URL.
|
||||
|
||||
Это ссылка на одну из страниц на сайте FastAPI: [How to](https://fastapi.tiangolo.com/lang/how-to/) — инструмент должен добавить код языка в URL.
|
||||
|
||||
Ссылка для тестирования неправильного атрибута: [**FastAPI** генераторы проектов](project-generation.md){.internal-link} - инструмент должен исправить атрибут.
|
||||
|
||||
Ссылка с заголовком: [Пример](https://example.com "Сайт для примера") - URL будет исправлен инструментом, заголовок сохранится.
|
||||
|
||||
### Markdown ссылки на статические ресурсы { #markdown-link-to-static-assets }
|
||||
|
||||
Это ссылки на статические ресурсы:
|
||||
|
||||
* [FastAPI Logo](https://fastapi.tiangolo.com/img/fastapi-logo.png)
|
||||
* [FastAPI CSS](https://fastapi.tiangolo.com/css/fastapi.css)
|
||||
* [FastAPI JS](https://fastapi.tiangolo.com/js/fastapi.js)
|
||||
|
||||
Инструмент НЕ должен добавлять код языка в их URL.
|
||||
|
||||
## Ссылки в стиле HTML { #html-style-links }
|
||||
|
||||
Это <a href="https://example.com" target="_blank" class="external-link">HTML-ссылка</a> на внешний сайт.
|
||||
|
||||
Это <a href="https://fastapi.tiangolo.com/lang">ссылка на основной сайт FastAPI</a> — инструмент должен добавить код языка в URL.
|
||||
|
||||
Это <a href="https://fastapi.tiangolo.com/lang/how-to/">ссылка на одну из страниц на сайте FastAPI</a> — инструмент должен добавить код языка в URL.
|
||||
|
||||
Ссылка для тестирования неправильного атрибута: <a href="project-generation.md" class="internal-link">**FastAPI** генераторы проектов</a> - инструмент должен исправить атрибут.
|
||||
|
||||
### HTML ссылки на статические ресурсы { #html-links-to-static-assets }
|
||||
|
||||
Это ссылки на статические ресурсы:
|
||||
|
||||
* <a href="https://fastapi.tiangolo.com/img/fastapi-logo.png">FastAPI Logo</a>
|
||||
* <a href="https://fastapi.tiangolo.com/css/fastapi.css">FastAPI CSS</a>
|
||||
* <a href="https://fastapi.tiangolo.com/js/fastapi.js">FastAPI JS</a>
|
||||
|
||||
Инструмент НЕ должен добавлять код языка в их URL.
|
||||
|
||||
# Заголовок (с HTML ссылкой на <a href="https://tiangolo.com">tiangolo.com</a>) { #header-with-html-link-to-tiangolo-com }
|
||||
|
||||
#Не заголовок
|
||||
|
||||
```Python
|
||||
# Также не заголовок
|
||||
```
|
||||
|
||||
Немного текста
|
||||
@@ -0,0 +1,30 @@
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from typer.testing import CliRunner
|
||||
|
||||
from scripts.translation_fixer import cli
|
||||
|
||||
data_path = Path(
|
||||
"scripts/tests/test_translation_fixer/test_complex_doc/data"
|
||||
).absolute()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"copy_test_files",
|
||||
[(f"{data_path}/en_doc.md", f"{data_path}/translated_doc.md")],
|
||||
indirect=True,
|
||||
)
|
||||
def test_fix(runner: CliRunner, root_dir: Path, copy_test_files):
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
["fix-pages", "docs/lang/docs/doc.md"],
|
||||
)
|
||||
assert result.exit_code == 0, result.output
|
||||
|
||||
fixed_content = (root_dir / "docs" / "lang" / "docs" / "doc.md").read_text()
|
||||
expected_content = (data_path / "translated_doc_expected.md").read_text()
|
||||
assert fixed_content == expected_content
|
||||
|
||||
assert "Fixing multiline code blocks in" in result.output
|
||||
assert "Fixing markdown links in" in result.output
|
||||
@@ -0,0 +1,19 @@
|
||||
# Header 1 { #header-1 }
|
||||
|
||||
Some text
|
||||
|
||||
## Header 2 { #header-2 }
|
||||
|
||||
Some more text
|
||||
|
||||
### Header 3 { #header-3 }
|
||||
|
||||
Even more text
|
||||
|
||||
# Header 4 { #header-4 }
|
||||
|
||||
A bit more text
|
||||
|
||||
#Not a header
|
||||
|
||||
Final portion of text
|
||||
@@ -0,0 +1,19 @@
|
||||
# Header 1 { #header-1 }
|
||||
|
||||
Some text
|
||||
|
||||
# Header 2 { #header-2 }
|
||||
|
||||
Some more text
|
||||
|
||||
### Header 3 { #header-3 }
|
||||
|
||||
Even more text
|
||||
|
||||
# Header 4 { #header-4 }
|
||||
|
||||
A bit more text
|
||||
|
||||
#Not a header
|
||||
|
||||
Final portion of text
|
||||
@@ -0,0 +1,19 @@
|
||||
# Header 1 { #header-1 }
|
||||
|
||||
Some text
|
||||
|
||||
## Header 2 { #header-2 }
|
||||
|
||||
Some more text
|
||||
|
||||
### Header 3 { #header-3 }
|
||||
|
||||
Even more text
|
||||
|
||||
## Header 4 { #header-4 }
|
||||
|
||||
A bit more text
|
||||
|
||||
#Not a header
|
||||
|
||||
Final portion of text
|
||||
@@ -0,0 +1,19 @@
|
||||
# Header 1 { #header-1 }
|
||||
|
||||
Some text
|
||||
|
||||
## Header 2 { #header-2 }
|
||||
|
||||
Some more text
|
||||
|
||||
### Header 3 { #header-3 }
|
||||
|
||||
Even more text
|
||||
|
||||
# Header 4 { #header-4 }
|
||||
|
||||
A bit more text
|
||||
|
||||
# Extra header
|
||||
|
||||
Final portion of text
|
||||
@@ -0,0 +1,19 @@
|
||||
# Header 1 { #header-1 }
|
||||
|
||||
Some text
|
||||
|
||||
## Header 2 { #header-2 }
|
||||
|
||||
Some more text
|
||||
|
||||
### Header 3 { #header-3 }
|
||||
|
||||
Even more text
|
||||
|
||||
Header 4 is missing
|
||||
|
||||
A bit more text
|
||||
|
||||
#Not a header
|
||||
|
||||
Final portion of text
|
||||
@@ -0,0 +1,60 @@
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from typer.testing import CliRunner
|
||||
|
||||
from scripts.translation_fixer import cli
|
||||
|
||||
data_path = Path(
|
||||
"scripts/tests/test_translation_fixer/test_header_permalinks/data"
|
||||
).absolute()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"copy_test_files",
|
||||
[(f"{data_path}/en_doc.md", f"{data_path}/translated_doc_level_mismatch_1.md")],
|
||||
indirect=True,
|
||||
)
|
||||
def test_level_mismatch_1(runner: CliRunner, root_dir: Path, copy_test_files):
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
["fix-pages", "docs/lang/docs/doc.md"],
|
||||
)
|
||||
assert result.exit_code == 1
|
||||
|
||||
fixed_content = (root_dir / "docs" / "lang" / "docs" / "doc.md").read_text()
|
||||
expected_content = Path(
|
||||
f"{data_path}/translated_doc_level_mismatch_1.md"
|
||||
).read_text()
|
||||
|
||||
assert fixed_content == expected_content # Translated doc remains unchanged
|
||||
assert "Error processing docs/lang/docs/doc.md" in result.output
|
||||
assert (
|
||||
"Header levels do not match between document and original document"
|
||||
" (found #, expected ##) for header №2 in line 5"
|
||||
) in result.output
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"copy_test_files",
|
||||
[(f"{data_path}/en_doc.md", f"{data_path}/translated_doc_level_mismatch_2.md")],
|
||||
indirect=True,
|
||||
)
|
||||
def test_level_mismatch_2(runner: CliRunner, root_dir: Path, copy_test_files):
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
["fix-pages", "docs/lang/docs/doc.md"],
|
||||
)
|
||||
assert result.exit_code == 1
|
||||
|
||||
fixed_content = (root_dir / "docs" / "lang" / "docs" / "doc.md").read_text()
|
||||
expected_content = Path(
|
||||
f"{data_path}/translated_doc_level_mismatch_2.md"
|
||||
).read_text()
|
||||
|
||||
assert fixed_content == expected_content # Translated doc remains unchanged
|
||||
assert "Error processing docs/lang/docs/doc.md" in result.output
|
||||
assert (
|
||||
"Header levels do not match between document and original document"
|
||||
" (found ##, expected #) for header №4 in line 13"
|
||||
) in result.output
|
||||
@@ -0,0 +1,56 @@
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from typer.testing import CliRunner
|
||||
|
||||
from scripts.translation_fixer import cli
|
||||
|
||||
data_path = Path(
|
||||
"scripts/tests/test_translation_fixer/test_header_permalinks/data"
|
||||
).absolute()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"copy_test_files",
|
||||
[(f"{data_path}/en_doc.md", f"{data_path}/translated_doc_number_gt.md")],
|
||||
indirect=True,
|
||||
)
|
||||
def test_gt(runner: CliRunner, root_dir: Path, copy_test_files):
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
["fix-pages", "docs/lang/docs/doc.md"],
|
||||
)
|
||||
assert result.exit_code == 1
|
||||
|
||||
fixed_content = (root_dir / "docs" / "lang" / "docs" / "doc.md").read_text()
|
||||
expected_content = Path(f"{data_path}/translated_doc_number_gt.md").read_text()
|
||||
|
||||
assert fixed_content == expected_content # Translated doc remains unchanged
|
||||
assert "Error processing docs/lang/docs/doc.md" in result.output
|
||||
assert (
|
||||
"Number of headers with permalinks does not match the number "
|
||||
"in the original document (5 vs 4)"
|
||||
) in result.output
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"copy_test_files",
|
||||
[(f"{data_path}/en_doc.md", f"{data_path}/translated_doc_number_lt.md")],
|
||||
indirect=True,
|
||||
)
|
||||
def test_lt(runner: CliRunner, root_dir: Path, copy_test_files):
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
["fix-pages", "docs/lang/docs/doc.md"],
|
||||
)
|
||||
assert result.exit_code == 1
|
||||
|
||||
fixed_content = (root_dir / "docs" / "lang" / "docs" / "doc.md").read_text()
|
||||
expected_content = Path(f"{data_path}/translated_doc_number_lt.md").read_text()
|
||||
|
||||
assert fixed_content == expected_content # Translated doc remains unchanged
|
||||
assert "Error processing docs/lang/docs/doc.md" in result.output
|
||||
assert (
|
||||
"Number of headers with permalinks does not match the number "
|
||||
"in the original document (3 vs 4)"
|
||||
) in result.output
|
||||
@@ -0,0 +1,19 @@
|
||||
# Header 1 { #header-1 }
|
||||
|
||||
Some text with a link to <a href="https://fastapi.tiangolo.com">FastAPI</a>.
|
||||
|
||||
## Header 2 { #header-2 }
|
||||
|
||||
Two links here: <a href="https://fastapi.tiangolo.com/how-to/">How to</a> and <a href="project-generation.md" class="internal-link" target="_blank">Project Generators</a>.
|
||||
|
||||
### Header 3 { #header-3 }
|
||||
|
||||
Another link: <a href="project-generation.md" class="internal-link" target="_blank" title="Link title">**FastAPI** Project Generators</a> with title.
|
||||
|
||||
# Header 4 { #header-4 }
|
||||
|
||||
Link to anchor: <a href="#header-2">Header 2</a>
|
||||
|
||||
# Header with <a href="http://example.com">link</a> { #header-with-link }
|
||||
|
||||
Some text
|
||||
@@ -0,0 +1,21 @@
|
||||
# Заголовок 1 { #header-1 }
|
||||
|
||||
Немного текста со ссылкой на <a href="https://fastapi.tiangolo.com">FastAPI</a>.
|
||||
|
||||
## Заголовок 2 { #header-2 }
|
||||
|
||||
Две ссылки здесь: <a href="https://fastapi.tiangolo.com/how-to/">How to</a> и <a href="project-generation.md" class="internal-link" target="_blank">Project Generators</a>.
|
||||
|
||||
### Заголовок 3 { #header-3 }
|
||||
|
||||
Ещё ссылка: <a href="project-generation.md" class="internal-link" target="_blank" title="Тайтл">**FastAPI** Генераторы Проектов</a> с тайтлом.
|
||||
|
||||
И ещё одна <a href="https://github.com">экстра ссылка</a>.
|
||||
|
||||
# Заголовок 4 { #header-4 }
|
||||
|
||||
Ссылка на якорь: <a href="#header-2">Заголовок 2</a>
|
||||
|
||||
# Заголовок со <a href="http://example.com">ссылкой</a> { #header-with-link }
|
||||
|
||||
Немного текста
|
||||
@@ -0,0 +1,19 @@
|
||||
# Заголовок 1 { #header-1 }
|
||||
|
||||
Немного текста со ссылкой на <a href="https://fastapi.tiangolo.com">FastAPI</a>.
|
||||
|
||||
## Заголовок 2 { #header-2 }
|
||||
|
||||
Две ссылки здесь: <a href="https://fastapi.tiangolo.com/how-to/">How to</a> и <a href="project-generation.md" class="internal-link" target="_blank">Project Generators</a>.
|
||||
|
||||
### Заголовок 3 { #header-3 }
|
||||
|
||||
Ещё ссылка: <a href="project-generation.md" class="internal-link" target="_blank" title="Тайтл">**FastAPI** Генераторы Проектов</a> с тайтлом.
|
||||
|
||||
# Заголовок 4 { #header-4 }
|
||||
|
||||
Ссылка на якорь: <a href="#header-2">Заголовок 2</a>
|
||||
|
||||
# Заголовок с потерянной ссылкой { #header-with-link }
|
||||
|
||||
Немного текста
|
||||
@@ -0,0 +1,54 @@
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from typer.testing import CliRunner
|
||||
|
||||
from scripts.translation_fixer import cli
|
||||
|
||||
data_path = Path("scripts/tests/test_translation_fixer/test_html_links/data").absolute()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"copy_test_files",
|
||||
[(f"{data_path}/en_doc.md", f"{data_path}/translated_doc_number_gt.md")],
|
||||
indirect=True,
|
||||
)
|
||||
def test_gt(runner: CliRunner, root_dir: Path, copy_test_files):
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
["fix-pages", "docs/lang/docs/doc.md"],
|
||||
)
|
||||
assert result.exit_code == 1, result.output
|
||||
|
||||
fixed_content = (root_dir / "docs" / "lang" / "docs" / "doc.md").read_text()
|
||||
expected_content = Path(f"{data_path}/translated_doc_number_gt.md").read_text()
|
||||
|
||||
assert fixed_content == expected_content # Translated doc remains unchanged
|
||||
assert "Error processing docs/lang/docs/doc.md" in result.output
|
||||
assert (
|
||||
"Number of HTML links does not match the number "
|
||||
"in the original document (7 vs 6)"
|
||||
) in result.output
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"copy_test_files",
|
||||
[(f"{data_path}/en_doc.md", f"{data_path}/translated_doc_number_lt.md")],
|
||||
indirect=True,
|
||||
)
|
||||
def test_lt(runner: CliRunner, root_dir: Path, copy_test_files):
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
["fix-pages", "docs/lang/docs/doc.md"],
|
||||
)
|
||||
# assert result.exit_code == 1, result.output
|
||||
|
||||
fixed_content = (root_dir / "docs" / "lang" / "docs" / "doc.md").read_text()
|
||||
expected_content = Path(f"{data_path}/translated_doc_number_lt.md").read_text()
|
||||
|
||||
assert fixed_content == expected_content # Translated doc remains unchanged
|
||||
assert "Error processing docs/lang/docs/doc.md" in result.output
|
||||
assert (
|
||||
"Number of HTML links does not match the number "
|
||||
"in the original document (5 vs 6)"
|
||||
) in result.output
|
||||
@@ -0,0 +1,19 @@
|
||||
# Header 1 { #header-1 }
|
||||
|
||||
Some text with a link to [FastAPI](https://fastapi.tiangolo.com).
|
||||
|
||||
## Header 2 { #header-2 }
|
||||
|
||||
Two links here: [How to](https://fastapi.tiangolo.com/how-to/) and [Project Generators](project-generation.md){.internal-link target=_blank}.
|
||||
|
||||
### Header 3 { #header-3 }
|
||||
|
||||
Another link: [**FastAPI** Project Generators](project-generation.md "Link title"){.internal-link target=_blank} with title.
|
||||
|
||||
# Header 4 { #header-4 }
|
||||
|
||||
Link to anchor: [Header 2](#header-2)
|
||||
|
||||
# Header with [link](http://example.com) { #header-with-link }
|
||||
|
||||
Some text
|
||||
@@ -0,0 +1,19 @@
|
||||
# Заголовок 1 { #header-1 }
|
||||
|
||||
Немного текста со ссылкой на [FastAPI](https://fastapi.tiangolo.com).
|
||||
|
||||
## Заголовок 2 { #header-2 }
|
||||
|
||||
Две ссылки здесь: [How to](https://fastapi.tiangolo.com/how-to/) и [Project Generators](project-generation.md){.internal-link target=_blank}.
|
||||
|
||||
### Заголовок 3 { #header-3 }
|
||||
|
||||
Ещё ссылка: [**FastAPI** Генераторы Проектов](project-generation.md "Тайтл"){.internal-link target=_blank} с тайтлом.
|
||||
|
||||
# Заголовок 4 { #header-4 }
|
||||
|
||||
Ссылка на якорь: [Заголовок 2](#header-2)
|
||||
|
||||
# Заголовок со [ссылкой](http://example.com) { #header-with-link }
|
||||
|
||||
Немного текста
|
||||
@@ -0,0 +1,21 @@
|
||||
# Заголовок 1 { #header-1 }
|
||||
|
||||
Немного текста со ссылкой на [FastAPI](https://fastapi.tiangolo.com).
|
||||
|
||||
## Заголовок 2 { #header-2 }
|
||||
|
||||
Две ссылки здесь: [How to](https://fastapi.tiangolo.com/how-to/) и [Project Generators](project-generation.md){.internal-link target=_blank}.
|
||||
|
||||
### Заголовок 3 { #header-3 }
|
||||
|
||||
Ещё ссылка: [**FastAPI** Генераторы Проектов](project-generation.md "Тайтл"){.internal-link target=_blank} с тайтлом.
|
||||
|
||||
И ещё одна [экстра ссылка](https://github.com).
|
||||
|
||||
# Заголовок 4 { #header-4 }
|
||||
|
||||
Ссылка на якорь: [Заголовок 2](#header-2)
|
||||
|
||||
# Заголовок со [ссылкой](http://example.com) { #header-with-link }
|
||||
|
||||
Немного текста
|
||||
@@ -0,0 +1,19 @@
|
||||
# Заголовок 1 { #header-1 }
|
||||
|
||||
Немного текста со ссылкой на [FastAPI](https://fastapi.tiangolo.com).
|
||||
|
||||
## Заголовок 2 { #header-2 }
|
||||
|
||||
Две ссылки здесь: [How to](https://fastapi.tiangolo.com/how-to/) и [Project Generators](project-generation.md){.internal-link target=_blank}.
|
||||
|
||||
### Заголовок 3 { #header-3 }
|
||||
|
||||
Ещё ссылка: [**FastAPI** Генераторы Проектов](project-generation.md "Тайтл"){.internal-link target=_blank} с тайтлом.
|
||||
|
||||
# Заголовок 4 { #header-4 }
|
||||
|
||||
Ссылка на якорь: [Заголовок 2](#header-2)
|
||||
|
||||
# Заголовок с потерянной ссылкой { #header-with-link }
|
||||
|
||||
Немного текста
|
||||
@@ -0,0 +1,56 @@
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from typer.testing import CliRunner
|
||||
|
||||
from scripts.translation_fixer import cli
|
||||
|
||||
data_path = Path(
|
||||
"scripts/tests/test_translation_fixer/test_markdown_links/data"
|
||||
).absolute()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"copy_test_files",
|
||||
[(f"{data_path}/en_doc.md", f"{data_path}/translated_doc_number_gt.md")],
|
||||
indirect=True,
|
||||
)
|
||||
def test_gt(runner: CliRunner, root_dir: Path, copy_test_files):
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
["fix-pages", "docs/lang/docs/doc.md"],
|
||||
)
|
||||
assert result.exit_code == 1, result.output
|
||||
|
||||
fixed_content = (root_dir / "docs" / "lang" / "docs" / "doc.md").read_text()
|
||||
expected_content = Path(f"{data_path}/translated_doc_number_gt.md").read_text()
|
||||
|
||||
assert fixed_content == expected_content # Translated doc remains unchanged
|
||||
assert "Error processing docs/lang/docs/doc.md" in result.output
|
||||
assert (
|
||||
"Number of markdown links does not match the number "
|
||||
"in the original document (7 vs 6)"
|
||||
) in result.output
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"copy_test_files",
|
||||
[(f"{data_path}/en_doc.md", f"{data_path}/translated_doc_number_lt.md")],
|
||||
indirect=True,
|
||||
)
|
||||
def test_lt(runner: CliRunner, root_dir: Path, copy_test_files):
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
["fix-pages", "docs/lang/docs/doc.md"],
|
||||
)
|
||||
# assert result.exit_code == 1, result.output
|
||||
|
||||
fixed_content = (root_dir / "docs" / "lang" / "docs" / "doc.md").read_text()
|
||||
expected_content = Path(f"{data_path}/translated_doc_number_lt.md").read_text()
|
||||
|
||||
assert fixed_content == expected_content # Translated doc remains unchanged
|
||||
assert "Error processing docs/lang/docs/doc.md" in result.output
|
||||
assert (
|
||||
"Number of markdown links does not match the number "
|
||||
"in the original document (5 vs 6)"
|
||||
) in result.output
|
||||
@@ -10,6 +10,7 @@ from typing import Annotated
|
||||
import git
|
||||
import typer
|
||||
import yaml
|
||||
from doc_parsing_utils import check_translation
|
||||
from github import Github
|
||||
from pydantic_ai import Agent
|
||||
from rich import print
|
||||
@@ -119,9 +120,27 @@ def translate_page(
|
||||
]
|
||||
)
|
||||
prompt = "\n\n".join(prompt_segments)
|
||||
print(f"Running agent for {out_path}")
|
||||
result = agent.run_sync(prompt)
|
||||
out_content = f"{result.output.strip()}\n"
|
||||
|
||||
for attempt_no in range(1, 4):
|
||||
print(f"Running agent for {out_path} (attempt {attempt_no}/3)")
|
||||
result = agent.run_sync(prompt)
|
||||
out_content = f"{result.output.strip()}\n"
|
||||
try:
|
||||
check_translation(
|
||||
doc_lines=out_content.splitlines(),
|
||||
en_doc_lines=original_content.splitlines(),
|
||||
lang_code=language,
|
||||
auto_fix=False,
|
||||
path=str(out_path),
|
||||
)
|
||||
break # Exit loop if no errors
|
||||
except ValueError as e:
|
||||
print(f"Translation check failed on attempt {attempt_no}/3: {e}")
|
||||
continue # Retry if not reached max attempts
|
||||
else: # Max retry attempts reached
|
||||
print(f"Translation failed for {out_path} after 3 attempts")
|
||||
raise typer.Exit(code=1)
|
||||
|
||||
print(f"Saving translation to {out_path}")
|
||||
out_path.write_text(out_content, encoding="utf-8", newline="\n")
|
||||
|
||||
|
||||
132
scripts/translation_fixer.py
Normal file
132
scripts/translation_fixer.py
Normal file
@@ -0,0 +1,132 @@
|
||||
import os
|
||||
from collections.abc import Iterable
|
||||
from pathlib import Path
|
||||
from typing import Annotated
|
||||
|
||||
import typer
|
||||
|
||||
from scripts.doc_parsing_utils import check_translation
|
||||
|
||||
non_translated_sections = (
|
||||
f"reference{os.sep}",
|
||||
"release-notes.md",
|
||||
"fastapi-people.md",
|
||||
"external-links.md",
|
||||
"newsletter.md",
|
||||
"management-tasks.md",
|
||||
"management.md",
|
||||
"contributing.md",
|
||||
)
|
||||
|
||||
|
||||
cli = typer.Typer()
|
||||
|
||||
|
||||
@cli.callback()
|
||||
def callback():
|
||||
pass
|
||||
|
||||
|
||||
def iter_all_lang_paths(lang_path_root: Path) -> Iterable[Path]:
|
||||
"""
|
||||
Iterate on the markdown files to translate in order of priority.
|
||||
"""
|
||||
|
||||
first_dirs = [
|
||||
lang_path_root / "learn",
|
||||
lang_path_root / "tutorial",
|
||||
lang_path_root / "advanced",
|
||||
lang_path_root / "about",
|
||||
lang_path_root / "how-to",
|
||||
]
|
||||
first_parent = lang_path_root
|
||||
yield from first_parent.glob("*.md")
|
||||
for dir_path in first_dirs:
|
||||
yield from dir_path.rglob("*.md")
|
||||
first_dirs_str = tuple(str(d) for d in first_dirs)
|
||||
for path in lang_path_root.rglob("*.md"):
|
||||
if str(path).startswith(first_dirs_str):
|
||||
continue
|
||||
if path.parent == first_parent:
|
||||
continue
|
||||
yield path
|
||||
|
||||
|
||||
def get_all_paths(lang: str):
|
||||
res: list[str] = []
|
||||
lang_docs_root = Path("docs") / lang / "docs"
|
||||
for path in iter_all_lang_paths(lang_docs_root):
|
||||
relpath = path.relative_to(lang_docs_root)
|
||||
if not str(relpath).startswith(non_translated_sections):
|
||||
res.append(str(relpath))
|
||||
return res
|
||||
|
||||
|
||||
def process_one_page(path: Path) -> bool:
|
||||
"""
|
||||
Fix one translated document by comparing it to the English version.
|
||||
|
||||
Returns True if processed successfully, False otherwise.
|
||||
"""
|
||||
|
||||
try:
|
||||
lang_code = path.parts[1]
|
||||
if lang_code == "en":
|
||||
print(f"Skipping English document: {path}")
|
||||
return True
|
||||
|
||||
en_doc_path = Path("docs") / "en" / Path(*path.parts[2:])
|
||||
|
||||
doc_lines = path.read_text(encoding="utf-8").splitlines()
|
||||
en_doc_lines = en_doc_path.read_text(encoding="utf-8").splitlines()
|
||||
|
||||
doc_lines = check_translation(
|
||||
doc_lines=doc_lines,
|
||||
en_doc_lines=en_doc_lines,
|
||||
lang_code=lang_code,
|
||||
auto_fix=True,
|
||||
path=str(path),
|
||||
)
|
||||
|
||||
# Write back the fixed document
|
||||
doc_lines.append("") # Ensure file ends with a newline
|
||||
path.write_text("\n".join(doc_lines), encoding="utf-8")
|
||||
|
||||
except ValueError as e:
|
||||
print(f"Error processing {path}: {e}")
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
@cli.command()
|
||||
def fix_all(ctx: typer.Context, language: str):
|
||||
docs = get_all_paths(language)
|
||||
|
||||
all_good = True
|
||||
for page in docs:
|
||||
doc_path = Path("docs") / language / "docs" / page
|
||||
res = process_one_page(doc_path)
|
||||
all_good = all_good and res
|
||||
|
||||
if not all_good:
|
||||
raise typer.Exit(code=1)
|
||||
|
||||
|
||||
@cli.command()
|
||||
def fix_pages(
|
||||
doc_paths: Annotated[
|
||||
list[Path],
|
||||
typer.Argument(help="List of paths to documents."),
|
||||
],
|
||||
):
|
||||
all_good = True
|
||||
for path in doc_paths:
|
||||
res = process_one_page(path)
|
||||
all_good = all_good and res
|
||||
|
||||
if not all_good:
|
||||
raise typer.Exit(code=1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
cli()
|
||||
Reference in New Issue
Block a user