From 34c7903300e84b53c86c2792196d069b15cb5888 Mon Sep 17 00:00:00 2001 From: Micah Jerome Ellison Date: Sat, 15 Jul 2023 12:35:10 -0700 Subject: [PATCH] Replace flake8 and isort with ruff linter and add `black --check` to linting step (#1763) * Add ruff * Add ruff config * Add ruff rules that look useful and are already passing * Add more ruff rules after talking with Jonathan * Add line length exception for acceptably long indented line * Resolve ruff line length 88 rule in args. Changing small lines but adding a noqa ignore directive to longer lines that look best as they are. Their dedented length is still less than 88 * poe format * Resolve all remaining ruff line length errors * Replace flake* and isort with ruff calls * Add black --check as final lint step. ruff catches most but not all black formatting issues * Remove unneeded flakeheaven setting * Remove flake* and isort now that ruff is handling all their business * Update pyproject, lockfile with latest version of ruff * Document each ruff rule with comment * Add black --version call before black --check * Remove extraneous period --- jrnl/args.py | 29 ++- jrnl/commands.py | 2 +- jrnl/config.py | 5 +- jrnl/controller.py | 8 +- jrnl/editor.py | 3 +- jrnl/install.py | 12 +- jrnl/journals/Entry.py | 4 +- jrnl/journals/FolderJournal.py | 3 +- jrnl/journals/Journal.py | 12 +- jrnl/messages/MsgText.py | 4 +- jrnl/override.py | 3 +- jrnl/plugins/fancy_exporter.py | 2 +- jrnl/plugins/tag_exporter.py | 2 +- jrnl/plugins/util.py | 3 +- jrnl/plugins/yaml_exporter.py | 14 +- jrnl/time.py | 10 +- poetry.lock | 324 +++------------------------------ pyproject.toml | 68 ++++--- tests/lib/then_steps.py | 46 +++-- tests/unit/test_parse_args.py | 4 +- 20 files changed, 162 insertions(+), 396 deletions(-) diff --git a/jrnl/args.py b/jrnl/args.py index 9b7dafe7f..53a77462e 100644 --- a/jrnl/args.py +++ b/jrnl/args.py @@ -78,7 +78,7 @@ def parse_args(args: list[str] = []) -> argparse.Namespace: """ We gratefully thank all contributors! Come see the whole list of code and financial contributors at https://github.com/jrnl-org/jrnl - And special thanks to Bad Lip Reading for the Yoda joke in the Writing section above :)""" + And special thanks to Bad Lip Reading for the Yoda joke in the Writing section above :)""" # noqa: E501 ), ) @@ -214,7 +214,8 @@ def parse_args(args: list[str] = []) -> argparse.Namespace: composing.add_argument( "--template", dest="template", - help="Path to template file. Can be a local path, absolute path, or a path relative to $XDG_DATA_HOME/jrnl/templates/", + help="Path to template file. Can be a local path, absolute path, or a path " + "relative to $XDG_DATA_HOME/jrnl/templates/", ) read_msg = ( @@ -265,13 +266,15 @@ def parse_args(args: list[str] = []) -> argparse.Namespace: "-contains", dest="contains", metavar="TEXT", - help="Show entries containing specific text (put quotes around text with spaces)", + help="Show entries containing specific text (put quotes around text with " + "spaces)", ) reading.add_argument( "-and", dest="strict", action="store_true", - help='Show only entries that match all conditions, like saying "x AND y" (default: OR)', + help='Show only entries that match all conditions, like saying "x AND y" ' + "(default: OR)", ) reading.add_argument( "-starred", @@ -290,7 +293,8 @@ def parse_args(args: list[str] = []) -> argparse.Namespace: dest="limit", default=None, metavar="NUMBER", - help="Show a maximum of NUMBER entries (note: '-n 3' and '-3' have the same effect)", + help="Show a maximum of NUMBER entries (note: '-n 3' and '-3' have the same " + "effect)", nargs="?", type=int, ) @@ -308,8 +312,12 @@ def parse_args(args: list[str] = []) -> argparse.Namespace: ), ) - search_options_msg = """ These help you do various tasks with the selected entries from your search. - If used on their own (with no search), they will act on your entire journal""" + search_options_msg = ( + " " # Preserves indentation + """ + These help you do various tasks with the selected entries from your search. + If used on their own (with no search), they will act on your entire journal""" + ) exporting = parser.add_argument_group( "Searching Options", textwrap.dedent(search_options_msg) ) @@ -360,7 +368,8 @@ def parse_args(args: list[str] = []) -> argparse.Namespace: "--tags", dest="tags", action="store_true", - help="Alias for '--format tags'. Returns a list of all tags and number of occurrences", + help="Alias for '--format tags'. Returns a list of all tags and number of " + "occurrences", ) exporting.add_argument( "--short", @@ -400,7 +409,7 @@ def parse_args(args: list[str] = []) -> argparse.Namespace: \t jrnl --config-override editor "nano" \n \t - Override color selections\n \t jrnl --config-override colors.body blue --config-override colors.title green - """, + """, # noqa: E501 ) config_overrides.add_argument( "--co", @@ -430,7 +439,7 @@ def parse_args(args: list[str] = []) -> argparse.Namespace: \t jrnl --config-file /home/user1/work_config.yaml \t - Use a personal config file stored on a thumb drive: \n \t jrnl --config-file /media/user1/my-thumb-drive/personal_config.yaml - """, + """, # noqa: E501 ) alternate_config.add_argument( diff --git a/jrnl/commands.py b/jrnl/commands.py index 83618ce29..5ba449e4b 100644 --- a/jrnl/commands.py +++ b/jrnl/commands.py @@ -142,7 +142,7 @@ def postconfig_encrypt( def postconfig_decrypt( args: argparse.Namespace, config: dict, original_config: dict ) -> int: - """Decrypts into new file. If filename is not set, we encrypt the journal file itself.""" + """Decrypts to file. If filename is not set, we encrypt the journal file itself.""" from jrnl.config import update_config from jrnl.install import save_config from jrnl.journals import open_journal diff --git a/jrnl/config.py b/jrnl/config.py index a2f0885c8..1fdded199 100644 --- a/jrnl/config.py +++ b/jrnl/config.py @@ -37,9 +37,10 @@ def make_yaml_valid_dict(input: list) -> dict: The dict is created through the yaml loader, with the assumption that "input[0]: input[1]" is valid yaml. - :param input: list of configuration keys in dot-notation and their respective values. + :param input: list of configuration keys in dot-notation and their respective values :type input: list - :return: A single level dict of the configuration keys in dot-notation and their respective desired values + :return: A single level dict of the configuration keys in dot-notation and their + respective desired values :rtype: dict """ diff --git a/jrnl/controller.py b/jrnl/controller.py index e0e222b5a..2e36551ba 100644 --- a/jrnl/controller.py +++ b/jrnl/controller.py @@ -34,9 +34,9 @@ def run(args: "Namespace"): """ Flow: - 1. Run standalone command if it doesn't require config (help, version, etc), then exit + 1. Run standalone command if it doesn't need config (help, version, etc), then exit 2. Load config - 3. Run standalone command if it does require config (encrypt, decrypt, etc), then exit + 3. Run standalone command if it does need config (encrypt, decrypt, etc), then exit 4. Load specified journal 5. Start append mode, or search mode 6. Perform actions with results from search mode (if needed) @@ -181,7 +181,9 @@ def append_mode(args: "Namespace", config: dict, journal: "Journal", **kwargs) - def _get_template(args, config) -> str: # Read template file and pass as raw text into the composer logging.debug( - f"Get template:\n--template: {args.template}\nfrom config: {config.get('template')}" + "Get template:\n" + f"--template: {args.template}\n" + f"from config: {config.get('template')}" ) template_path = args.template or config.get("template") diff --git a/jrnl/editor.py b/jrnl/editor.py index cbcf62074..61afed3c5 100644 --- a/jrnl/editor.py +++ b/jrnl/editor.py @@ -81,7 +81,8 @@ def get_template_path(template_path: str, jrnl_template_dir: str) -> str: actual_template_path = os.path.join(jrnl_template_dir, template_path) if not os.path.exists(actual_template_path): logging.debug( - f"Couldn't open {actual_template_path}. Treating template path like a local / abs path." + f"Couldn't open {actual_template_path}. " + "Treating template path like a local / abs path." ) actual_template_path = absolute_path(template_path) diff --git a/jrnl/install.py b/jrnl/install.py index f9d9ac1a5..4033c33c2 100644 --- a/jrnl/install.py +++ b/jrnl/install.py @@ -31,11 +31,11 @@ def upgrade_config(config_data: dict, alt_config_path: str | None = None) -> None: - """Checks if there are keys missing in a given config dict, and if so, updates the config file accordingly. - This essentially automatically ports jrnl installations if new config parameters are introduced in later - versions. - Also checks for existence of and difference in version number between config dict and current jrnl version, - and if so, update the config file accordingly. + """Checks if there are keys missing in a given config dict, and if so, updates the + config file accordingly. This essentially automatically ports jrnl installations + if new config parameters are introduced in later versions. Also checks for + existence of and difference in version number between config dict + and current jrnl version, and if so, update the config file accordingly. Supply alt_config_path if using an alternate config through --config-file.""" default_config = get_default_config() missing_keys = set(default_config).difference(config_data) @@ -167,7 +167,7 @@ def install() -> dict: def _initialize_autocomplete() -> None: - # readline is not included in Windows Active Python and perhaps some other distributions + # readline is not included in Windows Active Python and perhaps some other distss if sys.modules.get("readline"): import readline diff --git a/jrnl/journals/Entry.py b/jrnl/journals/Entry.py index 93b825f85..5b35d7346 100644 --- a/jrnl/journals/Entry.py +++ b/jrnl/journals/Entry.py @@ -89,7 +89,7 @@ def _parse_tags(self) -> set[str]: } def __str__(self): - """Returns a string representation of the entry to be written into a journal file.""" + """Returns string representation of the entry to be written to journal file.""" date_str = self.date.strftime(self.journal.config["timeformat"]) title = "[{}] {}".format(date_str, self.title.rstrip("\n ")) if self.starred: @@ -233,7 +233,7 @@ def __ne__(self, other: "Entry"): \s+ # AND a sequence of required spaces. ) |[\uFF01\uFF0E\uFF1F\uFF61\u3002] # CJK full/half width terminals usually do not have following spaces. - """, + """, # noqa: E501 re.VERBOSE, ) diff --git a/jrnl/journals/FolderJournal.py b/jrnl/journals/FolderJournal.py index 0d497fb83..c6faf1e02 100644 --- a/jrnl/journals/FolderJournal.py +++ b/jrnl/journals/FolderJournal.py @@ -122,7 +122,8 @@ def parse_editable_str(self, edited: str) -> None: @staticmethod def _get_files(journal_path: str) -> list[str]: - """Searches through sub directories starting with journal_path and find all text files that look like entries""" + """Searches through sub directories starting with journal_path and find all text + files that look like entries""" for year_folder in Folder._get_year_folders(pathlib.Path(journal_path)): for month_folder in Folder._get_month_folders(year_folder): yield from Folder._get_day_files(month_folder) diff --git a/jrnl/journals/Journal.py b/jrnl/journals/Journal.py index bd72788b7..d10548140 100644 --- a/jrnl/journals/Journal.py +++ b/jrnl/journals/Journal.py @@ -102,7 +102,7 @@ def _encrypt(self, text: str) -> bytes: return self.encryption_method.encrypt(text) def open(self, filename: str | None = None) -> "Journal": - """Opens the journal file defined in the config and parses it into a list of Entries. + """Opens the journal file and parses it into a list of Entries Entries have the form (date, title, body).""" filename = filename or self.config["journal"] dirname = os.path.dirname(filename) @@ -144,7 +144,7 @@ def write(self, filename: str | None = None) -> None: self._store(filename, text) def validate_parsing(self) -> bool: - """Confirms that the jrnl is still parsed correctly after being dumped to text.""" + """Confirms that the jrnl is still parsed correctly after conversion to text.""" new_entries = self._parse(self._to_text()) return all(entry == new_entries[i] for i, entry in enumerate(self.entries)) @@ -225,8 +225,9 @@ def limit(self, n: int | None = None) -> None: @property def tags(self) -> list[Tag]: """Returns a set of tuples (count, tag) for all tags present in the journal.""" - # Astute reader: should the following line leave you as puzzled as me the first time - # I came across this construction, worry not and embrace the ensuing moment of enlightment. + # Astute reader: should the following line leave you as puzzled as me the first + # time I came across this construction, worry not and embrace the ensuing moment + # of enlightment. tags = [tag for entry in self.entries for tag in set(entry.tags)] # To be read: [for entry in journal.entries: for tag in set(entry.tags): tag] tag_counts = {(tags.count(tag), tag) for tag in tags} @@ -343,7 +344,8 @@ def ask_action(entry): def new_entry(self, raw: str, date=None, sort: bool = True) -> Entry: """Constructs a new entry from some raw text input. - If a date is given, it will parse and use this, otherwise scan for a date in the input first. + If a date is given, it will parse and use this, otherwise scan for a date in + the input first. """ raw = raw.replace("\\n ", "\n").replace("\\n", "\n") diff --git a/jrnl/messages/MsgText.py b/jrnl/messages/MsgText.py index c8ac5b043..9361781d7 100644 --- a/jrnl/messages/MsgText.py +++ b/jrnl/messages/MsgText.py @@ -43,8 +43,8 @@ def __str__(self) -> str: Do you want to encrypt your journal? (You can always change this later) """ UseColorsQuestion = """ - Do you want jrnl to use colors when displaying entries? (You can always change this later) - """ + Do you want jrnl to use colors to display entries? (You can always change this later) + """ # noqa: E501 - the line is still under 88 when dedented YesOrNoPromptDefaultYes = "[Y/n]" YesOrNoPromptDefaultNo = "[y/N]" ContinueUpgrade = "Continue upgrading jrnl?" diff --git a/jrnl/override.py b/jrnl/override.py index bc85f47e1..368d1a37e 100644 --- a/jrnl/override.py +++ b/jrnl/override.py @@ -56,7 +56,8 @@ def _recursively_apply(tree: dict, nodes: list, override_value) -> dict: Args: config (dict): Configuration to modify - nodes (list): Vector of override keys; the length of the vector indicates tree depth + nodes (list): Vector of override keys; the length of the vector indicates tree + depth override_value (str): Runtime override passed from the command-line """ key = nodes[0] diff --git a/jrnl/plugins/fancy_exporter.py b/jrnl/plugins/fancy_exporter.py index 447f13473..a6cbe3610 100644 --- a/jrnl/plugins/fancy_exporter.py +++ b/jrnl/plugins/fancy_exporter.py @@ -18,7 +18,7 @@ class FancyExporter(TextExporter): - """This Exporter can convert entries and journals into text with unicode box drawing characters.""" + """This Exporter converts entries and journals into text with unicode boxes.""" names = ["fancy", "boxed"] extension = "txt" diff --git a/jrnl/plugins/tag_exporter.py b/jrnl/plugins/tag_exporter.py index b8b5eb798..c11606267 100644 --- a/jrnl/plugins/tag_exporter.py +++ b/jrnl/plugins/tag_exporter.py @@ -12,7 +12,7 @@ class TagExporter(TextExporter): - """This Exporter can lists the tags for entries and journals, exported as a plain text file.""" + """This Exporter lists the tags for entries and journals.""" names = ["tags"] extension = "tags" diff --git a/jrnl/plugins/util.py b/jrnl/plugins/util.py index ceaa0b041..180d86ea7 100644 --- a/jrnl/plugins/util.py +++ b/jrnl/plugins/util.py @@ -10,7 +10,8 @@ def get_tags_count(journal: "Journal") -> set[tuple[int, str]]: """Returns a set of tuples (count, tag) for all tags present in the journal.""" # Astute reader: should the following line leave you as puzzled as me the first time - # I came across this construction, worry not and embrace the ensuing moment of enlightment. + # I came across this construction, worry not and embrace the ensuing moment of + # enlightment. tags = [tag for entry in journal.entries for tag in set(entry.tags)] # To be read: [for entry in journal.entries: for tag in set(entry.tags): tag] tag_counts = {(tags.count(tag), tag) for tag in tags} diff --git a/jrnl/plugins/yaml_exporter.py b/jrnl/plugins/yaml_exporter.py index d960ef8a9..90c14086e 100644 --- a/jrnl/plugins/yaml_exporter.py +++ b/jrnl/plugins/yaml_exporter.py @@ -18,14 +18,15 @@ class YAMLExporter(TextExporter): - """This Exporter can convert entries and journals into Markdown formatted text with YAML front matter.""" + """This Exporter converts entries and journals into Markdown formatted text with + YAML front matter.""" names = ["yaml"] extension = "md" @classmethod def export_entry(cls, entry: "Entry", to_multifile: bool = True) -> str: - """Returns a markdown representation of a single entry, with YAML front matter.""" + """Returns a markdown representation of an entry, with YAML front matter.""" if to_multifile is False: raise JrnlException(Message(MsgText.YamlMustBeDirectory, MsgStyle.ERROR)) @@ -117,7 +118,14 @@ def export_entry(cls, entry: "Entry", to_multifile: bool = True) -> str: # source directory is entry.journal.config['journal'] # output directory is...? - return "{start}\ntitle: {title}\ndate: {date}\nstarred: {starred}\ntags: {tags}\n{dayone}body: |{body}{end}".format( + return ( + "{start}\n" + "title: {title}\n" + "date: {date}\n" + "starred: {starred}\n" + "tags: {tags}\n" + "{dayone}body: |{body}{end}" + ).format( start="---", date=date_str, title=entry.title, diff --git a/jrnl/time.py b/jrnl/time.py index dd6fcb0fe..da13f1d00 100644 --- a/jrnl/time.py +++ b/jrnl/time.py @@ -34,8 +34,8 @@ def parse( elif isinstance(date_str, datetime.datetime): return date_str - # Don't try to parse anything with 6 or fewer characters and was parsed from the existing journal. - # It's probably a markdown footnote + # Don't try to parse anything with 6 or fewer characters and was parsed from the + # existing journal. It's probably a markdown footnote if len(date_str) <= 6 and bracketed: return None @@ -82,9 +82,9 @@ def parse( else: date = datetime.datetime(*date[:6]) - # Ugly heuristic: if the date is more than 4 weeks in the future, we got the year wrong. - # Rather than this, we would like to see parsedatetime patched so we can tell it to prefer - # past dates + # Ugly heuristic: if the date is more than 4 weeks in the future, we got the year + # wrong. Rather than this, we would like to see parsedatetime patched so we can + # tell it to prefer past dates dt = datetime.datetime.now() - date if dt.days < -28 and not year_present: date = date.replace(date.year - 1) diff --git a/poetry.lock b/poetry.lock index 60c93c378..7b9bfcf5e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,10 +1,9 @@ -# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.5.0 and should not be changed by hand. [[package]] name = "ansiwrap" version = "0.8.4" description = "textwrap, but savvy to ANSI colors and styles" -category = "main" optional = false python-versions = "*" files = [ @@ -19,7 +18,6 @@ textwrap3 = ">=0.9.2" name = "appnope" version = "0.1.3" description = "Disable App Nap on macOS >= 10.9" -category = "dev" optional = false python-versions = "*" files = [ @@ -27,23 +25,10 @@ files = [ {file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"}, ] -[[package]] -name = "astor" -version = "0.8.1" -description = "Read/rewrite/write Python ASTs" -category = "dev" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -files = [ - {file = "astor-0.8.1-py2.py3-none-any.whl", hash = "sha256:070a54e890cefb5b3739d19f30f5a5ec840ffc9c50ffa7d23cc9fc1a38ebbfc5"}, - {file = "astor-0.8.1.tar.gz", hash = "sha256:6a6effda93f4e1ce9f618779b2dd1d9d84f1e32812c23a29b3fff6fd7f63fa5e"}, -] - [[package]] name = "asttokens" version = "2.2.1" description = "Annotate AST trees with source code positions" -category = "dev" optional = false python-versions = "*" files = [ @@ -61,7 +46,6 @@ test = ["astroid", "pytest"] name = "backcall" version = "0.2.0" description = "Specifications for callback functions passed in to an API" -category = "dev" optional = false python-versions = "*" files = [ @@ -73,7 +57,6 @@ files = [ name = "black" version = "23.3.0" description = "The uncompromising code formatter." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -122,7 +105,6 @@ uvloop = ["uvloop (>=0.15.2)"] name = "cachetools" version = "5.3.1" description = "Extensible memoizing collections and decorators" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -134,7 +116,6 @@ files = [ name = "certifi" version = "2022.12.7" description = "Python package for providing Mozilla's CA Bundle." -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -146,7 +127,6 @@ files = [ name = "cffi" version = "1.15.1" description = "Foreign Function Interface for Python calling C code." -category = "main" optional = false python-versions = "*" files = [ @@ -223,7 +203,6 @@ pycparser = "*" name = "chardet" version = "5.1.0" description = "Universal encoding detector for Python 3" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -235,7 +214,6 @@ files = [ name = "charset-normalizer" version = "3.0.1" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "dev" optional = false python-versions = "*" files = [ @@ -329,23 +307,10 @@ files = [ {file = "charset_normalizer-3.0.1-py3-none-any.whl", hash = "sha256:7e189e2e1d3ed2f4aebabd2d5b0f931e883676e51c7624826e0a4e5fe8a0bf24"}, ] -[[package]] -name = "classify-imports" -version = "4.2.0" -description = "Utilities for refactoring imports in python-like syntax." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "classify_imports-4.2.0-py2.py3-none-any.whl", hash = "sha256:dbbc264b70a470ed8c6c95976a11dfb8b7f63df44ed1af87328bbed2663f5161"}, - {file = "classify_imports-4.2.0.tar.gz", hash = "sha256:7abfb7ea92149b29d046bd34573d247ba6e68cc28100c801eba4af17964fc40e"}, -] - [[package]] name = "click" version = "8.1.3" description = "Composable command line interface toolkit" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -360,7 +325,6 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -372,7 +336,6 @@ files = [ name = "cryptography" version = "41.0.1" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -414,7 +377,6 @@ test-randomorder = ["pytest-randomly"] name = "decorator" version = "5.1.1" description = "Decorators for Humans" -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -426,7 +388,6 @@ files = [ name = "distlib" version = "0.3.6" description = "Distribution utilities" -category = "dev" optional = false python-versions = "*" files = [ @@ -434,23 +395,10 @@ files = [ {file = "distlib-0.3.6.tar.gz", hash = "sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46"}, ] -[[package]] -name = "entrypoints" -version = "0.4" -description = "Discover and load entry points from installed packages." -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "entrypoints-0.4-py3-none-any.whl", hash = "sha256:f174b5ff827504fd3cd97cc3f8649f3693f51538c7e4bdf3ef002c8429d42f9f"}, - {file = "entrypoints-0.4.tar.gz", hash = "sha256:b706eddaa9218a19ebcd67b56818f05bb27589b1ca9e8d797b74affad4ccacd4"}, -] - [[package]] name = "exceptiongroup" version = "1.1.0" description = "Backport of PEP 654 (exception groups)" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -465,7 +413,6 @@ test = ["pytest (>=6)"] name = "execnet" version = "1.9.0" description = "execnet: rapid multi-Python deployment" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -480,7 +427,6 @@ testing = ["pre-commit"] name = "executing" version = "1.2.0" description = "Get the currently executing AST node of a frame, and other information" -category = "dev" optional = false python-versions = "*" files = [ @@ -495,7 +441,6 @@ tests = ["asttokens", "littleutils", "pytest", "rich"] name = "filelock" version = "3.12.2" description = "A platform independent file lock." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -507,122 +452,10 @@ files = [ docs = ["furo (>=2023.5.20)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"] -[[package]] -name = "flake8" -version = "4.0.1" -description = "the modular source code checker: pep8 pyflakes and co" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, - {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, -] - -[package.dependencies] -mccabe = ">=0.6.0,<0.7.0" -pycodestyle = ">=2.8.0,<2.9.0" -pyflakes = ">=2.4.0,<2.5.0" - -[[package]] -name = "flake8-black" -version = "0.3.6" -description = "flake8 plugin to call black as a code style validator" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "flake8-black-0.3.6.tar.gz", hash = "sha256:0dfbca3274777792a5bcb2af887a4cad72c72d0e86c94e08e3a3de151bb41c34"}, - {file = "flake8_black-0.3.6-py3-none-any.whl", hash = "sha256:fe8ea2eca98d8a504f22040d9117347f6b367458366952862ac3586e7d4eeaca"}, -] - -[package.dependencies] -black = ">=22.1.0" -flake8 = ">=3" -tomli = {version = "*", markers = "python_version < \"3.11\""} - -[package.extras] -develop = ["build", "twine"] - -[[package]] -name = "flake8-isort" -version = "6.0.0" -description = "flake8 plugin that integrates isort ." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "flake8-isort-6.0.0.tar.gz", hash = "sha256:537f453a660d7e903f602ecfa36136b140de279df58d02eb1b6a0c84e83c528c"}, - {file = "flake8_isort-6.0.0-py3-none-any.whl", hash = "sha256:aa0cac02a62c7739e370ce6b9c31743edac904bae4b157274511fc8a19c75bbc"}, -] - -[package.dependencies] -flake8 = "*" -isort = ">=5.0.0,<6" - -[package.extras] -test = ["pytest"] - -[[package]] -name = "flake8-simplify" -version = "0.20.0" -description = "flake8 plugin which checks for code that can be simplified" -category = "dev" -optional = false -python-versions = ">=3.6.1" -files = [ - {file = "flake8_simplify-0.20.0-py3-none-any.whl", hash = "sha256:599a47824726c93fadcf0274e569daed45052e38cd906360d9080eaa3bd76d61"}, - {file = "flake8_simplify-0.20.0.tar.gz", hash = "sha256:7b8796bbea8aed45f56621c389d0556cc86f0afa5d992581139451240a8fbeca"}, -] - -[package.dependencies] -astor = ">=0.1" -flake8 = ">=3.7" - -[[package]] -name = "flake8-type-checking" -version = "2.4.0" -description = "A flake8 plugin for managing type-checking imports & forward references" -category = "dev" -optional = false -python-versions = ">=3.8" -files = [ - {file = "flake8_type_checking-2.4.0-py3-none-any.whl", hash = "sha256:2dee127f300bb95b7f17b7c3fff4f6336f5e4ba92082c15928c6e19b666cfba4"}, - {file = "flake8_type_checking-2.4.0.tar.gz", hash = "sha256:9ea96d01e6557a47835acf04020c48fabb9c3d4664c15f2920915e09e65c1d55"}, -] - -[package.dependencies] -classify-imports = "*" -flake8 = "*" - -[[package]] -name = "flakeheaven" -version = "3.3.0" -description = "FlakeHeaven is a [Flake8](https://gitlab.com/pycqa/flake8) wrapper to make it cool." -category = "dev" -optional = false -python-versions = ">=3.7,<4.0" -files = [ - {file = "flakeheaven-3.3.0-py3-none-any.whl", hash = "sha256:ae246197a178845b30b63fc03023f7ba925cc84cc96314ec19807dafcd6b39a3"}, - {file = "flakeheaven-3.3.0.tar.gz", hash = "sha256:eb07860e028ff8dd56cce742c4766624a37a4ce397fd34300254ab623d13047b"}, -] - -[package.dependencies] -colorama = "*" -entrypoints = "*" -flake8 = ">=4.0.1,<5.0.0" -pygments = "*" -toml = "*" -urllib3 = "*" - -[package.extras] -docs = ["alabaster", "myst-parser (>=0.18.0,<0.19.0)", "pygments-github-lexers", "sphinx"] - [[package]] name = "ghp-import" version = "2.1.0" description = "Copy your docs directly to the gh-pages branch." -category = "dev" optional = false python-versions = "*" files = [ @@ -640,7 +473,6 @@ dev = ["flake8", "markdown", "twine", "wheel"] name = "idna" version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -652,7 +484,6 @@ files = [ name = "importlib-metadata" version = "6.0.0" description = "Read metadata from Python packages" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -672,7 +503,6 @@ testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packag name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -684,7 +514,6 @@ files = [ name = "ipdb" version = "0.13.13" description = "IPython-enabled pdb" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -701,7 +530,6 @@ tomli = {version = "*", markers = "python_version > \"3.6\" and python_version < name = "ipython" version = "8.10.0" description = "IPython: Productive Interactive Computing" -category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -736,29 +564,10 @@ qtconsole = ["qtconsole"] test = ["pytest (<7.1)", "pytest-asyncio", "testpath"] test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pandas", "pytest (<7.1)", "pytest-asyncio", "testpath", "trio"] -[[package]] -name = "isort" -version = "5.12.0" -description = "A Python utility / library to sort Python imports." -category = "dev" -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, - {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, -] - -[package.extras] -colors = ["colorama (>=0.4.3)"] -pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] -plugins = ["setuptools"] -requirements-deprecated-finder = ["pip-api", "pipreqs"] - [[package]] name = "jaraco-classes" version = "3.2.3" description = "Utility functions for Python class constructs" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -777,7 +586,6 @@ testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-chec name = "jedi" version = "0.18.2" description = "An autocompletion tool for Python that can be used for text editors." -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -797,7 +605,6 @@ testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] name = "jeepney" version = "0.8.0" description = "Low-level, pure Python DBus protocol wrapper." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -813,7 +620,6 @@ trio = ["async_generator", "trio"] name = "jinja2" version = "3.1.2" description = "A very fast and expressive template engine." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -831,7 +637,6 @@ i18n = ["Babel (>=2.7)"] name = "keyring" version = "24.2.0" description = "Store and access your passwords safely." -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -855,7 +660,6 @@ testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", name = "mako" version = "1.2.4" description = "A super-fast templating language that borrows the best ideas from the existing templating languages." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -875,7 +679,6 @@ testing = ["pytest"] name = "markdown" version = "3.3.7" description = "Python implementation of Markdown." -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -890,7 +693,6 @@ testing = ["coverage", "pyyaml"] name = "markdown-it-py" version = "2.2.0" description = "Python port of markdown-it. Markdown parsing, done right!" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -915,7 +717,6 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] name = "markupsafe" version = "2.1.2" description = "Safely add untrusted strings to HTML/XML markup." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -975,7 +776,6 @@ files = [ name = "matplotlib-inline" version = "0.1.6" description = "Inline Matplotlib backend for Jupyter" -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -986,23 +786,10 @@ files = [ [package.dependencies] traitlets = "*" -[[package]] -name = "mccabe" -version = "0.6.1" -description = "McCabe checker, plugin for flake8" -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, - {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, -] - [[package]] name = "mdurl" version = "0.1.2" description = "Markdown URL utilities" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1014,7 +801,6 @@ files = [ name = "mergedeep" version = "1.3.4" description = "A deep merge function for 🐍." -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1026,7 +812,6 @@ files = [ name = "mkdocs" version = "1.4.3" description = "Project documentation with Markdown." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1054,7 +839,6 @@ min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-imp name = "more-itertools" version = "9.0.0" description = "More routines for operating on iterables, beyond itertools" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1066,7 +850,6 @@ files = [ name = "mypy-extensions" version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." -category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -1078,7 +861,6 @@ files = [ name = "packaging" version = "23.1" description = "Core utilities for Python packages" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1090,11 +872,9 @@ files = [ name = "parse" version = "1.19.0" description = "parse() is the opposite of format()" -category = "dev" optional = false python-versions = "*" files = [ - {file = "parse-1.19.0-py2.py3-none-any.whl", hash = "sha256:6ce007645384a91150cb7cd7c8a9db2559e273c2e2542b508cd1e342508c2601"}, {file = "parse-1.19.0.tar.gz", hash = "sha256:9ff82852bcb65d139813e2a5197627a94966245c897796760a3a2a8eb66f020b"}, ] @@ -1102,7 +882,6 @@ files = [ name = "parse-type" version = "0.6.0" description = "Simplifies to build parse types based on the parse module" -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*" files = [ @@ -1122,7 +901,6 @@ docs = ["sphinx (>=1.2)"] name = "parsedatetime" version = "2.6" description = "Parse human-readable date/time text." -category = "main" optional = false python-versions = "*" files = [ @@ -1134,7 +912,6 @@ files = [ name = "parso" version = "0.8.3" description = "A Python Parser" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1150,7 +927,6 @@ testing = ["docopt", "pytest (<6.0.0)"] name = "pastel" version = "0.2.1" description = "Bring colors to your terminal." -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1162,7 +938,6 @@ files = [ name = "pathspec" version = "0.11.0" description = "Utility library for gitignore style pattern matching of file paths." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1174,7 +949,6 @@ files = [ name = "pexpect" version = "4.8.0" description = "Pexpect allows easy control of interactive console applications." -category = "dev" optional = false python-versions = "*" files = [ @@ -1189,7 +963,6 @@ ptyprocess = ">=0.5" name = "pickleshare" version = "0.7.5" description = "Tiny 'shelve'-like database with concurrency support" -category = "dev" optional = false python-versions = "*" files = [ @@ -1201,7 +974,6 @@ files = [ name = "platformdirs" version = "3.6.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1217,7 +989,6 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest- name = "pluggy" version = "1.0.0" description = "plugin and hook calling mechanisms for python" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1233,7 +1004,6 @@ testing = ["pytest", "pytest-benchmark"] name = "poethepoet" version = "0.20.0" description = "A task runner that works well with poetry." -category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1252,7 +1022,6 @@ poetry-plugin = ["poetry (>=1.0,<2.0)"] name = "pprintpp" version = "0.4.0" description = "A drop-in replacement for pprint that's actually pretty" -category = "dev" optional = false python-versions = "*" files = [ @@ -1264,7 +1033,6 @@ files = [ name = "prompt-toolkit" version = "3.0.37" description = "Library for building powerful interactive command lines in Python" -category = "dev" optional = false python-versions = ">=3.7.0" files = [ @@ -1279,7 +1047,6 @@ wcwidth = "*" name = "ptyprocess" version = "0.7.0" description = "Run a subprocess in a pseudo terminal" -category = "dev" optional = false python-versions = "*" files = [ @@ -1291,7 +1058,6 @@ files = [ name = "pure-eval" version = "0.2.2" description = "Safely evaluate AST nodes without side effects" -category = "dev" optional = false python-versions = "*" files = [ @@ -1302,23 +1068,10 @@ files = [ [package.extras] tests = ["pytest"] -[[package]] -name = "pycodestyle" -version = "2.8.0" -description = "Python style guide checker" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, - {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"}, -] - [[package]] name = "pycparser" version = "2.21" description = "C parser in Python" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1326,23 +1079,10 @@ files = [ {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, ] -[[package]] -name = "pyflakes" -version = "2.4.0" -description = "passive checker of Python programs" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"}, - {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, -] - [[package]] name = "pygments" version = "2.14.0" description = "Pygments is a syntax highlighting package written in Python." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1357,7 +1097,6 @@ plugins = ["importlib-metadata"] name = "pyproject-api" version = "1.5.2" description = "API to interact with the python pyproject.toml based projects" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1377,7 +1116,6 @@ testing = ["covdefaults (>=2.3)", "importlib-metadata (>=6.6)", "pytest (>=7.3.1 name = "pytest" version = "7.4.0" description = "pytest: simple powerful testing with Python" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1400,7 +1138,6 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no name = "pytest-bdd" version = "6.1.1" description = "BDD for pytest" -category = "dev" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -1419,7 +1156,6 @@ typing-extensions = "*" name = "pytest-clarity" version = "1.0.1" description = "A plugin providing an alternative, colourful diff output for failing assertions." -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1435,7 +1171,6 @@ rich = ">=8.0.0" name = "pytest-xdist" version = "3.3.1" description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1456,7 +1191,6 @@ testing = ["filelock"] name = "python-dateutil" version = "2.8.2" description = "Extensions to the standard Python datetime module" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ @@ -1471,7 +1205,6 @@ six = ">=1.5" name = "pywin32-ctypes" version = "0.2.0" description = "" -category = "main" optional = false python-versions = "*" files = [ @@ -1483,7 +1216,6 @@ files = [ name = "pyxdg" version = "0.28" description = "PyXDG contains implementations of freedesktop.org standards in python." -category = "main" optional = false python-versions = "*" files = [ @@ -1495,7 +1227,6 @@ files = [ name = "pyyaml" version = "6.0" description = "YAML parser and emitter for Python" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1545,7 +1276,6 @@ files = [ name = "pyyaml-env-tag" version = "0.1" description = "A custom YAML tag for referencing environment variables in YAML files. " -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1560,7 +1290,6 @@ pyyaml = "*" name = "requests" version = "2.31.0" description = "Python HTTP for Humans." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1582,7 +1311,6 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "rich" version = "13.4.2" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -1601,7 +1329,6 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] name = "ruamel-yaml" version = "0.17.32" description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" -category = "main" optional = false python-versions = ">=3" files = [ @@ -1620,7 +1347,6 @@ jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] name = "ruamel-yaml-clib" version = "0.2.7" description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -1631,8 +1357,7 @@ files = [ {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win32.whl", hash = "sha256:763d65baa3b952479c4e972669f679fe490eee058d5aa85da483ebae2009d231"}, {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:d000f258cf42fec2b1bbf2863c61d7b8918d31ffee905da62dede869254d3b8a"}, {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:045e0626baf1c52e5527bd5db361bc83180faaba2ff586e763d3d5982a876a9e"}, - {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:1a6391a7cabb7641c32517539ca42cf84b87b667bad38b78d4d42dd23e957c81"}, - {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:9c7617df90c1365638916b98cdd9be833d31d337dbcd722485597b43c4a215bf"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_12_6_arm64.whl", hash = "sha256:721bc4ba4525f53f6a611ec0967bdcee61b31df5a56801281027a3a6d1c2daf5"}, {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:41d0f1fa4c6830176eef5b276af04c89320ea616655d01327d5ce65e50575c94"}, {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-win32.whl", hash = "sha256:f6d3d39611ac2e4f62c3128a9eed45f19a6608670c5a2f4f07f24e8de3441d38"}, {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:da538167284de58a52109a9b89b8f6a53ff8437dd6dc26d33b57bf6699153122"}, @@ -1663,11 +1388,36 @@ files = [ {file = "ruamel.yaml.clib-0.2.7.tar.gz", hash = "sha256:1f08fd5a2bea9c4180db71678e850b995d2a5f4537be0e94557668cf0f5f9497"}, ] +[[package]] +name = "ruff" +version = "0.0.276" +description = "An extremely fast Python linter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.0.276-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:c150912b8ebde843c10b33db90705d4fee48db6f05441e5d143be9f4c2f35df5"}, + {file = "ruff-0.0.276-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:5e9cd7238d34f24d7ccfadcce4dc6807b8c5a390f547dd7236d06488d9d6f40f"}, + {file = "ruff-0.0.276-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc7dc557cc3fa2a03a88e99425ceee91429cc7432e5a41087850c1629294faed"}, + {file = "ruff-0.0.276-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:13e5983836ae383c04de213954da731f14ea884aaf74467abc47e1d79d8cf1b7"}, + {file = "ruff-0.0.276-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4ac65df96be3e2f4b10bc97bbb624152281611b06ef1068d5bb064b7ad35d800"}, + {file = "ruff-0.0.276-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d070a64de4affd17e006d6986ef25601dbbc6b373844ece5396c33900f8b8563"}, + {file = "ruff-0.0.276-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2edcd6948a21fa7fb4594094da37a1aa1d205b7abaa718bd27d48ba1d7977348"}, + {file = "ruff-0.0.276-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57c49b525d8ca3838d8b614f42e342077bed95aedd9fe6e6ec419f39320c214e"}, + {file = "ruff-0.0.276-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5980960a748ada3ddfe4ea7ff3a01b9113c456a14cb1a39b4c30783012d4cba6"}, + {file = "ruff-0.0.276-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:12be4f007114cf5ed1242e522762651539521ec32ae0210cc4b8dfe434a872f0"}, + {file = "ruff-0.0.276-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:6ed8fc729b3e7b9f20a4e2aa6f24c798b06912f8a94cb3e8fd590eba055780df"}, + {file = "ruff-0.0.276-py3-none-musllinux_1_2_i686.whl", hash = "sha256:735d724031212c2ab63fafdea49d4581ae866a1180d06c29b0b5481228ca6bb9"}, + {file = "ruff-0.0.276-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:100ad9055d50977c2b4ab3de0db62d6e525bcd4aafbb660a842733bdbf650be9"}, + {file = "ruff-0.0.276-py3-none-win32.whl", hash = "sha256:1b34a3673b2e5d97df8f7f04090c0b74e9ae6d3d172921d0e0781192954afddf"}, + {file = "ruff-0.0.276-py3-none-win_amd64.whl", hash = "sha256:02deadc0f6abead6cc2d38ddd7100a52aba27a0d90315facaa44b8b4acdba162"}, + {file = "ruff-0.0.276-py3-none-win_arm64.whl", hash = "sha256:a6bd5b53ac689a43c7afc45bd574a7b3efe0ceb192e26e95a055c770ef2045b9"}, + {file = "ruff-0.0.276.tar.gz", hash = "sha256:d456c86eb6ce9225507f24fcc7bf72fa031bb7cc750023310e62889bf4ad4b6a"}, +] + [[package]] name = "secretstorage" version = "3.3.3" description = "Python bindings to FreeDesktop.org Secret Service API" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1683,7 +1433,6 @@ jeepney = ">=0.6" name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -1695,7 +1444,6 @@ files = [ name = "stack-data" version = "0.6.2" description = "Extract data from python stack frames and tracebacks for informative displays" -category = "dev" optional = false python-versions = "*" files = [ @@ -1715,7 +1463,6 @@ tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] name = "textwrap3" version = "0.9.2" description = "textwrap from Python 3.6 backport (plus a few tweaks)" -category = "main" optional = false python-versions = "*" files = [ @@ -1727,7 +1474,6 @@ files = [ name = "toml" version = "0.10.2" description = "Python Library for Tom's Obvious, Minimal Language" -category = "dev" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -1739,7 +1485,6 @@ files = [ name = "tomli" version = "2.0.1" description = "A lil' TOML parser" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1751,7 +1496,6 @@ files = [ name = "tox" version = "4.6.3" description = "tox is a generic virtualenv management and test command line tool" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1779,7 +1523,6 @@ testing = ["build[virtualenv] (>=0.10)", "covdefaults (>=2.3)", "detect-test-pol name = "traitlets" version = "5.9.0" description = "Traitlets Python configuration system" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1795,7 +1538,6 @@ test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"] name = "typing-extensions" version = "4.5.0" description = "Backported and Experimental Type Hints for Python 3.7+" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1807,7 +1549,6 @@ files = [ name = "tzdata" version = "2022.7" description = "Provider of IANA time zone data" -category = "main" optional = false python-versions = ">=2" files = [ @@ -1819,7 +1560,6 @@ files = [ name = "tzlocal" version = "5.0.1" description = "tzinfo object for the local timezone" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1837,7 +1577,6 @@ devenv = ["black", "check-manifest", "flake8", "pyroma", "pytest (>=4.3)", "pyte name = "urllib3" version = "1.26.14" description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ @@ -1854,7 +1593,6 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] name = "virtualenv" version = "20.23.1" description = "Virtual Python Environment builder" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1875,7 +1613,6 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess name = "watchdog" version = "2.3.0" description = "Filesystem events monitoring" -category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -1916,7 +1653,6 @@ watchmedo = ["PyYAML (>=3.10)"] name = "wcwidth" version = "0.2.6" description = "Measures the displayed width of unicode strings in a terminal" -category = "dev" optional = false python-versions = "*" files = [ @@ -1928,7 +1664,6 @@ files = [ name = "xmltodict" version = "0.13.0" description = "Makes working with XML feel like you are working with JSON" -category = "dev" optional = false python-versions = ">=3.4" files = [ @@ -1940,7 +1675,6 @@ files = [ name = "zipp" version = "3.14.0" description = "Backport of pathlib-compatible object wrapper for zip files" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1955,4 +1689,4 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools" [metadata] lock-version = "2.0" python-versions = ">=3.10.0, <3.13" -content-hash = "037329f79e6d33799cf05f4c71e15ea17368143eeb5e31adf59325c44e46fb45" +content-hash = "fe86fc1b8b2f74aba939a019b87fbe33fec5853c40b60a596ce8467a97de0045" diff --git a/pyproject.toml b/pyproject.toml index 1d5744285..3f9b83701 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,13 +44,7 @@ tzlocal = ">=4.0" # https://github.com/regebro/tzlocal/blob/master/CHANGES.txt [tool.poetry.dev-dependencies] black = { version = ">=21.5b2", allow-prereleases = true } -flakeheaven = ">=3.0" -flake8-black = ">=0.3.3" -flake8-isort = ">=5.0.0" -flake8-type-checking = ">=2.2.0" -flake8-simplify = ">=0.19" ipdb = "*" -isort = ">=5.10" mkdocs = ">=1.4" parse-type = ">=0.6.0" poethepoet = "*" @@ -59,6 +53,7 @@ pytest-bdd = ">=6.0" pytest-clarity = "*" pytest-xdist = ">=2.5.0" requests = "*" +ruff = ">=0.0.276" toml = ">=0.10" tox = "*" xmltodict = "*" @@ -88,18 +83,18 @@ test-run = [ # Groups of tasks format.default_item_type = "cmd" format.sequence = [ - "isort .", + "ruff check . --select I --fix", # equivalent to "isort ." "black .", ] -lint.env = { FLAKEHEAVEN_CACHE_TIMEOUT = "0" } lint.default_item_type = "cmd" lint.sequence = [ "poetry --version", "poetry check", - "flakeheaven --version", - "flakeheaven plugins", - "flakeheaven lint", + "ruff --version", + "ruff .", + "black --version", + "black --check ." ] test = [ @@ -107,11 +102,6 @@ test = [ "test-run", ] -[tool.isort] -profile = "black" -force_single_line = true -known_first_party = ["jrnl", "tests"] - [tool.pytest.ini_options] minversion = "6.0" required_plugins = [ @@ -137,29 +127,35 @@ filterwarnings = [ "ignore:[WinError 5].*" ] -[tool.flakeheaven] -max_line_length = 88 +[tool.ruff] +line-length = 88 + +# https://beta.ruff.rs/docs/rules/ +select = [ + 'F', # Pyflakes + 'E', # pycodestyle errors + 'W', # pycodestyle warnings + 'I', # isort + 'ASYNC', # flake8-async + 'S110', # try-except-pass + 'S112', # try-except-continue + 'EM', # flake8-errmsg + 'ISC', # flake8-implicit-str-concat + 'Q', # flake8-quotes + 'RSE', # flake8-raise + 'TID', # flake8-tidy-imports + 'TCH', # flake8-type-checking + 'T100', # debugger, don't allow break points + 'ICN' # flake8-import-conventions +] exclude = [".git", ".tox", ".venv", "node_modules"] -[tool.flakeheaven.plugins] -"py*" = ["+*"] -pycodestyle = [ - "-E101", - "-E111", "-E114", "-E115", "-E116", "-E117", - "-E12*", - "-E13*", - "-E2*", - "-E3*", - "-E401", - "-E5*", - "-E70", - "-W1*", "-W2*", "-W3*", "-W5*", -] -"flake8-*" = ["+*"] -flake8-black = ["-BLK901"] +[tool.ruff.isort] +force-single-line = true +known-first-party = ["jrnl", "tests"] -[tool.flakeheaven.exceptions."jrnl/journals/__init__.py"] -pyflakes = ["-F401"] +[tool.ruff.per-file-ignores] +"__init__.py" = ["F401"] # unused imports [build-system] requires = ["poetry-core>=1.0.0"] diff --git a/tests/lib/then_steps.py b/tests/lib/then_steps.py index 5ec75ad5b..7216a23fd 100644 --- a/tests/lib/then_steps.py +++ b/tests/lib/then_steps.py @@ -38,38 +38,41 @@ def output_should_match(regex, cli_run): assert matches, f"\nRegex didn't match:\n{regex}\n{str(out)}\n{str(matches)}" -@then(parse("the output {it_should:Should} contain\n{expected_output}", SHOULD_DICT)) -@then(parse('the output {it_should:Should} contain "{expected_output}"', SHOULD_DICT)) +@then(parse("the output {it_should:Should} contain\n{expected}", SHOULD_DICT)) +@then(parse('the output {it_should:Should} contain "{expected}"', SHOULD_DICT)) @then( parse( - "the {which_output_stream} output {it_should:Should} contain\n{expected_output}", + "the {which_output_stream} output {it_should:Should} contain\n{expected}", SHOULD_DICT, ) ) @then( parse( - 'the {which_output_stream} output {it_should:Should} contain "{expected_output}"', + 'the {which_output_stream} output {it_should:Should} contain "{expected}"', SHOULD_DICT, ) ) -def output_should_contain(expected_output, which_output_stream, cli_run, it_should): - output_str = f"\nEXPECTED:\n{expected_output}\n\nACTUAL STDOUT:\n{cli_run['stdout']}\n\nACTUAL STDERR:\n{cli_run['stderr']}" - assert expected_output +def output_should_contain(expected, which_output_stream, cli_run, it_should): + output_str = ( + f"\nEXPECTED:\n{expected}\n\n" + f"ACTUAL STDOUT:\n{cli_run['stdout']}\n\n" + f"ACTUAL STDERR:\n{cli_run['stderr']}" + ) + + assert expected if which_output_stream is None: - assert ((expected_output in cli_run["stdout"]) == it_should) or ( - (expected_output in cli_run["stderr"]) == it_should + assert ((expected in cli_run["stdout"]) == it_should) or ( + (expected in cli_run["stderr"]) == it_should ), output_str elif which_output_stream == "standard": - assert (expected_output in cli_run["stdout"]) == it_should, output_str + assert (expected in cli_run["stdout"]) == it_should, output_str elif which_output_stream == "error": - assert (expected_output in cli_run["stderr"]) == it_should, output_str + assert (expected in cli_run["stderr"]) == it_should, output_str else: - assert ( - expected_output in cli_run[which_output_stream] - ) == it_should, output_str + assert (expected in cli_run[which_output_stream]) == it_should, output_str @then(parse("the output should not contain\n{expected_output}")) @@ -119,7 +122,8 @@ def output_should_be_columns_wide(cli_run, width): @then( parse( - 'the default journal "{journal_file}" should be in the "{journal_dir}" directory' + 'the default journal "{journal_file}" ' + 'should be in the "{journal_dir}" directory' ) ) def default_journal_location(journal_file, journal_dir, config_on_disk, temp_dir): @@ -135,13 +139,15 @@ def default_journal_location(journal_file, journal_dir, config_on_disk, temp_dir @then( parse( - 'the config for journal "{journal_name}" {it_should:Should} contain "{some_yaml}"', + 'the config for journal "{journal_name}" ' + '{it_should:Should} contain "{some_yaml}"', SHOULD_DICT, ) ) @then( parse( - 'the config for journal "{journal_name}" {it_should:Should} contain\n{some_yaml}', + 'the config for journal "{journal_name}" ' + "{it_should:Should} contain\n{some_yaml}", SHOULD_DICT, ) ) @@ -164,13 +170,15 @@ def config_var_on_disk(config_on_disk, journal_name, it_should, some_yaml): @then( parse( - 'the config in memory for journal "{journal_name}" {it_should:Should} contain "{some_yaml}"', + 'the config in memory for journal "{journal_name}" ' + '{it_should:Should} contain "{some_yaml}"', SHOULD_DICT, ) ) @then( parse( - 'the config in memory for journal "{journal_name}" {it_should:Should} contain\n{some_yaml}', + 'the config in memory for journal "{journal_name}" ' + "{it_should:Should} contain\n{some_yaml}", SHOULD_DICT, ) ) diff --git a/tests/unit/test_parse_args.py b/tests/unit/test_parse_args.py index fd1d0844a..e30360201 100644 --- a/tests/unit/test_parse_args.py +++ b/tests/unit/test_parse_args.py @@ -242,7 +242,9 @@ def test_color_override(): def test_multiple_overrides(): parsed_args = cli_as_dict( - '--config-override colors.title green --config-override editor "nano" --config-override journal.scratchpad "/tmp/scratchpad"' + "--config-override colors.title green " + '--config-override editor "nano" ' + '--config-override journal.scratchpad "/tmp/scratchpad"' ) assert parsed_args == expected_args( config_override=[