Source code for projectreport.analyzer.parsers.python.setup_cfg

import ast
import configparser
from configparser import ConfigParser, ParsingError
from pathlib import Path
from typing import List, Optional, Union

from cached_property import cached_property

from projectreport.analyzer.parsers.base import Parser
from projectreport.analyzer.parsers.python.base import PythonParser
from projectreport.analyzer.parsers.python.classifier_topics import (
    get_topics_from_classifiers,
    get_topics_from_classifiers_str,
)
from projectreport.version import Version

# NOTE: This does not use the PythonParser as a base class because this is not a Python file
# being parsed (it is an ini file with the cfg extension)


[docs]class PythonSetupCfgParser(Parser): @cached_property def parsed(self) -> Optional[ConfigParser]: # Try to load the file as an ini file using configparser try: config = ConfigParser() config.read(self.path) return config except ParsingError: return None @cached_property def docstring(self) -> Optional[str]: if self.parsed is None: return None # Return the description value from the metadata section, if it exists return _get_string_from_config(self.parsed, "metadata", "description") @cached_property def version(self) -> Optional[Version]: if self.parsed is None: return None # Return the version value from the metadata section, if it exists version_str = _get_string_from_config(self.parsed, "metadata", "version") if version_str is None: return None return Version.from_str(version_str) @cached_property def topics(self) -> Optional[List[str]]: if self.parsed is None: return None classifiers = _get_from_config(self.parsed, "metadata", "classifiers") if classifiers is None: return None topics = get_topics_from_classifiers_str(classifiers) return topics
[docs] @classmethod def matches_path(cls, path: str) -> bool: return Path(path).name == "setup.cfg"
def _get_from_config(config: ConfigParser, section: str, option: str) -> Optional[str]: # Try to get the value from the config try: return config.get(section, option) except ( KeyError, AttributeError, configparser.NoOptionError, configparser.NoSectionError, ): return None def _get_string_from_config( config: ConfigParser, section: str, option: str ) -> Optional[str]: # Try to get the value from the config str_with_quotes = _get_from_config(config, section, option) if str_with_quotes is None: return None # Remove the quotes from the string, but only if they exist if str_with_quotes.startswith('"') and str_with_quotes.endswith('"'): return str_with_quotes[1:-1] elif str_with_quotes.startswith("'") and str_with_quotes.endswith("'"): return str_with_quotes[1:-1] else: return str_with_quotes