SciPy Core Developer Guide#
Entscheidungsfindungsprozess#
SciPy hat ein formales Governance-Modell, das in SciPy Project Governance dokumentiert ist. Der folgende Abschnitt dokumentiert auf informelle Weise, was in der Praxis für Entscheidungen über Code und Commit-Rechte geschieht. Das formale Governance-Modell ist maßgeblich, das untenstehende dient nur dem Kontext.
Code#
Alle wesentlichen Entscheidungen über das Hinzufügen (oder Nicht-Hinzufügen) neuer Funktionen, das Brechen von Abwärtskompatibilität oder andere bedeutende Änderungen am Codebestand sollten nach einer Diskussion (vorzugsweise mit vollständigem Konsens) im scipy-dev Forum getroffen werden.
Jede nicht-triviale Änderung (wobei trivial ein Tippfehler oder ein Einzeiler-Wartungs-Commit bedeutet) muss über einen Pull Request (PR) erfolgen. Er muss von einem anderen Entwickler überprüft werden. Sollte die Überprüfung nicht schnell genug erfolgen und es wichtig sein, dass der PR schnell gemerged wird, sollte der Einreicher des PRs eine Nachricht an das Forum senden, in der er mitteilt, dass er beabsichtigt, diesen PR ohne Überprüfung um Zeitpunkt X aus Grund Y zu mergen, es sei denn, jemand überprüft ihn vorher.
Änderungen und Neuzugänge sollten getestet werden. Ungetesteter Code ist kaputter Code.
Commit-Rechte#
Wer Commit-Rechte erhält, wird vom SciPy Steering Council entschieden; Änderungen an den Commit-Rechten werden dann im scipy-dev Forum angekündigt.
Entscheidung über neue Funktionen#
Die allgemeine Entscheidungsregel für die Annahme einer vorgeschlagenen neuen Funktion war bisher bedingt durch
Die Methode ist in vielen Bereichen anwendbar und wird als nützlich „allgemein anerkannt“,
Sie passt zum Thema des Untermoduls und erfordert keine umfangreichen Unterstützungssysteme für den Betrieb,
Die Implementierung erscheint solide und unwahrscheinlich, dass sie in Zukunft viel Anpassung erfordert (z. B. geringer erwarteter Wartungsaufwand),
Jemand möchte sie beitragen, und
Jemand möchte sie überprüfen.
Das letzte Kriterium ist oft ein Knackpunkt für vorgeschlagene Funktionen. Code kann erst gemerged werden, nachdem er gründlich überprüft wurde, und es gibt immer einen Rückstand an Wartungsaufgaben, die um die Zeit der Prüfer konkurrieren. Idealerweise sollten Mitwirkende einen Prüfer mit entsprechender Fachkenntnis organisieren, bevor sie mit der Arbeit beginnen.
Obwohl es schwierig ist, harte Regeln dafür zu geben, was „allgemein nützlich und allgemein als funktionierend anerkannt“ bedeutet, kann es hilfreich sein, Folgendes gegeneinander abzuwägen
Wird die Methode in der Praxis in verschiedenen Domänen verwendet/ist sie nützlich? Wie viel domänenspezifisches Hintergrundwissen ist erforderlich, um sie richtig anzuwenden?
Betrachten Sie den bereits vorhandenen Code im Modul. Ist das, was Sie hinzufügen, eine Auslassung? Löst es ein Problem, das das Modul lösen sollte? Ergänzt es eine bestehende Funktion auf signifikante Weise?
Betrachten Sie die Äquivalenzklasse ähnlicher Methoden/Funktionen, die üblicherweise erwartet werden. Was wäre davon im Prinzip die minimale Menge, damit keine offensichtliche Lücke in den angebotenen Funktionen bleibt? Wie viel davon wäre das? Deckt die Aufnahme eines repräsentativen Vertreters die meisten Anwendungsfälle ab? Wäre es im Prinzip sinnvoll, alles aus der minimalen Menge in das Modul aufzunehmen?
Ist das, was Sie hinzufügen, in der Literatur gut verstanden? Wenn nicht, wie sicher sind Sie, dass es gut laufen wird? Wie schneidet die Methode im Vergleich zu ähnlichen ab?
Beachten Sie, dass der zweimal jährlich stattfindende Release-Zyklus und die Abwärtskompatibilitätspolitik die Korrektur von Dingen später erschweren.
Die Umfänge der Untermodule variieren ebenfalls, daher ist es wahrscheinlich am besten, jedes als separates Projekt zu betrachten – „numerische Auswertung von Spezialfunktionen“ ist relativ gut definiert, aber „häufig benötigte Optimierungsalgorithmen“ weniger so.
Entwicklung auf GitHub#
Die SciPy-Entwicklung findet größtenteils auf GitHub statt; dieser Abschnitt beschreibt die erwartete Arbeitsweise für Issues, Pull Requests und die Verwaltung des Haupt-Repositorys scipy.
Labels und Meilensteine#
Jeder Issue und Pull Request erhält normalerweise mindestens zwei Labels: eines für das Thema oder die Komponente (scipy.stats, Documentation, etc.) und eines für die Art des Issues oder Pull Requests (enhancement, maintenance, defect, etc.). Weitere Labels, die je nach Situation hinzugefügt werden können
good-first-issue: für Issues, die für neue Mitwirkende geeignet sind.needs-work: für Pull Requests mit Überprüfungskommentaren, die noch nicht bearbeitet wurden.needs-decision: für Issues oder Pull Requests, die eine Entscheidung erfordern.needs-champion: für Pull Requests, die nicht vom ursprünglichen Autor abgeschlossen wurden, aber wiederbelebt werden sollten.backport-candidate: Fehlerkorrekturen, die vom Release-Manager für Backports in Betracht gezogen werden sollen.
Für jede geplante Release-Version wird ein Meilenstein erstellt. Issues, die für eine bestimmte Release behoben und Pull Requests, die gemerged werden müssen, sollten dem entsprechenden Meilenstein zugeordnet werden. Nach dem Mergen eines Pull Requests sollte sein Meilenstein (und der des von ihm geschlossenen Issues) auf die nächste kommende Release gesetzt werden – dies erleichtert die Übersicht über Änderungen und das Hinzufügen einer vollständigen Liste davon zu den Release Notes.
Workflow für die Überprüfung von Pull Requests#
Bei der Überprüfung von Pull Requests nutzen Sie bitte die Workflow-Funktionen für Pull Requests, siehe Using workflow features.
Umgang mit Pull Requests#
Beim Mergen von Beiträgen ist ein Committer dafür verantwortlich sicherzustellen, dass diese die unter Contributing to SciPy aufgeführten Anforderungen erfüllen. Überprüfen Sie auch, ob neue Funktionen und Abwärtskompatibilitätsbrüche im scipy-dev Forum besprochen wurden.
Neuer Code wird über einen Pull Request (PR) eingebracht.
Merge neuen Code mit dem grünen Button. Bei Merge-Konflikten bitten Sie den PR-Einreicher, neu zu basieren (dies kann einige
git-Anweisungen erfordern).Backports und triviale Ergänzungen zum Abschluss eines PR (wirklich trivial, wie ein Tippfehler oder PEP8-Fix) können direkt gepusht werden.
Bei PRs, die neue Funktionen hinzufügen oder in irgendeiner Weise komplex sind, warten Sie mindestens ein oder zwei Tage, bevor Sie sie mergen. So erhalten andere die Möglichkeit, Kommentare abzugeben, bevor der Code aufgenommen wird.
Das Squashen von Commits oder das Bereinigen von Commit-Nachrichten eines PRs, den Sie für zu unordentlich halten, ist in Ordnung. Stellen Sie jedoch sicher, dass der Name des ursprünglichen Autors dabei erhalten bleibt. Squashen wird dringend empfohlen, wenn Commit-Nachrichten nicht (ungefähr) den Richtlinien in Writing the commit message folgen.
Stellen Sie sicher, dass die Labels und Meilensteine für einen gemergten PR korrekt gesetzt sind.
Wenn Sie einen PR ablehnen möchten: Wenn es sehr offensichtlich ist, können Sie ihn einfach schließen und den Grund angeben. Wenn es nicht offensichtlich ist, ist es eine gute Idee, zuerst zu erklären, warum Sie den PR für die Aufnahme in SciPy als ungeeignet halten, und dann einem zweiten Committer zu erlauben, zu kommentieren oder ihn zu schließen.
Backporting#
Alle Pull Requests (ob sie Verbesserungen, Fehlerbehebungen oder etwas anderes enthalten) sollten gegen main gerichtet sein. Nur Fehlerkorrekturen sind Kandidaten für das Backporting in einen Wartungszweig. Die Backport-Strategie für SciPy ist, (a) nur wichtige Korrekturen zu backporten und (b) nur zu backporten, wenn einigermaßen sicher ist, dass eine neue Fehlerbehebungs-Release auf dem entsprechenden Wartungszweig erfolgen wird. Typischerweise fügt der Entwickler, der eine wichtige Fehlerkorrektur mergt, das Label backport-candidate hinzu und pingt den Release Manager, der entscheidet, ob und wann der Backport durchgeführt wird. Nach Abschluss des Backports muss das Label backport-candidate wieder entfernt werden.
Eine gute Strategie für einen Backport-Pull-Request ist die Kombination mehrerer Pull Requests aus dem Hauptzweig, um die Belastung der kontinuierlichen Integrationstests zu reduzieren und das „Verschmutzen“ des Wartungszweig-Verlaufs durch Merge-Commits zu minimieren. Es ist im Allgemeinen am besten, für jeden im Backport-Pull-Request enthaltenen Hauptzweig-Pull-Request einen einzelnen Commit zu haben. So ist der Verlauf klar und kann bei Bedarf einfach rückgängig gemacht werden.
Release Notes#
Wenn ein PR gemergt wird, überlegen Sie, ob die Änderungen in den Release Notes erwähnt werden müssen. Was erwähnt werden muss: neue Funktionen, abwärtsinkompatible Änderungen, Deprecations und „andere Änderungen“ (alles andere Bemerkenswerte, siehe ältere Release Notes für die Art der erwähnenswerten Dinge).
Release Note-Einträge werden im Wiki gepflegt. Der Release Manager sammelt Inhalte von dort und integriert sie in die HTML-Docs. Wir verwenden diesen Mechanismus, um Merge-Konflikte zu vermeiden, die entstehen würden, wenn jeder PR dieselbe Datei unter doc/release/ direkt berühren würde.
Änderungen können überwacht werden (Atom feed) und abgerufen werden (das Wiki ist ein Git-Repo: https://github.com/scipy/scipy.wiki.git).
Sonstiges#
Querverweise: Das Querverweisen auf Issues und Pull Requests auf GitHub ist oft nützlich. GitHub ermöglicht dies durch die Verwendung von gh-xxxx oder #xxxx, wobei xxxx die Issue/PR-Nummer ist. Das Format gh-xxxx wird dringend bevorzugt, da klar ist, dass es sich um einen GitHub-Link handelt. Ältere Issues enthalten #xxxx, was sich auf Trac (was wir vor GitHub verwendet haben) Tickets bezieht.
PR-Namenskonvention: Pull Requests, Issues und Commit-Nachrichten beginnen normalerweise mit einer dreibuchstabigen Abkürzung wie ENH: oder BUG:. Dies ist nützlich, um schnell die Art des Commits/PR/Issues zu erkennen. Für die vollständige Liste der Abkürzungen siehe writing the commit message.
Lizenzierung#
SciPy wird unter der modifizierten (3-Klausel) BSD-Lizenz vertrieben. Alle von Mitwirkenden zu SciPy hinzugefügten Codes, Dokumentationen und anderen Dateien werden unter dieser Lizenz lizenziert, es sei denn, eine andere Lizenz ist im Quellcode explizit angegeben. Mitwirkende behalten das Urheberrecht an dem Code, den sie schreiben und zur Aufnahme in SciPy einreichen.
Andere Lizenzen, die mit der modifizierten BSD-Lizenz, die SciPy verwendet, kompatibel sind, sind 2-Klausel BSD, MIT und PSF. Inkompatible Lizenzen sind GPL, Apache und benutzerdefinierte Lizenzen, die Namensnennung/Zitierung erfordern oder die kommerzielle Nutzung verbieten.
PRs werden oft mit Inhalten eingereicht, die aus nicht lizenziertem Code oder Code aus einer Standardlizenz kopiert oder abgeleitet wurden, die nicht mit der Lizenz von SciPy kompatibel ist. Zum Beispiel unterliegt Code, der auf StackOverflow veröffentlicht wird, einer CC-BY-SA-Lizenz, die aufgrund der Share-Alike-Klausel nicht kompatibel ist. Diese Beiträge können nicht für die Aufnahme in SciPy angenommen werden, es sei denn, der ursprüngliche Codeautor ist bereit, seinen Code unter der modifizierten BSD-Lizenz (oder einer kompatiblen Lizenz) neu zu lizenzieren. Wenn der ursprüngliche Autor zustimmt, fügen Sie einen Kommentar hinzu, der dies in den Quelldateien angibt, und leiten Sie die relevante Kommunikation an das scipy-dev Forum weiter.
Ein weiteres häufiges Vorkommnis ist, dass Code aus R, Octave (beide GPL-lizenziert) oder einer kommerziellen Anwendung übersetzt oder abgeleitet wird. Solcher Code kann ebenfalls nicht in SciPy aufgenommen werden. Allein die Implementierung von Funktionalität mit der gleichen API wie in R/Octave/… ist jedoch in Ordnung, solange der Autor den ursprünglichen, inkompatibel lizenzierten Quellcode nicht ansieht.
Versionsnummerierung#
Die Versionsnummerierung von SciPy entspricht PEP 440. Freigegebene Endversionen, die einzigen Versionen, die auf PyPI erscheinen, sind nummeriert als MAJOR.MINOR.MICRO, wobei
MAJOReine Ganzzahl ist, die die Hauptversion angibt. Sie ändert sich sehr selten; eine Änderung inMAJORdeutet auf große (möglicherweise abwärtsinkompatible) Änderungen hin.MINOReine Ganzzahl ist, die die Nebenversion angibt. Nebenversionen werden typischerweise zweimal jährlich veröffentlicht und können neue Funktionen, Deprecations und Fehlerkorrekturen enthalten.MICROeine Ganzzahl ist, die eine Fehlerkorrekturversion angibt. Fehlerkorrekturversionen werden bei Bedarf veröffentlicht, typischerweise ein oder zwei pro Nebenversion. Sie dürfen keine neuen Funktionen oder Deprecations enthalten.
Freigegebene Alpha-, Beta- und RC-Versionen (Release Candidate) werden wie Endversionen nummeriert, aber mit den Suffixen a#, b# und rc#, wobei # eine Ganzzahl ist. Entwicklungsversionen sind mit .dev0+<git-commit-hash> postfixed.
Beispiele für gültige SciPy-Versionszeichenfolgen sind
0.16.0
0.15.1
0.14.0a1
0.14.0b2
0.14.0rc1
0.17.0.dev0+ac53f09
Eine installierte SciPy-Version enthält diese Versionsbezeichner
scipy.__version__ # complete version string, including git commit hash for dev versions
scipy.version.short_version # string, only major.minor.micro
scipy.version.version # string, same as scipy.__version__
scipy.version.full_version # string, same as scipy.__version__
scipy.version.release # bool, development or (alpha/beta/rc/final) released version
scipy.version.git_revision # string, git commit hash from which scipy was built
Deprecations#
Es gibt verschiedene Gründe, bestehende Funktionalität zu entfernen: sie ist fehlerhaft, die API ist nicht verständlich, sie wird durch Funktionalität mit besserer Leistung ersetzt, sie muss in ein anderes SciPy-Untermodul verschoben werden usw.
Im Allgemeinen ist es keine gute Idee, etwas zu entfernen, ohne die Benutzer vorher darüber zu informieren. Daher sollte Folgendes getan werden, bevor etwas aus der öffentlichen API entfernt wird:
Schlagen Sie vor, die Funktionalität im scipy-dev Forum als veraltet zu kennzeichnen und holen Sie die Zustimmung ein, dass dies in Ordnung ist.
Fügen Sie eine
DeprecationWarninghinzu, die besagt, dass die Funktionalität veraltet ist und in welcher Version. Für Cython-APIs siehe Deprecating public Cython APIs für die praktischen Schritte.Erwähnen Sie die Deprecation in den Release Notes für diese Version.
Warten Sie mindestens 6 Monate nach dem Veröffentlichungsdatum der Version, die die
DeprecationWarningeingeführt hat, bevor Sie die Funktionalität entfernen.Erwähnen Sie die Entfernung der Funktionalität in den Release Notes.
Die 6-monatige Wartezeit bedeutet in der Praxis normalerweise, zwei Releases zu warten. Bei der Einführung der Warnung stellen Sie auch sicher, dass diese Warnungen bei der Ausführung der Testsuite gefiltert werden, damit sie die Ausgabe nicht verunreinigen.
Es ist möglich, dass es Gründe gibt, diese Deprecationsrichtlinie für eine bestimmte Deprecation zu ignorieren; dies kann immer im scipy-dev Forum besprochen werden.
Vendored Code#
Viele Teile des SciPy-Codebestands werden woanders gewartet und in SciPy vendored. Einige dieser Teile werden als Git-Submodule vendored, z. B. xsf, oder sie werden im Verzeichnis subprojects platziert (oder beides).
Andere Teile werden nicht als Git-Submodule oder im Verzeichnis subprojects vendored, obwohl sie einen gewarteten Upstream haben. Dies liegt normalerweise entweder daran, dass
- ein Teil des Upstream-Repositorys mit einem Skript vendored wird.
(Es ist möglich, dass diese Teile zukünftig unter
subprojectsverschoben werden.)
- Code wurde in SciPy kopiert und seitdem modifiziert.
(Es ist möglich, dass einige dieser Teile Patches erhalten, die upstream beigetragen werden, und zukünftig Git-Submodule werden oder unter
subprojectsverschoben werden.)
Wartende sollten vorsichtig sein, keine Beiträge (insbesondere triviale Änderungen) in Teile von SciPy aufzunehmen, in denen der Code aktiv upstream gewartet wird. Stattdessen sollten sie Mitwirkende auf das Upstream-Repository verweisen.
Teile des Codebestands, die mit einem Skript vendored werden, umfassen
PRIMA, unter
scipy/_lib/pyprima
Teile des Codebestands, die Code enthalten, der von einem Upstream kopiert wurde, umfassen
DIRECT, unter
scipy/optimize/_directARPACK, unter
scipy/sparse/linalg/_eigen/arpack/ARPACKSuperLU, unter
scipy/sparse/linalg/_dsolve/SuperLUtrlib, unter
scipy/optimize/_trlibUNU.RAN, unter
scipy/stats/_unuranCython/Tempita, unter
scipy/_build_utils/tempitafast_matrix_market, unter
scipy/io/_fast_matrix_marketnumpydoc/docscrape, unter
scipy/_lib/_docscrape.py
Bitte beziehen Sie sich auf scipy/scipy#21232 für weitere Details und zur Verfolgung von vendored Code im Repository.
Verteilung#
Die Verteilung von Python-Paketen ist nicht trivial – insbesondere für ein Paket mit komplexen Build-Anforderungen wie SciPy – und unterliegt Änderungen. Für einen aktuellen Überblick über empfohlene Werkzeuge und Techniken siehe die Python Packaging User Guide. Dieses Dokument behandelt einige der wichtigsten Probleme und Überlegungen für SciPy.
Abhängigkeiten#
Abhängigkeiten sind Dinge, die ein Benutzer installieren muss, um ein Paket zu verwenden (oder zu bauen/testen). Sie verursachen normalerweise Probleme, insbesondere wenn sie nicht optional sind. SciPy versucht, seine Abhängigkeiten auf ein Minimum zu beschränken; die aktuellen erforderlichen und optionalen Build-Zeit-Abhängigkeiten können in der Konfigurationsdatei von SciPy, pyproject.toml, eingesehen werden. Die einzige nicht-optionale Laufzeitabhängigkeit ist NumPy.
Darüber hinaus benötigt man natürlich C-, C++- und Fortran-Compiler, um SciPy zu bauen, aber wir betrachten diese nicht als Abhängigkeiten und diskutieren sie daher hier nicht. Details finden Sie unter Building from source.
Wenn ein Paket nützliche Funktionalität bietet und als neue Abhängigkeit vorgeschlagen wird, überlegen Sie auch, ob es sinnvoll ist, das Paket stattdessen zu vendoren (d. h. eine Kopie davon mit SciPy zu verteilen). Zum Beispiel wird decorator in scipy._lib vendored.
Probleme mit der Abhängigkeitsverwaltung#
Es gibt einige Probleme mit der Handhabung von Abhängigkeiten durch Python-Packaging-Tools, die von Projekten berichtet werden. Da SciPy regelmäßige Fehlerberichte dazu erhält, gehen wir hier etwas ins Detail.
SciPy meldet seine Abhängigkeit von NumPy über pyproject.toml für Build-Zwecke, und SciPy hat auch eine Laufzeitprüfung, dass eine geeignete Version von NumPy verfügbar ist. SciPy verwendet nicht mehr setup_requires (was in der Vergangenheit easy_install aufgerufen hat); Build-Abhängigkeiten werden jetzt nur noch über pyproject.toml gehandhabt. pyproject.toml basiert auf PEP 517; pip hat Flags wie --no-use-pep517 und --no-build-isolation, die pyproject.toml ignorieren oder anders behandeln können – wenn Benutzer diese Flags verwenden, sind sie dafür verantwortlich, die korrekten Build-Abhängigkeiten selbst zu installieren.
Versionsbereiche für NumPy und andere Abhängigkeiten#
Für Abhängigkeiten ist es wichtig, untere und obere Grenzen für ihre Versionen festzulegen. Für **Build-Zeit**-Abhängigkeiten sind diese in pyproject.toml angegeben und die Versionen gelten **nur** für den SciPy-Build selbst. Es ist in Ordnung, entweder einen Bereich oder eine bestimmte Version für eine Abhängigkeit wie meson-python oder pybind11 anzugeben. Für NumPy müssen wir uns auch mit ABI-Kompatibilität befassen. Mit NumPy >=2.0.0rc1 ist die Abwärtskompatibilität jedoch so weit wie die NumPy 1.19-Serie garantiert, so dass die Angabe einer niedrigsten unterstützten NumPy-Version zur Build-Zeit in pyproject.toml nicht mehr erforderlich ist.
Für **Laufzeitabhängigkeiten** (derzeit nur numpy) geben wir den Versionsbereich in pyproject.toml und in scipy/__init__.py an. Das richtige obere Limit ist etwas knifflig. Wenn wir kein Limit setzen, wird in ein paar Jahren eine zu neue Version gezogen, und NumPy hat bis dahin möglicherweise eine API veraltet und entfernt, von der SciPy abhing. Andererseits, wenn wir das obere Limit auf die neueste bereits veröffentlichte Version setzen, wird, sobald eine neue NumPy-Version veröffentlicht wird, keine passende SciPy-Version mehr vorhanden sein, die damit funktioniert. Da sowohl NumPy als auch SciPy in einem halbjährlichen Rhythmus veröffentlichen und Funktionen, die in NumPy veraltet sind, noch zwei weitere Releases Bestand haben sollten, geben wir das obere Limit als <2.xx+3.0 an (wobei xx die Nebenversion des neuesten bereits veröffentlichten NumPy ist).
Unterstützte Python- und NumPy-Versionen#
Die von SciPy unterstützten Python-Versionen sind in der Liste der PyPI-Klassifikatoren in pyproject.toml aufgeführt und in den Release Notes für jede Version erwähnt. Alle neu veröffentlichten Python-Versionen werden so schnell wie möglich unterstützt. Für die allgemeine Richtlinie zur Einstellung der Unterstützung für eine Python- oder NumPy-Version siehe NEP 29. Die endgültige Entscheidung über die Einstellung der Unterstützung wird immer im scipy-dev Forum getroffen.
Die niedrigste unterstützte NumPy-Version für eine SciPy-Version wird in den Release Notes erwähnt und ist in pyproject.toml und scipy/__init__.py kodiert. Typischerweise unterstützt die neueste SciPy-Version etwa 5-7 Nebenversionen von NumPy: bis zu 2,5 Jahre alte NumPy-Versionen (da die Häufigkeit von NumPy-Releases zum Zeitpunkt des Schreibens etwa 2x/Jahr beträgt) plus zwei Versionen in die Zukunft.
Unterstützte Versionen von optionalen Abhängigkeiten und Compilern sind in Toolchain Roadmap dokumentiert. Beachten Sie, dass nicht alle unterstützten Versionen optionaler Abhängigkeiten von SciPy's Continuous Integration Setup gut oder überhaupt getestet werden. Probleme diesbezüglich werden behandelt, sobald sie im Issue Tracker oder Forum auftreten.
Erstellen von Binärinstallern#
Hinweis
Dieser Abschnitt bezieht sich nur auf das Erstellen von SciPy-Binärinstallern zur **Verteilung**. Informationen zum Erstellen von SciPy auf demselben Computer, auf dem es verwendet werden soll, finden Sie unter Building from source.
Es gibt eine Reihe von Dingen, die bei der Erstellung und Verteilung von Binärdateien auf PyPI oder anderswo zu berücksichtigen sind.
Allgemein
Eine Binärdatei ist spezifisch für eine einzelne (Haupt-)Python-Version (da verschiedene Haupt-Python-Versionen nicht ABI-kompatibel sind, zumindest bis Python 3.12).
Build gegen NumPy
2.0.0, dann funktioniert es für alle NumPy-Versionen mit derselben Hauptversionsnummer (NumPy pflegt Abwärts-ABI-Kompatibilität) und bis zurück zur NumPy1.19-Serie zum Zeitpunkt des Schreibens.Das am einfachsten verfügbare Toolchain zum Erstellen portabler SciPy-Binärdateien ist unsere
cibuildwheel-Infrastruktur für gängige Plattformen, mit Details in unserem CI-Infrastrukturcode und verfügbar über den Befehlcibuildwheelunter Windows, Linux und MacOS, wenn auch in einigen Fällen mit zusätzlichen externen Abhängigkeiten.
Windows
Für 64-Bit-Windows-Installer, die mit einer kostenlosen Toolchain erstellt wurden, verwenden Sie die unter numpy/numpy dokumentierte Methode. Diese Methode wird wahrscheinlich für SciPy selbst verwendet werden, sobald klar ist, dass die Wartung dieser Toolchain langfristig nachhaltig ist. Einzelheiten finden Sie im Projekt MingwPy und diesem Thread.
Der andere Weg, 64-Bit-Windows-Installer zu erstellen, ist mit
icc,ifortplusMKL(oderMSVCanstelle vonicc). Anweisungen für die Intel-Toolchain finden Sie in diesem Artikel und für (teilweise) MSVC-Anweisungen siehe diese Wiki-Seite.Ältere SciPy-Releases enthielten einen .exe „superpack“-Installer. Diese enthielten 3 vollständige Builds (kein SSE, SSE2, SSE3) und wurden mit numpy/numpy-vendor erstellt. Dieses Build-Setup funktioniert bekanntermaßen nicht mehr gut und wird nicht mehr unterstützt. Es verwendete g77 anstelle von gfortran, aufgrund komplexer DLL-Verteilungsprobleme (siehe gh-2829). Da die Toolchain nicht mehr unterstützt wird, ist die g77-Unterstützung nicht mehr erforderlich und SciPy kann nun Fortran 90/95-Code enthalten.
Linux
PyPI-kompatible Linux-Wheels können über das manylinux-Projekt erstellt werden, das im Hintergrund von unserer
cibuildwheel-Infrastruktur verwendet wird.
Andere Linux-Build-Setups führen zu PyPI-inkompatiblen Wheels, die über benutzerdefinierte Kanäle vertrieben werden müssten, z. B. in einem Wheelhouse, siehe die Dokumentation zu wheel und Wheelhouse.
Interaktive Beispiele in Docstrings#
Beispiele innerhalb von Docstrings können mit der jupyterlite-sphinx-Erweiterung interaktiv gestaltet werden, die die Direktive .. try_examples:: implementiert. Wenn diese Direktive im Abschnitt „Examples“ eines Docstrings verwendet wird, erstellt sie einen Button, mit dem Benutzer das Beispiel in einem interaktiven JupyterLite-Fenster oder in einem neuen Tab als Jupyter-Notebook öffnen können. Für SciPy wird diese Direktive automatisch zu allen Docstrings mit einem „Examples“-Abschnitt durch die Konfigurationsoption global_enable_try_examples in doc/source/conf.py hinzugefügt.
Um die Schaltflächen auszublenden, die Docstring-Beispiele in eingebettete Notebooks umwandeln, bearbeiten Sie nach dem Erstellen der HTML-Dokumentation die Laufzeitkonfigurationsdatei try_examples.json nach scipy/doc/build/html/ und fügen Sie die URL-Pfade der zu ignorierenden Dateien zur Liste ignore_patterns hinzu. Diese Liste erwartet Elemente als JavaScript-Regex-Muster. Die Anfangsversion dieser Datei in einem sauberen Dokumentations-Build ist
{
"global_min_height": "400px",
"ignore_patterns": [".*"]
}
Die Schaltflächen zum Konvertieren von Beispielabschnitten in eingebettete interaktive Notebooks sind bei sauberen Dokumentations-Builds standardmäßig ausgeblendet.
Weitere Informationen finden Sie in der Dokumentation zur jupyterlite-sphinx TryExamples-Direktive.
Eine SciPy-Version erstellen#
Auf höchster Ebene tut der Release-Manager Folgendes, um eine neue SciPy-Version zu veröffentlichen
Schlagen Sie einen Release-Zeitplan im SciPy-Forum unter https://discuss.scientific-python.org/ vor.
Erstellen Sie den Wartungszweig für den Release.
Tagen Sie den Release.
Erstellen Sie alle Release-Artefakte (Quellen, Installer, Dokumentation).
Laden Sie die Release-Artefakte hoch.
Kündigen Sie den Release an.
Portieren Sie relevante Änderungen an Release-Notizen und Build-Skripten nach main.
In dieser Anleitung versuchen wir, detailliert zu beschreiben, wie jeder der oben genannten Schritte ausgeführt wird. Zusätzlich zu diesen Schritten, die vom Release-Manager ausgeführt werden müssen, finden Sie hier Beschreibungen von Release-bezogenen Aktivitäten und Konventionen von Interesse
Vorschlag eines Release-Zeitplans#
Ein typischer Release-Zyklus sieht wie folgt aus
Erstellen Sie den Wartungszweig
Veröffentlichen Sie eine Beta-Version
Veröffentlichen Sie einen "Release Candidate" (RC)
Veröffentlichen Sie bei Bedarf einen oder mehrere neue RCs
Veröffentlichen Sie die endgültige Version, sobald keine Probleme mit dem letzten Release Candidate mehr bestehen
Zwischen jedem der oben genannten Schritte liegt normalerweise mindestens eine Woche. Erfahrungsgemäß dauert ein Zyklus für eine neue Nebenversion zwischen 4 und 8 Wochen. Bugfix-Versionen benötigen keine Beta- oder RC-Versionen und können viel schneller erstellt werden.
Idealerweise ist der endgültige Release identisch mit dem letzten RC, es kann jedoch geringfügige Unterschiede geben - es liegt am Release-Manager, das Risiko einzuschätzen. Typischerweise ist bei Änderungen am kompilierten Code oder komplexem reinem Python-Code ein neuer RC erforderlich, während ein einfacher Bugfix, der von main zurückportiert wird, keinen neuen RC erfordert.
Um einen Zeitplan vorzuschlagen, senden Sie eine Liste mit geschätzten Daten für das Verzweigen und die Veröffentlichung von Beta/RC/Endversion an das SciPy-Forum unter https://discuss.scientific-python.org/. Bitten Sie in derselben Nachricht alle, zu prüfen, ob wichtige Probleme/PRs enthalten sein müssen und nicht mit dem Meilenstein für den Release oder dem Label "backport-candidate" gekennzeichnet sind.
Erstellen des Wartungszweigs#
Stellen Sie vor dem Verzweigen sicher, dass die Release-Notizen so weit wie möglich aktualisiert sind. Fügen Sie die Ausgabe von tools/gh_lists.py und tools/authors.py in die Release-Notizen ein.
Wartungszweige werden mit maintenance/<major>.<minor>.x benannt (z. B. 0.19.x). Um einen zu erstellen, pushen Sie einfach einen Zweig mit dem korrekten Namen in das SciPy-Repository. Direkt danach pushen Sie einen Commit, bei dem Sie die Versionsnummer im Hauptzweig erhöhen und Release-Notizen für diese neue Version hinzufügen. Senden Sie eine E-Mail an das SciPy-Forum unter https://discuss.scientific-python.org/, um die Leute darüber zu informieren, dass Sie dies getan haben.
Aktualisieren des Versionsumschalters#
Das Dropdown-Menü für den Versionsumschalter muss nur im main-Zweig mit den neuen Release-Informationen aktualisiert werden.
doc/source/_static/version_switcher.json: Fügen Sie den neuen Release, die neue Entwicklungsvorschau und übertragen Sie"preferred": truevom alten Release auf den neuen Release.
Aktualisieren der Obergrenzen von Abhängigkeiten#
In main setzen wir keine Obergrenzen, da wir dort neue Releases oder Entwicklungsvorschauen von Abhängigkeiten testen möchten. In einem Wartungszweig hingegen besteht das Ziel darin, Releases erstellen zu können, die jahrelang funktionieren. Daher müssen korrekte Obergrenzen gesetzt werden. Die folgenden Stellen müssen nach der Erstellung eines Wartungszweigs aktualisiert werden
pyproject.toml: alle Build-Zeit-Abhängigkeiten sowie unterstützte Pythonund NumPy-Versionen
scipy/__init__.py: für die NumPy-Versionsprüfung
Jede Datei enthält Kommentare, die beschreiben, wie die korrekten Obergrenzen gesetzt werden.
Tagging eines Releases#
Stellen Sie zuerst sicher, dass GPG korrekt eingerichtet ist. Sehen Sie sich scipy/scipy#4919 für eine Diskussion über das Signieren von Release-Tags und https://keyring.debian.org/creating-key.html für Anweisungen zur Erstellung eines GPG-Schlüssels an, falls Sie noch keinen haben. Beachten Sie, dass auf einigen Plattformen die Verwendung von gpg2 anstelle von gpg geeigneter sein kann, sodass Passwörter von gpg-agent gespeichert werden können, wie in scipy/scipy#10189 diskutiert. Bei der Fernvorbereitung eines Releases kann es notwendig sein, pinentry-mode loopback in ~/.gnupg/gpg-agent.conf einzustellen, da die Verwendung von gpg2 andernfalls über eine unzugängliche grafische Passwortabfrage läuft.
Um Ihren Schlüssel leichter als Sie selbst identifizieren zu können, sollten Sie Ihren Schlüssel an öffentliche Schlüsselserver senden, z. B. mit einem Befehl wie
gpg --send-keys <yourkeyid>
Stellen Sie sicher, dass alle relevanten Commits im Branch vorhanden sind. Überprüfen Sie insbesondere die Issues und PRs unter dem Meilenstein für den Release (scipy/scipy), PRs mit dem Label "backport-candidate" und stellen Sie sicher, dass die Release-Notizen aktuell sind und in die HTML-Dokumentation aufgenommen wurden.
Aktualisieren Sie dann die version in pyproject.toml und committen Sie die Änderung mit einer Nachricht wie REL: set version to <version-number>. Pushen Sie diesen Commit noch nicht in das SciPy-Repository.
Taggen Sie schließlich den Release lokal mit git tag -s <v1.x.y> (das -s stellt sicher, dass der Tag signiert ist). Wenn gpg2 bevorzugt wird, ist git config --global gpg.program gpg2 möglicherweise angemessen. Fahren Sie mit dem Erstellen von Release-Artefakten fort (nächster Abschnitt). Pushen Sie den Release-Commit erst dann in das SciPy-Repository, wenn Sie die sdists und die Dokumentation erfolgreich erstellt haben. Fahren Sie dann mit dem Erstellen von Wheels fort. Pushen Sie den Release-Tag erst dann in das Repository, wenn alle Wheels auf TravisCI und Appveyor erfolgreich erstellt wurden (wenn dies fehlschlägt, müssen Sie den Tag verschieben - was schlechte Praxis ist). Pushen Sie schließlich nach dem Pushen des Tags einen zweiten Commit, der die Versionsnummer inkrementiert und .dev0 für version: anhängt und ISRELEASED wieder auf False setzt. Dies gilt auch für neue Release Candidates und zum Entfernen des rc-Suffixes beim Wechsel von Release Candidate zu einer endgültigen Version.
Erstellen von Release-Artefakten#
Hier ist eine vollständige Liste der Artefakte, die für einen Release erstellt werden
sdist (
scipy-x.y.y.tar.gz, sowohl für PyPI als auch für GitHub Releases)Binäre Wheels für Windows, Linux und macOS
Dokumentation (html)
Eine Datei
README.txtEine Datei
Changelog
Eine sdist wird durch Ausführen von python -m build --sdist generiert (Hinweis: Dies müssen wir noch in einen CI-Job verschieben!), und der Changelog sowie die README werden durch Ausführen von python dev.py notes (mit Tags, siehe python dev.py notes --help) im Stammverzeichnis des Repos erstellt und landen in REPO_ROOT/release/. Tun Sie dies, nachdem Sie den signierten Tag lokal erstellt haben. Wenn dies ohne Probleme abgeschlossen ist, pushen Sie den Release-Commit (nicht den Tag, siehe oben) in das SciPy-Repository.
Um Wheels zu erstellen, pushen Sie einen Commit mit dem Text [wheel build] in den für den aktuellen Release verwendeten Branch. Dies löst cibuildwheel-Builds für alle benötigten Python-Versionen und Plattformen aus. Die entsprechenden Versionsfestlegungen für NumPy und andere Abhängigkeiten sollten kurz nach dem Verzweigen in pyproject.toml aktualisiert worden sein. Wenn die Wheel-Builds Probleme aufdecken, die mit Backports auf dem Wartungszweig behoben werden müssen, können Sie die lokalen Tags entfernen (z. B. git tag -d v1.2.0rc1) und mit dem Tagging oben auf dem neuen Kandidaten-Commit neu starten.
Die cibuildwheel-Infrastruktur führt die Tests aus den erstellten Wheels aus und lädt sie bei Erfolg auf https://anaconda.org/multibuild-wheels-staging/scipy hoch.
Von dort können Sie sie herunterladen, um sie auf PyPI hochzuladen. Dies kann automatisiert mit tools/download-wheels.py erfolgen
$ python tools/download-wheels.py 1.5.0rc1 -w REPO_ROOT/release/installers
Danach möchten wir die README-Datei neu generieren, um die MD5- und SHA256-Checksummen der gerade heruntergeladenen Wheels darin zu haben. Führen Sie python dev.py notes erneut aus.
Hochladen von Release-Artefakten#
Für einen Release gibt es derzeit fünf Orte im Web, an die Dinge hochgeladen werden können
PyPI (sdist, Wheels)
GitHub Releases (sdist, Release-Notizen, Changelog)
scipy.org (eine Ankündigung des Releases)
docs.scipy.org (html docs)
PyPI
Laden Sie zuerst die Wheels und dann die sdist hoch
twine upload REPO_ROOT/release/installers/*.whl
twine upload REPO_ROOT/release/installers/scipy-1.x.y.tar.gz
GitHub Releases
Verwenden Sie die GUI unter scipy/scipy, um den Release zu erstellen und alle Release-Artefakte hochzuladen. Zu diesem Zeitpunkt ist es angebracht, den Tag zu pushen und den neuen Release (Candidate) in der GUI mit diesem Tag zu verknüpfen. Zum Beispiel: git push upstream v1.2.0rc1, wobei upstream scipy/scipy repräsentiert. Es ist hilfreich, einen früheren Release zu überprüfen, um genau zu bestimmen, welche Artefakte in den GUI-Upload-Prozess aufgenommen werden sollen. Beachten Sie auch, dass die Release-Notizen nicht automatisch in die Release-Beschreibung auf GitHub übernommen werden und einige manuelle Formatierungen zu Markdown auf der Website sehr hilfreich sein können, um das Format früherer Releases anzupassen. Wir nehmen im Allgemeinen keine Liste von Issues und Pull Requests in diese GUI-Beschreibungen auf.
scipy.org
Die Quellen für die Website befinden sich in scipy/scipy.org. Aktualisieren Sie den Abschnitt "News" in content/en/news.md über einen PR. Dies gilt nur für echte Releases, nicht für Release Candidates.
docs.scipy.org
Erstellen Sie zuerst die SciPy-Dokumentation, indem Sie make dist in scipy/doc/ ausführen. Überprüfen Sie, ob sie in Ordnung aussehen, und laden Sie sie dann mit make upload USERNAME=rgommers RELEASE=0.19.0 auf den Doc-Server hoch. Beachten Sie, dass SSH-Zugriff auf den Doc-Server benötigt wird. Fragen Sie @pv (Server-Admin), @tylerjereddy oder @rgommers (können hochladen), wenn Sie diesen nicht haben.
Die Quellen für die Website selbst werden in scipy/docs.scipy.org gepflegt. Fügen Sie die neue SciPy-Version in die Tabelle der Releases in index.rst ein. Pushen Sie diesen Commit und führen Sie dann make upload USERNAME=yourusername aus. Dies gilt nur für echte Releases, nicht für Release Candidates.
Hinweis
Der Versionsumschalter auf der bereitgestellten Dokumentation wird den neuen Release erst als stabile Version berücksichtigen, wenn die Änderungen an version_switcher.json in den main-Zweig übernommen wurden (siehe gh-22305). Daher sollten die Release-Notizen und die Änderungen am Versionsumschalter idealerweise zur gleichen Zeit nach main portiert werden, wenn die Dokumentation für den neuen Release bereitgestellt wird.
Abschluss#
Senden Sie eine Nachricht, die den Release ankündigt, an https://discuss.scientific-python.org/c/announcements/.
Für Beta- und RC-Versionen bitten Sie die Leute, zu testen (die SciPy-Tests auszuführen und gegen ihren eigenen Code zu testen) und Probleme auf Github oder Discourse zu melden.
Nachdem der endgültige Release abgeschlossen ist, portieren Sie relevante Änderungen an Release-Notizen, Build-Skripten, der Zuordnung von Autorennamen in tools/authors.py und allen anderen Änderungen, die nur im Wartungszweig vorgenommen wurden, nach main.
Interaktive Beispiele aktivieren, indem die Laufzeitkonfigurationsdatei try_examples.json im Stammverzeichnis der hochgeladenen Dokumentation auf dem Release-Server bearbeitet wird. Man muss den regulären Ausdruck ".*" aus der Liste ignore_patterns entfernen.
$ ssh your-username@docs.scipy.org
$ cd /srv/docs_scipy_org/doc/scipy-1.13.1
$ vim try_examples.json # edit the ignore list to remove: ".*"