Tuyên bố miễn trừ trách nhiệm: Hướng dẫn này giả định rằng người đọc đã có kiến thức cơ bản về Python, API, Git và Bài kiểm tra đơn vị.
Tôi đã xem qua nhiều phần mềm CLI khác nhau với những hình ảnh động thú vị nhất và điều đó khiến tôi băn khoăn - liệu tôi có thể nâng cấp dự án trường học oẳn tù tì 'tối giản' của mình không?
Hi, chúng ta hãy chơi! Chọn máy bay chiến đấu của bạn (oẳn tù tì, kéo): đá
Như đã nêu trên Wikipedia, “Giao diện dòng lệnh (CLI) là phương tiện tương tác với thiết bị hoặc chương trình máy tính bằng các lệnh từ người dùng hoặc máy khách và phản hồi từ thiết bị hoặc chương trình, dưới dạng các dòng văn bản.”
Nói cách khác, chương trình CLI là chương trình mà người dùng sử dụng dòng lệnh để tương tác với chương trình bằng cách cung cấp hướng dẫn để thực thi.
Nhiều phần mềm hàng ngày được gói dưới dạng chương trình CLI. Lấy ví dụ về trình soạn thảo văn bản vim
- một công cụ đi kèm với bất kỳ hệ thống UNIX nào có thể được kích hoạt đơn giản bằng cách chạy vim <FILE>
trong thiết bị đầu cuối.
Liên quan đến Google Cloud CLI , hãy đi sâu vào giải phẫu của một chương trình CLI.
Đối số (Tham số) là các mục thông tin được cung cấp cho một chương trình. Nó thường được gọi là đối số vị trí vì chúng được xác định bởi vị trí của chúng.
Ví dụ: khi chúng tôi muốn đặt thuộc tính project
trong phần cốt lõi, chúng tôi chạy gcloud config set project <PROJECT_ID>
Đáng chú ý, chúng ta có thể dịch điều này thành
Lý lẽ | Nội dung |
---|---|
Đối số 0 | gcloud |
Đối số 1 | cấu hình |
… | … |
Các lệnh là một mảng các đối số cung cấp hướng dẫn cho máy tính.
Dựa trên ví dụ trước, chúng tôi đặt thuộc tính project
trong phần cốt lõi bằng cách chạy gcloud config set project <PROJECT_ID>
Nói cách khác, set
là một lệnh.
Thông thường, các lệnh là bắt buộc nhưng chúng ta có thể tạo ra các ngoại lệ. Dựa trên trường hợp sử dụng của chương trình, chúng ta có thể xác định các lệnh tùy chọn.
Quay lại lệnh gcloud config
, như đã nêu trong tài liệu chính thức của họ, gcloud config
là một nhóm lệnh cho phép bạn sửa đổi các thuộc tính. Việc sử dụng là như vậy:
gcloud config GROUP | COMMAND [GCLOUD_WIDE_FLAG … ]
theo đó LỆNH có thể là set
, list
, v.v. (Lưu ý rằng GROUP là config
)
Các tùy chọn là các loại tham số được ghi lại để sửa đổi hành vi của một lệnh. Chúng là các cặp khóa-giá trị được biểu thị bằng '-' hoặc '--'.
Quay lại việc sử dụng nhóm lệnh gcloud config
, (các) tùy chọn, trong trường hợp này, là GCLOUD_WIDE_FLAG
.
Ví dụ: giả sử rằng chúng tôi muốn hiển thị cách sử dụng và mô tả chi tiết của lệnh, chúng tôi chạy gcloud config set –help
. Nói cách khác, --help
là tùy chọn.
Một ví dụ khác là khi chúng tôi muốn đặt thuộc tính vùng trong phần tính toán của một dự án cụ thể, chúng tôi chạy gcloud config set compute <ZONE_NAME> –project=<PROJECT_ID>
. Nói cách khác, --project
là một tùy chọn chứa giá trị <PROJECT_ID>
.
Cũng cần lưu ý rằng vị trí của họ thường không quan trọng.
Các tùy chọn, giống như tên của nó, thường là tùy chọn, nhưng cũng có thể được điều chỉnh để trở thành bắt buộc.
Ví dụ: khi chúng tôi muốn tạo một cụm dataproc, chúng tôi chạy gcloud dataproc clusters create <CLUSTER_NAME> –region=<REGION>
. Và như đã nêu trong tài liệu sử dụng của họ:
gcloud dataproc clusters create (CLUSTER: –region=REGION)
Cờ --region
là bắt buộc nếu nó chưa được định cấu hình trước đó.
Các tùy chọn ngắn bắt đầu bằng -
theo sau là một ký tự chữ và số, trong khi các tùy chọn dài bắt đầu bằng --
theo sau là nhiều ký tự. Hãy coi các tùy chọn ngắn là lối tắt khi người dùng chắc chắn về những gì họ muốn trong khi các tùy chọn dài dễ đọc hơn.
Bạn đã chọn đá! Bây giờ máy tính sẽ thực hiện lựa chọn của nó.
Vì vậy, tôi đã nói dối… Chúng tôi sẽ không cố gắng nâng cấp chương trình CLI oẳn tù tì.
Thay vào đó, chúng ta hãy xem xét một kịch bản trong thế giới thực:
Nhóm của bạn sử dụng Trello để theo dõi các vấn đề và tiến độ của dự án. Nhóm của bạn đang tìm kiếm một cách đơn giản hơn để tương tác với bảng - tương tự như việc tạo kho lưu trữ GitHub mới thông qua thiết bị đầu cuối. Nhóm đã nhờ bạn tạo một chương trình CLI với yêu cầu cơ bản này là có thể thêm thẻ mới vào cột 'Việc cần làm' trên bảng.
Dựa trên yêu cầu đã đề cập, hãy phác thảo chương trình CLI của chúng tôi bằng cách xác định các yêu cầu của nó:
Yêu cầu chức năng
Những yêu cầu phi lý
Yêu cầu tùy chọn
Dựa trên những điều trên, chúng ta có thể chính thức hóa các lệnh và tùy chọn của chương trình CLI của mình như sau:
Ps Đừng lo lắng về hai cột cuối cùng, chúng ta sẽ tìm hiểu về nó sau…
Đối với ngăn xếp công nghệ của chúng tôi, chúng tôi sẽ gắn bó với điều này:
bài kiểm tra đơn vị
Trello
CLI
Tiện ích (Khác)
Chúng tôi sẽ giải quyết dự án này theo từng phần và đây là một đoạn nhỏ về những gì bạn có thể mong đợi:
Phần 1
py-trello
Phần 2
Phần 3
Máy tính đã chọn kéo! Hãy xem ai là người chiến thắng trong trận chiến này…
Mục tiêu là phân phối chương trình CLI dưới dạng gói trên PyPI . Vì vậy, một thiết lập như vậy là cần thiết:
trellocli/ __init__.py __main__.py models.py cli.py trelloservice.py tests/ test_cli.py test_trelloservice.py README.md pyproject.toml .env .gitignore
Đây là phần đi sâu vào từng tệp và/hoặc thư mục:
trellocli
: đóng vai trò là tên gói được người dùng sử dụng, ví dụ: pip install trellocli
__init__.py
: đại diện cho thư mục gốc của gói, tuân thủ thư mục dưới dạng gói Python__main__.py
: xác định điểm vào và cho phép người dùng chạy các mô-đun mà không cần chỉ định đường dẫn tệp bằng cách sử dụng cờ -m
, ví dụ: python -m <module_name>
để thay thế python -m <parent_folder>/<module_name>.py
models.py
: lưu trữ các lớp được sử dụng trên toàn cầu, ví dụ: các mô hình mà các phản hồi API dự kiến sẽ tuân theocli.py
: lưu trữ logic nghiệp vụ cho các lệnh và tùy chọn CLItrelloservice.py
: lưu trữ logic nghiệp vụ để tương tác với py-trello
tests
: lưu trữ các bài kiểm tra đơn vị cho chương trìnhtest_cli.py
: lưu trữ các bài kiểm tra đơn vị để triển khai CLItest_trelloservice.py
: lưu trữ các bài kiểm tra đơn vị để tương tác với py-trello
README.md
: lưu trữ tài liệu cho chương trìnhpyproject.toml
: lưu trữ các cấu hình và yêu cầu của gói.env
: lưu trữ các biến môi trường.gitignore
: chỉ định các tệp bị bỏ qua (không được theo dõi) trong quá trình kiểm soát phiên bản
Để có giải thích chi tiết hơn về việc xuất bản các gói Python, đây là một bài viết hay để xem: Cách xuất bản Gói Python mã nguồn mở lên PyPI của Geir Arne Hjelle
Trước khi bắt đầu, chúng ta hãy chạm vào cơ sở thiết lập gói.
Bắt đầu với tệp __init__.py
trong gói của chúng tôi, đây sẽ là nơi lưu trữ các biến và hằng số của gói, chẳng hạn như tên và phiên bản ứng dụng. Trong trường hợp của chúng tôi, chúng tôi muốn khởi tạo như sau:
# 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" }
Chuyển sang tệp __main__.py
, luồng chính của chương trình của bạn sẽ được lưu trữ tại đây. Trong trường hợp của chúng tôi, chúng tôi sẽ lưu trữ điểm vào chương trình CLI, giả sử rằng sẽ có một chức năng có thể gọi được trong 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()
Bây giờ gói đã được thiết lập, hãy xem cập nhật tệp README.md
của chúng tôi (tài liệu chính). Không có một cấu trúc cụ thể nào mà chúng ta phải tuân theo, nhưng một README tốt sẽ bao gồm những phần sau:
Một bài đăng tuyệt vời khác để đọc nếu bạn muốn tìm hiểu sâu hơn: Cách viết một README hay của merlos
Đây là cách tôi muốn cấu trúc README cho dự án này
<!--- README.md --> # Overview # Getting Started # Usage # Architecture ## Data Flow ## Tech Stack # Running Tests # Next Steps # References
Bây giờ hãy để nguyên bộ xương - chúng ta sẽ quay lại vấn đề này sau.
Tiếp tục, hãy định cấu hình siêu dữ liệu của gói dựa trên tài liệu chính thức
# 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" = ""
Lưu ý cách có các trình giữ chỗ mà bạn phải sửa đổi, ví dụ: tên người dùng, tên của bạn…
Một lưu ý khác, hiện tại chúng tôi sẽ để trống URL trang chủ. Chúng tôi sẽ thực hiện các thay đổi sau khi xuất bản nó lên GitHub. Hiện tại, chúng tôi cũng sẽ để trống phần phụ thuộc và thêm vào khi chúng tôi thực hiện.
Tiếp theo trong danh sách sẽ là tệp .env
của chúng tôi, nơi chúng tôi lưu trữ các biến môi trường của mình, chẳng hạn như khóa và bí mật API. Điều quan trọng cần lưu ý là Git không nên theo dõi tệp này vì nó chứa thông tin nhạy cảm.
Trong trường hợp của chúng tôi, chúng tôi sẽ lưu trữ thông tin đăng nhập Trello của mình tại đây. Để tạo Power-Up trong Trello, hãy làm theo hướng dẫn này . Cụ thể hơn, dựa trên việc sử dụng py-trello
, vì chúng tôi dự định sử dụng OAuth cho ứng dụng của mình, chúng tôi sẽ cần những thứ sau để tương tác với Trello:
Khi bạn đã truy xuất Khóa API và Bí mật của mình, hãy lưu trữ chúng trong tệp .env
như vậy
# .env TRELLO_API_KEY=<your_api_key> TRELLO_API_SECRET=<your_api_secret>
Cuối cùng nhưng không kém phần quan trọng, hãy sử dụng mẫu Python .gitignore
có thể tìm thấy tại đây . Lưu ý rằng điều này rất quan trọng để đảm bảo rằng tệp .env
của chúng tôi không bao giờ bị theo dõi - nếu tại một thời điểm nào đó, tệp .env
của chúng tôi bị theo dõi, ngay cả khi chúng tôi đã xóa tệp ở các bước sau, thì thiệt hại vẫn được thực hiện và các tác nhân độc hại có thể lần theo dấu vết trước đó bản vá cho thông tin nhạy cảm.
Bây giờ, quá trình thiết lập đã hoàn tất, hãy đẩy các thay đổi của chúng tôi lên GitHub. Tùy thuộc vào siêu dữ liệu được chỉ định trong pyproject.toml
, hãy nhớ cập nhật GIẤY PHÉP và URL trang chủ của bạn cho phù hợp. Để tham khảo về cách viết các cam kết tốt hơn: Viết các cam kết tốt hơn, Xây dựng các dự án tốt hơn của Victoria Dye
Các bước đáng chú ý khác:
Trước khi chúng tôi bắt đầu viết các bài kiểm tra của mình, điều quan trọng cần lưu ý là vì chúng tôi đang làm việc với một API nên chúng tôi sẽ triển khai các bài kiểm tra giả để có thể kiểm tra chương trình của mình mà không gặp rủi ro về thời gian ngừng hoạt động của API. Đây là một bài viết tuyệt vời khác về thử nghiệm mô phỏng bằng Python thực: Mocking APIs bên ngoài trong Python
Dựa trên các yêu cầu chức năng, mối quan tâm chính của chúng tôi là cho phép người dùng thêm thẻ mới. Tham khảo phương thức trong py-trello
: add_card . Để có thể làm như vậy, chúng ta phải gọi phương thức add_card
từ lớp List
, phương thức này có thể được truy xuất từ hàm get_list
từ lớp Board
, phương thức này có thể được truy xuất…
Bạn nắm được ý chính - chúng ta sẽ cần rất nhiều phương pháp trợ giúp để đến đích cuối cùng, hãy diễn đạt thành lời:
Cũng cần lưu ý rằng khi viết bài kiểm tra đơn vị, chúng tôi muốn bài kiểm tra của mình càng rộng càng tốt - Nó có xử lý lỗi tốt không? Liệu nó bao gồm mọi khía cạnh của chương trình của chúng tôi?
Tuy nhiên, chỉ với mục đích của hướng dẫn này, chúng tôi sẽ đơn giản hóa mọi thứ bằng cách chỉ kiểm tra các trường hợp thành công.
Trước khi đi sâu vào mã, hãy sửa đổi tệp pyproject.toml
của chúng tôi để bao gồm các phụ thuộc cần thiết cho việc viết/chạy thử nghiệm đơn vị.
# pyproject.toml [project] dependencies = [ "pytest==7.4.0", "pytest-mock==3.11.1" ]
Tiếp theo, hãy kích hoạt virtualenv của chúng tôi và chạy pip install .
để cài đặt các phụ thuộc.
Khi đã xong, cuối cùng chúng ta hãy viết một số bài kiểm tra. Nói chung, các thử nghiệm của chúng tôi phải bao gồm một phản hồi giả được trả về, một bản vá cho chức năng mà chúng tôi đang thử kiểm tra bằng cách sửa giá trị trả về bằng phản hồi giả và cuối cùng là một lệnh gọi đến hàm. Thử nghiệm mẫu để truy xuất mã thông báo truy cập của người dùng như sau:
# 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
Lưu ý trong mã mẫu của tôi rằng GetOAuthTokenResponse
là một mô hình chưa được đặt trong models.py
. Nó cung cấp cấu trúc để viết mã sạch hơn, chúng ta sẽ thấy nó hoạt động sau.
Để chạy thử nghiệm của chúng tôi, chỉ cần chạy python -m pytest
. Lưu ý rằng các bài kiểm tra của chúng tôi sẽ thất bại như thế nào, nhưng không sao - cuối cùng nó sẽ ổn thôi.
Góc thử thách 💡 Bạn thử tự viết thêm test xem sao? Vui lòng tham khảobản vá này để xem thử nghiệm của tôi trông như thế nào
Bây giờ, hãy xây dựng trelloservice
của chúng ta. Bắt đầu với việc thêm một phụ thuộc mới, đó là trình bao bọc py-trello
.
# pyproject.toml dependencies = [ "pytest==7.4.0", "pytest-mock==3.11.1", "py-trello==0.19.0" ]
Một lần nữa, chạy pip install .
để cài đặt các phụ thuộc.
Bây giờ, hãy bắt đầu bằng cách xây dựng các mô hình của chúng tôi - để điều chỉnh các phản hồi mà chúng tôi mong đợi trong trelloservice
. Đối với phần này, tốt nhất bạn nên tham khảo các bài kiểm tra đơn vị của chúng tôi và mã nguồn py-trello
để hiểu loại giá trị trả về mà chúng tôi có thể mong đợi.
Ví dụ: giả sử rằng chúng tôi muốn truy xuất mã thông báo truy cập của người dùng, tham khảo hàm create_oauth_token
của py-trello
( mã nguồn ), chúng tôi biết giá trị trả về sẽ giống như thế này
# trellocli/models.py # module imports # dependencies imports # misc imports from typing import NamedTuple class GetOAuthTokenResponse(NamedTuple): token: str token_secret: str status_code: int
Mặt khác, hãy lưu ý các quy ước đặt tên mâu thuẫn. Ví dụ: mô-đun py-trello
có một lớp có tên List
. Giải pháp thay thế cho vấn đề này là cung cấp bí danh trong quá trình nhập.
# trellocli/models.py # dependencies imports from trello import List as Trellolist
Vui lòng sử dụng cơ hội này để điều chỉnh các mô hình theo nhu cầu của chương trình của bạn. Ví dụ: giả sử bạn chỉ yêu cầu một thuộc tính từ giá trị trả về, bạn có thể cấu trúc lại mô hình của mình để trích xuất giá trị đã nói từ giá trị trả về thay vì lưu trữ toàn bộ.
# trellocli/models.py class GetBoardName(NamedTuple): """Model to store board id Attributes id (str): Extracted board id from Board value type """ id: str
Góc thử thách 💡 Bạn thử tự viết thêm các mẫu nữa xem sao? Vui lòng tham khảobản vá này để xem mô hình của tôi trông như thế nào
Mô hình ngừng hoạt động, hãy chính thức bắt đầu mã hóa trelloservice
. Một lần nữa, chúng ta nên tham khảo các bài kiểm tra đơn vị mà chúng tôi đã tạo - giả sử rằng danh sách các bài kiểm tra hiện tại không cung cấp phạm vi bảo hiểm đầy đủ cho dịch vụ, luôn quay lại và thêm các bài kiểm tra khác khi cần.
Theo thông lệ, hãy đưa tất cả các câu lệnh nhập vào đầu trang. Sau đó, tạo lớp TrelloService
và các phương thức giữ chỗ như mong đợi. Ý tưởng là chúng ta sẽ khởi tạo một phiên bản dùng chung của dịch vụ trong cli.py
và gọi các phương thức của nó tương ứng. Hơn nữa, chúng tôi đang hướng tới khả năng mở rộng, do đó cần có phạm vi bảo hiểm rộng rãi.
# 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
Xin lưu ý rằng lần này khi chúng tôi chạy thử nghiệm, các thử nghiệm của chúng tôi sẽ vượt qua như thế nào. Trên thực tế, điều này sẽ giúp chúng tôi đảm bảo rằng chúng tôi đi đúng hướng. Quy trình làm việc phải là mở rộng các chức năng của chúng tôi, chạy thử nghiệm, kiểm tra đạt/không đạt và cấu trúc lại cho phù hợp.
Hãy bắt đầu với hàm __init__
. Ý tưởng là gọi hàm get_user_oauth_token
tại đây và khởi tạo TrelloClient
. Một lần nữa, nhấn mạnh nhu cầu chỉ lưu trữ thông tin nhạy cảm như vậy trong tệp .env
, chúng tôi sẽ sử dụng phần phụ thuộc python-dotenv
để truy xuất thông tin nhạy cảm. Sau khi sửa đổi tệp pyproject.toml
của chúng tôi cho phù hợp, hãy bắt đầu thực hiện các bước ủy quyề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 )
Trong quá trình triển khai này, chúng tôi đã tạo một phương thức trợ giúp để xử lý mọi lỗi có thể thấy trước, ví dụ: khi người dùng nhấp vào Deny
trong khi ủy quyền. Hơn nữa, nó được thiết lập để yêu cầu ủy quyền của người dùng một cách đệ quy cho đến khi trả về phản hồi hợp lệ, vì thực tế là chúng tôi không thể tiếp tục trừ khi người dùng cho phép ứng dụng của chúng tôi truy cập dữ liệu tài khoản của họ.
Góc thử thách 💡 Thông báo TRELLO_AUTHORIZATION_ERROR
? Bạn có thể khai báo lỗi này là hằng số gói không? Tham khảo Thiết lập để biết thêm thông tin
Giờ thì phần ủy quyền đã hoàn tất, hãy chuyển sang các chức năng của trình trợ giúp, bắt đầu bằng việc truy xuất bảng Trello của người dùng.
# 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 )
Đối với việc truy xuất các danh sách (cột), chúng ta sẽ phải kiểm tra lớp Board
của py-trello
, hay nói cách khác, chúng ta phải chấp nhận một tham số mới của loại giá trị 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 )
Góc thử thách 💡 Bạn có thể tự triển khai hàm get_all_labels
và get_label
không? Sửa lại lớp Board
của py-trello
. Vui lòng tham khảobản vá này để xem triển khai của tôi trông như thế nào
Cuối cùng nhưng không kém phần quan trọng, cuối cùng chúng tôi đã đạt được mục tiêu mà chúng tôi đã hướng tới trong suốt thời gian qua - thêm một thẻ mới. Hãy nhớ rằng chúng ta sẽ không sử dụng tất cả các hàm đã khai báo trước đó ở đây - mục tiêu của các hàm trợ giúp là tăng khả năng mở rộng.
# 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 )
🎉 Giờ thì mọi việc đã hoàn tất, hãy nhớ cập nhật README của bạn cho phù hợp và đẩy mã của bạn lên GitHub.
Chúc mừng! Bạn đã thắng. Chơi lại (y/N)?
Cảm ơn bạn đã đồng hành cùng tôi :) Thông qua hướng dẫn này, bạn đã học thành công cách triển khai chế độ mô phỏng khi viết bài kiểm tra đơn vị, mô hình cấu trúc để tạo sự gắn kết, đọc qua mã nguồn để tìm các chức năng chính và triển khai logic nghiệp vụ bằng cách sử dụng trình bao bọc của bên thứ ba.
Hãy theo dõi Phần 2, nơi chúng ta sẽ đi sâu vào việc triển khai chính chương trình CLI.
Trong thời gian chờ đợi, chúng ta hãy giữ liên lạc nhé 👀
Mã nguồn GitHub: https://github.com/elainechan01/trellocli