avatarSaverio Mazza

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

4555

Abstract

)"</span>, data[<span class="hljs-string">"stargazers_count"</span>], data[<span class="hljs-string">"forks_count"</span>], last_updated, data[<span class="hljs-string">"description"</span>], ) <span class="hljs-keyword">else</span>: logger.error( <span class="hljs-string">f"Failed to fetch data for <span class="hljs-subst">{url}</span>, status code: <span class="hljs-subst">{response.status_code}</span>"</span> ) <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>, <span class="hljs-literal">None</span>, <span class="hljs-literal">None</span>, <span class="hljs-literal">None</span>, <span class="hljs-literal">None</span>

<span class="hljs-keyword">def</span> <span class="hljs-title function_">generate_table_section</span>(<span class="hljs-params">header, rows</span>): <span class="hljs-string">""" Generates a Markdown table section. """</span> table = <span class="hljs-string">f"| <span class="hljs-subst">{<span class="hljs-string">' | '</span>.join(header)}</span> |\n"</span> table += <span class="hljs-string">"|"</span> + <span class="hljs-string">":-:|"</span> * <span class="hljs-built_in">len</span>(header) + <span class="hljs-string">"\n"</span> <span class="hljs-comment"># Center align all columns</span> <span class="hljs-keyword">for</span> row <span class="hljs-keyword">in</span> rows: <span class="hljs-comment"># Make sure all elements are strings and skip rows with None values</span> <span class="hljs-keyword">if</span> <span class="hljs-built_in">all</span>(element <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span> <span class="hljs-keyword">for</span> element <span class="hljs-keyword">in</span> row): table += <span class="hljs-string">f"| <span class="hljs-subst">{<span class="hljs-string">' | '</span>.join(<span class="hljs-built_in">str</span>(element) <span class="hljs-keyword">for</span> element <span class="hljs-keyword">in</span> row)}</span> |\n"</span> <span class="hljs-keyword">return</span> table

<span class="hljs-keyword">def</span> <span class="hljs-title function_">update_readme</span>(<span class="hljs-params">under_review_repos, reference_inspiration_repos</span>): <span class="hljs-string">""" Updates the README file with separate tables for 'Under Review' and 'Reference and Inspiration' repositories. """</span> <span class="hljs-comment"># Section markers</span> start_marker_under_review = <span class="hljs-string">"<!-- START_SECTION:under-review -->"</span> end_marker_under_review = <span class="hljs-string">"<!-- END_SECTION:under-review -->"</span> start_marker_reference_inspiration = <span class="hljs-string">"<!-- START_SECTION:reference-inspiration -->"</span> end_marker_reference_inspiration = <span class="hljs-string">"<!-- END_SECTION:reference-inspiration -->"</span>

custom_heading_under_review = <span class="hljs-string">"## Repositories Under Review\n\n"</span>
custom_heading_reference_inspiration = <span class="hljs-string">"## Reference and Inspiration\n\n"</span>

under_review_stats = [get_repo_stats(url) <span class="hljs-keyword">for</span> url <span class="hljs-keyword">in</span> under_review_repos]
under_review_stats.sort(
    key=<span class="hljs-keyword">lambda</span> x: x[<span class="hljs-number">3</span>] <span class="hljs-keyword">if</span> x[<span class="hljs-number">3</span>] <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span> <span class="hljs-keyword">else</span> <span class="hljs-string">""</span>, reverse=<span class="hljs-literal">True</span>
)

reference_inspiration_stats = [
    get_repo_stats(url) <span class="hljs-keyword">for</span> url <span class="hljs-keyword">in</span> reference_inspiration_repos
]
reference_inspiration_stats.sort(
    key=<span class="hljs-keyword">lambda</span> x: x[<span class="hljs-number">3</span>] <span class="hljs-keyword">if</span> x[<span class="hljs-number">3</span>] <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span> <span class="hljs-keyword">else</span> <span class="hljs-string">""</span>, reverse=<span class="hljs-literal">True</span>
)

<span class="hljs-comment"># Generate tables</span>
un

Options

der_review_table = generate_table_section( [<span class="hljs-string">"Repository"</span>, <span class="hljs-string">"Stars"</span>, <span class="hljs-string">"Forks"</span>, <span class="hljs-string">"Last Updated"</span>, <span class="hljs-string">"About"</span>], under_review_stats, )

reference_inspiration_table = generate_table_section(
    [<span class="hljs-string">"Repository"</span>, <span class="hljs-string">"Stars"</span>, <span class="hljs-string">"Forks"</span>, <span class="hljs-string">"Last Updated"</span>, <span class="hljs-string">"About"</span>],
    reference_inspiration_stats,
)

<span class="hljs-comment"># Read the current README</span>
<span class="hljs-keyword">try</span>:
    <span class="hljs-keyword">with</span> <span class="hljs-built_in">open</span>(<span class="hljs-string">"README.md"</span>, <span class="hljs-string">"r"</span>) <span class="hljs-keyword">as</span> file:
        readme_content = file.read()
