Haftungsausschluss: In diesem Tutorial wird davon ausgegangen, dass die Leser über grundlegende Kenntnisse in Python, APIs, Git und Unit Tests verfügen. Ich bin auf verschiedene CLI-Software mit den coolsten Animationen gestoßen und habe mich gefragt: Könnte ich jemals mein „minimalistisches“ Stein-Schere-Papier-Schulprojekt aktualisieren? Hallo, lass uns spielen! Wählen Sie Ihren Kämpfer (Stein, Papier, Schere): Stein Was ist ein CLI-Programm? Wie es auf Wikipedia heißt: „Eine Befehlszeilenschnittstelle (CLI) ist ein Mittel zur Interaktion mit einem Gerät oder Computerprogramm mit Befehlen von einem Benutzer oder Client und Antworten vom Gerät oder Programm in Form von Textzeilen.“ Mit anderen Worten ist ein CLI-Programm ein Programm, bei dem der Benutzer die Befehlszeile verwendet, um mit dem Programm zu interagieren, indem er Anweisungen zur Ausführung gibt. Viele alltägliche Software ist als CLI-Programm verpackt. Nehmen Sie zum Beispiel den Texteditor – ein Tool, das mit jedem UNIX-System geliefert wird und einfach durch Ausführen im Terminal aktiviert werden kann. vim vim <FILE> Lassen Sie uns in Bezug auf die in die Anatomie eines CLI-Programms eintauchen. Google Cloud CLI Argumente Argumente (Parameter) sind Informationselemente, die einem Programm bereitgestellt werden. Sie werden oft als Positionsargumente bezeichnet, weil sie durch ihre Position identifiziert werden. Wenn wir beispielsweise die im Kernabschnitt festlegen möchten, führen wir aus project gcloud config set project <PROJECT_ID> Insbesondere können wir dies in übersetzen Streit Inhalt Argument 0 gcloud Argument 1 config … … Befehle Befehle sind eine Reihe von Argumenten, die dem Computer Anweisungen geben. Basierend auf dem vorherigen Beispiel legen wir die im Kernabschnitt fest, indem wir ausführen project gcloud config set project <PROJECT_ID> Mit anderen Worten, ist ein Befehl. set Optionale Befehle Normalerweise sind Befehle erforderlich, wir können jedoch Ausnahmen machen. Basierend auf dem Anwendungsfall des Programms können wir optionale Befehle definieren. Bezugnehmend auf den Befehl , wie in der offiziellen Dokumentation angegeben, handelt es sich bei um eine Befehlsgruppe, mit der Sie Eigenschaften ändern können. Die Verwendung ist als solche: gcloud config gcloud config gcloud config GROUP | COMMAND [GCLOUD_WIDE_FLAG … ] wobei COMMAND entweder , usw. sein kann ... (Beachten Sie, dass GROUP ist) set list config Optionen Optionen sind dokumentierte Parametertypen, die das Verhalten eines Befehls ändern. Es handelt sich um Schlüssel-Wert-Paare, die mit „-“ oder „--“ gekennzeichnet sind. Zurück zur Verwendung der Befehlsgruppe: Die Option(en) sind in diesem Fall . gcloud config GCLOUD_WIDE_FLAG Angenommen, wir möchten die detaillierte Verwendung und Beschreibung des Befehls anzeigen, führen wir aus. Mit anderen Worten: ist die Option. gcloud config set –help --help Ein weiteres Beispiel: Wenn wir die Zoneneigenschaft im Compute-Abschnitt eines bestimmten Projekts festlegen möchten, führen wir aus. Mit anderen Worten: ist eine Option, die den Wert enthält. gcloud config set compute <ZONE_NAME> –project=<PROJECT_ID> --project <PROJECT_ID> Es ist auch wichtig zu beachten, dass ihre Positionen normalerweise keine Rolle spielen. Obligatorische Optionen Optionen wie der Name sind normalerweise optional, können aber auch so angepasst werden, dass sie obligatorisch sind. Wenn wir beispielsweise einen Dataproc-Cluster erstellen möchten, führen wir aus. Und wie in ihrer Nutzungsdokumentation angegeben: gcloud dataproc clusters create <CLUSTER_NAME> –region=<REGION> gcloud dataproc clusters create (CLUSTER: –region=REGION) Das Flag ist obligatorisch, wenn es nicht zuvor konfiguriert wurde. --region Short-Optionen vs. Long-Optionen Kurze Optionen beginnen mit gefolgt von einem einzelnen alphanumerischen Zeichen, während lange Optionen mit gefolgt von mehreren Zeichen beginnen. Stellen Sie sich kurze Optionen als Abkürzungen vor, wenn der Benutzer sicher ist, was er möchte, während lange Optionen besser lesbar sind. - -- Du hast dich für Rock entschieden! Der Computer trifft nun seine Auswahl. Was werden wir mit diesem Tutorial erreichen? Also habe ich gelogen ... Wir werden nicht versuchen, das CLI-Programm „Stein-Papier-Schere“ zu aktualisieren. Schauen wir uns stattdessen ein reales Szenario an: Gliederung und Ziele Ihr Team verwendet Trello, um die Probleme und den Fortschritt des Projekts zu verfolgen. Ihr Team sucht nach einer einfacheren Möglichkeit, mit dem Board zu interagieren – ähnlich wie beim Erstellen eines neuen GitHub-Repositorys über das Terminal. Das Team hat sich an Sie gewandt, um ein CLI-Programm mit der Grundvoraussetzung zu erstellen, dass Sie der Spalte „Zu erledigen“ des Boards eine neue Karte hinzufügen können. Basierend auf der genannten Anforderung entwerfen wir unser CLI-Programm, indem wir seine Anforderungen definieren: Funktionale Anforderungen Der Benutzer kann einer Spalte auf der Tafel eine neue Karte hinzufügen Erforderliche Eingaben: Spalte, Kartenname Optionale Eingaben: Kartenbeschreibung, Kartenetiketten (aus vorhandenen auswählen) Nicht-funktionale Anforderungen Programm, das den Benutzer auffordert, Zugriff auf das Trello-Konto zu gewähren (Autorisierung) Programm, das den Benutzer auffordert, festzulegen, auf welchem Trello-Board gearbeitet werden soll (Konfiguration) Optionale Anforderungen Der Benutzer kann dem Board eine neue Spalte hinzufügen Der Benutzer kann dem Board ein neues Etikett hinzufügen Der Benutzer kann eine vereinfachte/detaillierte Ansicht aller Spalten sehen Basierend auf dem oben Gesagten können wir die Befehle und Optionen unseres CLI-Programms wie folgt formalisieren: Ps. Machen Sie sich keine Sorgen wegen der letzten beiden Spalten, wir werden später mehr darüber erfahren … Was unseren Tech-Stack betrifft, bleiben wir dabei: Unit-Tests pytest pytest-mock CLI-Test-Helfer Trello py-trello (Python-Wrapper für das Trello SDK) CLI Schreiber reich Simple-Term-Menü Dienstprogramme (Verschiedenes) python-dotenv Zeitleiste Wir werden dieses Projekt in Teilen angehen und hier ist ein Ausschnitt dessen, was Sie erwarten können: Teil 1 Implementierung der Geschäftslogik py-trello Teil 2 Implementierung der CLI-Geschäftslogik Verteilen des CLI-Programms als Paket Teil 3 Umsetzung optionaler funktionaler Anforderungen Paketaktualisierung Der Computer hat sich für die Schere entschieden! Mal sehen, wer diesen Kampf gewinnt ... Lass uns anfangen Ordnerstruktur Ziel ist es, das CLI-Programm als Paket auf zu verteilen. Daher ist ein solches Setup erforderlich: PyPI trellocli/ __init__.py __main__.py models.py cli.py trelloservice.py tests/ test_cli.py test_trelloservice.py README.md pyproject.toml .env .gitignore Hier ist ein tiefer Einblick in jede Datei und/oder jedes Verzeichnis: : fungiert als Paketname, der von Benutzern verwendet werden soll, z. B. trellocli pip install trellocli : Stellt das Stammverzeichnis des Pakets dar und passt den Ordner als Python-Paket an __init__.py : Definiert den Einstiegspunkt und ermöglicht Benutzern das Ausführen von Modulen ohne Angabe des Dateipfads durch Verwendung des Flags , z. B. , um zu ersetzen __main__.py -m python -m <module_name> python -m <parent_folder>/<module_name>.py : speichert global verwendete Klassen, z. B. Modelle, denen API-Antworten entsprechen sollen models.py : speichert die Geschäftslogik für CLI-Befehle und -Optionen cli.py : speichert die Geschäftslogik für die Interaktion mit trelloservice.py py-trello : speichert Unit-Tests für das Programm tests : speichert Unit-Tests für die CLI-Implementierung test_cli.py : speichert Unit-Tests für die Interaktion mit test_trelloservice.py py-trello : speichert die Dokumentation für das Programm README.md : speichert die Konfigurationen und Anforderungen des Pakets pyproject.toml : speichert Umgebungsvariablen .env : Gibt die Dateien an, die während der Versionskontrolle ignoriert (nicht verfolgt) werden sollen .gitignore Eine ausführlichere Erklärung zum Veröffentlichen von Python-Paketen finden Sie in diesem großartigen Artikel: „How to Publish an Open-Source Python Package to PyPI“ von Geir Arne Hjelle Aufstellen Bevor wir beginnen, gehen wir zunächst auf die Einrichtung des Pakets ein. Beginnend mit der Datei in unserem Paket, in der Paketkonstanten und -variablen wie App-Name und -Version gespeichert werden. In unserem Fall wollen wir Folgendes initialisieren: __init__.py App Name Ausführung SUCCESS- und ERROR-Konstanten # trellocli/__init__.py __app_name__ = "trellocli" __version__ = "0.1.0" ( SUCCESS, TRELLO_WRITE_ERROR, TRELLO_READ_ERROR ) = range(3) ERRORS = { TRELLO_WRITE_ERROR: "Error when writing to Trello", TRELLO_READ_ERROR: "Error when reading from Trello" } Wenn wir zur Datei übergehen, sollte hier der Hauptablauf Ihres Programms gespeichert sein. In unserem Fall speichern wir den Einstiegspunkt des CLI-Programms, vorausgesetzt, dass es in eine aufrufbare Funktion gibt. __main__.py cli.py # trellocli/__main__.py from trellocli import cli def main(): # we'll modify this later - after the implementation of `cli.py` pass if __name__ == "__main__": main() Nachdem das Paket nun eingerichtet wurde, werfen wir einen Blick auf die Aktualisierung unserer Datei (Hauptdokumentation). Es gibt keine bestimmte Struktur, der wir folgen müssen, aber eine gute README-Datei würde aus Folgendem bestehen: README.md Überblick Installation und Anforderungen Erste Schritte und Verwendung Ein weiterer toller Beitrag zum Nachlesen, wenn Sie tiefer eintauchen möchten: How to Write a Good README von merlos So möchte ich die README-Datei für dieses Projekt strukturieren <!--- README.md --> # Overview # Getting Started # Usage # Architecture ## Data Flow ## Tech Stack # Running Tests # Next Steps # References Lassen wir das Grundgerüst vorerst so, wie es ist – wir kommen später darauf zurück. Lassen Sie uns nun die Metadaten unseres Pakets basierend auf der konfigurieren offiziellen Dokumentation # pyproject.toml [project] name = "trellocli_<YOUR_USERNAME>" version = "0.1.0" authors = [ { name = "<YOUR_NAME>", email = "<YOUR_EMAIL>" } ] description = "Program to modify your Trello boards from your computer's command line" readme = "README.md" requires-python = ">=3.7" classifiers = [ "Programming Language :: Python :: 3", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", ] dependencies = [] [project.urls] "Homepage" = "" Beachten Sie, dass es Platzhalter gibt, die Sie ändern müssen, z. B. Ihren Benutzernamen, Ihren Namen usw. Außerdem lassen wir die Homepage-URL vorerst leer. Wir werden Änderungen vornehmen, nachdem wir es auf GitHub veröffentlicht haben. Außerdem lassen wir den Abschnitt „Abhängigkeiten“ vorerst leer und fügen ihn nach und nach hinzu. Als nächstes auf der Liste wäre unsere Datei, in der wir unsere Umgebungsvariablen wie API-Geheimnisse und Schlüssel speichern. Es ist wichtig zu beachten, dass diese Datei nicht von Git verfolgt werden sollte, da sie vertrauliche Informationen enthält. .env In unserem Fall speichern wir hier unsere Trello-Zugangsdaten. Befolgen Sie , um ein Power-Up in Trello zu erstellen. Genauer gesagt, basierend auf der Verwendung durch , da wir OAuth für unsere Anwendung verwenden möchten, benötigen wir Folgendes, um mit Trello zu interagieren: diese Anleitung py-trello API-Schlüssel (für unsere Anwendung) API-Geheimnis (für unsere Anwendung) Token (Token des Benutzers, um Zugriff auf seine Daten zu gewähren) Sobald Sie Ihren API-Schlüssel und Ihr Geheimnis abgerufen haben, speichern Sie sie als solche in der Datei .env # .env TRELLO_API_KEY=<your_api_key> TRELLO_API_SECRET=<your_api_secret> Zu guter Letzt verwenden wir die Vorlage Python , die Sie finden. Beachten Sie, dass dies von entscheidender Bedeutung ist, um sicherzustellen, dass unsere Datei niemals verfolgt wird. Wenn unsere Datei irgendwann verfolgt wurde, ist der Schaden bereits angerichtet und böswillige Akteure können die vorherige Datei aufspüren, auch wenn wir sie in späteren Schritten entfernt haben Patches für vertrauliche Informationen. .gitignore hier .env .env Nachdem die Einrichtung nun abgeschlossen ist, übertragen wir unsere Änderungen auf GitHub. Denken Sie je nach den in angegebenen Metadaten daran, Ihre LIZENZ und Homepage-URL entsprechend zu aktualisieren. Als Referenz zum Schreiben besserer Commits: pyproject.toml Write Better Commits, Build Better Projects von Victoria Dye Weitere bemerkenswerte Schritte: Erstellen Sie eine virtuelle Umgebung für das Projekt Unit-Tests Bevor wir mit dem Schreiben unserer Tests beginnen, ist es wichtig zu beachten, dass wir, da wir mit einer API arbeiten, Scheintests implementieren werden, um unser Programm ohne das Risiko von API-Ausfällen testen zu können. Hier ist ein weiterer großartiger Artikel über Mock-Tests von Real Python: Mocking External APIs in Python Basierend auf den funktionalen Anforderungen besteht unser Hauptanliegen darin, Benutzern das Hinzufügen einer neuen Karte zu ermöglichen. Verweisen auf die Methode in : . Dazu müssen wir die Methode aus der Klasse aufrufen, die über die Funktion aus der Klasse „ abgerufen werden kann. py-trello add_card add_card List get_list Board Sie verstehen das Wesentliche – wir werden viele Hilfsmethoden benötigen, um unser endgültiges Ziel zu erreichen. Sagen wir es in Worten: Testen Sie, um das Token des Clients abzurufen Testen Sie, um Boards abzurufen Testen Sie, um ein Board abzurufen Testen Sie, um Listen vom Board abzurufen Testen Sie, um eine Liste abzurufen Testen Sie, um Etiketten von der Tafel abzurufen Testen Sie, um ein Etikett abzurufen Testen Sie, um eine Karte hinzuzufügen Testen Sie, um der Karte ein Etikett hinzuzufügen Es ist auch wichtig zu beachten, dass wir beim Schreiben von Unit-Tests darauf achten, dass unsere Tests so umfangreich wie möglich sind. Werden Fehler gut verarbeitet? Deckt es jeden Aspekt unseres Programms ab? Allerdings werden wir in diesem Tutorial die Dinge vereinfachen, indem wir nur nach Erfolgsfällen suchen. Bevor wir in den Code eintauchen, ändern wir unsere Datei so, dass sie die Abhängigkeiten enthält, die zum Schreiben/Ausführen von Komponententests erforderlich sind. pyproject.toml # pyproject.toml [project] dependencies = [ "pytest==7.4.0", "pytest-mock==3.11.1" ] Als nächstes aktivieren wir unsere virtuelle Umgebung und führen um die Abhängigkeiten zu installieren. pip install . Sobald das erledigt ist, schreiben wir endlich einige Tests. Im Allgemeinen sollten unsere Tests eine zurückgegebene simulierte Antwort, einen Patch für die Funktion, die wir testen möchten, indem wir den Rückgabewert mit der simulierten Antwort korrigieren, und schließlich einen Aufruf der Funktion umfassen. Ein Beispieltest zum Abrufen der Zugriffstoken des Benutzers würde wie folgt aussehen: # tests/test_trelloservice.py # module imports from trellocli import SUCCESS from trellocli.trelloservice import TrelloService from trellocli.models import * # dependencies imports # misc imports def test_get_access_token(mocker): """Test to check success retrieval of user's access token""" mock_res = GetOAuthTokenResponse( token="test", token_secret="test", status_code=SUCCESS ) mocker.patch( "trellocli.trelloservice.TrelloService.get_user_oauth_token", return_value=mock_res ) trellojob = TrelloService() res = trellojob.get_user_oauth_token() assert res.status_code == SUCCESS Beachten Sie in meinem Beispielcode, dass ein Modell ist, das noch in festgelegt werden muss. Es bietet Struktur zum Schreiben sauberer Codes. Wir werden dies später in Aktion sehen. GetOAuthTokenResponse models.py Um unsere Tests auszuführen, führen Sie einfach aus. Beachten Sie, dass unsere Tests scheitern werden, aber das ist in Ordnung – am Ende wird es klappen. python -m pytest 💡 Können Sie versuchen, weitere Tests selbst zu schreiben? Sehen Sie sich gerne an, um zu sehen, wie meine Tests aussehen Challenge Corner diesen Patch Lassen Sie uns zunächst unseren aufbauen. Beginnen Sie mit dem Hinzufügen einer neuen Abhängigkeit, dem -Wrapper. trelloservice py-trello # pyproject.toml dependencies = [ "pytest==7.4.0", "pytest-mock==3.11.1", "py-trello==0.19.0" ] Führen Sie erneut um die Abhängigkeiten zu installieren. pip install . Modelle Beginnen wir nun mit dem Aufbau unserer Modelle – um die Antworten zu regulieren, die wir in erwarten. Für diesen Teil lesen Sie am besten unsere Unit-Tests und den Quellcode, um zu verstehen, welche Art von Rückgabewert wir erwarten können. trelloservice py-trello Angenommen, wir möchten das Zugriffstoken des Benutzers abrufen und beziehen uns dabei auf die Funktion von ( ). Wir wissen, dass wir einen Rückgabewert wie diesen erwarten können create_oauth_token py-trello Quellcode # trellocli/models.py # module imports # dependencies imports # misc imports from typing import NamedTuple class GetOAuthTokenResponse(NamedTuple): token: str token_secret: str status_code: int Beachten Sie andererseits widersprüchliche Namenskonventionen. Das Modul hat beispielsweise eine Klasse namens . Eine Lösung hierfür wäre die Bereitstellung eines Alias beim Import. py-trello List # trellocli/models.py # dependencies imports from trello import List as Trellolist Nutzen Sie diese Gelegenheit gerne auch, um die Modelle an die Bedürfnisse Ihres Programms anzupassen. Angenommen, Sie benötigen nur ein Attribut aus dem Rückgabewert. Sie könnten Ihr Modell so umgestalten, dass es den besagten Wert aus dem Rückgabewert extrahiert, anstatt ihn als Ganzes zu speichern. # trellocli/models.py class GetBoardName(NamedTuple): """Model to store board id Attributes id (str): Extracted board id from Board value type """ id: str 💡 Kannst du versuchen, selbst mehr Modelle zu schreiben? Sehen Sie sich gerne an, um zu sehen, wie meine Modelle aussehen Challenge Corner diesen Patch Geschäftslogik Aufstellen Modelle runter, lasst uns offiziell mit dem Codieren des beginnen. Auch hier sollten wir uns auf die von uns erstellten Unit-Tests beziehen. Nehmen wir an, dass die aktuelle Testliste den Dienst nicht vollständig abdeckt. Kommen Sie immer zurück und fügen Sie bei Bedarf weitere Tests hinzu. trelloservice Fügen Sie wie üblich alle Importanweisungen oben ein. Erstellen Sie dann wie erwartet die Klasse und die Platzhaltermethoden. Die Idee ist, dass wir eine gemeinsame Instanz des Dienstes in initialisieren und seine Methoden entsprechend aufrufen. Darüber hinaus streben wir nach Skalierbarkeit und damit nach einer umfassenden Abdeckung. TrelloService cli.py # trellocli/trelloservice.py # module imports from trellocli import TRELLO_READ_ERROR, TRELLO_WRITE_ERROR, SUCCESS from trellocli.models import * # dependencies imports from trello import TrelloClient # misc imports class TrelloService: """Class to implement the business logic needed to interact with Trello""" def __init__(self) -> None: pass def get_user_oauth_token() -> GetOAuthTokenResponse: pass def get_all_boards() -> GetAllBoardsResponse: pass def get_board() -> GetBoardResponse: pass def get_all_lists() -> GetAllListsResponse: pass def get_list() -> GetListResponse: pass def get_all_labels() -> GetAllLabelsResponse: pass def get_label() -> GetLabelResponse: pass def add_card() -> AddCardResponse: pass PS: Beachten Sie, dass unsere Tests dieses Mal bestanden werden, wenn wir unsere Tests durchführen. Tatsächlich wird uns das dabei helfen, sicherzustellen, dass wir auf dem richtigen Weg bleiben. Der Arbeitsablauf sollte darin bestehen, unsere Funktionen zu erweitern, unsere Tests auszuführen, auf Pass/Fail zu prüfen und entsprechend umzugestalten. Autorisierung und Initialisierung von TrelloClient Beginnen wir mit der Funktion . Die Idee ist, hier die Funktion aufzurufen und den zu initialisieren. Um die Notwendigkeit zu betonen, solche vertraulichen Informationen nur in der Datei zu speichern, verwenden wir die Abhängigkeit , um vertrauliche Informationen abzurufen. Nachdem wir unsere Datei entsprechend geändert haben, beginnen wir mit der Implementierung der Autorisierungsschritte. __init__ get_user_oauth_token TrelloClient .env python-dotenv pyproject.toml # trellocli/trelloservice.py class TrelloService: """Class to implement the business logic needed to interact with Trello""" def __init__(self) -> None: self.__load_oauth_token_env_var() self.__client = TrelloClient( api_key=os.getenv("TRELLO_API_KEY"), api_secret=os.getenv("TRELLO_API_SECRET"), token=os.getenv("TRELLO_OAUTH_TOKEN") ) def __load_oauth_token_env_var(self) -> None: """Private method to store user's oauth token as an environment variable""" load_dotenv() if not os.getenv("TRELLO_OAUTH_TOKEN"): res = self.get_user_oauth_token() if res.status_code == SUCCESS: dotenv_path = find_dotenv() set_key( dotenv_path=dotenv_path, key_to_set="TRELLO_OAUTH_TOKEN", value_to_set=res.token ) else: print("User denied access.") self.__load_oauth_token_env_var() def get_user_oauth_token(self) -> GetOAuthTokenResponse: """Helper method to retrieve user's oauth token Returns GetOAuthTokenResponse: user's oauth token """ try: res = create_oauth_token() return GetOAuthTokenResponse( token=res["oauth_token"], token_secret=res["oauth_token_secret"], status_code=SUCCESS ) except: return GetOAuthTokenResponse( token="", token_secret="", status_code=TRELLO_AUTHORIZATION_ERROR ) In dieser Implementierung haben wir eine Hilfsmethode erstellt, um alle vorhersehbaren Fehler zu behandeln, z. B. wenn der Benutzer während der Autorisierung auf klickt. Darüber hinaus ist es so eingerichtet, dass es rekursiv nach der Autorisierung des Benutzers fragt, bis eine gültige Antwort zurückgegeben wird, denn Tatsache ist, dass wir nicht fortfahren können, es sei denn, der Benutzer autorisiert unsere App, auf seine Kontodaten zuzugreifen. Deny 💡 Beachten Sie ? Können Sie diesen Fehler als Paketkonstante deklarieren? Weitere Informationen finden Sie unter „Setup“. Challenge Corner TRELLO_AUTHORIZATION_ERROR Hilfsfunktionen Nachdem der Autorisierungsteil nun abgeschlossen ist, gehen wir zu den Hilfsfunktionen über und beginnen mit dem Abrufen der Trello-Boards des Benutzers. # trellocli/trelloservice.py def get_all_boards(self) -> GetAllBoardsResponse: """Method to list all boards from user's account Returns GetAllBoardsResponse: array of user's trello boards """ try: res = self.__client.list_boards() return GetAllBoardsResponse( res=res, status_code=SUCCESS ) except: return GetAllBoardsResponse( res=[], status_code=TRELLO_READ_ERROR ) def get_board(self, board_id: str) -> GetBoardResponse: """Method to retrieve board Required Args board_id (str): board id Returns GetBoardResponse: trello board """ try: res = self.__client.get_board(board_id=board_id) return GetBoardResponse( res=res, status_code=SUCCESS ) except: return GetBoardResponse( res=None, status_code=TRELLO_READ_ERROR ) Zum Abrufen der Listen (Spalten) müssen wir die Klasse von auschecken, oder mit anderen Worten, wir müssen einen neuen Parameter des Werttyps akzeptieren. Board py-trello Board # trellocli/trelloservice.py def get_all_lists(self, board: Board) -> GetAllListsResponse: """Method to list all lists (columns) from the trello board Required Args board (Board): trello board Returns GetAllListsResponse: array of trello lists """ try: res = board.all_lists() return GetAllListsResponse( res=res, status_code=SUCCESS ) except: return GetAllListsResponse( res=[], status_code=TRELLO_READ_ERROR ) def get_list(self, board: Board, list_id: str) -> GetListResponse: """Method to retrieve list (column) from the trello board Required Args board (Board): trello board list_id (str): list id Returns GetListResponse: trello list """ try: res = board.get_list(list_id=list_id) return GetListResponse( res=res, status_code=SUCCESS ) except: return GetListResponse( res=None, status_code=TRELLO_READ_ERROR ) 💡 Könnten Sie die Funktionen und selbst implementieren? Überarbeiten Sie die Klasse von . Sehen Sie sich gerne an, um zu sehen, wie meine Implementierung aussieht Challenge Corner get_all_labels get_label Board py-trello diesen Patch Funktion zum Hinzufügen einer neuen Karte Zu guter Letzt haben wir endlich das erreicht, was wir die ganze Zeit angestrebt haben – das Hinzufügen einer neuen Karte. Beachten Sie, dass wir hier nicht alle zuvor deklarierten Funktionen verwenden – das Ziel der Hilfsfunktionen besteht darin, die Skalierbarkeit zu erhöhen. # trellocli/trelloservice.py def add_card( self, col: Trellolist, name: str, desc: str = "", labels: List[Label] = [] ) -> AddCardResponse: """Method to add a new card to a list (column) on the trello board Required Args col (Trellolist): trello list name (str): card name Optional Args desc (str): card description labels (List[Label]): list of labels to be added to the card Returns AddCardResponse: newly-added card """ try: # create new card new_card = col.add_card(name=name) # add optional description if desc: new_card.set_description(description=desc) # add optional labels if labels: for label in labels: new_card.add_label(label=label) return AddCardResponse( res=new_card, status_code=SUCCESS ) except: return AddCardResponse( res=new_card, status_code=TRELLO_WRITE_ERROR ) 🎉 Nachdem das erledigt ist, denken Sie daran, Ihre README-Datei entsprechend zu aktualisieren und Ihren Code auf GitHub zu übertragen. Glückwunsch! Du hast gewonnen. Nochmals spielen (j/n)? Einpacken Vielen Dank für Ihr Verständnis :) Durch dieses Tutorial haben Sie erfolgreich gelernt, Mocking beim Schreiben von Unit-Tests zu implementieren, Modelle für Kohärenz zu strukturieren, Quellcode zu lesen, um wichtige Funktionalitäten zu finden, und Geschäftslogik mithilfe eines Wrappers eines Drittanbieters zu implementieren. Halten Sie Ausschau nach Teil 2, in dem wir uns eingehend mit der Implementierung des CLI-Programms selbst befassen. Bleiben wir in der Zwischenzeit in Kontakt 👀 GitHub-Quellcode: https://github.com/elainechan01/trellocli