version turbo y version .go
This commit is contained in:
parent
778b286369
commit
4e0067a368
10
compila-go.sh
Normal file
10
compila-go.sh
Normal file
@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
echo "Compilando version Linux:"
|
||||
GO111MODULE=off GOOS=linux GOARCH=amd64 go build -o pipinfo.bin pipinfo.go
|
||||
GO111MODULE=off GOOS=linux GOARCH=amd64 go build -o pipbusca.bin pipbusca.go
|
||||
echo
|
||||
echo "Compilando version Windows:"
|
||||
GO111MODULE=off GOOS=windows GOARCH=amd64 go build -o pipinfo.exe pipinfo.go
|
||||
GO111MODULE=off GOOS=windows GOARCH=amd64 go build -o pipbusca.exe pipbusca.go
|
||||
echo
|
||||
|
||||
37
pip_busca-turbo
Normal file
37
pip_busca-turbo
Normal file
@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import requests
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print("Uso: pip_busca <cadena>")
|
||||
sys.exit(1)
|
||||
|
||||
query = sys.argv[1].lower()
|
||||
url = "https://pypi.org/simple/"
|
||||
|
||||
# Descarga en streaming (sin cargar todo en memoria)
|
||||
resp = requests.get(url, stream=True)
|
||||
|
||||
if resp.status_code != 200:
|
||||
print("❌ Error al descargar índice de PyPI")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"🔍 Buscando: {query}\n")
|
||||
|
||||
encontrados = 0
|
||||
max_resultados = 50 # configurable
|
||||
|
||||
for line in resp.iter_lines(decode_unicode=True):
|
||||
if not line:
|
||||
continue
|
||||
# Las líneas tienen formato: <a href="...">Nombre</a>
|
||||
if "<a href=" in line.lower():
|
||||
nombre = line.split(">")[1].split("<")[0]
|
||||
if query in nombre.lower():
|
||||
print(f"📦 {nombre}")
|
||||
encontrados += 1
|
||||
if encontrados >= max_resultados:
|
||||
break
|
||||
|
||||
if encontrados == 0:
|
||||
print("❌ No se encontraron paquetes.")
|
||||
107
pip_info-turbo
Normal file
107
pip_info-turbo
Normal file
@ -0,0 +1,107 @@
|
||||
#!/bin/bash
|
||||
# pip_info v2.0 — Luis GuLo Edition
|
||||
|
||||
mostrar_ayuda() {
|
||||
echo "═══════════════════════════════════════════════════════════════════════"
|
||||
echo "Uso: $0 <paquete> [--all] [--json]"
|
||||
echo ""
|
||||
echo "Opciones:"
|
||||
echo " --all Mostrar TODAS las versiones (incluye pre-release)"
|
||||
echo " --json Salida en JSON puro"
|
||||
echo ""
|
||||
echo "Por defecto muestra las 10 últimas versiones estables."
|
||||
echo "═══════════════════════════════════════════════════════════════════════"
|
||||
}
|
||||
|
||||
# ----------------------
|
||||
# Validación de argumentos
|
||||
# ----------------------
|
||||
if [[ "$1" == "--help" || "$1" == "-h" ]]; then
|
||||
mostrar_ayuda
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "❌ Error: Debe indicar el nombre del paquete."
|
||||
mostrar_ayuda
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PAQUETE="$1"
|
||||
FLAG_ALL="$2"
|
||||
FLAG_JSON="$3"
|
||||
|
||||
URL="https://pypi.org/pypi/$PAQUETE/json"
|
||||
RESPUESTA=$(curl -s "$URL")
|
||||
|
||||
# ----------------------
|
||||
# Validación del JSON
|
||||
# ----------------------
|
||||
if ! echo "$RESPUESTA" | jq empty 2>/dev/null; then
|
||||
echo "❌ PyPI devolvió una respuesta no válida (¿paquete inexistente?)."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! echo "$RESPUESTA" | jq -e '.info.name' >/dev/null; then
|
||||
echo "❌ No se encontró información para '$PAQUETE'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Salida JSON pura
|
||||
if [[ "$FLAG_ALL" == "--json" || "$FLAG_JSON" == "--json" ]]; then
|
||||
echo "$RESPUESTA"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ----------------------
|
||||
# Obtener campos principales
|
||||
# ----------------------
|
||||
NOMBRE=$(echo "$RESPUESTA" | jq -r '.info.name')
|
||||
VERSION=$(echo "$RESPUESTA" | jq -r '.info.version')
|
||||
DESCRIPCION=$(echo "$RESPUESTA" | jq -r '.info.summary')
|
||||
|
||||
echo "📦 Paquete: $NOMBRE"
|
||||
echo "🔢 Última versión: $VERSION"
|
||||
echo "📝 Descripción: $DESCRIPCION"
|
||||
echo
|
||||
|
||||
# ----------------------
|
||||
# Funciones para listar versiones
|
||||
# ----------------------
|
||||
|
||||
mostrar_estables() {
|
||||
echo "📚 Últimas 10 versiones ESTABLES:"
|
||||
echo
|
||||
|
||||
echo "$RESPUESTA" \
|
||||
| jq -r '.releases | keys[]' \
|
||||
| grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' \
|
||||
| sort -V -r \
|
||||
| head -n 10 \
|
||||
| while read v; do
|
||||
PY=$(echo "$RESPUESTA" | jq -r ".releases[\"$v\"][0].requires_python // \"N/A\"")
|
||||
printf " %-15s (Python %s)\n" "$v" "$PY"
|
||||
done
|
||||
}
|
||||
|
||||
mostrar_todas() {
|
||||
echo "📚 Todas las versiones:"
|
||||
echo
|
||||
|
||||
echo "$RESPUESTA" \
|
||||
| jq -r '.releases | keys[]' \
|
||||
| sort -V -r \
|
||||
| while read v; do
|
||||
PY=$(echo "$RESPUESTA" | jq -r ".releases[\"$v\"][0].requires_python // \"N/A\"")
|
||||
printf " %-15s (Python %s)\n" "$v" "$PY"
|
||||
done
|
||||
}
|
||||
|
||||
# ----------------------
|
||||
# Selección del modo
|
||||
# ----------------------
|
||||
if [[ "$FLAG_ALL" == "--all" ]]; then
|
||||
mostrar_todas
|
||||
else
|
||||
mostrar_estables
|
||||
fi
|
||||
BIN
pipbusca.bin
Normal file
BIN
pipbusca.bin
Normal file
Binary file not shown.
BIN
pipbusca.exe
Normal file
BIN
pipbusca.exe
Normal file
Binary file not shown.
143
pipbusca.go
Normal file
143
pipbusca.go
Normal file
@ -0,0 +1,143 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func extractAnchorText(line string) (string, bool) {
|
||||
// Busca el texto entre > y < del primer <a ...>...</a>
|
||||
gt := strings.Index(line, ">")
|
||||
if gt == -1 {
|
||||
return "", false
|
||||
}
|
||||
lt := strings.Index(line[gt+1:], "<")
|
||||
if lt == -1 {
|
||||
return "", false
|
||||
}
|
||||
text := line[gt+1 : gt+1+lt]
|
||||
text = strings.TrimSpace(text)
|
||||
if text == "" {
|
||||
return "", false
|
||||
}
|
||||
return text, true
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Flags
|
||||
maxResults := flag.Int("max", 30, "Número máximo de resultados a mostrar")
|
||||
prefix := flag.Bool("prefix", false, "Buscar por prefijo en lugar de subcadena")
|
||||
timeout := flag.Duration("timeout", 20*time.Second, "Timeout de la petición HTTP (e.g., 10s, 2m)")
|
||||
noColor := flag.Bool("nocolor", false, "Desactivar iconos/colores")
|
||||
flag.Parse()
|
||||
|
||||
if flag.NArg() < 1 {
|
||||
fmt.Println("Uso: pip_busca [opciones] <cadena_busqueda>")
|
||||
fmt.Println("Opciones:")
|
||||
fmt.Println(" -max N Limitar el número de resultados (por defecto 30)")
|
||||
fmt.Println(" -prefix Coincidencia por prefijo (más rápida si buscas por inicio)")
|
||||
fmt.Println(" -timeout DUR Timeout de HTTP (por defecto 20s)")
|
||||
fmt.Println(" -nocolor Desactiva iconos/colores en salida")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
query := strings.ToLower(flag.Arg(0))
|
||||
url := "https://pypi.org/simple/"
|
||||
|
||||
client := &http.Client{Timeout: *timeout}
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "❌ Error creando petición: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
req.Header.Set("User-Agent", "pip_busca-go/1.0 (+https://pypi.org)")
|
||||
req.Header.Set("Accept", "text/html")
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "❌ Error conectando con PyPI: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
fmt.Fprintf(os.Stderr, "❌ Respuesta HTTP no OK: %s\n", resp.Status)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if !*noColor {
|
||||
fmt.Printf("🔍 Buscando: %s\n\n", query)
|
||||
} else {
|
||||
fmt.Printf("Buscando: %s\n\n", query)
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(resp.Body)
|
||||
// Aumenta el buffer por si alguna línea es grande (aunque en /simple suele ser pequeño)
|
||||
const maxLine = 1024 * 1024 // 1 MiB
|
||||
buf := make([]byte, 64*1024)
|
||||
scanner.Buffer(buf, maxLine)
|
||||
|
||||
encontrados := 0
|
||||
queryStarted := false // para modo -prefix: romper cuando superemos el bloque
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
// Normalizamos a minúsculas para buscar
|
||||
lower := strings.ToLower(line)
|
||||
|
||||
// Solo nos interesan líneas con anclas
|
||||
if !strings.Contains(lower, "<a ") || !strings.Contains(lower, "</a>") {
|
||||
continue
|
||||
}
|
||||
|
||||
name, ok := extractAnchorText(line)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
nameLower := strings.ToLower(name)
|
||||
|
||||
match := false
|
||||
if *prefix {
|
||||
// Coincidencia por prefijo
|
||||
if strings.HasPrefix(nameLower, query) {
|
||||
match = true
|
||||
queryStarted = true
|
||||
} else if queryStarted {
|
||||
// /simple/ está ordenado; si ya pasamos el bloque del prefijo, podemos cortar.
|
||||
// Cuando el nombre actual ya no empieza por el prefijo y ya habíamos empezado
|
||||
// a encontrar coincidencias, significa que hemos superado la zona.
|
||||
break
|
||||
}
|
||||
} else {
|
||||
// Coincidencia por subcadena
|
||||
if strings.Contains(nameLower, query) {
|
||||
match = true
|
||||
}
|
||||
}
|
||||
|
||||
if match {
|
||||
if !*noColor {
|
||||
fmt.Printf("📦 %s\n", name)
|
||||
} else {
|
||||
fmt.Println(name)
|
||||
}
|
||||
encontrados++
|
||||
if encontrados >= *maxResults {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "⚠️ Aviso: error leyendo la respuesta: %v\n", err)
|
||||
}
|
||||
|
||||
if encontrados == 0 {
|
||||
fmt.Println("❌ No se encontraron paquetes.")
|
||||
}
|
||||
}
|
||||
BIN
pipinfo.bin
Normal file
BIN
pipinfo.bin
Normal file
Binary file not shown.
BIN
pipinfo.exe
Normal file
BIN
pipinfo.exe
Normal file
Binary file not shown.
98
pipinfo.go
Normal file
98
pipinfo.go
Normal file
@ -0,0 +1,98 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type ReleaseInfo struct {
|
||||
RequiresPython string `json:"requires_python"`
|
||||
}
|
||||
|
||||
type PackageInfo struct {
|
||||
Info struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
Summary string `json:"summary"`
|
||||
} `json:"info"`
|
||||
Releases map[string][]ReleaseInfo `json:"releases"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
if len(os.Args) < 2 {
|
||||
fmt.Println("Uso: pipinfo <paquete> [--all]")
|
||||
return
|
||||
}
|
||||
|
||||
pkg := os.Args[1]
|
||||
showAll := len(os.Args) > 2 && os.Args[2] == "--all"
|
||||
|
||||
url := fmt.Sprintf("https://pypi.org/pypi/%s/json", pkg)
|
||||
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
fmt.Printf("❌ Error de conexión: %v\n", err)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
fmt.Printf("❌ No se encontró el paquete '%s'\n", pkg)
|
||||
return
|
||||
}
|
||||
|
||||
var data PackageInfo
|
||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||
fmt.Printf("❌ Error procesando JSON: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("📦 Paquete: %s\n", data.Info.Name)
|
||||
fmt.Printf("🔢 Última versión: %s\n", data.Info.Version)
|
||||
fmt.Printf("📝 Descripción: %s\n\n", data.Info.Summary)
|
||||
|
||||
// Obtener lista de versiones
|
||||
versions := make([]string, 0, len(data.Releases))
|
||||
for v := range data.Releases {
|
||||
versions = append(versions, v)
|
||||
}
|
||||
|
||||
sort.Slice(versions, func(i, j int) bool {
|
||||
return versions[i] > versions[j]
|
||||
})
|
||||
|
||||
stableRegex := regexp.MustCompile(`^[0-9]+\.[0-9]+\.[0-9]+$`)
|
||||
|
||||
count := 0
|
||||
|
||||
if showAll {
|
||||
fmt.Println("📚 Todas las versiones:")
|
||||
for _, v := range versions {
|
||||
req := "N/A"
|
||||
if len(data.Releases[v]) > 0 && data.Releases[v][0].RequiresPython != "" {
|
||||
req = data.Releases[v][0].RequiresPython
|
||||
}
|
||||
fmt.Printf(" %-12s (Python %s)\n", v, req)
|
||||
}
|
||||
} else {
|
||||
fmt.Println("📚 Últimas 10 versiones estables:\n")
|
||||
for _, v := range versions {
|
||||
if stableRegex.MatchString(v) {
|
||||
req := "N/A"
|
||||
if len(data.Releases[v]) > 0 && data.Releases[v][0].RequiresPython != "" {
|
||||
req = data.Releases[v][0].RequiresPython
|
||||
}
|
||||
fmt.Printf(" %-12s (Python %s)\n", v, req)
|
||||
count++
|
||||
if count == 10 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user