paint-brush
Cómo crear un programa CLI de Python para la gestión de tableros de Trello (Parte 1)por@elainechan01
2,031 lecturas
2,031 lecturas

Cómo crear un programa CLI de Python para la gestión de tableros de Trello (Parte 1)

por Elaine Yun Ru Chan19m2023/08/15
Read on Terminal Reader

Demasiado Largo; Para Leer

Como se indica en Wikipedia, "una interfaz de línea de comandos (CLI) es un medio para interactuar con un dispositivo o programa de computadora con comandos de un usuario o cliente, y respuestas del dispositivo o programa, en forma de líneas de texto". En otras palabras, un programa CLI es un programa en el que el usuario utiliza la línea de comandos para interactuar con el programa proporcionando instrucciones para ejecutar. Gran parte del software del día a día está empaquetado como un programa CLI. Tome el editor de texto vim, por ejemplo, una herramienta incluida con cualquier sistema UNIX que se puede activar simplemente ejecutando vim <FILE> en la terminal. Con respecto a la CLI de Google Cloud, profundicemos en la anatomía de un programa CLI.
featured image - Cómo crear un programa CLI de Python para la gestión de tableros de Trello (Parte 1)
Elaine Yun Ru Chan HackerNoon profile picture
0-item

Descargo de responsabilidad: este tutorial asume que los lectores tienen un conocimiento básico de Python, API, Git y Unit Tests.

Me encontré con varios software CLI con las animaciones más geniales, y me hizo preguntarme: ¿podría alguna vez actualizar mi proyecto escolar 'minimalista' de piedra, papel o tijera?


¡Hola, vamos a jugar! Elige tu luchador (piedra, papel, tijera): roca

¿Qué es un programa CLI?

Como se indica en Wikipedia, "una interfaz de línea de comandos (CLI) es un medio para interactuar con un dispositivo o programa de computadora con comandos de un usuario o cliente, y respuestas del dispositivo o programa, en forma de líneas de texto".


En otras palabras, un programa CLI es un programa en el que el usuario utiliza la línea de comandos para interactuar con el programa proporcionando instrucciones para ejecutar.


Gran parte del software del día a día está empaquetado como un programa CLI. Tome el editor de texto vim , por ejemplo, una herramienta incluida con cualquier sistema UNIX que se puede activar simplemente ejecutando vim <FILE> en la terminal.


Con respecto a la CLI de Google Cloud , profundicemos en la anatomía de un programa CLI.

Argumentos

Los argumentos (parámetros) son elementos de información proporcionados a un programa. A menudo se los denomina argumentos posicionales porque se identifican por su posición.


Por ejemplo, cuando queremos establecer la propiedad project en la sección central, ejecutamos gcloud config set project <PROJECT_ID>


En particular, podemos traducir esto en

Argumento

Contenido

argumento 0

gcloud

argumento 1

configuración

Comandos

Los comandos son una serie de argumentos que proporcionan instrucciones a la computadora.


Con base en el ejemplo anterior, configuramos la propiedad project en la sección central ejecutando gcloud config set project <PROJECT_ID>


En otras palabras, set es un comando.

Comandos opcionales

Por lo general, se requieren comandos, pero podemos hacer excepciones. Según el caso de uso del programa, podemos definir comandos opcionales.


Volviendo al comando gcloud config , como se indica en su documentación oficial, gcloud config es un grupo de comandos que le permite modificar propiedades. El uso es como tal:

 gcloud config GROUP | COMMAND [GCLOUD_WIDE_FLAG … ]

por lo que COMMAND puede ser set , list , etc. (Tenga en cuenta que GROUP es config )

Opciones

Las opciones son tipos documentados de parámetros que modifican el comportamiento de un comando. Son pares clave-valor que se indican con '-' o '--'.


Volviendo al uso del grupo de comandos gcloud config , las opciones, en este caso, son GCLOUD_WIDE_FLAG .


Por ejemplo, digamos que queremos mostrar el uso detallado y la descripción del comando, ejecutamos gcloud config set –help . En otras palabras, --help es la opción.


Otro ejemplo es cuando queremos establecer la propiedad zone en la sección de cómputo de un proyecto específico, ejecutamos gcloud config set compute <ZONE_NAME> –project=<PROJECT_ID> . En otras palabras, --project es una opción que contiene el valor <PROJECT_ID> .


