# Path: pytablewriter/sanitizer/_python.py
# def sanitize_python_var_name(var_name: str, replacement_text: str = "") -> str:
#     """
#     Make a valid Python variable name from ``var_name``.
# 
#     To make a valid name:
# 
#     - Replace invalid characters for a Python variable name within
#       the ``var_name`` with the ``replacement_text``
#     - Delete invalid chars for the beginning of the variable name
#     - Append underscore (``"_"``) at the tail of the name if sanitized name
#       is one of the Python reserved names
# 
#     :param str filename: Name to sanitize.
#     :param str replacement_text: Replacement text.
#     :return: A replacement string.
#     :rtype: str
#     :raises ValueError: If ``var_name`` or ``replacement_text`` is invalid.
# 
#     :Example:
#         :ref:`example-sanitize-var-name`
# 
#     .. seealso::
#         :py:func:`.validate_python_var_name`
#     """
# 
#     return PythonVarNameSanitizer(var_name).sanitize(replacement_text)
# 
# def validate_python_var_name(var_name: str) -> None:
#     """
#     :param str var_name: Name to validate.
#     :raises pathvalidate.ValidationError (ErrorReason.INVALID_CHARACTER):
#         If the ``var_name`` is invalid as
#         `Python identifier
#         <https://docs.python.org/3/reference/lexical_analysis.html#identifiers>`__.
#     :raises pathvalidate.ValidationError (ErrorReason.RESERVED_NAME):
#         If the ``var_name`` is equals to
#         `Python reserved keywords
#         <https://docs.python.org/3/reference/lexical_analysis.html#keywords>`__
#         or
#         `Python built-in constants
#         <https://docs.python.org/3/library/constants.html>`__.
# 
#     :Example:
#         :ref:`example-validate-var-name`
#     """
# 
#     PythonVarNameSanitizer(var_name).validate()
# 
# Path: test/sanitizer/_common.py
# INVALID_PYTHON_VAR_CHARS = INVALID_JS_VAR_CHARS + ["$"]


import itertools
import string
import pytest
from pathvalidate.error import ErrorReason, ValidationError
from pytablewriter.sanitizer import sanitize_python_var_name, validate_python_var_name
from ._common import INVALID_PYTHON_VAR_CHARS

    @pytest.mark.parametrize(
        ["value", "expected"],
        [
            [None, ValueError],
            ["", ValidationError],
            ["123", ValueError],
            [1, TypeError],
            [True, TypeError],
        ],
    )
    def test_exception_type(self, value, expected):
        with pytest.raises(expected):
            validate_python_var_name(value)

    @pytest.mark.parametrize(
        ["value", "expected"],
        [
            [reserved_keyword, ErrorReason.RESERVED_NAME]
            for reserved_keyword in RESERVED_KEYWORDS + ["__debug__"]
        ],
    )
    def test_exception_reserved(self, value, expected):
        with pytest.raises(ValidationError) as e:
            validate_python_var_name(value)
        assert e.value.reason == expected
        assert e.value.reusable_name is False


class Test_sanitize_python_var_name:

# Path: pytablewriter/sanitizer/_python.py
# def sanitize_python_var_name(var_name: str, replacement_text: str = "") -> str:
#     """
#     Make a valid Python variable name from ``var_name``.
# 
#     To make a valid name:
# 
#     - Replace invalid characters for a Python variable name within
#       the ``var_name`` with the ``replacement_text``
#     - Delete invalid chars for the beginning of the variable name
#     - Append underscore (``"_"``) at the tail of the name if sanitized name
#       is one of the Python reserved names
# 
#     :param str filename: Name to sanitize.
#     :param str replacement_text: Replacement text.
#     :return: A replacement string.
#     :rtype: str
#     :raises ValueError: If ``var_name`` or ``replacement_text`` is invalid.
# 
#     :Example:
#         :ref:`example-sanitize-var-name`
# 
#     .. seealso::
#         :py:func:`.validate_python_var_name`
#     """
# 
#     return PythonVarNameSanitizer(var_name).sanitize(replacement_text)
# 
# def validate_python_var_name(var_name: str) -> None:
#     """
#     :param str var_name: Name to validate.
#     :raises pathvalidate.ValidationError (ErrorReason.INVALID_CHARACTER):
#         If the ``var_name`` is invalid as
#         `Python identifier
#         <https://docs.python.org/3/reference/lexical_analysis.html#identifiers>`__.
#     :raises pathvalidate.ValidationError (ErrorReason.RESERVED_NAME):
#         If the ``var_name`` is equals to
#         `Python reserved keywords
#         <https://docs.python.org/3/reference/lexical_analysis.html#keywords>`__
#         or
#         `Python built-in constants
#         <https://docs.python.org/3/library/constants.html>`__.
# 
#     :Example:
#         :ref:`example-validate-var-name`
#     """
# 
#     PythonVarNameSanitizer(var_name).validate()
# 
# Path: test/sanitizer/_common.py
# INVALID_PYTHON_VAR_CHARS = INVALID_JS_VAR_CHARS + ["$"]


# Path: test/sanitizer/test_python_var_name.py
import itertools
import string
import pytest
from pathvalidate.error import ErrorReason, ValidationError
from pytablewriter.sanitizer import sanitize_python_var_name, validate_python_var_name
from ._common import INVALID_PYTHON_VAR_CHARS


    @pytest.mark.parametrize(
        ["value", "expected"],
        [
            [None, ValueError],
            ["", ValidationError],
            ["123", ValueError],
            [1, TypeError],
            [True, TypeError],
        ],
    )
    def test_exception_type(self, value, expected):
        with pytest.raises(expected):
            validate_python_var_name(value)

    @pytest.mark.parametrize(
        ["value", "expected"],
        [
            [reserved_keyword, ErrorReason.RESERVED_NAME]
            for reserved_keyword in RESERVED_KEYWORDS + ["__debug__"]
        ],
    )
    def test_exception_reserved(self, value, expected):
        with pytest.raises(ValidationError) as e:
            validate_python_var_name(value)
        assert e.value.reason == expected
        assert e.value.reusable_name is False


class Test_sanitize_python_var_name:

    SANITIZE_CHAR_LIST = INVALID_PYTHON_VAR_CHARS