mirror of
https://github.com/ARUP-CAS/aiscr-qgis-amcr-viewer.git
synced 2026-10-11 13:27:33 +02:00
Compare commits
2
Commits
222fe03bb8
..
v2.1.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5841fc15de | ||
|
|
f8d938e353 |
No files matched your search
@@ -1,41 +0,0 @@
|
|||||||
name: Release PR Checks
|
|
||||||
|
|
||||||
# Hlídá bump verze a changelog v okamžiku, kdy se release větev
|
|
||||||
# version/vX.Y.Z slévá do main – tady poprvé jde skutečně o to, co se
|
|
||||||
# vydá, a zapomenutý bump by se jinak dostal rovnou k tagu a releasu.
|
|
||||||
#
|
|
||||||
# Kontroly viz tests/check_version_bump.py: verze v metadata.txt musí jít
|
|
||||||
# nahoru, první položka changelogu musí patřit nové verzi, CITATION.cff
|
|
||||||
# musí mít stejnou verzi (a posunuté date-released) a název větve musí
|
|
||||||
# odpovídat verzi, kterou nese.
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
version-bump:
|
|
||||||
name: Kontrola verze a changelogu
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: startsWith(github.head_ref, 'version/')
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Set up Python
|
|
||||||
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
||||||
with:
|
|
||||||
python-version: '3.12'
|
|
||||||
|
|
||||||
- name: Verze a changelog
|
|
||||||
run: |
|
|
||||||
python3 tests/check_version_bump.py \
|
|
||||||
"${{ github.event.pull_request.base.sha }}" \
|
|
||||||
"${{ github.head_ref }}"
|
|
||||||
+2
-2
@@ -25,5 +25,5 @@ abstract: >-
|
|||||||
the Digital archive of the Archaeological Map of the
|
the Digital archive of the Archaeological Map of the
|
||||||
Czech Republic (https://digiarchiv.aiscr.cz/).
|
Czech Republic (https://digiarchiv.aiscr.cz/).
|
||||||
license: GPL-3.0
|
license: GPL-3.0
|
||||||
version: '2.1.2'
|
version: '2.1.3'
|
||||||
date-released: '2026-09-01'
|
date-released: '2026-10-01'
|
||||||
@@ -138,11 +138,11 @@ restriction". Click *Vybrat…* to open a searchable, checkable list.
|
|||||||
| Lokalita – typ | — | ✓ | — | `f_typ_lokality` |
|
| Lokalita – typ | — | ✓ | — | `f_typ_lokality` |
|
||||||
| Lokalita – druh | — | ✓ | — | `f_druh_lokality` |
|
| Lokalita – druh | — | ✓ | — | `f_druh_lokality` |
|
||||||
| Lokalita – jistota určení | — | ✓ | — | `f_jistota` |
|
| Lokalita – jistota určení | — | ✓ | — | `f_jistota` |
|
||||||
| Lokalita – stav dochování | — | ✓ | — | `f_lokalita_zachovalost` |
|
| Lokalita - stav dochování | — | ✓ | — | `f_lokalita_zachovalost` |
|
||||||
| Období | ✓ | ✓ | ✓ | `f_obdobi` |
|
| Období | ✓ | ✓ | ✓ | `f_obdobi` |
|
||||||
| Kategorie nálezu | — | — | ✓ | `f_kategorie` |
|
| Kategorie nálezu | — | — | ✓ | `f_kategorie` |
|
||||||
| Druh nálezu | — | — | ✓ | `f_druh_nalezu` |
|
| Druh nálezu | — | — | ✓ | `f_druh_nalezu` |
|
||||||
| Materiál | — | — | ✓ | `f_specifikace` |
|
| Specifikace nálezu | — | — | ✓ | `f_specifikace` |
|
||||||
| Okolnosti nálezu | — | — | ✓ | `f_nalezove_okolnosti` |
|
| Okolnosti nálezu | — | — | ✓ | `f_nalezove_okolnosti` |
|
||||||
| Nálezce | — | — | ✓ | `f_nalezce` |
|
| Nálezce | — | — | ✓ | `f_nalezce` |
|
||||||
| Datum nálezu | — | — | ✓ | `samostatny_nalez_datum_nalezu` |
|
| Datum nálezu | — | — | ✓ | `samostatny_nalez_datum_nalezu` |
|
||||||
|
|||||||
@@ -104,6 +104,21 @@ def load_all_data():
|
|||||||
return categorized_data
|
return categorized_data
|
||||||
|
|
||||||
|
|
||||||
|
def _facet_name(item):
|
||||||
|
"""
|
||||||
|
Returns the value of one facet item from the Digiarchive API.
|
||||||
|
|
||||||
|
Digiarchive v4.1.0 (Solr 10, json.nl=arrarr) returns facet items as
|
||||||
|
["value", count] pairs; older versions returned {"name": "value", ...}
|
||||||
|
objects. Both shapes are accepted so the plugin works against either.
|
||||||
|
"""
|
||||||
|
if isinstance(item, dict):
|
||||||
|
return item.get("name")
|
||||||
|
if isinstance(item, (list, tuple)) and item:
|
||||||
|
return item[0]
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def fetch_set(base_url, internal_name, api_set, task=None):
|
def fetch_set(base_url, internal_name, api_set, task=None):
|
||||||
dataset = []
|
dataset = []
|
||||||
params_amcr = {
|
params_amcr = {
|
||||||
@@ -206,7 +221,9 @@ def fetch_set(base_url, internal_name, api_set, task=None):
|
|||||||
|
|
||||||
for r in records:
|
for r in records:
|
||||||
|
|
||||||
nazev = r["name"]
|
nazev = _facet_name(r)
|
||||||
|
if not nazev:
|
||||||
|
continue
|
||||||
|
|
||||||
dataset.append({
|
dataset.append({
|
||||||
'Název': nazev,
|
'Název': nazev,
|
||||||
@@ -217,17 +234,48 @@ def fetch_set(base_url, internal_name, api_set, task=None):
|
|||||||
break
|
break
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
# A partial set (e.g. pagination interrupted halfway) would
|
||||||
|
# silently drop codes – report the whole set as failed instead
|
||||||
|
# and let the caller keep the previous values
|
||||||
QgsMessageLog.logMessage(
|
QgsMessageLog.logMessage(
|
||||||
f"Chyba u setu {api_set}: {e}",
|
f"Chyba u setu {api_set}: {e}",
|
||||||
"AMČR", Qgis.MessageLevel.Warning)
|
"AMČR", Qgis.MessageLevel.Warning)
|
||||||
break
|
return []
|
||||||
|
|
||||||
return dataset
|
return dataset
|
||||||
|
|
||||||
|
|
||||||
def download_heslare(task=None):
|
def _read_existing_rows():
|
||||||
"""Fetches the codelists from the AMČR API and saves it to a CSV file."""
|
"""
|
||||||
|
Returns the rows of the current heslar.csv grouped by category, so a set
|
||||||
|
that fails to download can keep its previous values.
|
||||||
|
"""
|
||||||
|
rows = {}
|
||||||
|
if not os.path.exists(OUTPUT_FILE):
|
||||||
|
return rows
|
||||||
|
try:
|
||||||
|
with open(OUTPUT_FILE, encoding='utf-8-sig', newline='') as f:
|
||||||
|
for row in csv.DictReader(f, delimiter=';'):
|
||||||
|
cat = (row.get('Kategorie') or '').strip()
|
||||||
|
if cat:
|
||||||
|
rows.setdefault(cat, []).append(row)
|
||||||
|
except Exception as e:
|
||||||
|
QgsMessageLog.logMessage(
|
||||||
|
f"Nelze načíst stávající hesláře: {e}",
|
||||||
|
"AMČR", Qgis.MessageLevel.Warning)
|
||||||
|
return rows
|
||||||
|
|
||||||
|
|
||||||
|
def download_heslare(task=None, failed=None):
|
||||||
|
"""
|
||||||
|
Fetches the codelists from the AMČR API and saves it to a CSV file.
|
||||||
|
|
||||||
|
A set that fails or comes back empty keeps its rows from the current
|
||||||
|
heslar.csv instead of being wiped; its name is appended to ``failed``
|
||||||
|
(if given) so the caller can warn the user.
|
||||||
|
"""
|
||||||
ensure_codelists_dir()
|
ensure_codelists_dir()
|
||||||
|
existing = _read_existing_rows()
|
||||||
all_data = []
|
all_data = []
|
||||||
total_sets = len(slovnicek)
|
total_sets = len(slovnicek)
|
||||||
# index, (interni, api_nazev)
|
# index, (interni, api_nazev)
|
||||||
@@ -251,6 +299,18 @@ def download_heslare(task=None):
|
|||||||
if data is None:
|
if data is None:
|
||||||
return False # Cancelled mid-download
|
return False # Cancelled mid-download
|
||||||
|
|
||||||
|
if not data:
|
||||||
|
# Never replace a working codelist with nothing – an API change
|
||||||
|
# would otherwise silently empty the filter in the dialog
|
||||||
|
old = existing.get(interni, [])
|
||||||
|
QgsMessageLog.logMessage(
|
||||||
|
f"Heslář '{interni}' se nepodařilo stáhnout, "
|
||||||
|
f"ponechávám předchozí hodnoty ({len(old)} položek).",
|
||||||
|
"AMČR", Qgis.MessageLevel.Warning)
|
||||||
|
if failed is not None:
|
||||||
|
failed.append(interni)
|
||||||
|
data = old
|
||||||
|
|
||||||
all_data.extend(data)
|
all_data.extend(data)
|
||||||
|
|
||||||
# Report progress (0-100)
|
# Report progress (0-100)
|
||||||
@@ -261,7 +321,8 @@ def download_heslare(task=None):
|
|||||||
# Save to CSV
|
# Save to CSV
|
||||||
with open(OUTPUT_FILE, 'w', newline='', encoding='utf-8-sig') as f:
|
with open(OUTPUT_FILE, 'w', newline='', encoding='utf-8-sig') as f:
|
||||||
fieldnames = ['Název', 'Kód', 'Kategorie']
|
fieldnames = ['Název', 'Kód', 'Kategorie']
|
||||||
writer = csv.DictWriter(f, fieldnames=fieldnames, delimiter=';')
|
writer = csv.DictWriter(f, fieldnames=fieldnames, delimiter=';',
|
||||||
|
extrasaction='ignore')
|
||||||
writer.writeheader()
|
writer.writeheader()
|
||||||
writer.writerows(all_data)
|
writer.writerows(all_data)
|
||||||
|
|
||||||
|
|||||||
@@ -75,12 +75,15 @@ class UpdateCodelistsTask(QgsTask):
|
|||||||
super().__init__(description, QgsTask.Flag.CanCancel)
|
super().__init__(description, QgsTask.Flag.CanCancel)
|
||||||
self.success = False
|
self.success = False
|
||||||
self.exception = None
|
self.exception = None
|
||||||
|
# Codelists that failed to download and kept their previous values
|
||||||
|
self.failed_sets = []
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""Runs in a background thread."""
|
"""Runs in a background thread."""
|
||||||
try:
|
try:
|
||||||
# Call the download function with the task reference
|
# Call the download function with the task reference
|
||||||
self.success = download_heslare(task=self)
|
self.success = download_heslare(
|
||||||
|
task=self, failed=self.failed_sets)
|
||||||
return self.success
|
return self.success
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.exception = e
|
self.exception = e
|
||||||
@@ -91,6 +94,13 @@ class UpdateCodelistsTask(QgsTask):
|
|||||||
if result:
|
if result:
|
||||||
# Safely update the global variables in the main thread
|
# Safely update the global variables in the main thread
|
||||||
refresh_globals()
|
refresh_globals()
|
||||||
|
if self.failed_sets:
|
||||||
|
QgsMessageLog.logMessage(
|
||||||
|
"Hesláře AMČR aktualizovány částečně, beze změny "
|
||||||
|
f"zůstaly: {', '.join(self.failed_sets)}",
|
||||||
|
"AMČR", Qgis.MessageLevel.Warning
|
||||||
|
)
|
||||||
|
else:
|
||||||
QgsMessageLog.logMessage(
|
QgsMessageLog.logMessage(
|
||||||
"Hesláře AMČR byly úspěšně aktualizovány.",
|
"Hesláře AMČR byly úspěšně aktualizovány.",
|
||||||
"AMČR", Qgis.MessageLevel.Info
|
"AMČR", Qgis.MessageLevel.Info
|
||||||
@@ -333,7 +343,7 @@ class AmcrFilterDialog(QDialog):
|
|||||||
layout.addWidget(self.picker_jistota)
|
layout.addWidget(self.picker_jistota)
|
||||||
|
|
||||||
self.picker_lokalita_zachovalost = self.setup_picker(
|
self.picker_lokalita_zachovalost = self.setup_picker(
|
||||||
"Lokalita – stav dochování",
|
"Lokalita - stav dochování",
|
||||||
'lokalita_zachovalost',
|
'lokalita_zachovalost',
|
||||||
LOKALITA_ZACHOVALOST
|
LOKALITA_ZACHOVALOST
|
||||||
)
|
)
|
||||||
@@ -360,7 +370,7 @@ class AmcrFilterDialog(QDialog):
|
|||||||
layout.addWidget(self.picker_druh_nalezu)
|
layout.addWidget(self.picker_druh_nalezu)
|
||||||
|
|
||||||
self.picker_specifikace = self.setup_picker(
|
self.picker_specifikace = self.setup_picker(
|
||||||
"Materiál",
|
"Specifikace nálezu",
|
||||||
'specifikace',
|
'specifikace',
|
||||||
SPECIFIKACE
|
SPECIFIKACE
|
||||||
)
|
)
|
||||||
@@ -629,6 +639,16 @@ class AmcrFilterDialog(QDialog):
|
|||||||
|
|
||||||
def on_completed():
|
def on_completed():
|
||||||
_cleanup()
|
_cleanup()
|
||||||
|
if task.failed_sets:
|
||||||
|
QMessageBox.warning(
|
||||||
|
parent_win,
|
||||||
|
"Hesláře aktualizovány částečně",
|
||||||
|
"Některé hesláře se nepodařilo stáhnout, "
|
||||||
|
"ponechány byly jejich předchozí hodnoty:\n"
|
||||||
|
+ "\n".join(f"• {name}" for name in task.failed_sets)
|
||||||
|
+ "\n\nPodrobnosti jsou v panelu Zprávy, záložka AMČR."
|
||||||
|
)
|
||||||
|
return
|
||||||
QMessageBox.information(
|
QMessageBox.information(
|
||||||
parent_win,
|
parent_win,
|
||||||
"Hotovo",
|
"Hotovo",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import json
|
import json
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
@@ -680,8 +680,6 @@ def load_amcr_data(canvas, bb, filters=None,
|
|||||||
# One feature per component –
|
# One feature per component –
|
||||||
# all data on a single row, no relations needed
|
# all data on a single row, no relations needed
|
||||||
if komps:
|
if komps:
|
||||||
komps_count = len(komps)
|
|
||||||
|
|
||||||
for komp in komps:
|
for komp in komps:
|
||||||
if not komp_projde_filtrem(
|
if not komp_projde_filtrem(
|
||||||
komp, filter_areal,
|
komp, filter_areal,
|
||||||
@@ -703,7 +701,6 @@ def load_amcr_data(canvas, bb, filters=None,
|
|||||||
komp.get('komponenta_obdobi')
|
komp.get('komponenta_obdobi')
|
||||||
or {}
|
or {}
|
||||||
).get('value', ""),
|
).get('value', ""),
|
||||||
'vaha': 1/komps_count,
|
|
||||||
}
|
}
|
||||||
pian_lookup[dj_pian_value].append(
|
pian_lookup[dj_pian_value].append(
|
||||||
komp_meta)
|
komp_meta)
|
||||||
@@ -1059,7 +1056,6 @@ def load_amcr_data(canvas, bb, filters=None,
|
|||||||
"poznamka": "Poznámka/bližší popis",
|
"poznamka": "Poznámka/bližší popis",
|
||||||
"pred_org": "Předáno organizaci",
|
"pred_org": "Předáno organizaci",
|
||||||
"evidencni": "Evidenční číslo",
|
"evidencni": "Evidenční číslo",
|
||||||
"prvek_vaha": "Váha prvku",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if komponenty == "true":
|
if komponenty == "true":
|
||||||
@@ -1067,7 +1063,6 @@ def load_amcr_data(canvas, bb, filters=None,
|
|||||||
QgsField("komponenta", QMetaType.Type.QString),
|
QgsField("komponenta", QMetaType.Type.QString),
|
||||||
QgsField("komponenta_areal", QMetaType.Type.QString),
|
QgsField("komponenta_areal", QMetaType.Type.QString),
|
||||||
QgsField("komponenta_obdobi", QMetaType.Type.QString),
|
QgsField("komponenta_obdobi", QMetaType.Type.QString),
|
||||||
QgsField("prvek_vaha", QMetaType.Type.Double),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
for vl in layers:
|
for vl in layers:
|
||||||
@@ -1214,7 +1209,6 @@ def load_amcr_data(canvas, bb, filters=None,
|
|||||||
meta.get('komponenta_id', ""),
|
meta.get('komponenta_id', ""),
|
||||||
meta.get('komponenta_areal', ""),
|
meta.get('komponenta_areal', ""),
|
||||||
meta.get('komponenta_obdobi', ""),
|
meta.get('komponenta_obdobi', ""),
|
||||||
meta.get('vaha', 1),
|
|
||||||
])
|
])
|
||||||
|
|
||||||
feat.setAttributes(atributy)
|
feat.setAttributes(atributy)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ name=AMČR Viewer
|
|||||||
qgisMinimumVersion=3.44.0
|
qgisMinimumVersion=3.44.0
|
||||||
qgisMaximumVersion=4.99.0
|
qgisMaximumVersion=4.99.0
|
||||||
description=Viewing and downloading the AMČR data.
|
description=Viewing and downloading the AMČR data.
|
||||||
version=2.2.0
|
version=2.1.3
|
||||||
author=David Spáčil
|
author=David Spáčil
|
||||||
email=spacil@arub.cz
|
email=spacil@arub.cz
|
||||||
|
|
||||||
@@ -23,11 +23,10 @@ repository=https://github.com/ARUP-CAS/aiscr-qgis-amcr-viewer
|
|||||||
hasProcessingProvider=no
|
hasProcessingProvider=no
|
||||||
# Uncomment the following line and add your changelog:
|
# Uncomment the following line and add your changelog:
|
||||||
changelog=
|
changelog=
|
||||||
Plný seznam změn v češtině je dostupný zde: https://github.com/ARUP-CAS/aiscr-qgis-amcr-viewer/releases/tag/v2.2.0
|
Plný seznam změn v češtině je dostupný zde: https://github.com/ARUP-CAS/aiscr-qgis-amcr-viewer/releases/tag/v2.1.1
|
||||||
v2.2.0 (2026-09-02)
|
v2.1.3 (2026-10-01)
|
||||||
* Filter labels unified: "Specifikace nálezu" renamed to "Materiál" to match the attribute alias
|
* Fixed empty person codelists (excavation leaders, finders) after updating codelists against Digiarchive v4.1.0
|
||||||
* README rewritten to match the current state of the code
|
* A codelist that fails to download keeps its previous values and the user is warned
|
||||||
* Tables for Akce and Lokality contain a field with feature weight, when Komponenty rendering is enabled
|
|
||||||
v2.1.2 (2026-09-01)
|
v2.1.2 (2026-09-01)
|
||||||
* Qt6 compatibility
|
* Qt6 compatibility
|
||||||
* Code clean-up
|
* Code clean-up
|
||||||
|
|||||||
@@ -1,187 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
Guards the release PR (version/vX.Y.Z -> main).
|
|
||||||
|
|
||||||
Checks that the version actually moved forward and that the three places
|
|
||||||
that name it agree, because plugins.qgis.org and Zenodo both read from
|
|
||||||
files a human has to remember to touch by hand:
|
|
||||||
|
|
||||||
* amcr_viewer/metadata.txt: version= must be higher than on main, and the
|
|
||||||
first changelog entry must be for that exact version
|
|
||||||
* CITATION.cff: version must match metadata.txt, and date-released must
|
|
||||||
not be left pointing at the old release
|
|
||||||
* the branch name (version/vX.Y.Z) must match metadata.txt, so a stray
|
|
||||||
push to the wrong release branch is caught before merge
|
|
||||||
|
|
||||||
Run from the repository root:
|
|
||||||
|
|
||||||
python3 tests/check_version_bump.py <base_sha> <head_ref>
|
|
||||||
"""
|
|
||||||
|
|
||||||
import datetime
|
|
||||||
import re
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
|
|
||||||
METADATA = "amcr_viewer/metadata.txt"
|
|
||||||
CITATION = "CITATION.cff"
|
|
||||||
|
|
||||||
VERZE_METADATA = re.compile(r"^version=(.+)$", re.MULTILINE)
|
|
||||||
VERZE_CITATION = re.compile(r"^version:\s*'?([^'\n]+)'?\s*$", re.MULTILINE)
|
|
||||||
DATUM_CITATION = re.compile(r"^date-released:\s*'?([^'\n]+)'?\s*$",
|
|
||||||
re.MULTILINE)
|
|
||||||
# Přeskočí úvodní řádek "Plný seznam změn ... /vX.Y.Z" a najde první
|
|
||||||
# skutečnou položku changelogu.
|
|
||||||
POLOZKA_CHANGELOGU = re.compile(r"^\s+v([0-9][^\s(]*)\s*\(", re.MULTILINE)
|
|
||||||
BRANCH_VERZE = re.compile(r"^version/v(.+)$")
|
|
||||||
|
|
||||||
nalezy = []
|
|
||||||
|
|
||||||
|
|
||||||
def nacti_na_base(base_sha, cesta):
|
|
||||||
vysledek = subprocess.run(
|
|
||||||
["git", "show", f"{base_sha}:{cesta}"],
|
|
||||||
capture_output=True, text=True,
|
|
||||||
)
|
|
||||||
if vysledek.returncode != 0:
|
|
||||||
nalezy.append(f"{cesta}: na cílové větvi nejde přečíst "
|
|
||||||
f"(git show {base_sha}:{cesta} selhalo)")
|
|
||||||
return None
|
|
||||||
return vysledek.stdout
|
|
||||||
|
|
||||||
|
|
||||||
def nacti(cesta):
|
|
||||||
with open(cesta, encoding="utf-8") as f:
|
|
||||||
return f.read()
|
|
||||||
|
|
||||||
|
|
||||||
def hledej(vzor, text, cesta, popis):
|
|
||||||
shoda = vzor.search(text)
|
|
||||||
if not shoda:
|
|
||||||
nalezy.append(f"{cesta}: {popis} nenalezeno")
|
|
||||||
return None
|
|
||||||
return shoda.group(1).strip()
|
|
||||||
|
|
||||||
|
|
||||||
def verze_tuple(verze):
|
|
||||||
jadro = verze.split("-", 1)[0]
|
|
||||||
try:
|
|
||||||
return tuple(int(c) for c in jadro.split("."))
|
|
||||||
except ValueError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def je_bump(stara, nova):
|
|
||||||
if stara == nova:
|
|
||||||
return False
|
|
||||||
stara_t, nova_t = verze_tuple(stara), verze_tuple(nova)
|
|
||||||
if stara_t is None or nova_t is None:
|
|
||||||
# Nestandardní formát verze – nejde spolehlivě porovnat čísly,
|
|
||||||
# stačí tedy, že se řetězec liší.
|
|
||||||
return True
|
|
||||||
if nova_t != stara_t:
|
|
||||||
return nova_t > stara_t
|
|
||||||
# Stejné jádro (např. "-alpha" přípona): bump platí, pokud se text
|
|
||||||
# liší a nejde o couvnutí z release na prerelease.
|
|
||||||
return "-" in stara or "-" not in nova
|
|
||||||
|
|
||||||
|
|
||||||
def datum(text):
|
|
||||||
try:
|
|
||||||
return datetime.date.fromisoformat(text)
|
|
||||||
except ValueError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
if len(sys.argv) != 3:
|
|
||||||
print("použití: check_version_bump.py <base_sha> <head_ref>")
|
|
||||||
return 2
|
|
||||||
base_sha, head_ref = sys.argv[1], sys.argv[2]
|
|
||||||
|
|
||||||
base_metadata = nacti_na_base(base_sha, METADATA)
|
|
||||||
base_citation = nacti_na_base(base_sha, CITATION)
|
|
||||||
head_metadata = nacti(METADATA)
|
|
||||||
head_citation = nacti(CITATION)
|
|
||||||
|
|
||||||
if base_metadata is None or base_citation is None:
|
|
||||||
# Bez base souborů nejde nic dalšího smysluplně ověřit.
|
|
||||||
print("Nálezy:")
|
|
||||||
for nalez in nalezy:
|
|
||||||
print(f" {nalez}")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
stara_verze = hledej(VERZE_METADATA, base_metadata, METADATA,
|
|
||||||
"verze na cílové větvi (version=)")
|
|
||||||
nova_verze = hledej(VERZE_METADATA, head_metadata, METADATA,
|
|
||||||
"verze (version=)")
|
|
||||||
stara_citation_verze = hledej(VERZE_CITATION, base_citation, CITATION,
|
|
||||||
"verze na cílové větvi (version:)")
|
|
||||||
nova_citation_verze = hledej(VERZE_CITATION, head_citation, CITATION,
|
|
||||||
"verze (version:)")
|
|
||||||
stare_datum = hledej(DATUM_CITATION, base_citation, CITATION,
|
|
||||||
"date-released na cílové větvi")
|
|
||||||
nove_datum = hledej(DATUM_CITATION, head_citation, CITATION,
|
|
||||||
"date-released")
|
|
||||||
|
|
||||||
if None in (stara_verze, nova_verze, stara_citation_verze,
|
|
||||||
nova_citation_verze, stare_datum, nove_datum):
|
|
||||||
print("Nálezy:")
|
|
||||||
for nalez in nalezy:
|
|
||||||
print(f" {nalez}")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
# 1. metadata.txt: verze musí jít dopředu.
|
|
||||||
if not je_bump(stara_verze, nova_verze):
|
|
||||||
nalezy.append(
|
|
||||||
f"{METADATA}: verze nepovýšena ({stara_verze} -> {nova_verze})")
|
|
||||||
|
|
||||||
# 2. metadata.txt: první položka changelogu musí patřit nové verzi.
|
|
||||||
prvni_polozka = POLOZKA_CHANGELOGU.search(head_metadata)
|
|
||||||
if not prvni_polozka:
|
|
||||||
nalezy.append(f"{METADATA}: v changelog= nenalezena žádná položka "
|
|
||||||
f"'vX.Y.Z (...)'")
|
|
||||||
elif prvni_polozka.group(1) != nova_verze:
|
|
||||||
nalezy.append(
|
|
||||||
f"{METADATA}: první položka changelogu je pro "
|
|
||||||
f"v{prvni_polozka.group(1)}, ale version={nova_verze}")
|
|
||||||
|
|
||||||
# 3. CITATION.cff: verze musí souhlasit s metadata.txt.
|
|
||||||
if nova_citation_verze != nova_verze:
|
|
||||||
nalezy.append(
|
|
||||||
f"{CITATION}: version: {nova_citation_verze} neodpovídá "
|
|
||||||
f"{METADATA} version={nova_verze}")
|
|
||||||
|
|
||||||
# 4. CITATION.cff: date-released se musí posunout, a ne dozadu.
|
|
||||||
stary_datum_obj, novy_datum_obj = datum(stare_datum), datum(nove_datum)
|
|
||||||
if stary_datum_obj is None or novy_datum_obj is None:
|
|
||||||
nalezy.append(f"{CITATION}: date-released není platné datum "
|
|
||||||
f"ISO 8601 ({stare_datum!r} -> {nove_datum!r})")
|
|
||||||
elif novy_datum_obj < stary_datum_obj:
|
|
||||||
nalezy.append(
|
|
||||||
f"{CITATION}: date-released couvlo ({stare_datum} -> "
|
|
||||||
f"{nove_datum})")
|
|
||||||
elif nove_datum == stare_datum and stara_citation_verze != nova_citation_verze:
|
|
||||||
nalezy.append(
|
|
||||||
f"{CITATION}: version se změnila, ale date-released zůstalo "
|
|
||||||
f"na {stare_datum}")
|
|
||||||
|
|
||||||
# 5. Název release větve musí odpovídat verzi, kterou nese.
|
|
||||||
shoda_branch = BRANCH_VERZE.match(head_ref)
|
|
||||||
if shoda_branch and shoda_branch.group(1) != nova_verze:
|
|
||||||
nalezy.append(
|
|
||||||
f"větev {head_ref!r} neodpovídá {METADATA} "
|
|
||||||
f"version={nova_verze}")
|
|
||||||
|
|
||||||
if nalezy:
|
|
||||||
print("Nálezy:")
|
|
||||||
for nalez in nalezy:
|
|
||||||
print(f" {nalez}")
|
|
||||||
return 1
|
|
||||||
print(f"Kontrola verze a changelogu: v{stara_verze} -> v{nova_verze}, "
|
|
||||||
f"bez nálezů")
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
sys.exit(main())
|
|
||||||
Reference in new issue
Block a user