A linter to manage all your python exceptions and try/except blocks (limited only for those who like dinosaurs).

Overview

Manage your exceptions in Python like a PRO

PyPI Code style: black Downloads

Currently in BETA. Inspired by this blog post.

I shared the building process of this tool here.

“For those who like dinosaurs 🦖 and clean try/except blocks.”


Installation and usage

Installation

pip install tryceratops

Usage

tryceratops [filename or dir...]

You can enable experimental analyzers by running:

tryceratops --experimental [filename or dir...]

You can ignore specific violations by using: --ignore TCXXX repeatedly:

tryceratops --ignore TC201 --ignore TC202 [filename or dir...]

You can exclude dirs by using: --exclude dir/path repeatedly:

tryceratops --exclude tests --exclude .venv [filename or dir...]

example

Violations

All violations and its descriptions can be found in docs.

Ignoring violations

If you want to ignore a violation in a specific file, you can either:

  • Add a comment with notc to the top of the file you want to ignore
  • Add a comment with notc to the line you want to ignore
  • Add a comment with notc: CODE to the line you want to ignore a specific violation

Example:

def verbose_reraise_1():
    try:
        a = 1
    except Exception as ex:
        raise ex  # notc: TC202

Pre-commit

If you wish to use pre-commit, add this:

  - repo: https://github.com/guilatrova/tryceratops
    rev: v0.2.3
    hooks:
      - id: tryceratops

Configuration

You can set up a pyproject.toml file to set rules. This is useful to avoid reusing the same CLI flags over and over again and helps to define the structure of your project.

Example:

[tool.tryceratops]
exclude = ["samples"]
ignore = ["TC002", "TC200", "TC300"]
experimental = true

CLI flags always overwrite the config file.

License

MIT

Credits

Thanks to God for the inspiration 🙌 ☁️ ☀️

Logo icon was made by https://www.freepik.com

The black project for insights.

