olivia_finder.data_source.librariesio_ds

  1from typing import List, Union
  2from ..utilities.exception import OliviaFinderException
  3from ..utilities.config import Configuration
  4from .data_source import DataSource
  5import sys
  6import time
  7
  8
  9# Load the Libraries.io API key before importing the librariesio package
 10# -----------------------------------------------------------------------
 11
 12# try to load the API key from the configuration file
 13API_KEY = Configuration().get_key('librariesio', 'api_key')
 14if API_KEY is None:
 15    raise OliviaFinderException("API key for Libraries.io not found")
 16
 17# Set as environment variable
 18import os
 19os.environ["LIBRARIES_API_KEY"] = API_KEY
 20from pybraries.search import Search
 21
 22class LibrariesioDataSource(DataSource):
 23    """
 24    Data source for the Libraries.io API
 25
 26    .. warning::
 27
 28        - The API key must be set as an environment variable with the name `LIBRARIES_API_KEY`
 29        - The class will raise an exception if the API key is not found
 30        - The API key can be set in the configuration file
 31        - The API key can be obtained from the user's profile in Libraries.io
 32
 33    """
 34
 35    DEFAULT_DESCRIPTION = "Libraries.io data source"
 36    
 37    def __init__(self, platform: str):
 38        """
 39        Constructor of the class
 40
 41        Parameters
 42        ----------
 43        platform : str
 44            Platform of the data source to search for packages
 45
 46        Raises
 47        ------
 48        LibrariesIoException
 49            If the search object cannot be created
 50        """
 51        super().__init__()
 52        self.platform = platform
 53
 54        # Create the search object
 55        try:
 56            self.search = Search()
 57        except Exception as e:
 58            pass
 59
 60    def obtain_package_names(self) -> List[str]:
 61        """
 62        Obtains the list of packages from the data source.
 63        """
 64        raise NotImplementedError
 65    
 66    def obtain_package_data(self, package_name:str) -> Union[dict, None]:
 67        """
 68        Obtains the data of a package from the data source.
 69
 70        Parameters
 71        ----------
 72        package_name : str
 73            Name of the package
 74
 75        Returns
 76        -------
 77        dict
 78            Dictionary with the package data
 79        None
 80            If the package is not found
 81            
 82        Example
 83        -------
 84        >>> data_source = LibrariesioDataSource('name', 'description', 'platform')
 85        >>> data_source.obtain_package_data('package_name')
 86        {'name': 'package_name', 'version': '1.0.0', 'dependencies': ['package1', 'package2'], 'url': 'www.example.com'}
 87        """
 88
 89        # Get the package version and url
 90        self.logger.debug(f"Obtaining data of {package_name}")
 91
 92        # Redirect the output to /dev/null to avoid printing the output of the search (pybraries bug)
 93        stdout = sys.stdout     # Keep the standard output backed up
 94        sys.stdout = open('/dev/null', 'w')
 95
 96        try:
 97            dependencies_data = self.search.project_dependencies(
 98                platforms=self.platform, project=package_name
 99            )
