diff --git a/CITATION.cff b/CITATION.cff index 84790eb..50db2e5 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -3,7 +3,7 @@ message: If you use this software, please cite it using these metadata. title: PyPi Extractor abstract: Extract package information for a given user in PyPi. type: software -version: 0.1.0 +version: 0.1.1 date-released: 2024-06-11 repository-code: https://github.com/DevelopersToolbox/pypi-extractor-package keywords: diff --git a/README.md b/README.md index 112c0e9..770e9c7 100644 --- a/README.md +++ b/README.md @@ -66,10 +66,10 @@ pip install wolfsoftware.pypi-extractor Here's a basic example of how to use the PyPI Extractor: ```python -from wolfsoftware.pypi_extractor import PyPIPackageInfo +from wolfsoftware.pypi_extractor import PyPiExtractor # Initialize without username -pypi_info = PyPIPackageInfo() +pypi_info = PyPiExtractor() # Set username later pypi_info.set_username("your_pypi_username") @@ -78,7 +78,7 @@ pypi_info.set_username("your_pypi_username") try: packages_details = pypi_info.get_all_packages_details() print(packages_details) -except PyPIPackageInfoError as e: +except PyPiExtractorError as e: print(f"An error occurred: {e.message}") ``` @@ -87,7 +87,7 @@ except PyPIPackageInfoError as e: You can also set the username during initialization: ```python -pypi_info = PyPIPackageInfo("your_pypi_username") +pypi_info = PyPiExtractor("your_pypi_username") ``` ### Retrieving User Packages @@ -112,17 +112,17 @@ print(package_details) ### Classes -#### `PyPIPackageInfo` +#### `PyPiExtractor` A class to fetch and process package details for a given PyPI user. ##### `__init__(self, username: str)` -- Initializes the `PyPIPackageInfo` with a username. +- Initializes the `PyPiExtractor` with a username. - Parameters: - `username` (str): The PyPI username. - Raises: - - `PyPIPackageInfoError`: If the username is not provided. + - `PyPiExtractorError`: If the username is not provided. ##### `set_username(self, username: str)` @@ -130,7 +130,7 @@ A class to fetch and process package details for a given PyPI user. - Parameters: - `username` (str): The PyPI username. - Raises: - - `PyPIPackageInfoError`: If the username is not provided. + - `PyPiExtractorError`: If the username is not provided. ##### `get_user_packages(self) -> list` @@ -138,7 +138,7 @@ A class to fetch and process package details for a given PyPI user. - Returns: - `list`: A list of dictionaries containing package names and summaries. - Raises: - - `PyPIPackageInfoError`: If there is an error fetching or parsing the user profile. + - `PyPiExtractorError`: If there is an error fetching or parsing the user profile. ##### `get_package_details(self, package_name: str) -> dict` @@ -148,7 +148,7 @@ A class to fetch and process package details for a given PyPI user. - Returns: - `dict`: A dictionary containing detailed information about the package. - Raises: - - `PyPIPackageInfoError`: If there is an error fetching or parsing the package details. + - `PyPiExtractorError`: If there is an error fetching or parsing the package details. ##### `get_all_packages_details(self) -> list` @@ -156,11 +156,11 @@ A class to fetch and process package details for a given PyPI user. - Returns: - `list`: A list of dictionaries containing detailed information about each package. - Raises: - - `PyPIPackageInfoError`: If there is an error fetching or processing the package details. + - `PyPiExtractorError`: If there is an error fetching or processing the package details. -#### `PyPIPackageInfoError` +#### `PyPiExtractorError` -Custom exception class for `PyPIPackageInfo` errors. +Custom exception class for `PyPiExtractor` errors.