Comments
  • Provide file names when

    Provide file names when "Failed to process {len(self.discovery.failures)} files" is returned

    When running tryceratops if any of the files aren't able to process, more information should be returned about which files can't be processed.

    Specifically, running tryceratops on a simple project with only 16 files returns the following:

    Done processing! 🦖✨
    Processed 16 files
    Found 0 violations
    Failed to process 1 files
    Skipped 2340 files
    

    Without knowing which file failed to process, I'm not sure what, if anything, I should do for next steps.

    This message comes from interfaces.py line 51

    opened by ryancheley 9
  • Better naming: tryceratops and triceratops

    Better naming: tryceratops and triceratops

    Isn't the naming unfortunate when there is already a Python module called triceratops?

    • https://pypi.org/project/triceratops/
    • https://pypi.org/project/tryceratops/
    opened by kseistrup 9
  • Crash when displaying the output on Windows in Anaconda

    Crash when displaying the output on Windows in Anaconda

    It seems there can be an encoding issue with the text in "Done processing" on Windows with anaconda:

    File "C:\Users\anon\.cache\pre-commit\repoqfqlxkvs\py_env-python3\lib\site-packages\tryceratops\interfaces.py", line 50, in _present_status
        print("Done processing! \U0001f996\u2728")
      File "c:\Users\anon\anaconda3\lib\encodings\cp1252.py", line 19, in encode
        return codecs.charmap_encode(input,self.errors,encoding_table)[0]
    UnicodeEncodeError: 'charmap' codec can't encode characters in position 17-18: character maps to <undefined>
    
    bug 
    opened by Pierre-Sassoulas 6
  • New violation: Prefer TypeError for unexpected types

    New violation: Prefer TypeError for unexpected types

    Hi there,

    A couple of times on existing code bases I've ran into a problem with built-in exceptions. I'm hoping to interest you into accepting it into this project, as it's the closest I've seen so far to the use case.

    A simple GitHub search results in many codebases struggling with this pattern.

    The issue

    Often built-in exceptions are used regardless of their semantics. This results in confusing diagnostic information for the user.

    if isinstance(my_var, int):
        pass
    else:
        raise ValueError("...") #should be typeerror
    

    The above examples has variations with multiple elif statements and other exception types as RuntimeError.

    Similarly, if the if/elif conditions check values, not type, then a TypeError is misleading.

    Proposed solution

    Detect these patterns and report them, ideally fix them automatically (as pyupgrade would do).

    Are you open to including this functionality in the package? If you're to busy, but open, then the community could take a turn (hacktoberfest).

    help wanted good first issue violation hacktoberfest 
    opened by sbrugman 6
  • Generic name when running tryceratops as a module

    Generic name when running tryceratops as a module

    I installed tryceratops and tryceratops.exe got installed into a folder that is not on my PATH variable.

    What I usually do, to run things like black, is python -m black, and the same thing works for tryceratops, naturally.

    However, some of the command-line options give generic info back because __name__ is now "__main__":

     > python -m tryceratops --version
    __main__.py, version 0.2.3
    

    and

     > python -m tryceratops --help
    Usage: __main__.py [OPTIONS] [DIR]...
    # omitted
    

    Notice both appearances of __main__.py where I expected tryceratops or tryceratops.py. In my opinion the __main__.py doesn't look good, in a stylistic sense.

    opened by rodrigogiraoserrao 6
  • Allow Click 8

    Allow Click 8

    Current Click specification actually disallows Click ^8. This is causing dependency issues for me. This PR loosens the requirements to allow ^8 and ^7. This might not actually be desired, and we might want to constrain to ^8.0, but wanted to keep changes to a minimum for now. All tests are passing on Click 8.0.3.


    Thanks for the project!

    opened by paw-lu 5
  • Unpin dependencies (or adopt a bot to help upgrade it like Dependabot)

    Unpin dependencies (or adopt a bot to help upgrade it like Dependabot)

    Hi! Enjoying the project!

    One issue I have come across again is that this project's dependecy pinning causes conflicts with other libraries

    It happened once before to Click, and recently again have had trouble with Rich.

    • https://github.com/guilatrova/tryceratops/pull/39
    • https://github.com/guilatrova/tryceratops/pull/46

    Rich itself updates major versions pretty often, so this is likely to happen again in the future.

    Two solutions:

    1. Unpin the dependencies, this is becoming more popular. It just involves switching from pining to the major version to just enforcing a minmum version.

      - rich = "^10.14.0"
      + rich = ">=10.14.0"
      
    2. Use an automation tool like Dependabot to keep your depenencies up to date, and update often.

    Happy to help with either of these if you are interested.

    Again, thanks for the tool!

    Edit: Wrong article was linked in first point (it supported the second point)

    opened by paw-lu 4
  • Crash when the code analysed is unparseable

    Crash when the code analysed is unparseable

    Hello, thank you for this tool, I appreciate it.

    I encountered a crash on some code with git artifact not removed:

    Traceback (most recent call last):
      File "/home/psassoulas/.cache/pre-commit/repo1clg70g2/py_env-python3/lib/python3.8/site-packages/tryceratops/files/discovery.py", line 54, in _parse_python_files_from_dir
        parsed, filefilter = parse_file(filename)
      File "/home/psassoulas/.cache/pre-commit/repo1clg70g2/py_env-python3/lib/python3.8/site-packages/tryceratops/files/parser.py", line 42, in parse_file
        tree = parse_tree(content)
      File "/home/psassoulas/.cache/pre-commit/repo1clg70g2/py_env-python3/lib/python3.8/site-packages/tryceratops/files/parser.py", line 37, in parse_tree
        return ast.parse(content.read())
      File "/usr/lib/python3.8/ast.py", line 47, in parse
        return compile(source, filename, mode, flags,
      File "<unknown>", line 74
        <<<<<<< Updated upstream
    
    opened by Pierre-Sassoulas 4
  • tryceratops sometimes fails to create `.tryceratops-errors.log`, raising `FileNotFoundError` when checking

    tryceratops sometimes fails to create `.tryceratops-errors.log`, raising `FileNotFoundError` when checking

    Thanks for sharing this work. Interesting idea for a linter!


    When ran from a pre-commit hook as a local hook:

    repos:
      - repo: local
        hooks:
          - id: tryceratops
            name: tryceratops
            entry: tryceratops
            language: system
            types: [python]
    

    and tryceratops-errors.log has not been created yet, this is raised at each check:

    Traceback (most recent call last):
      File "/Users/pawlu/Documents/personal/nbpreview/.nox/pre-commit/bin/tryceratops", line 8, in <module>
        sys.exit(main())
      File "/Users/pawlu/Documents/personal/nbpreview/.nox/pre-commit/lib/python3.9/site-packages/tryceratops/__main__.py", line 62, in main
        entrypoint(prog_name="tryceratops")
      File "/Users/pawlu/Documents/personal/nbpreview/.nox/pre-commit/lib/python3.9/site-packages/click/core.py", line 829, in __call__
        return self.main(*args, **kwargs)
      File "/Users/pawlu/Documents/personal/nbpreview/.nox/pre-commit/lib/python3.9/site-packages/click/core.py", line 782, in main
        rv = self.invoke(ctx)
      File "/Users/pawlu/Documents/personal/nbpreview/.nox/pre-commit/lib/python3.9/site-packages/click/core.py", line 1066, in invoke
        return ctx.invoke(self.callback, **ctx.params)
      File "/Users/pawlu/Documents/personal/nbpreview/.nox/pre-commit/lib/python3.9/site-packages/click/core.py", line 610, in invoke
        return callback(*args, **kwargs)
      File "/Users/pawlu/Documents/personal/nbpreview/.nox/pre-commit/lib/python3.9/site-packages/tryceratops/__main__.py", line 57, in entrypoint
        interface.present_and_exit()
      File "/Users/pawlu/Documents/personal/nbpreview/.nox/pre-commit/lib/python3.9/site-packages/tryceratops/interfaces.py", line 95, in present_and_exit
        self._delete_empty_logs()
      File "/Users/pawlu/Documents/personal/nbpreview/.nox/pre-commit/lib/python3.9/site-packages/tryceratops/interfaces.py", line 86, in _delete_empty_logs
        is_log_empty = os.path.getsize(log_file_path) == 0
      File "/usr/local/Cellar/[email protected]/3.9.6/Frameworks/Python.framework/Versions/3.9/lib/python3.9/genericpath.py", line 50, in getsize
        return os.stat(filename).st_size
    FileNotFoundError: [Errno 2] No such file or directory: '/Users/pawlu/Documents/personal/nbpreview/.tryceratops-errors.log'
    

    Things work fine if the command is invoked directly through the terminal.

    opened by paw-lu 4
  • Is it bad to capture a bare `Exception`?

    Is it bad to capture a bare `Exception`?

    I learned that catching Exception is a dangerous shortcut. It does not communicate what is expected to fail, it might silence arbitrary unexpected errors (e.g. AttributeError where ValueError is expected) and finally it also catches severe misconditions like MemoryError. Thus usually I try to be as specific as possible.

    What is your position on catching Exception? Is it something thats acceptable in Tryceratops?

    opened by MaxG87 4
  • Fix #8

    Fix #8

    This fixes issue #8 by calling the logging.shutdown function: https://docs.python.org/3/library/logging.html#logging.shutdown

    As per the docs,

    Informs the logging system to perform an orderly shutdown by flushing and closing all handlers. This should be called at application exit and no further use of the logging system should be made after this call.

    When the logging module is imported, it registers this function as an exit handler (see atexit), so normally there’s no need to do that manually.

    There might be a more appropriate place to insert this .shutdown() call, but it must be before the empty logs are deleted.

    opened by rodrigogiraoserrao 4
  • feat: changed flake8 code from TC to TRY

    feat: changed flake8 code from TC to TRY

    Hi! Thanks for great project.

    As was mentioned in https://github.com/guilatrova/tryceratops/issues/41, there is a flake8 code clash between your project and flake8-type-checkin. When used together within single project tryceratops completely disables flake8-type-checkin. Flake8 doesn't give any warning about this, which leads to bad code passing linters silently.

    good first issue 
    opened by exister 1
  • Add `--config` option to specify the location of the configuration file.

    Add `--config` option to specify the location of the configuration file.

    Hi,

    I would like to point tryceratops to a specifc configuration file using a --config option or something similar. Currently, tryceratops tries to find the configuration itself.

    In my specifc use-case, I have a repository containing a cookiecutter template (https://github.com/pytask-dev/cookiecutter-pytask-project). There are two pyproject.toml files: one for the cookiecutter and one in the src folder which is rendered as part of the template. Since the latter pyproject.toml contains Jinja syntax it causes an error when tryceratops tries to read the file.

    What do you think? I assume not many people are having a similar problem because they don't divide configuration files or something like that.

    opened by tobiasraabe 3
  • False positive use 'exception' instead of 'error' when raisign a parser error with ``argparse``

    False positive use 'exception' instead of 'error' when raisign a parser error with ``argparse``

    In the following code the parser is mistaken for a logger and using parser.exception is suggested :

    import argparse
    
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "config_folder", help="Path to the project configuration folder"
    )
    args = parser.parse_args()
    try:
        int(args.config_folder) / 0
    except:
        parser.error(
            f"Your configuration folder can't be divided by zero, use something else !"
        )
    
    opened by Pierre-Sassoulas 4
  • False negative for TC003 long message not detected

    False negative for TC003 long message not detected

    Hello again :)

    The following code is not raising a TC003 but I think it should:

    import numpy as np
    
    
    def check_a_b(a: np.ndarray, b: np.ndarray) -> None:
        if len(a) != len(b):
            raise ValueError(
                "cezczeczeczecezczeczecnezklcnzelkczkenclkzecnzeklck"
                f"({len(a)})zedenzcklzelkcnzelcknzeklcnzelkncklzeckl"
                f"({len(b)})dzekckezncknzecklnzeklczkelcklzencknzeck"
            )
    
    
    bug help wanted hacktoberfest 
    opened by Pierre-Sassoulas 2
Releases(v1.1.0)
Owner
Guilherme Latrova
Sportist, Creator, Software writer, Coffee appreciator, Lucky husband and God servant :)
Guilherme Latrova
NLP techniques such as named entity recognition, sentiment analysis, topic modeling, text classification with Python to predict sentiment and rating of drug from user reviews.

This file contains the following documents sumbited for Baruch CIS9665 group 9 fall 2021. 1. Dataset: drug_reviews.csv 2. python codes for text classi

Aarif Munwar Jahan 2 Jan 04, 2023
Code for the paper "BERT Loses Patience: Fast and Robust Inference with Early Exit".

Patience-based Early Exit Code for the paper "BERT Loses Patience: Fast and Robust Inference with Early Exit". NEWS: We now have a better and tidier i

Kevin Canwen Xu 54 Jan 04, 2023
✔👉A Centralized WebApp to Ensure Road Safety by checking on with the activities of the driver and activating label generator using NLP.

AI-For-Road-Safety Challenge hosted by Omdena Hyderabad Chapter Original Repo Link : https://github.com/OmdenaAI/omdena-india-roadsafety Final Present

Prathima Kadari 7 Nov 29, 2022
NLP, Machine learning

Netflix-recommendation-system NLP, Machine learning About Recommendation algorithms are at the core of the Netflix product. It provides their members