También es importante tener en cuenta que sus posiciones generalmente no importan.

Opciones obligatorias

Las opciones, como su nombre, suelen ser opcionales, pero también se pueden adaptar para que sean obligatorias.


Por ejemplo, cuando queremos crear un clúster de dataproc, ejecutamos gcloud dataproc clusters create <CLUSTER_NAME> –region=<REGION> . Y como se indica en su documentación de uso:

 gcloud dataproc clusters create (CLUSTER: –region=REGION)

El indicador --region es obligatorio si no se ha configurado previamente.

Opciones cortas frente a opciones largas

Las opciones cortas comienzan con - seguidas de un solo carácter alfanumérico, mientras que las opciones largas comienzan con -- seguidas de varios caracteres. Piense en las opciones cortas como atajos cuando el usuario está seguro de lo que quiere, mientras que las opciones largas son más legibles.


¡Elegiste roca! La computadora ahora hará su selección.

¿Qué lograremos con este tutorial?

Así que mentí... No intentaremos actualizar el programa CLI básico de piedra, papel o tijera.

En su lugar, echemos un vistazo a un escenario del mundo real:

Esquema y objetivos

Su equipo usa Trello para realizar un seguimiento de los problemas y el progreso del proyecto. Su equipo está buscando una forma más simplificada de interactuar con el tablero, algo similar a crear un nuevo repositorio de GitHub a través de la terminal. El equipo recurrió a usted para crear un programa CLI con este requisito básico de poder agregar una nueva tarjeta a la columna 'To Do' del tablero.


Con base en el requisito mencionado, redactemos nuestro programa CLI definiendo sus requisitos:


Requerimientos funcionales

  • El usuario puede agregar una nueva tarjeta a una columna en el tablero
    • Entradas requeridas: columna, nombre de la tarjeta
    • Entradas opcionales: descripción de la tarjeta, etiquetas de la tarjeta (seleccione entre las existentes)

Requerimientos no funcionales

  • Programa para solicitar al usuario que proporcione acceso a la cuenta de Trello (autorización)
  • Programa para solicitar al usuario que establezca en qué placa de Trello trabajar (configuración)

Requisitos opcionales

  • El usuario puede agregar una nueva columna al tablero
  • El usuario puede agregar una nueva etiqueta al tablero
  • El usuario puede ver una vista simplificada/detallada de todas las columnas


En base a lo anterior, podemos formalizar los comandos y opciones de nuestro programa CLI como tal:

Vista de tabla detallada de la estructura de la CLI según los requisitos


PD No te preocupes por las dos últimas columnas, lo aprenderemos más tarde...


En cuanto a nuestra pila tecnológica, nos apegaremos a esto:


Pruebas unitarias

  • pytest
  • pytest-simulacro
  • cli-test-ayudantes

Trello

  • py-trello (envoltura de Python para el SDK de Trello)

CLI

  • tipeador
  • rico
  • menú-término-simple

Utilidades (Varios)

  • python-dotenv

Cronología

Abordaremos este proyecto en partes y aquí hay un fragmento de lo que puede esperar:


Parte 1

  • Implementación de la lógica de negocios py-trello

Parte 2

  • Implementación de lógica de negocios CLI
  • Distribuir el programa CLI como un paquete

parte 3

  • Implementación de requisitos funcionales opcionales
  • Actualización del paquete


¡La computadora eligió tijeras! A ver quien gana esta batalla...

Empecemos

Estructura de carpetas

El objetivo es distribuir el programa CLI como un paquete en PyPI . Por lo tanto, tal configuración es necesaria:

 trellocli/ __init__.py __main__.py models.py cli.py trelloservice.py tests/ test_cli.py test_trelloservice.py README.md pyproject.toml .env .gitignore


