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
DziriBERT: a Pre-trained Language Model for the Algerian Dialect

DziriBERT is the first Transformer-based Language Model that has been pre-trained specifically for the Algerian Dialect.

117 Jan 07, 2023
Resources for "Natural Language Processing" Coursera course.

Natural Language Processing course resources This github contains practical assignments for Natural Language Processing course by Higher School of Eco

Advanced Machine Learning specialisation by HSE 1.1k Jan 01, 2023
Pytorch-Named-Entity-Recognition-with-BERT

BERT NER Use google BERT to do CoNLL-2003 NER ! Train model using Python and Inference using C++ ALBERT-TF2.0 BERT-NER-TENSORFLOW-2.0 BERT-SQuAD Requi

Kamal Raj 1.1k Dec 25, 2022
使用pytorch+transformers复现了SimCSE论文中的有监督训练和无监督训练方法

SimCSE复现 项目描述 SimCSE是一种简单但是很巧妙的NLP对比学习方法,创新性地引入Dropout的方式,对样本添加噪声,从而达到对正样本增强的目的。 该框架的训练目的为:对于batch中的每个样本,拉近其与正样本之间的距离,拉远其与负样本之间的距离,使得模型能够在大规模无监督语料(也可以

58 Dec 20, 2022
SNCSE: Contrastive Learning for Unsupervised Sentence Embedding with Soft Negative Samples

SNCSE SNCSE: Contrastive Learning for Unsupervised Sentence Embedding with Soft Negative Samples This is the repository for SNCSE. SNCSE aims to allev

Sense-GVT 59 Jan 02, 2023
Code for the paper "Are Sixteen Heads Really Better than One?"

Are Sixteen Heads Really Better than One? This repository contains code to reproduce the experiments in our paper Are Sixteen Heads Really Better than

Paul Michel 143 Dec 14, 2022
A very simple framework for state-of-the-art Natural Language Processing (NLP)

A very simple framework for state-of-the-art NLP. Developed by Humboldt University of Berlin and friends. IMPORTANT: (30.08.2020) We moved our models

flair 12.3k Dec 31, 2022
Spam filtering made easy for you

spammy Author: Tasdik Rahman Latest version: 1.0.3 Contents 1 Overview 2 Features 3 Example 3.1 Accuracy of the classifier 4 Installation 4.1 Upgradin

Tasdik Rahman 137 Dec 18, 2022
Translate - a PyTorch Language Library

NOTE PyTorch Translate is now deprecated, please use fairseq instead. Translate - a PyTorch Language Library Translate is a library for machine transl

775 Dec 24, 2022
PyTorch code for EMNLP 2019 paper "LXMERT: Learning Cross-Modality Encoder Representations from Transformers".

LXMERT: Learning Cross-Modality Encoder Representations from Transformers Our servers break again :(. I have updated the links so that they should wor

Hao Tan 838 Dec 19, 2022
运小筹公众号是致力于分享运筹优化(LP、MIP、NLP、随机规划、鲁棒优化)、凸优化、强化学习等研究领域的内容以及涉及到的算法的代码实现。

OlittleRer 运小筹公众号是致力于分享运筹优化(LP、MIP、NLP、随机规划、鲁棒优化)、凸优化、强化学习等研究领域的内容以及涉及到的算法的代码实现。编程语言和工具包括Java、Python、Matlab、CPLEX、Gurobi、SCIP 等。 关注我们: 运筹小公众号 有问题可以直接在

运小筹 151 Dec 30, 2022
[ICLR 2021 Spotlight] Pytorch implementation for "Long-tailed Recognition by Routing Diverse Distribution-Aware Experts."

RIDE: Long-tailed Recognition by Routing Diverse Distribution-Aware Experts. by Xudong Wang, Long Lian, Zhongqi Miao, Ziwei Liu and Stella X. Yu at UC

Xudong (Frank) Wang 205 Dec 16, 2022
Code for CVPR 2021 paper: Revamping Cross-Modal Recipe Retrieval with Hierarchical Transformers and Self-supervised Learning

Revamping Cross-Modal Recipe Retrieval with Hierarchical Transformers and Self-supervised Learning This is the PyTorch companion code for the paper: A

Amazon 69 Jan 03, 2023
PIZZA - a task-oriented semantic parsing dataset

The PIZZA dataset continues the exploration of task-oriented parsing by introducing a new dataset for parsing pizza and drink orders, whose semantics cannot be captured by flat slots and intents.

17 Dec 14, 2022
This is a NLP based project to extract effective date of the contract from their text files.

Date-Extraction-from-Contracts This is a NLP based project to extract effective date of the contract from their text files. Problem statement This is

Sambhav Garg 1 Jan 26, 2022
Code for hyperboloid embeddings for knowledge graph entities

Implementation for the papers: Self-Supervised Hyperboloid Representations from Logical Queries over Knowledge Graphs, Nurendra Choudhary, Nikhil Rao,

30 Dec 10, 2022
Scene Text Retrieval via Joint Text Detection and Similarity Learning

This is the code of "Scene Text Retrieval via Joint Text Detection and Similarity Learning". For more details, please refer to our CVPR2021 paper.

79 Nov 29, 2022
Official source for spanish Language Models and resources made @ BSC-TEMU within the "Plan de las Tecnologías del Lenguaje" (Plan-TL).

Spanish Language Models 💃🏻 Corpora 📃 Corpora Number of documents Size (GB) BNE 201,080,084 570GB Models 🤖 RoBERTa-base BNE: https://huggingface.co

PlanTL-SANIDAD 203 Dec 20, 2022
The projects lets you extract glossary words and their definitions from a given piece of text automatically using NLP techniques

Unsupervised technique to Glossary and Definition Extraction Code Files GPT2-DefinitionModel.ipynb - GPT-2 model for definition generation. Data_Gener

Prakhar Mishra 28 May 25, 2021
Words_And_Phrases - Just a repo for useful words and phrases that might come handy in some scenarios. Feel free to add yours

Words_And_Phrases Just a repo for useful words and phrases that might come handy in some scenarios. Feel free to add yours Abbreviations Abbreviation

Subhadeep Mandal 1 Feb 01, 2022