Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use pathlib as much as possible #3967

Merged
merged 10 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 16 additions & 19 deletions benchmarks/benchmark_lighthouse.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from __future__ import annotations

import json
import os
import sys
from pathlib import Path

from utils import send_data_to_posthog

Expand All @@ -28,7 +28,7 @@ def insert_benchmarking_data(
send_data_to_posthog("lighthouse_benchmark", properties)


def get_lighthouse_scores(directory_path: str) -> dict:
def get_lighthouse_scores(directory_path: str | Path) -> dict:
"""Extracts the Lighthouse scores from the JSON files in the specified directory.

Args:
Expand All @@ -38,24 +38,21 @@ def get_lighthouse_scores(directory_path: str) -> dict:
dict: The Lighthouse scores.
"""
scores = {}

directory_path = Path(directory_path)
try:
for filename in os.listdir(directory_path):
if filename.endswith(".json") and filename != "manifest.json":
file_path = os.path.join(directory_path, filename)
with open(file_path, "r") as file:
data = json.load(file)
# Extract scores and add them to the dictionary with the filename as key
scores[data["finalUrl"].replace("http://localhost:3000/", "/")] = {
"performance_score": data["categories"]["performance"]["score"],
"accessibility_score": data["categories"]["accessibility"][
"score"
],
"best_practices_score": data["categories"]["best-practices"][
"score"
],
"seo_score": data["categories"]["seo"]["score"],
}
for filename in directory_path.iterdir():
if filename.suffix == ".json" and filename.stem != "manifest":
file_path = directory_path / filename
data = json.loads(file_path.read_text())
# Extract scores and add them to the dictionary with the filename as key
scores[data["finalUrl"].replace("http://localhost:3000/", "/")] = {
"performance_score": data["categories"]["performance"]["score"],
"accessibility_score": data["categories"]["accessibility"]["score"],
"best_practices_score": data["categories"]["best-practices"][
"score"
],
"seo_score": data["categories"]["seo"]["score"],
}
except Exception as e:
return {"error": e}

Expand Down
17 changes: 8 additions & 9 deletions benchmarks/benchmark_package_size.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

import argparse
import os
from pathlib import Path

from utils import get_directory_size, get_python_version, send_data_to_posthog


def get_package_size(venv_path, os_name):
def get_package_size(venv_path: Path, os_name):
"""Get the size of a specified package.

Args:
Expand All @@ -26,14 +27,12 @@ def get_package_size(venv_path, os_name):

is_windows = "windows" in os_name

full_path = (
["lib", f"python{python_version}", "site-packages"]
package_dir: Path = (
venv_path / "lib" / f"python{python_version}" / "site-packages"
if not is_windows
else ["Lib", "site-packages"]
else venv_path / "Lib" / "site-packages"
)

package_dir = os.path.join(venv_path, *full_path)
if not os.path.exists(package_dir):
if not package_dir.exists():
raise ValueError(
"Error: Virtual environment does not exist or is not activated."
)
Expand Down Expand Up @@ -63,9 +62,9 @@ def insert_benchmarking_data(
path: The path to the dir or file to check size.
"""
if "./dist" in path:
size = get_directory_size(path)
size = get_directory_size(Path(path))
else:
size = get_package_size(path, os_type_version)
size = get_package_size(Path(path), os_type_version)

# Prepare the event data
properties = {
Expand Down
3 changes: 2 additions & 1 deletion benchmarks/benchmark_web_size.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import argparse
import os
from pathlib import Path

from utils import get_directory_size, send_data_to_posthog

Expand All @@ -28,7 +29,7 @@ def insert_benchmarking_data(
pr_id: The id of the PR.
path: The path to the dir or file to check size.
"""
size = get_directory_size(path)
size = get_directory_size(Path(path))

# Prepare the event data
properties = {
Expand Down
15 changes: 8 additions & 7 deletions benchmarks/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

import os
import subprocess
from pathlib import Path

import httpx
from httpx import HTTPError


def get_python_version(venv_path, os_name):
def get_python_version(venv_path: Path, os_name):
"""Get the python version of python in a virtual env.

Args:
Expand All @@ -18,21 +19,21 @@ def get_python_version(venv_path, os_name):
The python version.
"""
python_executable = (
os.path.join(venv_path, "bin", "python")
venv_path / "bin" / "python"
if "windows" not in os_name
else os.path.join(venv_path, "Scripts", "python.exe")
else venv_path / "Scripts" / "python.exe"
)
try:
output = subprocess.check_output(
[python_executable, "--version"], stderr=subprocess.STDOUT
[str(python_executable), "--version"], stderr=subprocess.STDOUT
)
python_version = output.decode("utf-8").strip().split()[1]
return ".".join(python_version.split(".")[:-1])
except subprocess.CalledProcessError:
return None


def get_directory_size(directory):
def get_directory_size(directory: Path):
"""Get the size of a directory in bytes.

Args:
Expand All @@ -44,8 +45,8 @@ def get_directory_size(directory):
total_size = 0
for dirpath, _, filenames in os.walk(directory):
for f in filenames:
fp = os.path.join(dirpath, f)
total_size += os.path.getsize(fp)
fp = Path(dirpath) / f
total_size += fp.stat().st_size
return total_size


Expand Down
44 changes: 22 additions & 22 deletions integration/test_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import requests


def check_urls(repo_dir):
def check_urls(repo_dir: Path):
"""Check that all URLs in the repo are valid and secure.

Args:
Expand All @@ -21,33 +21,33 @@ def check_urls(repo_dir):
errors = []

for root, _dirs, files in os.walk(repo_dir):
if "__pycache__" in root:
root = Path(root)
if root.stem == "__pycache__":
continue

for file_name in files:
if not file_name.endswith(".py") and not file_name.endswith(".md"):
continue

file_path = os.path.join(root, file_name)
file_path = root / file_name
try:
with open(file_path, "r", encoding="utf-8", errors="ignore") as file:
for line in file:
urls = url_pattern.findall(line)
for url in set(urls):
if url.startswith("http://"):
errors.append(
f"Found insecure HTTP URL: {url} in {file_path}"
)
url = url.strip('"\n')
try:
response = requests.head(
url, allow_redirects=True, timeout=5
)
response.raise_for_status()
except requests.RequestException as e:
errors.append(
f"Error accessing URL: {url} in {file_path} | Error: {e}, , Check your path ends with a /"
)
for line in file_path.read_text().splitlines():
urls = url_pattern.findall(line)
for url in set(urls):
if url.startswith("http://"):
errors.append(
f"Found insecure HTTP URL: {url} in {file_path}"
)
url = url.strip('"\n')
try:
response = requests.head(
url, allow_redirects=True, timeout=5
)
response.raise_for_status()
except requests.RequestException as e:
errors.append(
f"Error accessing URL: {url} in {file_path} | Error: {e}, , Check your path ends with a /"
)
except Exception as e:
errors.append(f"Error reading file: {file_path} | Error: {e}")

Expand All @@ -58,7 +58,7 @@ def check_urls(repo_dir):
"repo_dir",
[Path(__file__).resolve().parent.parent / "reflex"],
)
def test_find_and_check_urls(repo_dir):
def test_find_and_check_urls(repo_dir: Path):
"""Test that all URLs in the repo are valid and secure.

Args:
Expand Down
2 changes: 1 addition & 1 deletion reflex/compiler/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ def _compile_root_stylesheet(stylesheets: list[str]) -> str:
stylesheet_full_path = (
Path.cwd() / constants.Dirs.APP_ASSETS / stylesheet.strip("/")
)
if not os.path.exists(stylesheet_full_path):
if not stylesheet_full_path.exists():
raise FileNotFoundError(
f"The stylesheet file {stylesheet_full_path} does not exist."
)
Expand Down
9 changes: 4 additions & 5 deletions reflex/compiler/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from __future__ import annotations

import os
from pathlib import Path
from typing import Any, Callable, Dict, Optional, Type, Union
from urllib.parse import urlparse
Expand Down Expand Up @@ -448,16 +447,16 @@ def add_meta(
return page


def write_page(path: str, code: str):
def write_page(path: str | Path, code: str):
"""Write the given code to the given path.

Args:
path: The path to write the code to.
code: The code to write.
"""
path_ops.mkdir(os.path.dirname(path))
with open(path, "w", encoding="utf-8") as f:
f.write(code)
path = Path(path)
path_ops.mkdir(path.parent)
path.write_text(code, encoding="utf-8")


def empty_dir(path: str | Path, keep_files: list[str] | None = None):
Expand Down
3 changes: 2 additions & 1 deletion reflex/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import os
import sys
import urllib.parse
from pathlib import Path
from typing import Any, Dict, List, Optional, Set

try:
Expand Down Expand Up @@ -188,7 +189,7 @@ class Config:
telemetry_enabled: bool = True

# The bun path
bun_path: str = constants.Bun.DEFAULT_PATH
bun_path: str | Path = constants.Bun.DEFAULT_PATH

# List of origins that are allowed to connect to the backend API.
cors_allowed_origins: List[str] = ["*"]
Expand Down
26 changes: 14 additions & 12 deletions reflex/constants/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import platform
from enum import Enum
from importlib import metadata
from pathlib import Path
from types import SimpleNamespace

from platformdirs import PlatformDirs
Expand Down Expand Up @@ -66,18 +67,19 @@ class Reflex(SimpleNamespace):
# Get directory value from enviroment variables if it exists.
_dir = os.environ.get("REFLEX_DIR", "")

DIR = _dir or (
# on windows, we use C:/Users/<username>/AppData/Local/reflex.
# on macOS, we use ~/Library/Application Support/reflex.
# on linux, we use ~/.local/share/reflex.
# If user sets REFLEX_DIR envroment variable use that instead.
PlatformDirs(MODULE_NAME, False).user_data_dir
DIR = Path(
_dir
or (
# on windows, we use C:/Users/<username>/AppData/Local/reflex.
# on macOS, we use ~/Library/Application Support/reflex.
# on linux, we use ~/.local/share/reflex.
# If user sets REFLEX_DIR envroment variable use that instead.
PlatformDirs(MODULE_NAME, False).user_data_dir
)
)
# The root directory of the reflex library.

ROOT_DIR = os.path.dirname(
os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
)
ROOT_DIR = Path(__file__).parents[2]

RELEASES_URL = f"https://api.github.com/repos/reflex-dev/templates/releases"

Expand Down Expand Up @@ -125,11 +127,11 @@ class Dirs(SimpleNamespace):
"""Folders used by the template system of Reflex."""

# The template directory used during reflex init.
BASE = os.path.join(Reflex.ROOT_DIR, Reflex.MODULE_NAME, ".templates")
BASE = Reflex.ROOT_DIR / Reflex.MODULE_NAME / ".templates"
# The web subdirectory of the template directory.
WEB_TEMPLATE = os.path.join(BASE, "web")
WEB_TEMPLATE = BASE / "web"
# The jinja template directory.
JINJA_TEMPLATE = os.path.join(BASE, "jinja")
JINJA_TEMPLATE = BASE / "jinja"
# Where the code for the templates is stored.
CODE = "code"

Expand Down
7 changes: 3 additions & 4 deletions reflex/constants/config.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Config constants."""

import os
from pathlib import Path
from types import SimpleNamespace

from reflex.constants.base import Dirs, Reflex
Expand All @@ -17,9 +18,7 @@ class Config(SimpleNamespace):
# The name of the reflex config module.
MODULE = "rxconfig"
# The python config file.
FILE = f"{MODULE}{Ext.PY}"
# The previous config file.
PREVIOUS_FILE = f"pcconfig{Ext.PY}"
FILE = Path(f"{MODULE}{Ext.PY}")


class Expiration(SimpleNamespace):
Expand All @@ -37,7 +36,7 @@ class GitIgnore(SimpleNamespace):
"""Gitignore constants."""

# The gitignore file.
FILE = ".gitignore"
FILE = Path(".gitignore")
# Files to gitignore.
DEFAULTS = {Dirs.WEB, "*.db", "__pycache__/", "*.py[cod]", "assets/external/"}

Expand Down
Loading
Loading