Aquí hay una inmersión profunda en cada archivo y/o directorio:

  • trellocli : actúa como el nombre del paquete que usarán los usuarios, por ejemplo, pip install trellocli
    • __init__.py : representa la raíz del paquete, conforma la carpeta como un paquete de Python
    • __main__.py : define el punto de entrada y permite a los usuarios ejecutar módulos sin especificar la ruta del archivo usando el indicador -m , por ejemplo, python -m <module_name> para reemplazar python -m <parent_folder>/<module_name>.py
    • models.py : almacena clases utilizadas globalmente, por ejemplo, modelos a los que se espera que se ajusten las respuestas de la API
    • cli.py : almacena la lógica comercial para los comandos y opciones de la CLI
    • trelloservice.py : almacena la lógica comercial para interactuar con py-trello
  • tests : almacena pruebas unitarias para el programa
    • test_cli.py : almacena pruebas unitarias para la implementación de CLI
    • test_trelloservice.py : almacena pruebas unitarias para la interacción con py-trello
  • README.md : almacena documentación para el programa
  • pyproject.toml : almacena las configuraciones y requisitos del paquete
  • .env : almacena variables de entorno
  • .gitignore : especifica los archivos que se ignorarán (no se rastrearán) durante el control de versiones


Para obtener una explicación más detallada de la publicación de paquetes de Python, aquí hay un excelente artículo para consultar: Cómo publicar un paquete de Python de código abierto en PyPI por Geir Arne Hjelle

Configuración

Antes de comenzar, veamos cómo configurar el paquete.


Comenzando con el archivo __init__.py en nuestro paquete, que sería donde se almacenan las constantes y variables del paquete, como el nombre y la versión de la aplicación. En nuestro caso, queremos inicializar lo siguiente:

  • nombre de la aplicación
  • versión
  • Constantes de ÉXITO y ERROR
 # 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" }


Pasando al archivo __main__.py , el flujo principal de su programa debe almacenarse aquí. En nuestro caso, almacenaremos el punto de entrada del programa CLI, asumiendo que habrá una función invocable en 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()


Ahora que se ha configurado el paquete, echemos un vistazo a la actualización de nuestro archivo README.md (documentación principal). No hay una estructura específica que debamos seguir, pero un buen LÉAME consistiría en lo siguiente:

  • Descripción general
  • Instalación y Requisitos
  • Primeros pasos y uso

Otra gran publicación para leer si desea profundizar más: Cómo escribir un buen LÉAME por merlos


Así es como me gustaría estructurar el LÉAME para este proyecto

 <!--- README.md --> # Overview # Getting Started # Usage # Architecture ## Data Flow ## Tech Stack # Running Tests # Next Steps # References


Dejemos el esqueleto como está por ahora; volveremos a esto más tarde.


Continuando, configuremos los metadatos de nuestro paquete según la documentación oficial.

 # 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" = ""


Observe cómo hay marcadores de posición que debe modificar, por ejemplo, su nombre de usuario, su nombre...


En otra nota, dejaremos la URL de la página de inicio vacía por ahora. Haremos los cambios después de haberlo publicado en GitHub. También dejaremos la porción de dependencias vacía por ahora y agregaremos a medida que avanzamos.


El siguiente en la lista sería nuestro archivo .env donde almacenamos nuestras variables de entorno, como claves y secretos de API. Es importante tener en cuenta que Git no debe realizar un seguimiento de este archivo, ya que contiene información confidencial.


En nuestro caso, almacenaremos aquí nuestras credenciales de Trello. Para crear un Power-Up en Trello, siga esta guía . Más específicamente, en función del uso de py-trello , ya que tenemos la intención de usar OAuth para nuestra aplicación, necesitaremos lo siguiente para interactuar con Trello:

  • Clave API (para nuestra aplicación)
  • API Secret (para nuestra aplicación)
  • Token (token del usuario para otorgar acceso a sus datos)


Una vez que haya recuperado su clave API y su secreto, guárdelos en el archivo .env como tal

 # .env TRELLO_API_KEY=<your_api_key> TRELLO_API_SECRET=<your_api_secret>


Por último, pero no menos importante, usemos la plantilla Python .gitignore que se puede encontrar aquí . Tenga en cuenta que esto es crucial para garantizar que nunca se rastree nuestro archivo .env : si en algún momento se rastreó nuestro archivo .env , incluso si eliminamos el archivo en pasos posteriores, el daño ya está hecho y los actores malintencionados pueden rastrear el archivo anterior. parches para información sensible.


Ahora que la configuración está completa, subamos nuestros cambios a GitHub. Según los metadatos especificados en pyproject.toml , recuerde actualizar su LICENCIA y la URL de la página de inicio en consecuencia. Para referencia sobre cómo escribir mejores confirmaciones: Write Better Commits, Build Better Projects por Victoria Dye


