You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

cppython

Package Overview
Dependencies
Maintainers
1
Versions
121
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cppython - pypi Package Compare versions

Comparing version
0.7.1.dev31
to
0.7.1.dev32
+131
-70
cppython/builder.py
"""Everything needed to build a CPPython project
"""
import logging
from importlib import metadata
from inspect import getmodule
from logging import Logger
from pathlib import Path
from typing import Any
from cppython_core.exceptions import ConfigError, PluginError
from cppython_core.exceptions import PluginError
from cppython_core.plugin_schema.generator import Generator

@@ -23,2 +23,3 @@ from cppython_core.plugin_schema.provider import Provider

resolve_provider,
resolve_scm,
)

@@ -29,6 +30,7 @@ from cppython_core.schema import (

CPPythonGlobalConfiguration,
CPPythonLocalConfiguration,
DataPluginT,
PEP621Configuration,
PEP621Data,
ProjectConfiguration,
ProjectData,
PyProject,
)

@@ -43,87 +45,101 @@

def generate_core_data(
self,
configuration: ProjectConfiguration,
pep621_configuration: PEP621Configuration,
cppython_configuration: CPPythonLocalConfiguration,
plugin_build_date: PluginBuildData,
) -> CoreData:
"""Parses and returns resolved data from all configuration sources
def setup_logger(self, project_configuration: ProjectConfiguration) -> None:
"""_summary_
Args:
configuration: Input configuration
pep621_configuration: Project table configuration
cppython_configuration: Tool configuration
plugin_build_date: Build data
project_configuration: _description_
"""
# Default logging levels
levels = [logging.WARNING, logging.INFO, logging.DEBUG]
Raises:
ConfigError: Raised if data cannot be parsed
# Add default output stream
self.logger.addHandler(logging.StreamHandler())
self.logger.setLevel(levels[project_configuration.verbosity])
self.logger.info("Logging setup complete")
def generate_project_data(self, project_configuration: ProjectConfiguration) -> ProjectData:
"""_summary_
Args:
project_configuration: _description_
Returns:
The resolved core object
_description_
"""
global_configuration = CPPythonGlobalConfiguration()
return resolve_project_configuration(project_configuration)
project_data = resolve_project_configuration(configuration)
def generate_data_plugins(self, pyproject: PyProject) -> PluginBuildData:
"""_summary_
try:
pep621_data = resolve_pep621(pep621_configuration, configuration)
Args:
pyproject: _description_
except ConfigError:
configuration.version = self.extract_scm_version(configuration.pyproject_file.parent)
pep621_data = resolve_pep621(pep621_configuration, configuration)
Returns:
_description_
"""
cppython_data = resolve_cppython(cppython_configuration, global_configuration, project_data, plugin_build_date)
raw_generator_plugins = self.find_generators()
generator_plugins = self.filter_plugins(
raw_generator_plugins,
pyproject.tool.cppython.generator_name,
"Generator",
)
return CoreData(project_data=project_data, pep621_data=pep621_data, cppython_data=cppython_data)
raw_provider_plugins = self.find_providers()
provider_plugins = self.filter_plugins(
raw_provider_plugins,
pyproject.tool.cppython.provider_name,
"Provider",
)
def extract_scm_version(self, path: Path) -> str:
"""Locates an available SCM plugin that can report version information about the given path
# Solve the messy interactions between plugins
generator_type, provider_type = self.solve(generator_plugins, provider_plugins)
return PluginBuildData(generator_type=generator_type, provider_type=provider_type)
def generate_pep621_data(
self, pyproject: PyProject, project_configuration: ProjectConfiguration, scm: SCM | None
) -> PEP621Data:
"""_summary_
Args:
path: The directory to query
pyproject: _description_
project_configuration: _description_
scm: _description_
Raises:
PluginError: If no SCM plugin can be found
Returns:
A version token
_description_
"""
return resolve_pep621(pyproject.project, project_configuration, scm)
group = "SCM"
group_lower = group.lower()
def generate_core_data(
self,
project_data: ProjectData,
pyproject: PyProject,
pep621_data: PEP621Data,
plugin_build_date: PluginBuildData,
) -> CoreData:
"""Parses and returns resolved data from all configuration sources
scm_types: list[type[SCM]] = []
Args:
project_data: Project data
pyproject: TODO
pep621_data: TODO
plugin_build_date: TODO
if not (entries := list(metadata.entry_points(group=f"cppython.{group_lower}"))):
raise PluginError("No SCM plugin found")
Raises:
ConfigError: Raised if data cannot be parsed
# Filter entries
for entry_point in entries:
plugin_type = entry_point.load()
if not issubclass(plugin_type, SCM):
self.logger.warning(
f"Found incompatible plugin. The '{resolve_name(plugin_type)}' plugin must be an instance of"
f" '{group_lower}'"
)
else:
scm_types.append(plugin_type)
Returns:
The resolved core object
"""
# Deduce the SCM repository
plugin = None
for scm_type in scm_types:
scm = scm_type()
if scm.supported(path):
plugin = scm
break
global_configuration = CPPythonGlobalConfiguration()
if not plugin:
raise PluginError("No applicable SCM plugin found for the given path")
cppython_data = resolve_cppython(pyproject.tool.cppython, global_configuration, project_data, plugin_build_date)
if (version := plugin.version(path)) is None:
raise PluginError("Project has no version information")
return CoreData(project_data=project_data, pep621_data=pep621_data, cppython_data=cppython_data)
return version
def find_generators(self) -> list[type[Generator]]:

@@ -194,3 +210,3 @@ """_summary_

def filter_plugins(
self, plugin_types: list[type[DataPluginT]], directory: Path, pinned_name: str | None, group_name: str
self, plugin_types: list[type[DataPluginT]], pinned_name: str | None, group_name: str
) -> list[type[DataPluginT]]:

@@ -201,3 +217,2 @@ """Finds and filters data plugins

plugin_types: The plugin type to lookup
directory: The data to query support for the filtered plugins
pinned_name: The configuration name

@@ -228,7 +243,6 @@ group_name: The group name

for loaded_type in plugin_types:
if loaded_type.supported(directory):
self.logger.warning(
f"A {group_name} plugin is supported: {resolve_name(loaded_type)} from {getmodule(loaded_type)}"
)
supported_types.append(loaded_type)
self.logger.warning(
f"A {group_name} plugin is supported: {resolve_name(loaded_type)} from {getmodule(loaded_type)}"
)
supported_types.append(loaded_type)

@@ -272,2 +286,49 @@ # Fail

def create_scm(
self,
project_data: ProjectData,
) -> SCM | None:
"""_summary_
Args:
project_data: _description_
Raises:
PluginError: Ya
Returns:
_description_
"""
group = "scm"
path = project_data.pyproject_file.parent
scm_types: list[type[SCM]] = []
if not (entries := list(metadata.entry_points(group=f"cppython.{group}"))):
raise PluginError("No SCM plugin found")
# Filter entries
for entry_point in entries:
plugin_type = entry_point.load()
if not issubclass(plugin_type, SCM):
self.logger.warning(
f"Found incompatible plugin. The '{resolve_name(plugin_type)}' plugin must be an instance of"
f" '{group}'"
)
else:
scm_types.append(plugin_type)
# Deduce the SCM repository
plugin = None
for scm_type in scm_types:
if scm_type.features(path).repository:
scm_data = resolve_scm(project_data)
plugin = scm_type(scm_data)
break
if not plugin:
self.logger.error("No applicable SCM plugin found for the given path")
return plugin
def create_generator(

@@ -274,0 +335,0 @@ self, core_data: CoreData, generator_configuration: dict[str, Any], generator_type: type[Generator]

@@ -5,3 +5,7 @@ """Git SCM plugin"""

from cppython_core.plugin_schema.scm import SCM
from cppython_core.plugin_schema.scm import (
SCM,
SCMPluginGroupData,
SupportedSCMFeatures,
)
from cppython_core.schema import Information

@@ -15,20 +19,24 @@ from dulwich.errors import NotGitRepository

def __init__(self, group_data: SCMPluginGroupData) -> None:
self.group_data = group_data
@staticmethod
def supported(directory: Path) -> bool:
"""Queries repository status of a path
def features(directory: Path) -> SupportedSCMFeatures:
"""Broadcasts the shared features of the SCM plugin to CPPython
Args:
directory: The input path to query
directory: The root directory where features are evaluated
Returns:
Whether the given path is a repository root
The supported features
"""
is_repository = True
try:
Repo(str(directory))
return True
except NotGitRepository:
return False
is_repository = False
return SupportedSCMFeatures(repository=is_repository)
@staticmethod

@@ -43,7 +51,7 @@ def information() -> Information:

def version(self, path: Path) -> str:
def version(self, directory: Path) -> str:
"""Extracts the system's version metadata
Args:
path: The repository path
directory: The repository path

@@ -50,0 +58,0 @@ Returns:

@@ -9,3 +9,4 @@ """Manages data flow to and from plugins

from cppython_core.exceptions import ConfigError, PluginError
from cppython_core.resolution import PluginBuildData, resolve_name
from cppython_core.plugin_schema.scm import SCM
from cppython_core.resolution import resolve_name
from cppython_core.schema import CoreData, Interface, ProjectConfiguration, PyProject

@@ -22,46 +23,29 @@ from pydantic import ValidationError

def __init__(
self, configuration: ProjectConfiguration, interface: Interface, pyproject_data: dict[str, Any]
self, project_configuration: ProjectConfiguration, interface: Interface, pyproject_data: dict[str, Any]
) -> None:
self._enabled = False
self._interface = interface
# Default logging levels
levels = [logging.WARNING, logging.INFO, logging.DEBUG]
# Add default output stream
self.logger = logging.getLogger("cppython")
self.logger.addHandler(logging.StreamHandler())
self.logger.setLevel(levels[configuration.verbosity])
self.logger.info("Initializing project")
try:
pyproject = PyProject(**pyproject_data)
builder = Builder(self.logger)
builder.setup_logger(project_configuration)
raw_generator_plugins = builder.find_generators()
generator_plugins = builder.filter_plugins(
raw_generator_plugins,
configuration.pyproject_file.parent,
pyproject.tool.cppython.generator_name,
"Generator",
)
self.logger.info("Initializing project")
raw_provider_plugins = builder.find_providers()
provider_plugins = builder.filter_plugins(
raw_provider_plugins,
configuration.pyproject_file.parent,
pyproject.tool.cppython.provider_name,
"Provider",
)
project_data = builder.generate_project_data(project_configuration)
self._scm = builder.create_scm(project_data)
# Solve the messy interactions between plugins
generator_type, provider_type = builder.solve(generator_plugins, provider_plugins)
pyproject = PyProject(**pyproject_data)
pyproject_build_data = PluginBuildData(generator_type=generator_type, provider_type=provider_type)
plugin_build_data = builder.generate_data_plugins(pyproject)
# Once the plugins are resolved, the core data is complete and can be generated
pep621_data = builder.generate_pep621_data(pyproject, project_configuration, self._scm)
self._core_data = builder.generate_core_data(
configuration, pyproject.project, pyproject.tool.cppython, pyproject_build_data
project_data,
pyproject,
pep621_data,
plugin_build_data,
)

@@ -71,5 +55,7 @@

self._generator = builder.create_generator(
self.core_data, pyproject.tool.cppython.generator, generator_type
self._core_data, pyproject.tool.cppython.generator, plugin_build_data.generator_type
)
self._provider = builder.create_provider(self.core_data, pyproject.tool.cppython.provider, provider_type)
self._provider = builder.create_provider(
self._core_data, pyproject.tool.cppython.provider, plugin_build_data.provider_type
)

@@ -97,10 +83,19 @@ except ConfigError:

@property
def core_data(self) -> CoreData:
def core_data(self) -> CoreData | None:
"""Core data
Returns:
Core data
Core data, if enabled
"""
return self._core_data
return self._core_data if self._enabled else None
@property
def scm(self) -> SCM | None:
"""SCM
Returns:
SCM, if enabled
"""
return self._scm if self._enabled else None
async def download_provider_tools(self) -> None:

@@ -113,3 +108,3 @@ """Download the provider tooling if required"""

name = resolve_name(type(self._provider))
base_path = self.core_data.cppython_data.install_path
base_path = self._core_data.cppython_data.install_path

@@ -116,0 +111,0 @@ path = base_path / name

Metadata-Version: 2.1
Name: cppython
Version: 0.7.1.dev31
Version: 0.7.1.dev32
Summary: A Python management solution for C++ dependencies

@@ -5,0 +5,0 @@ License: MIT

@@ -19,3 +19,3 @@ [project]

]
version = "0.7.1.dev31"
version = "0.7.1.dev32"

@@ -22,0 +22,0 @@ [project.license-files]