2024-01-22 10:36:06 +00:00
|
|
|
|
package gen
|
|
|
|
|
|
|
|
|
|
import (
|
2024-11-16 08:32:47 +00:00
|
|
|
|
_ "embed" // Пакет для встраивания содержимого файлов в бинарники Go, использовав откладку //go:embed
|
|
|
|
|
"encoding/json" // Пакет для работы с JSON: декодирование и кодирование
|
|
|
|
|
"errors" // Пакет для создания и обработки ошибок
|
|
|
|
|
"fmt" // Пакет для форматированного ввода и вывода
|
|
|
|
|
"io" // Пакет для интерфейсов ввода и вывода
|
|
|
|
|
"net/http" // Пакет для HTTP-клиентов и серверов
|
|
|
|
|
"text/template" // Пакет для обработки текстовых шаблонов
|
2024-01-22 10:36:06 +00:00
|
|
|
|
)
|
|
|
|
|
|
2024-11-16 08:32:47 +00:00
|
|
|
|
// Используем директиву //go:embed для встраивания содержимого файла шаблона в строку pipTmpl
|
|
|
|
|
// Встраивание файла tmpls/pip.tmpl.sh
|
2024-01-22 10:36:06 +00:00
|
|
|
|
//go:embed tmpls/pip.tmpl.sh
|
|
|
|
|
var pipTmpl string
|
|
|
|
|
|
2024-11-16 08:32:47 +00:00
|
|
|
|
// PipOptions содержит параметры, которые будут переданы в шаблон
|
2024-01-22 10:36:06 +00:00
|
|
|
|
type PipOptions struct {
|
2024-11-16 08:32:47 +00:00
|
|
|
|
Name string // Имя пакета
|
|
|
|
|
Version string // Версия пакета
|
|
|
|
|
Description string // Описание пакета
|
2024-01-22 10:36:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-11-16 08:32:47 +00:00
|
|
|
|
// pypiAPIResponse представляет структуру ответа от API PyPI
|
2024-01-22 10:36:06 +00:00
|
|
|
|
type pypiAPIResponse struct {
|
2024-11-16 08:32:47 +00:00
|
|
|
|
Info pypiInfo `json:"info"` // Информация о пакете
|
|
|
|
|
URLs []pypiURL `json:"urls"` // Список URL-адресов для загрузки пакета
|
2024-01-22 10:36:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-11-16 08:32:47 +00:00
|
|
|
|
// Метод SourceURL ищет и возвращает URL исходного distribution для пакета, если он существует
|
2024-01-22 10:36:06 +00:00
|
|
|
|
func (res pypiAPIResponse) SourceURL() (pypiURL, error) {
|
2024-11-16 08:32:47 +00:00
|
|
|
|
for _, url := range res.URLs {
|
|
|
|
|
if url.PackageType == "sdist" {
|
|
|
|
|
return url, nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return pypiURL{}, errors.New("package doesn't have a source distribution")
|
2024-01-22 10:36:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-11-16 08:32:47 +00:00
|
|
|
|
// pypiInfo содержит основную информацию о пакете, такую как имя, версия и пр.
|
2024-01-22 10:36:06 +00:00
|
|
|
|
type pypiInfo struct {
|
2024-11-16 08:32:47 +00:00
|
|
|
|
Name string `json:"name"`
|
|
|
|
|
Version string `json:"version"`
|
|
|
|
|
Summary string `json:"summary"`
|
|
|
|
|
Homepage string `json:"home_page"`
|
|
|
|
|
License string `json:"license"`
|
2024-01-22 10:36:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-11-16 08:32:47 +00:00
|
|
|
|
// pypiURL представляет информацию об одном из доступных для загрузки URL
|
2024-01-22 10:36:06 +00:00
|
|
|
|
type pypiURL struct {
|
2024-11-16 08:32:47 +00:00
|
|
|
|
Digests map[string]string `json:"digests"` // Контрольные суммы для файлов
|
|
|
|
|
Filename string `json:"filename"` // Имя файла
|
|
|
|
|
PackageType string `json:"packagetype"` // Тип пакета (например sdist)
|
2024-01-22 10:36:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-11-16 08:32:47 +00:00
|
|
|
|
// Функция Pip загружает информацию о пакете из PyPI и использует шаблон для вывода информации
|
2024-01-22 10:36:06 +00:00
|
|
|
|
func Pip(w io.Writer, opts PipOptions) error {
|
2024-11-16 08:32:47 +00:00
|
|
|
|
// Создаем новый шаблон с добавлением функций из FuncMap
|
|
|
|
|
tmpl, err := template.New("pip").
|
|
|
|
|
Funcs(funcs).
|
|
|
|
|
Parse(pipTmpl)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2024-01-22 10:36:06 +00:00
|
|
|
|
|
2024-11-16 08:32:47 +00:00
|
|
|
|
// Формируем URL для запроса к PyPI на основании имени и версии пакета
|
|
|
|
|
url := fmt.Sprintf(
|
|
|
|
|
"https://pypi.org/pypi/%s/%s/json",
|
|
|
|
|
opts.Name,
|
|
|
|
|
opts.Version,
|
|
|
|
|
)
|
2024-01-22 10:36:06 +00:00
|
|
|
|
|
2024-11-16 08:32:47 +00:00
|
|
|
|
// Выполняем HTTP GET запрос к PyPI
|
|
|
|
|
res, err := http.Get(url)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
defer res.Body.Close() // Закрываем тело ответа после завершения работы
|
|
|
|
|
if res.StatusCode != 200 {
|
|
|
|
|
return fmt.Errorf("pypi: %s", res.Status)
|
|
|
|
|
}
|
2024-01-22 10:36:06 +00:00
|
|
|
|
|
2024-11-16 08:32:47 +00:00
|
|
|
|
// Раскодируем ответ JSON от PyPI в структуру pypiAPIResponse
|
|
|
|
|
var resp pypiAPIResponse
|
|
|
|
|
err = json.NewDecoder(res.Body).Decode(&resp)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2024-01-22 10:36:06 +00:00
|
|
|
|
|
2024-11-16 08:32:47 +00:00
|
|
|
|
// Если в opts указано описание, используем его вместо описания из PyPI
|
|
|
|
|
if opts.Description != "" {
|
|
|
|
|
resp.Info.Summary = opts.Description
|
|
|
|
|
}
|
2024-01-22 10:36:06 +00:00
|
|
|
|
|
2024-11-16 08:32:47 +00:00
|
|
|
|
// Выполняем шаблон с использованием данных из resp и записываем результат в w
|
|
|
|
|
return tmpl.Execute(w, resp)
|
2024-01-22 10:36:06 +00:00
|
|
|
|
}
|