[HN Gopher] Show HN: A New Python Linter
___________________________________________________________________
Show HN: A New Python Linter
Author : latrova
Score : 62 points
Date : 2021-07-08 11:51 UTC (11 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| underyx wrote:
| Shameless plug of Semgrep, a project I'm working on:
|
| I just wrote this Semgrep rule in 45 seconds which replicates the
| TC201 rule from tryceratops: https://semgrep.dev/s/underyx:tc201
|
| Writing this rule was definitely easier than writing a new linter
| package, but also easier than writing a custom pylint or flake8
| plugin.
|
| Message to OP: we are working on making Semgrep's rule registry
| (https://semgrep.dev/explore) a much more community-centric
| place. Our vision is that just like you could publish the GitHub
| repo of guilatrova/tryceratops, you could publish a set of
| Semgrep rules under your name and brand. Semgrep users could then
| find and use your lightweight "linter" via the registry. If
| you're interested in being one of the first authors to publish on
| the Semgrep Registry, please reach out at bence@returntocorp.com!
| mdaniel wrote:
| I would value knowing how to flag the _lack_ of usage of the
| variable within the catch body; I had this problem while trying
| to write a semgrep rule for Java, but if I were working with
| python, it'd make me just as mad
|
| I'll show the Java version first, because it's more obvious,
| then the equivalent in Python to stay moderately on-topic
| try { ((String)null).length(); } catch
| (Exception e) { System.err.println("I swallow errors
| for fun!"); } try:
| dict()["kaboom"] except KeyError as ke:
| logger.error("it did not work")
|
| In the python version, I would accept the presence of
| `logger.exception` but my question in both code snippets is how
| to detect that nothing touches the exception variable within
| the catch block
| underyx wrote:
| If I understand the comment right, the solution is to first
| use pattern-inside to mark that you're interested in all try-
| except blocks, and then pattern-not-inside to remove the ones
| that correctly reraise the exception. Could you check this
| out? https://semgrep.dev/s/underyx:always-reraise
|
| If this helped, I recommend joining https://r2c.dev/slack --
| we've got a #rules channel dedicated to solving problems like
| this :)
| stavros wrote:
| As I understood it, the GP is looking to flag the non-usage
| of the "ke" variable in the exception body.
| whitten wrote:
| Why did the approach mentioned not work? 1) recognize all
| exception bodies. 2) recognize all exception bodies that
| use the ke variable and mark them as okay.
|
| Anything left should be an exception body that didn't use
| the ke variable, right ?
| stavros wrote:
| It sounds correct (as long as it can distinguish between
| use and shadowing), but the GP talked about reraising so
| I wasn't sure if they meant the same thing.
| stavros wrote:
| Semgrep looks great, is it free/OSS? I don't know how powerful
| it is from looking at the front page, but if it can replace
| many of our tools, I'd love to use it as a pre-commit hook with
| pre-commit.com.
| underyx wrote:
| Totally, it's LGPL licensed!
| https://github.com/returntocorp/semgrep
|
| Here's how to use it with pre-commit:
| https://semgrep.dev/docs/extensions/#pre-commit
| stavros wrote:
| Well that's awesome, I'm very excited about this now! Thank
| you for working on it!
| underyx wrote:
| Yay! I'm based out of Athens right now so (just a shot in
| the dark but) if you happen to be here also, drop by The
| Cube and I'll help you get set up with it :D
| stavros wrote:
| Ah, unfortunately I'm in Thessaloniki, but tell Stavros
| he'll never have my Twitter handle!
|
| And obviously if you're ever around these parts, I'd love
| to have a drink!
| underyx wrote:
| Haha, I'll tell that to all the Stavroses I meet from now
| on.
|
| Cheers!
| kseistrup wrote:
| It's somewhat confusing that there is already a `triceratops`
| python module: https://pypi.org/project/triceratops/
| foxbee wrote:
| Great timing. I was just looking into pylint
| yewenjie wrote:
| How does it compare with the existing linters?
| latrova wrote:
| AFAICT There's no linter that helps you with try/except blocks
| leading people to be inconsistent across the project
| 0x008 wrote:
| Well most linters tell you not to use a bare except :)
| stinos wrote:
| The animation shows replacing 'raise ex' with 'raise' but just
| leaves the now unused ex in 'catch Exception as ex', and in one
| of the comments here there's a similar unused name ke in
| 'Keyerror as ke'. That hurts my C++ eyes a bit, but not having
| studied a lot of other Python code I wonder: is this a common
| thing to do, or are these just 2 'bad' examples?
| latrova wrote:
| It's 2 bad examples, this linter is focused on try/except
| blocks. For more general linting I would suggest flake8 :)
|
| I'm planning on writing a plugin for it.
| tomas789 wrote:
| What is an advantage of this over just writing new rules to
| something like Pylint?
| red_hare wrote:
| Very cool! I'd open a PR to implement it in our Python repo today
| if it were a flake8 plugin.
|
| As a separate linter, I have to update the half-a-dozen places my
| current linters (flake8 and mypy) get applied (Makefile,
| .vscode/settings.json, shared vimrc, cloudbuild.yaml, etc.)
|
| If it were a flake8 plugin, I can just pip install and select the
| TC codes in my .flake8 configuration.
| Chiron1991 wrote:
| I second this.
| latrova wrote:
| I'm so glad to hear that. It should be very simple to implement
| a plugin. Once I'm able to, I'll create it and let you know! :)
| bpicolo wrote:
| I'd recommend a trigger comment word other than `notc`. It's hard
| to remember - not obvious why it would be `notc` in the first
| place.
|
| But also it would be pronounced like "nazi"? Not exactly the
| association you might be looking for.
| _ZeD_ wrote:
| I'm not a native english speaker... but how in the world "notc"
| sounds like "nazi"?
|
| I'll try to pronounce it like "no-ti-see", or "notick" or
| something like that
| jldugger wrote:
| In my eyes, the options are "no tc" and "not c". "Not c" is
| pronounced exactly the same as the german loanword.
| johnisgood wrote:
| If I say it as "not C", then it does not sound much like
| "nazi", but if I say it quickly, then it could be mistaken
| for "nazi". I am not a native English speaker either.
| warent wrote:
| I'm a native American English speaker and automatically read
| notc as "not-see" which is the same pronunciation as nazi
| latrova wrote:
| Wow! Good catch! The idea was to be: "NO Try Catch" and
| somewhat recall "NO T ry C eratops", but now that you pointed
| out it doesn't make sense sense and it's not intuitive.
|
| What do you think about "notry"?
| themanmaran wrote:
| notry is better. But why not be more verbose and just have
| `no_try_catch`
| eddyg wrote:
| Why not the standard `noqa`?
| jackhalford wrote:
| Nobody seems to have touched on this so I'll go.
|
| Since trying rust's ans zig's error system I have avoided using
| python exception and replaced them with [1]. Basically functions
| return Ok(value) or Err(msg). callers can then get the result
| with `a = fn(a,b).unroll()`. For Ok it will unwrap and for Err it
| will return early (with a decorator to catch the virtual
| exception). The only overhead is the decorator, apart from this
| the ergonomics are the same as rust.
|
| It's so nice I hope it becomes a part of the language some day.
|
| [1] https://pypi.org/project/result/
| stavros wrote:
| That's nice, thanks for reminding me of this. I will use it for
| a project, as I, too, very much like the way Rust does error
| handling.
| rzarate wrote:
| I'd love to see a violation category for error handling (ie.
| making sure that all exceptions are handled appropriately).
|
| After using Golang for an extended period of time, coming back to
| Python has been frustrating at times because it is not as
| straight forward to handle errors/exceptions (especially when
| using external libraries that aren't well documented).
| murgindrag wrote:
| I want a linter where I can exclude specific things in some kind
| of configuration. Having linter hash tags in files is:
|
| - Ugly and makes for less readable code.
|
| - Doesn't apply the same exception in similar situations. If I
| made an exception to a rule in one place, I'd like it to apply
| everywhere I have similar contexts.
|
| - Gives a binary good / bad. A linter ought to flag questionable
| choices to look at -- not just bad choices. At that point, I
| should be able to say "oops, let me fix that," or "I meant to do
| that" without leaving garbage around.
|
| I'd like this stuff in a linter config/data file, ideally, as
| semantically as possible. If I tell a spell checker that yes, in
| fact, my company name is a misspelling of a common word, I don't
| need to tell it twice. This is not true for linters.
|
| I'd also like all the linty stuff configured in one place, with
| one syntax. Not pylint + pycodestyle.
|
| Examples of use-cases:
|
| - A lot of the times when I'm building an API, I have unused
| arguments in interim versions of the code. That's okay.
|
| - I occasionally break Python naming conventions, especially when
| either planning a code refactor, or when trying to comply with
| non-Python naming conventions
|
| - I generally dislike lines > 80 characters, but often, that's
| the right way to do things, especially if the alternative is
| breaking up a long token like a URL.
|
| And so on. I'd like all of these caught, and then I'd like to
| give the linter a pat on the back, say "Thank you, but here it's
| okay," and move on with my life.
|
| There's actually a lot more stuff which could be put into a
| linter once you assume that being wrong even 80% of the time
| still makes for a helpful tool. If a linter flags give things and
| I change one as a result, that's well worth the little bit of
| hassle. If a linter keeps flagging those things forever, it's no
| longer worth the hassle.
| zzzeek wrote:
| flake8 is the most common linter front end and allows for
| exclusions/inclusions in configuration files.
|
| https://flake8.pycqa.org/en/latest/user/configuration.html
| neolog wrote:
| Why not just add a rule to pylint or flake8?
| woodrowbarlow wrote:
| it looks like this linter is _specifically_ for try/except
| linting. do you anticipate users will use this alongside another
| linter? or do you plan to grow into a full linter?
| [deleted]
| lorey wrote:
| I would love to see this as a flake8 extension. An own tool
| with own formatting, workflow, etc.? I'm not sure...
| latrova wrote:
| Today I use black (formatting), isort (import sort), and flake8
| (general linting) for all my projects. I imagine people
| combining tryceratops power with other linters as well since
| the focus is very narrow.
|
| I'll create a flake8 plugin soon since some people are
| interested in it.
___________________________________________________________________
(page generated 2021-07-08 23:03 UTC)