100
101            # Check if data is empty
102            if dependencies_data is None:
103
104                # Sleep for 3 second to avoid the API rate limit
105                self.logger.debug(f"Package {package_name} not found. Sleeping for 4 seconds for the API rate limit")
106                time.sleep(4)
107
108            # Try again
109            dependencies_data = self.search.project_dependencies(
110                platforms=self.platform, project=package_name
111            )
112
113            # Check if data is empty
114            if dependencies_data is None:
115
116                self.logger.debug(f"Package {package_name} not found")
117                return None
118            else:
119                self.logger.debug(f"Package {package_name} found")
120
121        except Exception as e:
122            self.logger.error(f"Exception while obtaining {package_name} dependencies")
123            return None
124
125        finally:
126            # Restore the original standard output
127            sys.stdout.close()
128            sys.stdout = stdout 
129
130        version = dependencies_data["dependencies_for_version"]
131        url = dependencies_data["package_manager_url"]
132
133
134        # Obtain the dependencies (dependencies field, project_name)
135        # Obtain the dependency version (atest_stable field)
136        dependencies = []
137
138        for dependency in dependencies_data["dependencies"]:
139            dependency_name = dependency["project_name"]
140            dependency_version = dependency["latest_stable"]
141
142            dependency_data = {
143                "name": dependency_name,
144                "version": dependency_version,
145            }
146
147            dependencies.append(dependency_data)
148
149        return {
150            "name": package_name,
151            "version": version,
152            "dependencies": dependencies,
153            "url": url
154        }
155        
156    def obtain_packages_data(self, package_names: List[str]) -> List[dict]:
157        '''
158        Obtains the data of a list of package names from the data source.
159
160        Returns
161        -------
162        List[dict]
163            The data of the packages as a list of dictionaries
164
165        Example
166        -------
167        >>> data_source = LibrariesioDataSource('name', 'description', 'platform')
168        >>> data_source.obtain_packages_data(['package1', 'package2'])
169        [{'name': 'package1', 'version': '1.0.0', 'dependencies': ['package1', 'package2'], 'url': 'www.example.com'}, 
170        {'name': 'package2', 'version': '1.0.0', 'dependencies': ['package1', 'package2'], 'url': 'www.example.com'}]
171        '''
172
173        packages_data = []
174
175        for package_name in package_names:
176            if package_data := self.obtain_package_data(package_name):
177                packages_data.append(package_data)
178
179        return packages_data
class LibrariesioDataSource(olivia_finder.data_source.data_source.DataSource):
 23class LibrariesioDataSource(DataSource):
 24    """
 25    Data source for the Libraries.io API
 26
 27    .. warning::
 28
 29        - The API key must be set as an environment variable with the name `LIBRARIES_API_KEY`
 30        - The class will raise an exception if the API key is not found
 31        - The API key can be set in the configuration file
 32        - The API key can be obtained from the user's profile in Libraries.io
 33
 34    """
 35
 36    DEFAULT_DESCRIPTION = "Libraries.io data source"
 37    
 38    def __init__(self, platform: str):
 39        """
 40        Constructor of the class
 41
 42        Parameters
 43        ----------
 44        platform : str
 45            Platform of the data source to search for packages
 46
 47        Raises
 48        ------
 49        LibrariesIoException
 50            If the search object cannot be created
 51        """
 52        super().__init__()
 53        self.platform = platform
 54
 55        # Create the search object
 56        try:
 57            self.search = Search()
 58        except Exception as e:
 59            pass
 60
 61    def obtain_package_names(self) -> List[str]:
 62        """
 63        Obtains the list of packages from the data source.
 64        """
 65        raise NotImplementedError
 66    
 67    def obtain_package_data(self, package_name:str) -> Union[dict, None]:
 68        """
 69        Obtains the data of a package from the data source.
 70
 71        Parameters
 72        ----------
 73        package_name : str
 74            Name of the package
 75
 76        Returns
 77        -------
 78        dict
 79            Dictionary with the package data
 80        None
 81            If the package is not found
 82            
 83        Example
 84        -------
 85        >>> data_source = LibrariesioDataSource('name', 'description', 'platform')
 86        >>> data_source.obtain_package_data('package_name')
 87        {'name': 'package_name', 'version': '1.0.0', 'dependencies': ['package1', 'package2'], 'url': 'www.example.com'}
 88        """
 89
 90        # Get the package version and url
 91        self.logger.debug(f"Obtaining data of {package_name}")
 92
 93        # Redirect the output to /dev/null to avoid printing the output of the search (pybraries bug)
 94        stdout = sys.stdout     # Keep the standard output backed up
 95        sys.stdout = open('/dev/null', 'w')
 96
 97        try:
 98            dependencies_data = self.search.project_dependencies(
 99                platforms=self.platform, project=package_name
100            )
101
102            # Check if data is empty
103            if dependencies_data is None:
104
105                # Sleep for 3 second to avoid the API rate limit
106                self.logger.debug(f"Package {package_name} not found. Sleeping for 4 seconds for the API rate limit")
107                time.sleep(4)
108
109            # Try again
110            dependencies_data = self.search.project_dependencies(
111                platforms=self.platform, project=package_name
112            )
113
114            # Check if data is empty
115            if dependencies_data is None:
116
117                self.logger.debug(f"Package {package_name} not found")
118                return None
119            else:
120                self.logger.debug(f"Package {package_name} found")
121
122        except Exception as e:
123            self.logger.error(f"Exception while obtaining {package_name} dependencies")
124            return None
125
126        finally:
127            # Restore the original standard output
128            sys.stdout.close()
129            sys.stdout = stdout 
130
131        version = dependencies_data["dependencies_for_version"]
132        url = dependencies_data["package_manager_url"]
133
134
135        # Obtain the dependencies (dependencies field, project_name)
136        # Obtain the dependency version (atest_stable field)
137        dependencies = []
138
139        for dependency in dependencies_data["dependencies"]:
140            dependency_name = dependency["project_name"]
141            dependency_version = dependency["latest_stable"]
142
143            dependency_data = {
144                "name": dependency_name,
145                "version": dependency_version,
146            }
147
148            dependencies.append(dependency_data)
149
150        return {
151            "name": package_name,
152            "version": version,
153            "dependencies": dependencies,
154            "url": url
155        }
156        
157    def obtain_packages_data(self, package_names: List[str]) -> List[dict]:
158        '''
159        Obtains the data of a list of package names from the data source.
160
161        Returns
162        -------
163        List[dict]
164            The data of the packages as a list of dictionaries
165
166        Example
167        -------
168        >>> data_source = LibrariesioDataSource('name', 'description', 'platform')
169        >>> data_source.obtain_packages_data(['package1', 'package2'])
170        [{'name': 'package1', 'version': '1.0.0', 'dependencies': ['package1', 'package2'], 'url': 'www.example.com'}, 
171        {'name': 'package2', 'version': '1.0.0', 'dependencies': ['package1', 'package2'], 'url': 'www.example.com'}]
172        '''
173
174        packages_data = []
175
176        for package_name in package_names:
177            if package_data := self.obtain_package_data(package_name):
178                packages_data.append(package_data)
179
180        return packages_data