Otros pasos destacados:

Pruebas unitarias

Antes de comenzar a escribir nuestras pruebas, es importante tener en cuenta que debido a que estamos trabajando con una API, implementaremos pruebas simuladas para poder probar nuestro programa sin el riesgo de tiempo de inactividad de la API. Aquí hay otro excelente artículo sobre pruebas simuladas de Real Python: Simulación de API externas en Python


Según los requisitos funcionales, nuestra principal preocupación es permitir que los usuarios agreguen una nueva tarjeta. Haciendo referencia al método en py-trello : add_card . Para poder hacerlo, debemos llamar al método add_card de la clase List , del cual se puede recuperar de la función get_list de la clase Board , del cual se puede recuperar…


Entiendes la esencia: necesitaremos muchos métodos de ayuda para llegar a nuestro destino final, digámoslo en palabras:

  • Prueba para recuperar el token del cliente
  • Prueba para recuperar tableros
  • Prueba para recuperar un tablero
  • Prueba para recuperar listas del tablero
  • Prueba para recuperar una lista
  • Prueba para recuperar etiquetas del tablero
  • Prueba para recuperar una etiqueta
  • Prueba para agregar tarjeta
  • Prueba para agregar etiqueta a la tarjeta


También es importante tener en cuenta que al escribir pruebas unitarias, queremos que nuestras pruebas sean lo más extensas posible. ¿Maneja bien los errores? ¿Cubre todos los aspectos de nuestro programa?


Sin embargo, solo para el propósito de este tutorial, simplificaremos las cosas al verificar solo los casos de éxito.


Antes de profundizar en el código, modifiquemos nuestro archivo pyproject.toml para incluir las dependencias necesarias para escribir/ejecutar pruebas unitarias.

 # pyproject.toml [project] dependencies = [ "pytest==7.4.0", "pytest-mock==3.11.1" ]


A continuación, activemos nuestro virtualenv y ejecutemos pip install . para instalar las dependencias.


Una vez hecho esto, escribamos finalmente algunas pruebas. En general, nuestras pruebas deben incluir una respuesta simulada para ser devuelta, un parche para la función que intentamos probar arreglando el valor de retorno con la respuesta simulada y, finalmente, una llamada a la función. Una prueba de muestra para recuperar los tokens de acceso del usuario sería la siguiente:

 # 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


Observe en mi código de muestra que GetOAuthTokenResponse es un modelo que aún no se ha configurado en models.py . Proporciona estructura para escribir código más limpio, lo veremos en acción más adelante.


Para ejecutar nuestras pruebas, simplemente ejecute python -m pytest . Observe cómo fallarán nuestras pruebas, pero está bien, al final funcionará.


Rincón del desafío 💡 ¿Puedes intentar escribir más pruebas por tu cuenta? Siéntase libre de consultareste parche para ver cómo se ven mis pruebas


Por ahora, construyamos nuestro trelloservice . Comenzando con la adición de una nueva dependencia, ese es el contenedor py-trello .

 # pyproject.toml dependencies = [ "pytest==7.4.0", "pytest-mock==3.11.1", "py-trello==0.19.0" ]


Una vez más, ejecute pip install . para instalar las dependencias.

Modelos

Ahora, comencemos por construir nuestros modelos, para regular las respuestas que esperamos en trelloservice . Para esta parte, es mejor consultar nuestras pruebas unitarias y el código fuente de py-trello para comprender el tipo de valor de retorno que podemos esperar.


Por ejemplo, digamos que queremos recuperar el token de acceso del usuario, haciendo referencia a la función create_oauth_token de py-trello ( código fuente ), sabemos que esperamos que el valor de retorno sea algo como esto

 # trellocli/models.py # module imports # dependencies imports # misc imports from typing import NamedTuple class GetOAuthTokenResponse(NamedTuple): token: str token_secret: str status_code: int


Por otro lado, tenga cuidado con las convenciones de nomenclatura conflictivas. Por ejemplo, el módulo py-trello tiene una clase llamada List . Una solución para esto sería proporcionar un alias durante la importación.

 # trellocli/models.py # dependencies imports from trello import List as Trellolist


