Python API для Github, получение содержимого в определенном каталоге для конкретной ветки, не возвращающее все содержимое

#python #git #github

#python #git #github

Вопрос:

Используя PyGithub API, я пытаюсь извлечь все содержимое из определенной папки из определенной ветки репозитория, размещенного на Github. Я не могу поделиться фактическим репозиторием или спецификой данных, но код, который я использую, таков:

 import github
import json
import requests
import base64

from collections import namedtuple
Package = namedtuple('Package', 'name version')

# Parameters
gh_token = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
header = {"Authorization": f"token {gh_token}"}
gh_hostname = 'devtopia.xxx.com'
gh = github.Github(base_url=f'https://{gh_hostname}/api/v3', login_or_token = gh_token)
repo_name = "xxxxxxxxx/SupportFiles"
conda_meta = "xxxxxxx/bin/Python/envs/xxxxxx-xx/conda-meta"
repo = gh.get_repo(repo_name)


def parse_conda_meta(branch):
    package_list = []
    meta_contents = repo.get_contents(conda_meta, ref=branch)  #<< Returns less files than expected for 
                                                               # a specified branch "xxx/release/3.2.0",
                                                               # returns expected number of files for 
                                                               # "master" branch.
    for i, pkg in enumerate(meta_contents):
        if ".json" in pkg.name:  # filter for JSON files
            print(i, pkg.name)
            # Need to use GitHub Data API (REST) blobs instead of easier
            # `github` with `pkg.decoded_content` here because that method
            # only works with files <= 1MB whereas Data API allows for
            # reading files <= 100MB.
            resp = requests.get(f"https://devtopia.xxxx.com/api/v3/repos/xxxxxxxxx/SupportFiles/git/blobs/{pkg.sha}?ref={branch}", headers=header)
            pkg_cont = json.loads(base64.b64decode(json.loads(resp.content)["content"]))
            package_list.append(Package(pkg_cont['name'], pkg_cont['version']))
        else:
            print('>>', i, pkg.name)
    return package_list


if __name__ == "__main__":
    pkgs = parse_conda_meta("xxx/release/3.2.0")
    print(pkgs)
    print(len(pkgs))
 

По какой-то причине, в которой я не могу разобраться, я не получаю правильное количество возвращаемых файлов repo.get_contents(conda_meta, ref=branch) . Для ветки, которую я указываю, когда эта ветка извлекается, я вижу 186 файлов в папке conda-meta. Однако repo.get_contents(conda_meta, ref=branch) возвращает только 182, мне не хватает четырех файлов JSON.

Есть ли какие-то ограничения repo.get_contents , о которых я не знаю? Я читал документ, но не могу найти ничего, что намекало бы на проблему, с которой я столкнулся. Есть один момент, когда он обрабатывает только файлы размером до 1 МБ, но я вижу возвращаемые файлы большего размера, чем этот (например, python равен 1.204МБ и возвращается в списке файлов). Я считаю, что это относится только к чтению содержимого файла более 1 МБ, с которым я справляюсь, используя GitHub Data API (REST) дальше по потоку. Я что-то делаю не так?

Спасибо за чтение, любая помощь в этом очень ценится!

Комментарии:

1. Я вижу, вы анонимизировали имя хоста, это для GitHub Enterprise? Если да, то какая версия?

2. Эй, я полагаю, что это нормально, чтобы поделиться, мы используем Devtopia , см. Обновленный исходный пост с именем хоста, не анонимизированным. Спасибо!

Ответ №1:

Обновление с решением!

Проблема:

После еще нескольких поисков я нашел причину проблемы. Это не связано с приведенным выше кодом или repo.get_contents(conda_meta, ref=branch) конкретно. На самом деле это столкновение unix / windows, которое было ошибочно введено в наш репозиторий для этой конкретной ветки «xxx / release / 3.2.0», но отсутствует в других.

Итак, в чем была проблема? NTFS (и Windows в более широком смысле) по умолчанию не учитывает регистр, но Git из мира Unix и по умолчанию учитывает регистр

Мы непреднамеренно создали две папки для Python в каталоге bin conda_meta path ( xxxxxx/bin/ ), одну папку с именем «Python» и одну с именем «python» (обратите внимание на нижний регистр). При локальном извлечении репозитория отображается только папка «Python», содержащая все 168 файлов. Однако на GitHub путь с «Python» содержит 182 файла, в то время как путь с «python» содержит оставшиеся 4 файла.

Решение:

Решение состоит в том, чтобы добавить conda_meta_folders параметр, который принимает список путей к parse_conda_meta каждому каталогу и выполняет поиск в нем. Хотя может быть более простое решение, я изучаю, возможно ли сделать что-то подобное git config core.ignorecase true с PyGithub API. Кто-нибудь знает, возможно ли, чтобы PyGithub соблюдал это или был настроен для этого?

Комментарии:

1. core.ignorecase это не настройка для управления Git, а скорее настройка для информирования Git. Он сообщает Git: Эй, если вы создаете Python/, а затем пишете python/foo.py , это закончится в Python/foo.py вместо этого. Если вы включите или выключите его, вы неправильно информируете Git: он настроен на основе того, как на самом деле ведет себя ваш компьютер (Git пробует несколько вещей при первом создании репозитория, чтобы выяснить, как ведет себя ваш компьютер).