Data source for the Libraries.io API

  • The API key must be set as an environment variable with the name LIBRARIES_API_KEY
  • The class will raise an exception if the API key is not found
  • The API key can be set in the configuration file
  • The API key can be obtained from the user's profile in Libraries.io
LibrariesioDataSource(platform: str)
38    def __init__(self, platform: str):
39        """
40        Constructor of the class
41
42        Parameters
43        ----------
44        platform : str
45            Platform of the data source to search for packages
46
47        Raises
48        ------
49        LibrariesIoException
50            If the search object cannot be created
51        """
52        super().__init__()
53        self.platform = platform
54
55        # Create the search object
56        try:
57            self.search = Search()
58        except Exception as e:
59            pass

Constructor of the class

Parameters
  • platform (str): Platform of the data source to search for packages
Raises
  • LibrariesIoException: If the search object cannot be created
def obtain_package_names(self) -> List[str]:
61    def obtain_package_names(self) -> List[str]:
62        """
63        Obtains the list of packages from the data source.
64        """
65        raise NotImplementedError

Obtains the list of packages from the data source.

def obtain_package_data(self, package_name: str) -> Optional[dict]:
 67    def obtain_package_data(self, package_name:str) -> Union[dict, None]:
 68        """
 69        Obtains the data of a package from the data source.
 70
 71        Parameters
 72        ----------
 73        package_name : str
 74            Name of the package
 75
 76        Returns
 77        -------
 78        dict
 79            Dictionary with the package data
 80        None
 81            If the package is not found
 82            
 83        Example
 84        -------
 85        >>> data_source = LibrariesioDataSource('name', 'description', 'platform')
 86        >>> data_source.obtain_package_data('package_name')
 87        {'name': 'package_name', 'version': '1.0.0', 'dependencies': ['package1', 'package2'], 'url': 'www.example.com'}
 88        """
 89
 90        # Get the package version and url
 91        self.logger.debug(f"Obtaining data of {package_name}")
 92
 93        # Redirect the output to /dev/null to avoid printing the output of the search (pybraries bug)
 94        stdout = sys.stdout     # Keep the standard output backed up
 95        sys.stdout = open('/dev/null', 'w')
 96
 97        try:
 98            dependencies_data = self.search.project_dependencies(
 99                platforms=self.platform, project=package_name
100            )
101
102            # Check if data is empty
103            if dependencies_data is None:
104
105                # Sleep for 3 second to avoid the API rate limit
106                self.logger.debug(f"Package {package_name} not found. Sleeping for 4 seconds for the API rate limit")
107                time.sleep(4)
108
109            # Try again
110            dependencies_data = self.search.project_dependencies(
111                platforms=self.platform, project=package_name
112            )
113
114            # Check if data is empty
115            if dependencies_data is None:
116
117                self.logger.debug(f"Package {package_name} not found")
118                return None
119            else:
120                self.logger.debug(f"Package {package_name} found")
121
122        except Exception as e:
123            self.logger.error(f"Exception while obtaining {package_name} dependencies")
124            return None
125
126        finally:
127            # Restore the original standard output
128            sys.stdout.close()
129            sys.stdout = stdout 
130
131        version = dependencies_data["dependencies_for_version"]
132        url = dependencies_data["package_manager_url"]
133
134
135        # Obtain the dependencies (dependencies field, project_name)
136        # Obtain the dependency version (atest_stable field)
137        dependencies = []
138
139        for dependency in dependencies_data["dependencies"]:
140            dependency_name = dependency["project_name"]
141            dependency_version = dependency["latest_stable"]
142
143            dependency_data = {
144                "name": dependency_name,
145                "version": dependency_version,
146            }
147
148            dependencies.append(dependency_data)
149
150        return {
151            "name": package_name,
152            "version": version,
153            "dependencies": dependencies,
154            "url": url
155        }

