Source code for derobertis_cv.pltemplates.software.project

from datetime import datetime
from typing import List, Optional, Sequence, Union

import pyexlatex as pl
import pyexlatex.layouts as ll
from pyexlatex.models.item import ItemBase

from derobertis_cv.pltemplates.logo import HasLogo


[docs] class SoftwareProject(HasLogo, pl.Template):
[docs] def __init__( self, title: str, description: str, display_title: Optional[ Union[str, ItemBase, Sequence[Union[str, ItemBase]]] ] = None, created: Optional[datetime] = None, updated: Optional[datetime] = None, version: Optional[str] = None, loc: Optional[int] = None, commits: Optional[int] = None, url: Optional[str] = None, compact: bool = False, github_url: Optional[str] = None, docs_url: Optional[str] = None, logo_url: Optional[str] = None, package_directory: Optional[str] = None, logo_svg_text: Optional[str] = None, logo_base64: Optional[str] = None, logo_fa_icon_class_str: Optional[str] = None, ): self.title = title self.display_title = display_title self.description = description self.created = created self.updated = updated self.version = version self.loc = loc self.commits = commits self.url = url self.compact = compact self.github_url = github_url self.docs_url = docs_url self.logo_url = logo_url self.package_directory = package_directory self.logo_svg_text = logo_svg_text self.logo_base64 = logo_base64 self.logo_fa_icon_class_str = logo_fa_icon_class_str self.contents = self._get_contents() super().__init__()
@property def url(self) -> Optional[str]: try: return self._url except AttributeError: return self.github_url @url.setter def url(self, value: Optional[str]): if value is not None: self._url = value def _get_contents(self): headers = self._get_header() description_area = self._get_description_area() all_contents = [ *headers, *description_area, ] return pl.NoPageBreak(all_contents) def _get_description_area(self): if not self.description: return [] return [ pl.OutputLineBreak(size_adjustment="8pt"), self.description, pl.OutputLineBreak(size_adjustment="-3pt"), ] def _get_header(self): if self.compact: return [ll.HorizontallySpaced([self._title_obj, self._loc_commits_obj])] title_created_line = ll.HorizontallySpaced( [ self._title_obj, f"Created: {self._date_str(self.created)}" if self.created else None, ] ) loc_commits_updated_line = ll.HorizontallySpaced( [ self._loc_commits_obj, f"Updated: {self._date_str(self.updated)}" if self.updated else None, ] ) return [title_created_line, pl.OutputLineBreak(), loc_commits_updated_line] def _date_str(self, dt: datetime) -> str: return f"{dt.date()}" @property def _loc_str(self) -> str: if self.loc is None: return "" if self.loc < 1000: return f"{self.loc} LOC" # Convert to thousands format with k, e.g. 20k lines thousands = round(self.loc / 1000, 0) return f"{thousands:.0f}k LOC" @property def _title_obj(self) -> Union[pl.Bold, List[Union[pl.Hyperlink, pl.Bold]]]: if self.display_title: title_content = f"{self.title} ({self.display_title})" else: title_content = self.title if self.url is None: title = pl.Bold(title_content) else: # Handle hyperlink styled_title = pl.TextColor( self.title, color=pl.RGB(50, 82, 209, color_name="darkblue") ) styled_title = pl.Bold(styled_title) title = [ pl.Hyperlink(self.url, styled_title), pl.Bold(f" ({self.display_title})") if self.display_title else None, ] title = [t for t in title if t is not None] self.add_data_from_content(title) return title @property def _loc_commits_obj(self) -> Optional[pl.Italics]: if not (self.loc or self.commits): return None loc_commits_str = "" if self.loc: loc_commits_str += self._loc_str if self.loc and self.commits: loc_commits_str += ", " if self.commits: loc_commits_str += f"{self.commits} commits" return pl.Italics(loc_commits_str)
[docs] @classmethod def from_project_report_dict(cls, pr_dict: dict, use_full_loc: bool = True): create_dict = {} direct_attrs = [ "created", "updated", "description", "package_directory", "url", "docs_url", "github_url", "logo_url", "logo_svg_text", "version", ] if use_full_loc: loc_attr = "full_lines" else: loc_attr = "lines" map_attrs = {"name": "title", loc_attr: "loc", "num_commits": "commits"} for attr in direct_attrs: create_dict[attr] = pr_dict.get(attr) for pr_attr, create_attr in map_attrs.items(): create_dict[create_attr] = pr_dict[pr_attr] # Fill description with docstring if none if not create_dict["description"]: create_dict["description"] = pr_dict.get("docstring") return cls(**create_dict) # type: ignore
[docs] @classmethod def list_from_project_report_dict_list( cls, pr_dict_list: List[dict], use_full_loc: bool = True ): return [ cls.from_project_report_dict(pr_dict, use_full_loc=use_full_loc) for pr_dict in pr_dict_list ]