<span class="hljs-keyword">except</span> FileNotFoundError:
    logger.error(<span class="hljs-string">"README.md file not found."</span>)
    <span class="hljs-keyword">return</span>

<span class="hljs-comment"># Update the README</span>
updated_readme = readme_content
sections = [
    (
        start_marker_under_review,
        end_marker_under_review,
        under_review_table,
        custom_heading_under_review,
    ),
    (
        start_marker_reference_inspiration,
        end_marker_reference_inspiration,
        reference_inspiration_table,
        custom_heading_reference_inspiration,
    ),
]

<span class="hljs-keyword">for</span> start_marker, end_marker, table, heading <span class="hljs-keyword">in</span> sections:
    <span class="hljs-keyword">if</span> start_marker <span class="hljs-keyword">in</span> updated_readme <span class="hljs-keyword">and</span> end_marker <span class="hljs-keyword">in</span> updated_readme:
        section_start = updated_readme.find(start_marker)
        section_end = updated_readme.find(end_marker) + <span class="hljs-built_in">len</span>(end_marker)
        updated_readme = (
            updated_readme[:section_start]
            + start_marker
            + <span class="hljs-string">"\n"</span>
            + heading
            + table
            + end_marker
            + updated_readme[section_end:]
        )
    <span class="hljs-keyword">else</span>:
        logger.info(
            <span class="hljs-string">f"Markers for <span class="hljs-subst">{heading.strip()}</span> not found, appending new table at the end."</span>
        )
        updated_readme += <span class="hljs-string">"\n"</span> + start_marker + <span class="hljs-string">"\n"</span> + heading + table + end_marker

<span class="hljs-comment"># Write the updated README</span>
<span class="hljs-keyword">try</span>:
    <span class="hljs-keyword">with</span> <span class="hljs-built_in">open</span>(<span class="hljs-string">"README.md"</span>, <span class="hljs-string">"w"</span>) <span class="hljs-keyword">as</span> file:
        file.write(updated_readme)
<span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
    logger.error(<span class="hljs-string">f"Error writing to README.md: <span class="hljs-subst">{e}</span>"</span>)

