prompt: TSQL - L031 incorrectly triggers "Avoid using aliases in join condition" when no join present
  ## Expected Behaviour
  
  Both of these queries should pass, the only difference is the addition of a table alias 'a':
  
  1/ no alias
  
  ```
  SELECT [hello]
  FROM
      mytable
  ```
  
  2/ same query with alias
  
  ```
  SELECT a.[hello]
  FROM
      mytable AS a
  ```
  
  ## Observed Behaviour
  
  1/ passes
  2/ fails with: L031: Avoid using aliases in join condition.
  
  But there is no join condition :-)
  
  ## Steps to Reproduce
  
  Lint queries above
  
  ## Dialect
  
  TSQL
  
  ## Version
  
  sqlfluff 0.6.9
  Python 3.6.9
  
  ## Configuration
  
  N/A
  
instance: {"FAIL_TO_PASS": "[\"test/cli/commands_test.py::test__cli__command_directed\"]", "PASS_TO_PASS": "[\"test/cli/commands_test.py::test__cli__command_dialect\", \"test/cli/commands_test.py::test__cli__command_dialect_legacy\", \"test/cli/commands_test.py::test__cli__command_lint_stdin[command0]\", \"test/cli/commands_test.py::test__cli__command_lint_stdin[command1]\", \"test/cli/commands_test.py::test__cli__command_lint_stdin[command2]\", \"test/cli/commands_test.py::test__cli__command_lint_stdin[command3]\", \"test/cli/commands_test.py::test__cli__command_lint_parse[command0]\", \"test/cli/commands_test.py::test__cli__command_lint_parse[command1]\", \"test/cli/commands_test.py::test__cli__command_lint_parse[command2]\", \"test/cli/commands_test.py::test__cli__command_lint_parse[command3]\", \"test/cli/commands_test.py::test__cli__command_lint_parse[command4]\", \"test/cli/commands_test.py::test__cli__command_lint_parse[command5]\", \"test/cli/commands_test.py::test__cli__command_lint_parse[command6]\", \"test/cli/commands_test.py::test__cli__command_lint_parse[command7]\", \"test/cli/commands_test.py::test__cli__command_lint_parse[command8]\", \"test/cli/commands_test.py::test__cli__command_lint_parse[command9]\", \"test/cli/commands_test.py::test__cli__command_lint_parse[command10]\", \"test/cli/commands_test.py::test__cli__command_lint_parse[command11]\", \"test/cli/commands_test.py::test__cli__command_lint_parse[command12]\", \"test/cli/commands_test.py::test__cli__command_lint_parse[command13]\", \"test/cli/commands_test.py::test__cli__command_lint_parse[command14]\", \"test/cli/commands_test.py::test__cli__command_lint_parse[command15]\", \"test/cli/commands_test.py::test__cli__command_lint_parse[command16]\", \"test/cli/commands_test.py::test__cli__command_lint_parse[command17]\", \"test/cli/commands_test.py::test__cli__command_lint_parse[command18]\", \"test/cli/commands_test.py::test__cli__command_lint_parse[command19]\", \"test/cli/commands_test.py::test__cli__command_lint_parse[command20]\", \"test/cli/commands_test.py::test__cli__command_lint_parse[command21]\", \"test/cli/commands_test.py::test__cli__command_lint_parse_with_retcode[command0-1]\", \"test/cli/commands_test.py::test__cli__command_lint_parse_with_retcode[command1-1]\", \"test/cli/commands_test.py::test__cli__command_lint_parse_with_retcode[command2-1]\", \"test/cli/commands_test.py::test__cli__command_lint_warning_explicit_file_ignored\", \"test/cli/commands_test.py::test__cli__command_lint_skip_ignore_files\", \"test/cli/commands_test.py::test__cli__command_versioning\", \"test/cli/commands_test.py::test__cli__command_version\", \"test/cli/commands_test.py::test__cli__command_rules\", \"test/cli/commands_test.py::test__cli__command_dialects\", \"test/cli/commands_test.py::test__cli__command__fix[L001-test/fixtures/linter/indentation_errors.sql]\", \"test/cli/commands_test.py::test__cli__command__fix[L008-test/fixtures/linter/whitespace_errors.sql]\", \"test/cli/commands_test.py::test__cli__command__fix[L008-test/fixtures/linter/indentation_errors.sql]\", \"test/cli/commands_test.py::test__cli__command__fix[L003-test/fixtures/linter/indentation_error_hard.sql]\", \"test/cli/commands_test.py::test__cli__command_fix_stdin[select\", \"test/cli/commands_test.py::test__cli__command_fix_stdin[\", \"test/cli/commands_test.py::test__cli__command_fix_stdin[SELECT\", \"test/cli/commands_test.py::test__cli__command_fix_stdin_logging_to_stderr\", \"test/cli/commands_test.py::test__cli__command_fix_stdin_safety\", \"test/cli/commands_test.py::test__cli__command_fix_stdin_error_exit_code[create\", \"test/cli/commands_test.py::test__cli__command_fix_stdin_error_exit_code[select\", \"test/cli/commands_test.py::test__cli__command__fix_no_force[L001-test/fixtures/linter/indentation_errors.sql-y-0-0]\", \"test/cli/commands_test.py::test__cli__command__fix_no_force[L001-test/fixtures/linter/indentation_errors.sql-n-65-1]\", \"test/cli/commands_test.py::test__cli__command_parse_serialize_from_stdin[yaml]\", \"test/cli/commands_test.py::test__cli__command_parse_serialize_from_stdin[json]\", \"test/cli/commands_test.py::test__cli__command_lint_serialize_from_stdin[select\", \"test/cli/commands_test.py::test__cli__command_lint_serialize_from_stdin[SElect\", \"test/cli/commands_test.py::test__cli__command_fail_nice_not_found[command0]\", \"test/cli/commands_test.py::test__cli__command_fail_nice_not_found[command1]\", \"test/cli/commands_test.py::test__cli__command_lint_serialize_multiple_files[yaml]\", \"test/cli/commands_test.py::test__cli__command_lint_serialize_multiple_files[json]\", \"test/cli/commands_test.py::test__cli__command_lint_serialize_multiple_files[github-annotation]\", \"test/cli/commands_test.py::test__cli__command_lint_serialize_github_annotation\", \"test/cli/commands_test.py::test___main___help\", \"test/cli/commands_test.py::test_encoding[utf-8-ascii]\", \"test/cli/commands_test.py::test_encoding[utf-8-sig-UTF-8-SIG]\", \"test/cli/commands_test.py::test_encoding[utf-32-UTF-32]\"]", "base_commit": "14e1a23a3166b9a645a16de96f694c77a5d4abb7", "created_at": "2021-10-13T11:35:29Z", "environment_setup_commit": "67023b85c41d23d6c6d69812a41b207c4f8a9331", "hints_text": "Actually, re-reading the docs I think this is the intended behaviour... closing", "instance_id": "sqlfluff__sqlfluff-1625", "patch": "diff --git a/src/sqlfluff/rules/L031.py b/src/sqlfluff/rules/L031.py\n--- a/src/sqlfluff/rules/L031.py\n+++ b/src/sqlfluff/rules/L031.py\n@@ -211,7 +211,7 @@ def _lint_aliases_in_join(\n             violation_buff.append(\n                 LintResult(\n                     anchor=alias_info.alias_identifier_ref,\n-                    description=\"Avoid using aliases in join condition\",\n+                    description=\"Avoid aliases in from clauses and join conditions.\",\n                     fixes=fixes,\n                 )\n             )\n", "problem_statement": "TSQL - L031 incorrectly triggers \"Avoid using aliases in join condition\" when no join present\n## Expected Behaviour\r\n\r\nBoth of these queries should pass, the only difference is the addition of a table alias 'a':\r\n\r\n1/ no alias\r\n\r\n```\r\nSELECT [hello]\r\nFROM\r\n    mytable\r\n```\r\n\r\n2/ same query with alias\r\n\r\n```\r\nSELECT a.[hello]\r\nFROM\r\n    mytable AS a\r\n```\r\n\r\n## Observed Behaviour\r\n\r\n1/ passes\r\n2/ fails with: L031: Avoid using aliases in join condition.\r\n\r\nBut there is no join condition :-)\r\n\r\n## Steps to Reproduce\r\n\r\nLint queries above\r\n\r\n## Dialect\r\n\r\nTSQL\r\n\r\n## Version\r\n\r\nsqlfluff 0.6.9\r\nPython 3.6.9\r\n\r\n## Configuration\r\n\r\nN/A\n", "repo": "sqlfluff/sqlfluff", "test_patch": "diff --git a/test/cli/commands_test.py b/test/cli/commands_test.py\n--- a/test/cli/commands_test.py\n+++ b/test/cli/commands_test.py\n@@ -49,7 +49,7 @@ def invoke_assert_code(\n expected_output = \"\"\"== [test/fixtures/linter/indentation_error_simple.sql] FAIL\n L:   2 | P:   4 | L003 | Indentation not hanging or a multiple of 4 spaces\n L:   5 | P:  10 | L010 | Keywords must be consistently upper case.\n-L:   5 | P:  13 | L031 | Avoid using aliases in join condition\n+L:   5 | P:  13 | L031 | Avoid aliases in from clauses and join conditions.\n \"\"\"\n \n \n", "version": "0.6"}
parsed_commit_content: {"file_diffs":[{"old_file_content":"\"\"\"Implementation of Rule L031.\"\"\"\n\nfrom collections import Counter, defaultdict\nfrom typing import Generator, NamedTuple\n\nfrom sqlfluff.core.parser import BaseSegment\nfrom sqlfluff.core.rules.base import BaseRule, LintFix, LintResult\nfrom sqlfluff.core.rules.doc_decorators import document_fix_compatible\n\n\n@document_fix_compatible\nclass Rule_L031(BaseRule):\n    \"\"\"Avoid table aliases in from clauses and join conditions.\n\n    | **Anti-pattern**\n    | In this example, alias 'o' is used for the orders table, and 'c' is used for 'customers' table.\n\n    .. code-block:: sql\n\n        SELECT\n            COUNT(o.customer_id) as order_amount,\n            c.name\n        FROM orders as o\n        JOIN customers as c on o.id = c.user_id\n\n\n    | **Best practice**\n    |  Avoid aliases.\n\n    .. code-block:: sql\n\n        SELECT\n            COUNT(orders.customer_id) as order_amount,\n            customers.name\n        FROM orders\n        JOIN customers on orders.id = customers.user_id\n\n        -- Self-join will not raise issue\n\n        SELECT\n            table.a,\n            table_alias.b,\n        FROM\n            table\n            LEFT JOIN table AS table_alias ON table.foreign_key = table_alias.foreign_key\n\n    \"\"\"\n\n    def _eval(self, segment, **kwargs):\n        \"\"\"Identify aliases in from clause and join conditions.\n\n        Find base table, table expressions in join, and other expressions in select clause\n        and decide if it's needed to report them.\n        \"\"\"\n        if segment.is_type(\"select_statement\"):\n            # A buffer for all table expressions in join conditions\n            from_expression_elements = []\n            column_reference_segments = []\n\n            from_clause_segment = segment.get_child(\"from_clause\")\n\n            if not from_clause_segment:\n                return None\n\n            from_expression = from_clause_segment.get_child(\"from_expression\")\n            from_expression_element = None\n            if from_expression:\n                from_expression_element = from_expression.get_child(\n                    \"from_expression_element\"\n                )\n\n            if not from_expression_element:\n                return None\n            from_expression_element = from_expression_element.get_child(\n                \"table_expression\"\n            )\n\n            # Find base table\n            base_table = None\n            if from_expression_element:\n                base_table = from_expression_element.get_child(\"object_reference\")\n\n            from_clause_index = segment.segments.index(from_clause_segment)\n            from_clause_and_after = segment.segments[from_clause_index:]\n\n            for clause in from_clause_and_after:\n                for from_expression_element in clause.recursive_crawl(\n                    \"from_expression_element\"\n                ):\n                    from_expression_elements.append(from_expression_element)\n                for column_reference in clause.recursive_crawl(\"column_reference\"):\n                    column_reference_segments.append(column_reference)\n\n            return (\n                self._lint_aliases_in_join(\n                    base_table,\n                    from_expression_elements,\n                    column_reference_segments,\n                    segment,\n                )\n                or None\n            )\n        return None\n\n    class TableAliasInfo(NamedTuple):\n        \"\"\"Structure yielded by_filter_table_expressions().\"\"\"\n\n        table_ref: BaseSegment\n        whitespace_ref: BaseSegment\n        alias_exp_ref: BaseSegment\n        alias_identifier_ref: BaseSegment\n\n    @classmethod\n    def _filter_table_expressions(\n        cls, base_table, from_expression_elements\n    ) -> Generator[TableAliasInfo, None, None]:\n        for from_expression in from_expression_elements:\n            table_expression = from_expression.get_child(\"table_expression\")\n            if not table_expression:\n                continue\n            table_ref = table_expression.get_child(\"object_reference\")\n\n            # If the from_expression_element has no object_references - skip it\n            # An example case is a lateral flatten, where we have a function segment\n            # instead of a table_reference segment.\n            if not table_ref:\n                continue\n\n            # If this is self-join - skip it\n            if (\n                base_table\n                and base_table.raw == table_ref.raw\n                and base_table != table_ref\n            ):\n                continue\n\n            whitespace_ref = from_expression.get_child(\"whitespace\")\n\n            # If there's no alias expression - skip it\n            alias_exp_ref = from_expression.get_child(\"alias_expression\")\n            if alias_exp_ref is None:\n                continue\n\n            alias_identifier_ref = alias_exp_ref.get_child(\"identifier\")\n            yield cls.TableAliasInfo(\n                table_ref, whitespace_ref, alias_exp_ref, alias_identifier_ref\n            )\n\n    def _lint_aliases_in_join(\n        self, base_table, from_expression_elements, column_reference_segments, segment\n    ):\n        \"\"\"Lint and fix all aliases in joins - except for self-joins.\"\"\"\n        # A buffer to keep any violations.\n        violation_buff = []\n\n        to_check = list(\n            self._filter_table_expressions(base_table, from_expression_elements)\n        )\n\n        # How many times does each table appear in the FROM clause?\n        table_counts = Counter(ai.table_ref.raw for ai in to_check)\n\n        # What is the set of aliases used for each table? (We are mainly\n        # interested in the NUMBER of different aliases used.)\n        table_aliases = defaultdict(set)\n        for ai in to_check:\n            table_aliases[ai.table_ref.raw].add(ai.alias_identifier_ref.raw)\n\n        # For each aliased table, check whether to keep or remove it.\n        for alias_info in to_check:\n            # If the same table appears more than once in the FROM clause with\n            # different alias names, do not consider removing its aliases.\n            # The aliases may have been introduced simply to make each\n            # occurrence of the table independent within the query.\n            if (\n                table_counts[alias_info.table_ref.raw] > 1\n                and len(table_aliases[alias_info.table_ref.raw]) > 1\n            ):\n                continue\n\n            select_clause = segment.get_child(\"select_clause\")\n\n            ids_refs = []\n\n            # Find all references to alias in select clause\n            alias_name = alias_info.alias_identifier_ref.raw\n            for alias_with_column in select_clause.recursive_crawl(\"object_reference\"):\n                used_alias_ref = alias_with_column.get_child(\"identifier\")\n                if used_alias_ref and used_alias_ref.raw == alias_name:\n                    ids_refs.append(used_alias_ref)\n\n            # Find all references to alias in column references\n            for exp_ref in column_reference_segments:\n                used_alias_ref = exp_ref.get_child(\"identifier\")\n                # exp_ref.get_child('dot') ensures that the column reference includes a table reference\n                if used_alias_ref.raw == alias_name and exp_ref.get_child(\"dot\"):\n                    ids_refs.append(used_alias_ref)\n\n            # Fixes for deleting ` as sth` and for editing references to aliased tables\n            fixes = [\n                *[\n                    LintFix(\"delete\", d)\n                    for d in [alias_info.alias_exp_ref, alias_info.whitespace_ref]\n                ],\n                *[\n                    LintFix(\"edit\", alias, alias.edit(alias_info.table_ref.raw))\n                    for alias in [alias_info.alias_identifier_ref, *ids_refs]\n                ],\n            ]\n\n            violation_buff.append(\n                LintResult(\n                    anchor=alias_info.alias_identifier_ref,\n                    description=\"Avoid using aliases in join condition\",\n                    fixes=fixes,\n                )\n            )\n\n        return violation_buff or None\n","new_file_content":"\"\"\"Implementation of Rule L031.\"\"\"\n\nfrom collections import Counter, defaultdict\nfrom typing import Generator, NamedTuple, Optional\n\nfrom sqlfluff.core.parser import BaseSegment\nfrom sqlfluff.core.rules.base import BaseRule, LintFix, LintResult, RuleContext\nfrom sqlfluff.core.rules.doc_decorators import document_fix_compatible\n\n\n@document_fix_compatible\nclass Rule_L031(BaseRule):\n    \"\"\"Avoid table aliases in from clauses and join conditions.\n\n    | **Anti-pattern**\n    | In this example, alias 'o' is used for the orders table, and 'c' is used for 'customers' table.\n\n    .. code-block:: sql\n\n        SELECT\n            COUNT(o.customer_id) as order_amount,\n            c.name\n        FROM orders as o\n        JOIN customers as c on o.id = c.user_id\n\n\n    | **Best practice**\n    |  Avoid aliases.\n\n    .. code-block:: sql\n\n        SELECT\n            COUNT(orders.customer_id) as order_amount,\n            customers.name\n        FROM orders\n        JOIN customers on orders.id = customers.user_id\n\n        -- Self-join will not raise issue\n\n        SELECT\n            table.a,\n            table_alias.b,\n        FROM\n            table\n            LEFT JOIN table AS table_alias ON table.foreign_key = table_alias.foreign_key\n\n    \"\"\"\n\n    def _eval(self, context: RuleContext) -> Optional[LintResult]:\n        \"\"\"Identify aliases in from clause and join conditions.\n\n        Find base table, table expressions in join, and other expressions in select clause\n        and decide if it's needed to report them.\n        \"\"\"\n        if context.segment.is_type(\"select_statement\"):\n            # A buffer for all table expressions in join conditions\n            from_expression_elements = []\n            column_reference_segments = []\n\n            from_clause_segment = context.segment.get_child(\"from_clause\")\n\n            if not from_clause_segment:\n                return None\n\n            from_expression = from_clause_segment.get_child(\"from_expression\")\n            from_expression_element = None\n            if from_expression:\n                from_expression_element = from_expression.get_child(\n                    \"from_expression_element\"\n                )\n\n            if not from_expression_element:\n                return None\n            from_expression_element = from_expression_element.get_child(\n                \"table_expression\"\n            )\n\n            # Find base table\n            base_table = None\n            if from_expression_element:\n                base_table = from_expression_element.get_child(\"object_reference\")\n\n            from_clause_index = context.segment.segments.index(from_clause_segment)\n            from_clause_and_after = context.segment.segments[from_clause_index:]\n\n            for clause in from_clause_and_after:\n                for from_expression_element in clause.recursive_crawl(\n                    \"from_expression_element\"\n                ):\n                    from_expression_elements.append(from_expression_element)\n                for column_reference in clause.recursive_crawl(\"column_reference\"):\n                    column_reference_segments.append(column_reference)\n\n            return (\n                self._lint_aliases_in_join(\n                    base_table,\n                    from_expression_elements,\n                    column_reference_segments,\n                    context.segment,\n                )\n                or None\n            )\n        return None\n\n    class TableAliasInfo(NamedTuple):\n        \"\"\"Structure yielded by_filter_table_expressions().\"\"\"\n\n        table_ref: BaseSegment\n        whitespace_ref: BaseSegment\n        alias_exp_ref: BaseSegment\n        alias_identifier_ref: BaseSegment\n\n    @classmethod\n    def _filter_table_expressions(\n        cls, base_table, from_expression_elements\n    ) -> Generator[TableAliasInfo, None, None]:\n        for from_expression in from_expression_elements:\n            table_expression = from_expression.get_child(\"table_expression\")\n            if not table_expression:\n                continue\n            table_ref = table_expression.get_child(\"object_reference\")\n\n            # If the from_expression_element has no object_references - skip it\n            # An example case is a lateral flatten, where we have a function segment\n            # instead of a table_reference segment.\n            if not table_ref:\n                continue\n\n            # If this is self-join - skip it\n            if (\n                base_table\n                and base_table.raw == table_ref.raw\n                and base_table != table_ref\n            ):\n                continue\n\n            whitespace_ref = from_expression.get_child(\"whitespace\")\n\n            # If there's no alias expression - skip it\n            alias_exp_ref = from_expression.get_child(\"alias_expression\")\n            if alias_exp_ref is None:\n                continue\n\n            alias_identifier_ref = alias_exp_ref.get_child(\"identifier\")\n            yield cls.TableAliasInfo(\n                table_ref, whitespace_ref, alias_exp_ref, alias_identifier_ref\n            )\n\n    def _lint_aliases_in_join(\n        self, base_table, from_expression_elements, column_reference_segments, segment\n    ):\n        \"\"\"Lint and fix all aliases in joins - except for self-joins.\"\"\"\n        # A buffer to keep any violations.\n        violation_buff = []\n\n        to_check = list(\n            self._filter_table_expressions(base_table, from_expression_elements)\n        )\n\n        # How many times does each table appear in the FROM clause?\n        table_counts = Counter(ai.table_ref.raw for ai in to_check)\n\n        # What is the set of aliases used for each table? (We are mainly\n        # interested in the NUMBER of different aliases used.)\n        table_aliases = defaultdict(set)\n        for ai in to_check:\n            table_aliases[ai.table_ref.raw].add(ai.alias_identifier_ref.raw)\n\n        # For each aliased table, check whether to keep or remove it.\n        for alias_info in to_check:\n            # If the same table appears more than once in the FROM clause with\n            # different alias names, do not consider removing its aliases.\n            # The aliases may have been introduced simply to make each\n            # occurrence of the table independent within the query.\n            if (\n                table_counts[alias_info.table_ref.raw] > 1\n                and len(table_aliases[alias_info.table_ref.raw]) > 1\n            ):\n                continue\n\n            select_clause = segment.get_child(\"select_clause\")\n\n            ids_refs = []\n\n            # Find all references to alias in select clause\n            alias_name = alias_info.alias_identifier_ref.raw\n            for alias_with_column in select_clause.recursive_crawl(\"object_reference\"):\n                used_alias_ref = alias_with_column.get_child(\"identifier\")\n                if used_alias_ref and used_alias_ref.raw == alias_name:\n                    ids_refs.append(used_alias_ref)\n\n            # Find all references to alias in column references\n            for exp_ref in column_reference_segments:\n                used_alias_ref = exp_ref.get_child(\"identifier\")\n                # exp_ref.get_child('dot') ensures that the column reference includes a table reference\n                if (\n                    used_alias_ref\n                    and used_alias_ref.raw == alias_name\n                    and exp_ref.get_child(\"dot\")\n                ):\n                    ids_refs.append(used_alias_ref)\n\n            # Fixes for deleting ` as sth` and for editing references to aliased tables\n            fixes = [\n                *[\n                    LintFix(\"delete\", d)\n                    for d in [alias_info.alias_exp_ref, alias_info.whitespace_ref]\n                ],\n                *[\n                    LintFix(\"edit\", alias, alias.edit(alias_info.table_ref.raw))\n                    for alias in [alias_info.alias_identifier_ref, *ids_refs]\n                ],\n            ]\n\n            violation_buff.append(\n                LintResult(\n                    anchor=alias_info.alias_identifier_ref,\n                    description=\"Avoid aliases in from clauses and join conditions.\",\n                    fixes=fixes,\n                )\n            )\n\n        return violation_buff or None\n","header":{"file":{"path":"src/sqlfluff/rules/L031.py"},"misc_line":null},"index_line":null,"is_binary_file":false,"binary_line":null,"minus_file":{"path":"a/src/sqlfluff/rules/L031.py"},"plus_file":{"path":"b/src/sqlfluff/rules/L031.py"},"hunks":[{"descriptor":{"old_range":{"start":211,"length":7},"new_range":{"start":211,"length":7},"section":"def _lint_aliases_in_join("},"line_group":{"all_lines":[{"content":"            violation_buff.append(","type":"context"},{"content":"                LintResult(","type":"context"},{"content":"                    anchor=alias_info.alias_identifier_ref,","type":"context"},{"content":"                    description=\"Avoid using aliases in join condition\",","type":"deleted"},{"content":"                    description=\"Avoid aliases in from clauses and join conditions.\",","type":"added"},{"content":"                    fixes=fixes,","type":"context"},{"content":"                )","type":"context"},{"content":"            )","type":"context"},{"content":"","type":"context"}]},"modified_entities":[],"added_entities":[],"deleted_entities":[]}]}],"old_commit_hash":"14e1a23a3166b9a645a16de96f694c77a5d4abb7","new_commit_hash":"e3fb8535acf3cdded95476fbfc723a8359550d94","commit_message":"Ensure the temporary file is written to disk before using it","commit_date":"2021-10-26T18:45:50-04:00","metadata":{}}