Harshith VH 6 Jan 12, 2022
DLO8012: Natural Language Processing & CSL804: Computational Lab - II

NATURAL-LANGUAGE-PROCESSING-AND-COMPUTATIONAL-LAB-II DLO8012: NLP & CSL804: CL-II [SEMESTER VIII] Syllabus NLP - Reference Books THE WALL MEGA SATISH

AMEY THAKUR 7 Apr 28, 2022
Code examples for my Write Better Python Code series on YouTube.

Write Better Python Code This repository contains the code examples used in my Write Better Python Code series published on YouTube: https:/

858 Dec 29, 2022
🛸 Use pretrained transformers like BERT, XLNet and GPT-2 in spaCy

spacy-transformers: Use pretrained transformers like BERT, XLNet and GPT-2 in spaCy This package provides spaCy components and architectures to use tr

Explosion 1.2k Jan 08, 2023
Anuvada: Interpretable Models for NLP using PyTorch

Anuvada: Interpretable Models for NLP using PyTorch So, you want to know why your classifier arrived at a particular decision or why your flashy new d

EDGE 102 Oct 01, 2022
Transformer Based Korean Sentence Spacing Corrector

TKOrrector Transformer Based Korean Sentence Spacing Corrector License Summary This solution is made available under Apache 2 license. See the LICENSE

