Skip to content

Commit

Permalink
icm install: Initial prototype
Browse files Browse the repository at this point in the history
  • Loading branch information
Obijuan committed Jun 17, 2024
1 parent bcac55a commit 94afbe0
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 143 deletions.
12 changes: 12 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,18 @@
"internalConsoleOptions": "neverOpen",
"preLaunchTask": "Clear terminal",
},
{
"name": "ICM install",
"type": "debugpy",
"request": "launch",
"program": "icm-run.py",
"args": ["install"],
//"console": "internalConsole",
"console": "integratedTerminal",
"justMyCode": true,
"internalConsoleOptions": "neverOpen",
"preLaunchTask": "Clear terminal",
},
]
}

14 changes: 13 additions & 1 deletion icm/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@

import click

from icm.commands import cmd_create, cmd_validate, cmd_update, cmd_info
from icm.commands import (
cmd_create,
cmd_validate,
cmd_update,
cmd_info,
cmd_install,
)


@click.group()
Expand Down Expand Up @@ -39,3 +45,9 @@ def validate():
def info():
"""Show system information"""
cmd_info.main()


@cli.command()
def install():
"""Install collections"""
cmd_install.main()
147 changes: 5 additions & 142 deletions icm/commands/cmd_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,73 +9,11 @@
# -- Licence GPLv2

import platform
import shutil
import zipfile
import os
from pathlib import Path
from typing import NamedTuple

import requests
import click
from tqdm import tqdm


# -- Context information
class Context(NamedTuple):
"""general Context information"""

@property
def terminal_width(self) -> int:
"""Get the terminal with in columns"""
return shutil.get_terminal_size().columns

@property
def line(self) -> str:
"""Return a line as long as the terminal width"""
return "─" * self.terminal_width


# -- Folder information
class Folders(NamedTuple):
"""Icestudio related folders"""

@property
def home(self) -> Path:
"""Return the home user folder"""
return Path.home()
from icm.commons import commons

@property
def icestudio(self) -> Path:
"""Return the icestudio data folder"""
return self.home / ".icestudio"

@property
def collections(self) -> Path:
"""Return the icestudio collections folder"""
return self.icestudio / "collections"

@staticmethod
def check(folder: Path) -> str:
"""Return a check character depending if the folder exists
✅ : Folder exists
❌ : Folder does NOT exist
"""
return "✅ " if folder.exists() else "❌ "


# -- Information about collections
icek = {"name": "iceK", "version": "0.1.4"}

# -- Collection file
COLLECTION_FILE = "v"

# -- Template URL
# -- Full collection download url: PREFIX + NAME + SUFFIX + FILE
TEMPLATE_URL_PREFIX = "https://github.com/FPGAwars/"
TEMPLATE_URL_SUFFIX = "/archive/refs/tags/"


def print_system_info(ctx: Context) -> None:
def print_system_info(ctx: commons.Context) -> None:
"""Print System information"""

# -- Header
Expand All @@ -94,7 +32,7 @@ def print_system_info(ctx: Context) -> None:
click.echo(click.style("• Version: ", fg="green") + f"{plat.version}")


def print_folders_info(ctx: Context, folders: Folders) -> None:
def print_folders_info(ctx: commons.Context, folders: commons.Folders) -> None:
"""Print Sytem folders info"""

# -- Header
Expand Down Expand Up @@ -127,8 +65,8 @@ def main():
"""ENTRY POINT: Show system information"""

# -- Get context information
ctx = Context()
folders = Folders()
ctx = commons.Context()
folders = commons.Folders()

# --------------------------------
# -- Print System information
Expand All @@ -139,78 +77,3 @@ def main():
# -- System folders
# ----------------------------
print_folders_info(ctx, folders)

# --- Scafold for the installation of collections
# -- Download url:
# https://github.com/FPGAwars/iceK/archive/refs/tags/v0.1.4.zip
# -- Build the collection filename
filename = f"v{icek['version']}.zip"
print(f"Colection file: {filename}")

absolut_filename = f"{folders.collections}/{filename}"
print(f"Absolut filename: {absolut_filename}")

url = f"{TEMPLATE_URL_PREFIX}{icek['name']}{TEMPLATE_URL_SUFFIX}{filename}"
print(f"Url: {url}")

# -- Download the collection
# Realizar la solicitud HTTP para obtener el contenido del archivo
response = requests.get(url, stream=True, timeout=10)

# Verificar que la solicitud se completó correctamente
if response.status_code == 200:

# Obtener el tamaño total del archivo desde los headers
total_size = int(response.headers.get("content-length", 0))

# Abrir un archivo local con el nombre especificado en
# modo escritura binaria
with open(absolut_filename, "wb") as file:

# Crear una barra de progreso con tqdm
with tqdm(
total=total_size, unit="B", unit_scale=True, desc=filename
) as pbar:
# Iterar sobre el contenido en bloques
for chunk in response.iter_content(chunk_size=1024):
# Filtrar bloques vacíos
if chunk:
# Escribir el contenido del bloque en el archivo local
file.write(chunk)
# Actualizar la barra de progreso
pbar.update(len(chunk))

# shutil.copyfileobj(response.raw, file)
print(f"Archivo descargado y guardado como {filename}")
else:
print(
f"Error al descargar el archivo. "
f"Código de estado: {response.status_code}"
)

