pax_global_header 0000666 0000000 0000000 00000000064 15005643713 0014516 g ustar 00root root 0000000 0000000 52 comment=3f8be847ddd19286bdfb573f46b8191e70d7c538 litestar-2.16.0/ 0000775 0000000 0000000 00000000000 15005643713 0013433 5 ustar 00root root 0000000 0000000 litestar-2.16.0/.all-contributorsrc 0000664 0000000 0000000 00000146076 15005643713 0017302 0 ustar 00root root 0000000 0000000 { "files": [ "README.md" ], "imageSize": 100, "commit": false, "contributors": [ { "login": "Goldziher", "name": "Na'aman Hirschfeld", "avatar_url": "https://avatars.githubusercontent.com/u/30733348?v=4", "profile": "https://www.linkedin.com/in/nhirschfeld/", "contributions": [ "maintenance", "code", "doc", "test", "ideas", "example", "bug" ] }, { "login": "peterschutt", "name": "Peter Schutt", "avatar_url": "https://avatars.githubusercontent.com/u/20659309?v=4", "profile": "https://github.com/peterschutt", "contributions": [ "maintenance", "code", "doc", "test", "ideas", "example", "bug" ] }, { "login": "ashwinvin", "name": "Ashwin Vinod", "avatar_url": "https://avatars.githubusercontent.com/u/38067089?v=4", "profile": "https://ashwinvin.github.io", "contributions": [ "code", "doc" ] }, { "login": "dkress59", "name": "Damian", "avatar_url": "https://avatars.githubusercontent.com/u/28515387?v=4", "profile": "http://www.damiankress.de", "contributions": [ "doc" ] }, { "login": "vincentsarago", "name": "Vincent Sarago", "avatar_url": "https://avatars.githubusercontent.com/u/10407788?v=4", "profile": "https://remotepixel.ca", "contributions": [ "code" ] }, { "login": "JonasKs", "name": "Jonas Krüger Svensson", "avatar_url": "https://avatars.githubusercontent.com/u/5310116?v=4", "profile": "https://hotfix.guru", "contributions": [ "platform" ] }, { "login": "sondrelg", "name": "Sondre Lillebø Gundersen", "avatar_url": "https://avatars.githubusercontent.com/u/25310870?v=4", "profile": "https://github.com/sondrelg", "contributions": [ "platform" ] }, { "login": "vrslev", "name": "Lev", "avatar_url": "https://avatars.githubusercontent.com/u/75225148?v=4", "profile": "https://github.com/vrslev", "contributions": [ "code", "ideas" ] }, { "login": "timwedde", "name": "Tim Wedde", "avatar_url": "https://avatars.githubusercontent.com/u/20231751?v=4", "profile": "https://github.com/timwedde", "contributions": [ "code" ] }, { "login": "tclasen", "name": "Tory Clasen", "avatar_url": "https://avatars.githubusercontent.com/u/11999013?v=4", "profile": "https://github.com/tclasen", "contributions": [ "code" ] }, { "login": "Bobronium", "name": "Arseny Boykov", "avatar_url": "https://avatars.githubusercontent.com/u/36469655?v=4", "profile": "http://t.me/Bobronium", "contributions": [ "code", "ideas" ] }, { "login": "yudjinn", "name": "Jacob Rodgers", "avatar_url": "https://avatars.githubusercontent.com/u/7493084?v=4", "profile": "https://github.com/yudjinn", "contributions": [ "example" ] }, { "login": "danesolberg", "name": "Dane Solberg", "avatar_url": "https://avatars.githubusercontent.com/u/25882507?v=4", "profile": "https://github.com/danesolberg", "contributions": [ "code" ] }, { "login": "madlad33", "name": "madlad33", "avatar_url": "https://avatars.githubusercontent.com/u/54079440?v=4", "profile": "https://github.com/madlad33", "contributions": [ "code" ] }, { "login": "Butch78", "name": "Matthew Aylward ", "avatar_url": "https://avatars.githubusercontent.com/u/19205392?v=4", "profile": "http://matthewtyleraylward.com", "contributions": [ "code" ] }, { "login": "Joko013", "name": "Jan Klima", "avatar_url": "https://avatars.githubusercontent.com/u/30841710?v=4", "profile": "https://github.com/Joko013", "contributions": [ "code" ] }, { "login": "i404788", "name": "C2D", "avatar_url": "https://avatars.githubusercontent.com/u/50617709?v=4", "profile": "https://github.com/i404788", "contributions": [ "test" ] }, { "login": "to-ph", "name": "to-ph", "avatar_url": "https://avatars.githubusercontent.com/u/84818322?v=4", "profile": "https://github.com/to-ph", "contributions": [ "code" ] }, { "login": "imbev", "name": "imbev", "avatar_url": "https://avatars.githubusercontent.com/u/105524473?v=4", "profile": "https://imbev.gitlab.io/site", "contributions": [ "doc" ] }, { "login": "185504a9", "name": "cătălin", "avatar_url": "https://avatars.githubusercontent.com/u/45485069?v=4", "profile": "https://git.roboces.dev/catalin", "contributions": [ "code" ] }, { "login": "Seon82", "name": "Seon82", "avatar_url": "https://avatars.githubusercontent.com/u/46298009?v=4", "profile": "https://github.com/Seon82", "contributions": [ "doc" ] }, { "login": "slavugan", "name": "Slava", "avatar_url": "https://avatars.githubusercontent.com/u/8457612?v=4", "profile": "https://github.com/slavugan", "contributions": [ "code" ] }, { "login": "Harry-Lees", "name": "Harry", "avatar_url": "https://avatars.githubusercontent.com/u/52263746?v=4", "profile": "https://github.com/Harry-Lees", "contributions": [ "code", "doc" ] }, { "login": "cofin", "name": "Cody Fincher", "avatar_url": "https://avatars.githubusercontent.com/u/204685?v=4", "profile": "https://github.com/cofin", "contributions": [ "maintenance", "code", "doc", "test", "ideas", "example", "bug" ] }, { "login": "cclauss", "name": "Christian Clauss", "avatar_url": "https://avatars.githubusercontent.com/u/3709715?v=4", "profile": "https://www.patreon.com/cclauss", "contributions": [ "doc" ] }, { "login": "josepdaniel", "name": "josepdaniel", "avatar_url": "https://avatars.githubusercontent.com/u/36941460?v=4", "profile": "https://github.com/josepdaniel", "contributions": [ "code" ] }, { "login": "devtud", "name": "devtud", "avatar_url": "https://avatars.githubusercontent.com/u/6808024?v=4", "profile": "https://github.com/devtud", "contributions": [ "bug" ] }, { "login": "nramos0", "name": "Nicholas Ramos", "avatar_url": "https://avatars.githubusercontent.com/u/35410160?v=4", "profile": "https://github.com/nramos0", "contributions": [ "code" ] }, { "login": "seladb", "name": "seladb", "avatar_url": "https://avatars.githubusercontent.com/u/9059541?v=4", "profile": "https://twitter.com/seladb", "contributions": [ "doc", "code" ] }, { "login": "aedify-swi", "name": "Simon Wienhöfer", "avatar_url": "https://avatars.githubusercontent.com/u/66629131?v=4", "profile": "https://github.com/aedify-swi", "contributions": [ "code" ] }, { "login": "mobiusxs", "name": "MobiusXS", "avatar_url": "https://avatars.githubusercontent.com/u/57055149?v=4", "profile": "https://github.com/mobiusxs", "contributions": [ "code" ] }, { "login": "Aidan-Simard", "name": "Aidan Simard", "avatar_url": "https://avatars.githubusercontent.com/u/73361895?v=4", "profile": "http://aidansimard.dev", "contributions": [ "doc" ] }, { "login": "waweber", "name": "wweber", "avatar_url": "https://avatars.githubusercontent.com/u/714224?v=4", "profile": "https://github.com/waweber", "contributions": [ "code" ] }, { "login": "samuelcolvin", "name": "Samuel Colvin", "avatar_url": "https://avatars.githubusercontent.com/u/4039449?v=4", "profile": "http://scolvin.com", "contributions": [ "code" ] }, { "login": "toudi", "name": "Mateusz Mikołajczyk", "avatar_url": "https://avatars.githubusercontent.com/u/81148?v=4", "profile": "https://github.com/toudi", "contributions": [ "code" ] }, { "login": "Alex-CodeLab", "name": "Alex ", "avatar_url": "https://avatars.githubusercontent.com/u/1678423?v=4", "profile": "https://github.com/Alex-CodeLab", "contributions": [ "code" ] }, { "login": "odiseo0", "name": "Odiseo", "avatar_url": "https://avatars.githubusercontent.com/u/87550035?v=4", "profile": "https://github.com/odiseo0", "contributions": [ "doc" ] }, { "login": "ingjavierpinilla", "name": "Javier Pinilla", "avatar_url": "https://avatars.githubusercontent.com/u/36714646?v=4", "profile": "https://github.com/ingjavierpinilla", "contributions": [ "code" ] }, { "login": "Chaoyingz", "name": "Chaoying", "avatar_url": "https://avatars.githubusercontent.com/u/32626585?v=4", "profile": "https://github.com/Chaoyingz", "contributions": [ "doc" ] }, { "login": "infohash", "name": "infohash", "avatar_url": "https://avatars.githubusercontent.com/u/46137868?v=4", "profile": "https://github.com/infohash", "contributions": [ "code" ] }, { "login": "john-ingles", "name": "John Ingles", "avatar_url": "https://avatars.githubusercontent.com/u/35442886?v=4", "profile": "https://www.linkedin.com/in/john-ingles/", "contributions": [ "code" ] }, { "login": "h0rn3t", "name": "Eugene", "avatar_url": "https://avatars.githubusercontent.com/u/1213719?v=4", "profile": "https://github.com/h0rn3t", "contributions": [ "test", "code" ] }, { "login": "jonadaly", "name": "Jon Daly", "avatar_url": "https://avatars.githubusercontent.com/u/26462826?v=4", "profile": "https://github.com/jonadaly", "contributions": [ "doc", "code" ] }, { "login": "Harshal6927", "name": "Harshal Laheri", "avatar_url": "https://avatars.githubusercontent.com/u/73422191?v=4", "profile": "https://harshallaheri.me/", "contributions": [ "code", "doc" ] }, { "login": "sorasful", "name": "Téva KRIEF", "avatar_url": "https://avatars.githubusercontent.com/u/32820423?v=4", "profile": "https://github.com/sorasful", "contributions": [ "code" ] }, { "login": "jtraub", "name": "Konstantin Mikhailov", "avatar_url": "https://avatars.githubusercontent.com/u/153191?v=4", "profile": "https://github.com/jtraub", "contributions": [ "maintenance", "code", "doc", "test", "ideas", "example", "bug" ] }, { "login": "devmitch", "name": "Mitchell Henry", "avatar_url": "https://avatars.githubusercontent.com/u/17354727?v=4", "profile": "http://linkedin.com/in/mitchell-henry334/", "contributions": [ "doc" ] }, { "login": "chbndrhnns", "name": "chbndrhnns", "avatar_url": "https://avatars.githubusercontent.com/u/7534547?v=4", "profile": "https://github.com/chbndrhnns", "contributions": [ "doc" ] }, { "login": "nielsvanhooy", "name": "nielsvanhooy", "avatar_url": "https://avatars.githubusercontent.com/u/40770348?v=4", "profile": "https://github.com/nielsvanhooy", "contributions": [ "code", "bug", "test" ] }, { "login": "provinzkraut", "name": "provinzkraut", "avatar_url": "https://avatars.githubusercontent.com/u/25355197?v=4", "profile": "https://github.com/provinzkraut", "contributions": [ "maintenance", "code", "doc", "test", "ideas", "example", "bug", "design" ] }, { "login": "jab", "name": "Joshua Bronson", "avatar_url": "https://avatars.githubusercontent.com/u/64992?v=4", "profile": "https://github.com/jab", "contributions": [ "doc" ] }, { "login": "ReznikovRoman", "name": "Roman Reznikov", "avatar_url": "https://avatars.githubusercontent.com/u/44291988?v=4", "profile": "http://linkedin.com/in/roman-reznikov", "contributions": [ "doc" ] }, { "login": "mookrs", "name": "mookrs", "avatar_url": "https://avatars.githubusercontent.com/u/985439?v=4", "profile": "http://mookrs.com", "contributions": [ "doc" ] }, { "login": "mivade", "name": "Mike DePalatis", "avatar_url": "https://avatars.githubusercontent.com/u/2805515?v=4", "profile": "http://mike.depalatis.net", "contributions": [ "doc" ] }, { "login": "pemocarlo", "name": "Carlos Alberto Pérez-Molano", "avatar_url": "https://avatars.githubusercontent.com/u/7297323?v=4", "profile": "https://github.com/pemocarlo", "contributions": [ "doc" ] }, { "login": "ThinksFast", "name": "ThinksFast", "avatar_url": "https://avatars.githubusercontent.com/u/114229148?v=4", "profile": "https://www.bestcryptocodes.com", "contributions": [ "test", "doc" ] }, { "login": "ottermata", "name": "Christopher Krause", "avatar_url": "https://avatars.githubusercontent.com/u/9451844?v=4", "profile": "https://github.com/ottermata", "contributions": [ "code" ] }, { "login": "smithk86", "name": "Kyle Smith", "avatar_url": "https://avatars.githubusercontent.com/u/1161424?v=4", "profile": "http://www.kylesmith.me", "contributions": [ "code", "doc", "bug" ] }, { "login": "scott2b", "name": "Scott Bradley", "avatar_url": "https://avatars.githubusercontent.com/u/307713?v=4", "profile": "https://github.com/scott2b", "contributions": [ "bug" ] }, { "login": "srikanthccv", "name": "Srikanth Chekuri", "avatar_url": "https://avatars.githubusercontent.com/u/22846633?v=4", "profile": "https://www.linkedin.com/in/srikanthccv/", "contributions": [ "test", "doc" ] }, { "login": "LonelyVikingMichael", "name": "Michael Bosch", "avatar_url": "https://avatars.githubusercontent.com/u/78952809?v=4", "profile": "https://lonelyviking.com", "contributions": [ "doc" ] }, { "login": "sssssss340", "name": "sssssss340", "avatar_url": "https://avatars.githubusercontent.com/u/8406195?v=4", "profile": "https://github.com/sssssss340", "contributions": [ "bug" ] }, { "login": "ste-pool", "name": "ste-pool", "avatar_url": "https://avatars.githubusercontent.com/u/17198460?v=4", "profile": "https://github.com/ste-pool", "contributions": [ "code", "infra" ] }, { "login": "Alc-Alc", "name": "Alc-Alc", "avatar_url": "https://avatars.githubusercontent.com/u/45509143?v=4", "profile": "https://github.com/Alc-Alc", "contributions": [ "doc", "code", "test", "infra" ] }, { "login": "asomethings", "name": "asomethings", "avatar_url": "https://avatars.githubusercontent.com/u/16171942?v=4", "profile": "http://asomethings.com", "contributions": [ "code" ] }, { "login": "garburator", "name": "Garry Bullock", "avatar_url": "https://avatars.githubusercontent.com/u/14207857?v=4", "profile": "https://github.com/garburator", "contributions": [ "doc" ] }, { "login": "NiclasHaderer", "name": "Niclas Haderer", "avatar_url": "https://avatars.githubusercontent.com/u/109728711?v=4", "profile": "https://github.com/NiclasHaderer", "contributions": [ "code" ] }, { "login": "dialvarezs", "name": "Diego Alvarez", "avatar_url": "https://avatars.githubusercontent.com/u/13831919?v=4", "profile": "https://github.com/dialvarezs", "contributions": [ "doc", "code", "test" ] }, { "login": "rgajason", "name": "Jason Nance", "avatar_url": "https://avatars.githubusercontent.com/u/51208317?v=4", "profile": "https://www.rgare.com", "contributions": [ "doc" ] }, { "login": "spikenn", "name": "Igor Kapadze", "avatar_url": "https://avatars.githubusercontent.com/u/32995595?v=4", "profile": "https://github.com/spikenn", "contributions": [ "doc" ] }, { "login": "Jarmos-san", "name": "Somraj Saha", "avatar_url": "https://avatars.githubusercontent.com/u/31373860?v=4", "profile": "https://jarmos.vercel.app", "contributions": [ "doc" ] }, { "login": "maggias", "name": "Magnús Ágúst Skúlason", "avatar_url": "https://avatars.githubusercontent.com/u/11139514?v=4", "profile": "http://skulason.me", "contributions": [ "code", "doc" ] }, { "login": "pomma89", "name": "Alessio Parma", "avatar_url": "https://avatars.githubusercontent.com/u/4697032?v=4", "profile": "https://alessioparma.xyz/", "contributions": [ "doc" ] }, { "login": "Lugoues", "name": "Peter Brunner", "avatar_url": "https://avatars.githubusercontent.com/u/372610?v=4", "profile": "https://github.com/Lugoues", "contributions": [ "code" ] }, { "login": "JacobCoffee", "name": "Jacob Coffee", "avatar_url": "https://avatars.githubusercontent.com/u/45884264?v=4", "profile": "https://scriptr.dev/", "contributions": [ "doc", "code", "test", "infra", "ideas", "maintenance", "business", "design" ] }, { "login": "Gamazic", "name": "Gamazic", "avatar_url": "https://avatars.githubusercontent.com/u/33692402?v=4", "profile": "https://github.com/Gamazic", "contributions": [ "code" ] }, { "login": "kareemmahlees", "name": "Kareem Mahlees", "avatar_url": "https://avatars.githubusercontent.com/u/89863279?v=4", "profile": "https://github.com/kareemmahlees", "contributions": [ "code" ] }, { "login": "abdulhaq-e", "name": "Abdulhaq Emhemmed", "avatar_url": "https://avatars.githubusercontent.com/u/2532125?v=4", "profile": "https://github.com/abdulhaq-e", "contributions": [ "code", "doc" ] }, { "login": "jenish2014", "name": "Jenish", "avatar_url": "https://avatars.githubusercontent.com/u/9599888?v=4", "profile": "https://github.com/jenish2014", "contributions": [ "code", "doc" ] }, { "login": "chris-telemetry", "name": "chris-telemetry", "avatar_url": "https://avatars.githubusercontent.com/u/78052999?v=4", "profile": "https://github.com/chris-telemetry", "contributions": [ "code" ] }, { "login": "WardPearce", "name": "Ward", "avatar_url": "https://avatars.githubusercontent.com/u/27844174?v=4", "profile": "http://wardpearce.com", "contributions": [ "bug" ] }, { "login": "knowsuchagency", "name": "Stephan Fitzpatrick", "avatar_url": "https://avatars.githubusercontent.com/u/11974795?v=4", "profile": "https://knowsuchagency.com", "contributions": [ "bug" ] }, { "login": "ekeric13", "name": "Eric Kennedy", "avatar_url": "https://avatars.githubusercontent.com/u/6489651?v=4", "profile": "https://codepen.io/ekeric13/", "contributions": [ "doc" ] }, { "login": "wassafshahzad", "name": "wassaf shahzad", "avatar_url": "https://avatars.githubusercontent.com/u/25094157?v=4", "profile": "https://github.com/wassafshahzad", "contributions": [ "code" ] }, { "login": "nilsso", "name": "Nils Olsson", "avatar_url": "https://avatars.githubusercontent.com/u/567181?v=4", "profile": "http://nilsso.github.io", "contributions": [ "code", "bug" ] }, { "login": "Nadock", "name": "Riley Chase", "avatar_url": "https://avatars.githubusercontent.com/u/1491530?v=4", "profile": "http://rileychase.net", "contributions": [ "code" ] }, { "login": "onerandomusername", "name": "arl", "avatar_url": "https://avatars.githubusercontent.com/u/71233171?v=4", "profile": "https://gh.arielle.codes", "contributions": [ "maintenance" ] }, { "login": "Galdanwing", "name": "Antoine van der Horst", "avatar_url": "https://avatars.githubusercontent.com/u/29492757?v=4", "profile": "https://github.com/Galdanwing", "contributions": [ "doc" ] }, { "login": "zoni", "name": "Nick Groenen", "avatar_url": "https://avatars.githubusercontent.com/u/145285?v=4", "profile": "https://nick.groenen.me", "contributions": [ "doc" ] }, { "login": "giorgiovilardo", "name": "Giorgio Vilardo", "avatar_url": "https://avatars.githubusercontent.com/u/56472600?v=4", "profile": "https://github.com/giorgiovilardo", "contributions": [ "doc" ] }, { "login": "bollwyvl", "name": "Nicholas Bollweg", "avatar_url": "https://avatars.githubusercontent.com/u/45380?v=4", "profile": "https://github.com/bollwyvl", "contributions": [ "code" ] }, { "login": "tompin82", "name": "Tomas Jonsson", "avatar_url": "https://avatars.githubusercontent.com/u/47041409?v=4", "profile": "https://github.com/tompin82", "contributions": [ "test", "code" ] }, { "login": "khiemdoan", "name": "Khiem Doan", "avatar_url": "https://avatars.githubusercontent.com/u/15646249?v=4", "profile": "https://www.linkedin.com/in/khiem-doan/", "contributions": [ "doc" ] }, { "login": "kedod", "name": "kedod", "avatar_url": "https://avatars.githubusercontent.com/u/35638715?v=4", "profile": "https://github.com/kedod", "contributions": [ "doc", "code", "test" ] }, { "login": "sonpro1296", "name": "sonpro1296", "avatar_url": "https://avatars.githubusercontent.com/u/17319142?v=4", "profile": "https://github.com/sonpro1296", "contributions": [ "code", "test", "infra", "doc" ] }, { "login": "patrickarmengol", "name": "Patrick Armengol", "avatar_url": "https://avatars.githubusercontent.com/u/42473149?v=4", "profile": "https://patrickarmengol.com", "contributions": [ "doc" ] }, { "login": "SanderWegter", "name": "Sander", "avatar_url": "https://avatars.githubusercontent.com/u/7465799?v=4", "profile": "https://sanderwegter.nl", "contributions": [ "doc" ] }, { "login": "erhuabushuo", "name": "疯人院主任", "avatar_url": "https://avatars.githubusercontent.com/u/1642364?v=4", "profile": "https://github.com/erhuabushuo", "contributions": [ "doc" ] }, { "login": "aviral-nayya", "name": "aviral-nayya", "avatar_url": "https://avatars.githubusercontent.com/u/121891493?v=4", "profile": "https://github.com/aviral-nayya", "contributions": [ "code" ] }, { "login": "whiskeyriver", "name": "whiskeyriver", "avatar_url": "https://avatars.githubusercontent.com/u/162092?v=4", "profile": "https://github.com/whiskeyriver", "contributions": [ "code" ] }, { "login": "v3ss0n", "name": "Phyo Arkar Lwin", "avatar_url": "https://avatars.githubusercontent.com/u/419606?v=4", "profile": "https://hexcode.tech", "contributions": [ "code" ] }, { "login": "MatthewNewland", "name": "MatthewNewland", "avatar_url": "https://avatars.githubusercontent.com/u/9618670?v=4", "profile": "https://github.com/MatthewNewland", "contributions": [ "bug", "code", "test" ] }, { "login": "vtarchon", "name": "Tom Kuo", "avatar_url": "https://avatars.githubusercontent.com/u/1598170?v=4", "profile": "https://github.com/vtarchon", "contributions": [ "bug" ] }, { "login": "LeckerenSirupwaffeln", "name": "LeckerenSirupwaffeln", "avatar_url": "https://avatars.githubusercontent.com/u/83568015?v=4", "profile": "https://github.com/LeckerenSirupwaffeln", "contributions": [ "bug" ] }, { "login": "eldano1995", "name": "Daniel González Fernández", "avatar_url": "https://avatars.githubusercontent.com/u/24553679?v=4", "profile": "https://github.com/eldano1995", "contributions": [ "doc" ] }, { "login": "01EK98", "name": "01EK98", "avatar_url": "https://avatars.githubusercontent.com/u/101988390?v=4", "profile": "https://github.com/01EK98", "contributions": [ "doc" ] }, { "login": "sarbor", "name": "Sarbo Roy", "avatar_url": "https://avatars.githubusercontent.com/u/15257226?v=4", "profile": "https://github.com/sarbor", "contributions": [ "code" ] }, { "login": "rseeley", "name": "Ryan Seeley", "avatar_url": "https://avatars.githubusercontent.com/u/5397221?v=4", "profile": "https://github.com/rseeley", "contributions": [ "code" ] }, { "login": "ctrl-Felix", "name": "Felix", "avatar_url": "https://avatars.githubusercontent.com/u/62290842?v=4", "profile": "https://github.com/ctrl-Felix", "contributions": [ "doc", "bug" ] }, { "login": "gsakkis", "name": "George Sakkis", "avatar_url": "https://avatars.githubusercontent.com/u/291289?v=4", "profile": "https://www.linkedin.com/in/gsakkis", "contributions": [ "code" ] }, { "login": "floxay", "name": "Huba Tuba", "avatar_url": "https://avatars.githubusercontent.com/u/57007485?v=4", "profile": "https://github.com/floxay", "contributions": [ "doc", "code", "test" ] }, { "login": "sfermigier", "name": "Stefane Fermigier", "avatar_url": "https://avatars.githubusercontent.com/u/271079?v=4", "profile": "http://fermigier.com/", "contributions": [ "doc" ] }, { "login": "r4gesingh47", "name": "r4ge", "avatar_url": "https://avatars.githubusercontent.com/u/71139938?v=4", "profile": "https://github.com/r4gesingh47", "contributions": [ "code", "doc" ] }, { "login": "jaykv", "name": "Jay", "avatar_url": "https://avatars.githubusercontent.com/u/18240054?v=4", "profile": "https://github.com/jaykv", "contributions": [ "code" ] }, { "login": "sinisaos", "name": "sinisaos", "avatar_url": "https://avatars.githubusercontent.com/u/30960668?v=4", "profile": "https://github.com/sinisaos", "contributions": [ "doc" ] }, { "login": "Tsdevendra1", "name": "Tharuka Devendra", "avatar_url": "https://avatars.githubusercontent.com/u/38055748?v=4", "profile": "https://github.com/Tsdevendra1", "contributions": [ "code" ] }, { "login": "euri10", "name": "euri10", "avatar_url": "https://avatars.githubusercontent.com/u/1104190?v=4", "profile": "https://github.com/euri10", "contributions": [ "code", "doc", "bug" ] }, { "login": "su-shubham", "name": "Shubham", "avatar_url": "https://avatars.githubusercontent.com/u/75021117?v=4", "profile": "https://github.com/su-shubham", "contributions": [ "doc" ] }, { "login": "erik-hasse", "name": "Erik Hasse", "avatar_url": "https://avatars.githubusercontent.com/u/37126755?v=4", "profile": "https://www.linkedin.com/in/erik-hasse", "contributions": [ "bug", "code" ] }, { "login": "sobolevn", "name": "Nikita Sobolev", "avatar_url": "https://avatars.githubusercontent.com/u/4660275?v=4", "profile": "https://sobolevn.me", "contributions": [ "infra", "code" ] }, { "login": "lazyc97", "name": "Nguyễn Hoàng Đức", "avatar_url": "https://avatars.githubusercontent.com/u/8538104?v=4", "profile": "https://github.com/lazyc97", "contributions": [ "bug" ] }, { "login": "RavanaBhrama", "name": "RavanaBhrama", "avatar_url": "https://avatars.githubusercontent.com/u/131459969?v=4", "profile": "https://github.com/RavanaBhrama", "contributions": [ "doc" ] }, { "login": "mj0nez", "name": "Marcel Johannesmann", "avatar_url": "https://avatars.githubusercontent.com/u/20128340?v=4", "profile": "https://github.com/mj0nez", "contributions": [ "doc" ] }, { "login": "therealzanfar", "name": "Matthew", "avatar_url": "https://avatars.githubusercontent.com/u/10294685?v=4", "profile": "http://zanfar.com/", "contributions": [ "doc" ] }, { "login": "Mattwmaster58", "name": "Mattwmaster58", "avatar_url": "https://avatars.githubusercontent.com/u/26337069?v=4", "profile": "https://github.com/Mattwmaster58", "contributions": [ "bug", "code", "test" ] }, { "login": "aorith", "name": "Manuel Sanchez Pinar", "avatar_url": "https://avatars.githubusercontent.com/u/5411704?v=4", "profile": "https://es.linkedin.com/in/manusp", "contributions": [ "doc" ] }, { "login": "juan-riveros", "name": "Juan Riveros", "avatar_url": "https://avatars.githubusercontent.com/u/1297567?v=4", "profile": "https://github.com/juan-riveros", "contributions": [ "doc" ] }, { "login": "davidbrochart", "name": "David Brochart", "avatar_url": "https://avatars.githubusercontent.com/u/4711805?v=4", "profile": "https://github.com/davidbrochart", "contributions": [ "doc" ] }, { "login": "sean-donoghue", "name": "Sean Donoghue", "avatar_url": "https://avatars.githubusercontent.com/u/64597271?v=4", "profile": "https://github.com/sean-donoghue", "contributions": [ "doc" ] }, { "login": "sykloid", "name": "P.C. Shyamshankar", "avatar_url": "https://avatars.githubusercontent.com/u/22753?v=4", "profile": "https://sykloid.org/", "contributions": [ "bug", "code", "test" ] }, { "login": "wevonosky", "name": "William Evonosky", "avatar_url": "https://avatars.githubusercontent.com/u/19598171?v=4", "profile": "https://github.com/wevonosky", "contributions": [ "code" ] }, { "login": "geeshta", "name": "geeshta", "avatar_url": "https://avatars.githubusercontent.com/u/61031243?v=4", "profile": "https://github.com/geeshta", "contributions": [ "doc", "code", "bug" ] }, { "login": "RobertRosca", "name": "Robert Rosca", "avatar_url": "https://avatars.githubusercontent.com/u/32569096?v=4", "profile": "https://fosstodon.org/@robertrosca", "contributions": [ "doc" ] }, { "login": "syshenyu", "name": "DICE_Lab", "avatar_url": "https://avatars.githubusercontent.com/u/92897003?v=4", "profile": "https://github.com/syshenyu", "contributions": [ "code" ] }, { "login": "lsanpablo", "name": "Luis San Pablo", "avatar_url": "https://avatars.githubusercontent.com/u/7145688?v=4", "profile": "https://github.com/lsanpablo", "contributions": [ "code", "test", "doc" ] }, { "login": "Lancetnik", "name": "Pastukhov Nikita", "avatar_url": "https://avatars.githubusercontent.com/u/44573917?v=4", "profile": "https://github.com/Lancetnik", "contributions": [ "doc" ] }, { "login": "ddxv", "name": "James O'Claire", "avatar_url": "https://avatars.githubusercontent.com/u/7601451?v=4", "profile": "http://jamesoclaire.com", "contributions": [ "doc" ] }, { "login": "pbaletkeman", "name": "Pete", "avatar_url": "https://avatars.githubusercontent.com/u/22402240?v=4", "profile": "https://github.com/pbaletkeman", "contributions": [ "doc" ] }, { "login": "heralight", "name": "Alexandre Richonnier", "avatar_url": "https://avatars.githubusercontent.com/u/534840?v=4", "profile": "http://www.hera.cc", "contributions": [ "code", "doc" ] }, { "login": "betaboon", "name": "betaboon", "avatar_url": "https://avatars.githubusercontent.com/u/7346933?v=4", "profile": "https://github.com/betaboon", "contributions": [ "code" ] }, { "login": "brakhane", "name": "Dennis Brakhane", "avatar_url": "https://avatars.githubusercontent.com/u/541637?v=4", "profile": "https://github.com/brakhane", "contributions": [ "code", "bug" ] }, { "login": "AgarwalPragy", "name": "Pragy Agarwal", "avatar_url": "https://avatars.githubusercontent.com/u/7423639?v=4", "profile": "https://mind.wiki", "contributions": [ "doc" ] }, { "login": "dybi", "name": "Piotr Dybowski", "avatar_url": "https://avatars.githubusercontent.com/u/36961162?v=4", "profile": "https://github.com/dybi", "contributions": [ "doc" ] }, { "login": "myslak71", "name": "Konrad Szczurek", "avatar_url": "https://avatars.githubusercontent.com/u/43068450?v=4", "profile": "https://github.com/myslak71", "contributions": [ "doc", "test" ] }, { "login": "orgarten", "name": "Orell Garten", "avatar_url": "https://avatars.githubusercontent.com/u/10799869?v=4", "profile": "https://github.com/orgarten", "contributions": [ "code", "doc", "test" ] }, { "login": "Kumzy", "name": "Julien", "avatar_url": "https://avatars.githubusercontent.com/u/5995441?v=4", "profile": "https://github.com/Kumzy", "contributions": [ "doc" ] }, { "login": "leejayhsu", "name": "Leejay Hsu", "avatar_url": "https://avatars.githubusercontent.com/u/37034741?v=4", "profile": "https://github.com/leejayhsu", "contributions": [ "maintenance", "infra", "doc" ] }, { "login": "mbeijen", "name": "Michiel W. Beijen", "avatar_url": "https://avatars.githubusercontent.com/u/659504?v=4", "profile": "https://x14.nl", "contributions": [ "doc" ] }, { "login": "baoliay2008", "name": "L. Bao", "avatar_url": "https://avatars.githubusercontent.com/u/13620348?v=4", "profile": "https://github.com/baoliay2008", "contributions": [ "doc" ] }, { "login": "jdglaser", "name": "Jarred Glaser", "avatar_url": "https://avatars.githubusercontent.com/u/32422167?v=4", "profile": "http://jarredglaser.com", "contributions": [ "doc" ] }, { "login": "hunterjsb", "name": "Hunter Boyd", "avatar_url": "https://avatars.githubusercontent.com/u/69213737?v=4", "profile": "https://github.com/hunterjsb", "contributions": [ "doc" ] }, { "login": "cesarmg1980", "name": "Cesar Giulietti", "avatar_url": "https://avatars.githubusercontent.com/u/38872121?v=4", "profile": "https://github.com/cesarmg1980", "contributions": [ "doc" ] }, { "login": "marcuslimdw", "name": "Marcus Lim", "avatar_url": "https://avatars.githubusercontent.com/u/42759889?v=4", "profile": "https://gitlab.com/marcuslimdw/", "contributions": [ "doc" ] }, { "login": "hzhou0", "name": "Henry Zhou", "avatar_url": "https://avatars.githubusercontent.com/u/43188301?v=4", "profile": "https://github.com/hzhou0", "contributions": [ "bug", "code" ] }, { "login": "WilliamStam", "name": "William Stam", "avatar_url": "https://avatars.githubusercontent.com/u/182800?v=4", "profile": "https://github.com/WilliamStam", "contributions": [ "doc" ] }, { "login": "andrewdoh", "name": "andrew do", "avatar_url": "https://avatars.githubusercontent.com/u/7662358?v=4", "profile": "https://github.com/andrewdoh", "contributions": [ "code", "test", "doc" ] }, { "login": "cbscsm", "name": "Boseong Choi", "avatar_url": "https://avatars.githubusercontent.com/u/31615733?v=4", "profile": "https://github.com/cbscsm", "contributions": [ "code", "test" ] }, { "login": "wer153", "name": "Kim Minki", "avatar_url": "https://avatars.githubusercontent.com/u/23370765?v=4", "profile": "https://github.com/wer153", "contributions": [ "code", "doc" ] }, { "login": "jseop-lim", "name": "Jeongseop Lim", "avatar_url": "https://avatars.githubusercontent.com/u/86508420?v=4", "profile": "https://velog.io/@azzurri21", "contributions": [ "doc" ] }, { "login": "FergusMok", "name": "FergusMok", "avatar_url": "https://avatars.githubusercontent.com/u/10182564?v=4", "profile": "https://github.com/FergusMok", "contributions": [ "doc", "code", "test" ] }, { "login": "manusinghal19", "name": "Manu Singhal", "avatar_url": "https://avatars.githubusercontent.com/u/8455587?v=4", "profile": "https://github.com/manusinghal19", "contributions": [ "doc" ] }, { "login": "jrycw", "name": "Jerry Wu", "avatar_url": "https://avatars.githubusercontent.com/u/67060418?v=4", "profile": "https://cv.ycwu.space", "contributions": [ "doc" ] }, { "login": "horo-fox", "name": "horo", "avatar_url": "https://avatars.githubusercontent.com/u/143025439?v=4", "profile": "https://github.com/horo-fox", "contributions": [ "bug" ] }, { "login": "rosstitmarsh", "name": "Ross Titmarsh", "avatar_url": "https://avatars.githubusercontent.com/u/23349806?v=4", "profile": "https://github.com/rosstitmarsh", "contributions": [ "code" ] }, { "login": "korneevm", "name": "Mike Korneev", "avatar_url": "https://avatars.githubusercontent.com/u/743250?v=4", "profile": "https://github.com/korneevm", "contributions": [ "doc" ] }, { "login": "patrickneise", "name": "Patrick Neise", "avatar_url": "https://avatars.githubusercontent.com/u/6312074?v=4", "profile": "https://github.com/patrickneise", "contributions": [ "code" ] }, { "login": "JeanArhancet", "name": "Jean Arhancet", "avatar_url": "https://avatars.githubusercontent.com/u/10811879?v=4", "profile": "https://github.com/JeanArhancet", "contributions": [ "bug" ] }, { "login": "betaprior", "name": "Leo Alekseyev", "avatar_url": "https://avatars.githubusercontent.com/u/338250?v=4", "profile": "http://dnquark.com", "contributions": [ "code" ] }, { "login": "aranvir", "name": "aranvir", "avatar_url": "https://avatars.githubusercontent.com/u/75439739?v=4", "profile": "https://github.com/aranvir", "contributions": [ "doc", "code", "test" ] }, { "login": "bunny-therapist", "name": "bunny-therapist", "avatar_url": "https://avatars.githubusercontent.com/u/87039365?v=4", "profile": "https://github.com/bunny-therapist", "contributions": [ "code" ] }, { "login": "benluo", "name": "Ben Luo", "avatar_url": "https://avatars.githubusercontent.com/u/70398?v=4", "profile": "http://www.benluo.cc", "contributions": [ "doc" ] }, { "login": "hugovk", "name": "Hugo van Kemenade", "avatar_url": "https://avatars.githubusercontent.com/u/1324225?v=4", "profile": "https://github.com/hugovk", "contributions": [ "doc" ] }, { "login": "error418", "name": "Michael Gerbig", "avatar_url": "https://avatars.githubusercontent.com/u/7716544?v=4", "profile": "https://error418.github.io", "contributions": [ "doc" ] }, { "login": "crisog", "name": "CrisOG", "avatar_url": "https://avatars.githubusercontent.com/u/40803711?v=4", "profile": "https://github.com/crisog", "contributions": [ "bug", "code", "test" ] }, { "login": "haryle", "name": "harryle", "avatar_url": "https://avatars.githubusercontent.com/u/64817481?v=4", "profile": "https://github.com/haryle", "contributions": [ "code", "test" ] }, { "login": "ubernostrum", "name": "James Bennett", "avatar_url": "https://avatars.githubusercontent.com/u/12384?v=4", "profile": "http://www.b-list.org/", "contributions": [ "bug" ] }, { "login": "sherbang", "name": "sherbang", "avatar_url": "https://avatars.githubusercontent.com/u/275015?v=4", "profile": "https://github.com/sherbang", "contributions": [ "doc" ] }, { "login": "carlsmedstad", "name": "Carl Smedstad", "avatar_url": "https://avatars.githubusercontent.com/u/6952324?v=4", "profile": "https://github.com/carlsmedstad", "contributions": [ "test" ] }, { "login": "maintain0404", "name": "Taein Min", "avatar_url": "https://avatars.githubusercontent.com/u/50428534?v=4", "profile": "https://github.com/maintain0404", "contributions": [ "doc" ] }, { "login": "wallseat", "name": "Stanislav Lyu.", "avatar_url": "https://avatars.githubusercontent.com/u/26143672?v=4", "profile": "https://github.com/wallseat", "contributions": [ "bug" ] }, { "login": "tibor-reiss", "name": "Tibor Reiss", "avatar_url": "https://avatars.githubusercontent.com/u/75096465?v=4", "profile": "https://github.com/tibor-reiss", "contributions": [ "test", "doc", "code" ] }, { "login": "0xE111", "name": "Alex", "avatar_url": "https://avatars.githubusercontent.com/u/11032969?v=4", "profile": "https://pogrom.dev", "contributions": [ "bug", "code" ] }, { "login": "JorenSix", "name": "Joren Six", "avatar_url": "https://avatars.githubusercontent.com/u/60453?v=4", "profile": "http://0110.be", "contributions": [ "doc" ] }, { "login": "jderrien", "name": "jderrien", "avatar_url": "https://avatars.githubusercontent.com/u/145396?v=4", "profile": "https://github.com/jderrien", "contributions": [ "doc" ] }, { "login": "PossiblePanda", "name": "PossiblePanda", "avatar_url": "https://avatars.githubusercontent.com/u/85448494?v=4", "profile": "https://possiblepanda.me", "contributions": [ "doc" ] }, { "login": "evstratbg", "name": "evstrat", "avatar_url": "https://avatars.githubusercontent.com/u/10176401?v=4", "profile": "https://github.com/evstratbg", "contributions": [ "infra" ] }, { "login": "eltociear", "name": "Ikko Eltociear Ashimine", "avatar_url": "https://avatars.githubusercontent.com/u/22633385?v=4", "profile": "https://speakerdeck.com/eltociear", "contributions": [ "doc" ] }, { "login": "taihim", "name": "Taimur Ibrahim", "avatar_url": "https://avatars.githubusercontent.com/u/13764071?v=4", "profile": "https://github.com/taihim", "contributions": [ "doc" ] }, { "login": "l-armstrong", "name": "l-armstrong", "avatar_url": "https://avatars.githubusercontent.com/u/43922258?v=4", "profile": "https://github.com/l-armstrong", "contributions": [ "doc" ] }, { "login": "Anu-cool-007", "name": "Anuranjan Srivastava", "avatar_url": "https://avatars.githubusercontent.com/u/16525919?v=4", "profile": "https://github.com/Anu-cool-007", "contributions": [ "code" ] }, { "login": "Zimzozaur", "name": "Simon Joseph", "avatar_url": "https://avatars.githubusercontent.com/u/106471045?v=4", "profile": "https://github.com/Zimzozaur", "contributions": [ "doc" ] }, { "login": "abelkm99", "name": "Abel Kidanemariam", "avatar_url": "https://avatars.githubusercontent.com/u/41730180?v=4", "profile": "https://github.com/abelkm99", "contributions": [ "code", "test", "doc" ] }, { "login": "trim21", "name": "Trim21", "avatar_url": "https://avatars.githubusercontent.com/u/13553903?v=4", "profile": "https://blog.trim21.me/", "contributions": [ "code", "test" ] }, { "login": "aarcex3", "name": "Agustin Arce", "avatar_url": "https://avatars.githubusercontent.com/u/59893355?v=4", "profile": "http://aarcex3.github.io", "contributions": [ "doc" ] }, { "login": "FarhanAliRaza", "name": "Farhan Ali Raza", "avatar_url": "https://avatars.githubusercontent.com/u/62690310?v=4", "profile": "https://github.com/FarhanAliRaza", "contributions": [ "doc" ] }, { "login": "pogopaule", "name": "Fabian", "avatar_url": "https://avatars.githubusercontent.com/u/576949?v=4", "profile": "https://github.com/pogopaule", "contributions": [ "code" ] }, { "login": "mohammedbabelly20", "name": "Mohammed Babelly", "avatar_url": "https://avatars.githubusercontent.com/u/104768048?v=4", "profile": "https://github.com/mohammedbabelly20", "contributions": [ "code" ] }, { "login": "charles-dyfis-net", "name": "Charles Duffy", "avatar_url": "https://avatars.githubusercontent.com/u/22370?v=4", "profile": "https://keybase.io/charlesdyfisnet", "contributions": [ "code" ] }, { "login": "RenameMe1", "name": "Evgeny Demchenko", "avatar_url": "https://avatars.githubusercontent.com/u/165988121?v=4", "profile": "https://github.com/RenameMe1", "contributions": [ "doc", "test" ] }, { "login": "olzhasar", "name": "Olzhas Arystanov", "avatar_url": "https://avatars.githubusercontent.com/u/12471703?v=4", "profile": "https://olzhasar.com", "contributions": [ "bug", "doc" ] }, { "login": "vikigenius", "name": "Vikash", "avatar_url": "https://avatars.githubusercontent.com/u/12724810?v=4", "profile": "https://github.com/vikigenius", "contributions": [ "code" ] }, { "login": "ftsartek", "name": "Jordan Russell", "avatar_url": "https://avatars.githubusercontent.com/u/20253317?v=4", "profile": "https://github.com/ftsartek", "contributions": [ "doc", "test", "code" ] }, { "login": "sloria", "name": "Steven Loria", "avatar_url": "https://avatars.githubusercontent.com/u/2379650?v=4", "profile": "https://stevenloria.com", "contributions": [ "doc" ] }, { "login": "oek1ng", "name": "oek1ng", "avatar_url": "https://avatars.githubusercontent.com/u/193062679?v=4", "profile": "https://github.com/oek1ng", "contributions": [ "code" ] }, { "login": "Ada-lave", "name": "Vladislav", "avatar_url": "https://avatars.githubusercontent.com/u/113159483?v=4", "profile": "https://github.com/Ada-lave", "contributions": [ "doc" ] }, { "login": "eandersons", "name": "Edgars", "avatar_url": "https://avatars.githubusercontent.com/u/9976861?v=4", "profile": "https://gaitenis.id.lv", "contributions": [ "doc" ] }, { "login": "Jannchie", "name": "Jianqi Pan", "avatar_url": "https://avatars.githubusercontent.com/u/29743310?v=4", "profile": "https://jannchie.com", "contributions": [ "code" ] } ], "contributorsPerLine": 7, "projectName": "litestar", "projectOwner": "litestar-org", "repoType": "github", "repoHost": "https://github.com", "skipCi": true, "commitConvention": "angular", "commitType": "docs" } litestar-2.16.0/.devcontainer/ 0000775 0000000 0000000 00000000000 15005643713 0016172 5 ustar 00root root 0000000 0000000 litestar-2.16.0/.devcontainer/Dockerfile 0000664 0000000 0000000 00000001261 15005643713 0020164 0 ustar 00root root 0000000 0000000 # [Choice] Python version (use -bookworm or -bullseye variants on local arm64/Apple Silicon): 3, 3.13, 3.12, 3.11, 3.10, 3.9, 3.8, 3-bookworm, 3.13-bookworm, 3.12-bookworm, 3.11-bookworm, 3.10-bookworm, 3.9-bookworm, 3.8-bookworm, 3-bullseye, 3.11-bullseye, 3.10-bullseye, 3.9-bullseye, 3.8-bullseye, 3-buster, 3.11-buster, 3.10-buster, 3.9-buster, 3.8-buster ARG VERSION=3.12 ARG VARIANT=-bookworm FROM python:${VERSION}${VARIANT} ARG VERSION ENV UV_LOCKED=1 UV_PYTHON=${VERSION} COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ && apt-get purge -y fish RUN python3 -m pip install --upgrade setuptools cython pip litestar-2.16.0/.devcontainer/devcontainer.json 0000664 0000000 0000000 00000003406 15005643713 0021551 0 ustar 00root root 0000000 0000000 { "name": "litestar-org/litestar", "build": { "dockerfile": "./Dockerfile", "context": "." }, "features": { "ghcr.io/devcontainers/features/common-utils:2": { "installZsh": "true", "username": "vscode", "userUid": "1000", "userGid": "1000", "upgradePackages": "true" }, "ghcr.io/devcontainers/features/github-cli:1": {}, "ghcr.io/devcontainers-contrib/features/pre-commit:2": {}, "ghcr.io/devcontainers/features/python:1": "none", "ghcr.io/devcontainers/features/git:1": { "version": "latest", "ppa": "false" } }, "customizations": { "codespaces": { "openFiles": ["CONTRIBUTING.rst"] }, "vscode": { "extensions": [ "mhutchie.git-graph", "eamodio.gitlens", "github.vscode-github-actions", "ms-python.black-formatter", "ms-python.mypy-type-checker", "charliermarsh.ruff" ], "settings": { "python.editor.defaultFormatter": "charliermarsh.ruff", "python.defaultInterpreterPath": "${workspaceFolder}/.venv", "python.terminal.activateEnvInCurrentTerminal": true, "python.testing.unittestEnabled": false, "python.testing.pytestEnabled": true, "python.testing.pytestArgs": ["."], "python.terminal.launchArgs": ["-X", "dev"], "terminal.integrated.shell.linux": "/bin/bash", "terminal.integrated.profiles.linux": { "bash": { "path": "bash", "icon": "terminal-bash" }, "zsh": { "path": "zsh" }, "fish": { "path": "fish" } } } } }, "forwardPorts": [8000], "postCreateCommand": [ "uv", "sync" ], "remoteUser": "vscode" } litestar-2.16.0/.github/ 0000775 0000000 0000000 00000000000 15005643713 0014773 5 ustar 00root root 0000000 0000000 litestar-2.16.0/.github/CODEOWNERS 0000664 0000000 0000000 00000001076 15005643713 0016372 0 ustar 00root root 0000000 0000000 # Code owner settings for `litestar` # @maintainers should be assigned to all reviews. # Most specific assignment takes precedence though, so if you add a more specific thing than the `*` glob, you must also add @maintainers # For more info about code owners see https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners#codeowners-file-example # Global Assignment * @litestar-org/maintainers @litestar-org/members # Documentation docs/* @litestar-org/maintainers @JacobCoffee @provinzkraut litestar-2.16.0/.github/ISSUE_TEMPLATE/ 0000775 0000000 0000000 00000000000 15005643713 0017156 5 ustar 00root root 0000000 0000000 litestar-2.16.0/.github/ISSUE_TEMPLATE/BUG.yml 0000664 0000000 0000000 00000005122 15005643713 0020316 0 ustar 00root root 0000000 0000000 name: "Bug Report" description: Create an issue for a bug. title: "Bug:
litestar
tag on Stack Overflow",
"link": "https://stackoverflow.com/questions/tagged/litestar",
"icon": "coc",
},
},
},
}
def update_html_context(
app: Sphinx, pagename: str, templatename: str, context: dict[str, Any], doctree: document
) -> None:
context["generate_toctree_html"] = partial(context["generate_toctree_html"], startdepth=0)
def delayed_setup(app: Sphinx) -> None:
"""
When running linkcheck pydata_sphinx_theme causes a build failure, and checking
the builder in the initial `setup` function call is not possible, so the check
and extension setup has to be delayed until the builder is initialized.
"""
if app.builder.name == "linkcheck":
return
app.setup_extension("pydata_sphinx_theme")
app.connect("html-page-context", update_html_context) # type: ignore
def setup(app: Sphinx) -> dict[str, bool]:
app.connect("builder-inited", delayed_setup, priority=0) # type: ignore
app.setup_extension("litestar_sphinx_theme")
return {"parallel_read_safe": True, "parallel_write_safe": True}
litestar-2.16.0/docs/contribution-guide.rst 0000664 0000000 0000000 00000000053 15005643713 0020725 0 ustar 00root root 0000000 0000000 :orphan:
.. include:: ../CONTRIBUTING.rst
litestar-2.16.0/docs/examples/ 0000775 0000000 0000000 00000000000 15005643713 0016201 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0020300 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/application_hooks/ 0000775 0000000 0000000 00000000000 15005643713 0021707 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/application_hooks/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0024006 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/application_hooks/after_exception_hook.py 0000664 0000000 0000000 00000002041 15005643713 0026455 0 ustar 00root root 0000000 0000000 import logging
from typing import TYPE_CHECKING
from litestar import Litestar, get
from litestar.exceptions import HTTPException
from litestar.status_codes import HTTP_400_BAD_REQUEST
logger = logging.getLogger()
if TYPE_CHECKING:
from litestar.types import Scope
@get("/some-path", sync_to_thread=False)
def my_handler() -> None:
"""Route handler that raises an exception."""
raise HTTPException(detail="bad request", status_code=HTTP_400_BAD_REQUEST)
async def after_exception_handler(exc: Exception, scope: "Scope") -> None:
"""Hook function that will be invoked after each exception."""
state = Litestar.from_scope(scope).state
if not hasattr(state, "error_count"):
state.error_count = 1
else:
state.error_count += 1
logger.info(
"an exception of type %s has occurred for requested path %s and the application error count is %d.",
type(exc).__name__,
scope["path"],
state.error_count,
)
app = Litestar([my_handler], after_exception=[after_exception_handler])
litestar-2.16.0/docs/examples/application_hooks/before_send_hook.py 0000664 0000000 0000000 00000002066 15005643713 0025560 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from typing import TYPE_CHECKING
from litestar import Litestar, get
from litestar.datastructures import MutableScopeHeaders
if TYPE_CHECKING:
from typing import Dict
from litestar.types import Message, Scope
@get("/test", sync_to_thread=False)
def handler() -> Dict[str, str]:
"""Example Handler function."""
return {"key": "value"}
async def before_send_hook_handler(message: Message, scope: Scope) -> None:
"""The function will be called on each ASGI message.
We therefore ensure it runs only on the message start event.
"""
if message["type"] == "http.response.start":
headers = MutableScopeHeaders.from_message(message=message)
headers["My Header"] = Litestar.from_scope(scope).state.message
def on_startup(app: Litestar) -> None:
"""A function that will populate the app state before any requests are received."""
app.state.message = "value injected during send"
app = Litestar(route_handlers=[handler], on_startup=[on_startup], before_send=[before_send_hook_handler])
litestar-2.16.0/docs/examples/application_hooks/lifespan_manager.py 0000664 0000000 0000000 00000001076 15005643713 0025560 0 ustar 00root root 0000000 0000000 from contextlib import asynccontextmanager
from typing import AsyncGenerator
from sqlalchemy.ext.asyncio import create_async_engine
from litestar import Litestar
@asynccontextmanager
async def db_connection(app: Litestar) -> AsyncGenerator[None, None]:
engine = getattr(app.state, "engine", None)
if engine is None:
engine = create_async_engine("postgresql+asyncpg://postgres:mysecretpassword@pg.db:5432/db")
app.state.engine = engine
try:
yield
finally:
await engine.dispose()
app = Litestar(lifespan=[db_connection])
litestar-2.16.0/docs/examples/application_hooks/on_app_init.py 0000664 0000000 0000000 00000001225 15005643713 0024560 0 ustar 00root root 0000000 0000000 from typing import TYPE_CHECKING
from litestar import Litestar
if TYPE_CHECKING:
from litestar.config.app import AppConfig
async def close_db_connection() -> None:
"""Closes the database connection on application shutdown."""
def receive_app_config(app_config: "AppConfig") -> "AppConfig":
"""Receives parameters from the application.
In reality, this would be a library of boilerplate that is carried from one application to another, or a third-party
developed application configuration tool.
"""
app_config.on_shutdown.append(close_db_connection)
return app_config
app = Litestar([], on_app_init=[receive_app_config])
litestar-2.16.0/docs/examples/application_state/ 0000775 0000000 0000000 00000000000 15005643713 0021704 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/application_state/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0024003 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/application_state/passing_initial_state.py 0000664 0000000 0000000 00000000432 15005643713 0026632 0 ustar 00root root 0000000 0000000 from typing import Any, Dict
from litestar import Litestar, get
from litestar.datastructures import State
@get("/", sync_to_thread=False)
def handler(state: State) -> Dict[str, Any]:
return state.dict()
app = Litestar(route_handlers=[handler], state=State({"count": 100}))
litestar-2.16.0/docs/examples/application_state/using_application_state.py 0000664 0000000 0000000 00000002705 15005643713 0027172 0 ustar 00root root 0000000 0000000 import logging
from typing import TYPE_CHECKING, Any
from litestar import Litestar, Request, get
from litestar.datastructures import State
from litestar.di import Provide
if TYPE_CHECKING:
from litestar.types import ASGIApp, Receive, Scope, Send
logger = logging.getLogger(__name__)
def set_state_on_startup(app: Litestar) -> None:
"""Startup and shutdown hooks can receive `State` as a keyword arg."""
app.state.value = "abc123"
def middleware_factory(*, app: "ASGIApp") -> "ASGIApp":
"""A middleware can access application state via `scope`."""
async def my_middleware(scope: "Scope", receive: "Receive", send: "Send") -> None:
state = Litestar.from_scope(scope).state
logger.info("state value in middleware: %s", state.value)
await app(scope, receive, send)
return my_middleware
async def my_dependency(state: State) -> Any:
"""Dependencies can receive state via injection."""
logger.info("state value in dependency: %s", state.value)
@get("/", dependencies={"dep": Provide(my_dependency)}, middleware=[middleware_factory], sync_to_thread=False)
def get_handler(state: State, request: Request, dep: Any) -> None:
"""Handlers can receive state via injection."""
logger.info("state value in handler from `State`: %s", state.value)
logger.info("state value in handler from `Request`: %s", request.app.state.value)
app = Litestar(route_handlers=[get_handler], on_startup=[set_state_on_startup])
litestar-2.16.0/docs/examples/application_state/using_custom_state.py 0000664 0000000 0000000 00000000572 15005643713 0026201 0 ustar 00root root 0000000 0000000 from typing import Any, Dict
from litestar import Litestar, get
from litestar.datastructures import State
class MyState(State):
count: int = 0
def increment(self) -> None:
self.count += 1
@get("/", sync_to_thread=False)
def handler(state: MyState) -> Dict[str, Any]:
state.increment()
return state.dict()
app = Litestar(route_handlers=[handler])
litestar-2.16.0/docs/examples/application_state/using_immutable_state.py 0000664 0000000 0000000 00000000507 15005643713 0026644 0 ustar 00root root 0000000 0000000 from typing import Any, Dict
from litestar import Litestar, get
from litestar.datastructures import ImmutableState
@get("/", sync_to_thread=False)
def handler(state: ImmutableState) -> Dict[str, Any]:
setattr(state, "count", 1) # raises AttributeError
return state.dict()
app = Litestar(route_handlers=[handler])
litestar-2.16.0/docs/examples/caching/ 0000775 0000000 0000000 00000000000 15005643713 0017575 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/caching/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0021674 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/caching/cache.py 0000664 0000000 0000000 00000001050 15005643713 0021206 0 ustar 00root root 0000000 0000000 from litestar import Litestar, get
from litestar.config.response_cache import CACHE_FOREVER
@get("/cached", cache=True)
async def my_cached_handler() -> str:
return "cached"
@get("/cached-seconds", cache=120) # seconds
async def my_cached_handler_seconds() -> str:
return "cached for 120 seconds"
@get("/cached-forever", cache=CACHE_FOREVER)
async def my_cached_handler_forever() -> str:
return "cached forever"
app = Litestar(
[my_cached_handler, my_cached_handler_seconds, my_cached_handler_forever],
)
litestar-2.16.0/docs/examples/caching/cache_response_filter.py 0000664 0000000 0000000 00000000754 15005643713 0024503 0 ustar 00root root 0000000 0000000 from litestar import Litestar
from litestar.config.response_cache import ResponseCacheConfig
from litestar.types import HTTPScope
def custom_cache_response_filter(_: HTTPScope, status_code: int) -> bool:
# Cache only 2xx responses
return 200 <= status_code < 300
response_cache_config = ResponseCacheConfig(cache_response_filter=custom_cache_response_filter)
# Create the app with a custom cache response filter
app = Litestar(
response_cache_config=response_cache_config,
)
litestar-2.16.0/docs/examples/caching/key_builder.py 0000664 0000000 0000000 00000000467 15005643713 0022454 0 ustar 00root root 0000000 0000000 from litestar import Litestar, Request
from litestar.config.response_cache import ResponseCacheConfig
def key_builder(request: Request) -> str:
return request.url.path + request.headers.get("my-header", "")
app = Litestar([], response_cache_config=ResponseCacheConfig(key_builder=key_builder))
litestar-2.16.0/docs/examples/caching/key_builder_for_route_handler.py 0000664 0000000 0000000 00000000504 15005643713 0026225 0 ustar 00root root 0000000 0000000 from litestar import Litestar, Request, get
def key_builder(request: Request) -> str:
return request.url.path + request.headers.get("my-header", "")
@get("/cached-path", cache=True, cache_key_builder=key_builder)
async def cached_handler() -> str:
return "cached"
app = Litestar([cached_handler])
litestar-2.16.0/docs/examples/caching/redis_store.py 0000664 0000000 0000000 00000001040 15005643713 0022464 0 ustar 00root root 0000000 0000000 import asyncio
from litestar import Litestar, get
from litestar.config.response_cache import ResponseCacheConfig
from litestar.stores.redis import RedisStore
@get(cache=10)
async def something() -> str:
await asyncio.sleep(1)
return "something"
redis_store = RedisStore.with_client(url="redis://localhost/", port=6379, db=0)
cache_config = ResponseCacheConfig(store="redis_backed_store")
app = Litestar(
[something],
stores={"redis_backed_store": redis_store},
response_cache_config=cache_config,
)
litestar-2.16.0/docs/examples/channels/ 0000775 0000000 0000000 00000000000 15005643713 0017774 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/channels/create_route_handlers.py 0000664 0000000 0000000 00000000504 15005643713 0024706 0 ustar 00root root 0000000 0000000 from litestar import Litestar
from litestar.channels import ChannelsPlugin
from litestar.channels.backends.memory import MemoryChannelsBackend
channels_plugin = ChannelsPlugin(
backend=MemoryChannelsBackend(),
channels=["foo", "bar"],
create_ws_route_handlers=True,
)
app = Litestar(plugins=[channels_plugin])
litestar-2.16.0/docs/examples/channels/create_route_handlers_send_history.py 0000664 0000000 0000000 00000000742 15005643713 0027504 0 ustar 00root root 0000000 0000000 from litestar import Litestar
from litestar.channels import ChannelsPlugin
from litestar.channels.backends.memory import MemoryChannelsBackend
channels_plugin = ChannelsPlugin(
backend=MemoryChannelsBackend(history=10), # set the amount of messages per channel
# to keep in the backend
channels=["foo", "bar"],
create_ws_route_handlers=True,
ws_handler_send_history=10, # send 10 entries of the history by default
)
app = Litestar(plugins=[channels_plugin])
litestar-2.16.0/docs/examples/channels/iter_stream.py 0000664 0000000 0000000 00000001055 15005643713 0022665 0 ustar 00root root 0000000 0000000 from litestar import Litestar, WebSocket, websocket
from litestar.channels import ChannelsPlugin
from litestar.channels.backends.memory import MemoryChannelsBackend
@websocket("/ws")
async def handler(socket: WebSocket, channels: ChannelsPlugin) -> None:
await socket.accept()
async with channels.start_subscription(["some_channel"]) as subscriber:
async for message in subscriber.iter_events():
await socket.send_text(message)
app = Litestar(
[handler],
plugins=[ChannelsPlugin(backend=MemoryChannelsBackend())],
)
litestar-2.16.0/docs/examples/channels/put_history.py 0000664 0000000 0000000 00000001052 15005643713 0022735 0 ustar 00root root 0000000 0000000 from litestar import Litestar, WebSocket, websocket
from litestar.channels import ChannelsPlugin
from litestar.channels.backends.memory import MemoryChannelsBackend
@websocket("/ws")
async def handler(socket: WebSocket, channels: ChannelsPlugin) -> None:
await socket.accept()
async with channels.start_subscription(["some_channel"]) as subscriber:
await channels.put_subscriber_history(subscriber, ["some_channel"], limit=10)
app = Litestar(
[handler],
plugins=[ChannelsPlugin(backend=MemoryChannelsBackend(history=20))],
)
litestar-2.16.0/docs/examples/channels/run_in_background.py 0000664 0000000 0000000 00000001227 15005643713 0024041 0 ustar 00root root 0000000 0000000 from litestar import Litestar, WebSocket, websocket
from litestar.channels import ChannelsPlugin
from litestar.channels.backends.memory import MemoryChannelsBackend
@websocket("/ws")
async def handler(socket: WebSocket, channels: ChannelsPlugin) -> None:
await socket.accept()
async with channels.start_subscription(["some_channel"]) as subscriber, subscriber.run_in_background(
socket.send_text
):
while True:
response = await socket.receive_text()
await socket.send_text(response)
app = Litestar(
[handler],
plugins=[ChannelsPlugin(backend=MemoryChannelsBackend(), channels=["some_channel"])],
)
litestar-2.16.0/docs/examples/contrib/ 0000775 0000000 0000000 00000000000 15005643713 0017641 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/contrib/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0021740 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/contrib/piccolo/ 0000775 0000000 0000000 00000000000 15005643713 0021271 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/contrib/piccolo/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0023370 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/contrib/piccolo/app.py 0000664 0000000 0000000 00000003573 15005643713 0022433 0 ustar 00root root 0000000 0000000 from typing import List
from piccolo.columns import Boolean, Varchar
from piccolo.table import Table, create_db_tables
from litestar import Litestar, MediaType, delete, get, patch, post
from litestar.contrib.piccolo import PiccoloDTO
from litestar.dto import DTOConfig, DTOData
from litestar.exceptions import NotFoundException
from .piccolo_conf import DB
class Task(Table, db=DB):
"""
An example table.
"""
name = Varchar()
completed = Boolean(default=False)
class PatchDTO(PiccoloDTO[Task]):
"""Allow partial updates."""
config = DTOConfig(exclude={"id"}, partial=True)
@get(
"/tasks",
return_dto=PiccoloDTO[Task],
media_type=MediaType.JSON,
tags=["Task"],
)
async def tasks() -> List[Task]:
return await Task.select().order_by(Task.id, ascending=False)
@post(
"/tasks",
dto=PiccoloDTO[Task],
return_dto=PiccoloDTO[Task],
media_type=MediaType.JSON,
tags=["Task"],
)
async def create_task(data: Task) -> Task:
await data.save()
await data.refresh()
return data
@patch(
"/tasks/{task_id:int}",
dto=PatchDTO,
return_dto=PiccoloDTO[Task],
media_type=MediaType.JSON,
tags=["Task"],
)
async def update_task(task_id: int, data: DTOData[Task]) -> Task:
task = await Task.objects().get(Task.id == task_id)
if not task:
raise NotFoundException("Task does not exist")
result = data.update_instance(task)
await result.save()
return result
@delete("/tasks/{task_id:int}", tags=["Task"])
async def delete_task(task_id: int) -> None:
task = await Task.objects().get(Task.id == task_id)
if not task:
raise NotFoundException("Task does not exist")
await task.remove()
async def on_startup():
await create_db_tables(Task, if_not_exists=True)
app = Litestar(route_handlers=[tasks, create_task, delete_task, update_task], on_startup=[on_startup], debug=True)
litestar-2.16.0/docs/examples/contrib/piccolo/piccolo_conf.py 0000664 0000000 0000000 00000000104 15005643713 0024273 0 ustar 00root root 0000000 0000000 from piccolo.engine.sqlite import SQLiteEngine
DB = SQLiteEngine()
litestar-2.16.0/docs/examples/contrib/sqlalchemy/ 0000775 0000000 0000000 00000000000 15005643713 0022003 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/contrib/sqlalchemy/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0024102 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/contrib/sqlalchemy/plugins/ 0000775 0000000 0000000 00000000000 15005643713 0023464 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/contrib/sqlalchemy/plugins/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0025563 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/contrib/sqlalchemy/plugins/sqlalchemy_async_before_send_handler.py 0000664 0000000 0000000 00000000701 15005643713 0033423 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from litestar import Litestar
from litestar.plugins.sqlalchemy import (
SQLAlchemyAsyncConfig,
SQLAlchemyInitPlugin,
async_autocommit_before_send_handler,
)
config = SQLAlchemyAsyncConfig(
connection_string="sqlite+aiosqlite:///:memory:", before_send_handler=async_autocommit_before_send_handler
)
plugin = SQLAlchemyInitPlugin(config=config)
app = Litestar(route_handlers=[], plugins=[plugin])
litestar-2.16.0/docs/examples/contrib/sqlalchemy/plugins/sqlalchemy_async_dependencies.py 0000664 0000000 0000000 00000001443 15005643713 0032105 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from typing import TYPE_CHECKING
from sqlalchemy import select
from litestar import Litestar, post
from litestar.plugins.sqlalchemy import SQLAlchemyAsyncConfig, SQLAlchemyInitPlugin
if TYPE_CHECKING:
from typing import Tuple
from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession
@post("/")
async def handler(db_session: AsyncSession, db_engine: AsyncEngine) -> Tuple[int, int]:
one = (await db_session.execute(select(1))).scalar()
async with db_engine.begin() as conn:
two = (await conn.execute(select(2))).scalar()
return one, two
config = SQLAlchemyAsyncConfig(connection_string="sqlite+aiosqlite:///async.sqlite")
plugin = SQLAlchemyInitPlugin(config=config)
app = Litestar(route_handlers=[handler], plugins=[plugin])
litestar-2.16.0/docs/examples/contrib/sqlalchemy/plugins/sqlalchemy_async_init_plugin_example.py 0000664 0000000 0000000 00000002467 15005643713 0033522 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from typing import TYPE_CHECKING
from sqlalchemy import select
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from litestar import Litestar, post
from litestar.plugins.sqlalchemy import SQLAlchemyAsyncConfig, SQLAlchemyInitPlugin
if TYPE_CHECKING:
from typing import Any, Dict, List
from sqlalchemy.ext.asyncio import AsyncSession
class Base(DeclarativeBase): ...
class TodoItem(Base):
__tablename__ = "todo_item"
title: Mapped[str] = mapped_column(primary_key=True)
done: Mapped[bool]
@post("/")
async def add_item(data: Dict[str, Any], db_session: AsyncSession) -> List[Dict[str, Any]]:
todo_item = TodoItem(**data)
async with db_session.begin():
db_session.add(todo_item)
return [
{
"title": item.title,
"done": item.done,
}
for item in (await db_session.execute(select(TodoItem))).scalars()
]
async def init_db(app: Litestar) -> None:
async with config.get_engine().begin() as conn:
await conn.run_sync(Base.metadata.create_all)
config = SQLAlchemyAsyncConfig(connection_string="sqlite+aiosqlite:///todo_async.sqlite")
plugin = SQLAlchemyInitPlugin(config=config)
app = Litestar(route_handlers=[add_item], plugins=[plugin], on_startup=[init_db], debug=True)
litestar-2.16.0/docs/examples/contrib/sqlalchemy/plugins/sqlalchemy_async_plugin_example.py 0000664 0000000 0000000 00000001760 15005643713 0032472 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from typing import TYPE_CHECKING, Sequence
from sqlalchemy import select
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from litestar import Litestar, post
from litestar.plugins.sqlalchemy import SQLAlchemyAsyncConfig, SQLAlchemyPlugin
if TYPE_CHECKING:
from sqlalchemy.ext.asyncio import AsyncSession
class Base(DeclarativeBase): ...
class TodoItem(Base):
__tablename__ = "todo_item"
title: Mapped[str] = mapped_column(primary_key=True)
done: Mapped[bool]
@post("/")
async def add_item(data: TodoItem, db_session: AsyncSession) -> Sequence[TodoItem]:
async with db_session.begin():
db_session.add(data)
return (await db_session.execute(select(TodoItem))).scalars().all()
config = SQLAlchemyAsyncConfig(
connection_string="sqlite+aiosqlite:///todo_async.sqlite", create_all=True, metadata=Base.metadata
)
plugin = SQLAlchemyPlugin(config=config)
app = Litestar(route_handlers=[add_item], plugins=[plugin])
litestar-2.16.0/docs/examples/contrib/sqlalchemy/plugins/sqlalchemy_async_serialization_dto.py 0000664 0000000 0000000 00000001133 15005643713 0033176 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from typing import TYPE_CHECKING
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from litestar import Litestar, post
from litestar.plugins.sqlalchemy import SQLAlchemyDTO
if TYPE_CHECKING:
from typing import List
class Base(DeclarativeBase): ...
class TodoItem(Base):
__tablename__ = "todo_item"
title: Mapped[str] = mapped_column(primary_key=True)
done: Mapped[bool]
@post("/", dto=SQLAlchemyDTO[TodoItem])
async def add_item(data: TodoItem) -> List[TodoItem]:
return [data]
app = Litestar(route_handlers=[add_item])
litestar-2.16.0/docs/examples/contrib/sqlalchemy/plugins/sqlalchemy_async_serialization_plugin.py 0000664 0000000 0000000 00000001171 15005643713 0033710 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from typing import TYPE_CHECKING
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from litestar import Litestar, post
from litestar.plugins.sqlalchemy import SQLAlchemySerializationPlugin
if TYPE_CHECKING:
from typing import List
class Base(DeclarativeBase): ...
class TodoItem(Base):
__tablename__ = "todo_item"
title: Mapped[str] = mapped_column(primary_key=True)
done: Mapped[bool]
@post("/")
async def add_item(data: TodoItem) -> List[TodoItem]:
return [data]
app = Litestar(route_handlers=[add_item], plugins=[SQLAlchemySerializationPlugin()])
sqlalchemy_async_serialization_plugin_marking_fields.py 0000664 0000000 0000000 00000001434 15005643713 0036671 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/contrib/sqlalchemy/plugins from __future__ import annotations
from typing import TYPE_CHECKING
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from litestar import Litestar, post
from litestar.dto import dto_field
from litestar.plugins.sqlalchemy import SQLAlchemySerializationPlugin
if TYPE_CHECKING:
from typing import List
class Base(DeclarativeBase): ...
class TodoItem(Base):
__tablename__ = "todo_item"
title: Mapped[str] = mapped_column(primary_key=True)
done: Mapped[bool]
super_secret_value: Mapped[str] = mapped_column(info=dto_field("private"))
@post("/")
async def add_item(data: TodoItem) -> List[TodoItem]:
data.super_secret_value = "This is a secret"
return [data]
app = Litestar(route_handlers=[add_item], plugins=[SQLAlchemySerializationPlugin()])
litestar-2.16.0/docs/examples/contrib/sqlalchemy/plugins/sqlalchemy_sync_before_send_handler.py 0000664 0000000 0000000 00000000647 15005643713 0033273 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from litestar import Litestar
from litestar.plugins.sqlalchemy import SQLAlchemyInitPlugin, SQLAlchemySyncConfig, sync_autocommit_before_send_handler
config = SQLAlchemySyncConfig(
connection_string="sqlite:///:memory:",
before_send_handler=sync_autocommit_before_send_handler,
)
plugin = SQLAlchemyInitPlugin(config=config)
app = Litestar(route_handlers=[], plugins=[plugin])
litestar-2.16.0/docs/examples/contrib/sqlalchemy/plugins/sqlalchemy_sync_dependencies.py 0000664 0000000 0000000 00000001415 15005643713 0031743 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from typing import TYPE_CHECKING
from sqlalchemy import select
from litestar import Litestar, post
from litestar.plugins.sqlalchemy import SQLAlchemyInitPlugin, SQLAlchemySyncConfig
if TYPE_CHECKING:
from typing import Tuple
from sqlalchemy import Engine
from sqlalchemy.orm import Session
@post("/", sync_to_thread=True)
def handler(db_session: Session, db_engine: Engine) -> Tuple[int, int]:
one = db_session.execute(select(1)).scalar()
with db_engine.begin() as conn:
two = conn.execute(select(2)).scalar()
return one, two
config = SQLAlchemySyncConfig(connection_string="sqlite:///sync.sqlite")
plugin = SQLAlchemyInitPlugin(config=config)
app = Litestar(route_handlers=[handler], plugins=[plugin])
litestar-2.16.0/docs/examples/contrib/sqlalchemy/plugins/sqlalchemy_sync_init_plugin_example.py 0000664 0000000 0000000 00000002362 15005643713 0033353 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from typing import TYPE_CHECKING
from sqlalchemy import select
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from litestar import Litestar, post
from litestar.plugins.sqlalchemy import SQLAlchemyInitPlugin, SQLAlchemySyncConfig
if TYPE_CHECKING:
from typing import Any, Dict, List
from sqlalchemy.orm import Session
class Base(DeclarativeBase): ...
class TodoItem(Base):
__tablename__ = "todo_item"
title: Mapped[str] = mapped_column(primary_key=True)
done: Mapped[bool]
@post("/", sync_to_thread=True)
def add_item(data: Dict[str, Any], db_session: Session) -> List[Dict[str, Any]]:
todo_item = TodoItem(**data)
with db_session.begin():
db_session.add(todo_item)
return [
{
"title": item.title,
"done": item.done,
}
for item in db_session.execute(select(TodoItem)).scalars()
]
def init_db(app: Litestar) -> None:
with config.get_engine().begin() as conn:
Base.metadata.create_all(conn)
config = SQLAlchemySyncConfig(connection_string="sqlite:///todo_sync.sqlite")
plugin = SQLAlchemyInitPlugin(config=config)
app = Litestar(route_handlers=[add_item], plugins=[plugin], on_startup=[init_db])
litestar-2.16.0/docs/examples/contrib/sqlalchemy/plugins/sqlalchemy_sync_plugin_example.py 0000664 0000000 0000000 00000001714 15005643713 0032330 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from typing import TYPE_CHECKING, Sequence
from sqlalchemy import select
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from litestar import Litestar, post
from litestar.plugins.sqlalchemy import SQLAlchemyPlugin, SQLAlchemySyncConfig
if TYPE_CHECKING:
from sqlalchemy.orm import Session
class Base(DeclarativeBase): ...
class TodoItem(Base):
__tablename__ = "todo_item"
title: Mapped[str] = mapped_column(primary_key=True)
done: Mapped[bool]
@post("/", sync_to_thread=True)
def add_item(data: TodoItem, db_session: Session) -> Sequence[TodoItem]:
with db_session.begin():
db_session.add(data)
return db_session.execute(select(TodoItem)).scalars().all()
config = SQLAlchemySyncConfig(connection_string="sqlite:///todo_sync.sqlite", create_all=True, metadata=Base.metadata)
plugin = SQLAlchemyPlugin(config=config)
app = Litestar(route_handlers=[add_item], plugins=[plugin])
litestar-2.16.0/docs/examples/contrib/sqlalchemy/plugins/sqlalchemy_sync_serialization_plugin.py 0000664 0000000 0000000 00000001211 15005643713 0033542 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from typing import TYPE_CHECKING
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from litestar import Litestar, post
from litestar.plugins.sqlalchemy import SQLAlchemySerializationPlugin
if TYPE_CHECKING:
from typing import List
class Base(DeclarativeBase): ...
class TodoItem(Base):
__tablename__ = "todo_item"
title: Mapped[str] = mapped_column(primary_key=True)
done: Mapped[bool]
@post("/", sync_to_thread=False)
def add_item(data: TodoItem) -> List[TodoItem]:
return [data]
app = Litestar(route_handlers=[add_item], plugins=[SQLAlchemySerializationPlugin()])
sqlalchemy_sync_serialization_plugin_marking_fields.py 0000664 0000000 0000000 00000001454 15005643713 0036532 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/contrib/sqlalchemy/plugins from __future__ import annotations
from typing import TYPE_CHECKING
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from litestar import Litestar, post
from litestar.dto import dto_field
from litestar.plugins.sqlalchemy import SQLAlchemySerializationPlugin
if TYPE_CHECKING:
from typing import List
class Base(DeclarativeBase): ...
class TodoItem(Base):
__tablename__ = "todo_item"
title: Mapped[str] = mapped_column(primary_key=True)
done: Mapped[bool]
super_secret_value: Mapped[str] = mapped_column(info=dto_field("private"))
@post("/", sync_to_thread=False)
def add_item(data: TodoItem) -> List[TodoItem]:
data.super_secret_value = "This is a secret"
return [data]
app = Litestar(route_handlers=[add_item], plugins=[SQLAlchemySerializationPlugin()])
litestar-2.16.0/docs/examples/contrib/sqlalchemy/plugins/tutorial/ 0000775 0000000 0000000 00000000000 15005643713 0025327 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/contrib/sqlalchemy/plugins/tutorial/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0027426 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/contrib/sqlalchemy/plugins/tutorial/full_app_no_plugins.py 0000664 0000000 0000000 00000006252 15005643713 0031745 0 ustar 00root root 0000000 0000000 from contextlib import asynccontextmanager
from typing import Any, AsyncGenerator, Dict, List, Optional, Sequence
from sqlalchemy import select
from sqlalchemy.exc import IntegrityError, NoResultFound
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from litestar import Litestar, get, post, put
from litestar.datastructures import State
from litestar.exceptions import ClientException, NotFoundException
from litestar.status_codes import HTTP_409_CONFLICT
TodoType = Dict[str, Any]
TodoCollectionType = List[TodoType]
class Base(DeclarativeBase): ...
class TodoItem(Base):
__tablename__ = "todo_items"
title: Mapped[str] = mapped_column(primary_key=True)
done: Mapped[bool]
@asynccontextmanager
async def db_connection(app: Litestar) -> AsyncGenerator[None, None]:
engine = getattr(app.state, "engine", None)
if engine is None:
engine = create_async_engine("sqlite+aiosqlite:///todo.sqlite", echo=True)
app.state.engine = engine
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
try:
yield
finally:
await engine.dispose()
sessionmaker = async_sessionmaker(expire_on_commit=False)
def serialize_todo(todo: TodoItem) -> TodoType:
return {"title": todo.title, "done": todo.done}
async def get_todo_by_title(todo_name: str, session: AsyncSession) -> TodoItem:
query = select(TodoItem).where(TodoItem.title == todo_name)
result = await session.execute(query)
try:
return result.scalar_one()
except NoResultFound as e:
raise NotFoundException(detail=f"TODO {todo_name!r} not found") from e
async def get_todo_list(done: Optional[bool], session: AsyncSession) -> Sequence[TodoItem]:
query = select(TodoItem)
if done is not None:
query = query.where(TodoItem.done.is_(done))
result = await session.execute(query)
return result.scalars().all()
@get("/")
async def get_list(state: State, done: Optional[bool] = None) -> TodoCollectionType:
async with sessionmaker(bind=state.engine) as session:
return [serialize_todo(todo) for todo in await get_todo_list(done, session)]
@post("/")
async def add_item(data: TodoType, state: State) -> TodoType:
new_todo = TodoItem(title=data["title"], done=data["done"])
async with sessionmaker(bind=state.engine) as session:
try:
async with session.begin():
session.add(new_todo)
except IntegrityError as e:
raise ClientException(
status_code=HTTP_409_CONFLICT,
detail=f"TODO {new_todo.title!r} already exists",
) from e
return serialize_todo(new_todo)
@put("/{item_title:str}")
async def update_item(item_title: str, data: TodoType, state: State) -> TodoType:
async with sessionmaker(bind=state.engine) as session, session.begin():
todo_item = await get_todo_by_title(item_title, session)
todo_item.title = data["title"]
todo_item.done = data["done"]
return serialize_todo(todo_item)
app = Litestar([get_list, add_item, update_item], lifespan=[db_connection])
litestar-2.16.0/docs/examples/contrib/sqlalchemy/plugins/tutorial/full_app_with_init_plugin.py 0000664 0000000 0000000 00000005032 15005643713 0033137 0 ustar 00root root 0000000 0000000 from typing import AsyncGenerator, List, Optional
from sqlalchemy import select
from sqlalchemy.exc import IntegrityError, NoResultFound
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from litestar import Litestar, get, post, put
from litestar.exceptions import ClientException, NotFoundException
from litestar.plugins.sqlalchemy import (
SQLAlchemyAsyncConfig,
SQLAlchemyInitPlugin,
SQLAlchemySerializationPlugin,
)
from litestar.status_codes import HTTP_409_CONFLICT
class Base(DeclarativeBase): ...
class TodoItem(Base):
__tablename__ = "todo_items"
title: Mapped[str] = mapped_column(primary_key=True)
done: Mapped[bool]
async def provide_transaction(db_session: AsyncSession) -> AsyncGenerator[AsyncSession, None]:
try:
async with db_session.begin():
yield db_session
except IntegrityError as exc:
raise ClientException(
status_code=HTTP_409_CONFLICT,
detail=str(exc),
) from exc
async def get_todo_by_title(todo_name: str, session: AsyncSession) -> TodoItem:
query = select(TodoItem).where(TodoItem.title == todo_name)
result = await session.execute(query)
try:
return result.scalar_one()
except NoResultFound as e:
raise NotFoundException(detail=f"TODO {todo_name!r} not found") from e
async def get_todo_list(done: Optional[bool], session: AsyncSession) -> List[TodoItem]:
query = select(TodoItem)
if done is not None:
query = query.where(TodoItem.done.is_(done))
result = await session.execute(query)
return list(result.scalars().all())
@get("/")
async def get_list(transaction: AsyncSession, done: Optional[bool] = None) -> List[TodoItem]:
return await get_todo_list(done, transaction)
@post("/")
async def add_item(data: TodoItem, transaction: AsyncSession) -> TodoItem:
transaction.add(data)
return data
@put("/{item_title:str}")
async def update_item(item_title: str, data: TodoItem, transaction: AsyncSession) -> TodoItem:
todo_item = await get_todo_by_title(item_title, transaction)
todo_item.title = data.title
todo_item.done = data.done
return todo_item
db_config = SQLAlchemyAsyncConfig(
connection_string="sqlite+aiosqlite:///todo.sqlite", metadata=Base.metadata, create_all=True
)
app = Litestar(
[get_list, add_item, update_item],
dependencies={"transaction": provide_transaction},
plugins=[
SQLAlchemySerializationPlugin(),
SQLAlchemyInitPlugin(db_config),
],
)
litestar-2.16.0/docs/examples/contrib/sqlalchemy/plugins/tutorial/full_app_with_plugin.py 0000664 0000000 0000000 00000004731 15005643713 0032121 0 ustar 00root root 0000000 0000000 from typing import AsyncGenerator, List, Optional
from sqlalchemy import select
from sqlalchemy.exc import IntegrityError, NoResultFound
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from litestar import Litestar, get, post, put
from litestar.exceptions import ClientException, NotFoundException
from litestar.plugins.sqlalchemy import SQLAlchemyAsyncConfig, SQLAlchemyPlugin
from litestar.status_codes import HTTP_409_CONFLICT
class Base(DeclarativeBase): ...
class TodoItem(Base):
__tablename__ = "todo_items"
title: Mapped[str] = mapped_column(primary_key=True)
done: Mapped[bool]
async def provide_transaction(db_session: AsyncSession) -> AsyncGenerator[AsyncSession, None]:
try:
async with db_session.begin():
yield db_session
except IntegrityError as exc:
raise ClientException(
status_code=HTTP_409_CONFLICT,
detail=str(exc),
) from exc
async def get_todo_by_title(todo_name: str, session: AsyncSession) -> TodoItem:
query = select(TodoItem).where(TodoItem.title == todo_name)
result = await session.execute(query)
try:
return result.scalar_one()
except NoResultFound as e:
raise NotFoundException(detail=f"TODO {todo_name!r} not found") from e
async def get_todo_list(done: Optional[bool], session: AsyncSession) -> List[TodoItem]:
query = select(TodoItem)
if done is not None:
query = query.where(TodoItem.done.is_(done))
result = await session.execute(query)
return list(result.scalars().all())
@get("/")
async def get_list(transaction: AsyncSession, done: Optional[bool] = None) -> List[TodoItem]:
return await get_todo_list(done, transaction)
@post("/")
async def add_item(data: TodoItem, transaction: AsyncSession) -> TodoItem:
transaction.add(data)
return data
@put("/{item_title:str}")
async def update_item(item_title: str, data: TodoItem, transaction: AsyncSession) -> TodoItem:
todo_item = await get_todo_by_title(item_title, transaction)
todo_item.title = data.title
todo_item.done = data.done
return todo_item
db_config = SQLAlchemyAsyncConfig(
connection_string="sqlite+aiosqlite:///todo.sqlite",
metadata=Base.metadata,
create_all=True,
before_send_handler="autocommit",
)
app = Litestar(
[get_list, add_item, update_item],
dependencies={"transaction": provide_transaction},
plugins=[SQLAlchemyPlugin(db_config)],
)
full_app_with_serialization_plugin.py 0000664 0000000 0000000 00000005771 15005643713 0035004 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/contrib/sqlalchemy/plugins/tutorial from contextlib import asynccontextmanager
from typing import AsyncGenerator, List, Optional
from sqlalchemy import select
from sqlalchemy.exc import IntegrityError, NoResultFound
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from litestar import Litestar, get, post, put
from litestar.datastructures import State
from litestar.exceptions import ClientException, NotFoundException
from litestar.plugins.sqlalchemy import SQLAlchemySerializationPlugin
from litestar.status_codes import HTTP_409_CONFLICT
class Base(DeclarativeBase): ...
class TodoItem(Base):
__tablename__ = "todo_items"
title: Mapped[str] = mapped_column(primary_key=True)
done: Mapped[bool]
@asynccontextmanager
async def db_connection(app: Litestar) -> AsyncGenerator[None, None]:
engine = getattr(app.state, "engine", None)
if engine is None:
engine = create_async_engine("sqlite+aiosqlite:///todo.sqlite", echo=True)
app.state.engine = engine
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
try:
yield
finally:
await engine.dispose()
sessionmaker = async_sessionmaker(expire_on_commit=False)
async def provide_transaction(state: State) -> AsyncGenerator[AsyncSession, None]:
async with sessionmaker(bind=state.engine) as session:
try:
async with session.begin():
yield session
except IntegrityError as exc:
raise ClientException(
status_code=HTTP_409_CONFLICT,
detail=str(exc),
) from exc
async def get_todo_by_title(todo_name: str, session: AsyncSession) -> TodoItem:
query = select(TodoItem).where(TodoItem.title == todo_name)
result = await session.execute(query)
try:
return result.scalar_one()
except NoResultFound as e:
raise NotFoundException(detail=f"TODO {todo_name!r} not found") from e
async def get_todo_list(done: Optional[bool], session: AsyncSession) -> List[TodoItem]:
query = select(TodoItem)
if done is not None:
query = query.where(TodoItem.done.is_(done))
result = await session.execute(query)
return list(result.scalars().all())
@get("/")
async def get_list(transaction: AsyncSession, done: Optional[bool] = None) -> List[TodoItem]:
return await get_todo_list(done, transaction)
@post("/")
async def add_item(data: TodoItem, transaction: AsyncSession) -> TodoItem:
transaction.add(data)
return data
@put("/{item_title:str}")
async def update_item(item_title: str, data: TodoItem, transaction: AsyncSession) -> TodoItem:
todo_item = await get_todo_by_title(item_title, transaction)
todo_item.title = data.title
todo_item.done = data.done
return todo_item
app = Litestar(
[get_list, add_item, update_item],
dependencies={"transaction": provide_transaction},
lifespan=[db_connection],
plugins=[SQLAlchemySerializationPlugin()],
)
litestar-2.16.0/docs/examples/contrib/sqlalchemy/plugins/tutorial/full_app_with_session_di.py 0000664 0000000 0000000 00000006263 15005643713 0032764 0 ustar 00root root 0000000 0000000 from contextlib import asynccontextmanager
from typing import Any, AsyncGenerator, Dict, List, Optional
from sqlalchemy import select
from sqlalchemy.exc import IntegrityError, NoResultFound
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from litestar import Litestar, get, post, put
from litestar.datastructures import State
from litestar.exceptions import ClientException, NotFoundException
from litestar.status_codes import HTTP_409_CONFLICT
TodoType = Dict[str, Any]
TodoCollectionType = List[TodoType]
class Base(DeclarativeBase): ...
class TodoItem(Base):
__tablename__ = "todo_items"
title: Mapped[str] = mapped_column(primary_key=True)
done: Mapped[bool]
@asynccontextmanager
async def db_connection(app: Litestar) -> AsyncGenerator[None, None]:
engine = getattr(app.state, "engine", None)
if engine is None:
engine = create_async_engine("sqlite+aiosqlite:///todo.sqlite")
app.state.engine = engine
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
try:
yield
finally:
await engine.dispose()
sessionmaker = async_sessionmaker(expire_on_commit=False)
async def provide_transaction(state: State) -> AsyncGenerator[AsyncSession, None]:
async with sessionmaker(bind=state.engine) as session:
try:
async with session.begin():
yield session
except IntegrityError as exc:
raise ClientException(
status_code=HTTP_409_CONFLICT,
detail=str(exc),
) from exc
def serialize_todo(todo: TodoItem) -> TodoType:
return {"title": todo.title, "done": todo.done}
async def get_todo_by_title(todo_name, session: AsyncSession) -> TodoItem:
query = select(TodoItem).where(TodoItem.title == todo_name)
result = await session.execute(query)
try:
return result.scalar_one()
except NoResultFound as e:
raise NotFoundException(detail=f"TODO {todo_name!r} not found") from e
async def get_todo_list(done: Optional[bool], session: AsyncSession) -> List[TodoItem]:
query = select(TodoItem)
if done is not None:
query = query.where(TodoItem.done.is_(done))
result = await session.execute(query)
return result.scalars().all()
@get("/")
async def get_list(transaction: AsyncSession, done: Optional[bool] = None) -> TodoCollectionType:
return [serialize_todo(todo) for todo in await get_todo_list(done, transaction)]
@post("/")
async def add_item(data: TodoType, transaction: AsyncSession) -> TodoType:
new_todo = TodoItem(title=data["title"], done=data["done"])
transaction.add(new_todo)
return serialize_todo(new_todo)
@put("/{item_title:str}")
async def update_item(item_title: str, data: TodoType, transaction: AsyncSession) -> TodoType:
todo_item = await get_todo_by_title(item_title, transaction)
todo_item.title = data["title"]
todo_item.done = data["done"]
return serialize_todo(todo_item)
app = Litestar(
[get_list, add_item, update_item],
dependencies={"transaction": provide_transaction},
lifespan=[db_connection],
)
litestar-2.16.0/docs/examples/contrib/sqlalchemy/sqlalchemy_async_repository.py 0000664 0000000 0000000 00000015731 15005643713 0030222 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from datetime import date
from typing import TYPE_CHECKING
from uuid import UUID
from pydantic import BaseModel as _BaseModel
from pydantic import TypeAdapter
from sqlalchemy import ForeignKey, select
from sqlalchemy.orm import Mapped, mapped_column, relationship, selectinload
from litestar import Litestar, get
from litestar.controller import Controller
from litestar.di import Provide
from litestar.handlers.http_handlers.decorators import delete, patch, post
from litestar.pagination import OffsetPagination
from litestar.params import Parameter
from litestar.plugins.sqlalchemy import (
AsyncSessionConfig,
SQLAlchemyAsyncConfig,
SQLAlchemyInitPlugin,
base,
filters,
repository,
)
if TYPE_CHECKING:
from sqlalchemy.ext.asyncio import AsyncSession
class BaseModel(_BaseModel):
"""Extend Pydantic's BaseModel to enable ORM mode"""
model_config = {"from_attributes": True}
# The SQLAlchemy base includes a declarative model for you to use in your models.
# The `UUIDBase` class includes a `UUID` based primary key (`id`)
class AuthorModel(base.UUIDBase):
# we can optionally provide the table name instead of auto-generating it
__tablename__ = "author" # type: ignore[assignment]
name: Mapped[str]
dob: Mapped[date | None]
books: Mapped[list[BookModel]] = relationship(back_populates="author", lazy="noload")
# The `UUIDAuditBase` class includes the same UUID` based primary key (`id`) and 2
# additional columns: `created_at` and `updated_at`. `created_at` is a timestamp of when the
# record created, and `updated_at` is the last time the record was modified.
class BookModel(base.UUIDAuditBase):
__tablename__ = "book" # type: ignore[assignment]
title: Mapped[str]
author_id: Mapped[UUID] = mapped_column(ForeignKey("author.id"))
author: Mapped[AuthorModel] = relationship(lazy="joined", innerjoin=True, viewonly=True)
# we will explicitly define the schema instead of using DTO objects for clarity.
class Author(BaseModel):
id: UUID | None
name: str
dob: date | None = None
class AuthorCreate(BaseModel):
name: str
dob: date | None = None
class AuthorUpdate(BaseModel):
name: str | None = None
dob: date | None = None
class AuthorRepository(repository.SQLAlchemyAsyncRepository[AuthorModel]):
"""Author repository."""
model_type = AuthorModel
async def provide_authors_repo(db_session: AsyncSession) -> AuthorRepository:
"""This provides the default Authors repository."""
return AuthorRepository(session=db_session)
# we can optionally override the default `select` used for the repository to pass in
# specific SQL options such as join details
async def provide_author_details_repo(db_session: AsyncSession) -> AuthorRepository:
"""This provides a simple example demonstrating how to override the join options for the repository."""
return AuthorRepository(
statement=select(AuthorModel).options(selectinload(AuthorModel.books)),
session=db_session,
)
def provide_limit_offset_pagination(
current_page: int = Parameter(ge=1, query="currentPage", default=1, required=False),
page_size: int = Parameter(
query="pageSize",
ge=1,
default=10,
required=False,
),
) -> filters.LimitOffset:
"""Add offset/limit pagination.
Return type consumed by `Repository.apply_limit_offset_pagination()`.
Parameters
----------
current_page : int
LIMIT to apply to select.
page_size : int
OFFSET to apply to select.
"""
return filters.LimitOffset(page_size, page_size * (current_page - 1))
class AuthorController(Controller):
"""Author CRUD"""
dependencies = {"authors_repo": Provide(provide_authors_repo)}
@get(path="/authors")
async def list_authors(
self,
authors_repo: AuthorRepository,
limit_offset: filters.LimitOffset,
) -> OffsetPagination[Author]:
"""List authors."""
results, total = await authors_repo.list_and_count(limit_offset)
type_adapter = TypeAdapter(list[Author])
return OffsetPagination[Author](
items=type_adapter.validate_python(results),
total=total,
limit=limit_offset.limit,
offset=limit_offset.offset,
)
@post(path="/authors")
async def create_author(
self,
authors_repo: AuthorRepository,
data: AuthorCreate,
) -> Author:
"""Create a new author."""
obj = await authors_repo.add(
AuthorModel(**data.model_dump(exclude_unset=True, exclude_none=True)),
)
await authors_repo.session.commit()
return Author.model_validate(obj)
# we override the authors_repo to use the version that joins the Books in
@get(path="/authors/{author_id:uuid}", dependencies={"authors_repo": Provide(provide_author_details_repo)})
async def get_author(
self,
authors_repo: AuthorRepository,
author_id: UUID = Parameter(
title="Author ID",
description="The author to retrieve.",
),
) -> Author:
"""Get an existing author."""
obj = await authors_repo.get(author_id)
return Author.model_validate(obj)
@patch(
path="/authors/{author_id:uuid}",
dependencies={"authors_repo": Provide(provide_author_details_repo)},
)
async def update_author(
self,
authors_repo: AuthorRepository,
data: AuthorUpdate,
author_id: UUID = Parameter(
title="Author ID",
description="The author to update.",
),
) -> Author:
"""Update an author."""
raw_obj = data.model_dump(exclude_unset=True, exclude_none=True)
raw_obj.update({"id": author_id})
obj = await authors_repo.update(AuthorModel(**raw_obj))
await authors_repo.session.commit()
return Author.from_orm(obj)
@delete(path="/authors/{author_id:uuid}")
async def delete_author(
self,
authors_repo: AuthorRepository,
author_id: UUID = Parameter(
title="Author ID",
description="The author to delete.",
),
) -> None:
"""Delete a author from the system."""
_ = await authors_repo.delete(author_id)
await authors_repo.session.commit()
session_config = AsyncSessionConfig(expire_on_commit=False)
sqlalchemy_config = SQLAlchemyAsyncConfig(
connection_string="sqlite+aiosqlite:///test.sqlite", session_config=session_config
) # Create 'db_session' dependency.
sqlalchemy_plugin = SQLAlchemyInitPlugin(config=sqlalchemy_config)
async def on_startup() -> None:
"""Initializes the database."""
async with sqlalchemy_config.get_engine().begin() as conn:
await conn.run_sync(base.UUIDBase.metadata.create_all)
app = Litestar(
route_handlers=[AuthorController],
on_startup=[on_startup],
plugins=[SQLAlchemyInitPlugin(config=sqlalchemy_config)],
dependencies={"limit_offset": Provide(provide_limit_offset_pagination)},
)
litestar-2.16.0/docs/examples/contrib/sqlalchemy/sqlalchemy_declarative_models.py 0000664 0000000 0000000 00000004572 15005643713 0030435 0 ustar 00root root 0000000 0000000 from __future__ import annotations
import uuid
from datetime import date
from typing import List
from uuid import UUID
from sqlalchemy import ForeignKey, func, select
from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession
from sqlalchemy.orm import Mapped, mapped_column, relationship
from litestar import Litestar, get
from litestar.plugins.sqlalchemy import AsyncSessionConfig, SQLAlchemyAsyncConfig, SQLAlchemyPlugin, base
# The SQLAlchemy base includes a declarative model for you to use in your models.
# The `UUIDBase` class includes a `UUID` based primary key (`id`)
class Author(base.UUIDBase):
__tablename__ = "author"
name: Mapped[str]
dob: Mapped[date]
books: Mapped[List[Book]] = relationship(back_populates="author", lazy="selectin")
# The `UUIDAuditBase` class includes the same UUID` based primary key (`id`) and 2
# additional columns: `created_at` and `updated_at`. `created_at` is a timestamp of when the
# record created, and `updated_at` is the last time the record was modified.
class Book(base.UUIDAuditBase):
__tablename__ = "book"
title: Mapped[str]
author_id: Mapped[UUID] = mapped_column(ForeignKey("author.id"))
author: Mapped[Author] = relationship(lazy="joined", innerjoin=True, viewonly=True)
session_config = AsyncSessionConfig(expire_on_commit=False)
sqlalchemy_config = SQLAlchemyAsyncConfig(
connection_string="sqlite+aiosqlite:///test.sqlite", session_config=session_config, create_all=True
) # Create 'async_session' dependency.
async def on_startup(app: Litestar) -> None:
"""Adds some dummy data if no data is present."""
async with sqlalchemy_config.get_session() as session:
statement = select(func.count()).select_from(Author)
count = await session.execute(statement)
if not count.scalar():
author_id = uuid.uuid4()
session.add(Author(name="Stephen King", dob=date(1954, 9, 21), id=author_id))
session.add(Book(title="It", author_id=author_id))
await session.commit()
@get(path="/authors")
async def get_authors(db_session: AsyncSession, db_engine: AsyncEngine) -> List[Author]:
"""Interact with SQLAlchemy engine and session."""
return list(await db_session.scalars(select(Author)))
app = Litestar(
route_handlers=[get_authors],
on_startup=[on_startup],
debug=True,
plugins=[SQLAlchemyPlugin(config=sqlalchemy_config)],
)
litestar-2.16.0/docs/examples/contrib/sqlalchemy/sqlalchemy_repository_bulk_operations.py 0000664 0000000 0000000 00000005364 15005643713 0032306 0 ustar 00root root 0000000 0000000 import json
from pathlib import Path
from typing import Any
from rich import get_console
from sqlalchemy import create_engine
from sqlalchemy.orm import Mapped, Session, sessionmaker
from litestar.plugins.sqlalchemy import base, repository
from litestar.repository.filters import LimitOffset
here = Path(__file__).parent
console = get_console()
class USState(base.UUIDBase):
# you can optionally override the generated table name by manually setting it.
__tablename__ = "us_state_lookup" # type: ignore[assignment]
abbreviation: Mapped[str]
name: Mapped[str]
class USStateRepository(repository.SQLAlchemySyncRepository[USState]):
"""US State repository."""
model_type = USState
engine = create_engine(
"duckdb:///:memory:",
future=True,
)
session_factory: sessionmaker[Session] = sessionmaker(engine, expire_on_commit=False)
def open_fixture(fixtures_path: Path, fixture_name: str) -> Any:
"""Loads JSON file with the specified fixture name
Args:
fixtures_path (Path): The path to look for fixtures
fixture_name (str): The fixture name to load.
Raises:
FileNotFoundError: Fixtures not found.
Returns:
Any: The parsed JSON data
"""
fixture = Path(fixtures_path / f"{fixture_name}.json")
if fixture.exists():
with fixture.open(mode="r", encoding="utf-8") as f:
f_data = f.read()
return json.loads(f_data)
raise FileNotFoundError(f"Could not find the {fixture_name} fixture")
def run_script() -> None:
"""Load data from a fixture."""
# Initializes the database.
with engine.begin() as conn:
USState.metadata.create_all(conn)
with session_factory() as db_session:
# 1) Load the JSON data into the US States table.
repo = USStateRepository(session=db_session)
fixture = open_fixture(here, USStateRepository.model_type.__tablename__) # type: ignore
objs = repo.add_many([USStateRepository.model_type(**raw_obj) for raw_obj in fixture])
db_session.commit()
console.print(f"Created {len(objs)} new objects.")
# 2) Select paginated data and total row count.
created_objs, total_objs = repo.list_and_count(LimitOffset(limit=10, offset=0))
console.print(f"Selected {len(created_objs)} records out of a total of {total_objs}.")
# 3) Let's remove the batch of records selected.
deleted_objs = repo.delete_many([new_obj.id for new_obj in created_objs])
console.print(f"Removed {len(deleted_objs)} records out of a total of {total_objs}.")
# 4) Let's count the remaining rows
remaining_count = repo.count()
console.print(f"Found {remaining_count} remaining records after delete.")
if __name__ == "__main__":
run_script()
litestar-2.16.0/docs/examples/contrib/sqlalchemy/sqlalchemy_repository_crud.py 0000664 0000000 0000000 00000006533 15005643713 0030042 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from contextlib import asynccontextmanager
from datetime import date, datetime
from typing import AsyncIterator
from uuid import UUID
import anyio
from rich import get_console
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
from sqlalchemy.orm import Mapped
from litestar.plugins.sqlalchemy import base, repository
console = get_console()
# the SQLAlchemy base includes a declarative model for you to use in your models.
# The `Base` class includes a `UUID` based primary key (`id`)
class Author(base.UUIDBase):
name: Mapped[str]
dob: Mapped[date]
dod: Mapped[date | None]
class AuthorRepository(repository.SQLAlchemyAsyncRepository[Author]):
"""Author repository."""
model_type = Author
engine = create_async_engine(
"sqlite+aiosqlite:///test.sqlite",
future=True,
)
session_factory = async_sessionmaker(engine, expire_on_commit=False)
# let's make a simple context manager as an example here.
@asynccontextmanager
async def repository_factory() -> AsyncIterator[AuthorRepository]:
async with session_factory() as db_session:
try:
yield AuthorRepository(session=db_session)
except Exception: # noqa: BLE001
await db_session.rollback()
else:
await db_session.commit()
async def create_author() -> Author:
async with repository_factory() as repo:
obj = await repo.add(
Author(
name="F. Scott Fitzgerald",
dob=datetime.strptime("1896-09-24", "%Y-%m-%d").date(),
)
)
console.print(f"Created Author record for {obj.name} with primary key {obj.id}.")
return obj
async def update_author(obj: Author) -> Author:
async with repository_factory() as repo:
obj = await repo.update(obj)
console.print(f"Updated Author record for {obj.name} with primary key {obj.id}.")
return obj
async def remove_author(id: UUID) -> Author:
async with repository_factory() as repo:
obj = await repo.delete(id)
console.print(f"Deleted Author record for {obj.name} with primary key {obj.id}.")
return obj
async def get_author_if_exists(id: UUID) -> Author | None:
async with repository_factory() as repo:
obj = await repo.get_one_or_none(id=id)
if obj is not None:
console.print(f"Found Author record for {obj.name} with primary key {obj.id}.")
else:
console.print(f"Could not find Author with primary key {id}.")
return obj
async def run_script() -> None:
"""Load data from a fixture."""
async with engine.begin() as conn:
await conn.run_sync(base.UUIDBase.metadata.create_all)
# 1) create a new Author record.
console.print("1) Adding a new record")
author = await create_author()
author_id = author.id
# 2) Let's update the Author record.
console.print("2) Updating a record.")
author.dod = datetime.strptime("1940-12-21", "%Y-%m-%d").date()
await update_author(author)
# 3) Let's delete the record we just created.
console.print("3) Removing a record.")
await remove_author(author_id)
# 4) Let's verify the record no longer exists.
console.print("4) Select one or none.")
_should_be_none = await get_author_if_exists(author_id)
if __name__ == "__main__":
anyio.run(run_script)
litestar-2.16.0/docs/examples/contrib/sqlalchemy/sqlalchemy_repository_extension.py 0000664 0000000 0000000 00000013642 15005643713 0031120 0 ustar 00root root 0000000 0000000 from __future__ import annotations
import random
import re
import string
import unicodedata
from typing import TYPE_CHECKING, Any
from uuid import UUID
from pydantic import BaseModel as _BaseModel
from pydantic import TypeAdapter
from sqlalchemy.orm import Mapped, declarative_mixin, mapped_column
from sqlalchemy.types import String
from litestar import Litestar, get, post
from litestar.di import Provide
from litestar.plugins.sqlalchemy import (
AsyncSessionConfig,
SQLAlchemyAsyncConfig,
SQLAlchemyInitPlugin,
base,
repository,
)
if TYPE_CHECKING:
from sqlalchemy.ext.asyncio import AsyncSession
class BaseModel(_BaseModel):
"""Extend Pydantic's BaseModel to enable ORM mode"""
model_config = {"from_attributes": True}
# we are going to add a simple "slug" to our model that is a URL safe surrogate key to
# our database record.
@declarative_mixin
class SlugKey:
"""Slug unique Field Model Mixin."""
__abstract__ = True
slug: Mapped[str] = mapped_column(String(length=100), nullable=False, unique=True, sort_order=-9)
# this class can be re-used with any model that has the `SlugKey` Mixin
class SQLAlchemyAsyncSlugRepository(repository.SQLAlchemyAsyncRepository[repository.ModelT]):
"""Extends the repository to include slug model features.."""
async def get_available_slug(
self,
value_to_slugify: str,
**kwargs: Any,
) -> str:
"""Get a unique slug for the supplied value.
If the value is found to exist, a random 4 digit character is appended to the end.
There may be a better way to do this, but I wanted to limit the number of
additional database calls.
Args:
value_to_slugify (str): A string that should be converted to a unique slug.
**kwargs: stuff
Returns:
str: a unique slug for the supplied value. This is safe for URLs and other
unique identifiers.
"""
slug = self._slugify(value_to_slugify)
if await self._is_slug_unique(slug):
return slug
# generate a random 4 digit alphanumeric string to make the slug unique and
# avoid another DB lookup.
random_string = "".join(random.choices(string.ascii_lowercase + string.digits, k=4))
return f"{slug}-{random_string}"
@staticmethod
def _slugify(value: str) -> str:
"""slugify.
Convert to ASCII if 'allow_unicode' is False. Convert spaces or repeated
dashes to single dashes. Remove characters that aren't alphanumerics,
underscores, or hyphens. Convert to lowercase. Also strip leading and
trailing whitespace, dashes, and underscores.
Args:
value (str): the string to slugify
Returns:
str: a slugified string of the value parameter
"""
value = unicodedata.normalize("NFKD", value).encode("ascii", "ignore").decode("ascii")
value = re.sub(r"[^\w\s-]", "", value.lower())
return re.sub(r"[-\s]+", "-", value).strip("-_")
async def _is_slug_unique(
self,
slug: str,
**kwargs: Any,
) -> bool:
return await self.get_one_or_none(slug=slug) is None
# The `UUIDAuditBase` class includes the same UUID` based primary key (`id`) and 2
# additional columns: `created_at` and `updated_at`. `created_at` is a timestamp of when the
# record created, and `updated_at` is the last time the record was modified.
class BlogPost(base.UUIDAuditBase, SlugKey):
title: Mapped[str]
content: Mapped[str]
class BlogPostRepository(SQLAlchemyAsyncSlugRepository[BlogPost]):
"""Blog Post repository."""
model_type = BlogPost
class BlogPostDTO(BaseModel):
id: UUID | None
slug: str
title: str
content: str
class BlogPostCreate(BaseModel):
title: str
content: str
# we can optionally override the default `select` used for the repository to pass in
# specific SQL options such as join details
async def provide_blog_post_repo(db_session: AsyncSession) -> BlogPostRepository:
"""This provides a simple example demonstrating how to override the join options
for the repository."""
return BlogPostRepository(session=db_session)
session_config = AsyncSessionConfig(expire_on_commit=False)
sqlalchemy_config = SQLAlchemyAsyncConfig(
connection_string="sqlite+aiosqlite:///test.sqlite", session_config=session_config
) # Create 'async_session' dependency.
sqlalchemy_plugin = SQLAlchemyInitPlugin(config=sqlalchemy_config)
async def on_startup() -> None:
"""Initializes the database."""
async with sqlalchemy_config.get_engine().begin() as conn:
await conn.run_sync(base.UUIDAuditBase.metadata.create_all)
@get(path="/")
async def get_blogs(
blog_post_repo: BlogPostRepository,
) -> list[BlogPostDTO]:
"""Interact with SQLAlchemy engine and session."""
objs = await blog_post_repo.list()
type_adapter = TypeAdapter(list[BlogPostDTO])
return type_adapter.validate_python(objs)
@get(path="/{post_slug:str}")
async def get_blog_details(
post_slug: str,
blog_post_repo: BlogPostRepository,
) -> BlogPostDTO:
"""Interact with SQLAlchemy engine and session."""
obj = await blog_post_repo.get_one(slug=post_slug)
return BlogPostDTO.model_validate(obj)
@post(path="/")
async def create_blog(
blog_post_repo: BlogPostRepository,
data: BlogPostCreate,
) -> BlogPostDTO:
"""Create a new blog post."""
_data = data.model_dump(exclude_unset=True, by_alias=False, exclude_none=True)
_data["slug"] = await blog_post_repo.get_available_slug(_data["title"])
obj = await blog_post_repo.add(BlogPost(**_data))
await blog_post_repo.session.commit()
return BlogPostDTO.model_validate(obj)
app = Litestar(
route_handlers=[create_blog, get_blogs, get_blog_details],
dependencies={"blog_post_repo": Provide(provide_blog_post_repo, sync_to_thread=False)},
on_startup=[on_startup],
plugins=[SQLAlchemyInitPlugin(config=sqlalchemy_config)],
)
litestar-2.16.0/docs/examples/contrib/sqlalchemy/sqlalchemy_sync_repository.py 0000664 0000000 0000000 00000015505 15005643713 0030060 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from datetime import date
from typing import TYPE_CHECKING
from uuid import UUID
from pydantic import BaseModel as _BaseModel
from pydantic import TypeAdapter
from sqlalchemy import ForeignKey, select
from sqlalchemy.orm import Mapped, mapped_column, relationship, selectinload
from litestar import Litestar, get
from litestar.controller import Controller
from litestar.di import Provide
from litestar.handlers.http_handlers.decorators import delete, patch, post
from litestar.pagination import OffsetPagination
from litestar.params import Parameter
from litestar.plugins.sqlalchemy import (
SQLAlchemyInitPlugin,
SQLAlchemySyncConfig,
base,
repository,
)
from litestar.repository.filters import LimitOffset
if TYPE_CHECKING:
from sqlalchemy.orm import Session
class BaseModel(_BaseModel):
"""Extend Pydantic's BaseModel to enable ORM mode"""
model_config = {"from_attributes": True}
# The SQLAlchemy base includes a declarative model for you to use in your models.
# The `UUIDBase` class includes a `UUID` based primary key (`id`)
class AuthorModel(base.UUIDBase):
# we can optionally provide the table name instead of auto-generating it
__tablename__ = "author" # type: ignore[assignment]
name: Mapped[str]
dob: Mapped[date | None]
books: Mapped[list[BookModel]] = relationship(back_populates="author", lazy="noload")
# The `UUIDAuditBase` class includes the same UUID` based primary key (`id`) and 2
# additional columns: `created_at` and `updated_at`. `created_at` is a timestamp of when the
# record created, and `updated_at` is the last time the record was modified.
class BookModel(base.UUIDAuditBase):
__tablename__ = "book" # type: ignore[assignment]
title: Mapped[str]
author_id: Mapped[UUID] = mapped_column(ForeignKey("author.id"))
author: Mapped[AuthorModel] = relationship(lazy="joined", innerjoin=True, viewonly=True)
# we will explicitly define the schema instead of using DTO objects for clarity.
class Author(BaseModel):
id: UUID | None
name: str
dob: date | None = None
class AuthorCreate(BaseModel):
name: str
dob: date | None = None
class AuthorUpdate(BaseModel):
name: str | None = None
dob: date | None = None
class AuthorRepository(repository.SQLAlchemySyncRepository[AuthorModel]):
"""Author repository."""
model_type = AuthorModel
async def provide_authors_repo(db_session: Session) -> AuthorRepository:
"""This provides the default Authors repository."""
return AuthorRepository(session=db_session)
# we can optionally override the default `select` used for the repository to pass in
# specific SQL options such as join details
async def provide_author_details_repo(db_session: Session) -> AuthorRepository:
"""This provides a simple example demonstrating how to override the join options
for the repository."""
return AuthorRepository(
statement=select(AuthorModel).options(selectinload(AuthorModel.books)),
session=db_session,
)
def provide_limit_offset_pagination(
current_page: int = Parameter(ge=1, query="currentPage", default=1, required=False),
page_size: int = Parameter(
query="pageSize",
ge=1,
default=10,
required=False,
),
) -> LimitOffset:
"""Add offset/limit pagination.
Return type consumed by `Repository.apply_limit_offset_pagination()`.
Parameters
----------
current_page : int
LIMIT to apply to select.
page_size : int
OFFSET to apply to select.
"""
return LimitOffset(page_size, page_size * (current_page - 1))
class AuthorController(Controller):
"""Author CRUD"""
dependencies = {"authors_repo": Provide(provide_authors_repo, sync_to_thread=False)}
@get(path="/authors")
def list_authors(
self,
authors_repo: AuthorRepository,
limit_offset: LimitOffset,
) -> OffsetPagination[Author]:
"""List authors."""
results, total = authors_repo.list_and_count(limit_offset)
type_adapter = TypeAdapter(list[Author])
return OffsetPagination[Author](
items=type_adapter.validate_python(results),
total=total,
limit=limit_offset.limit,
offset=limit_offset.offset,
)
@post(path="/authors")
def create_author(
self,
authors_repo: AuthorRepository,
data: AuthorCreate,
) -> Author:
"""Create a new author."""
obj = authors_repo.add(
AuthorModel(**data.model_dump(exclude_unset=True, exclude_none=True)),
)
authors_repo.session.commit()
return Author.model_validate(obj)
# we override the authors_repo to use the version that joins the Books in
@get(
path="/authors/{author_id:uuid}",
dependencies={"authors_repo": Provide(provide_author_details_repo, sync_to_thread=False)},
)
def get_author(
self,
authors_repo: AuthorRepository,
author_id: UUID = Parameter(
title="Author ID",
description="The author to retrieve.",
),
) -> Author:
"""Get an existing author."""
obj = authors_repo.get(author_id)
return Author.model_validate(obj)
@patch(
path="/authors/{author_id:uuid}",
dependencies={"authors_repo": Provide(provide_author_details_repo, sync_to_thread=False)},
)
def update_author(
self,
authors_repo: AuthorRepository,
data: AuthorUpdate,
author_id: UUID = Parameter(
title="Author ID",
description="The author to update.",
),
) -> Author:
"""Update an author."""
raw_obj = data.model_dump(exclude_unset=True, exclude_none=True)
raw_obj.update({"id": author_id})
obj = authors_repo.update(AuthorModel(**raw_obj))
authors_repo.session.commit()
return Author.model_validate(obj)
@delete(path="/authors/{author_id:uuid}")
def delete_author(
self,
authors_repo: AuthorRepository,
author_id: UUID = Parameter(
title="Author ID",
description="The author to delete.",
),
) -> None:
"""Delete a author from the system."""
_ = authors_repo.delete(author_id)
authors_repo.session.commit()
sqlalchemy_config = SQLAlchemySyncConfig(connection_string="sqlite:///test.sqlite") # Create 'db_session' dependency.
sqlalchemy_plugin = SQLAlchemyInitPlugin(config=sqlalchemy_config)
def on_startup() -> None:
"""Initializes the database."""
with sqlalchemy_config.get_engine().begin() as conn:
base.UUIDBase.metadata.create_all(conn)
app = Litestar(
route_handlers=[AuthorController],
on_startup=[on_startup],
plugins=[SQLAlchemyInitPlugin(config=sqlalchemy_config)],
dependencies={"limit_offset": Provide(provide_limit_offset_pagination)},
)
litestar-2.16.0/docs/examples/contrib/sqlalchemy/us_state_lookup.json 0000664 0000000 0000000 00000006135 15005643713 0026123 0 ustar 00root root 0000000 0000000 [
{
"name": "Alabama",
"abbreviation": "AL"
},
{
"name": "Alaska",
"abbreviation": "AK"
},
{
"name": "Arizona",
"abbreviation": "AZ"
},
{
"name": "Arkansas",
"abbreviation": "AR"
},
{
"name": "California",
"abbreviation": "CA"
},
{
"name": "Colorado",
"abbreviation": "CO"
},
{
"name": "Connecticut",
"abbreviation": "CT"
},
{
"name": "Delaware",
"abbreviation": "DE"
},
{
"name": "District Of Columbia",
"abbreviation": "DC"
},
{
"name": "Florida",
"abbreviation": "FL"
},
{
"name": "Georgia",
"abbreviation": "GA"
},
{
"name": "Guam",
"abbreviation": "GU"
},
{
"name": "Hawaii",
"abbreviation": "HI"
},
{
"name": "Idaho",
"abbreviation": "ID"
},
{
"name": "Illinois",
"abbreviation": "IL"
},
{
"name": "Indiana",
"abbreviation": "IN"
},
{
"name": "Iowa",
"abbreviation": "IA"
},
{
"name": "Kansas",
"abbreviation": "KS"
},
{
"name": "Kentucky",
"abbreviation": "KY"
},
{
"name": "Louisiana",
"abbreviation": "LA"
},
{
"name": "Maine",
"abbreviation": "ME"
},
{
"name": "Maryland",
"abbreviation": "MD"
},
{
"name": "Massachusetts",
"abbreviation": "MA"
},
{
"name": "Michigan",
"abbreviation": "MI"
},
{
"name": "Minnesota",
"abbreviation": "MN"
},
{
"name": "Mississippi",
"abbreviation": "MS"
},
{
"name": "Missouri",
"abbreviation": "MO"
},
{
"name": "Montana",
"abbreviation": "MT"
},
{
"name": "Nebraska",
"abbreviation": "NE"
},
{
"name": "Nevada",
"abbreviation": "NV"
},
{
"name": "New Hampshire",
"abbreviation": "NH"
},
{
"name": "New Jersey",
"abbreviation": "NJ"
},
{
"name": "New Mexico",
"abbreviation": "NM"
},
{
"name": "New York",
"abbreviation": "NY"
},
{
"name": "North Carolina",
"abbreviation": "NC"
},
{
"name": "North Dakota",
"abbreviation": "ND"
},
{
"name": "Ohio",
"abbreviation": "OH"
},
{
"name": "Oklahoma",
"abbreviation": "OK"
},
{
"name": "Oregon",
"abbreviation": "OR"
},
{
"name": "Palau",
"abbreviation": "PW"
},
{
"name": "Pennsylvania",
"abbreviation": "PA"
},
{
"name": "Puerto Rico",
"abbreviation": "PR"
},
{
"name": "Rhode Island",
"abbreviation": "RI"
},
{
"name": "South Carolina",
"abbreviation": "SC"
},
{
"name": "South Dakota",
"abbreviation": "SD"
},
{
"name": "Tennessee",
"abbreviation": "TN"
},
{
"name": "Texas",
"abbreviation": "TX"
},
{
"name": "Utah",
"abbreviation": "UT"
},
{
"name": "Vermont",
"abbreviation": "VT"
},
{
"name": "Virginia",
"abbreviation": "VA"
},
{
"name": "Washington",
"abbreviation": "WA"
},
{
"name": "West Virginia",
"abbreviation": "WV"
},
{
"name": "Wisconsin",
"abbreviation": "WI"
},
{
"name": "Wyoming",
"abbreviation": "WY"
}
]
litestar-2.16.0/docs/examples/data_transfer_objects/ 0000775 0000000 0000000 00000000000 15005643713 0022527 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/data_transfer_objects/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0024626 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/data_transfer_objects/defining_dtos_on_layers.py 0000664 0000000 0000000 00000002537 15005643713 0027777 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from dataclasses import dataclass, field
from typing import List
from uuid import UUID, uuid4
from litestar import Controller, delete, get, post, put
from litestar.app import Litestar
from litestar.dto import DataclassDTO
from litestar.dto.config import DTOConfig
@dataclass
class User:
name: str
email: str
age: int
id: UUID = field(default_factory=uuid4)
class UserWriteDTO(DataclassDTO[User]):
config = DTOConfig(exclude={"id"})
class UserReadDTO(DataclassDTO[User]): ...
class UserController(Controller):
dto = UserWriteDTO
return_dto = UserReadDTO
@post("/", sync_to_thread=False)
def create_user(self, data: User) -> User:
return data
@get("/", sync_to_thread=False)
def get_users(self) -> List[User]:
return [User(name="Mr Sunglass", email="mr.sunglass@example.com", age=30)]
@get("/{user_id:uuid}", sync_to_thread=False)
def get_user(self, user_id: UUID) -> User:
return User(id=user_id, name="Mr Sunglass", email="mr.sunglass@example.com", age=30)
@put("/{user_id:uuid}", sync_to_thread=False)
def update_user(self, data: User) -> User:
return data
@delete("/{user_id:uuid}", return_dto=None, sync_to_thread=False)
def delete_user(self, user_id: UUID) -> None:
return None
app = Litestar([UserController])
litestar-2.16.0/docs/examples/data_transfer_objects/factory/ 0000775 0000000 0000000 00000000000 15005643713 0024176 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/data_transfer_objects/factory/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0026275 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/data_transfer_objects/factory/dto_data_problem_statement.py 0000664 0000000 0000000 00000001671 15005643713 0032140 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from dataclasses import dataclass, field
from uuid import UUID, uuid4
from litestar import Litestar, post
from litestar.dto import DataclassDTO, DTOConfig
@dataclass
class User:
name: str
email: str
age: int
id: UUID = field(default_factory=uuid4)
class UserWriteDTO(DataclassDTO[User]):
"""Don't allow client to set the id."""
config = DTOConfig(exclude={"id"})
# We need a dto for the handler to parse the request data per the configuration, however,
# we don't need a return DTO as we are returning a dataclass, and Litestar already knows
# how to serialize dataclasses.
@post("/users", dto=UserWriteDTO, return_dto=None, sync_to_thread=False)
def create_user(data: User) -> User:
"""Create an user."""
return data
app = Litestar(route_handlers=[create_user])
# run: /users -H "Content-Type: application/json" -d '{"name":"Peter","email": "peter@example.com", "age":41}'
litestar-2.16.0/docs/examples/data_transfer_objects/factory/dto_data_usage.py 0000664 0000000 0000000 00000001313 15005643713 0027511 0 ustar 00root root 0000000 0000000 from dataclasses import dataclass
from uuid import UUID, uuid4
from litestar import Litestar, post
from litestar.dto import DataclassDTO, DTOConfig, DTOData
@dataclass
class User:
name: str
email: str
age: int
id: UUID
class UserWriteDTO(DataclassDTO[User]):
"""Don't allow client to set the id."""
config = DTOConfig(exclude={"id"})
@post("/users", dto=UserWriteDTO, return_dto=None, sync_to_thread=False)
def create_user(data: DTOData[User]) -> User:
"""Create an user."""
return data.create_instance(id=uuid4())
app = Litestar(route_handlers=[create_user])
# run: /users -H "Content-Type: application/json" -d '{"name":"Peter", "email": "peter@example.com", "age":41}'
litestar-2.16.0/docs/examples/data_transfer_objects/factory/enveloping_return_data.py 0000664 0000000 0000000 00000001712 15005643713 0031307 0 ustar 00root root 0000000 0000000 from dataclasses import dataclass
from datetime import datetime
from typing import Generic, List, TypeVar
from sqlalchemy.orm import Mapped
from litestar import Litestar, get
from litestar.dto import DTOConfig
from litestar.plugins.sqlalchemy import SQLAlchemyDTO
from .my_lib import Base
T = TypeVar("T")
@dataclass
class WithCount(Generic[T]):
count: int
data: List[T]
class User(Base):
name: Mapped[str]
password: Mapped[str]
created_at: Mapped[datetime]
class UserDTO(SQLAlchemyDTO[User]):
config = DTOConfig(exclude={"password", "created_at"})
@get("/users", dto=UserDTO, sync_to_thread=False)
def get_users() -> WithCount[User]:
return WithCount(
count=1,
data=[
User(
id=1,
name="Litestar User",
password="xyz",
created_at=datetime.now(),
),
],
)
app = Litestar(route_handlers=[get_users])
# run: /users
litestar-2.16.0/docs/examples/data_transfer_objects/factory/excluding_fields.py 0000664 0000000 0000000 00000003351 15005643713 0030062 0 ustar 00root root 0000000 0000000 from datetime import datetime
from typing import List
from uuid import UUID
from sqlalchemy import ForeignKey
from sqlalchemy.orm import Mapped, mapped_column, relationship
from typing_extensions import Annotated
from litestar import Litestar, post
from litestar.dto import DTOConfig, dto_field
from litestar.plugins.sqlalchemy import SQLAlchemyDTO
from .my_lib import Base
class Address(Base):
street: Mapped[str]
city: Mapped[str]
state: Mapped[str]
zip: Mapped[str]
class Pets(Base):
name: Mapped[str]
user_id: Mapped[UUID] = mapped_column(ForeignKey("user.id"))
class User(Base):
name: Mapped[str]
password: Mapped[str] = mapped_column(info=dto_field("private"))
created_at: Mapped[datetime] = mapped_column(info=dto_field("read-only"))
address_id: Mapped[UUID] = mapped_column(ForeignKey("address.id"), info=dto_field("private"))
address: Mapped[Address] = relationship(info=dto_field("read-only"))
pets: Mapped[List[Pets]] = relationship(info=dto_field("read-only"))
UserDTO = SQLAlchemyDTO[User]
config = DTOConfig(
exclude={
"id",
"address.id",
"address.street",
"pets.0.id",
"pets.0.user_id",
}
)
ReadUserDTO = SQLAlchemyDTO[Annotated[User, config]]
@post("/users", dto=UserDTO, return_dto=ReadUserDTO, sync_to_thread=False)
def create_user(data: User) -> User:
data.created_at = datetime.min
data.address = Address(street="123 Main St", city="Anytown", state="NY", zip="12345")
data.pets = [Pets(id=1, name="Fido"), Pets(id=2, name="Spot")]
return data
app = Litestar(route_handlers=[create_user])
# run: /users -H "Content-Type: application/json" -d '{"name":"Litestar User","password":"xyz","created_at":"2023-04-24T00:00:00Z"}'
litestar-2.16.0/docs/examples/data_transfer_objects/factory/included_fields.py 0000664 0000000 0000000 00000003255 15005643713 0027672 0 ustar 00root root 0000000 0000000 from datetime import datetime
from typing import List
from uuid import UUID
from sqlalchemy import ForeignKey
from sqlalchemy.orm import Mapped, mapped_column, relationship
from typing_extensions import Annotated
from litestar import Litestar, post
from litestar.dto import DTOConfig, dto_field
from litestar.plugins.sqlalchemy import SQLAlchemyDTO
from .my_lib import Base
class Address(Base):
street: Mapped[str]
city: Mapped[str]
state: Mapped[str]
zip: Mapped[str]
class Pets(Base):
name: Mapped[str]
user_id: Mapped[UUID] = mapped_column(ForeignKey("user.id"))
class User(Base):
name: Mapped[str]
password: Mapped[str] = mapped_column(info=dto_field("private"))
created_at: Mapped[datetime] = mapped_column(info=dto_field("read-only"))
address_id: Mapped[UUID] = mapped_column(ForeignKey("address.id"), info=dto_field("private"))
address: Mapped[Address] = relationship(info=dto_field("read-only"))
pets: Mapped[List[Pets]] = relationship(info=dto_field("read-only"))
UserDTO = SQLAlchemyDTO[User]
config = DTOConfig(
include={
"address.street",
"pets.0.name",
}
)
ReadUserDTO = SQLAlchemyDTO[Annotated[User, config]]
@post("/users", dto=UserDTO, return_dto=ReadUserDTO, sync_to_thread=False)
def create_user(data: User) -> User:
data.created_at = datetime.min
data.address = Address(street="123 Main St", city="Anytown", state="NY", zip="12345")
data.pets = [Pets(id=1, name="Fido"), Pets(id=2, name="Spot")]
return data
app = Litestar(route_handlers=[create_user])
# run: /users -H "Content-Type: application/json" -d '{"name":"Litestar User","password":"xyz","created_at":"2023-04-24T00:00:00Z"}'
litestar-2.16.0/docs/examples/data_transfer_objects/factory/leading_underscore_private.py 0000664 0000000 0000000 00000000635 15005643713 0032142 0 ustar 00root root 0000000 0000000 from dataclasses import dataclass
from litestar import Litestar, post
from litestar.dto import DataclassDTO
@dataclass
class Foo:
this_will: str
_this_will: str = "Mars"
@post("/", dto=DataclassDTO[Foo], sync_to_thread=False)
def handler(data: Foo) -> Foo:
return data
app = Litestar(route_handlers=[handler])
# run: / -H "Content-Type: application/json" -d '{"bar":"stay","_baz":"go_away!"}'
litestar-2.16.0/docs/examples/data_transfer_objects/factory/leading_underscore_private_override.py 0000664 0000000 0000000 00000001012 15005643713 0034027 0 ustar 00root root 0000000 0000000 from dataclasses import dataclass
from litestar import Litestar, post
from litestar.dto import DataclassDTO, DTOConfig
@dataclass
class Foo:
this_will: str
_this_will: str = "not_go_away!"
class DTO(DataclassDTO[Foo]):
config = DTOConfig(underscore_fields_private=False)
@post("/", dto=DTO, sync_to_thread=False)
def handler(data: Foo) -> Foo:
return data
app = Litestar(route_handlers=[handler])
# run: / -H "Content-Type: application/json" -d '{"this_will":"stay","_this_will":"not_go_away!"}'
litestar-2.16.0/docs/examples/data_transfer_objects/factory/marking_fields.py 0000664 0000000 0000000 00000002436 15005643713 0027533 0 ustar 00root root 0000000 0000000 from datetime import datetime
from sqlalchemy.orm import Mapped, mapped_column
from litestar import Litestar, post
from litestar.dto import dto_field
from litestar.plugins.sqlalchemy import SQLAlchemyDTO
from .my_lib import Base
class User(Base):
# `Base` defines `id` field as:
# id: Mapped[UUID] = mapped_column(default=uuid4, primary_key=True)
name: Mapped[str]
password: Mapped[str] = mapped_column(info=dto_field("private"))
created_at: Mapped[datetime] = mapped_column(info=dto_field("read-only"))
UserDTO = SQLAlchemyDTO[User]
@post("/users", dto=UserDTO, sync_to_thread=False)
def create_user(data: User) -> User:
# even though the client did not send the id field,
# since it is a primary key it is autogenerated
assert "id" in vars(data)
# even though the client sent the password and created_at field, it is not in the data object
assert "password" not in vars(data)
assert "created_at" not in vars(data)
# normally the database would set the created_at timestamp
data.created_at = datetime.min
return data # the response includes the created_at field
app = Litestar(route_handlers=[create_user])
# run: /users -H "Content-Type: application/json" -d '{"name":"Litestar User","password":"xyz","created_at":"2023-04-24T00:00:00Z"}'
litestar-2.16.0/docs/examples/data_transfer_objects/factory/my_lib.py 0000664 0000000 0000000 00000001166 15005643713 0026027 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from typing import Any
from sqlalchemy.orm import DeclarativeBase
from litestar.plugins.sqlalchemy import base, mixins
class _Base(base.CommonTableAttributes, mixins.UUIDPrimaryKey, DeclarativeBase):
"""Fake base SQLAlchemy model for typing purposes."""
Base: _Base
def __getattr__(name: str) -> Any:
if name == "Base":
return type(
"Base",
(base.CommonTableAttributes, mixins.UUIDPrimaryKey, DeclarativeBase),
{"registry": base.create_registry()},
)
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
litestar-2.16.0/docs/examples/data_transfer_objects/factory/paginated_return_data.py 0000664 0000000 0000000 00000001630 15005643713 0031074 0 ustar 00root root 0000000 0000000 from datetime import datetime
from sqlalchemy.orm import Mapped
from litestar import Litestar, get
from litestar.dto import DTOConfig
from litestar.pagination import ClassicPagination
from litestar.plugins.sqlalchemy import SQLAlchemyDTO
from .my_lib import Base
class User(Base):
name: Mapped[str]
password: Mapped[str]
created_at: Mapped[datetime]
class UserDTO(SQLAlchemyDTO[User]):
config = DTOConfig(exclude={"password", "created_at"})
@get("/users", dto=UserDTO, sync_to_thread=False)
def get_users() -> ClassicPagination[User]:
return ClassicPagination(
page_size=10,
total_pages=1,
current_page=1,
items=[
User(
id=1,
name="Litestar User",
password="xyz",
created_at=datetime.now(),
),
],
)
app = Litestar(route_handlers=[get_users])
# run: /users
litestar-2.16.0/docs/examples/data_transfer_objects/factory/patch_requests.py 0000664 0000000 0000000 00000001713 15005643713 0027604 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from dataclasses import dataclass
from uuid import UUID
from litestar import Litestar, patch
from litestar.dto import DataclassDTO, DTOConfig, DTOData
@dataclass
class Person:
id: UUID
name: str
age: int
class PatchDTO(DataclassDTO[Person]):
"""Don't allow client to set the id, and allow partial updates."""
config = DTOConfig(exclude={"id"}, partial=True)
peter_uuid = UUID("f32ff2ce-e32f-4537-9dc0-26e7599f1380")
database = {peter_uuid: Person(id=peter_uuid, name="Peter", age=40)}
@patch("/person/{person_id:uuid}", dto=PatchDTO, return_dto=None, sync_to_thread=False)
def update_person(person_id: UUID, data: DTOData[Person]) -> Person:
"""Partially update a person."""
return data.update_instance(database[person_id])
app = Litestar(route_handlers=[update_person])
# run: /person/f32ff2ce-e32f-4537-9dc0-26e7599f1380 -X PATCH -H "Content-Type: application/json" -d '{"name":"Peter Pan"}'
litestar-2.16.0/docs/examples/data_transfer_objects/factory/providing_values_for_nested_data.py 0000664 0000000 0000000 00000001537 15005643713 0033337 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from dataclasses import dataclass
from litestar import Litestar, post
from litestar.dto import DataclassDTO, DTOConfig, DTOData
@dataclass
class Address:
id: int
street: str
@dataclass
class Person:
id: int
name: str
age: int
address: Address
class ReadDTO(DataclassDTO[Person]):
config = DTOConfig()
class WriteDTO(DataclassDTO[Person]):
config = DTOConfig(exclude={"id", "address.id"})
@post("/person", dto=WriteDTO, return_dto=ReadDTO, sync_to_thread=False)
def create_person(data: DTOData[Person]) -> Person:
# Logic for persisting the person goes here
return data.create_instance(id=1, address__id=2)
app = Litestar(route_handlers=[create_person])
# run: /person -H "Content-Type: application/json" -d '{"name":"Peter","age":41, "address": {"street": "Fake Street"}}'
litestar-2.16.0/docs/examples/data_transfer_objects/factory/related_items.py 0000664 0000000 0000000 00000002606 15005643713 0027375 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from uuid import UUID
from sqlalchemy import ForeignKey
from sqlalchemy.orm import Mapped, mapped_column, relationship
from typing_extensions import Annotated
from litestar import Litestar, put
from litestar.dto import DTOConfig
from litestar.plugins.sqlalchemy import SQLAlchemyDTO
from .my_lib import Base
class A(Base):
b_id: Mapped[UUID] = mapped_column(ForeignKey("b.id"))
b: Mapped[B] = relationship(back_populates="a")
class B(Base):
a: Mapped[A] = relationship(back_populates="b")
data_config = DTOConfig(max_nested_depth=0)
DataDTO = SQLAlchemyDTO[Annotated[A, data_config]]
# default config sets max_nested_depth to 1
ReturnDTO = SQLAlchemyDTO[A]
@put("/a", dto=DataDTO, return_dto=ReturnDTO, sync_to_thread=False)
def update_a(data: A) -> A:
# this shows that "b" was not parsed out of the inbound data
assert "b" not in vars(data)
# Now we'll create an instance of B and assign it"
# This includes a reference back to ``a`` which is not serialized in the return data
# because default ``max_nested_depth`` is set to 1
data.b = B(id=data.b_id, a=data)
return data
app = Litestar(route_handlers=[update_a])
# run: /a -H "Content-Type: application/json" -X PUT -d '{"id": "6955e63c-c2bc-4707-8fa4-2144d1764746", "b_id": "9cf3518d-7e19-4215-9ec2-e056cac55bf7", "b": {"id": "9cf3518d-7e19-4215-9ec2-e056cac55bf7"}}'
litestar-2.16.0/docs/examples/data_transfer_objects/factory/renaming_all_fields.py 0000664 0000000 0000000 00000002034 15005643713 0030525 0 ustar 00root root 0000000 0000000 from datetime import datetime
from sqlalchemy.orm import Mapped, mapped_column
from typing_extensions import Annotated
from litestar import Litestar, post
from litestar.dto import DTOConfig, dto_field
from litestar.plugins.sqlalchemy import SQLAlchemyDTO
from .my_lib import Base
class User(Base):
first_name: Mapped[str]
password: Mapped[str] = mapped_column(info=dto_field("private"))
created_at: Mapped[datetime] = mapped_column(info=dto_field("read-only"))
config = DTOConfig(rename_strategy="camel")
# another rename strategy with a custom callback:
# config = DTOConfig(rename_strategy=lambda x: f"-{x}-")
UserDTO = SQLAlchemyDTO[Annotated[User, config]]
@post("/users", dto=UserDTO, sync_to_thread=False)
def create_user(data: User) -> User:
assert data.first_name == "Litestar User"
data.created_at = datetime.min
return data
app = Litestar(route_handlers=[create_user])
# run: /users -H "Content-Type: application/json" -d '{"firstName":"Litestar User","password":"xyz","createdAt":"2023-04-24T00:00:00Z"}'
litestar-2.16.0/docs/examples/data_transfer_objects/factory/renaming_fields.py 0000664 0000000 0000000 00000001660 15005643713 0027701 0 ustar 00root root 0000000 0000000 from datetime import datetime
from sqlalchemy.orm import Mapped, mapped_column
from typing_extensions import Annotated
from litestar import Litestar, post
from litestar.dto import DTOConfig, dto_field
from litestar.plugins.sqlalchemy import SQLAlchemyDTO
from .my_lib import Base
class User(Base):
name: Mapped[str]
password: Mapped[str] = mapped_column(info=dto_field("private"))
created_at: Mapped[datetime] = mapped_column(info=dto_field("read-only"))
config = DTOConfig(rename_fields={"name": "userName"})
UserDTO = SQLAlchemyDTO[Annotated[User, config]]
@post("/users", dto=UserDTO, sync_to_thread=False)
def create_user(data: User) -> User:
assert data.name == "Litestar User"
data.created_at = datetime.min
return data
app = Litestar(route_handlers=[create_user])
# run: /users -H "Content-Type: application/json" -d '{"userName":"Litestar User","password":"xyz","created_at":"2023-04-24T00:00:00Z"}'
litestar-2.16.0/docs/examples/data_transfer_objects/factory/response_return_data.py 0000664 0000000 0000000 00000001426 15005643713 0031001 0 ustar 00root root 0000000 0000000 from datetime import datetime
from sqlalchemy.orm import Mapped
from litestar import Litestar, Response, get
from litestar.dto import DTOConfig
from litestar.plugins.sqlalchemy import SQLAlchemyDTO
from .my_lib import Base
class User(Base):
name: Mapped[str]
password: Mapped[str]
created_at: Mapped[datetime]
class UserDTO(SQLAlchemyDTO[User]):
config = DTOConfig(exclude={"password", "created_at"})
@get("/users", dto=UserDTO, sync_to_thread=False)
def get_users() -> Response[User]:
return Response(
content=User(
id=1,
name="Litestar User",
password="xyz",
created_at=datetime.now(),
),
headers={"X-Total-Count": "1"},
)
app = Litestar(route_handlers=[get_users])
# run: /users
litestar-2.16.0/docs/examples/data_transfer_objects/factory/simple_dto_factory_example.py 0000664 0000000 0000000 00000001306 15005643713 0032151 0 ustar 00root root 0000000 0000000 from datetime import datetime
from sqlalchemy.orm import Mapped
from litestar import Litestar, post
from litestar.plugins.sqlalchemy import SQLAlchemyDTO
from .my_lib import Base
class User(Base):
# `Base` defines `id` field as:
# id: Mapped[UUID] = mapped_column(default=uuid4, primary_key=True)
name: Mapped[str]
password: Mapped[str]
created_at: Mapped[datetime]
UserDTO = SQLAlchemyDTO[User]
@post("/users", dto=UserDTO, sync_to_thread=False)
def create_user(data: User) -> User:
return data
app = Litestar(route_handlers=[create_user])
# run: /users -H "Content-Type: application/json" -d '{"name":"Litestar User","password":"xyz","created_at":"2023-04-24T00:00:00Z"}'
litestar-2.16.0/docs/examples/data_transfer_objects/factory/tutorial/ 0000775 0000000 0000000 00000000000 15005643713 0026041 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/data_transfer_objects/factory/tutorial/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0030140 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/data_transfer_objects/factory/tutorial/controller.py 0000664 0000000 0000000 00000003016 15005643713 0030576 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from dataclasses import dataclass
from litestar import Controller, Litestar, patch, post, put
from litestar.dto import DataclassDTO, DTOConfig, DTOData
@dataclass
class Person:
name: str
age: int
email: str
id: int
class ReadDTO(DataclassDTO[Person]):
config = DTOConfig(exclude={"email"})
class WriteDTO(DataclassDTO[Person]):
config = DTOConfig(exclude={"id"})
class PatchDTO(DataclassDTO[Person]):
config = DTOConfig(exclude={"id"}, partial=True)
class PersonController(Controller):
dto = WriteDTO
return_dto = ReadDTO
@post("/person", sync_to_thread=False)
def create_person(self, data: DTOData[Person]) -> Person:
# Logic for persisting the person goes here
return data.create_instance(id=1)
@put("/person/{person_id:int}", sync_to_thread=False)
def update_person(self, person_id: int, data: DTOData[Person]) -> Person:
# Usually the Person would be retrieved from a database
person = Person(id=person_id, name="John", age=50, email="email_of_john@example.com")
return data.update_instance(person)
@patch("/person/{person_id:int}", dto=PatchDTO, sync_to_thread=False)
def patch_person(self, person_id: int, data: DTOData[Person]) -> Person:
# Usually the Person would be retrieved from a database
person = Person(id=person_id, name="John", age=50, email="email_of_john@example.com")
return data.update_instance(person)
app = Litestar(route_handlers=[PersonController])
litestar-2.16.0/docs/examples/data_transfer_objects/factory/tutorial/dto_data.py 0000664 0000000 0000000 00000001234 15005643713 0030172 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from dataclasses import dataclass
from litestar import Litestar, post
from litestar.dto import DataclassDTO, DTOConfig, DTOData
@dataclass
class Person:
name: str
age: int
email: str
id: int
class ReadDTO(DataclassDTO[Person]):
config = DTOConfig(exclude={"email"})
class WriteDTO(DataclassDTO[Person]):
config = DTOConfig(exclude={"id"})
@post("/person", dto=WriteDTO, return_dto=ReadDTO, sync_to_thread=False)
def create_person(data: DTOData[Person]) -> Person:
# Logic for persisting the person goes here
return data.create_instance(id=1)
app = Litestar(route_handlers=[create_person])
litestar-2.16.0/docs/examples/data_transfer_objects/factory/tutorial/explicit_field_renaming.py 0000664 0000000 0000000 00000002432 15005643713 0033260 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from dataclasses import dataclass
from typing import List
from litestar import Litestar, get
from litestar.dto import DataclassDTO, DTOConfig
@dataclass
class Address:
street: str
city: str
country: str
@dataclass
class Person:
name: str
age: int
email: str
address: Address
children: List[Person]
class ReadDTO(DataclassDTO[Person]):
config = DTOConfig(
exclude={"email", "address.street", "children.0.email", "children.0.address"},
rename_fields={"address": "location"},
)
@get("/person/{name:str}", return_dto=ReadDTO, sync_to_thread=False)
def get_person(name: str) -> Person:
# Your logic to retrieve the person goes here
# For demonstration purposes, a placeholder Person instance is returned
address = Address(street="123 Main St", city="Cityville", country="Countryland")
child1 = Person(name="Child1", age=10, email="child1@example.com", address=address, children=[])
child2 = Person(name="Child2", age=8, email="child2@example.com", address=address, children=[])
return Person(
name=name,
age=30,
email=f"email_of_{name}@example.com",
address=address,
children=[child1, child2],
)
app = Litestar(route_handlers=[get_person])
litestar-2.16.0/docs/examples/data_transfer_objects/factory/tutorial/field_renaming_strategy.py 0000664 0000000 0000000 00000002414 15005643713 0033301 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from dataclasses import dataclass
from typing import List
from litestar import Litestar, get
from litestar.dto import DataclassDTO, DTOConfig
@dataclass
class Address:
street: str
city: str
country: str
@dataclass
class Person:
name: str
age: int
email: str
address: Address
children: List[Person]
class ReadDTO(DataclassDTO[Person]):
config = DTOConfig(
exclude={"email", "address.street", "children.0.email", "children.0.address"},
rename_strategy="upper",
)
@get("/person/{name:str}", return_dto=ReadDTO, sync_to_thread=False)
def get_person(name: str) -> Person:
# Your logic to retrieve the person goes here
# For demonstration purposes, a placeholder Person instance is returned
address = Address(street="123 Main St", city="Cityville", country="Countryland")
child1 = Person(name="Child1", age=10, email="child1@example.com", address=address, children=[])
child2 = Person(name="Child2", age=8, email="child2@example.com", address=address, children=[])
return Person(
name=name,
age=30,
email=f"email_of_{name}@example.com",
address=address,
children=[child1, child2],
)
app = Litestar(route_handlers=[get_person])
litestar-2.16.0/docs/examples/data_transfer_objects/factory/tutorial/initial_pattern.py 0000664 0000000 0000000 00000000776 15005643713 0031613 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from dataclasses import dataclass
from litestar import Litestar, get
@dataclass
class Person:
name: str
age: int
email: str
@get("/person/{name:str}", sync_to_thread=False)
def get_person(name: str) -> Person:
# Your logic to retrieve the person goes here
# For demonstration purposes, a placeholder Person instance is returned
return Person(name=name, age=30, email=f"email_of_{name}@example.com")
app = Litestar(route_handlers=[get_person])
litestar-2.16.0/docs/examples/data_transfer_objects/factory/tutorial/max_nested_depth.py 0000664 0000000 0000000 00000002407 15005643713 0031731 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from dataclasses import dataclass
from typing import List
from litestar import Litestar, get
from litestar.dto import DataclassDTO, DTOConfig
@dataclass
class Address:
street: str
city: str
country: str
@dataclass
class Person:
name: str
age: int
email: str
address: Address
children: List[Person]
class ReadDTO(DataclassDTO[Person]):
config = DTOConfig(
exclude={"email", "address.street", "children.0.email", "children.0.address"},
max_nested_depth=2,
)
@get("/person/{name:str}", return_dto=ReadDTO, sync_to_thread=False)
def get_person(name: str) -> Person:
# Your logic to retrieve the person goes here
# For demonstration purposes, a placeholder Person instance is returned
address = Address(street="123 Main St", city="Cityville", country="Countryland")
child1 = Person(name="Child1", age=10, email="child1@example.com", address=address, children=[])
child2 = Person(name="Child2", age=8, email="child2@example.com", address=address, children=[])
return Person(
name=name,
age=30,
email=f"email_of_{name}@example.com",
address=address,
children=[child1, child2],
)
app = Litestar(route_handlers=[get_person])
litestar-2.16.0/docs/examples/data_transfer_objects/factory/tutorial/multiple_handlers.py 0000664 0000000 0000000 00000002733 15005643713 0032133 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from dataclasses import dataclass
from litestar import Litestar, patch, post, put
from litestar.dto import DataclassDTO, DTOConfig, DTOData
@dataclass
class Person:
name: str
age: int
email: str
id: int
class ReadDTO(DataclassDTO[Person]):
config = DTOConfig(exclude={"email"})
class WriteDTO(DataclassDTO[Person]):
config = DTOConfig(exclude={"id"})
class PatchDTO(DataclassDTO[Person]):
config = DTOConfig(exclude={"id"}, partial=True)
@post("/person", dto=WriteDTO, return_dto=ReadDTO, sync_to_thread=False)
def create_person(data: DTOData[Person]) -> Person:
# Logic for persisting the person goes here
return data.create_instance(id=1)
@put("/person/{person_id:int}", dto=WriteDTO, return_dto=ReadDTO, sync_to_thread=False)
def update_person(person_id: int, data: DTOData[Person]) -> Person:
# Usually the Person would be retrieved from a database
person = Person(id=person_id, name="John", age=50, email="email_of_john@example.com")
return data.update_instance(person)
@patch("/person/{person_id:int}", dto=PatchDTO, return_dto=ReadDTO, sync_to_thread=False)
def patch_person(person_id: int, data: DTOData[Person]) -> Person:
# Usually the Person would be retrieved from a database
person = Person(id=person_id, name="John", age=50, email="email_of_john@example.com")
return data.update_instance(person)
app = Litestar(route_handlers=[create_person, update_person, patch_person])
litestar-2.16.0/docs/examples/data_transfer_objects/factory/tutorial/nested_collection_exclude.py 0000664 0000000 0000000 00000002334 15005643713 0033623 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from dataclasses import dataclass
from typing import List
from litestar import Litestar, get
from litestar.dto import DataclassDTO, DTOConfig
@dataclass
class Address:
street: str
city: str
country: str
@dataclass
class Person:
name: str
age: int
email: str
address: Address
children: List[Person]
class ReadDTO(DataclassDTO[Person]):
config = DTOConfig(exclude={"email", "address.street", "children.0.email", "children.0.address"})
@get("/person/{name:str}", return_dto=ReadDTO, sync_to_thread=False)
def get_person(name: str) -> Person:
# Your logic to retrieve the person goes here
# For demonstration purposes, a placeholder Person instance is returned
address = Address(street="123 Main St", city="Cityville", country="Countryland")
child1 = Person(name="Child1", age=10, email="child1@example.com", address=address, children=[])
child2 = Person(name="Child2", age=8, email="child2@example.com", address=address, children=[])
return Person(
name=name,
age=30,
email=f"email_of_{name}@example.com",
address=address,
children=[child1, child2],
)
app = Litestar(route_handlers=[get_person])
litestar-2.16.0/docs/examples/data_transfer_objects/factory/tutorial/nested_exclude.py 0000664 0000000 0000000 00000001554 15005643713 0031413 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from dataclasses import dataclass
from litestar import Litestar, get
from litestar.dto import DataclassDTO, DTOConfig
@dataclass
class Address:
street: str
city: str
country: str
@dataclass
class Person:
name: str
age: int
email: str
address: Address
class ReadDTO(DataclassDTO[Person]):
config = DTOConfig(exclude={"email", "address.street"})
@get("/person/{name:str}", return_dto=ReadDTO, sync_to_thread=False)
def get_person(name: str) -> Person:
# Your logic to retrieve the person goes here
# For demonstration purposes, a placeholder Person instance is returned
address = Address(street="123 Main St", city="Cityville", country="Countryland")
return Person(name=name, age=30, email=f"email_of_{name}@example.com", address=address)
app = Litestar(route_handlers=[get_person])
litestar-2.16.0/docs/examples/data_transfer_objects/factory/tutorial/patch_handlers.py 0000664 0000000 0000000 00000001464 15005643713 0031377 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from dataclasses import dataclass
from litestar import Litestar, patch
from litestar.dto import DataclassDTO, DTOConfig, DTOData
@dataclass
class Person:
name: str
age: int
email: str
id: int
class ReadDTO(DataclassDTO[Person]):
config = DTOConfig(exclude={"email"})
class PatchDTO(DataclassDTO[Person]):
config = DTOConfig(exclude={"id"}, partial=True)
@patch("/person/{person_id:int}", dto=PatchDTO, return_dto=ReadDTO, sync_to_thread=False)
def update_person(person_id: int, data: DTOData[Person]) -> Person:
# Usually the Person would be retrieved from a database
person = Person(id=person_id, name="John", age=50, email="email_of_john@example.com")
return data.update_instance(person)
app = Litestar(route_handlers=[update_person])
litestar-2.16.0/docs/examples/data_transfer_objects/factory/tutorial/put_handlers.py 0000664 0000000 0000000 00000001442 15005643713 0031104 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from dataclasses import dataclass
from litestar import Litestar, put
from litestar.dto import DataclassDTO, DTOConfig, DTOData
@dataclass
class Person:
name: str
age: int
email: str
id: int
class ReadDTO(DataclassDTO[Person]):
config = DTOConfig(exclude={"email"})
class WriteDTO(DataclassDTO[Person]):
config = DTOConfig(exclude={"id"})
@put("/person/{person_id:int}", dto=WriteDTO, return_dto=ReadDTO, sync_to_thread=False)
def update_person(person_id: int, data: DTOData[Person]) -> Person:
# Usually the Person would be retrieved from a database
person = Person(id=person_id, name="John", age=50, email="email_of_john@example.com")
return data.update_instance(person)
app = Litestar(route_handlers=[update_person])
litestar-2.16.0/docs/examples/data_transfer_objects/factory/tutorial/read_only_fields_error.py 0000664 0000000 0000000 00000001164 15005643713 0033130 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from dataclasses import dataclass
from litestar import Litestar, post
from litestar.dto import DataclassDTO, DTOConfig
@dataclass
class Person:
name: str
age: int
email: str
id: int
class ReadDTO(DataclassDTO[Person]):
config = DTOConfig(exclude={"email"})
class WriteDTO(DataclassDTO[Person]):
config = DTOConfig(exclude={"id"})
@post("/person", dto=WriteDTO, return_dto=ReadDTO, sync_to_thread=False)
def create_person(data: Person) -> Person:
# Logic for persisting the person goes here
return data
app = Litestar(route_handlers=[create_person])
litestar-2.16.0/docs/examples/data_transfer_objects/factory/tutorial/simple_dto_exclude.py 0000664 0000000 0000000 00000001224 15005643713 0032262 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from dataclasses import dataclass
from litestar import Litestar, get
from litestar.dto import DataclassDTO, DTOConfig
@dataclass
class Person:
name: str
age: int
email: str
class ReadDTO(DataclassDTO[Person]):
config = DTOConfig(exclude={"email"})
@get("/person/{name:str}", return_dto=ReadDTO, sync_to_thread=False)
def get_person(name: str) -> Person:
# Your logic to retrieve the person goes here
# For demonstration purposes, a placeholder Person instance is returned
return Person(name=name, age=30, email=f"email_of_{name}@example.com")
app = Litestar(route_handlers=[get_person])
litestar-2.16.0/docs/examples/data_transfer_objects/factory/tutorial/simple_receiving_data.py 0000664 0000000 0000000 00000001013 15005643713 0032723 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from dataclasses import dataclass
from litestar import Litestar, post
from litestar.dto import DataclassDTO, DTOConfig
@dataclass
class Person:
name: str
age: int
email: str
class ReadDTO(DataclassDTO[Person]):
config = DTOConfig(exclude={"email"})
@post("/person", return_dto=ReadDTO, sync_to_thread=False)
def create_person(data: Person) -> Person:
# Logic for persisting the person goes here
return data
app = Litestar(route_handlers=[create_person])
litestar-2.16.0/docs/examples/data_transfer_objects/factory/type_checking.py 0000664 0000000 0000000 00000001253 15005643713 0027365 0 ustar 00root root 0000000 0000000 from datetime import datetime
from sqlalchemy.orm import Mapped, mapped_column
from litestar import Litestar, post
from litestar.dto import dto_field
from litestar.plugins.sqlalchemy import SQLAlchemyDTO
from .my_lib import Base
class User(Base):
name: Mapped[str]
password: Mapped[str] = mapped_column(info=dto_field("private"))
created_at: Mapped[datetime] = mapped_column(info=dto_field("read-only"))
class Foo(Base):
foo: Mapped[str]
UserDTO = SQLAlchemyDTO[User]
@post("/users", dto=UserDTO)
def create_user(data: Foo) -> Foo:
return data
# This will raise an exception at handler registration time.
app = Litestar(route_handlers=[create_user])
litestar-2.16.0/docs/examples/data_transfer_objects/factory/unknown_fields.py 0000664 0000000 0000000 00000001013 15005643713 0027570 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from dataclasses import dataclass
from typing_extensions import Annotated
from litestar import Litestar, post
from litestar.dto import DataclassDTO, DTOConfig
@dataclass
class User:
id: str
UserDTO = DataclassDTO[Annotated[User, DTOConfig(forbid_unknown_fields=True)]]
@post("/users", dto=UserDTO)
async def create_user(data: User) -> User:
return data
app = Litestar([create_user])
# run: /users -H "Content-Type: application/json" -d '{"id": "1", "name": "Peter"}'
litestar-2.16.0/docs/examples/data_transfer_objects/models.py 0000664 0000000 0000000 00000000371 15005643713 0024365 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from dataclasses import dataclass
from uuid import UUID
from litestar.dto import DataclassDTO
@dataclass
class User:
id: UUID
name: str
UserDTO = DataclassDTO[User]
UserReturnDTO = DataclassDTO[User]
litestar-2.16.0/docs/examples/data_transfer_objects/overriding_implicit_return_dto.py 0000664 0000000 0000000 00000000717 15005643713 0031415 0 ustar 00root root 0000000 0000000 from dataclasses import dataclass, field
from uuid import UUID, uuid4
from litestar import Litestar, post
from litestar.dto import DataclassDTO
@dataclass
class User:
name: str
email: str
age: int
id: UUID = field(default_factory=uuid4)
UserDTO = DataclassDTO[User]
@post(dto=UserDTO, return_dto=None, sync_to_thread=False)
def create_user(data: User) -> bytes:
return data.name.encode(encoding="utf-8")
app = Litestar([create_user])
litestar-2.16.0/docs/examples/data_transfer_objects/the_dto_parameter.py 0000664 0000000 0000000 00000000207 15005643713 0026566 0 ustar 00root root 0000000 0000000 from litestar import post
from .models import User, UserDTO
@post(dto=UserDTO)
def create_user(data: User) -> User:
return data
litestar-2.16.0/docs/examples/data_transfer_objects/the_return_dto_parameter.py 0000664 0000000 0000000 00000000260 15005643713 0030164 0 ustar 00root root 0000000 0000000 from litestar import post
from .models import User, UserDTO, UserReturnDTO
@post(dto=UserDTO, return_dto=UserReturnDTO)
def create_user(data: User) -> User:
return data
litestar-2.16.0/docs/examples/datastructures/ 0000775 0000000 0000000 00000000000 15005643713 0021256 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/datastructures/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0023355 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/datastructures/headers/ 0000775 0000000 0000000 00000000000 15005643713 0022671 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/datastructures/headers/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0024770 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/datastructures/headers/cache_control.py 0000664 0000000 0000000 00000001762 15005643713 0026054 0 ustar 00root root 0000000 0000000 import time
from litestar import Controller, Litestar, get
from litestar.datastructures import CacheControlHeader
class MyController(Controller):
cache_control = CacheControlHeader(max_age=86_400, public=True)
@get("/chance_of_rain", sync_to_thread=False)
def get_chance_of_rain(self) -> float:
"""This endpoint uses the cache control value defined in the controller which overrides the app value."""
return 0.5
@get("/timestamp", cache_control=CacheControlHeader(no_store=True), sync_to_thread=False)
def get_server_time(self) -> float:
"""This endpoint overrides the cache control value defined in the controller."""
return time.time()
@get("/population", sync_to_thread=False)
def get_population_count() -> int:
"""This endpoint will use the cache control defined in the app."""
return 100000
app = Litestar(
route_handlers=[MyController, get_population_count],
cache_control=CacheControlHeader(max_age=2_628_288, public=True),
)
litestar-2.16.0/docs/examples/datastructures/headers/etag.py 0000664 0000000 0000000 00000002772 15005643713 0024173 0 ustar 00root root 0000000 0000000 import random
import time
from litestar import Controller, Litestar, get
from litestar.datastructures import ETag
from litestar.enums import MediaType
from litestar.response import Response
class MyController(Controller):
etag = ETag(value="foo")
@get("/chance_of_rain")
def get_chance_of_rain(self) -> float:
"""This endpoint uses the etag value in the controller which overrides the app value.
The returned header will be `etag: "foo"`
"""
return 0.5
@get("/timestamp", etag=ETag(value="bar"))
def get_server_time(self) -> float:
"""This endpoint overrides the etag defined in the controller.
The returned header will be `etag: W/"bar"`
"""
return time.time()
@get("/population")
def get_population_count() -> int:
"""This endpoint will use the etag defined in the app.
The returned header will be `etag: "bar"`
"""
return 100000
@get("/population-dynamic", etag=ETag(documentation_only=True))
def get_population_count_dynamic() -> Response[str]:
"""The etag defined in this route handler will not be returned, and does not need a value.
It will only be used for OpenAPI generation.
"""
population_count = random.randint(0, 1000)
return Response(
content=str(population_count),
headers={"etag": str(population_count)},
media_type=MediaType.TEXT,
status_code=200,
)
app = Litestar(route_handlers=[MyController, get_population_count], etag=ETag(value="bar"))
litestar-2.16.0/docs/examples/datastructures/headers/etag_parsing.py 0000664 0000000 0000000 00000000243 15005643713 0025705 0 ustar 00root root 0000000 0000000 from litestar.datastructures import ETag
assert ETag.from_header('"foo"') == ETag(value="foo")
assert ETag.from_header('W/"foo"') == ETag(value="foo", weak=True)
litestar-2.16.0/docs/examples/datastructures/secrets/ 0000775 0000000 0000000 00000000000 15005643713 0022726 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/datastructures/secrets/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0025025 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/datastructures/secrets/secret_body.py 0000664 0000000 0000000 00000000420 15005643713 0025576 0 ustar 00root root 0000000 0000000 from dataclasses import dataclass
from litestar import post
from litestar.datastructures.secret_values import SecretString
@dataclass
class Sensitive:
value: SecretString
@post(sync_to_thread=False)
def post_handler(data: Sensitive) -> Sensitive:
return data
litestar-2.16.0/docs/examples/datastructures/secrets/secret_header.py 0000664 0000000 0000000 00000001351 15005643713 0026075 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from dataclasses import dataclass
from secrets import compare_digest
from typing_extensions import Annotated
from litestar import get
from litestar.datastructures.secret_values import SecretString
from litestar.exceptions import NotAuthorizedException
from litestar.params import Parameter
SECRET_VALUE = "super-secret" # An example secret value - this should be stored securely in production.
@dataclass
class Sensitive:
value: str
@get(sync_to_thread=False)
def get_handler(secret: Annotated[SecretString, Parameter(header="x-secret")]) -> Sensitive:
if not compare_digest(secret.get_secret(), SECRET_VALUE):
raise NotAuthorizedException
return Sensitive(value="sensitive data")
litestar-2.16.0/docs/examples/dependency_injection/ 0000775 0000000 0000000 00000000000 15005643713 0022361 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/dependency_injection/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0024460 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/dependency_injection/dependency_non_optional_not_provided.py 0000664 0000000 0000000 00000001222 15005643713 0032401 0 ustar 00root root 0000000 0000000 from typing import Any
from typing_extensions import Annotated
from litestar import Litestar, get
from litestar.params import Dependency
@get("/")
def hello_world(non_optional_dependency: Annotated[int, Dependency()]) -> dict[str, Any]:
"""Notice we haven't provided the dependency to the route.
This is not great, however by explicitly marking dependencies, Litestar won't let the app start.
"""
return {"hello": non_optional_dependency}
app = Litestar(route_handlers=[hello_world])
# ImproperlyConfiguredException: 500: Explicit dependency 'non_optional_dependency' for 'hello_world' has no default
# value, or provided dependency.
litestar-2.16.0/docs/examples/dependency_injection/dependency_skip_validation.py 0000664 0000000 0000000 00000001103 15005643713 0030304 0 ustar 00root root 0000000 0000000 from typing import Any, Dict
from typing_extensions import Annotated
from litestar import Litestar, get
from litestar.di import Provide
from litestar.params import Dependency
async def provide_str() -> str:
"""Returns a string."""
return "whoops"
@get("/", dependencies={"injected": Provide(provide_str)}, sync_to_thread=False)
def hello_world(injected: Annotated[int, Dependency(skip_validation=True)]) -> Dict[str, Any]:
"""Handler expects an `int`, but we've provided a `str`."""
return {"hello": injected}
app = Litestar(route_handlers=[hello_world])
litestar-2.16.0/docs/examples/dependency_injection/dependency_validation_error.py 0000664 0000000 0000000 00000000706 15005643713 0030477 0 ustar 00root root 0000000 0000000 from typing import Any, Dict
from litestar import Litestar, get
from litestar.di import Provide
async def provide_str() -> str:
"""Returns a string."""
return "whoops"
@get("/", dependencies={"injected": Provide(provide_str)}, sync_to_thread=False)
def hello_world(injected: int) -> Dict[str, Any]:
"""Handler expects an `int`, but we've provided a `str`."""
return {"hello": injected}
app = Litestar(route_handlers=[hello_world])
litestar-2.16.0/docs/examples/dependency_injection/dependency_with_default.py 0000664 0000000 0000000 00000000630 15005643713 0027607 0 ustar 00root root 0000000 0000000 from typing import Any, Dict
from litestar import Litestar, get
@get("/", sync_to_thread=False)
def hello_world(optional_dependency: int = 3) -> Dict[str, Any]:
"""Notice we haven't provided the dependency to the route.
This is OK, because of the default value, but the parameter shows in the docs.
"""
return {"hello": optional_dependency}
app = Litestar(route_handlers=[hello_world])
litestar-2.16.0/docs/examples/dependency_injection/dependency_with_dependency_fn_and_default.py 0000664 0000000 0000000 00000001022 15005643713 0033306 0 ustar 00root root 0000000 0000000 from typing import Any, Dict
from typing_extensions import Annotated
from litestar import Litestar, get
from litestar.params import Dependency
@get("/", sync_to_thread=False)
def hello_world(optional_dependency: Annotated[int, Dependency(default=3)]) -> Dict[str, Any]:
"""Notice we haven't provided the dependency to the route.
This is OK, because of the default value, and now the parameter is excluded from the docs.
"""
return {"hello": optional_dependency}
app = Litestar(route_handlers=[hello_world])
litestar-2.16.0/docs/examples/dependency_injection/dependency_yield_exceptions.py 0000664 0000000 0000000 00000001612 15005643713 0030500 0 ustar 00root root 0000000 0000000 from typing import Dict, Generator
from litestar import Litestar, get
from litestar.di import Provide
STATE = {"result": None, "connection": "closed"}
def generator_function() -> Generator[str, None, None]:
"""Set the connection state to open and close it after the handler returns.
If an error occurs, set `result` to `"error"`, else set it to `"OK"`.
"""
try:
STATE["connection"] = "open"
yield "hello"
STATE["result"] = "OK"
except ValueError:
STATE["result"] = "error"
finally:
STATE["connection"] = "closed"
@get("/{name:str}", dependencies={"message": Provide(generator_function)})
def index(name: str, message: str) -> Dict[str, str]:
"""If `name` is "John", return a message, otherwise raise an error."""
if name == "John":
return {name: message}
raise ValueError()
app = Litestar(route_handlers=[index])
litestar-2.16.0/docs/examples/dependency_injection/dependency_yield_simple.py 0000664 0000000 0000000 00000001103 15005643713 0027603 0 ustar 00root root 0000000 0000000 from typing import Dict, Generator
from litestar import Litestar, get
from litestar.di import Provide
CONNECTION = {"open": False}
def generator_function() -> Generator[Dict[str, bool], None, None]:
"""Set connection to open and close it after the handler returns."""
CONNECTION["open"] = True
yield CONNECTION
CONNECTION["open"] = False
@get("/", dependencies={"conn": Provide(generator_function)})
def index(conn: Dict[str, bool]) -> Dict[str, bool]:
"""Return the current connection state."""
return conn
app = Litestar(route_handlers=[index])
litestar-2.16.0/docs/examples/deployment/ 0000775 0000000 0000000 00000000000 15005643713 0020361 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/deployment/nginx-unit/ 0000775 0000000 0000000 00000000000 15005643713 0022461 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/deployment/nginx-unit/install-macos.sh 0000664 0000000 0000000 00000000101 15005643713 0025553 0 ustar 00root root 0000000 0000000 brew install unit-python311
brew install nginx/unit/unit-python3
litestar-2.16.0/docs/examples/deployment/nginx-unit/unit.json 0000664 0000000 0000000 00000000644 15005643713 0024337 0 ustar 00root root 0000000 0000000 {
"listeners": {
"*:8080": {
"pass": "applications/litestar"
}
},
"applications": {
"litestar": {
"type": "python 3.11",
"home": "/Users/user/project/litestar/.venv/",
"path": "/Users/user/project/litestar/src/app",
"module": "run",
"callable": "app",
"stderr": "/Users/user/project/litestar/error.log",
"user": "user",
"processes": 1
}
}
}
litestar-2.16.0/docs/examples/encoding_decoding/ 0000775 0000000 0000000 00000000000 15005643713 0021623 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/encoding_decoding/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0023722 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/encoding_decoding/custom_type_encoding_decoding.py 0000664 0000000 0000000 00000004037 15005643713 0030256 0 ustar 00root root 0000000 0000000 from typing import Any, Type
from msgspec import Struct
from litestar import Litestar, post
class TenantUser:
"""Custom Type that represents a user associated to a tenant
Parsed from / serialized to a combined tenant + user id string of the form
TENANTPREFIX_USERID
i.e. separated by underscore.
"""
tenant_prefix: str
user_id: str
def __init__(self, tenant_prefix: str, user_id: str) -> None:
self.tenant_prefix = tenant_prefix
self.user_id = user_id
@classmethod
def from_string(cls, s: str) -> "TenantUser":
splits = s.split("_", maxsplit=1)
if len(splits) < 2:
raise ValueError(
"Could not split up tenant user id string. "
"Expecting underscore for separation of tenant prefix and user id."
)
return cls(tenant_prefix=splits[0], user_id=splits[1])
def to_combined_str(self) -> str:
return self.tenant_prefix + "_" + self.user_id
def tenant_user_type_predicate(type: Type) -> bool:
return type is TenantUser
def tenant_user_enc_hook(u: TenantUser) -> Any:
return u.to_combined_str()
def tenant_user_dec_hook(tenant_user_id_str: str) -> TenantUser:
return TenantUser.from_string(tenant_user_id_str)
def general_dec_hook(type: Type, obj: Any) -> Any:
if tenant_user_type_predicate(type):
return tenant_user_dec_hook(obj)
raise NotImplementedError(f"Encountered unknown type during decoding: {type!s}")
class UserAsset(Struct):
user: TenantUser
name: str
@post("/asset", sync_to_thread=False)
def create_asset(
data: UserAsset,
) -> UserAsset:
assert isinstance(data.user, TenantUser)
return data
app = Litestar(
[create_asset],
type_encoders={TenantUser: tenant_user_enc_hook}, # tell litestar how to encode TenantUser
type_decoders=[(tenant_user_type_predicate, general_dec_hook)], # tell litestar how to decode TenantUser
)
# run: /asset -X POST -H "Content-Type: application/json" -d '{"name":"SomeAsset","user":"TenantA_Somebody"}'
litestar-2.16.0/docs/examples/encoding_decoding/custom_type_pydantic.py 0000664 0000000 0000000 00000003343 15005643713 0026446 0 ustar 00root root 0000000 0000000 from pydantic import BaseModel, BeforeValidator, ConfigDict, PlainSerializer, WithJsonSchema
from typing_extensions import Annotated
from litestar import Litestar, post
class TenantUser:
"""Custom Type that represents a user associated to a tenant
Parsed from / serialized to a combined tenant + user id string of the form
TENANTPREFIX_USERID
i.e. separated by underscore.
"""
tenant_prefix: str
user_id: str
def __init__(self, tenant_prefix: str, user_id: str) -> None:
self.tenant_prefix = tenant_prefix
self.user_id = user_id
@classmethod
def from_string(cls, s: str) -> "TenantUser":
splits = s.split("_", maxsplit=1)
if len(splits) < 2:
raise ValueError(
"Could not split up tenant user id string. "
"Expecting underscore for separation of tenant prefix and user id."
)
return cls(tenant_prefix=splits[0], user_id=splits[1])
def to_combined_str(self) -> str:
return self.tenant_prefix + "_" + self.user_id
PydAnnotatedTenantUser = Annotated[
TenantUser,
BeforeValidator(lambda x: TenantUser.from_string(x)),
PlainSerializer(lambda x: x.to_combined_str(), return_type=str),
WithJsonSchema({"type": "string"}, mode="serialization"),
]
class UserAsset(BaseModel):
model_config = ConfigDict(arbitrary_types_allowed=True)
user: PydAnnotatedTenantUser
name: str
@post("/asset", sync_to_thread=False)
def create_asset(
data: UserAsset,
) -> UserAsset:
assert isinstance(data.user, TenantUser)
return data
app = Litestar(
[create_asset],
)
# run: /asset -X POST -H "Content-Type: application/json" -d '{"name":"SomeAsset","user":"TenantA_Somebody"}'
litestar-2.16.0/docs/examples/exceptions/ 0000775 0000000 0000000 00000000000 15005643713 0020362 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/exceptions/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0022461 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/exceptions/implicit_media_type.py 0000664 0000000 0000000 00000000147 15005643713 0024750 0 ustar 00root root 0000000 0000000 from litestar import get
@get(sync_to_thread=False)
def handler(q: int) -> str:
raise ValueError
litestar-2.16.0/docs/examples/exceptions/layered_handlers.py 0000664 0000000 0000000 00000002035 15005643713 0024241 0 ustar 00root root 0000000 0000000 from litestar import Litestar, Request, Response, get
from litestar.exceptions import HTTPException, ValidationException
def app_exception_handler(request: Request, exc: HTTPException) -> Response:
return Response(
content={
"error": "server error",
"path": request.url.path,
"detail": exc.detail,
"status_code": exc.status_code,
},
status_code=500,
)
def router_handler_exception_handler(request: Request, exc: ValidationException) -> Response:
return Response(
content={"error": "validation error", "path": request.url.path},
status_code=400,
)
@get("/")
async def index() -> None:
raise HTTPException("something's gone wrong")
@get(
"/greet",
exception_handlers={ValidationException: router_handler_exception_handler},
)
async def greet(name: str) -> str:
return f"hello {name}"
app = Litestar(
route_handlers=[index, greet],
exception_handlers={HTTPException: app_exception_handler},
)
# run: /
# run: /greet
litestar-2.16.0/docs/examples/exceptions/override_default_handler.py 0000664 0000000 0000000 00000001436 15005643713 0025760 0 ustar 00root root 0000000 0000000 from litestar import Litestar, MediaType, Request, Response, get
from litestar.exceptions import HTTPException
from litestar.status_codes import HTTP_500_INTERNAL_SERVER_ERROR
def plain_text_exception_handler(_: Request, exc: Exception) -> Response:
"""Default handler for exceptions subclassed from HTTPException."""
status_code = getattr(exc, "status_code", HTTP_500_INTERNAL_SERVER_ERROR)
detail = getattr(exc, "detail", "")
return Response(
media_type=MediaType.TEXT,
content=detail,
status_code=status_code,
)
@get("/")
async def index() -> None:
raise HTTPException(detail="an error occurred", status_code=400)
app = Litestar(
route_handlers=[index],
exception_handlers={HTTPException: plain_text_exception_handler},
)
# run: /
litestar-2.16.0/docs/examples/exceptions/per_exception_handlers.py 0000664 0000000 0000000 00000002716 15005643713 0025466 0 ustar 00root root 0000000 0000000 from litestar import Litestar, MediaType, Request, Response, get
from litestar.exceptions import HTTPException, ValidationException
from litestar.status_codes import HTTP_500_INTERNAL_SERVER_ERROR
def validation_exception_handler(request: Request, exc: ValidationException) -> Response:
return Response(
media_type=MediaType.TEXT,
content=f"validation error: {exc.detail}",
status_code=400,
)
def internal_server_error_handler(request: Request, exc: Exception) -> Response:
return Response(
media_type=MediaType.TEXT,
content=f"server error: {exc}",
status_code=500,
)
def value_error_handler(request: Request, exc: ValueError) -> Response:
return Response(
media_type=MediaType.TEXT,
content=f"value error: {exc}",
status_code=400,
)
@get("/validation-error")
async def validation_error(some_query_param: str) -> str:
return some_query_param
@get("/server-error")
async def server_error() -> None:
raise HTTPException()
@get("/value-error")
async def value_error() -> None:
raise ValueError("this is wrong")
app = Litestar(
route_handlers=[validation_error, server_error, value_error],
exception_handlers={
ValidationException: validation_exception_handler,
HTTP_500_INTERNAL_SERVER_ERROR: internal_server_error_handler,
ValueError: value_error_handler,
},
)
# run: /validation-error
# run: /server-error
# run: /value-error
litestar-2.16.0/docs/examples/hello_world.py 0000664 0000000 0000000 00000000411 15005643713 0021061 0 ustar 00root root 0000000 0000000 from typing import Dict
from litestar import Litestar, get
@get("/")
async def hello_world() -> Dict[str, str]:
"""Handler function that returns a greeting dictionary."""
return {"hello": "world"}
app = Litestar(route_handlers=[hello_world])
# run: /
litestar-2.16.0/docs/examples/lifecycle_hooks/ 0000775 0000000 0000000 00000000000 15005643713 0021343 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/lifecycle_hooks/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0023442 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/lifecycle_hooks/after_request.py 0000664 0000000 0000000 00000001025 15005643713 0024564 0 ustar 00root root 0000000 0000000 from typing import Dict
from litestar import Litestar, MediaType, Response, get
async def after_request(response: Response) -> Response:
if response.media_type == MediaType.TEXT:
return Response({"message": response.content})
return response
@get("/hello")
async def hello() -> str:
return "Hello, world"
@get("/goodbye")
async def goodbye() -> Dict[str, str]:
return {"message": "Goodbye"}
app = Litestar(route_handlers=[hello, goodbye], after_request=after_request)
# run: /hello
# run: /goodbye
litestar-2.16.0/docs/examples/lifecycle_hooks/after_response.py 0000664 0000000 0000000 00000000635 15005643713 0024740 0 ustar 00root root 0000000 0000000 from collections import defaultdict
from typing import Dict
from litestar import Litestar, Request, get
COUNTER: Dict[str, int] = defaultdict(int)
async def after_response(request: Request) -> None:
COUNTER[request.url.path] += 1
@get("/hello")
async def hello() -> Dict[str, int]:
return COUNTER
app = Litestar(route_handlers=[hello], after_response=after_response)
# run: /hello
# run: /hello
litestar-2.16.0/docs/examples/lifecycle_hooks/before_request.py 0000664 0000000 0000000 00000001205 15005643713 0024725 0 ustar 00root root 0000000 0000000 from typing import Dict, Optional
from litestar import Litestar, Request, get
async def before_request_handler(request: Request) -> Optional[Dict[str, str]]:
name = request.query_params["name"]
if name == "Ben":
return {"message": "These are not the bytes you are looking for"}
request.state["message"] = f"Use the handler, {name}"
return None
@get("/")
async def handler(request: Request, name: str) -> Dict[str, str]:
message: str = request.state["message"]
return {"message": message}
app = Litestar(route_handlers=[handler], before_request=before_request_handler)
# run: /?name=Luke
# run: /?name=Ben
litestar-2.16.0/docs/examples/lifecycle_hooks/layered_hooks.py 0000664 0000000 0000000 00000001124 15005643713 0024543 0 ustar 00root root 0000000 0000000 from litestar import Litestar, Response, get
def after_request_app(response: Response) -> Response:
return Response(content=b"app after request")
def after_request_handler(response: Response) -> Response:
return Response(content=b"handler after request")
@get("/")
async def handler() -> str:
return "hello, world"
@get("/override", after_request=after_request_handler)
async def handler_with_override() -> str:
return "hello, world"
app = Litestar(
route_handlers=[handler, handler_with_override],
after_request=after_request_app,
)
# run: /
# run: /override
litestar-2.16.0/docs/examples/middleware/ 0000775 0000000 0000000 00000000000 15005643713 0020316 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/middleware/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0022415 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/middleware/abstract_middleware_migration_new.py 0000664 0000000 0000000 00000001007 15005643713 0027610 0 ustar 00root root 0000000 0000000 import anyio
from litestar import Litestar
from litestar.middleware import ASGIMiddleware
from litestar.types import ASGIApp, Receive, Scope, Send
class TimeoutMiddleware(ASGIMiddleware):
def __init__(self, timeout: float):
self.timeout = timeout
async def handle(self, scope: Scope, receive: Receive, send: Send, next_app: ASGIApp) -> None:
with anyio.move_on_after(self.timeout):
await next_app(scope, receive, send)
app = Litestar(middleware=[TimeoutMiddleware(timeout=5)])
litestar-2.16.0/docs/examples/middleware/abstract_middleware_migration_old.py 0000664 0000000 0000000 00000001563 15005643713 0027604 0 ustar 00root root 0000000 0000000 import anyio
from litestar import Litestar
from litestar.middleware import AbstractMiddleware, DefineMiddleware
from litestar.types import ASGIApp, Receive, Scope, Scopes, Send
class TimeoutMiddleware(AbstractMiddleware):
def __init__(
self,
app: ASGIApp,
timeout: float,
exclude: str | list[str] | None = None,
exclude_opt_key: str | None = None,
scopes: Scopes | None = None,
):
self.timeout = timeout
super().__init__(app=app, exclude=exclude, exclude_opt_key=exclude_opt_key, scopes=scopes)
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
with anyio.move_on_after(self.timeout):
await self.app(scope, receive, send)
app = Litestar(
middleware=[
DefineMiddleware(
TimeoutMiddleware,
timeout=5,
)
]
)
litestar-2.16.0/docs/examples/middleware/base.py 0000664 0000000 0000000 00000004530 15005643713 0021604 0 ustar 00root root 0000000 0000000 import time
from typing import Dict
from litestar import Litestar, WebSocket, get, websocket
from litestar.datastructures import MutableScopeHeaders
from litestar.enums import ScopeType
from litestar.middleware import ASGIMiddleware
from litestar.types import ASGIApp, Message, Receive, Scope, Send
class MyMiddleware(ASGIMiddleware):
scopes = (ScopeType.HTTP,)
exclude_path_pattern = ("first_path", "second_path")
exclude_opt_key = "exclude_from_my_middleware"
async def handle(self, scope: Scope, receive: Receive, send: Send, next_app: ASGIApp) -> None:
start_time = time.monotonic()
async def send_wrapper(message: "Message") -> None:
if message["type"] == "http.response.start":
process_time = time.monotonic() - start_time
headers = MutableScopeHeaders.from_message(message=message)
headers["X-Process-Time"] = str(process_time)
await send(message)
await next_app(scope, receive, send_wrapper)
@websocket("/my-websocket")
async def websocket_handler(socket: WebSocket) -> None:
"""
Websocket handler - is excluded because the middleware scopes includes 'ScopeType.HTTP'
"""
await socket.accept()
await socket.send_json({"hello": "websocket"})
await socket.close()
@get("/first_path", sync_to_thread=False)
def first_handler() -> Dict[str, str]:
"""Handler is excluded due to regex pattern matching "first_path"."""
return {"hello": "first"}
@get("/second_path", sync_to_thread=False)
def second_handler() -> Dict[str, str]:
"""Handler is excluded due to regex pattern matching "second_path"."""
return {"hello": "second"}
@get("/third_path", exclude_from_my_middleware=True, sync_to_thread=False)
def third_handler() -> Dict[str, str]:
"""Handler is excluded due to the opt key 'exclude_from_my_middleware' matching the middleware 'exclude_opt_key'."""
return {"hello": "third"}
@get("/greet", sync_to_thread=False)
def not_excluded_handler() -> Dict[str, str]:
"""This handler is not excluded, and thus the middleware will execute on every incoming request to it."""
return {"hello": "world"}
app = Litestar(
route_handlers=[
websocket_handler,
first_handler,
second_handler,
third_handler,
not_excluded_handler,
],
middleware=[MyMiddleware()],
)
litestar-2.16.0/docs/examples/middleware/call_order.py 0000664 0000000 0000000 00000002676 15005643713 0023011 0 ustar 00root root 0000000 0000000 from typing import TYPE_CHECKING, List, Type
from litestar import Controller, Litestar, Router, get
from litestar.datastructures import State
from litestar.middleware import MiddlewareProtocol
if TYPE_CHECKING:
from litestar.types import ASGIApp, Receive, Scope, Send
def create_test_middleware(middleware_id: int) -> Type[MiddlewareProtocol]:
class TestMiddleware(MiddlewareProtocol):
def __init__(self, app: "ASGIApp") -> None:
self.app = app
async def __call__(self, scope: "Scope", receive: "Receive", send: "Send") -> None:
litestar_app = scope["app"]
litestar_app.state.setdefault("middleware_calls", [])
litestar_app.state["middleware_calls"].append(middleware_id)
await self.app(scope, receive, send)
return TestMiddleware
class MyController(Controller):
path = "/controller"
middleware = [create_test_middleware(4), create_test_middleware(5)]
@get(
"/handler",
middleware=[create_test_middleware(6), create_test_middleware(7)],
)
async def my_handler(self, state: State) -> List[int]:
return state["middleware_calls"]
router = Router(
path="/router",
route_handlers=[MyController],
middleware=[create_test_middleware(2), create_test_middleware(3)],
)
app = Litestar(
route_handlers=[router],
middleware=[create_test_middleware(0), create_test_middleware(1)],
)
# run: /router/controller/handler
litestar-2.16.0/docs/examples/middleware/logging_middleware.py 0000664 0000000 0000000 00000000731 15005643713 0024514 0 ustar 00root root 0000000 0000000 from typing import Dict
from litestar import Litestar, get
from litestar.logging.config import LoggingConfig
from litestar.middleware.logging import LoggingMiddlewareConfig
logging_middleware_config = LoggingMiddlewareConfig()
@get("/", sync_to_thread=False)
def my_handler() -> Dict[str, str]:
return {"hello": "world"}
app = Litestar(
route_handlers=[my_handler],
logging_config=LoggingConfig(),
middleware=[logging_middleware_config.middleware],
)
litestar-2.16.0/docs/examples/middleware/middleware_protocol_migration_new.py 0000664 0000000 0000000 00000000461 15005643713 0027651 0 ustar 00root root 0000000 0000000 from litestar.middleware import ASGIMiddleware
from litestar.types import ASGIApp, Receive, Scope, Send
class MyMiddleware(ASGIMiddleware):
async def handle(self, scope: Scope, receive: Receive, send: Send, next_app: ASGIApp) -> None:
# do stuff
await next_app(scope, receive, send)
litestar-2.16.0/docs/examples/middleware/middleware_protocol_migration_old.py 0000664 0000000 0000000 00000000556 15005643713 0027643 0 ustar 00root root 0000000 0000000 from litestar.middleware import MiddlewareProtocol
from litestar.types import ASGIApp, Receive, Scope, Send
class MyMiddleware(MiddlewareProtocol):
def __init__(self, app: ASGIApp) -> None:
self.app = app
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
# do stuff
await self.app(scope, receive, send)
litestar-2.16.0/docs/examples/middleware/rate_limit.py 0000664 0000000 0000000 00000000700 15005643713 0023016 0 ustar 00root root 0000000 0000000 from litestar import Litestar, MediaType, get
from litestar.middleware.rate_limit import RateLimitConfig
rate_limit_config = RateLimitConfig(rate_limit=("minute", 1), exclude=["/schema"])
@get("/", media_type=MediaType.TEXT, sync_to_thread=False)
def handler() -> str:
"""Handler which should not be accessed more than once per minute."""
return "ok"
app = Litestar(route_handlers=[handler], middleware=[rate_limit_config.middleware])
litestar-2.16.0/docs/examples/middleware/request_timing.py 0000664 0000000 0000000 00000001517 15005643713 0023733 0 ustar 00root root 0000000 0000000 import time
from litestar.datastructures import MutableScopeHeaders
from litestar.enums import ScopeType
from litestar.middleware import ASGIMiddleware
from litestar.types import ASGIApp, Message, Receive, Scope, Send
class ProcessTimeHeader(ASGIMiddleware):
scopes = (ScopeType.HTTP, ScopeType.ASGI)
async def handle(self, scope: Scope, receive: Receive, send: Send, next_app: ASGIApp) -> None:
start_time = time.monotonic()
async def send_wrapper(message: Message) -> None:
if message["type"] == "http.response.start":
process_time = time.monotonic() - start_time
headers = MutableScopeHeaders.from_message(message=message)
headers["X-Process-Time"] = str(process_time)
await send(message)
await next_app(scope, receive, send_wrapper)
litestar-2.16.0/docs/examples/middleware/session/ 0000775 0000000 0000000 00000000000 15005643713 0022001 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/middleware/session/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0024100 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/middleware/session/cookie_backend.py 0000664 0000000 0000000 00000000400 15005643713 0025265 0 ustar 00root root 0000000 0000000 from os import urandom
from litestar import Litestar
from litestar.middleware.session.client_side import CookieBackendConfig
session_config = CookieBackendConfig(secret=urandom(16)) # type: ignore
app = Litestar(middleware=[session_config.middleware])
litestar-2.16.0/docs/examples/middleware/session/cookies_full_example.py 0000664 0000000 0000000 00000002325 15005643713 0026546 0 ustar 00root root 0000000 0000000 from os import urandom
from typing import Dict
from litestar import Litestar, Request, delete, get, post
from litestar.middleware.session.client_side import CookieBackendConfig
# we initialize to config with a 16 byte key, i.e. 128 a bit key.
# in real world usage we should inject the secret from the environment
session_config = CookieBackendConfig(secret=urandom(16)) # type: ignore[arg-type]
@get("/session", sync_to_thread=False)
def check_session_handler(request: Request) -> Dict[str, bool]:
"""Handler function that accesses request.session."""
return {"has_session": request.session != {}}
@post("/session", sync_to_thread=False)
def create_session_handler(request: Request) -> None:
"""Handler to set the session."""
if not request.session:
# value can be a dictionary or pydantic model
request.set_session({"username": "moishezuchmir"})
@delete("/session", sync_to_thread=False)
def delete_session_handler(request: Request) -> None:
"""Handler to clear the session."""
if request.session:
request.clear_session()
app = Litestar(
route_handlers=[check_session_handler, create_session_handler, delete_session_handler],
middleware=[session_config.middleware],
)
litestar-2.16.0/docs/examples/middleware/session/file_store.py 0000664 0000000 0000000 00000000470 15005643713 0024507 0 ustar 00root root 0000000 0000000 from pathlib import Path
from litestar import Litestar
from litestar.middleware.session.server_side import ServerSideSessionConfig
from litestar.stores.file import FileStore
app = Litestar(
middleware=[ServerSideSessionConfig().middleware],
stores={"sessions": FileStore(path=Path("session_data"))},
)
litestar-2.16.0/docs/examples/middleware/using_asgi_middleware.py 0000664 0000000 0000000 00000003777 15005643713 0025233 0 ustar 00root root 0000000 0000000 import anyio
from litestar import Litestar, get
from litestar.enums import ScopeType
from litestar.exceptions import ClientException
from litestar.middleware import ASGIMiddleware
from litestar.types import ASGIApp, Receive, Scope, Send
class TimeoutMiddleware(ASGIMiddleware):
# we can configure some things on the class level here, related to when our
# middleware should be applied.
# if the requests' 'scope["type"]' is not "http", the middleware will be skipped
scopes = (ScopeType.HTTP,)
# if the handler for a request has set an opt of 'no_timeout=True', the middleware
# will be skipped
exclude_opt_key = "no_timeout"
# the base class does not define an '__init__' method, so we're free to overwrite
# this, which we're making use of to add some configuration
def __init__(
self,
timeout: float,
exclude_path_pattern: str | tuple[str, ...] | None = None,
) -> None:
self.timeout = timeout
# we can also dynamically configure the options provided by the base class on
# the instance level
self.exclude_path_pattern = exclude_path_pattern
async def handle(self, scope: Scope, receive: Receive, send: Send, next_app: ASGIApp) -> None:
try:
with anyio.fail_after(self.timeout):
# call the next app in the chain
await next_app(scope, receive, send)
except TimeoutError:
# if the request has timed out, raise an exception. since the whole
# application is wrapped in an exception handling middleware, it will
# transform this exception into a response for us
raise ClientException(status_code=408) from None
@get("/", no_timeout=True)
async def handler_with_opt_skip() -> None:
pass
@get("/not-this-path")
async def handler_with_path_skip() -> None:
pass
app = Litestar(
route_handlers=[
handler_with_opt_skip,
handler_with_path_skip,
],
middleware=[TimeoutMiddleware(timeout=5)],
)
litestar-2.16.0/docs/examples/openapi/ 0000775 0000000 0000000 00000000000 15005643713 0017634 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/openapi/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0021733 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/openapi/customize_operation_class.py 0000664 0000000 0000000 00000003242 15005643713 0025476 0 ustar 00root root 0000000 0000000 from dataclasses import dataclass, field
from typing import Dict, List, Optional
from litestar import Litestar, MediaType, Request, post
from litestar.exceptions import HTTPException
from litestar.openapi.spec import OpenAPIMediaType, OpenAPIType, Operation, RequestBody, Schema
from litestar.status_codes import HTTP_400_BAD_REQUEST
@dataclass
class CustomOperation(Operation):
"""Custom Operation class which includes a non-standard field which is part of an OpenAPI extension."""
x_code_samples: Optional[List[Dict[str, str]]] = field(default=None, metadata={"alias": "x-codeSamples"})
def __post_init__(self) -> None:
self.tags = ["ok"]
self.description = "Requires OK, Returns OK"
self.request_body = RequestBody(
content={
"text": OpenAPIMediaType(
schema=Schema(
title="Body",
type=OpenAPIType.STRING,
example="OK",
)
),
},
description="OK is the only accepted value",
)
self.x_codeSamples = [
{"lang": "Python", "source": "import requests; requests.get('localhost/example')", "label": "Python"},
{"lang": "cURL", "source": "curl -XGET localhost/example", "label": "curl"},
]
@post("/", operation_class=CustomOperation, media_type=MediaType.TEXT)
async def route(request: Request) -> str:
"""
Returns: OK
"""
if (await request.body()) == b"OK":
return "OK"
raise HTTPException(status_code=HTTP_400_BAD_REQUEST, detail="request payload must be OK")
app = Litestar(route_handlers=[route])
litestar-2.16.0/docs/examples/openapi/customize_path.py 0000664 0000000 0000000 00000000644 15005643713 0023250 0 ustar 00root root 0000000 0000000 from typing import Dict
from litestar import Litestar, get
from litestar.openapi.config import OpenAPIConfig
@get("/")
def hello_world() -> Dict[str, str]:
return {"message": "Hello World"}
app = Litestar(
route_handlers=[hello_world],
openapi_config=OpenAPIConfig(
title="My API",
description="This is the description of my API",
version="0.1.0",
path="/docs",
),
)
litestar-2.16.0/docs/examples/openapi/customize_pydantic_model_name.py 0000664 0000000 0000000 00000000571 15005643713 0026306 0 ustar 00root root 0000000 0000000 from uuid import UUID, uuid4
from pydantic import BaseModel
from litestar import Litestar, get
class IdModel(BaseModel):
__schema_name__ = "IdContainer"
id: UUID
@get("/id", sync_to_thread=False)
def retrieve_id_handler() -> IdModel:
"""
Returns: An IdModel
"""
return IdModel(id=uuid4())
app = Litestar(route_handlers=[retrieve_id_handler])
litestar-2.16.0/docs/examples/openapi/plugins/ 0000775 0000000 0000000 00000000000 15005643713 0021315 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/openapi/plugins/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0023414 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/openapi/plugins/custom_plugin.py 0000664 0000000 0000000 00000003222 15005643713 0024556 0 ustar 00root root 0000000 0000000 from __future__ import annotations
from collections.abc import Sequence
from typing import Any
from litestar.connection import Request
from litestar.openapi.plugins import OpenAPIRenderPlugin
class ScalarRenderPlugin(OpenAPIRenderPlugin):
def __init__(
self,
*,
version: str = "1.19.5",
js_url: str | None = None,
css_url: str | None = None,
path: str | Sequence[str] = "/scalar",
**kwargs: Any,
) -> None:
self.js_url = js_url or f"https://cdn.jsdelivr.net/npm/@scalar/api-reference@{version}"
self.css_url = css_url
super().__init__(path=path, **kwargs)
def render(self, request: Request, openapi_schema: dict[str, Any]) -> bytes:
style_sheet_link = f'' if self.css_url else ""
head = f"""
{{ message.message }} (Category:{{ message.category }})
{% endfor %} """ ) app = Litestar( plugins=[flash_plugin], route_handlers=[index], template_config=template_config, middleware=[ServerSideSessionConfig().middleware], ) litestar-2.16.0/docs/examples/plugins/init_plugin_protocol.py 0000664 0000000 0000000 00000001171 15005643713 0024476 0 ustar 00root root 0000000 0000000 from typing import Dict from litestar import Litestar, get from litestar.config.app import AppConfig from litestar.di import Provide from litestar.plugins import InitPlugin @get("/", sync_to_thread=False) def route_handler(name: str) -> Dict[str, str]: return {"hello": name} def get_name() -> str: return "world" class MyPlugin(InitPlugin): def on_app_init(self, app_config: AppConfig) -> AppConfig: app_config.dependencies["name"] = Provide(get_name, sync_to_thread=False) app_config.route_handlers.append(route_handler) return app_config app = Litestar(plugins=[MyPlugin()]) # run: / litestar-2.16.0/docs/examples/plugins/problem_details/ 0000775 0000000 0000000 00000000000 15005643713 0023027 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/plugins/problem_details/basic_usage.py 0000664 0000000 0000000 00000001743 15005643713 0025653 0 ustar 00root root 0000000 0000000 from dataclasses import dataclass from litestar import Litestar, post from litestar.plugins.problem_details import ProblemDetailsConfig, ProblemDetailsException, ProblemDetailsPlugin @dataclass class PurchaseItem: item_id: int quantity: int @post("/purchase") async def purchase(data: PurchaseItem) -> None: # Logic to check if the user has enough credit to buy the item. # We assume the user does not have enough credit. raise ProblemDetailsException( type_="https://example.com/probs/out-of-credit", title="You do not have enough credit.", detail="Your current balance is 30, but that costs 50.", instance="/account/12345/msgs/abc", extra={"balance": 30}, ) problem_details_plugin = ProblemDetailsPlugin(ProblemDetailsConfig()) app = Litestar(route_handlers=[purchase], plugins=[problem_details_plugin]) # run: /purchase --header "Content-Type: application/json" --request POST --data '{"item_id": 1234, "quantity": 2}' litestar-2.16.0/docs/examples/plugins/problem_details/convert_exceptions.py 0000664 0000000 0000000 00000003011 15005643713 0027315 0 ustar 00root root 0000000 0000000 from __future__ import annotations from dataclasses import dataclass from litestar import Litestar, post from litestar.plugins.problem_details import ProblemDetailsConfig, ProblemDetailsException, ProblemDetailsPlugin @dataclass class PurchaseItem: item_id: int quantity: int class PurchaseNotAllowedError(Exception): def __init__(self, account_id: int, balance: int, detail: str) -> None: self.account_id = account_id self.balance = balance self.detail = detail @post("/purchase") async def purchase(data: PurchaseItem) -> None: raise PurchaseNotAllowedError( account_id=12345, balance=30, detail="Your current balance is 30, but that costs 50.", ) def convert_purchase_not_allowed_to_problem_details(exc: PurchaseNotAllowedError) -> ProblemDetailsException: return ProblemDetailsException( type_="https://example.com/probs/out-of-credit", title="You do not have enough credit.", detail=exc.detail, instance=f"/account/{exc.account_id}/msgs/abc", extra={"balance": exc.balance}, ) problem_details_plugin = ProblemDetailsPlugin( ProblemDetailsConfig( enable_for_all_http_exceptions=True, exception_to_problem_detail_map={PurchaseNotAllowedError: convert_purchase_not_allowed_to_problem_details}, ) ) app = Litestar(route_handlers=[purchase], plugins=[problem_details_plugin]) # run: /purchase --header "Content-Type: application/json" --request POST --data '{"item_id": 1234, "quantity": 2}' litestar-2.16.0/docs/examples/plugins/problem_details/convert_http_exceptions.py 0000664 0000000 0000000 00000001574 15005643713 0030370 0 ustar 00root root 0000000 0000000 from dataclasses import dataclass from litestar import Litestar, post from litestar.exceptions.http_exceptions import NotFoundException from litestar.plugins.problem_details import ProblemDetailsConfig, ProblemDetailsPlugin @dataclass class PurchaseItem: item_id: int quantity: int @post("/purchase") async def purchase(data: PurchaseItem) -> None: # Logic to check if the user has enough credit to buy the item. # We assume the user does not have enough credit. raise NotFoundException(detail="No item with the given ID was found", extra={"item_id": data.item_id}) problem_details_plugin = ProblemDetailsPlugin(ProblemDetailsConfig(enable_for_all_http_exceptions=True)) app = Litestar(route_handlers=[purchase], plugins=[problem_details_plugin]) # run: /purchase --header "Content-Type: application/json" --request POST --data '{"item_id": 1234, "quantity": 2}' litestar-2.16.0/docs/examples/plugins/prometheus/ 0000775 0000000 0000000 00000000000 15005643713 0022055 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/plugins/prometheus/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0024154 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/plugins/prometheus/using_prometheus_exporter.py 0000664 0000000 0000000 00000001244 15005643713 0027760 0 ustar 00root root 0000000 0000000 from litestar import Litestar from litestar.plugins.prometheus import PrometheusConfig, PrometheusController def create_app(group_path: bool = False): # Default app name and prefix is litestar. prometheus_config = PrometheusConfig(group_path=group_path) # By default the metrics are available in prometheus format and the path is set to '/metrics'. # If you want to change the path and format you can do it by subclassing the PrometheusController class. # Creating the litestar app instance with our custom PrometheusConfig and PrometheusController. return Litestar(route_handlers=[PrometheusController], middleware=[prometheus_config.middleware]) litestar-2.16.0/docs/examples/plugins/prometheus/using_prometheus_exporter_with_extra_configs.py 0000664 0000000 0000000 00000003152 15005643713 0033726 0 ustar 00root root 0000000 0000000 from typing import Any, Dict from litestar import Litestar, Request from litestar.plugins.prometheus import PrometheusConfig, PrometheusController # We can modify the path of our custom handler and override the metrics format by subclassing the PrometheusController. class CustomPrometheusController(PrometheusController): path = "/custom-path" openmetrics_format = True # Let's assume this as our extra custom labels which we want our metrics to have. # The values can be either a string or a callable that returns a string. def custom_label_callable(request: Request[Any, Any, Any]) -> str: return "v2.0" extra_labels = { "version_no": custom_label_callable, "location": "earth", } # Customizing the buckets for the histogram. buckets = [0.1, 0.2, 0.3, 0.4, 0.5] # Adding exemplars to the metrics. # Note that this supported only in openmetrics format. def custom_exemplar(request: Request[Any, Any, Any]) -> Dict[str, str]: return {"trace_id": "1234"} # Creating the instance of PrometheusConfig with our own custom options. # The given options are not necessary, you can use the default ones # as well by just creating a raw instance PrometheusConfig() prometheus_config = PrometheusConfig( app_name="litestar-example", prefix="litestar", labels=extra_labels, buckets=buckets, # pyright: ignore[reportArgumentType] exemplars=custom_exemplar, excluded_http_methods=["POST"], ) # Creating the litestar app instance with our custom PrometheusConfig and PrometheusController. app = Litestar(route_handlers=[CustomPrometheusController], middleware=[prometheus_config.middleware]) litestar-2.16.0/docs/examples/plugins/sqlalchemy/ 0000775 0000000 0000000 00000000000 15005643713 0022024 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/plugins/sqlalchemy/configure.py 0000664 0000000 0000000 00000000344 15005643713 0024360 0 ustar 00root root 0000000 0000000 from litestar.plugins.sqlalchemy import SQLAlchemyAsyncConfig, SQLAlchemyPlugin sqlalchemy_config = SQLAlchemyAsyncConfig(connection_string="sqlite+aiosqlite:///test.sqlite") plugin = SQLAlchemyPlugin(config=sqlalchemy_config) litestar-2.16.0/docs/examples/plugins/sqlalchemy/modelling.py 0000664 0000000 0000000 00000000237 15005643713 0024352 0 ustar 00root root 0000000 0000000 from sqlalchemy.orm import Mapped from litestar.plugins.sqlalchemy import base class TodoItem(base.UUIDBase): title: Mapped[str] done: Mapped[bool] litestar-2.16.0/docs/examples/plugins/sqlalchemy_init_plugin/ 0000775 0000000 0000000 00000000000 15005643713 0024425 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/plugins/sqlalchemy_init_plugin/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0026524 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/plugins/sqlalchemy_init_plugin/sqlalchemy_async.py 0000664 0000000 0000000 00000001610 15005643713 0030334 0 ustar 00root root 0000000 0000000 from __future__ import annotations from typing import TYPE_CHECKING from sqlalchemy import text from litestar import Litestar, get from litestar.plugins.sqlalchemy import SQLAlchemyAsyncConfig, SQLAlchemyInitPlugin if TYPE_CHECKING: from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession @get(path="/sqlalchemy-app") async def async_sqlalchemy_init(db_session: AsyncSession, db_engine: AsyncEngine) -> str: """Interact with SQLAlchemy engine and session.""" one = (await db_session.execute(text("SELECT 1"))).scalar_one() async with db_engine.begin() as conn: two = (await conn.execute(text("SELECT 2"))).scalar_one() return f"{one} {two}" sqlalchemy_config = SQLAlchemyAsyncConfig(connection_string="sqlite+aiosqlite:///test.sqlite") app = Litestar( route_handlers=[async_sqlalchemy_init], plugins=[SQLAlchemyInitPlugin(config=sqlalchemy_config)], ) litestar-2.16.0/docs/examples/plugins/sqlalchemy_init_plugin/sqlalchemy_sync.py 0000664 0000000 0000000 00000001565 15005643713 0030204 0 ustar 00root root 0000000 0000000 from __future__ import annotations from typing import TYPE_CHECKING from sqlalchemy import text from litestar import Litestar, get from litestar.plugins.sqlalchemy import SQLAlchemyInitPlugin, SQLAlchemySyncConfig if TYPE_CHECKING: from sqlalchemy import Engine from sqlalchemy.orm import Session @get(path="/sqlalchemy-app", sync_to_thread=True) def async_sqlalchemy_init(db_session: Session, db_engine: Engine) -> str: """Interact with SQLAlchemy engine and session.""" one = db_session.execute(text("SELECT 1")).scalar_one() with db_engine.connect() as conn: two = conn.execute(text("SELECT 2")).scalar_one() return f"{one} {two}" sqlalchemy_config = SQLAlchemySyncConfig(connection_string="sqlite:///test.sqlite") app = Litestar( route_handlers=[async_sqlalchemy_init], plugins=[SQLAlchemyInitPlugin(config=sqlalchemy_config)], ) litestar-2.16.0/docs/examples/request_data/ 0000775 0000000 0000000 00000000000 15005643713 0020662 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/request_data/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0022761 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/request_data/custom_request.py 0000664 0000000 0000000 00000001664 15005643713 0024325 0 ustar 00root root 0000000 0000000 from litestar import Litestar, Request, get from litestar.connection.base import empty_receive, empty_send from litestar.enums import HttpMethod from litestar.types import Receive, Scope, Send KITTEN_NAMES_MAP = { HttpMethod.GET: "Whiskers", } class CustomRequest(Request): """Enrich request with the kitten name.""" __slots__ = ("kitten_name",) def __init__(self, scope: Scope, receive: Receive = empty_receive, send: Send = empty_send) -> None: """Initialize CustomRequest class.""" super().__init__(scope=scope, receive=receive, send=send) self.kitten_name = KITTEN_NAMES_MAP.get(scope["method"], "Mittens") @get(path="/kitten-name", sync_to_thread=False) def get_kitten_name(request: CustomRequest) -> str: """Get kitten name based on the HTTP method.""" return request.kitten_name app = Litestar( route_handlers=[get_kitten_name], request_class=CustomRequest, debug=True, ) litestar-2.16.0/docs/examples/request_data/msgpack_request.py 0000664 0000000 0000000 00000001015 15005643713 0024426 0 ustar 00root root 0000000 0000000 from typing import Any, Dict from typing_extensions import Annotated from litestar import Litestar, post from litestar.enums import RequestEncodingType from litestar.params import Body @post(path="/", sync_to_thread=False) def msgpack_handler( data: Annotated[Dict[str, Any], Body(media_type=RequestEncodingType.MESSAGEPACK)], ) -> Dict[str, Any]: # This will try to parse the request body as `MessagePack` regardless of the # `Content-Type` return data app = Litestar(route_handlers=[msgpack_handler]) litestar-2.16.0/docs/examples/request_data/request_data_1.py 0000664 0000000 0000000 00000000301 15005643713 0024127 0 ustar 00root root 0000000 0000000 from typing import Dict from litestar import Litestar, post @post(path="/") async def index(data: Dict[str, str]) -> Dict[str, str]: return data app = Litestar(route_handlers=[index]) litestar-2.16.0/docs/examples/request_data/request_data_10.py 0000664 0000000 0000000 00000001211 15005643713 0024210 0 ustar 00root root 0000000 0000000 from typing import Any, Dict, List, Tuple from typing_extensions import Annotated from litestar import Litestar, post from litestar.datastructures import UploadFile from litestar.enums import RequestEncodingType from litestar.params import Body @post(path="/") async def handle_file_upload( data: Annotated[List[UploadFile], Body(media_type=RequestEncodingType.MULTI_PART)], ) -> Dict[str, Tuple[str, str, Any]]: result = {} for file in data: content = await file.read() result[file.filename] = (len(content), file.content_type, file.headers) return result app = Litestar(route_handlers=[handle_file_upload]) litestar-2.16.0/docs/examples/request_data/request_data_2.py 0000664 0000000 0000000 00000000352 15005643713 0024136 0 ustar 00root root 0000000 0000000 from dataclasses import dataclass from litestar import Litestar, post @dataclass class User: id: int name: str @post(path="/") async def index(data: User) -> User: return data app = Litestar(route_handlers=[index]) litestar-2.16.0/docs/examples/request_data/request_data_3.py 0000664 0000000 0000000 00000000617 15005643713 0024143 0 ustar 00root root 0000000 0000000 from dataclasses import dataclass from typing_extensions import Annotated from litestar import Litestar, post from litestar.params import Body @dataclass class User: id: int name: str @post(path="/") async def create_user( data: Annotated[User, Body(title="Create User", description="Create a new user.")], ) -> User: return data app = Litestar(route_handlers=[create_user]) litestar-2.16.0/docs/examples/request_data/request_data_4.py 0000664 0000000 0000000 00000000663 15005643713 0024145 0 ustar 00root root 0000000 0000000 from dataclasses import dataclass from typing_extensions import Annotated from litestar import Litestar, post from litestar.enums import RequestEncodingType from litestar.params import Body @dataclass class User: id: int name: str @post(path="/") async def create_user( data: Annotated[User, Body(media_type=RequestEncodingType.URL_ENCODED)], ) -> User: return data app = Litestar(route_handlers=[create_user]) litestar-2.16.0/docs/examples/request_data/request_data_5.py 0000664 0000000 0000000 00000001312 15005643713 0024136 0 ustar 00root root 0000000 0000000 from dataclasses import dataclass from typing import Dict from typing_extensions import Annotated from litestar import Litestar, post from litestar.datastructures import UploadFile from litestar.enums import RequestEncodingType from litestar.params import Body @dataclass class User: id: int name: str form_input_name: UploadFile @post(path="/") async def create_user( data: Annotated[User, Body(media_type=RequestEncodingType.MULTI_PART)], ) -> Dict[str, str]: content = await data.form_input_name.read() filename = data.form_input_name.filename return {"id": data.id, "name": data.name, "filename": filename, "size": len(content)} app = Litestar(route_handlers=[create_user]) litestar-2.16.0/docs/examples/request_data/request_data_6.py 0000664 0000000 0000000 00000001041 15005643713 0024136 0 ustar 00root root 0000000 0000000 from typing_extensions import Annotated from litestar import Litestar, MediaType, post from litestar.datastructures import UploadFile from litestar.enums import RequestEncodingType from litestar.params import Body @post(path="/", media_type=MediaType.TEXT) async def handle_file_upload( data: Annotated[UploadFile, Body(media_type=RequestEncodingType.MULTI_PART)], ) -> str: content = await data.read() filename = data.filename return f"{filename},length: {len(content)}" app = Litestar(route_handlers=[handle_file_upload]) litestar-2.16.0/docs/examples/request_data/request_data_7.py 0000664 0000000 0000000 00000001060 15005643713 0024140 0 ustar 00root root 0000000 0000000 from typing_extensions import Annotated from litestar import Litestar, MediaType, post from litestar.datastructures import UploadFile from litestar.enums import RequestEncodingType from litestar.params import Body @post(path="/", media_type=MediaType.TEXT, sync_to_thread=False) def handle_file_upload( data: Annotated[UploadFile, Body(media_type=RequestEncodingType.MULTI_PART)], ) -> str: content = data.file.read() filename = data.filename return f"{filename},length: {len(content)}" app = Litestar(route_handlers=[handle_file_upload]) litestar-2.16.0/docs/examples/request_data/request_data_8.py 0000664 0000000 0000000 00000001402 15005643713 0024141 0 ustar 00root root 0000000 0000000 from typing import Dict from pydantic import BaseModel, ConfigDict from typing_extensions import Annotated from litestar import Litestar, post from litestar.datastructures import UploadFile from litestar.enums import RequestEncodingType from litestar.params import Body class FormData(BaseModel): model_config = ConfigDict(arbitrary_types_allowed=True) cv: UploadFile diploma: UploadFile @post(path="/") async def handle_file_upload( data: Annotated[FormData, Body(media_type=RequestEncodingType.MULTI_PART)], ) -> Dict[str, str]: cv_content = await data.cv.read() diploma_content = await data.diploma.read() return {"cv": cv_content.decode(), "diploma": diploma_content.decode()} app = Litestar(route_handlers=[handle_file_upload]) litestar-2.16.0/docs/examples/request_data/request_data_9.py 0000664 0000000 0000000 00000001152 15005643713 0024144 0 ustar 00root root 0000000 0000000 from typing import Dict from typing_extensions import Annotated from litestar import Litestar, post from litestar.datastructures import UploadFile from litestar.enums import RequestEncodingType from litestar.params import Body @post(path="/") async def handle_file_upload( data: Annotated[Dict[str, UploadFile], Body(media_type=RequestEncodingType.MULTI_PART)], ) -> Dict[str, str]: file_contents = {} for name, file in data.items(): content = await file.read() file_contents[file.filename] = len(content) return file_contents app = Litestar(route_handlers=[handle_file_upload]) litestar-2.16.0/docs/examples/responses/ 0000775 0000000 0000000 00000000000 15005643713 0020222 5 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/responses/__init__.py 0000664 0000000 0000000 00000000000 15005643713 0022321 0 ustar 00root root 0000000 0000000 litestar-2.16.0/docs/examples/responses/background_tasks_1.py 0000664 0000000 0000000 00000001071 15005643713 0024337 0 ustar 00root root 0000000 0000000 import logging from typing import Dict from litestar import Litestar, Response, get from litestar.background_tasks import BackgroundTask logger = logging.getLogger(__name__) async def logging_task(identifier: str, message: str) -> None: logger.info("%s: %s", identifier, message) @get("/", sync_to_thread=False) def greeter(name: str) -> Response[Dict[str, str]]: return Response( {"hello": name}, background=BackgroundTask(logging_task, "greeter", message=f"was called with name {name}"), ) app = Litestar(route_handlers=[greeter]) litestar-2.16.0/docs/examples/responses/background_tasks_2.py 0000664 0000000 0000000 00000000754 15005643713 0024347 0 ustar 00root root 0000000 0000000 import logging from typing import Dict from litestar import Litestar, get from litestar.background_tasks import BackgroundTask logger = logging.getLogger(__name__) async def logging_task(identifier: str, message: str) -> None: logger.info("%s: %s", identifier, message) @get("/", background=BackgroundTask(logging_task, "greeter", message="was called"), sync_to_thread=False) def greeter() -> Dict[str, str]: return {"hello": "world"} app = Litestar(route_handlers=[greeter]) litestar-2.16.0/docs/examples/responses/background_tasks_3.py 0000664 0000000 0000000 00000001317 15005643713 0024344 0 ustar 00root root 0000000 0000000 import logging from typing import Dict from litestar import Litestar, Response, get from litestar.background_tasks import BackgroundTask, BackgroundTasks logger = logging.getLogger(__name__) greeted = set() async def logging_task(name: str) -> None: logger.info("%s was greeted", name) async def saving_task(name: str) -> None: greeted.add(name) @get("/", sync_to_thread=False) def greeter(name: str) -> Response[Dict[str, str]]: return Response( {"hello": name}, background=BackgroundTasks( [ BackgroundTask(logging_task, name), BackgroundTask(saving_task, name), ] ), ) app = Litestar(route_handlers=[greeter]) litestar-2.16.0/docs/examples/responses/custom_responses.py 0000664 0000000 0000000 00000000536 15005643713 0024213 0 ustar 00root root 0000000 0000000 from litestar import Litestar, Response, get from litestar.datastructures import MultiDict class MultiDictResponse(Response): type_encoders = {MultiDict: lambda d: d.dict()} @get("/") async def index() -> MultiDict: return MultiDict([("foo", "bar"), ("foo", "baz")]) app = Litestar([index], response_class=MultiDictResponse) # run: / litestar-2.16.0/docs/examples/responses/json_suffix_responses.py 0000664 0000000 0000000 00000000771 15005643713 0025237 0 ustar 00root root 0000000 0000000 from typing import Any, Dict import litestar.status_codes from litestar import Litestar, get @get( "/resources", status_code=litestar.status_codes.HTTP_418_IM_A_TEAPOT, media_type="application/vnd.example.resource+json", ) async def retrieve_resource() -> Dict[str, Any]: return { "title": "Server thinks it is a teapot", "type": "Server delusion", "status": litestar.status_codes.HTTP_418_IM_A_TEAPOT, } app = Litestar(route_handlers=[retrieve_resource]) litestar-2.16.0/docs/examples/responses/response_content.py 0000664 0000000 0000000 00000001477 15005643713 0024175 0 ustar 00root root 0000000 0000000 from litestar import Litestar, MediaType, Request, Response, get @get("/resource", sync_to_thread=False) def retrieve_resource(request: Request) -> Response[bytes]: provided_types = [MediaType.TEXT, MediaType.HTML, "application/xml"] preferred_type = request.accept.best_match(provided_types, default=MediaType.TEXT) content = None if preferred_type == MediaType.TEXT: content = b"Hello World!" elif preferred_type == MediaType.HTML: content = b"