reference_inspiration_repos = [ <span class="hljs-string">"https://github.com/jonra1993/fastapi-alembic-sqlmodel-async"</span>, <span class="hljs-string">"https://github.com/igorbenav/fastcrud"</span>, <span class="hljs-string">"https://github.com/FrancescoXX/fullstack-flask-app"</span>, <span class="hljs-comment"># Add more repository URLs as needed for reference and inspiration</span> ]

<span class="hljs-comment"># Example usage</span> under_review_repos = [ <span class="hljs-string">"https://github.com/XamHans/video-2-text?tab=readme-ov-file"</span>, <span class="hljs-string">"https://github.com/waseemhnyc/instagraph-nextjs-fastapi"</span>, <span class="hljs-string">"https://github.com/Aeternalis-Ingenium/JumpStart"</span>, ]

<span class="hljs-comment"># Update the README</span> update_readme(under_review_repos, reference_inspiration_repos)</pre></div><figure id="c88a"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*-CLu84-AAv9drNok39vVXw.png"><figcaption></figcaption></figure></article></body>

GitHub Repository Information Aggregator and README Updater

This code is designed to automate the process of fetching, sorting, and displaying information about GitHub repositories in a README file. It consists of several key functions:

  1. get_repo_info_from_url(url): Extracts the owner and repository name from a GitHub URL.
  2. get_repo_stats(url): Fetches repository statistics such as star count, fork count, last update date, and description from GitHub’s API. The “Last Updated” date is formatted in the YYYY-MM-DD format.
  3. generate_table_section(header, rows): Generates a Markdown table section. It takes a header (column names) and rows (data for each repository) to create a table.
  4. update_readme(under_review_repos, reference_inspiration_repos): This is the main function that updates the README file. It processes two lists of GitHub repository URLs: ‘Under Review’ and ‘Reference and Inspiration’. For each list, it fetches repository statistics, sorts them in descending order based on the last updated date, and generates a Markdown table. These tables are then inserted into the README file at specified markers for each section.

The script ensures that only repositories with valid URLs are processed. It uses error logging for troubleshooting and handles file operations for reading and updating the README file. This script is particularly useful for developers who need to maintain a curated list of repositories with up-to-date information in their project documentation or personal GitHub profiles.

https://github.com/mazzasaverio/fastapi-cloudrun-starter

import requests
from loguru import logger
from datetime import datetime
from urllib.parse import urlparse


def get_repo_info_from_url(url):
    """
    Extracts the owner and repository name from a GitHub URL.
    """
    parsed_url = urlparse(url)
    path_parts = parsed_url.path.strip("/").split("/")
    if len(path_parts) >= 2:
        return path_parts[-2], path_parts[-1]  # owner, repo
    else:
        return None, None


def get_repo_stats(url):
    """
    Fetches the statistics of a given GitHub repository URL.
    """
    owner, repo = get_repo_info_from_url(url)
    if not owner or not repo:
        logger.error(f"Invalid GitHub URL: {url}")
        return None, None, None, None

    api_url = f"https://api.github.com/repos/{owner}/{repo}"
    response = requests.get(api_url)

    if response.status_code == 200:
        data = response.json()
        last_updated = datetime.strptime(
            data["updated_at"], "%Y-%m-%dT%H:%M:%SZ"
        ).strftime("%Y-%m-%d")
        return (
            f"[{repo}]({url})",
            data["stargazers_count"],
            data["forks_count"],
            last_updated,
            data["description"],
        )
    else:
        logger.error(
            f"Failed to fetch data for {url}, status code: {response.status_code}"
        )
        return None, None, None, None, None


def generate_table_section(header, rows):
    """
    Generates a Markdown table section.
    """
    table = f"| {' | '.join(header)} |\n"
    table += "|" + ":-:|" * len(header) + "\n"  # Center align all columns
    for row in rows:
        # Make sure all elements are strings and skip rows with None values
        if all(element is not None for element in row):
            table += f"| {' | '.join(str(element) for element in row)} |\n"
    return table


def update_readme(under_review_repos, reference_inspiration_repos):
    """
    Updates the README file with separate tables for 'Under Review' and 'Reference and Inspiration' repositories.
    """
    # Section markers
    start_marker_under_review = "<!-- START_SECTION:under-review -->"
    end_marker_under_review = "<!-- END_SECTION:under-review -->"
    start_marker_reference_inspiration = "<!-- START_SECTION:reference-inspiration -->"
    end_marker_reference_inspiration = "<!-- END_SECTION:reference-inspiration -->"

    custom_heading_under_review = "## Repositories Under Review\n\n"
    custom_heading_reference_inspiration = "## Reference and Inspiration\n\n"

    under_review_stats = [get_repo_stats(url) for url in under_review_repos]
    under_review_stats.sort(
        key=lambda x: x[3] if x[3] is not None else "", reverse=True
    )

    reference_inspiration_stats = [
        get_repo_stats(url) for url in reference_inspiration_repos
    ]
    reference_inspiration_stats.sort(
        key=lambda x: x[3] if x[3] is not None else "", reverse=True
    )

    # Generate tables
    under_review_table = generate_table_section(
        ["Repository", "Stars", "Forks", "Last Updated", "About"],
        under_review_stats,
    )

    reference_inspiration_table = generate_table_section(
        ["Repository", "Stars", "Forks", "Last Updated", "About"],
        reference_inspiration_stats,
    )

    # Read the current README
    try:
        with open("README.md", "r") as file:
            readme_content = file.read()
    except FileNotFoundError:
        logger.error("README.md file not found.")
        return

    # Update the README
    updated_readme = readme_content
    sections = [
        (
            start_marker_under_review,
            end_marker_under_review,
            under_review_table,
            custom_heading_under_review,
        ),
        (
            start_marker_reference_inspiration,
            end_marker_reference_inspiration,
            reference_inspiration_table,
            custom_heading_reference_inspiration,
        ),
    ]

    for start_marker, end_marker, table, heading in sections:
        if start_marker in updated_readme and end_marker in updated_readme:
            section_start = updated_readme.find(start_marker)
            section_end = updated_readme.find(end_marker) + len(end_marker)
            updated_readme = (
                updated_readme[:section_start]
                + start_marker
                + "\n"
                + heading
                + table
                + end_marker
                + updated_readme[section_end:]
            )
        else:
            logger.info(
                f"Markers for {heading.strip()} not found, appending new table at the end."
            )
            updated_readme += "\n" + start_marker + "\n" + heading + table + end_marker

    # Write the updated README
    try:
        with open("README.md", "w") as file:
            file.write(updated_readme)
    except Exception as e:
        logger.error(f"Error writing to README.md: {e}")


reference_inspiration_repos = [
    "https://github.com/jonra1993/fastapi-alembic-sqlmodel-async",
    "https://github.com/igorbenav/fastcrud",
    "https://github.com/FrancescoXX/fullstack-flask-app",
    # Add more repository URLs as needed for reference and inspiration
]

# Example usage
under_review_repos = [
    "https://github.com/XamHans/video-2-text?tab=readme-ov-file",
    "https://github.com/waseemhnyc/instagraph-nextjs-fastapi",
    "https://github.com/Aeternalis-Ingenium/JumpStart",
]

# Update the README
update_readme(under_review_repos, reference_inspiration_repos)
Python
Coding
Data Science
Machine Learning
Fastapi
Recommended from ReadMedium