From 04903bf4cf1b430425ac1d4244ea4b7c1b608649 Mon Sep 17 00:00:00 2001 From: Luckery <1196623300@qq.com> Date: Thu, 16 Jan 2025 00:50:42 +0800 Subject: [PATCH 1/4] fix: Refactor test cases --- src/casvisor/base.py | 19 ++-- src/casvisor/main.py | 18 +-- src/casvisor/record.py | 80 ++++++------- src/tests/test_base.py | 57 ++++------ src/tests/test_main.py | 35 +++--- src/tests/test_record.py | 237 ++++++++++++++------------------------- src/tests/test_util.py | 29 +++++ 7 files changed, 214 insertions(+), 261 deletions(-) create mode 100644 src/tests/test_util.py diff --git a/src/casvisor/base.py b/src/casvisor/base.py index 259cdb2..a6c1920 100644 --- a/src/casvisor/base.py +++ b/src/casvisor/base.py @@ -43,9 +43,9 @@ def set_http_client(http_client: HttpClient): class BaseClient: - def __init__(self, client_id: str, client_secret: str, endpoint: str): - self.client_id = client_id - self.client_secret = client_secret + def __init__(self, clientId: str, clientSecret: str, endpoint: str): + self.clientId = clientId + self.clientSecret = clientSecret self.endpoint = endpoint def do_get_response(self, url: str) -> Response: @@ -89,16 +89,15 @@ def do_post( def do_post_bytes_raw(self, url: str, content_type: str, body: bytes) -> bytes: if not content_type: content_type = "text/plain;charset=UTF-8" - headers = { - "Content-Type": content_type, - "Authorization": f"Basic {self.client_id}:{self.client_secret}", - } - resp = client.post(url, headers=headers, data=body) + + headers = {"Content-Type": content_type} + resp = client.post( + url, headers=headers, data=body, auth=(self.clientId, self.clientSecret) + ) return resp.content def do_get_bytes_raw_without_check(self, url: str) -> bytes: - headers = {"Authorization": f"Basic {self.client_id}:{self.client_secret}"} - resp = client.get(url, headers=headers) + resp = client.get(url, auth=(self.clientId, self.clientSecret)) return resp.content def prepare_body( diff --git a/src/casvisor/main.py b/src/casvisor/main.py index ffdb344..df6585d 100644 --- a/src/casvisor/main.py +++ b/src/casvisor/main.py @@ -20,16 +20,16 @@ class CasvisorSDK(_RecordSDK): def __init__( self, endpoint: str, - client_id: str, - client_secret: str, - organization_name: str, - application_name: str, + clientId: str, + clientSecret: str, + organizationName: str, + applicationName: str, ): self.endpoint = endpoint - self.client_id = client_id - self.client_secret = client_secret - self.organization_name = organization_name - self.application_name = application_name + self.clientId = clientId + self.clientSecret = clientSecret + self.organizationName = organizationName + self.applicationName = applicationName # Initialize the base client - self.base_client = BaseClient(client_id, client_secret, endpoint) + self.baseClient = BaseClient(clientId, clientSecret, endpoint) diff --git a/src/casvisor/record.py b/src/casvisor/record.py index 8a40e3c..a4f974f 100644 --- a/src/casvisor/record.py +++ b/src/casvisor/record.py @@ -14,46 +14,46 @@ import json from typing import Dict, List, Optional, Tuple -from .base import BaseClient +from .base import BaseClient, Response from . import util class Record: def __init__( self, - id: int, - owner: str, - name: str, - created_time: str, - organization: str, - client_ip: str, - user: str, - method: str, - request_uri: str, - action: str, - language: str, - object: str, - response: str, - provider: str, - block: str, - is_triggered: bool, + createdTime: Optional[str] = None, + organization: Optional[str] = None, + clientIp: Optional[str] = None, + user: Optional[str] = None, + method: Optional[str] = None, + requestUri: Optional[str] = None, + action: Optional[str] = None, + language: Optional[str] = None, + object: Optional[str] = None, + response: Optional[str] = None, + provider: Optional[str] = None, + block: Optional[str] = None, + isTriggered: Optional[bool] = None, + id: Optional[int] = None, + owner: Optional[str] = None, + name: Optional[str] = None, ): self.id = id self.owner = owner self.name = name - self.created_time = created_time + self.createdTime = createdTime self.organization = organization - self.client_ip = client_ip + self.clientIp = clientIp self.user = user self.method = method - self.request_uri = request_uri + self.requestUri = requestUri self.action = action self.language = language self.object = object self.response = response self.provider = provider self.block = block - self.is_triggered = is_triggered + self.isTriggered = isTriggered def to_dict(self) -> Dict: return self.__dict__ @@ -64,30 +64,30 @@ def from_dict(cls, data: Dict) -> "Record": class _RecordSDK: - def __init__(self, base_client: BaseClient, organization_name: str): - self.base_client = base_client - self.organization_name = organization_name + def __init__(self, base_client: BaseClient, organizationName: str): + self.baseClient = base_client + self.organizationName = organizationName def get_records(self) -> List[Record]: - query_map = {"owner": self.organization_name} - url = util.get_url(self.base_client.endpoint, "get-records", query_map) - bytes = self.base_client.do_get_bytes(url) + query_map = {"owner": self.organizationName} + url = util.get_url(self.baseClient.endpoint, "get-records", query_map) + bytes = self.baseClient.do_get_bytes(url) return [Record.from_dict(record) for record in json.loads(bytes)] def get_record(self, name: str) -> Record: - query_map = {"id": f"{self.organization_name}/{name}"} - url = util.get_url(self.base_client.endpoint, "get-record", query_map) - bytes = self.base_client.do_get_bytes(url) + query_map = {"id": f"{self.organizationName}/{name}"} + url = util.get_url(self.baseClient.endpoint, "get-record", query_map) + bytes = self.baseClient.do_get_bytes(url) return Record.from_dict(json.loads(bytes)) def get_pagination_records( - self, p: int, page_size: int, query_map: Dict[str, str] + self, p: int, pageSize: int, query_map: Dict[str, str] ) -> Tuple[List[Record], int]: - query_map["owner"] = self.organization_name + query_map["owner"] = self.organizationName query_map["p"] = str(p) - query_map["page_size"] = str(page_size) - url = util.get_url(self.base_client.endpoint, "get-records", query_map) - response = self.base_client.do_get_response(url) + query_map["pageSize"] = str(pageSize) + url = util.get_url(self.baseClient.endpoint, "get-records", query_map) + response = self.baseClient.do_get_response(url) return [Record.from_dict(record) for record in response.data], response.data2 def update_record(self, record: Record) -> bool: @@ -96,9 +96,9 @@ def update_record(self, record: Record) -> bool: def add_record(self, record: Record) -> bool: if not record.owner: - record.owner = self.organization_name + record.owner = self.organizationName if not record.organization: - record.organization = self.organization_name + record.organization = self.organizationName _, affected = self.modify_record("add-record", record, None) return affected @@ -108,12 +108,12 @@ def delete_record(self, record: Record) -> bool: def modify_record( self, action: str, record: Record, columns: Optional[List[str]] - ) -> Tuple[Dict, bool]: + ) -> Tuple[Response, bool]: query_map = {"id": f"{record.owner}/{record.name}"} if columns: query_map["columns"] = ",".join(columns) if not record.owner: record.owner = "admin" post_bytes = json.dumps(record.to_dict()).encode("utf-8") - resp = self.base_client.do_post(action, query_map, post_bytes, False, False) - return resp, resp["data"] == "Affected" + resp = self.baseClient.do_post(action, query_map, post_bytes, False, False) + return resp, resp.data == "Affected" diff --git a/src/tests/test_base.py b/src/tests/test_base.py index 08d3cb3..90fa305 100644 --- a/src/tests/test_base.py +++ b/src/tests/test_base.py @@ -15,23 +15,21 @@ import unittest import requests_mock from src.casvisor import BaseClient, Response +from src.tests.test_util import TestEndpoint, TestClientId, TestClientSecret class TestBaseClient(unittest.TestCase): def test_base_client_do_get_response_success(self): # Arrange - client_id = "client123" - client_secret = "secret456" - endpoint = "https://example.com" - base_client = BaseClient(client_id, client_secret, endpoint) - mock_response = {"status": "ok", "msg": "Success", "data": [], "data2": []} - url = f"{endpoint}/api/action" + baseClient = BaseClient(TestClientId, TestClientSecret, TestEndpoint) + mockResponse = {"status": "ok", "msg": "Success", "data": [], "data2": []} + url = f"{TestEndpoint}/api/action" # Mock HTTP GET response with requests_mock.Mocker() as m: - m.get(url, json=mock_response) + m.get(url, json=mockResponse) # Act - response = base_client.do_get_response(url) + response = baseClient.do_get_response(url) # Assert self.assertIsInstance(response, Response) @@ -42,40 +40,34 @@ def test_base_client_do_get_response_success(self): def test_base_client_do_get_response_error(self): # Arrange - client_id = "client123" - client_secret = "secret456" - endpoint = "https://example.com" - base_client = BaseClient(client_id, client_secret, endpoint) - mock_response = {"status": "error", "msg": "Something went wrong"} - url = f"{endpoint}/api/action" + baseClient = BaseClient(TestClientId, TestClientSecret, TestEndpoint) + mockResponse = {"status": "error", "msg": "Something went wrong"} + url = f"{TestEndpoint}/api/action" # Mock HTTP GET response with requests_mock.Mocker() as m: - m.get(url, json=mock_response) + m.get(url, json=mockResponse) # Act & Assert with self.assertRaises(Exception) as context: - base_client.do_get_response(url) + baseClient.do_get_response(url) self.assertTrue("Something went wrong" in str(context.exception)) def test_do_get_bytes(self): # Arrange - client_id = "client123" - client_secret = "secret456" - endpoint = "https://example.com" - base_client = BaseClient(client_id, client_secret, endpoint) - mock_response = { + baseClient = BaseClient(TestClientId, TestClientSecret, TestEndpoint) + mockResponse = { "status": "ok", "msg": "Success", "data": {"key": "value"}, "data2": [], } - url = f"{endpoint}/api/action" + url = f"{TestEndpoint}/api/action" # Mock HTTP GET response with requests_mock.Mocker() as m: - m.get(url, json=mock_response) + m.get(url, json=mockResponse) # Act - result = base_client.do_get_bytes(url) + result = baseClient.do_get_bytes(url) # Assert self.assertIsInstance(result, bytes) @@ -83,11 +75,8 @@ def test_do_get_bytes(self): def test_do_post(self): # Arrange - client_id = "client123" - client_secret = "secret456" - endpoint = "https://example.com" - base_client = BaseClient(client_id, client_secret, endpoint) - mock_response = { + baseClient = BaseClient(TestClientId, TestClientSecret, TestEndpoint) + mockResponse = { "status": "ok", "msg": "Success", "data": "Affected", @@ -96,8 +85,8 @@ def test_do_post(self): # Act with requests_mock.Mocker() as m: - m.post(f"{endpoint}/api/action", json=mock_response) - response = base_client.do_post( + m.post(f"{TestEndpoint}/api/action", json=mockResponse) + response = baseClient.do_post( "action", {"param": "value"}, b'{"test": "data"}', False, False ) @@ -108,11 +97,11 @@ def test_do_post(self): def test_prepare_body_form(self): # Arrange - client = BaseClient("id", "secret", "endpoint") - post_bytes = b'{"field": "value"}' + baseClient = BaseClient(TestClientId, TestClientSecret, TestEndpoint) + postBytes = b'{"field": "value"}' # Act - content_type, body = client.prepare_body(post_bytes, True, False) + content_type, body = baseClient.prepare_body(postBytes, True, False) # Assert self.assertTrue(content_type.startswith("multipart/form-data")) diff --git a/src/tests/test_main.py b/src/tests/test_main.py index 25c5fb6..d251fec 100644 --- a/src/tests/test_main.py +++ b/src/tests/test_main.py @@ -14,30 +14,37 @@ import unittest from src.casvisor import BaseClient, CasvisorSDK +from src.tests.test_util import ( + TestEndpoint, + TestClientId, + TestClientSecret, + TestOrganization, + TestApplication, +) class TestCasvisorSDK(unittest.TestCase): def test_casvisor_sdk_initialization(self): # Arrange - endpoint = "https://example.com" - client_id = "client123" - client_secret = "secret456" - organization_name = "org789" - application_name = "app012" + endpoint = TestEndpoint + client_id = TestClientId + client_secret = TestClientSecret + organization_name = TestOrganization + application_name = TestApplication # Act sdk = CasvisorSDK( endpoint=endpoint, - client_id=client_id, - client_secret=client_secret, - organization_name=organization_name, - application_name=application_name, + clientId=client_id, + clientSecret=client_secret, + organizationName=organization_name, + applicationName=application_name, ) # Assert self.assertEqual(sdk.endpoint, endpoint) - self.assertEqual(sdk.client_id, client_id) - self.assertEqual(sdk.client_secret, client_secret) - self.assertEqual(sdk.organization_name, organization_name) - self.assertEqual(sdk.application_name, application_name) - self.assertIsInstance(sdk.base_client, BaseClient) + self.assertEqual(sdk.clientId, client_id) + self.assertEqual(sdk.clientSecret, client_secret) + self.assertEqual(sdk.organizationName, organization_name) + self.assertEqual(sdk.applicationName, application_name) + self.assertIsInstance(sdk.baseClient, BaseClient) diff --git a/src/tests/test_record.py b/src/tests/test_record.py index d9b62c0..639065f 100644 --- a/src/tests/test_record.py +++ b/src/tests/test_record.py @@ -13,171 +13,100 @@ # limitations under the License. import unittest +import time from src.casvisor import Record, BaseClient, _RecordSDK -import requests_mock +from src.tests.test_util import ( + TestClientId, + TestClientSecret, + TestEndpoint, + TestOrganization, + get_random_name, +) class TestRecord(unittest.TestCase): - def test_record_to_dict(self): - # Arrange + def test_record(self): + name = get_random_name("record") + + timestamp = int(time.time()) + tm = time.gmtime(timestamp) + createdTime = time.strftime("%Y-%m-%dT%H:%M:%SZ", tm) + + # Create a new record record = Record( - id=1, - owner="org123", - name="record_name", - created_time="2023-10-01T12:00:00Z", - organization="org123", - client_ip="192.168.1.1", - user="user1", - method="GET", - request_uri="/api/endpoint", - action="view", + owner=TestOrganization, + name=name, + createdTime=createdTime, + organization=TestOrganization, + clientIp="120.85.97.21", + user="admin", + method="POST", + requestUri="/api/test_request_uri", + action="test_action", + object="test_object", language="en", - object="object1", - response="200 OK", - provider="provider1", - block="block1", - is_triggered=True, + response='{"status":"ok", "msg":"test_response"}', + isTriggered=True, ) - # Act - record_dict = record.to_dict() - - # Assert - self.assertEqual(record_dict["id"], 1) - self.assertEqual(record_dict["owner"], "org123") - self.assertEqual(record_dict["name"], "record_name") - # Additional assertions as needed - - def test_record_from_dict(self): - # Arrange - record_data = { - "id": 1, - "owner": "org123", - "name": "record_name", - "created_time": "2023-10-01T12:00:00Z", - "organization": "org123", - "client_ip": "192.168.1.1", - "user": "user1", - "method": "GET", - "request_uri": "/api/endpoint", - "action": "view", - "language": "en", - "object": "object1", - "response": "200 OK", - "provider": "provider1", - "block": "block1", - "is_triggered": True, - } - - # Act - record = Record.from_dict(record_data) - - # Assert - self.assertEqual(record.id, 1) - self.assertEqual(record.owner, "org123") - self.assertEqual(record.name, "record_name") - # Additional assertions as needed - - def test_record_sdk_get_records(self): - # Arrange - client_id = "client123" - client_secret = "secret456" - endpoint = "https://example.com" - organization_name = "org123" - base_client = BaseClient(client_id, client_secret, endpoint) - sdk = _RecordSDK(base_client, organization_name) + client = BaseClient(TestClientId, TestClientSecret, TestEndpoint) + sdk = _RecordSDK(client, TestOrganization) - self.assertIsInstance(sdk, _RecordSDK) + # Add a new record + try: + result = sdk.add_record(record) + except Exception as e: + self.fail(f"Failed to add record: {e}") - def test_get_records(self): - # Arrange - client_id = "client123" - client_secret = "secret456" - endpoint = "https://example.com" - organization_name = "org123" - base_client = BaseClient(client_id, client_secret, endpoint) - sdk = _RecordSDK(base_client, organization_name) - - mock_response = { - "status": "ok", - "msg": "Success", - "data": [ - { - "id": 1, - "owner": "org123", - "name": "record1", - "created_time": "2023-10-01T12:00:00Z", - "organization": "org123", - "client_ip": "192.168.1.1", - "user": "user1", - "method": "GET", - "request_uri": "/api/endpoint", - "action": "view", - "language": "en", - "object": "object1", - "response": "200 OK", - "provider": "provider1", - "block": "block1", - "is_triggered": True, - } - ], - "data2": [], - } - - # Mock HTTP GET response - with requests_mock.Mocker() as m: - m.get(f"{endpoint}/api/get-records", json=mock_response) - # Act + # Get all records, check if our added record is inside the list + try: records = sdk.get_records() + except Exception as e: + self.fail(f"Failed to get records: {e}") + names = [item.name for item in records] + self.assertIn(name, names, "Added record not found in list") + + # Get the record + try: + retrieved_record = sdk.get_record(name) + except Exception as e: + self.fail(f"Failed to get record: {e}") + self.assertEqual( + name, retrieved_record.name, "Retrieved record does not match added record" + ) - # Assert - self.assertEqual(len(records), 1) - self.assertIsInstance(records[0], Record) - self.assertEqual(records[0].id, 1) - self.assertEqual(records[0].name, "record1") - - def test_get_pagination_records(self): - # Arrange - client_id = "client123" - client_secret = "secret456" - endpoint = "https://example.com" - organization_name = "org123" - base_client = BaseClient(client_id, client_secret, endpoint) - sdk = _RecordSDK(base_client, organization_name) - - mock_response = { - "status": "ok", - "msg": "Success", - "data": [ - { - "id": 1, - "owner": "org123", - "name": "record1", - "created_time": "2023-10-01T12:00:00Z", - "organization": "org123", - "client_ip": "192.168.1.1", - "user": "user1", - "method": "GET", - "request_uri": "/api/endpoint", - "action": "view", - "language": "en", - "object": "object1", - "response": "200 OK", - "provider": "provider1", - "block": "block1", - "is_triggered": True, - } - ], - "data2": 10, # total count - } + # Update the record + updated_action = "updated_action" + retrieved_record.action = updated_action + try: + result = sdk.update_record(retrieved_record) + except Exception as e: + self.fail(f"Failed to update record: {e}") + self.assertTrue(result, "Failed to update record") + + # Validate the update + try: + updated_record = sdk.get_record(name) + + except Exception as e: + self.fail(f"Failed to get record: {e}") + self.assertEqual( + updated_action, + updated_record.action, + "Failed to update record, action mismatch", + ) - # Mock HTTP GET response - with requests_mock.Mocker() as m: - m.get(f"{endpoint}/api/get-records", json=mock_response) - # Act - records, total = sdk.get_pagination_records(1, 10, {}) + # Delete the record + try: + result = sdk.delete_record(record) + except Exception as e: + self.fail(f"Failed to delete record: {e}") + self.assertTrue(result, "Failed to delete record") - # Assert - self.assertEqual(len(records), 1) - self.assertEqual(total, 10) - self.assertIsInstance(records[0], Record) + # Validate the deletion + try: + records = sdk.get_records() + except Exception as e: + self.fail(f"Failed to get records: {e}") + names = [item.name for item in records] + self.assertNotIn(name, names, "Failed to delete record, it's still in the list") diff --git a/src/tests/test_util.py b/src/tests/test_util.py new file mode 100644 index 0000000..213d964 --- /dev/null +++ b/src/tests/test_util.py @@ -0,0 +1,29 @@ +# Copyright 2025 The casbin Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import random + +TestEndpoint = "https://demo.casvisor.com" +TestClientId = "b108dacba027db36ec26" +TestClientSecret = "124140638b4f9de7e78e79ba22d451c17bfa9688" +TestOrganization = "casbin" +TestApplication = "app-casvisor" + +def get_random_code(length): + std_nums = "0123456789" + result = "".join(random.choice(std_nums) for _ in range(length)) + return result + +def get_random_name(prefix): + return f"{prefix}_{get_random_code(6)}" \ No newline at end of file From db0570a579d6769bedc81b930cca76d5c7ae88a2 Mon Sep 17 00:00:00 2001 From: Luckery <1196623300@qq.com> Date: Thu, 16 Jan 2025 00:51:41 +0800 Subject: [PATCH 2/4] fix: Restore pipy and other configurations --- .github/workflows/build.yml | 4 ++-- package.json | 26 ++++++++++++++++++-------- pyproject.toml | 27 +++++++++++++++++++++++++-- setup.cfg | 3 ++- 4 files changed, 47 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e17d92a..bc46a75 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -54,7 +54,7 @@ jobs: - name: Setup semantic-release run: | npm init -y - npm install -g semantic-release @semantic-release/github @semantic-release/commit-analyzer @semantic-release/release-notes-generator + npm install -g semantic-release @semantic-release/github @semantic-release/changelog @semantic-release/commit-analyzer @semantic-release/git @semantic-release/release-notes-generator semantic-release-pypi - name: Set up Python uses: actions/setup-python@v2 @@ -67,5 +67,5 @@ jobs: - name: Release env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} + PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} run: npx semantic-release \ No newline at end of file diff --git a/package.json b/package.json index 48616f1..4e98792 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { "name": "casvisor-python-sdk", - "version": "0.1.0", + "version": "1.0.0", "repository": { "type": "git", - "url": "https://github.com/ljl66-66/casvisor-python-sdk.git" + "url": "https://github.com/casvisor/casvisor-python-sdk.git" }, "release": { "branches": [ @@ -12,14 +12,24 @@ "plugins": [ "@semantic-release/commit-analyzer", "@semantic-release/release-notes-generator", + "semantic-release-pypi", + "@semantic-release/github", [ - "@semantic-release/github", + "@semantic-release/changelog", { - "successComment": false, - "failComment": false, - "failTitle": false, - "releasedLabels": false, - "addReleases": "bottom" + "changelogFile": "CHANGELOG.md", + "changelogTitle": "# Semantic Versioning Changelog" + } + ], + [ + "@semantic-release/git", + { + "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}", + "assets": [ + "CHANGELOG.md", + "setup.py", + "setup.cfg" + ] } ] ] diff --git a/pyproject.toml b/pyproject.toml index 7876372..ae43792 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "casvisor-python-sdk" -version = "0.1.0" +version = "1.0.0" description = "Python SDK for Casvisor" readme = "README.md" requires-python = ">=3.8" @@ -8,15 +8,17 @@ authors = [ { name = "Casvisor", email = "admin@casvisor.com" } ] license = { file = "LICENSE" } +keywords = ["Casvisor"] classifiers = [ "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", - "Programming Language :: Python :: 3", + "Programming Language :: Python", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", ] dynamic = ["dependencies"] @@ -29,3 +31,24 @@ dependencies = {file = ["requirements.txt"]} [build-system] requires = ["setuptools", "wheel"] build-backend = "setuptools.build_meta" + +[tool.black] +line-length = 88 +target-version = ["py38", "py39", "py310", "py311"] +include = '\.pyi?$' + +[tool.ruff] +line-length = 88 + +select = [ + "E", # pycodestyle errors + "W", # pycodestyle warnings + "F", # pyflakes + "I", # isort + "C", # flake8-comprehensions + "B", # flake8-bugbear +] + +# Allow autofix for all enabled rules (when `--fix`) is provided. +fixable = ["I", "F"] +unfixable = [] \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 8c11939..fb0e768 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = casvisor -version = 0.1.0 +version = 1.0.0 author = Casvisor author_email = admin@casvisor.org url = https://github.com/casvisor/casvisor-python-sdk @@ -19,6 +19,7 @@ classifiers = Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 + Programming Language :: Python :: 3.12 [options] package_dir = From 0090e0a86f195709f93c18d3b622248a8f9f229c Mon Sep 17 00:00:00 2001 From: Luckery <123811390+ljl66-66@users.noreply.github.com> Date: Sun, 26 Jan 2025 14:27:02 +0800 Subject: [PATCH 3/4] fix: Format code style * fix: Try publishing to the pypi test site * fix: Format code style * fix: Test the master branch --- .github/workflows/build.yml | 5 +++-- pyproject.toml | 1 + setup.cfg | 2 +- src/casvisor/__init__.py | 2 +- src/casvisor/base.py | 4 +++- src/casvisor/record.py | 3 ++- src/casvisor/util.py | 3 ++- src/tests/test_base.py | 4 +++- src/tests/test_main.py | 5 +++-- src/tests/test_record.py | 5 +++-- src/tests/test_util.py | 4 +++- 11 files changed, 25 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bc46a75..0533fc4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,9 +2,9 @@ name: build on: push: - branches: [ master ] + branches: [ master, Fix-CI-errors ] pull_request: - branches: [ master ] + branches: [ master, Fix-CI-errors ] jobs: test: @@ -68,4 +68,5 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} + PYPI_REPOSITORY_URL: https://test.pypi.org/legacy/ run: npx semantic-release \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index ae43792..6ab3b6a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,7 @@ include = '\.pyi?$' [tool.ruff] line-length = 88 +[tool.ruff.lint] select = [ "E", # pycodestyle errors "W", # pycodestyle warnings diff --git a/setup.cfg b/setup.cfg index fb0e768..592797c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [metadata] -name = casvisor +name = casvisor-python-sdk-test version = 1.0.0 author = Casvisor author_email = admin@casvisor.org diff --git a/src/casvisor/__init__.py b/src/casvisor/__init__.py index 39877d2..818e3da 100644 --- a/src/casvisor/__init__.py +++ b/src/casvisor/__init__.py @@ -12,8 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # -from .main import CasvisorSDK from .base import BaseClient, Response +from .main import CasvisorSDK from .record import Record, _RecordSDK __all__ = ["CasvisorSDK", "BaseClient", "Response", "Record", "_RecordSDK"] diff --git a/src/casvisor/base.py b/src/casvisor/base.py index a6c1920..e544be5 100644 --- a/src/casvisor/base.py +++ b/src/casvisor/base.py @@ -13,8 +13,10 @@ # limitations under the License. import json -from typing import Dict, Union, List, Tuple +from typing import Dict, List, Tuple, Union + import requests + from . import util diff --git a/src/casvisor/record.py b/src/casvisor/record.py index a4f974f..bc07ad2 100644 --- a/src/casvisor/record.py +++ b/src/casvisor/record.py @@ -14,8 +14,9 @@ import json from typing import Dict, List, Optional, Tuple -from .base import BaseClient, Response + from . import util +from .base import BaseClient, Response class Record: diff --git a/src/casvisor/util.py b/src/casvisor/util.py index 9857519..ada8767 100644 --- a/src/casvisor/util.py +++ b/src/casvisor/util.py @@ -13,9 +13,10 @@ # limitations under the License. -from requests_toolbelt.multipart.encoder import MultipartEncoder from typing import Dict, Tuple +from requests_toolbelt.multipart.encoder import MultipartEncoder + def get_url(base_url: str, action: str, query_map: Dict[str, str]) -> str: query = "&".join([f"{k}={v}" for k, v in query_map.items()]) diff --git a/src/tests/test_base.py b/src/tests/test_base.py index 90fa305..3cd60be 100644 --- a/src/tests/test_base.py +++ b/src/tests/test_base.py @@ -13,9 +13,11 @@ # limitations under the License. import unittest + import requests_mock + from src.casvisor import BaseClient, Response -from src.tests.test_util import TestEndpoint, TestClientId, TestClientSecret +from src.tests.test_util import TestClientId, TestClientSecret, TestEndpoint class TestBaseClient(unittest.TestCase): diff --git a/src/tests/test_main.py b/src/tests/test_main.py index d251fec..d357e2b 100644 --- a/src/tests/test_main.py +++ b/src/tests/test_main.py @@ -13,13 +13,14 @@ # limitations under the License. import unittest + from src.casvisor import BaseClient, CasvisorSDK from src.tests.test_util import ( - TestEndpoint, + TestApplication, TestClientId, TestClientSecret, + TestEndpoint, TestOrganization, - TestApplication, ) diff --git a/src/tests/test_record.py b/src/tests/test_record.py index 639065f..04eb9bd 100644 --- a/src/tests/test_record.py +++ b/src/tests/test_record.py @@ -12,9 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -import unittest import time -from src.casvisor import Record, BaseClient, _RecordSDK +import unittest + +from src.casvisor import BaseClient, Record, _RecordSDK from src.tests.test_util import ( TestClientId, TestClientSecret, diff --git a/src/tests/test_util.py b/src/tests/test_util.py index 213d964..6bc95c4 100644 --- a/src/tests/test_util.py +++ b/src/tests/test_util.py @@ -20,10 +20,12 @@ TestOrganization = "casbin" TestApplication = "app-casvisor" + def get_random_code(length): std_nums = "0123456789" result = "".join(random.choice(std_nums) for _ in range(length)) return result + def get_random_name(prefix): - return f"{prefix}_{get_random_code(6)}" \ No newline at end of file + return f"{prefix}_{get_random_code(6)}" From 85e4ed62434bd175683adcef5be939206d1f70f6 Mon Sep 17 00:00:00 2001 From: Luckery <1196623300@qq.com> Date: Sun, 26 Jan 2025 14:33:21 +0800 Subject: [PATCH 4/4] fix: Pypi officially released --- .github/workflows/build.yml | 5 ++--- setup.cfg | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0533fc4..bc46a75 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,9 +2,9 @@ name: build on: push: - branches: [ master, Fix-CI-errors ] + branches: [ master ] pull_request: - branches: [ master, Fix-CI-errors ] + branches: [ master ] jobs: test: @@ -68,5 +68,4 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} - PYPI_REPOSITORY_URL: https://test.pypi.org/legacy/ run: npx semantic-release \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 592797c..f0863c3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [metadata] -name = casvisor-python-sdk-test +name = casvisor-python-sdk version = 1.0.0 author = Casvisor author_email = admin@casvisor.org