diff --git a/setup.py b/setup.py index 4b377bc..d9cd5bb 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ setup( name='wolfsoftware.pypi-extractor', - version='0.1.0', + version='0.1.1', author='Wolf Software', author_email='pypi@wolfsoftware.com', description='Extract package information for a given user in PyPi.', diff --git a/tests/test_pypi_extractor.py b/tests/test_pypi_extractor.py index e114606..d4b9aa0 100644 --- a/tests/test_pypi_extractor.py +++ b/tests/test_pypi_extractor.py @@ -9,7 +9,7 @@ import pytest -from wolfsoftware.pypi_extractor import PyPIPackageInfo, PyPIPackageInfoError # pylint: disable=unused-import +from wolfsoftware.pypi_extractor import PyPiExtractor, PyPiExtractorError # pylint: disable=unused-import, no-name-in-module from .testconf import ( # noqa: F401 pylint: disable=unused-import mock_get_user_packages_success, mock_get_user_packages_error, @@ -45,12 +45,12 @@ def test_init_with_empty_username() -> None: does not raise an error, and that attempting to fetch packages without setting a username raises a PyPIPackageInfoError. """ - pypi_info = PyPIPackageInfo() + pypi_info = PyPiExtractor() - with pytest.raises(PyPIPackageInfoError, match="Username must be set before fetching packages"): + with pytest.raises(PyPiExtractorError, match="Username must be set before fetching packages"): pypi_info.get_user_packages() - with pytest.raises(PyPIPackageInfoError, match="Username must be set before fetching package details"): + with pytest.raises(PyPiExtractorError, match="Username must be set before fetching package details"): pypi_info.get_all_packages_details() @@ -58,10 +58,10 @@ def test_set_username() -> None: """ Test setting the username after initialization. - This test verifies that the username can be set after initializing the PyPIPackageInfo class, + This test verifies that the username can be set after initializing the PyPiExtractor class, and that it functions correctly with the set username. """ - pypi_info = PyPIPackageInfo() + pypi_info = PyPiExtractor() pypi_info.set_username("testuser") assert pypi_info.username == "testuser" # nosec: B101 @@ -70,11 +70,11 @@ def test_set_username_with_invalid_value() -> None: """ Test setting the username with an invalid value. - This test verifies that setting the username to an empty string raises a PyPIPackageInfoError. + This test verifies that setting the username to an empty string raises a PyPiExtractorError. """ - pypi_info = PyPIPackageInfo() + pypi_info = PyPiExtractor() - with pytest.raises(PyPIPackageInfoError, match="Username must be provided"): + with pytest.raises(PyPiExtractorError, match="Username must be provided"): pypi_info.set_username("") @@ -86,7 +86,7 @@ def test_get_user_packages_success(mock_get_user_packages_success) -> None: # n to return a successful response and verifies that the get_user_packages method returns the expected list of packages. """ - pypi_info = PyPIPackageInfo("testuser") + pypi_info = PyPiExtractor("testuser") packages: List = pypi_info.get_user_packages() assert len(packages) == 2 # nosec: B101 @@ -101,11 +101,11 @@ def test_get_user_packages_error(mock_get_user_packages_error) -> None: # noqa: Test get_user_packages method when there is an error. This test uses the mock_get_user_packages_error fixture to mock requests.get method - to raise an exception and verifies that the get_user_packages method raises a PyPIPackageInfoError. + to raise an exception and verifies that the get_user_packages method raises a PyPiExtractorError. """ - pypi_info = PyPIPackageInfo("testuser") + pypi_info = PyPiExtractor("testuser") - with pytest.raises(PyPIPackageInfoError, match="Error fetching user profile: Request error"): + with pytest.raises(PyPiExtractorError, match="Error fetching user profile: Request error"): pypi_info.get_user_packages() @@ -117,7 +117,7 @@ def test_get_package_details_success(mock_get_package_details_success) -> None: to return a successful response and verifies that the get_package_details method returns the expected package details. """ - pypi_info = PyPIPackageInfo("testuser") + pypi_info = PyPiExtractor("testuser") details: Dict[str, Any] = pypi_info.get_package_details("Package1") assert details['name'] == "Package1" # nosec: B101 @@ -141,11 +141,11 @@ def test_get_package_details_error(mock_get_package_details_error) -> None: # n Test get_package_details method when there is an error. This test uses the mock_get_package_details_error fixture to mock requests.get method - to raise an exception and verifies that the get_package_details method raises a PyPIPackageInfoError. + to raise an exception and verifies that the get_package_details method raises a PyPiExtractorError. """ - pypi_info = PyPIPackageInfo("testuser") + pypi_info = PyPiExtractor("testuser") - with pytest.raises(PyPIPackageInfoError, match="Error fetching package details: Request error"): + with pytest.raises(PyPiExtractorError, match="Error fetching package details: Request error"): pypi_info.get_package_details("Package1") @@ -157,7 +157,7 @@ def test_get_all_packages_details_success(mock_get_all_packages_details_success) to return a successful response for both user packages and package details, and verifies that the get_all_packages_details method returns the expected list of detailed package information. """ - pypi_info = PyPIPackageInfo("testuser") + pypi_info = PyPiExtractor("testuser") details: List = pypi_info.get_all_packages_details() assert len(details) == 2 # nosec: B101 diff --git a/wolfsoftware/pypi_extractor/__init__.py b/wolfsoftware/pypi_extractor/__init__.py index 52dd4af..364d447 100644 --- a/wolfsoftware/pypi_extractor/__init__.py +++ b/wolfsoftware/pypi_extractor/__init__.py @@ -8,8 +8,8 @@ import importlib.metadata -from .exceptions import PyPIPackageInfoError -from .pypi import PyPIPackageInfo +from .exceptions import PyPiExtractorError +from .pypi import PyPiExtractor try: __version__: str = importlib.metadata.version('pypi_extractor') @@ -17,6 +17,6 @@ __version__ = 'unknown' __all__: list[str] = [ - 'PyPIPackageInfoError', - 'PyPIPackageInfo' + 'PyPiExtractorError', + 'PyPiExtractor' ] diff --git a/wolfsoftware/pypi_extractor/exceptions.py b/wolfsoftware/pypi_extractor/exceptions.py index dc3581b..bf0ba44 100644 --- a/wolfsoftware/pypi_extractor/exceptions.py +++ b/wolfsoftware/pypi_extractor/exceptions.py @@ -1,12 +1,12 @@ """ -This module defines custom exceptions for the PyPI package info retriever. +This module defines custom exceptions for the PyPI Extractor package. Classes: - - PyPIPackageInfoError: A custom exception class for errors in the PyPIPackageInfo class. + - PyPiExtractorError: A custom exception class for errors in the PyPiExtractor class. """ -class PyPIPackageInfoError(Exception): +class PyPiExtractorError(Exception): """ Custom exception class for PyPIPackageInfo errors. diff --git a/wolfsoftware/pypi_extractor/pypi.py b/wolfsoftware/pypi_extractor/pypi.py index 15a36d4..1b07b4b 100644 --- a/wolfsoftware/pypi_extractor/pypi.py +++ b/wolfsoftware/pypi_extractor/pypi.py @@ -1,8 +1,8 @@ """ -This module defines the PyPIPackageInfo class for fetching and processing package details from PyPI. +This module defines the PyPiExtractor class for fetching and processing package details from PyPI. Classes: - - PyPIPackageInfo: A class to fetch and process package details for a given PyPI user. + - PyPiExtractor: A class to fetch and process package details for a given PyPI user. """ from typing import Any, Dict, List, Optional @@ -10,10 +10,10 @@ import requests from bs4 import BeautifulSoup -from .exceptions import PyPIPackageInfoError +from .exceptions import PyPiExtractorError -class PyPIPackageInfo: +class PyPiExtractor: """ A class to fetch and process package details for a given PyPI user. @@ -41,7 +41,7 @@ def set_username(self, username: str) -> None: PyPIPackageInfoError: If the username is not provided. """ if not username: - raise PyPIPackageInfoError("Username must be provided") + raise PyPiExtractorError("Username must be provided") self.username = username def get_user_packages(self) -> List[Dict[str, str]]: @@ -55,14 +55,14 @@ def get_user_packages(self) -> List[Dict[str, str]]: PyPIPackageInfoError: If the username is not set or if there is an error fetching or parsing the user profile. """ if not self.username: - raise PyPIPackageInfoError("Username must be set before fetching packages") + raise PyPiExtractorError("Username must be set before fetching packages") profile_url: str = "https://pypi.org/user/" + self.username + "/" try: response: requests.Response = requests.get(profile_url, timeout=10) response.raise_for_status() except requests.RequestException as e: - raise PyPIPackageInfoError(f"Error fetching user profile: {e}") from e + raise PyPiExtractorError(f"Error fetching user profile: {e}") from e soup = BeautifulSoup(response.text, 'html.parser') packages: List[Dict[str, str]] = [] @@ -72,7 +72,7 @@ def get_user_packages(self) -> List[Dict[str, str]]: summary: str = project.find('p', class_='package-snippet__description').text.strip() packages.append({'name': package_name, 'summary': summary}) except AttributeError as e: - raise PyPIPackageInfoError(f"Error parsing package details: {e}") from e + raise PyPiExtractorError(f"Error parsing package details: {e}") from e return packages @@ -94,12 +94,12 @@ def get_package_details(self, package_name: str) -> Dict[str, Any]: response: requests.Response = requests.get(url, timeout=10) response.raise_for_status() except requests.RequestException as e: - raise PyPIPackageInfoError(f"Error fetching package details: {e}") from e + raise PyPiExtractorError(f"Error fetching package details: {e}") from e try: package_data: Any = response.json() except json.JSONDecodeError as e: - raise PyPIPackageInfoError(f"Error decoding JSON response: {e}") from e + raise PyPiExtractorError(f"Error decoding JSON response: {e}") from e info: Any = package_data.get('info', {}) current_version: str = info.get('version') @@ -149,21 +149,21 @@ def get_all_packages_details(self) -> List[Dict[str, Any]]: PyPIPackageInfoError: If there is an error fetching or processing the package details. """ if not self.username: - raise PyPIPackageInfoError("Username must be set before fetching package details") + raise PyPiExtractorError("Username must be set before fetching package details") try: packages: List[Dict[str, str]] = self.get_user_packages() - except PyPIPackageInfoError as e: - raise PyPIPackageInfoError(f"Failed to get user packages: {e}") from e + except PyPiExtractorError as e: + raise PyPiExtractorError(f"Failed to get user packages: {e}") from e if not packages: - raise PyPIPackageInfoError(f"No packages found for user/organization '{self.username}'") + raise PyPiExtractorError(f"No packages found for user/organization '{self.username}'") detailed_packages: List[Dict[str, Any]] = [] for package in packages: try: details: Dict[str, Any] = self.get_package_details(package['name']) detailed_packages.append(details) - except PyPIPackageInfoError as e: - raise PyPIPackageInfoError(f"Failed to get details for package '{package['name']}': {e}") from e + except PyPiExtractorError as e: + raise PyPiExtractorError(f"Failed to get details for package '{package['name']}': {e}") from e return detailed_packages