Paul Hyung Yuel Kim 3 Apr 18, 2022
SurvTRACE: Transformers for Survival Analysis with Competing Events

⭐ SurvTRACE: Transformers for Survival Analysis with Competing Events This repo provides the implementation of SurvTRACE for survival analysis. It is

Zifeng 13 Oct 06, 2022
Rhyme with AI

Local development Create a conda virtual environment and activate it: conda env create --file environment.yml conda activate rhyme-with-ai Install the

GoDataDriven 28 Nov 21, 2022
A CRM department in a local bank works on classify their lost customers with their past datas. So they want predict with these method that average loss balance and passive duration for future.

Rule-Based-Classification-in-a-Banking-Case. A CRM department in a local bank works on classify their lost customers with their past datas. So they wa

ÖMER YILDIZ 4 Mar 20, 2022
NLP - Machine learning

Flipkart-product-reviews NLP - Machine learning About Product reviews is an essential part of an online store like Flipkart’s branding and marketing.

Harshith VH 1 Oct 29, 2021
Repository for the paper "Optimal Subarchitecture Extraction for BERT"

Bort Companion code for the paper "Optimal Subarchitecture Extraction for BERT." Bort is an optimal subset of architectural parameters for the BERT ar

Alexa 461 Nov 21, 2022
Auto-researching tool generating word documents.

About ResearchTE automates researching by generating document with answers to given questions. Supports getting results from: Google DuckDuckGo (with

1 Feb 14, 2022
PUA Programming Language written in Python.

pua-lang PUA Programming Language written in Python. Installation git clone https://github.com/zhaoyang97/pua-lang.git cd pua-lang pip install . Try

zy 4 Feb 19, 2022
DiffSinger: Singing Voice Synthesis via Shallow Diffusion Mechanism (SVS & TTS); AAAI 2022

DiffSinger: Singing Voice Synthesis via Shallow Diffusion Mechanism This repository is the official PyTorch implementation of our AAAI-2022 paper, in

Jinglin Liu 829 Jan 07, 2023
Python library to make development of portfolio analysis faster and easier

Trafalgar Python library to make development of portfolio analysis faster and easier Installation 🔥 For the moment, Trafalgar is still in beta develo

Santosh Passoubady 641 Jan 01, 2023
A versatile token stream for handwritten parsers.

Writing recursive-descent parsers by hand can be quite elegant but it's often a bit more verbose than expected, especially when it comes to handling indentation and reporting proper syntax errors. Th

Valentin Berlier 8 Nov 30, 2022
Implementaion of our ACL 2022 paper Bridging the Data Gap between Training and Inference for Unsupervised Neural Machine Translation

Bridging the Data Gap between Training and Inference for Unsupervised Neural Machine Translation This is the implementaion of our paper: Bridging the

hezw.tkcw 20 Dec 12, 2022