While working on a project that required OpenAPI docs across multiple frameworks, I got tired of maintaining separate solutions. I liked FastAPI’s clean and intuitive routing, so I built FastOpenAPI, bringing a similar approach to other Python frameworks (Flask, Sanic, Falcon, Starlette, etc).
It's meant for developers who prefer FastAPI-style routing but need or want to use a different framework.
The project is still evolving, and I’d love any feedback or testing from the community!
asabla · 39d ago
for someone that comes primarily from a .net background. This looks fantastic!
Just one thing that I tried to find more information about is: are you suppose to rely on the prefix for specifying api version?
Disclaimer:
I'm on a phone while writing this, so I just might have missed something obvious
other then that, kudos for releasing this package!
mr_Fatalyst · 39d ago
In the examples, I used prefixes to demonstrate API versioning, but you're not limited to this approach. Prefixes can be used for general route structuring as well (like grouping entities, etc.), not just for versioning.
In this example, routes are split into routers by entities, which are then grouped into an api_v1 router, and finally, this api_v1 router is added to the main router.
fjdjshsh · 38d ago
In what context do you need to maintain multiple frameworks?
My use case for fastAPI is very specific (we only maintain APIs for ML models), so I'm curious to learn about this.
odie5533 · 38d ago
Legacy applications built with Flask and modern ones with FastAPI.
pamelafox · 38d ago
Does the flask extra also support quart?
pamelafox · 38d ago
And would it document a streaming API? (With transfer-encoding: chunked)
The support for that in OpenAPI is still in progress, I believe.
mr_Fatalyst · 38d ago
Currently, FastOpenAPI doesn't provide built-in support specifically for documenting streaming APIs.
As far as I'm aware, support for streaming (chunked responses) in the OpenAPI specification itself is still limited.
mr_Fatalyst · 38d ago
Yes, Quart is supported.
The full list of frameworks is: Falcon, Flask, Quart, Sanic, Starlette, and Tornado.
Looks like I accidentally missed Quart in some parts of the docs—my bad, apologies! It’s included in the examples.
raylad · 37d ago
Why no Django?
mr_Fatalyst · 37d ago
How I answered before, I started working on a router for DRF/Django integration, but Django's project structure made it surprisingly tricky to implement cleanly. I keep it in my mind.
wg0 · 38d ago
After years of development - Now I prefer declarative approach. Specs first, generate the code from it and implement required Interfaces.
One great too for that is TypeSpec[0].
This also allows thinking about the API first and ensures that what's documented is what's implemented.
Doesn't most people? Until you're no longer in the happy path of whatever you use to generate code.
wg0 · 37d ago
Nah. Has not happened.
lvncelot · 38d ago
I'm also really happy with spec first. We're using openapi-generator[1] to generate types from a yaml schema (inverting the more standard approach of generating the yaml) in our Typescript (mostly Nest.js) backends, and export those types as packages for use in our frontends.
Being able to retrofit declarations/specifications to existing code, both for maintaining backwards compatibility and reducing rework, is very valuable, though.
ltbarcly3 · 39d ago
Every FastApi project I've worked on (more than a few) had an average of less than 1 concurrent request per process. The amount of engineering effort they put into debugging the absolute mess that is async python when it was easily the worst tool for the job is remarkable. If you don't know why it is hilarious that a FastApi project would have less than one concurrent request per process you shouldn't be making technical decisions.
supriyo-biswas · 38d ago
I'm not sure about your workload but FastAPI should definitely be able to process more than one request per second assuming that the workload isn't placing a compute bound or synchronous task in the event loop and as long as you're using an ASGI server like Gunicorn for serving requests.
The thing about not marking compute bound or synchronous tasks properly was the cause of a gnarly performance issue with an application at a previous employer, and such mistakes are easy to make -- I'll give you that.
acdha · 39d ago
That’s completely off topic, and it says more about the team than the tool.
ltbarcly3 · 38d ago
The topic is generating documentation for FastApi API's right? If someone came and said "here's a great way to prevent over-spray when painting your dog" I think it would be reasonable to take one small step back and just explain that painting your dog is a bad idea.
acdha · 38d ago
The first line of the linked page says otherwise:
> FastOpenAPI is a library for generating and integrating OpenAPI schemas using Pydantic v2 and various frameworks (Falcon, Flask, Sanic, Starlette, Tornado).
And, no, the analogy to painting dogs isn’t valid. I’m sure you’re right to say that the projects you worked on did not end well but that single anecdote doesn’t invalidate all of the other projects which didn’t have that problem, much less the desire other people might want for a similarly-easy experience when using different frameworks.
dtkav · 39d ago
lol what. Did they not use an asgi server? Sounds like it was just misconfigured.
tempest_ · 38d ago
Honestly it is mostly caused by people from the machine learning end of the ecosystem not understanding how cooperative multitasking works and trying to bolt a web framework to their model.
That coupled with the relative immaturity of the python async ecosystem leads to lots of rough edges. Especially when they deploy these things into heavily abstracted cloud ecosystems like Kubernetes.
FastAPI also trys to help by making it "easy" to run sync code but that too is an abstraction that is not majorly documented and has limitations.
ltbarcly3 · 38d ago
Everything you say here is true, but if you do an analysis and run benchmarks on non-toy projects you'll quickly find that async Python is a bad choice in virtually every use case. Even for use cases that are extremely IO bound and use almost no compute async python ends up dramatically increasing the variance in your response times and lowering your overall throughput. If you give me an async python solution, I will bet you whatever you want that I can reimplement it using threads, reduce LOC, make it far more debugabble and readable, make it far easier to reason about what the consequences of a given change are for response times, make it resistant to small, seemingly inconsequential code changes causing dramatic, disastrous consequences when deployed, etc etc etc. Plus you won't have a stupid coloring problem with two copies of every function. No more spending entire days trying to figure out why some callback never runs or why it fires twice. Async python is only for people who don't know what they are doing and therefore can't realize how bad their solution is performing, how much more effort they are spending building and debugging vs how much they should have to put into it, and how poorly it performs vs how it could perform.
memset · 39d ago
This is really cool - something I've been looking for with Flask. Cleanest implementation with just the decorator that I've seen.
(As an aside, is there an open-source UI for docs that actually looks good - professional quality, or even lets you try out endpoints? All of the decent ones are proprietary nowadays.)
mr_Fatalyst · 39d ago
Thanks a lot! Glad to hear it fits your needs.
For a clean, documentation UI, the best open-source options right now are probably Swagger UI and ReDoc. FastOpenAPI uses both by default:
- Swagger UI: interactive, lets you try out endpoints live.
- ReDoc: more minimalist and professional-looking but static.
If you're looking for something different, you might check out RapiDoc, which is also open-source, modern, customizable, and supports interactive API exploration.
ddorian43 · 38d ago
Maybe Rapidoc?
These335 · 38d ago
Love Flask, but this has always been a missing tool. I have a question though - it seems like you're actually modifying the response data type for Flask routes so that it's a Pydantic model. Is that an optional approach? While I wish that were the official standard, if it is not optional then I think that's quite a big ask for maintainers of existing APIs who want to use your docs library. Regardless, I'm looking forward to trying it out! Looks great.
mr_Fatalyst · 38d ago
Glad you like the idea!
Actually, returning a Pydantic model directly isn't mandatory—it's just a recommended and convenient approach to ensure automatic data validation and documentation.
If you prefer, you can keep your existing route handlers as-is, returning dictionaries or other JSON-serializable objects. FastOpenAPI will handle these just fine. But using Pydantic models provides type safety and cleaner docs out of the box.
odie5533 · 38d ago
Awesome project! It looks so seamless for Flask! Just switch routers, and you model deserialization/serialization, and /docs. Really impressive work!
Is there any way to not need the response_model= and instead infer from return type?
mr_Fatalyst · 38d ago
Thanks!
Right now, explicitly specifying response_model is required, but only for documentation purposes. Python's type annotations alone aren't sufficient for reliable inference at runtime. I'm considering adding automatic inference support not only for models but also for basic types (like built-in primitives).
s3rius · 37d ago
That's really neat! I made a project for fastapi-like dependency injection for AioHTTP and it also has OpenAPI spec generation. If I could, I would like to use your library for specs instead of self-written solution.
Thanks! I have a draft for aiohttp integration. I think I'll add it later.
gister123 · 38d ago
Python async has been a big mess. I haven’t looked back since moving to a Go + GRPC + Protobuf stack. I would highly recommend it.
jt_b · 38d ago
Love Go (and async python, for different reasons) but miss me with the gRPC unless you are building hardened internal large enterprise systems. We adopted it at a late stage startup for a microservices architecture, and the pain is immense.
So many issues with type duplication due to weird footguns around the generated types. Lots of places where we needed to essentially duplicate a model due to the generated types not allowing us to modify or copy parts of a generated type's value and so forth.
qwertox · 38d ago
I really enjoy Python's asyncio. I'm a big fan of aiohttp and the entire aio* ecosystem.
Then there's Rust's Tokio for the things that need performance.
linkdd · 38d ago
You should take a look at AnyIO, which unifies asyncio and Trio (it can use both event loops as a backend).
Two big deals of Trio and AnyIO are channels (similar to Go's channels), the ability to return data from starting a task in a nursery/task group:
async def my_consumer(task_status = anyio.TASK_STATUS_IGNORED):
tx, rx = anyio.create_memory_object_stream()
task_status.started(tx)
async for message in rx:
...
async def my_producer(tx):
await tx.send("hello")
await tx.send("world")
await tx.aclose()
async def main():
async with anyio.create_task_group() as tg:
tx = await tg.start(my_consumer)
tg.start_soon(my_producer, tx)
mr_Fatalyst · 35d ago
Big thanks to everyone for the feedback and your reactions! I've started working on version 0.5.0 and will try to include as much as possible of what was highlighted here.
bravura · 39d ago
I'm looking for a solution to filter large openapi specs to the most concise complete subset. I've implemented three different variations, two of which appear not to prune enough, and one of which appears to prune too much.
Any recommendations?
dtkav · 39d ago
Are you trying to prune inaccessible types or something?
I'm not sure what you mean by concise complete subset, but in the past I had good success with custom rules in spectral [0].
The task: I have a massive OpenAPI spec, and I want to drop all operations except for read-only ones. I want to preserve all referenced types, but slim the YAML as much as possible and remove extraneous elements.
I've tried prunes operations while preserving referenced components using redocly.
I've tried openapi-extract CLI to extract only components I reference.
And I've tried openapi-format CLI.
They all give different results, and I can't tell whether I am pruning too much or too little.
And yes I'm using spectral at the end, but it doesn't necessarily show it you're missing something that isn't referenced in the final output.
servercobra · 38d ago
Interesting, are you trying to automatically create and use components? Or only show certain fields?
Everdred2dx · 38d ago
Nice. This was one of the main shortcomings in Falcon that pushed me to switch some projects to FastAPI. That said FastAPI had many other benefits that went far beyond API specs.
dtkav · 39d ago
Nice work! What's your take on spec-first vs. code-first?
I'm a fan of spec-first (i worked on connexion), but I've noticed that code-first seems to be more popular.
RadiozRadioz · 39d ago
Spec-first is my preferred approach these days, but I had to grow into it. It didn't make sense early on until I'd written the same boilerplate 100s of times and realised how much time I was wasting.
The upfront cost is higher than the 10 lines it takes to make a working FastAPI app, but once you're past that it becomes a huge timesaver. It's an investment that pays dividends, so definitely for the patient programmer with a long-term view. Not to mention the automatic improvement in API consistently.
I worry slightly about AI completion generating all the code-first boilerplate before people give spec-first a try. It's the same speedup, but with none of the determinism or standardisation.
dtkav · 39d ago
For me it was two things:
- collaborative live API design/review with rapid iteration.
- developing automation on openapi specs to help teams avoid making backwards compatibile changes.
It is much easier to catch things in design.
spec-first is probably most useful for large public APIs.
DanHulton · 38d ago
Just to drop another two cents in here - I feel like code-first is great when it's a solo project or very experimental, but when you're working on a larger team, or more to the point, working with other teams, spec-first is invaluable.
You can publish a working spec long before worrying about any sort of technical implementation, which means you can get feedback from the other teams involved, which can save an immense amount of time. Additionally, the other team can start working from your clear spec sooner, so you unblock them, AND there are all kinds of great mocking tools to fake your api until it's actually done. Oh, and there are libraries that can check your requests/responses in your tests, to ensure you're keeping to the agreed-on spec, so it makes tests more valuable and easier to write, too!
Honestly, even with all that, I wasn't sold on spec first at first because authoring OpenAPI specs SUCKS. It's such a verbose and hard to read and write format. But then I found TypeSpec, and I haven't looked back. I'm converted our existing specs to TypeSpec and they're half the size or less (usually way less). This is easier to write, but critically, easier to read, which makes PRs against a spec a lot more understandable and meaningful.
If you've ever been on the fence about spec-driven development, give TypeSpec a try. It was a real game changer for me.
Cool, I introduced something like typespec at the last company i worked for and it was great. We called it the domain graph and we able to generate entire platform APIs and clients.
I still want to build something that can handle protocol evolution and also do protocol up/down migration on the response (like the stripe API team has done).
jillesvangurp · 38d ago
I do the opposite and leave generating openapi docs to an LLM. Mostly that just involves spelling out the obvious; so it's not a particularly hard job for an LLM.
The code is the full specification of what a thing does. Anything else is just a watered down version of the thing.
In architecture terms, there is no blue print for the blue print, typically. This is a fundamental misconception some people have about software design vs. traditional engineering/architecture.
When designing buildings, you put all your effort in the blue print. And then you build it. With software, you put all your effort in the blue print (i.e. the source code). And then you run/compile it. In neither case is it valuable to have a meta blue print. At best you might do some sketching, prototyping, modeling. But these are activities intended to learn, not to document. 3D printing makes the metaphor more obvious maybe. Because it makes engineering more similar to software development. All the key work is digital.
dtkav · 38d ago
I think you might have a fundamental misunderstanding about what OpenAPI specs are for.
If you just need docs then maybe that works for you. OpenAPI can do so much more though - it can specify a protocol.
If you can't see why a protocol specification is different from an implementation of that protocol then I don't know what to tell you.
jillesvangurp · 37d ago
Most uses of OpenAPI I've seen is simple REST API documentation.
Many internet standards & protocols are typically developed together with their reference implementation. E.g. the IETF is pretty good at that for things like HTTP. Waterfall just doesn't work for anything moderately complicated.
If it's simple, a lot of upfront documentation is not going to be that helpful. If it's not, a proof of concept implementation that irons out all the design mistakes and that proves it is any good would be a good idea. There aren't a lot of good protocols that get developed without those.
Anyway, the article is about slapping openapi specs on python web frameworks, which suggests it's being used in its usual role of documenting existing APIs here. And for REST protocols, python is a great tool to prototype those.
mr_Fatalyst · 39d ago
Thanks! I personally prefer code-first because it aligns well with Python’s dynamic nature and feels more natural in daily coding. Spec-first definitely has advantages (especially clarity and collaboration), but it can sometimes introduce friction, especially when rapidly iterating on APIs.
I think the popularity of code-first tools (like FastAPI) mostly comes from the convenience of quickly defining and changing APIs right alongside your code.
dtkav · 39d ago
Yeah, that's fair. Do you maintain any Public APIs or mostly private ones?
There are a bunch of trade-offs based on your starting point and where you want to get to.
I have found Spec-First is useful for a retrofit and having large org API design standards, but then code first can be helpful again if you are writing a framework to have consistent endpoints by default (like pocketbase's API).
If you're maintaining a private API then it makes sense to optimise for individual developer velocity and code-first seems like a good fit.
mr_Fatalyst · 38d ago
You're right, I'm mostly maintaining different private APIs. In that context, optimizing for individual developer velocity definitely makes code-first more appealing. But you're spot-on about larger orgs and standards—spec-first can simplify collaboration and consistency in those scenarios.
Onavo · 39d ago
No love for Django? I am looking for an alternative to DRF and Django-ninja that can optionally generate typed APIs and docs directly from the model definitions.
ensignavenger · 39d ago
Django Ninja provides this already for Django, and it is great.
odie5533 · 38d ago
Docs are a bit lacking still
jensenbox · 39d ago
Why are you looking for an alternative to Django Ninja? What about it is deficient for you? Curious because I am about to use it.
mariocesar · 39d ago
Not a technical reason: I've been using Django Ninja to medium/big app with lot of validation logic, and it was a delight. It was easy to start and integrates well with Django, but I'm moving away from it, not because I dislike it, I still like the approach and ergonomics. However, the project seems somewhat abandoned or at least struggling with updates (last release is in August 2024) and with lots of PRs staled. There are forks like django-shinobi https://github.com/pmdevita/django-shinobi that are moving forward and have releases
Right now I'm shifting to FastAPI + Django since much of my logic is already in Pydantic classes, and authentication is token based, so FastAPI mainly is a wrapper for my Django app. Still, it doesn't feel ideal. I would prefer to use django-shinobi, but when I first try to migrate to FastAPI I did it most of the hard stuff in a day
If you're considering options, I recommend giving django-shinobi a try. I hope it gains more traction and involves more maintainers.
vital1k · 38d ago
Hi mariocesar
Django ninja creator here
The project is used in a lot of critical infrastructure so we are prasing more about stability and performance rather then newest featers
On the other hand we prise all fork and keep an eye on them on the features that seems interesting
BTW next relrase is planned by the end of this month
Cheers
mariocesar · 38d ago
Im really happy to hear from you and from Django Ninja!
First off, I just want to say how grateful I am for your work. I know how challenging it can be to maintain opensource projects, and I truly appreciate the effort
Wishing you all the best.
This is a bit unrelated, but something thats been on my mind, how are things for you with everything going on in Ukraine? I cant imagine how difficult it must be to deal with such situation while also staying active in open source
mr_Fatalyst · 39d ago
I actually started working on a router for DRF/Django integration, but Django's project structure made it surprisingly tricky to implement cleanly. It's still on my list though.
Onavo · 39d ago
I would suggest having an option for pure Django integration, without DRF.
scrollaway · 39d ago
I believe django-ninja is as good as it gets for this, to be honest. But I wouldn't try to support DRF. Django Ninja implements its own routing and it's a lot better that way.
Onavo · 39d ago
Django Ninja isn't particularly well maintained, there have been a few attempts at forking already. Also I think the author of Django Ninja is more concerned about surviving the war right now.
sastraxi · 39d ago
DRF-spectacular is an okay choice here, you have to manage consistency with return types yourself but the docs and customization options are well done.
stackskipton · 39d ago
There is already plenty available that will do what you want. FastAPI or Litestar are two popular ones.
BerislavLopac · 37d ago
I'm honestly disappointed how OpenAPI keeps being used over and over as documentation, and extremely rarely as what it excels at, which is specification.
We build all kinds of frameworks with routing and request/response validation, and then extract that into OpenAPI format, ofteng having to jump through hoops to adapt our internal data types and structures into those supported by JSON Schema. Instead, we could be doing the opposite: writing the OpenAPI spec first, and use tooling to make routing and validation based on it in an automated way. That has been done before [0] [1], but we're still just scratching the surface of what is possible.
Yes, I am aware that it's not easy to manually write the specs using JSON or even YAML, but we need a better focus on tooling around it; currently only Stoplight [2] gives a solid level of support in that area.
Why not just use fastAPI and have it built into the framework?
mr_Fatalyst · 39d ago
Sometimes you simply can't switch frameworks—due to legacy code, project constraints, or team preferences. FastOpenAPI is specifically designed for situations like these: it provides FastAPI-style routing and automated OpenAPI docs without forcing you to change the underlying framework.
P.S. I'd prefer FastAPI as well ;)
karolinepauls · 38d ago
Because not everyone wants to be a part of the asyncio trend.
Asyncio in Python is a poor feature that splits the language's ecosystem into 2 mutually-incompatible worlds, something Python only gets away with because it's too big to fail.
Meanwhile we've had Gevent for decades now. It gives us async that you can forget you have. Because rather than making code async, it makes the VM async.
Gevent could have been merged into CPython, but they chose explicit "structured concurrency" and the rest is history. History of sometimes moving forward and sometimes straying from the path and getting lost.
And lost Python's asyncio is. PDB, which lots of other debuggers base on, is still broken (cannot use await). The ecosystem? IPython uses asyncio internally so it cannot easily be embedded in a working async program. The only embeddable REPL I was able to find is this: https://github.com/prompt-toolkit/ptpython/blob/master/examp...... actually, it looks like someone is working on adding `await` support to PDB now, years after asyncio's first release.
Overall, lots of churn to get something (maybe) as good as Gevent, which we had in Python 2.7, or even before.
If a similar amount of effort was spent on first-class support for code hot-reloading and live program inspection, we would get a massive boost of productivity. But somehow even otherwise bright people choose to reimplement working solutions into something objectively worse, meanwhile our development/debugging loop still emulates loading punchcards into mainframes.
ddorian43 · 38d ago
Agree on every word. They'll probably make free threaded shitty too somehow. We'll see.
dtkav · 39d ago
It sounded to me like they need to retrofit several projects written in different python servers.
JodieBenitez · 39d ago
No Bottle ?
adhamsalama · 39d ago
Cool!
wseqyrku · 39d ago
I like this. I think genai could be used to fill in gaps in, for example, Wikipedia with a note that it's AI generated. If anything I think that's a good starting point.
While working on a project that required OpenAPI docs across multiple frameworks, I got tired of maintaining separate solutions. I liked FastAPI’s clean and intuitive routing, so I built FastOpenAPI, bringing a similar approach to other Python frameworks (Flask, Sanic, Falcon, Starlette, etc).
It's meant for developers who prefer FastAPI-style routing but need or want to use a different framework.
The project is still evolving, and I’d love any feedback or testing from the community!
Just one thing that I tried to find more information about is: are you suppose to rely on the prefix for specifying api version?
Disclaimer: I'm on a phone while writing this, so I just might have missed something obvious
other then that, kudos for releasing this package!
Personally, I prefer using router composition for flexible route organization. You can see a clear example of this with Flask here: https://github.com/mr-fatalyst/fastopenapi/tree/master/examp...
In this example, routes are split into routers by entities, which are then grouped into an api_v1 router, and finally, this api_v1 router is added to the main router.
My use case for fastAPI is very specific (we only maintain APIs for ML models), so I'm curious to learn about this.
The full list of frameworks is: Falcon, Flask, Quart, Sanic, Starlette, and Tornado.
Looks like I accidentally missed Quart in some parts of the docs—my bad, apologies! It’s included in the examples.
One great too for that is TypeSpec[0].
This also allows thinking about the API first and ensures that what's documented is what's implemented.
[0] https://typespec.io
Doesn't most people? Until you're no longer in the happy path of whatever you use to generate code.
[1] https://github.com/OpenAPITools/openapi-generator
The thing about not marking compute bound or synchronous tasks properly was the cause of a gnarly performance issue with an application at a previous employer, and such mistakes are easy to make -- I'll give you that.
> FastOpenAPI is a library for generating and integrating OpenAPI schemas using Pydantic v2 and various frameworks (Falcon, Flask, Sanic, Starlette, Tornado).
And, no, the analogy to painting dogs isn’t valid. I’m sure you’re right to say that the projects you worked on did not end well but that single anecdote doesn’t invalidate all of the other projects which didn’t have that problem, much less the desire other people might want for a similarly-easy experience when using different frameworks.
That coupled with the relative immaturity of the python async ecosystem leads to lots of rough edges. Especially when they deploy these things into heavily abstracted cloud ecosystems like Kubernetes.
FastAPI also trys to help by making it "easy" to run sync code but that too is an abstraction that is not majorly documented and has limitations.
(As an aside, is there an open-source UI for docs that actually looks good - professional quality, or even lets you try out endpoints? All of the decent ones are proprietary nowadays.)
For a clean, documentation UI, the best open-source options right now are probably Swagger UI and ReDoc. FastOpenAPI uses both by default:
- Swagger UI: interactive, lets you try out endpoints live. - ReDoc: more minimalist and professional-looking but static.
If you're looking for something different, you might check out RapiDoc, which is also open-source, modern, customizable, and supports interactive API exploration.
Actually, returning a Pydantic model directly isn't mandatory—it's just a recommended and convenient approach to ensure automatic data validation and documentation.
If you prefer, you can keep your existing route handlers as-is, returning dictionaries or other JSON-serializable objects. FastOpenAPI will handle these just fine. But using Pydantic models provides type safety and cleaner docs out of the box.
Is there any way to not need the response_model= and instead infer from return type?
Right now, explicitly specifying response_model is required, but only for documentation purposes. Python's type annotations alone aren't sufficient for reliable inference at runtime. I'm considering adding automatic inference support not only for models but also for basic types (like built-in primitives).
Here's my project repo: https://github.com/taskiq-python/aiohttp-deps
https://github.com/mr-fatalyst/fastopenapi/tree/0.5.0-dev
Example: https://github.com/mr-fatalyst/fastopenapi/tree/0.5.0-dev/ex...
So many issues with type duplication due to weird footguns around the generated types. Lots of places where we needed to essentially duplicate a model due to the generated types not allowing us to modify or copy parts of a generated type's value and so forth.
Then there's Rust's Tokio for the things that need performance.
Two big deals of Trio and AnyIO are channels (similar to Go's channels), the ability to return data from starting a task in a nursery/task group:
Any recommendations?
I'm not sure what you mean by concise complete subset, but in the past I had good success with custom rules in spectral [0].
[0] https://github.com/stoplightio/spectral
I've tried prunes operations while preserving referenced components using redocly.
I've tried openapi-extract CLI to extract only components I reference.
And I've tried openapi-format CLI.
They all give different results, and I can't tell whether I am pruning too much or too little.
And yes I'm using spectral at the end, but it doesn't necessarily show it you're missing something that isn't referenced in the final output.
I'm a fan of spec-first (i worked on connexion), but I've noticed that code-first seems to be more popular.
The upfront cost is higher than the 10 lines it takes to make a working FastAPI app, but once you're past that it becomes a huge timesaver. It's an investment that pays dividends, so definitely for the patient programmer with a long-term view. Not to mention the automatic improvement in API consistently.
I worry slightly about AI completion generating all the code-first boilerplate before people give spec-first a try. It's the same speedup, but with none of the determinism or standardisation.
- collaborative live API design/review with rapid iteration.
- developing automation on openapi specs to help teams avoid making backwards compatibile changes.
It is much easier to catch things in design.
spec-first is probably most useful for large public APIs.
You can publish a working spec long before worrying about any sort of technical implementation, which means you can get feedback from the other teams involved, which can save an immense amount of time. Additionally, the other team can start working from your clear spec sooner, so you unblock them, AND there are all kinds of great mocking tools to fake your api until it's actually done. Oh, and there are libraries that can check your requests/responses in your tests, to ensure you're keeping to the agreed-on spec, so it makes tests more valuable and easier to write, too!
Honestly, even with all that, I wasn't sold on spec first at first because authoring OpenAPI specs SUCKS. It's such a verbose and hard to read and write format. But then I found TypeSpec, and I haven't looked back. I'm converted our existing specs to TypeSpec and they're half the size or less (usually way less). This is easier to write, but critically, easier to read, which makes PRs against a spec a lot more understandable and meaningful.
If you've ever been on the fence about spec-driven development, give TypeSpec a try. It was a real game changer for me.
https://typespec.io/
I still want to build something that can handle protocol evolution and also do protocol up/down migration on the response (like the stripe API team has done).
The code is the full specification of what a thing does. Anything else is just a watered down version of the thing.
In architecture terms, there is no blue print for the blue print, typically. This is a fundamental misconception some people have about software design vs. traditional engineering/architecture.
When designing buildings, you put all your effort in the blue print. And then you build it. With software, you put all your effort in the blue print (i.e. the source code). And then you run/compile it. In neither case is it valuable to have a meta blue print. At best you might do some sketching, prototyping, modeling. But these are activities intended to learn, not to document. 3D printing makes the metaphor more obvious maybe. Because it makes engineering more similar to software development. All the key work is digital.
If you just need docs then maybe that works for you. OpenAPI can do so much more though - it can specify a protocol.
If you can't see why a protocol specification is different from an implementation of that protocol then I don't know what to tell you.
Many internet standards & protocols are typically developed together with their reference implementation. E.g. the IETF is pretty good at that for things like HTTP. Waterfall just doesn't work for anything moderately complicated.
If it's simple, a lot of upfront documentation is not going to be that helpful. If it's not, a proof of concept implementation that irons out all the design mistakes and that proves it is any good would be a good idea. There aren't a lot of good protocols that get developed without those.
Anyway, the article is about slapping openapi specs on python web frameworks, which suggests it's being used in its usual role of documenting existing APIs here. And for REST protocols, python is a great tool to prototype those.
I think the popularity of code-first tools (like FastAPI) mostly comes from the convenience of quickly defining and changing APIs right alongside your code.
There are a bunch of trade-offs based on your starting point and where you want to get to.
I have found Spec-First is useful for a retrofit and having large org API design standards, but then code first can be helpful again if you are writing a framework to have consistent endpoints by default (like pocketbase's API).
If you're maintaining a private API then it makes sense to optimise for individual developer velocity and code-first seems like a good fit.
Right now I'm shifting to FastAPI + Django since much of my logic is already in Pydantic classes, and authentication is token based, so FastAPI mainly is a wrapper for my Django app. Still, it doesn't feel ideal. I would prefer to use django-shinobi, but when I first try to migrate to FastAPI I did it most of the hard stuff in a day
If you're considering options, I recommend giving django-shinobi a try. I hope it gains more traction and involves more maintainers.
Django ninja creator here
The project is used in a lot of critical infrastructure so we are prasing more about stability and performance rather then newest featers
On the other hand we prise all fork and keep an eye on them on the features that seems interesting
BTW next relrase is planned by the end of this month
Cheers
First off, I just want to say how grateful I am for your work. I know how challenging it can be to maintain opensource projects, and I truly appreciate the effort
Wishing you all the best.
This is a bit unrelated, but something thats been on my mind, how are things for you with everything going on in Ukraine? I cant imagine how difficult it must be to deal with such situation while also staying active in open source
We build all kinds of frameworks with routing and request/response validation, and then extract that into OpenAPI format, ofteng having to jump through hoops to adapt our internal data types and structures into those supported by JSON Schema. Instead, we could be doing the opposite: writing the OpenAPI spec first, and use tooling to make routing and validation based on it in an automated way. That has been done before [0] [1], but we're still just scratching the surface of what is possible.
Yes, I am aware that it's not easy to manually write the specs using JSON or even YAML, but we need a better focus on tooling around it; currently only Stoplight [2] gives a solid level of support in that area.
[0] https://connexion.readthedocs.io
[1] https://pyapi-server.readthedocs.io/
[2] https://stoplight.io/
P.S. I'd prefer FastAPI as well ;)
Asyncio in Python is a poor feature that splits the language's ecosystem into 2 mutually-incompatible worlds, something Python only gets away with because it's too big to fail.
Meanwhile we've had Gevent for decades now. It gives us async that you can forget you have. Because rather than making code async, it makes the VM async.
Gevent could have been merged into CPython, but they chose explicit "structured concurrency" and the rest is history. History of sometimes moving forward and sometimes straying from the path and getting lost.
And lost Python's asyncio is. PDB, which lots of other debuggers base on, is still broken (cannot use await). The ecosystem? IPython uses asyncio internally so it cannot easily be embedded in a working async program. The only embeddable REPL I was able to find is this: https://github.com/prompt-toolkit/ptpython/blob/master/examp...... actually, it looks like someone is working on adding `await` support to PDB now, years after asyncio's first release.
Overall, lots of churn to get something (maybe) as good as Gevent, which we had in Python 2.7, or even before.
If a similar amount of effort was spent on first-class support for code hot-reloading and live program inspection, we would get a massive boost of productivity. But somehow even otherwise bright people choose to reimplement working solutions into something objectively worse, meanwhile our development/debugging loop still emulates loading punchcards into mainframes.