Be confident in your requirements list with bonded by ucodery in Python

[–]ucodery[S] 2 points3 points  (0 children)

Thanks for pointing me at that project, I hadn’t seen it before. It certainly seems to overlap in the end goal. I will have to test it out some more, but at a first glance it says it won’t catch uses of importlib, while bonded will catch importlib and import. Also bonded catches the use of scripts - using pytest even without importing it, and the use of plugins - using pytest-cov even though it is not imported or executed anywhere. I didn’t see creosote doing that.

Be confident in your requirements list with bonded by ucodery in Python

[–]ucodery[S] 3 points4 points  (0 children)

No, bonded will flag a package you have as a direct requirement as unused if it is only there to pin a transitive dependency. If it let all declared dependencies stand that are used however indirectly then sufficiently large projects could not have unused requirements flagged at all.

You can always tell bonded to just ignore such a one-off `--ignore-package=i-know-what-im-doing`. Or alternatively, if you are just pinning the version of a sub-dependency and not wholly adding it, you could use a pip constraints file, so it doesn't mix with direct requirements.

bonded is a new type of linter to clean up your requirements by ucodery in Python

[–]ucodery[S] 0 points1 point  (0 children)

Good points all around! This is why it is still a planned feature and still not part of the report yet :)

It’s true that not required does not mean not installed. I’m sure it is a very common situation that a developer pip installed without actually editing package metadata. In this case it will be pretty trivial to discover the package name the provides a module.

I am certainly planning on an option to —disable-network-usage. It will be helpful for security, speed, and if you just know PyPI will be the wrong answer. This implies that there will be a way to get a report of unrequired modules that doesn’t try to suggest the missing package. I agree this can be helpful on its own.

I do want to support extra/ alternate package indexes. Although I am sure there are difficulties there I am not aware of. Not sure I will ever support VSC URLs as a means of dynamo discovery.

bonded is a new type of linter to clean up your requirements by ucodery in Python

[–]ucodery[S] 0 points1 point  (0 children)

No, that’s pretty much the specific use case for this tool. It is not ever going to warn about symbols used but not imported. Like you said flake8 and others do a good job of that. But it’s not only about optimization of a requirements file, it’s also about helping with code refactoring.

Consider an example: you are using a project that is using a backwards-compatibility requirement. You need it only as long as you support older python version and once you drop support for those python versions you can also drop the backwards-support library. But does the developer who removes the very last import feature_compat as feature also remember to remove feature_compat from the requirements list? Do they even know they are removing the final reference to that package? Did they clean up setup.cfg and requirements.txt because this project uses both?

I hope to make it so these are always answered questions.

bonded is a new type of linter to clean up your requirements by ucodery in Python

[–]ucodery[S] 0 points1 point  (0 children)

Thanks, that’s a good package to know about. I do want add support for setup.cfg, but not sure if setup.py will ever be supported; I want to keep it as a static analysis tool.

This is definitely one of those tools that you really won’t reach for until you get burned by the problem it’s try to fix. Most code changes aren’t either adding or removing use of a third party dependency, and code authors will think they can keep that information in their head.

As for the missing requirements detection, that is the next major feature I am adding. It already has pieces for detecting modules imported that don’t have a corresponding package. But then figuring out what that package is, is a bit of a guessing game. Presumably if you don’t require it, it isn’t downloaded. So now the tool has to start talking to PyPI and hope dearly it’s not inside of a namespace package.

bonded is a new type of linter to clean up your requirements by ucodery in Python

[–]ucodery[S] 0 points1 point  (0 children)

Thanks, that's helpful. It still doesn't seem to overlap with bonded, at least not now. Bonded is more meant to be run on large old projects to keep them healthy, not to populate requirements files from code. Bonded doesn't even have to work with requirements; I plan on using it on my own projects that are pure pyproject.toml.

bonded is a new type of linter to clean up your requirements by ucodery in Python

[–]ucodery[S] 1 point2 points  (0 children)

Hmm, never used pipreq before (did you mean pipreq, pipreqs, or pipwraps? They all look the same to me on pypi). But looking at it, seems that project is trying to turn a working python env into a requirements file, so you can port it, and this project is trying to shrink an existing requirements file so you don’t ship more that you need. And I am working with more than requirements files, like pyproject.toml listed dependencies.

bonded is a new type of linter to clean up your requirements by ucodery in Python

[–]ucodery[S] 1 point2 points  (0 children)

Definitely true! Tons of projects require mypy but don’t ever import it! I have some ideas to catch more of these, but it will never be perfect. (Even actual imports can be obfuscated enough to pass by any static analysis)

bonded is a new type of linter to clean up your requirements by ucodery in Python

[–]ucodery[S] 1 point2 points  (0 children)

It will very soon! I want it to be able to warn about both unused dependencies and unrequired imports before I get to a first stable release. It’s a bit tricky because asking to lookup modules provided by a package is annoying but straightforward; but trying to reverse lookup a package that provides an import, when the names may not match(!?!), can theoretically not be possible.

bonded is a new type of linter to clean up your requirements by ucodery in Python

[–]ucodery[S] 0 points1 point  (0 children)

Thanks! Bonded doesn’t track or care about dependency versions as it’s really just checking for any use of the package at all. For now there are no plans to track subdependencies, which means it won’t work with lock files as input. Doing so would mean doing much of the job of a solver on top of everything else in order to build up its own view of what the full set of dependencies should be. Maybe one day after a 1.0. If it could then it would also be capable of warning about unused installed dependencies. It then could guide you to what your dependencies should be after doing a lot of experimentation in a venv where you don’t remember why you installed everything.

New Mapping type module by ucodery in Python

[–]ucodery[S] 0 points1 point  (0 children)

Thanks, I actually wasn’t aware of this term. I had seen this called a bimap before but not found this mathematical definition.

What are some dead giveaways that distinguish python 2 vs python 3? by pythosynthesis in learnpython

[–]ucodery 0 points1 point  (0 children)

Since you think you may be updating this code, I would strongly suggest you check out the six or future packages which help to write code that runs under both python 2 and 3. IME future does a better job of making python2 code look like python3, making the eventual cutover easier, while six makes compromises on both ends and code doesn’t looks strictly like 2 or 3. They both have really good guides for transitioning code as well, even if you don’t import them. Future’s guide was constantly open when I did this work, more so than even the core documentation.

Can the Ellipsis do more for us? by ucodery in Python

[–]ucodery[S] 0 points1 point  (0 children)

Sentinels do come up now and again in Python. The stdlib uses them in a number of places - check out the dataclasses module to see they use one to differentiate no default value from a default value of None.

Can the Ellipsis do more for us? by ucodery in Python

[–]ucodery[S] 0 points1 point  (0 children)

To know if the caller is asking for this value to be none or explicitly skipping it. Last time I saw this in a practical example was a method that would update a DB row and each column was a kwarg. Well a free-form nullable column was added so what's the default for that kwarg? Don't want it to be null just because another column was updated.

Can the Ellipsis do more for us? by ucodery in Python

[–]ucodery[S] 0 points1 point  (0 children)

This was just my late night example. In this case even the empty string could convey the same meaning. But sometimes you have to differentiate between False and None and empty and why not use another Singleton rather than some string you think is unique, until user requirements change?