# -- Uncompress the collection

# Nombre del archivo ZIP
zip_filename = absolut_filename

# Directorio de destino para descomprimir los archivos
extract_to = folders.collections

# Abrir el archivo ZIP y extraer su contenido con barra de progreso
with zipfile.ZipFile(zip_filename, "r") as zip_ref:
# Obtener la lista de archivos en el archivo ZIP
file_list = zip_ref.namelist()

# Crear una barra de progreso
with tqdm(
total=len(file_list), desc="Descomprimiendo", unit="file"
) as pbar:
# Iterar sobre cada archivo en el archivo ZIP
for file in file_list:
# Extraer cada archivo
zip_ref.extract(file, extract_to)
# Actualizar la barra de progreso
pbar.update(1)

# -- Borrar el archivo zip
os.remove(zip_filename)
102 changes: 102 additions & 0 deletions icm/commands/cmd_install.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
"""Install command"""

import zipfile
import os
import requests
from tqdm import tqdm
from icm.commons import commons

# -- Information about collections
icek = {"name": "iceK", "version": "0.1.4"}

# -- Collection file
COLLECTION_FILE = "v"

# -- Template URL
# -- Full collection download url: PREFIX + NAME + SUFFIX + FILE
TEMPLATE_URL_PREFIX = "https://github.com/FPGAwars/"
TEMPLATE_URL_SUFFIX = "/archive/refs/tags/"


def main():
"""ENTRY POINT: Install collections"""

# -- Get context information
folders = commons.Folders()

print("Install!!!")

# --- Scafold for the installation of collections
# -- Download url:
# https://github.com/FPGAwars/iceK/archive/refs/tags/v0.1.4.zip
# -- Build the collection filename
filename = f"v{icek['version']}.zip"
print(f"Colection file: {filename}")

absolut_filename = f"{folders.collections}/{filename}"
print(f"Absolut filename: {absolut_filename}")

url = f"{TEMPLATE_URL_PREFIX}{icek['name']}{TEMPLATE_URL_SUFFIX}{filename}"
print(f"Url: {url}")

# -- Download the collection
# Realizar la solicitud HTTP para obtener el contenido del archivo
response = requests.get(url, stream=True, timeout=10)

# Verificar que la solicitud se completó correctamente
if response.status_code == 200:

# Obtener el tamaño total del archivo desde los headers
total_size = int(response.headers.get("content-length", 0))

# Abrir un archivo local con el nombre especificado en
# modo escritura binaria
with open(absolut_filename, "wb") as file:

# Crear una barra de progreso con tqdm
with tqdm(
total=total_size, unit="B", unit_scale=True, desc=filename
) as pbar:
# Iterar sobre el contenido en bloques
for chunk in response.iter_content(chunk_size=1024):
# Filtrar bloques vacíos
if chunk:
# Escribir el contenido del bloque en el archivo local
file.write(chunk)
# Actualizar la barra de progreso
pbar.update(len(chunk))

# shutil.copyfileobj(response.raw, file)
print(f"Archivo descargado y guardado como {filename}")
else:
print(
f"Error al descargar el archivo. "
f"Código de estado: {response.status_code}"
)

# -- Uncompress the collection

# Nombre del archivo ZIP
zip_filename = absolut_filename

# Directorio de destino para descomprimir los archivos
extract_to = folders.collections

# Abrir el archivo ZIP y extraer su contenido con barra de progreso
with zipfile.ZipFile(zip_filename, "r") as zip_ref:
# Obtener la lista de archivos en el archivo ZIP
file_list = zip_ref.namelist()

# Crear una barra de progreso
with tqdm(
total=len(file_list), desc="Descomprimiendo", unit="file"
) as pbar:
# Iterar sobre cada archivo en el archivo ZIP
for file in file_list:
# Extraer cada archivo
zip_ref.extract(file, extract_to)
# Actualizar la barra de progreso
pbar.update(1)

# -- Borrar el archivo zip
os.remove(zip_filename)
Empty file added icm/commons/__init__.py
Empty file.
48 changes: 48 additions & 0 deletions icm/commons/commons.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"""Data structures common to all the modules"""

from typing import NamedTuple
import shutil
from pathlib import Path


# -- Context information
class Context(NamedTuple):
"""general Context information"""

@property
def terminal_width(self) -> int:
"""Get the terminal with in columns"""
return shutil.get_terminal_size().columns

@property
def line(self) -> str:
"""Return a line as long as the terminal width"""
return "─" * self.terminal_width


# -- Folder information
class Folders(NamedTuple):
"""Icestudio related folders"""

@property
def home(self) -> Path:
"""Return the home user folder"""
return Path.home()

@property
def icestudio(self) -> Path:
"""Return the icestudio data folder"""
return self.home / ".icestudio"

@property
def collections(self) -> Path:
"""Return the icestudio collections folder"""
return self.icestudio / "collections"

@staticmethod
def check(folder: Path) -> str:
"""Return a check character depending if the folder exists
✅ : Folder exists
❌ : Folder does NOT exist
"""
return "✅ " if folder.exists() else "❌ "

0 comments on commit 94afbe0

Please sign in to comment.