Last active
September 8, 2023 01:23
-
-
Save emoss08/446e5f4b6536167a84cd57fc90288be9 to your computer and use it in GitHub Desktop.
Converts models.TextChoices to Typescript Const
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Converts Models.TextChoices to TypeScript Const. | |
Primarily used for Select Fields | |
Example: | |
Input: | |
class JobFunctionChoices(models.TextChoices): | |
MANAGER = "MANAGER", _("Manager") | |
MANAGEMENT_TRAINEE = "MANAGEMENT_TRAINEE", _("Management Trainee") | |
SUPERVISOR = "SUPERVISOR", _("Supervisor") | |
DISPATCHER = "DISPATCHER", _("Dispatcher") | |
BILLING = "BILLING", _("Billing") | |
FINANCE = "FINANCE", _("Finance") | |
SAFETY = "SAFETY", _("Safety") | |
SYS_ADMIN = "SYS_ADMIN", _("System Administrator") | |
TEST = "TEST", _("Test Job Function") | |
Output: | |
export const jobFunctionChoices = [ | |
{ value: "MANAGER", label: "Manager" }, | |
{ value: "MANAGEMENT_TRAINEE", label: "Management Trainee" }, | |
{ value: "SUPERVISOR", label: "Supervisor" }, | |
{ value: "DISPATCHER", label: "Dispatcher" }, | |
{ value: "BILLING", label: "Billing" }, | |
{ value: "FINANCE", label: "Finance" }, | |
{ value: "SAFETY", label: "Safety" }, | |
{ value: "SYS_ADMIN", label: "System Administrator" }, | |
{ value: "TEST", label: "Test Job Function" }, | |
]; | |
""" | |
import ast | |
import os | |
from collections.abc import Generator | |
from typing import Any | |
def find_files(directory: str, extension: str) -> Generator[bytes | str, Any, None]: | |
"""Generate file paths that match a given extension in a directory. | |
This generator walks a directory tree, starting at `directory`, and yields | |
paths to files that have the specified `extension`. | |
Args: | |
directory (str): The root directory from which the search starts. | |
extension (str): The file extension to match. | |
Yields: | |
str: Full file path for each file that matches the given extension. | |
""" | |
for root, dirs, files in os.walk(directory): | |
for file in files: | |
if file.endswith(extension): | |
yield os.path.join(root, file) | |
def find_and_convert_choices(directory: str) -> None: | |
"""Find Django TextChoices in Python files and print their TypeScript equivalent. | |
This function uses the `ast` module to parse Python source code and look for | |
Django TextChoices declarations. For each TextChoices found, it prints a TypeScript | |
equivalent. | |
Args: | |
directory (str): The root directory where the search for Python files starts. | |
Returns | |
None: This function does not return anything. | |
""" | |
for file in find_files(directory, ".py"): | |
with open(file) as f: | |
content = f.read() | |
try: | |
module = ast.parse(content) | |
except SyntaxError as e: | |
print(f"Skipping file {file} due to syntax error: {e}") | |
continue | |
for class_node in [ | |
n for n in ast.walk(module) if isinstance(n, ast.ClassDef) | |
]: | |
for base in class_node.bases: | |
if isinstance(base, ast.Attribute) and base.attr == "TextChoices": | |
ts_conversion = [] | |
for assign_node in [ | |
n for n in ast.walk(class_node) if isinstance(n, ast.Assign) | |
]: | |
for _ in assign_node.targets: | |
if ( | |
isinstance(assign_node.value, ast.Tuple) | |
and len(assign_node.value.elts) == 2 | |
): | |
value = assign_node.value.elts[0].s | |
label = assign_node.value.elts[1].args[0].s | |
ts_conversion.append( | |
f' {{ value: "{value}", label: "{label}" }},' | |
) | |
ts_string = ( | |
f"export const {class_node.name[0].lower() + class_node.name[1:]} = [\n" | |
+ "\n".join(ts_conversion) | |
+ "\n];" | |
) | |
print(ts_string) | |
f.close() | |
find_and_convert_choices("../billing") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment