mirror of
https://github.com/ARUP-CAS/aiscr-qgis-amcr-viewer.git
synced 2026-10-11 13:27:33 +02:00
Compare commits
4
Commits
v2.1.3
..
222fe03bb8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
222fe03bb8 | ||
|
|
236907b9df | ||
|
|
49fbd91cea | ||
|
|
62d9ebd6f0 |
No files matched your search
@@ -0,0 +1,41 @@
|
|||||||
|
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.3'
|
version: '2.1.2'
|
||||||
date-released: '2026-10-01'
|
date-released: '2026-09-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` |
|
||||||
| Specifikace nálezu | — | — | ✓ | `f_specifikace` |
|
| Materiál | — | — | ✓ | `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,21 +104,6 @@ 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 = {
|
||||||
@@ -221,9 +206,7 @@ def fetch_set(base_url, internal_name, api_set, task=None):
|
|||||||
|
|
||||||
for r in records:
|
for r in records:
|
||||||
|
|
||||||
nazev = _facet_name(r)
|
nazev = r["name"]
|
||||||
if not nazev:
|
|
||||||
continue
|
|
||||||
|
|
||||||
dataset.append({
|
dataset.append({
|
||||||
'Název': nazev,
|
'Název': nazev,
|
||||||
@@ -234,48 +217,17 @@ 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)
|
||||||
return []
|
break
|
||||||
|
|
||||||
return dataset
|
return dataset
|
||||||
|
|
||||||
|
|
||||||
def _read_existing_rows():
|
def download_heslare(task=None):
|
||||||
"""
|
"""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)
|
||||||
@@ -299,18 +251,6 @@ def download_heslare(task=None, failed=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)
|
||||||
@@ -321,8 +261,7 @@ def download_heslare(task=None, failed=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,15 +75,12 @@ 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(
|
self.success = download_heslare(task=self)
|
||||||
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
|
||||||
@@ -94,13 +91,6 @@ 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
|
||||||
@@ -343,7 +333,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
|
||||||
)
|
)
|
||||||
@@ -370,7 +360,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(
|
||||||
"Specifikace nálezu",
|
"Materiál",
|
||||||
'specifikace',
|
'specifikace',
|
||||||
SPECIFIKACE
|
SPECIFIKACE
|
||||||
)
|
)
|
||||||
@@ -639,16 +629,6 @@ 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,6 +680,8 @@ 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,
|
||||||
@@ -701,6 +703,7 @@ 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)
|
||||||
@@ -1056,6 +1059,7 @@ 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":
|
||||||
@@ -1063,6 +1067,7 @@ 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:
|
||||||
@@ -1209,6 +1214,7 @@ 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.1.3
|
version=2.2.0
|
||||||
author=David Spáčil
|
author=David Spáčil
|
||||||
email=spacil@arub.cz
|
email=spacil@arub.cz
|
||||||
|
|
||||||
@@ -23,10 +23,11 @@ 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.1.1
|
Plný seznam změn v češtině je dostupný zde: https://github.com/ARUP-CAS/aiscr-qgis-amcr-viewer/releases/tag/v2.2.0
|
||||||
v2.1.3 (2026-10-01)
|
v2.2.0 (2026-09-02)
|
||||||
* Fixed empty person codelists (excavation leaders, finders) after updating codelists against Digiarchive v4.1.0
|
* Filter labels unified: "Specifikace nálezu" renamed to "Materiál" to match the attribute alias
|
||||||
* A codelist that fails to download keeps its previous values and the user is warned
|
* README rewritten to match the current state of the code
|
||||||
|
* 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
|
||||||
|
|||||||
@@ -0,0 +1,187 @@
|
|||||||
|
# -*- 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