No dude en aprovechar también esta oportunidad para adaptar los modelos a las necesidades de su programa. Por ejemplo, digamos que solo necesita un atributo del valor devuelto, podría refactorizar su modelo para esperar extraer dicho valor del valor devuelto en lugar de almacenarlo como un todo.

 # trellocli/models.py class GetBoardName(NamedTuple): """Model to store board id Attributes id (str): Extracted board id from Board value type """ id: str


Rincón del desafío 💡 ¿Puedes intentar escribir más modelos por tu cuenta? Siéntase libre de consultareste parche para ver cómo se ven mis modelos

Lógica de negocios

Configuración

Modelos abajo, comencemos oficialmente a codificar el trelloservice . Nuevamente, debemos referirnos a las pruebas unitarias que creamos; digamos que la lista actual de pruebas no brinda una cobertura completa para el servicio, siempre regrese y agregue más pruebas cuando sea necesario.


Como de costumbre, incluya todas las declaraciones de importación hacia la parte superior. Luego cree la clase TrelloService y los métodos de marcador de posición como se esperaba. La idea es que inicialicemos una instancia compartida del servicio en cli.py y llamemos a sus métodos en consecuencia. Además, nuestro objetivo es la escalabilidad, por lo tanto, la necesidad de una amplia cobertura.

 # 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 observe cómo esta vez cuando ejecutamos nuestras pruebas, nuestras pruebas pasarán. De hecho, esto nos ayudará a asegurarnos de mantenernos en el camino correcto. El flujo de trabajo debe ser para ampliar nuestras funciones, ejecutar nuestras pruebas, verificar si pasa/falla y refactorizar en consecuencia.

Autorización e inicialización de TrelloClient

Comencemos con la función __init__ . La idea es llamar a la función get_user_oauth_token aquí e inicializar TrelloClient . Nuevamente, enfatizando la necesidad de almacenar dicha información confidencial solo en el archivo .env , usaremos la dependencia python-dotenv para recuperar información confidencial. Después de modificar nuestro archivo pyproject.toml en consecuencia, comencemos a implementar los pasos de autorización.

 # 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 )


En esta implementación, creamos un método auxiliar para manejar cualquier error previsible, por ejemplo, cuando el usuario hace clic en Deny durante la autorización. Además, está configurado para solicitar de forma recursiva la autorización del usuario hasta que se devuelva una respuesta válida, porque el hecho es que no podemos continuar a menos que el usuario autorice nuestra aplicación para acceder a los datos de su cuenta.


Rincón del desafío 💡 ¿Aviso TRELLO_AUTHORIZATION_ERROR ? ¿Puedes declarar este error como una constante del paquete? Consulte Configuración para obtener más información.

Funciones auxiliares

Ahora que la parte de la autorización está lista, pasemos a las funciones auxiliares, comenzando con la recuperación de los tableros de Trello del usuario.

 # 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 )


En cuanto a la recuperación de las listas (columnas), tendremos que revisar la clase Board de py-trello , o en otras palabras, debemos aceptar un nuevo parámetro del tipo Board value.

 # 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 )


Rincón del desafío 💡 ¿Podrías implementar la función get_all_labels y get_label por tu cuenta? Revisar la clase Board de py-trello . Siéntase libre de consultareste parche para ver cómo se ve mi implementación

Función para agregar una nueva tarjeta

Por último, pero no menos importante, finalmente logramos lo que habíamos estado buscando todo este tiempo: agregar una nueva tarjeta. Tenga en cuenta que no usaremos todas las funciones declaradas anteriormente aquí: el objetivo de las funciones auxiliares es aumentar la escalabilidad.

 # 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 )


🎉 Ahora que está hecho y desempolvado, recuerde actualizar su README en consecuencia y envíe su código a GitHub.


¡Felicidades! Ganaste. ¿Reproducir de nuevo (sí/no)?

Envolver

Gracias por su paciencia :) A través de este tutorial, aprendió con éxito a implementar la simulación al escribir pruebas unitarias, estructurar modelos para la cohesión, leer el código fuente para encontrar funcionalidades clave e implementar la lógica comercial utilizando un contenedor de terceros.


Esté atento a la Parte 2, donde profundizaremos en la implementación del programa CLI en sí.


Mientras tanto, sigamos en contacto 👀