Skip to content

Refactor: Improve get_vale_conf script for structure and error handling#358

Merged
tang-mm merged 8 commits into
mainfrom
fix-get-vale-script
Mar 31, 2025
Merged

Refactor: Improve get_vale_conf script for structure and error handling#358
tang-mm merged 8 commits into
mainfrom
fix-get-vale-script

Conversation

@tang-mm

@tang-mm tang-mm commented Mar 19, 2025

Copy link
Copy Markdown
Contributor

(Resolves DOCPR-1416)

This pull request refactors the get_vale_conf.py script to improve its structure and error handling.

Description

* Modularize the code into new methods create_dir_if_not_exists, download_file, and download_github_directory.

  • Changed directory paths to use SPHINX_DIR instead of DIR to ensure consistency.
  • Added logic for downloading nested directories when they exist
    * Improved error handling for timeout and API failure, with error messages for download failures.
  • Modified the main() function to return appropriate exit codes when called by Makefile

Update after review:

  • Instead of using API calls to download individual files, this PR changes to clone the repository into a /tmp directory, and then copy the target files to the current project
  • Default to file overwriting, and added cmd option --no-overwrite to skip overwriting

@tang-mm tang-mm requested review from SecondSkoll and akcano March 19, 2025 05:46

@akcano akcano left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, but I think some changes may be needed.

Comment thread docs/.sphinx/get_vale_conf.py Outdated
if download_file(item["download_url"], output_file):
success_count += 1

print(f"Downloaded {success_count} items")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may prove cumbersome with the recursion above; we don't get a total count but print separate numbers per each dir instead

Comment thread docs/.sphinx/get_vale_conf.py Outdated
def download_file(url, output_path):
"""Download a file to the specified path"""
try:
print(f" Downloading: {os.path.basename(output_path)}")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest using the logging module instead of print statements globally: https://docs.python.org/3/library/logging.html

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment thread docs/.sphinx/get_vale_conf.py Outdated
response.raise_for_status()

create_dir_if_not_exists(output_dir)
items = response.json()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So while this function does allow any URL to be parsed - which could cause this issue, the only URLs used by this function are specific locations within the repo, and not the whole repo. So unless we have 100+ rules, this shouldn't be an issue.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is indeed a potential issue. Considering the recursive situation, I have refactored the entire script to use git clone instead of Github APIs to download files. This approach is also more efficient than making individual calls.

Comment thread docs/.sphinx/get_vale_conf.py Outdated
Comment on lines +89 to +107
rules_dir = os.path.join(SPHINX_DIR, "styles/Canonical")
vocab_dir = os.path.join(SPHINX_DIR, "styles/config/vocabularies/Canonical")
dict_dir = os.path.join(SPHINX_DIR, "styles/config/dictionaries")

# GitHub API URLs
rules_github_url = f"{GITHUB_API_BASE}/contents/styles/Canonical"
vocab_github_url = f"{GITHUB_API_BASE}/contents/styles/config/vocabularies/Canonical"
dict_github_url = f"{GITHUB_API_BASE}/contents/styles/config/dictionaries"

# Download through GitHub API
if not download_github_directory(rules_github_url, rules_dir):
print(f"Failed to download directory from {rules_github_url}")
return 1
if not download_github_directory(vocab_github_url, vocab_dir):
print(f"Failed to download directory from {vocab_github_url}")
return 1
if not download_github_directory(dict_github_url, dict_dir):
print(f"Failed to download directory from {dict_github_url}")
return 1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
rules_dir = os.path.join(SPHINX_DIR, "styles/Canonical")
vocab_dir = os.path.join(SPHINX_DIR, "styles/config/vocabularies/Canonical")
dict_dir = os.path.join(SPHINX_DIR, "styles/config/dictionaries")
# GitHub API URLs
rules_github_url = f"{GITHUB_API_BASE}/contents/styles/Canonical"
vocab_github_url = f"{GITHUB_API_BASE}/contents/styles/config/vocabularies/Canonical"
dict_github_url = f"{GITHUB_API_BASE}/contents/styles/config/dictionaries"
# Download through GitHub API
if not download_github_directory(rules_github_url, rules_dir):
print(f"Failed to download directory from {rules_github_url}")
return 1
if not download_github_directory(vocab_github_url, vocab_dir):
print(f"Failed to download directory from {vocab_github_url}")
return 1
if not download_github_directory(dict_github_url, dict_dir):
print(f"Failed to download directory from {dict_github_url}")
return 1
base_paths = [
"styles/Canonical",
"styles/config/vocabularies/Canonical",
"styles/config/dictionaries",
]
downloads = [
(
f"{GITHUB_API_BASE}/contents/{base_path}",
os.path.join(SPHINX_DIR, base_path),
)
for base_path in base_paths
]
failed_downloads = [
url
for (url, destination) in downloads
if not download_github_directory(url, destination)
]
if failed_downloads:
for url in failed_downloads:
print(f"Failed to download directory from {url}")
return 1

or something like this in case the layout is extended later

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done - refactored into a dict

Comment thread docs/.sphinx/get_vale_conf.py
tang-mm added 4 commits March 26, 2025 17:50
Change to use `git clone` to download the whole repository into /tmp,
which is more efficient than API calls. Copy over the files once
download is completed
Add overwrite option
@tang-mm tang-mm requested a review from akcano March 26, 2025 17:05
# Create temporary directory on disk for cloning
temp_dir = tempfile.mkdtemp()
logging.info("Cloning repository <%s> to temporary directory: %s", GITHUB_REPO, temp_dir)
clone_cmd = ["git", "clone", "--depth", "1", GITHUB_CLONE_URL, temp_dir]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A note: for more intensive use, there's a nice wrapper: https://gitpython.readthedocs.io/en/stable/

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for sharing the link! It's a nice solution with pure python. But since we're only cloning one single repo here, I'll go with the original git command without installing another package

@tang-mm tang-mm merged commit 3c1540b into main Mar 31, 2025
@nhennigan nhennigan deleted the fix-get-vale-script branch February 13, 2026 22:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants