File indexing completed on 2024-04-21 07:39:08

0001 # -*- coding: utf-8 -*-
0002 #
0003 # SPDX-FileCopyrightText: 2016 Olivier Churlaud <olivier@churlaud.com>
0004 #
0005 # SPDX-License-Identifier: BSD-2-Clause
0006 
0007 import logging
0008 import os.path
0009 import string
0010 from kapidox import utils
0011 
0012 ## @package kapidox.models
0013 #
0014 # Contains the classes representing the objects used by kapidox
0015 #
0016 
0017 class Library(object):
0018     """ Library
0019     """
0020 
0021     def __init__(self, metainfo, products, platforms, all_maintainers):
0022         """
0023             Constructor of the Library object
0024             
0025             Args:
0026                 metainfo:     (dict) dictionary describing a library
0027                 products:     (list of Products) list of all already created products
0028                 platforms:    (dict) dictionary of all platforms for which the library
0029                               is available, where the key is a platform and the value
0030                               is a restriction. For instance:  
0031                                 { 
0032                                     'Linux': '', 
0033                                     'Windows': 'Tested with Windows 10 only'
0034                                 }
0035                               would work.
0036                 all_maintainers: (dict of dict)  all possible maintainers, where the main key
0037                               is a username/unique pseudo, and the key is a dictionary of name,
0038                               email address. For example:
0039                                 {
0040                                     'username01': { 'name': 'Paul Developer', 'email': 'mail@example.com' },
0041                                     'username02': { 'name': 'Marc Developer2', 'email': 'mail2@example.com' }
0042                                 }
0043                               would work. 
0044                                 
0045         """
0046         self.product = None        
0047         self.subproduct = None
0048 
0049         if 'group' in metainfo:
0050             productname = metainfo['group']
0051             self.part_of_group = True
0052         else:
0053             productname = metainfo['name']
0054             self.part_of_group = False
0055         if utils.serialize_name(productname) not in products:
0056             productname = metainfo['name']
0057             del metainfo['group']
0058             products[utils.serialize_name(metainfo['name'])] = Product(metainfo, all_maintainers)
0059             self.part_of_group = False
0060             logging.warning("Group of {fancyname} not found: dropped.".format_map(metainfo))
0061         self.product = products[utils.serialize_name(productname)]
0062         if self.product is None:
0063             raise ValueError("'{name}' does not belong to a product."
0064                              .format_map(metainfo))
0065 
0066         if 'subgroup' in metainfo and self.part_of_group:
0067             for sp in self.product.subproducts:
0068                 if sp.name == utils.serialize_name(metainfo['subgroup']):
0069                     self.subproduct = sp
0070             if self.subproduct is None:
0071                 logging.warning("Subgroup {subgroup} of library {name} not documented, subgroup will be None"
0072                                 .format_map(metainfo))
0073 
0074         if self.subproduct is not None:
0075             self.parent = self.subproduct
0076             self.subproduct.libraries.append(self)
0077         else:
0078             self.parent = self.product
0079         self.product.libraries.append(self)
0080 
0081         self.metainfo = metainfo
0082         self.name = metainfo['name']
0083         self.fancyname = metainfo['fancyname']
0084         self.description = metainfo.get('description')
0085         self.maintainers = utils.set_maintainers(metainfo.get('maintainer'), all_maintainers)
0086         self.platforms = platforms
0087         self.outputdir = self._set_outputdir(self.part_of_group)
0088         self.href = '../' + self.outputdir.lower() + '/html/index.html'
0089         self.path = metainfo['path']
0090         self.srcdirs = utils.tolist(metainfo.get('public_source_dirs', ['src']))
0091         self.docdir = utils.tolist(metainfo.get('public_doc_dir', ['docs']))
0092         if 'public_example_dirs' in metainfo:
0093             self.exampledirs = utils.tolist(metainfo.get('public_example_dirs', ['examples']))
0094         else:
0095             # backward compat
0096             self.exampledirs = utils.tolist(metainfo.get('public_example_dir', ['examples']))
0097         self.dependency_diagram = None
0098         self.type = metainfo.get('type', '')
0099         self.portingAid = metainfo.get('portingAid', False)
0100         self.deprecated = metainfo.get('deprecated', False)
0101         self.libraries = metainfo.get('libraries', [])
0102         self.cmakename = metainfo.get('cmakename', '')
0103         self.irc = metainfo.get('irc', self.product.irc)
0104         self.mailinglist = metainfo.get('mailinglist', self.product.mailinglist)
0105         self.repopath = utils.set_repopath(metainfo['repo_id'])
0106 
0107     def _extend_parent(self, metainfo, key, key_obj, default):
0108         if key in metainfo:
0109             return metainfo[key]
0110         elif getattr(self.product, key_obj) is not None:
0111             return getattr(self.product, key_obj)
0112         else:
0113             return default
0114 
0115     def _set_outputdir(self, grouped):
0116         outputdir = self.name
0117         if grouped:
0118             outputdir = os.path.join(self.product.outputdir, outputdir)
0119         return outputdir.lower()
0120 
0121 
0122 class Product(object):
0123     """ Product
0124     """
0125 
0126     # TODO: If no name and no group, it will fail !
0127     def __init__(self, metainfo, all_maintainers):
0128         """
0129             Constructor of the Product object
0130             
0131             Args:
0132                 metainfo:     (dict) dictionary describing a product
0133                 all_maintainers: (dict of dict)  all possible maintainers, where the main key
0134                               is a username/unique pseudo, and the key is a dictionary of name,
0135                               email address. For example:
0136                                 {
0137                                     'username01': { 'name': 'Paul Developer', 'email': 'mail@example.com' },
0138                                     'username02': { 'name': 'Marc Developer2', 'email': 'mail2@example.com' }
0139                                 }
0140                               would work. 
0141                                 
0142         """
0143         
0144         self.metainfo = metainfo
0145         self.parent = None
0146         # if there is a group, the product is the group
0147         # else the product is directly the library
0148             
0149         if 'group_info' in metainfo:
0150             self.name = utils.serialize_name(metainfo['group_info'].get('name', metainfo.get('group')))
0151             self.fancyname = metainfo['group_info'].get('fancyname', string.capwords(self.name))
0152             self.description = metainfo['group_info'].get('description')
0153             self.long_description = metainfo['group_info'].get('long_description', [])
0154             self.maintainers = utils.set_maintainers(metainfo['group_info'].get('maintainer'),
0155                                                      all_maintainers)
0156             self.platforms = metainfo['group_info'].get('platforms')
0157             self.outputdir = self.name
0158             self.href = self.outputdir + '/index.html'
0159             self.logo_url_src = self._set_logo_src(metainfo['path'],
0160                                                    metainfo['group_info'])
0161             self.logo_url = self._set_logo()
0162             self.libraries = []  # We'll set this later
0163             self.subgroups = []  # We'll set this later
0164             self.irc = metainfo['group_info'].get('irc', 'kde-devel')
0165             self.mailinglist = metainfo['group_info'].get('mailinglist', 'kde-devel')
0166             self.subproducts = self._extract_subproducts(metainfo['group_info'])
0167             self.part_of_group = True
0168 
0169         elif 'group' not in metainfo:
0170             self.name = utils.serialize_name(metainfo['name'])
0171             self.fancyname = metainfo['fancyname']
0172             self.description = metainfo.get('description')
0173             self.maintainers = utils.set_maintainers(metainfo.get('maintainer'), all_maintainers)
0174             self.platforms = [x['name'] for x in metainfo.get('platforms', [{'name': None}])]
0175             self.outputdir = self.name
0176             self.href = self.outputdir + '/html/index.html'
0177             self.logo_url_src = self._set_logo_src(metainfo['path'], metainfo)
0178             self.logo_url = self._set_logo()
0179             self.libraries = []
0180             self.irc = None
0181             self.mailinglist = None
0182             self.part_of_group = False
0183         else:
0184             raise ValueError("I do not recognize a product in {name}."
0185                              .format_map(metainfo))
0186 
0187     def _extract_subproducts(self, groupinfo):
0188         subproducts = []
0189         if 'subgroups' in groupinfo:
0190             for sg in groupinfo['subgroups']:
0191                 if 'name' in sg:
0192                     subproducts.append(Subproduct(sg, self))
0193         return subproducts
0194 
0195     def _set_logo(self):
0196         if self.logo_url_src is not None:
0197             filename, ext = os.path.splitext(self.logo_url_src)
0198             return os.path.join(self.outputdir, self.name) + ext
0199         else:
0200             return None
0201 
0202     def _set_logo_src(self, path, dct):
0203         defined_not_found = False
0204         if 'logo' in dct:
0205             logo_url = os.path.join(path, dct['logo'])
0206             if os.path.isfile(logo_url):
0207                 return logo_url
0208             else:
0209                 defined_not_found = True
0210 
0211         logo_url = os.path.join(path, 'logo.png')
0212         if os.path.isfile(logo_url):
0213             if defined_not_found:
0214                 logging.warning(f'Defined {self.fancyname} logo file does not exist, set back to found logo.png')
0215             return logo_url
0216 
0217         if defined_not_found:
0218             logging.warning(f'Defined {self.fancyname} logo file does not exist, set back to None')
0219 
0220         return None
0221 
0222 
0223 class Subproduct(object):
0224     """ Subproduct
0225     """
0226     def __init__(self, spinfo, product):
0227         """
0228             Constructor of the Subproduct object
0229             
0230             Args:
0231                 spinfo:       (dict) description of the subproduct. It is not more than:
0232                 {
0233                     'name': 'Subproduct Name',
0234                     'description': 'This subproduct does this and that',
0235                     'order': 3, # this is optional
0236                 }
0237                 for example.
0238                 product:      (Product) the product it is part of.
0239         """
0240         self.fancyname = spinfo['name']
0241         self.name = utils.serialize_name(spinfo['name'])
0242         self.description = spinfo.get('description')
0243         self.order = spinfo.get('order', 99)  # If no order, go to end
0244         self.libraries = []
0245         self.product = product
0246         self.parent = product