Edward's Tech Site

this site made with Next.js 13, see the code

HOWTO: Apr 13 - Python
Set up Python scripting CLI in a Vite React site to speed up development
  • this howto is for you if
    • you have never used Python and are looking for a pragmatic way to use it in your projects
    • want to create command line tools that speed up your development, e.g. scripts like Angular's ng generate component component-name, but for your own projects
  • what we will build
    • we will start with a React site that reads a JSON file of flashcards
    • and change it so that we can update a simpler text file of flashcards which we parse into JSON with an npm command that executes a Python script
  • what we will do
    • we will set up a Vite React site that shows flashcards from data in a JSON file
    • we will set up Python so that we can run an npm script which parses a text file into the JSON file
    • note that the idea here is not to use Python to create an API
      • but to run scripts that e.g. create or alter JSON and .tsx files, etc.
      • this is one idea of Datapod, to be able to execute scripts that help you code faster
        • this is somewhat like in Angular the command to create a component: ng generate component component-name
    • this howto is the first steps in building a Datapod called "Datapod for React/Python/JSON"
      • so what we do is realistic, i.e. a site that you can use to create e.g. develop tools that parse data, etc.
      • but the steps in this howto are just enough to get up and running with Python scripts that can be executed from the command line
        • which is useful in any project if you want to quickly make automated tasks
      • of course a further concept of Datapod is that eventually I will build a backend which in turn allows the frontend to execute these commands
        • this will allow e.g. a developer to fill out a form and click a button in the frontend in order to (1) create a page, (2) parse data, etc.
  • code is here
  • live-coding video of this howto is here
  • >>> 1. install Python, clone the React site, and create two npm scripts which each run a test Python script
    • install Python: ../downloadshttps://www.python.org/downloads
    • check version
      • python --version
      • I have 3.12.2
    • create a Vite React site by creating a repo with this template and cloning it locally: ../datapod-for-react-jsonhttps://github.com/edwardtanguay/datapod-for-react-json
      • I called my project datapod-for-react-python-json
    • in root, create "scripts" directory
      • in the bash shell, go into that scripts directory
      • make this directory a Python virtual directory
        • python -m venv env
        • note that this created and env directory in scripts, filled with directories and files
        • this will allow you to install packages only for this project without installing them globally
        • think of it as npm for Python
      • add this env file to your .gitignore, so that it is not checked into your GitHub repository
        • add to .gitignore
          • scripts/env
    • now create these files:
    • /scripts/create-page.py
      • print("this will create a new page in the app")
    • /scripts/parse-data.py
      • print("this will parse the data")
    • in package.json, add these two npm script commands to run these Python commands
      • "cp": "cd scripts && python create-page.py",
        "pd": "cd scripts && python parse-data.py",
    • note that these commands change into the directory first, then run the script from there
      • this will be important when we import functions from with relative paths later
    • execute the npm commands from the command line
      • npm run cp
      • npm run pd
  • >>> 2. start React site and create text flashcard file
    • start React site
      • npm i
      • npm run dev
    • note that the flashcards showing on the Welcome page are being loaded from the /data/flashcards.json file
    • rename the /data directory to /parseddata
      • we do this since we are going to be parsing a text file and saving the output here in /parseddata which will be read-only
      • dataModel.ts - you will need to change the path here
        • import rawFlashcards from "../../parseddata/flashcards.json";
      • make sure the site works again
    • create /data/flashcards.txt
      • it
        and it will take some time
        e ci vorrà del tempo
         
        it
        this will ensure that you get
        cìo garantirà di ottenere
         
        es
        this has certain advantages
        est tiene ciertas ventajas
         
        es
        in such a way that
        de tal manera que
    • we will now program the parse-data script so that it parses this text file flashcard objects, and then overwrites the flashcards.json file with this new data
  • >>> 3. set up utilities that can be used by any command
    • we have two scripts, create-page.py and parse-data.py, that we want to program
    • and in my Datapod there will be many more scripts, e.g. create-component.py, delete-page.py, etc.
    • all of these scripts should be able to use a common library of tools
      • this is what we are going to set up now
    • create this folder and files
    • debug.py
      • def devlog(line: str):
        print(f"DEBUG ### {line} ################################")
    • files.py
      • import os
         
        def get_lines_from_file(file_name: str) -> list[str]:
        """
        Get all lines from a file as a list of strings.
         
        Usage:
        lines = get_lines_from_file("../../notes.txt")
        """
        try:
        with open(file_name, "r", encoding="utf-8") as f:
        contents = f.read()
        except Exception as e:
        raise RuntimeError(f"Failed to read file: {e}")
         
        lines = [line.strip() for line in contents.split('\n')]
        return lines
    • in the create-page script, let's use the debug function
      • create-page.py
        • import utils.debug as debug
           
          debug.devlog("this will create a new page in the app")
    • watch how the Trae editor works with Python to give you intellisense that shows which functions are available to you as a dropdown:
      • this should also work in VSCode or Cursor
    • notice also that the """ comment block inside the function will show up in these editors as well, which gives you context-related help on the functions you are using
    • now let's use the file utility function in the parse-data script
      • parse-data/main.py
        • import utils.debug as debug
          import utils.files as files
           
          debug.devlog("this shows the lines of the text file")
          lines = files.get_lines_from_file("../data/flashcards.txt")
          for i, line in enumerate(lines, 1):
          print(f"{i:03d}: {line}")
    • execute the command: npm run pd
    • ignore these pycache directories that Python creates so they don't get checked into your repository
      • .gitignore
        • __pycache__/
  • >>> 4. program the parse-data script to convert the text file of flashcards into JSON
    • first we need a utils function to create a random suuid
      • utils/general.py
        • import random
          import string
           
          def generate_short_uuid() -> str:
          """
          Return a random short UUID (6 characters)
           
          Example output: "q35HZa"
          """
          charset = string.ascii_letters + string.digits # A-Z, a-z, 0-9
          length = 6
          return ''.join(random.choice(charset) for _ in range(length))
    • then let's completely rewrite the parse-data code to create flashcards.json based on flashcards.txt
      • parse-data/main.py
        • import utils.debug as debug
          import utils.files as files
          import utils.general as general
          import json
           
          class Flashcard:
          def __init__(self, suuid, category, front, back):
          self.suuid = suuid
          self.category = category
          self.front = front
          self.back = back
           
          lines = files.get_lines_from_file("../data/flashcards.txt")
           
          flashcards = []
          for i in range(0, len(lines), 4):
          if i + 3 > len(lines):
          break
           
          category = lines[i].strip()
          front = lines[i+1].strip()
          back = lines[i+2].strip()
           
          flashcard = Flashcard(
          suuid=general.generate_short_uuid(),
          category=category,
          front=front,
          back=back
          )
           
          flashcards.append(flashcard.__dict__)
           
          try:
          # Convert flashcards to JSON
          json_data = json.dumps(flashcards, indent=4)
           
          # Write JSON data to file
          with open("../parseddata/flashcards.json", 'w') as json_file:
          json_file.write(json_data)
           
          print("Successfully updated flashcards.json")
           
          except Exception as err:
          print(f"Error: {err}")
    • now when you add a flashcard to flashcards.txt and run the npm run pd command, a new flashcard will appear on your site
  • >>> 5. next steps
    • my next steps will be to program the "create page" commmand, which will create a file and change two files
      • but that is a bit involved for this howto which was just to show how to set everything up and organize your directories and files
      • creating more commands is more of the same coding that we did for the parse-data command
    • I hope this howto got you working with Python in a pragmatic way, creating scripts that help speed up your development