mirror of
https://github.com/rasbt/LLMs-from-scratch.git
synced 2026-04-10 12:33:42 +00:00
Uv workflow improvements (#531)
* Uv workflow improvements * Uv workflow improvements * linter improvements * pytproject.toml fixes * pytproject.toml fixes * pytproject.toml fixes * pytproject.toml fixes * pytproject.toml fixes * pytproject.toml fixes * windows fixes * windows fixes * windows fixes * windows fixes * windows fixes * windows fixes * win32 fix * win32 fix * win32 fix * win32 fix * win32 fix * win32 fix * win32 fix * win32 fix * win32 fix * win32 fix * win32 fix * win32 fix * win32 fix * win32 fix * win32 fix * win32 fix * win32 fix * win32 fix * win32 fix
This commit is contained in:
committed by
GitHub
parent
29353c74d8
commit
a08d7aaa84
@@ -3,99 +3,100 @@
|
||||
# - https://www.manning.com/books/build-a-large-language-model-from-scratch
|
||||
# Code: https://github.com/rasbt/LLMs-from-scratch
|
||||
|
||||
from importlib.metadata import PackageNotFoundError, import_module
|
||||
import importlib.metadata
|
||||
|
||||
from importlib.metadata import PackageNotFoundError, import_module, version as get_version
|
||||
from os.path import dirname, exists, join, realpath
|
||||
from packaging.version import parse as version_parse
|
||||
from packaging.requirements import Requirement
|
||||
from packaging.specifiers import SpecifierSet
|
||||
import platform
|
||||
import sys
|
||||
|
||||
if version_parse(platform.python_version()) < version_parse("3.9"):
|
||||
print("[FAIL] We recommend Python 3.9 or newer but"
|
||||
" found version %s" % (sys.version))
|
||||
print("[FAIL] We recommend Python 3.9 or newer but found version %s" % sys.version)
|
||||
else:
|
||||
print("[OK] Your Python version is %s" % (platform.python_version()))
|
||||
print("[OK] Your Python version is %s" % platform.python_version())
|
||||
|
||||
|
||||
def get_packages(pkgs):
|
||||
versions = []
|
||||
"""
|
||||
Returns a dictionary mapping package names (in lowercase) to their installed version.
|
||||
"""
|
||||
result = {}
|
||||
for p in pkgs:
|
||||
try:
|
||||
# Try to import the package
|
||||
imported = import_module(p)
|
||||
try:
|
||||
version = (getattr(imported, "__version__", None) or
|
||||
getattr(imported, "version", None) or
|
||||
getattr(imported, "version_info", None))
|
||||
version = getattr(imported, "__version__", None)
|
||||
if version is None:
|
||||
# If common attributes don"t exist, use importlib.metadata
|
||||
version = importlib.metadata.version(p)
|
||||
versions.append(version)
|
||||
version = get_version(p)
|
||||
result[p.lower()] = version
|
||||
except PackageNotFoundError:
|
||||
# Handle case where package is not installed
|
||||
versions.append("0.0")
|
||||
result[p.lower()] = "0.0"
|
||||
except ImportError:
|
||||
# Fallback if importlib.import_module fails for unexpected reasons
|
||||
versions.append("0.0")
|
||||
return versions
|
||||
result[p.lower()] = "0.0"
|
||||
return result
|
||||
|
||||
|
||||
def get_requirements_dict():
|
||||
"""
|
||||
Parses requirements.txt and returns a dictionary mapping package names (lowercase)
|
||||
to a specifier string (e.g. ">=2.18.0,<3.0"). It uses packaging.requirements.Requirement
|
||||
to properly handle environment markers.
|
||||
"""
|
||||
|
||||
PROJECT_ROOT = dirname(realpath(__file__))
|
||||
PROJECT_ROOT_UP_TWO = dirname(dirname(PROJECT_ROOT))
|
||||
REQUIREMENTS_FILE = join(PROJECT_ROOT_UP_TWO, "requirements.txt")
|
||||
if not exists(REQUIREMENTS_FILE):
|
||||
REQUIREMENTS_FILE = join(PROJECT_ROOT, "requirements.txt")
|
||||
|
||||
d = {}
|
||||
reqs = {}
|
||||
with open(REQUIREMENTS_FILE) as f:
|
||||
for line in f:
|
||||
if not line.strip():
|
||||
# Remove inline comments and trailing whitespace.
|
||||
# This splits on the first '#' and takes the part before it.
|
||||
line = line.split("#", 1)[0].strip()
|
||||
if not line:
|
||||
continue
|
||||
if "," in line:
|
||||
left, right = line.split(",")
|
||||
lower = right.split("#")[0].strip()
|
||||
package, _, upper = left.split(" ")
|
||||
package = package.strip()
|
||||
_, lower = lower.split(" ")
|
||||
lower = lower.strip()
|
||||
upper = upper.strip()
|
||||
d[package] = (upper, lower)
|
||||
else:
|
||||
line = line.split("#")[0].strip()
|
||||
line = line.split(" ")
|
||||
line = [ln.strip() for ln in line]
|
||||
d[line[0]] = line[-1]
|
||||
return d
|
||||
try:
|
||||
req = Requirement(line)
|
||||
except Exception as e:
|
||||
print(f"Skipping line due to parsing error: {line} ({e})")
|
||||
continue
|
||||
# Evaluate the marker if present.
|
||||
if req.marker is not None and not req.marker.evaluate():
|
||||
continue
|
||||
# Store the package name and its version specifier.
|
||||
spec = str(req.specifier) if req.specifier else ">=0"
|
||||
reqs[req.name.lower()] = spec
|
||||
return reqs
|
||||
|
||||
|
||||
def check_packages(d):
|
||||
versions = get_packages(d.keys())
|
||||
|
||||
for (pkg_name, suggested_ver), actual_ver in zip(d.items(), versions):
|
||||
if isinstance(suggested_ver, tuple):
|
||||
lower, upper = suggested_ver[0], suggested_ver[1]
|
||||
else:
|
||||
lower = suggested_ver
|
||||
upper = None
|
||||
def check_packages(reqs):
|
||||
"""
|
||||
Checks the installed versions of packages against the requirements.
|
||||
"""
|
||||
installed = get_packages(reqs.keys())
|
||||
for pkg_name, spec_str in reqs.items():
|
||||
spec_set = SpecifierSet(spec_str)
|
||||
actual_ver = installed.get(pkg_name, "0.0")
|
||||
if actual_ver == "N/A":
|
||||
continue
|
||||
actual_ver = version_parse(actual_ver)
|
||||
lower = version_parse(lower)
|
||||
if upper is not None:
|
||||
upper = version_parse(upper)
|
||||
if actual_ver < lower and upper is None:
|
||||
print(f"[FAIL] {pkg_name} {actual_ver}, please upgrade to >= {lower}")
|
||||
elif actual_ver < lower:
|
||||
print(f"[FAIL] {pkg_name} {actual_ver}, please upgrade to >= {lower} and < {upper}")
|
||||
elif upper is not None and actual_ver >= upper:
|
||||
print(f"[FAIL] {pkg_name} {actual_ver}, please downgrade to >= {lower} and < {upper}")
|
||||
actual_ver_parsed = version_parse(actual_ver)
|
||||
# If the installed version is a pre-release, allow pre-releases in the specifier.
|
||||
if actual_ver_parsed.is_prerelease:
|
||||
spec_set.prereleases = True
|
||||
if actual_ver_parsed not in spec_set:
|
||||
print(f"[FAIL] {pkg_name} {actual_ver_parsed}, please install a version matching {spec_set}")
|
||||
else:
|
||||
print(f"[OK] {pkg_name} {actual_ver}")
|
||||
print(f"[OK] {pkg_name} {actual_ver_parsed}")
|
||||
|
||||
|
||||
def main():
|
||||
d = get_requirements_dict()
|
||||
check_packages(d)
|
||||
reqs = get_requirements_dict()
|
||||
check_packages(reqs)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user