Skip to content

Commit

Permalink
added method to retrieve release info
Browse files Browse the repository at this point in the history
  • Loading branch information
xrotwang committed Nov 26, 2023
1 parent 39e2f44 commit 91cb4de
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 1 deletion.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changes

## [Unreleased]

- Add Python 3.12 to supported versions.
- Added API method to retrieve release information from GitHub/Zenodo.


## [2.0.0] - 2023-10-20

Zenodo's upgrade from Oct. 13, 2023 brought a couple of breaking changes for the Zenodo API.
Expand Down
3 changes: 2 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ classifiers =
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
Programming Language :: Python :: Implementation :: CPython
Programming Language :: Python :: Implementation :: PyPy
License :: OSI Approved :: Apache Software License
Expand Down Expand Up @@ -92,7 +93,7 @@ show_missing = true
skip_covered = true

[tox:tox]
envlist = py38, py39, py310, py311
envlist = py38, py39, py310, py311, py312
isolated_build = true
skip_missing_interpreter = true

Expand Down
67 changes: 67 additions & 0 deletions src/cldfzenodo/api.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import re
import json
import shlex
import typing
import subprocess
import urllib.error
import urllib.parse
import urllib.request

from pycldf import Source
from pycldf.ext.discovery import DatasetResolver
from clldutils.path import ensure_cmd

from cldfzenodo.record import Record, ZENODO_DOI_FORMAT, ZENODO_DOI_PATTERN, get_doi

Expand Down Expand Up @@ -189,6 +193,69 @@ def iter_records(self,
if res.error:
return res # pragma: no cover

def get_github_release_info(
self,
repos: str,
tag: typing.Optional[str] = None,
bibid: typing.Optional[str] = None
) -> typing.Tuple[
typing.Union[str, None],
typing.Union[str, None],
typing.Union[str, None],
typing.Union[Source, None]
]:
"""
Get information about a GitHub repository release that has been archived with Zenodo.
We assume, that the DOI of the upload on Zenodo has been added to the release description
on GitHub.
:param repos: GitHub repository specifier in the form `org/repo`.
:param tag: Optional version tag.
:param bibid: Optional identifier to use for the BibTeX record.
:return: A quadruple (tag, DOI, APA citation, BibTeX record)
"""
def gh(args):
return subprocess.check_output([ensure_cmd('gh')] + shlex.split(args)).decode('utf8')

version_pattern = re.compile(r'(?P<tag>v[0-9]+\.[0-9]+(\.[0-9]+)?)')
doi_pattern = re.compile(r'https://doi\.org/(?P<doi>10\.5281/zenodo\.[0-9]+)')

if not tag:
latest = gh('release list -L 1 -R {}'.format(repos))
if not latest:
return None, None, None, None # pragma: no cover
match = version_pattern.search(latest)
assert match, latest
tag = match.group('tag')

info = gh('release view {} -R {}'.format(tag, repos))
match = None
for match in doi_pattern.finditer(info):
pass
if match:
doi = match.group('doi')
if doi:
cit = self.records(
id_=ZENODO_DOI_PATTERN.match(doi).group('recid'),
params=dict(style='apa'),
headers=dict(Accept='text/x-bibliography')).strip()
bib = self.records(
id_=ZENODO_DOI_PATTERN.match(doi).group('recid'),
params=dict(style='bibtex'),
headers=dict(Accept='text/x-bibliography')).strip()
bib = Source.from_bibtex(re.sub(
r', (?P<field>[a-zA-Z]+)=',
lambda m: ',\n {} = '.format(m.group('field')),
bib), _check_id=False)
bib.id = bibid or repos.replace('/', '_')
del bib['abstractNote']
del bib['month']
bib['edition'] = tag
bib['type'] = 'Data set'
return tag, doi, cit, bib
return tag, None, None, None # pragma: no cover


# Since an Api instance does some caching, we provide one instance as module global.
API = Api()
Expand Down
49 changes: 49 additions & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,52 @@ def test_Api_get_record(urlopen, mocker):
assert Api().get_record(conceptdoi='10.5281/zenodo.5173799', version='v1.1') is not None

assert list(Api().iter_versions('10.5281/zenodo.5173799'))


def test_Api_get_github_release_info(mocker):
class Subprocess:
@staticmethod
def check_output(cmd):
if 'list' in cmd:
return b"""TITLE TYPE TAG NAME PUBLISHED
Glottolog Database 4.8 Latest v4.8 about 4 months ago"""
return """v4.8
xrotwang released this about 4 months ago
Hammarström, Harald & Forkel, Robert & Haspelmath, Martin & Bank, Sebastian. 2023. Glottolog 4.8. Leipzig: Max
Planck Institute for Evolutionary Anthropology. (Available online at https://glottolog.org/)
DOI https://doi.org/10.5281/zenodo.8131084
View on GitHub: https://github.com/glottolog/glottolog/releases/tag/v4.8""".encode('utf8')

class Response:
def __init__(self, what):
self.what = what

def read(self):
if self.what == 'apa':
return b'The Citation'
return (' @misc{harald hammarström_robert forkel_martin haspelmath_sebastian bank_2023, '
'title={glottolog/glottolog: Glottolog database 4.8}, '
'DOI={10.5281/zenodo.8131084}, '
'abstractNote={Hammarström, Harald & Forkel, Robert & Haspelmath, Martin & Bank, Sebastian. 2023. Glottolog 4.8. Leipzig: Max Planck Institute for Evolutionary Anthropology. (Available online at https://glottolog.org)}, '
'publisher={Zenodo}, '
'author={Harald Hammarström and Robert Forkel and Martin Haspelmath and Sebastian Bank}, '
'year={2023}, '
'month={Jul} }').encode('utf8')

def urlopen(req):
if 'style=apa' in req.full_url:
return Response('apa')
return Response('bibtex')

mocker.patch('cldfzenodo.api.subprocess', Subprocess())
mocker.patch('cldfzenodo.api.urllib.request.urlopen', urlopen)

tag, doi, cit, bib = Api().get_github_release_info('glottolog/glottolog', bibid='x')
assert tag == 'v4.8'
assert doi == '10.5281/zenodo.8131084'
assert cit == 'The Citation'
assert bib.id == 'x'

0 comments on commit 91cb4de

Please sign in to comment.