Obtains the data of a package from the data source.

Parameters
  • package_name (str): Name of the package
Returns
  • dict: Dictionary with the package data
  • None: If the package is not found
Example
>>> data_source = LibrariesioDataSource('name', 'description', 'platform')
>>> data_source.obtain_package_data('package_name')
{'name': 'package_name', 'version': '1.0.0', 'dependencies': ['package1', 'package2'], 'url': 'www.example.com'}
def obtain_packages_data(self, package_names: List[str]) -> List[dict]:
157    def obtain_packages_data(self, package_names: List[str]) -> List[dict]:
158        '''
159        Obtains the data of a list of package names from the data source.
160
161        Returns
162        -------
163        List[dict]
164            The data of the packages as a list of dictionaries
165
166        Example
167        -------
168        >>> data_source = LibrariesioDataSource('name', 'description', 'platform')
169        >>> data_source.obtain_packages_data(['package1', 'package2'])
170        [{'name': 'package1', 'version': '1.0.0', 'dependencies': ['package1', 'package2'], 'url': 'www.example.com'}, 
171        {'name': 'package2', 'version': '1.0.0', 'dependencies': ['package1', 'package2'], 'url': 'www.example.com'}]
172        '''
173
174        packages_data = []
175
176        for package_name in package_names:
177            if package_data := self.obtain_package_data(package_name):
178                packages_data.append(package_data)
179
180        return packages_data

Obtains the data of a list of package names from the data source.

Returns
  • List[dict]: The data of the packages as a list of dictionaries
Example
>>> data_source = LibrariesioDataSource('name', 'description', 'platform')
>>> data_source.obtain_packages_data(['package1', 'package2'])
[{'name': 'package1', 'version': '1.0.0', 'dependencies': ['package1', 'package2'], 'url': 'www.example.com'}, 
{'name': 'package2', 'version': '1.0.0', 'dependencies': ['package1', 'package2'], 'url': 'www.example.com'}]