openlawlibrary/pygls

Why Pydantic?

Closed this issue · 11 comments

nmrtv commented

Is there any reason why you use Pydantic internally? Compared to attrs+cattrs it's at least 5 times slower and doesn't provide any benefits.

https://stefan.sofa-rockers.org/2020/05/29/attrs-dataclasses-pydantic/
https://threeofwands.com/why-i-use-attrs-instead-of-pydantic/

I'd also like to know why setup.cfg requires pydantic's version to be earlier then 1.9.

@doronbehar < 1.9 version add by this PR: #148

@doronbehar < 1.9 version add by this PR: #148

That PR is missing an explanation why the version was limited to < 1.9. Current upstream version is 1.9.

There's quote of PR's description:

pydantic seems to make breaking changes at minor releases;
however 1.8 works just fine so I've allowed 1.7.x and 1.8.x

limited to < 1.9 broke our (NixOS packages) cmake-language-server too :/

This affects packages that use pygls, such as Esbonio.

There is no way to have VS Code autocomplete (Pydantic 1.9.0) and the Esbonio language server (for documentation using Sphinx) running at the same time.

Sort of vaguely related, I just added pygls to CrossHair. (really thankful for this package!)

But since CrossHair needs to run in the developer's Python environment, it's most likely to work when pygls has few dependencies and has few restrictions on dependency versions. (else they'll conflict with the developer's project)

Finally, this is an esoteric use case, so I don't think my vote should matter that much!

tombh commented

Latest master now specifies pydantic>=1.9.1,<1.10 and we'll be releasing this on Pypi soon. Could this be a fix? But more generally, what is the best practice for this situation? For example, vendoring all dependencies in the package with something like https://github.com/pradyunsg/vendoring?

what is the best practice for this situation

imo best practice is what I did in #148: set an upper bound at the point where it is reasonable to believe that breaking changes would be likely to happen. That's the way to protect your users from unexpected breakage if and when pydantic (or whatever) does release a breaking change.

However, I acknowledge that

  • this is not universally accepted as best practice, there's a significant body of opinion that thinks that upper bounds cause more harm than good

    • ie some folk would rather risk that breakage, the implicit ask for maintainers being that they will fix such things promptly if and when they happen
    • but the thinking is that actually breaking changes are rare, users can avoid taking those changes, and so holding back the ecosystem is worse
  • specifying upper bounds places an implicit burden on maintainers to keep an eye out for new releases of dependencies and update those upper bounds as appropriate

    • that burden can be shared by contributors: #223 was open before this thread noticed that pydantic was outdated (and near-duplicate #229 followed)
    • but those contributions don't do much good until they are merged and released
tombh commented

Thanks for the reply @dimbleby

So it looks like we're going to be completely removing Pydantic in the upcoming #273 release. So I'm not sure how relevant this issue is now?

But there's 2 separate themes I'm still curious about.

  1. From what you've said I get the impression that neither vendoring nor isolating dependencies (a la Nix) is a standard practice in the Python ecosystem? It may not even be standard practice in any ecosystem apart from Nix? Hence why we just have to live with trying to support overlapping versions between mutual dependencies in disparate projects.
  2. Even in a Nix-like, per-project, isolated-dependency system, dependency version definition semantics such as the chevron, ^0.18.0, are also critical. But I think this is already a solved problem in Python with lock files? Which Pygls doesn't currently use.

No need to answer these unless anything obvious comes up. Just wondering out loud about the general expectations in the Python ecosystem.

Either way, the fact that Pydantic seems to make breaking changes on minor version bumps would be a faux pas in any ecosystem.

pydantic is just an example of the general question: this project has other dependencies and will continue to have to decide whether or not to put upper bounds on those dependencies. There are pros and cons, which I tried to set out fairly above.

vendoring is typically an exceptional-circumstances-only choice in the python world.

tombh commented

Pygls has now migrated to lsprotocol, so no longer depends on Pydantic. lsprotocol itseslf uses https://github.com/python-attrs/cattrs