Пример #1
0
def gen_cobom_csv(projfolder, namebase, force=False):
    """
    Generates a CSV file in the
    :mod:`tendril.boms.outputbase.CompositeOutputBom` format, including the
    BOMs of the all the defined configurations of the project. This function
    uses a :mod:`csv.writer` instead of rendering a jinja2 template.

    It also generates configdocs for all the defined configurations of the
    project, using :func:`gen_confpdf`.

    :param projfolder: The gEDA project folder.
    :type projfolder: str
    :param namebase: The project name.
    :type namebase: str
    :param force: Regenerate even if up-to-date.
    :type force: bool
    :return: The output file path.

    .. rubric:: Paths

    * Output Files :  ``<project_doc_folder>/confdocs/conf_boms.csv``
    * Also triggers : :func:`gen_confpdf` for all listed configurations.
    * Source Files : The project's schematic folder.

    """
    gpf = projfile.GedaProjectFile(projfolder)
    configfile = conffile.ConfigsFile(projfolder)
    sch_mtime = fsutils.get_folder_mtime(gpf.configsfile.schfolder)

    docfolder = get_project_doc_folder(projfolder)
    cobom_csv_path = path.join(docfolder, 'confdocs', 'conf-boms.csv')
    outf_mtime = fsutils.get_file_mtime(cobom_csv_path, fs=refdoc_fs)

    if not force and outf_mtime is not None and outf_mtime > sch_mtime:
        logger.debug('Skipping up-to-date ' + cobom_csv_path)
        return cobom_csv_path

    logger.info('Regenerating ' + cobom_csv_path + os.linesep +
                'Last modified : ' + str(sch_mtime) +
                '; Last Created : ' + str(outf_mtime))

    bomlist = []
    for cfn in configfile.configuration_names:
        gen_confpdf(projfolder, cfn, namebase, force=force)
        lbom = boms_electronics.import_pcb(projfolder)
        lobom = lbom.create_output_bom(cfn)
        bomlist.append(lobom)
    cobom = boms_outputbase.CompositeOutputBom(bomlist)

    with refdoc_fs.open(cobom_csv_path, 'wb') as f:
        writer = csv.writer(f)
        writer.writerow(['device'] +
                        [x.configname for x in cobom.descriptors])
        for line in cobom.lines:
            writer.writerow([line.ident] + line.columns)
Пример #2
0
def gen_cobom_csv(projfolder, namebase, force=False):
    """
    Generates a CSV file in the
    :mod:`tendril.boms.outputbase.CompositeOutputBom` format, including the
    BOMs of the all the defined configurations of the project. This function
    uses a :mod:`csv.writer` instead of rendering a jinja2 template.

    It also generates configdocs for all the defined configurations of the
    project, using :func:`gen_confpdf`.

    :param projfolder: The gEDA project folder.
    :type projfolder: str
    :param namebase: The project name.
    :type namebase: str
    :param force: Regenerate even if up-to-date.
    :type force: bool
    :return: The output file path.

    .. rubric:: Paths

    * Output Files :  ``<project_doc_folder>/confdocs/conf_boms.csv``
    * Also triggers : :func:`gen_confpdf` for all listed configurations.
    * Source Files : The project's schematic folder.

    """
    gpf = projfile.GedaProjectFile(projfolder)
    configfile = conffile.ConfigsFile(projfolder)
    sch_mtime = fsutils.get_folder_mtime(gpf.schfolder)

    docfolder = get_project_doc_folder(projfolder)
    cobom_csv_path = path.join(docfolder, 'confdocs', 'conf-boms.csv')
    outf_mtime = fsutils.get_file_mtime(cobom_csv_path, fs=refdoc_fs)

    if not force and outf_mtime is not None and outf_mtime > sch_mtime:
        logger.debug('Skipping up-to-date ' + cobom_csv_path)
        return cobom_csv_path

    logger.info('Regenerating ' + cobom_csv_path + os.linesep +
                'Last modified : ' + str(sch_mtime) +
                '; Last Created : ' + str(outf_mtime))

    bomlist = []
    for cfn in configfile.configuration_names:
        gen_confpdf(projfolder, cfn, namebase, force=force)
        lbom = boms_electronics.import_pcb(projfolder)
        lobom = lbom.create_output_bom(cfn)
        bomlist.append(lobom)
    cobom = boms_outputbase.CompositeOutputBom(bomlist)

    with refdoc_fs.open(cobom_csv_path, 'wb') as f:
        writer = csv.writer(f)
        writer.writerow(['device'] +
                        [x.configname for x in cobom.descriptors])
        for line in cobom.lines:
            writer.writerow([line.ident] + line.columns)
Пример #3
0
def gen_schpdf(projfolder, namebase, force=False):
    """
    Generates a PDF file of all the project schematics listed in the
    gEDA project file. This function does not ise jinja2 and latex. It
    relies on :func:`tendril.gedaif.gschem.conv_gsch2pdf` instead.

    :param projfolder: The gEDA project folder.
    :type projfolder: str
    :param namebase: The project name.
    :type namebase: str
    :param force: Regenerate even if up-to-date.
    :type force: bool
    :return: The output file path.

    .. rubric:: Paths

    * Output File :  ``<project_doc_folder>/<namebase>-schematic.pdf``
    * Source Files : The project's schematic folder.

    """
    gpf = projfile.GedaProjectFile(projfolder)
    sch_mtime = fsutils.get_folder_mtime(gpf.schfolder)

    configfile = conffile.ConfigsFile(projfolder)
    docfolder = get_project_doc_folder(projfolder)

    schpdfpath = path.join(docfolder, namebase + '-schematic.pdf')
    outf_mtime = fsutils.get_file_mtime(schpdfpath, fs=refdoc_fs)

    if not force and outf_mtime is not None and outf_mtime > sch_mtime:
        logger.debug('Skipping up-to-date ' + schpdfpath)
        return schpdfpath

    logger.info('Regenerating ' + schpdfpath + os.linesep +
                'Last modified : ' + str(sch_mtime) +
                '; Last Created : ' + str(outf_mtime))

    if configfile.rawconfig is not None:
        workspace_outpath = workspace_fs.getsyspath(schpdfpath)
        workspace_folder = workspace_fs.getsyspath(path.dirname(schpdfpath))
        workspace_fs.makedir(path.dirname(schpdfpath),
                             recursive=True, allow_recreate=True)
        pdffiles = []
        for schematic in gpf.schfiles:
            schfile = os.path.normpath(projfolder + '/schematic/' + schematic)
            pdffile = gschem.conv_gsch2pdf(schfile, workspace_folder)
            pdffiles.append(pdffile)
        pdf.merge_pdf(pdffiles, workspace_outpath)
        for pdffile in pdffiles:
            os.remove(pdffile)
        copyfile(workspace_fs, schpdfpath,
                 refdoc_fs, schpdfpath,
                 overwrite=True)
        return schpdfpath
Пример #4
0
    def get_bom_file(self):
        if not os.path.exists(self._cache_folder):
            os.makedirs(self._cache_folder)
            os.chmod(self._cache_folder, 0o777)

        bom_mtime = fsutils.get_file_mtime(self._cached_bom_path)
        source_mtime = fsutils.get_folder_mtime(self._source_folder)

        if self._use_cached is True and bom_mtime is not None \
                and source_mtime < bom_mtime:
            return open(self._cached_bom_path, 'r')
        else:
            self.generate_bom_file(self._temp_bom_path, **self._generator_args)
            shutil.copy(self._temp_bom_path, self._cached_bom_path)
            os.chmod(self._cached_bom_path, 0o666)
            return open(self._cached_bom_path, 'r')
Пример #5
0
    def get_bom_file(self):
        if not os.path.exists(self._cache_folder):
            os.makedirs(self._cache_folder)

        bom_mtime = fsutils.get_file_mtime(self._cached_bom_path)
        source_folder = os.path.join(self.projectfolder, self._basefolder)
        source_mtime = fsutils.get_folder_mtime(source_folder)

        if self._use_cached is True and bom_mtime is not None \
                and source_mtime < bom_mtime:
            return open(self._cached_bom_path, 'r')
        else:
            self.generate_bom_file(self._temp_bom_path,
                                   **self._generator_args)
            shutil.copy(self._temp_bom_path, self._cached_bom_path)
            return open(self._cached_bom_path, 'r')
Пример #6
0
def gen_pcb_gbr(projfolder, force=False):
    """
    Generates gerber files for the PCB provided by the gEDA project, and also
    creates a ``zip`` file of the generated gerbers.

    The pcbfile is the one listed in the gEDA project file, and the
    pcbname is the one specified in the
    :mod:`tendril.gedaif.conffile.ConfigsFile`.

    This function does not use jinja2 and latex. It relies on
    :func:`tendril.gedaif.pcb.conv_pcb2gbr` instead.

    :param projfolder: The gEDA project folder.
    :type projfolder: str
    :param force: Regenerate even if up-to-date.
    :type force: bool
    :return: The output file path.

    .. rubric:: Paths

    * Output Files :  ``<project_doc_folder>/../gerber/*``
    * Output Zip File : ``<project_doc_folder>/../<pcbfile>-gerber.zip``
    * Source Files : The project's `.pcb` file.

    """
    configfile = conffile.ConfigsFile(projfolder)
    gpf = projfile.GedaProjectFile(configfile.projectfolder)
    pcb_mtime = fsutils.get_file_mtime(
        os.path.join(configfile.projectfolder, 'pcb', gpf.pcbfile + '.pcb'))
    if pcb_mtime is None:
        logger.warning("PCB does not seem to exist for : " + projfolder)
        return
    docfolder = get_project_doc_folder(projfolder)
    imgfolder = os.path.join(docfolder, os.pardir, 'img')
    gbrfolder = os.path.join(docfolder, os.pardir, 'gerber')
    outf_mtime = None
    if not refdoc_fs.exists(gbrfolder):
        refdoc_fs.makedir(gbrfolder)
    else:
        outf_mtime = fsutils.get_folder_mtime(gbrfolder, fs=refdoc_fs)
    if not refdoc_fs.exists(imgfolder):
        refdoc_fs.makedir(imgfolder)

    if not force and outf_mtime is not None and outf_mtime > pcb_mtime:
        logger.debug('Skipping up-to-date ' + gbrfolder)
        return gbrfolder

    logger.info('Regenerating ' + gbrfolder + os.linesep + 'Last modified : ' +
                str(pcb_mtime) + '; Last Created : ' + str(outf_mtime))
    rf = refdoc_fs.listdir(gbrfolder, files_only=True, full=True)
    for f in rf:
        refdoc_fs.remove(f)

    workspace_folder = workspace_fs.getsyspath(gbrfolder)
    workspace_fs.makedir(gbrfolder, recursive=True, allow_recreate=True)

    gbrfolder = pcb.conv_pcb2gbr(
        os.path.join(configfile.projectfolder, 'pcb', gpf.pcbfile + '.pcb'),
        workspace_folder)

    workspace_fs.makedir(imgfolder, recursive=True, allow_recreate=True)

    img_workspace_folder = workspace_fs.getsyspath(imgfolder)
    gen_pcb_img(gbrfolder,
                outfolder=img_workspace_folder,
                outfname=gpf.pcbfile,
                force=False)

    for f in os.listdir(img_workspace_folder):
        fpath = os.path.relpath(os.path.join(img_workspace_folder, f),
                                workspace_fs.getsyspath('/'))
        copyfile(workspace_fs, fpath, refdoc_fs, fpath, overwrite=True)

    zfile = os.path.join(workspace_folder, os.pardir,
                         gpf.pcbfile + '-gerber.zip')
    fsutils.zipdir(gbrfolder, zfile)

    for f in os.listdir(workspace_folder):
        fpath = os.path.relpath(os.path.join(workspace_folder, f),
                                workspace_fs.getsyspath('/'))
        copyfile(workspace_fs, fpath, refdoc_fs, fpath, overwrite=True)
    zfpath = os.path.relpath(os.path.join(workspace_folder, zfile),
                             workspace_fs.getsyspath('/'))
    copyfile(workspace_fs, zfpath, refdoc_fs, zfpath, overwrite=True)

    return gbrfolder
Пример #7
0
def gen_confpdf(projfolder, configname, namebase, force=False):
    """
    Generates a PDF file of the documentation for a specific configuration
    of a project. It uses other document generator functions to make the
    various parts of the master document and then merges them.

    :param projfolder: The gEDA project folder.
    :type projfolder: str
    :param configname: The name of the configuration.
    :type configname: str
    :param namebase: The project name.
    :type namebase: str
    :param force: Regenerate even if up-to-date.
    :type force: bool
    :return: The output file path.

    .. rubric:: Paths

    * Output File :  ``<project_doc_folder>/confdocs/<configname>.pdf``
    * Source Files : The project's schematic folder.

    .. rubric:: Included Documents

    * Configuration BOM, generated by :func:`gen_confbom`
    * (Full) Schematic PDF, generated by :func:`gen_schpdf`

    .. todo:: It may be useful to rebuild the schematics after removing
              all the unpopulated components. This is a fairly involved
              process, and is deferred until later.

    """
    gpf = projfile.GedaProjectFile(projfolder)
    sch_mtime = fsutils.get_folder_mtime(gpf.schfolder)

    docfolder = get_project_doc_folder(projfolder)
    confdocfile = path.join(docfolder, 'confdocs', configname + '.pdf')
    outf_mtime = fsutils.get_file_mtime(confdocfile, fs=refdoc_fs)

    if not force and outf_mtime is not None and outf_mtime > sch_mtime:
        logger.debug('Skipping up-to-date ' + confdocfile)
        return confdocfile

    logger.info('Regenerating ' + confdocfile + os.linesep +
                'Last modified : ' + str(sch_mtime) + '; Last Created : ' +
                str(outf_mtime))

    pdffiles = [
        gen_confbom(projfolder, configname, force),
        gen_confdoc(projfolder, configname, force),
        gen_schpdf(projfolder, namebase, configname=configname, force=force)
    ]

    for p in pdffiles:
        if p and not workspace_fs.exists(p):
            workspace_fs.makedir(path.dirname(p),
                                 recursive=True,
                                 allow_recreate=True)
            copyfile(refdoc_fs, p, workspace_fs, p)

    workspace_pdffiles = [
        workspace_fs.getsyspath(x) for x in pdffiles if x is not None
    ]

    workspace_outpath = workspace_fs.getsyspath(confdocfile)
    workspace_fs.makedir(path.dirname(confdocfile),
                         recursive=True,
                         allow_recreate=True)
    pdf.merge_pdf(workspace_pdffiles, workspace_outpath)
    copyfile(workspace_fs, confdocfile, refdoc_fs, confdocfile, overwrite=True)
    return confdocfile
Пример #8
0
def gen_masterdoc(projfolder, namebase, force=False):
    """
    Generates a PDF file of the project's Master documentation. It uses
    other document generator functions to make the various parts of the
    master document and then merges them.

    .. note:: Due to the way groups and motifs are handled, an
              unconfigured BOM is somewhat meaningless. Therefore,
              no BOM is included in the masterdoc.

    :param projfolder: The gEDA project folder.
    :type projfolder: str
    :param namebase: The project name.
    :type namebase: str
    :param force: Regenerate even if up-to-date.
    :type force: bool
    :return: The output file path.

    .. rubric:: Paths

    * Output File :  ``<project_doc_folder>/<namebase>-masterdoc.pdf``
    * Source Files : The project's schematic folder.

    .. rubric:: Included Documents

    * Config Documentation, generated by :func:`gen_configsdoc`
    * Schematic PDF, generated by :func:`gen_schpdf`

    """
    gpf = projfile.GedaProjectFile(projfolder)
    sch_mtime = fsutils.get_folder_mtime(gpf.schfolder)

    docfolder = get_project_doc_folder(projfolder)
    masterdocfile = path.join(docfolder, namebase + '-masterdoc.pdf')
    outf_mtime = fsutils.get_file_mtime(masterdocfile, fs=refdoc_fs)

    if not force and outf_mtime is not None and outf_mtime > sch_mtime:
        logger.debug('Skipping up-to-date ' + masterdocfile)
        return masterdocfile

    logger.info('Regnerating ' + masterdocfile + os.linesep +
                'Last modified : ' + str(sch_mtime) + '; Last Created : ' +
                str(outf_mtime))

    pdffiles = [
        gen_configsdoc(projfolder, namebase, force=False),
        gen_schpdf(projfolder, namebase, force=False)
    ]

    for p in pdffiles:
        if p and not workspace_fs.exists(p):
            workspace_fs.makedir(path.dirname(p),
                                 recursive=True,
                                 allow_recreate=True)
            copyfile(refdoc_fs, p, workspace_fs, p)

    workspace_pdffiles = [
        workspace_fs.getsyspath(x) for x in pdffiles if x is not None
    ]

    workspace_outpath = workspace_fs.getsyspath(masterdocfile)
    workspace_fs.makedir(path.dirname(masterdocfile),
                         recursive=True,
                         allow_recreate=True)
    pdf.merge_pdf(workspace_pdffiles, workspace_outpath)
    copyfile(workspace_fs,
             masterdocfile,
             refdoc_fs,
             masterdocfile,
             overwrite=True)
    return masterdocfile
Пример #9
0
def gen_schpdf(projfolder, namebase, configname=None, force=False):
    """
    Generates a PDF file of all the project schematics listed in the
    gEDA project file. This function does not use jinja2 and latex. It
    relies on :func:`tendril.gedaif.gschem.conv_gsch2pdf` instead.

    :param projfolder: The gEDA project folder.
    :type projfolder: str
    :param namebase: The project name.
    :type namebase: str
    :param force: Regenerate even if up-to-date.
    :type force: bool
    :return: The output file path.

    .. rubric:: Paths

    * Output File :  ``<project_doc_folder>/<namebase>-schematic.pdf``
    * Source Files : The project's schematic folder.

    """
    gpf = projfile.GedaProjectFile(projfolder)
    sch_mtime = fsutils.get_folder_mtime(gpf.schfolder)

    configfile = conffile.ConfigsFile(projfolder)
    docfolder = get_project_doc_folder(projfolder)

    # TODO Consider converting all configurations in one go instead?
    if configname is None:
        schpdfpath = path.join(docfolder, namebase + '-schematic.pdf')
    else:
        docfolder = path.join(docfolder, 'confdocs')
        pdfname = configname + '-conf-schematic.pdf'
        schpdfpath = path.join(docfolder, pdfname)
    outf_mtime = fsutils.get_file_mtime(schpdfpath, fs=refdoc_fs)

    if not force and outf_mtime is not None and outf_mtime > sch_mtime:
        logger.debug('Skipping up-to-date ' + schpdfpath)
        return schpdfpath

    logger.info('Regenerating ' + schpdfpath + os.linesep +
                'Last modified : ' + str(sch_mtime) + '; Last Created : ' +
                str(outf_mtime))

    if configfile.rawconfig is not None:
        workspace_outpath = workspace_fs.getsyspath(schpdfpath)
        workspace_folder = workspace_fs.getsyspath(docfolder)
        workspace_fs.makedir(docfolder, recursive=True, allow_recreate=True)
        pdffiles = []
        obom = None
        if configname is not None:
            tfolder = path.join(docfolder, configname)
            workspace_tfolder = workspace_fs.getsyspath(tfolder)
            workspace_fs.makedir(tfolder, recursive=False, allow_recreate=True)
            bom = boms_electronics.import_pcb(projfolder)
            bom.configure_motifs(configname)
            obom = bom.create_output_bom(configname)
        for schematic in gpf.schfiles:
            schfile = os.path.normpath(projfolder + '/schematic/' + schematic)
            if configname is not None:
                tschfile = path.join(workspace_tfolder, schematic)
                gschem.rewrite_schematic(schfile, obom, gpf, tschfile)
                pdffile = gschem.conv_gsch2pdf(tschfile, workspace_tfolder)
                os.remove(tschfile)
            else:
                pdffile = gschem.conv_gsch2pdf(schfile, workspace_folder)
            pdffiles.append(pdffile)
        pdf.merge_pdf(pdffiles, workspace_outpath)
        for pdffile in pdffiles:
            os.remove(pdffile)
        copyfile(workspace_fs,
                 schpdfpath,
                 refdoc_fs,
                 schpdfpath,
                 overwrite=True)
        return schpdfpath
Пример #10
0
def gen_confdoc(projfolder, configname, force=False):
    """
    Generate a PDF documenting a single configuration of the project. The
    document should include a reasonably thorough representation of the
    contents of the configuration related sections of the
    `tendril.gedaif.conffile.ConfigsFile``.

    :param projfolder: The gEDA project folder
    :type projfolder: str
    :param configname: The configuration name for which the BOM should be
                       generated.
    :type configname: str
    :param force: Regenerate even if up-to-date.
    :type force: bool
    :return: The output file path.

    .. rubric:: Paths

    * Output File :  ``<project_doc_folder>/confdocs/<configname>-doc.pdf``
    * Source Files : The project's schematic folder.

    .. rubric:: Template Used

    ``tendril/dox/templates/projects/geda-conf-doc.tex``
    (:download:`Included version
    <../../tendril/dox/templates/projects/geda-conf-doc.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``configname``
          - The name of the configuration (a card or cable name).
        * - ``desc``
          - The description of the configuration.
        * - ``pcbname``
          - The name of the base PCB.
        * - ``obom``
          - An :mod:`tendril.boms.outputbase.OutputBom` instance

    """
    gpf = projfile.GedaProjectFile(projfolder)
    sch_mtime = fsutils.get_folder_mtime(gpf.schfolder)

    docfolder = get_project_doc_folder(projfolder)
    outpath = path.join(docfolder, 'confdocs', configname + '-doc.pdf')
    outf_mtime = fsutils.get_file_mtime(outpath, fs=refdoc_fs)

    if not force and outf_mtime is not None and outf_mtime > sch_mtime:
        logger.debug('Skipping up-to-date ' + outpath)
        return outpath

    logger.info('Regenerating ' + outpath + os.linesep + 'Last modified : ' +
                str(sch_mtime) + '; Last Created : ' + str(outf_mtime))
    bom = boms_electronics.import_pcb(projfolder)
    obom = bom.create_output_bom(configname)
    group_oboms = bom.get_group_boms(configname)
    stage = {
        'configname': obom.descriptor.configname,
        'pcbname': obom.descriptor.pcbname,
        'bom': bom,
        'obom': obom,
        'group_oboms': group_oboms
    }

    config = obom.descriptor.configurations.configuration(configname)
    stage['desc'] = config['desc']

    template = 'projects/geda-conf-doc.tex'

    workspace_outpath = workspace_fs.getsyspath(outpath)
    workspace_fs.makedir(path.dirname(outpath),
                         recursive=True,
                         allow_recreate=True)
    render.render_pdf(stage, template, workspace_outpath)
    copyfile(workspace_fs, outpath, refdoc_fs, outpath, overwrite=True)

    return outpath
Пример #11
0
def gen_pcb_gbr(projfolder, force=False):
    """
    Generates gerber files for the PCB provided by the gEDA project, and also
    creates a ``zip`` file of the generated gerbers.

    The pcbfile is the one listed in the gEDA project file, and the
    pcbname is the one specified in the
    :mod:`tendril.gedaif.conffile.ConfigsFile`.

    This function does not use jinja2 and latex. It relies on
    :func:`tendril.gedaif.pcb.conv_pcb2gbr` instead.

    :param projfolder: The gEDA project folder.
    :type projfolder: str
    :param force: Regenerate even if up-to-date.
    :type force: bool
    :return: The output file path.

    .. rubric:: Paths

    * Output Files :  ``<project_doc_folder>/../gerber/*``
    * Output Zip File : ``<project_doc_folder>/../<pcbfile>-gerber.zip``
    * Source Files : The project's `.pcb` file.

    """
    configfile = conffile.ConfigsFile(projfolder)
    gpf = projfile.GedaProjectFile(configfile.projectfolder)
    pcb_mtime = fsutils.get_file_mtime(
        os.path.join(configfile.projectfolder, 'pcb', gpf.pcbfile + '.pcb')
    )
    if pcb_mtime is None:
        logger.warning("PCB does not seem to exist for : " + projfolder)
        return
    docfolder = get_project_doc_folder(projfolder)
    imgfolder = os.path.join(docfolder, os.pardir, 'img')
    gbrfolder = os.path.join(docfolder, os.pardir, 'gerber')
    outf_mtime = None
    if not refdoc_fs.exists(gbrfolder):
        refdoc_fs.makedir(gbrfolder)
    else:
        outf_mtime = fsutils.get_folder_mtime(gbrfolder, fs=refdoc_fs)
    if not refdoc_fs.exists(imgfolder):
        refdoc_fs.makedir(imgfolder)

    if not force and outf_mtime is not None and outf_mtime > pcb_mtime:
        logger.debug('Skipping up-to-date ' + gbrfolder)
        return gbrfolder

    logger.info('Regenerating ' + gbrfolder + os.linesep +
                'Last modified : ' + str(pcb_mtime) +
                '; Last Created : ' + str(outf_mtime))
    rf = refdoc_fs.listdir(gbrfolder, files_only=True, full=True)
    for f in rf:
        refdoc_fs.remove(f)

    workspace_folder = workspace_fs.getsyspath(gbrfolder)
    workspace_fs.makedir(gbrfolder,
                         recursive=True, allow_recreate=True)

    gbrfolder = pcb.conv_pcb2gbr(
        os.path.join(configfile.projectfolder, 'pcb', gpf.pcbfile + '.pcb'),
        workspace_folder
    )

    workspace_fs.makedir(imgfolder,
                         recursive=True, allow_recreate=True)

    img_workspace_folder = workspace_fs.getsyspath(imgfolder)
    gen_pcb_img(gbrfolder, outfolder=img_workspace_folder,
                outfname=gpf.pcbfile, force=False)

    for f in os.listdir(img_workspace_folder):
        fpath = os.path.relpath(
            os.path.join(img_workspace_folder, f), workspace_fs.getsyspath('/')
        )
        copyfile(workspace_fs, fpath, refdoc_fs, fpath, overwrite=True)

    zfile = os.path.join(
        workspace_folder, os.pardir, gpf.pcbfile + '-gerber.zip'
    )
    fsutils.zipdir(gbrfolder, zfile)

    for f in os.listdir(workspace_folder):
        fpath = os.path.relpath(
            os.path.join(workspace_folder, f), workspace_fs.getsyspath('/')
        )
        copyfile(workspace_fs, fpath, refdoc_fs, fpath, overwrite=True)
    zfpath = os.path.relpath(
        os.path.join(workspace_folder, zfile), workspace_fs.getsyspath('/')
    )
    copyfile(workspace_fs, zfpath, refdoc_fs, zfpath, overwrite=True)

    return gbrfolder
Пример #12
0
def gen_confpdf(projfolder, configname, namebase, force=False):
    """
    Generates a PDF file of the documentation for a specific configuration
    of a project. It uses other document generator functions to make the
    various parts of the master document and then merges them.

    :param projfolder: The gEDA project folder.
    :type projfolder: str
    :param configname: The name of the configuration.
    :type configname: str
    :param namebase: The project name.
    :type namebase: str
    :param force: Regenerate even if up-to-date.
    :type force: bool
    :return: The output file path.

    .. rubric:: Paths

    * Output File :  ``<project_doc_folder>/confdocs/<configname>.pdf``
    * Source Files : The project's schematic folder.

    .. rubric:: Included Documents

    * Configuration BOM, generated by :func:`gen_confbom`
    * (Full) Schematic PDF, generated by :func:`gen_schpdf`

    .. todo:: It may be useful to rebuild the schematics after removing
              all the unpopulated components. This is a fairly involved
              process, and is deferred until later.

    """
    gpf = projfile.GedaProjectFile(projfolder)
    sch_mtime = fsutils.get_folder_mtime(gpf.schfolder)

    docfolder = get_project_doc_folder(projfolder)
    confdocfile = path.join(docfolder, 'confdocs', configname + '.pdf')
    outf_mtime = fsutils.get_file_mtime(confdocfile, fs=refdoc_fs)

    if not force and outf_mtime is not None and outf_mtime > sch_mtime:
        logger.debug('Skipping up-to-date ' + confdocfile)
        return confdocfile

    logger.info('Regenerating ' + confdocfile + os.linesep +
                'Last modified : ' + str(sch_mtime) +
                '; Last Created : ' + str(outf_mtime))

    pdffiles = [gen_confbom(projfolder, configname, force),
                gen_confdoc(projfolder, configname, force),
                gen_schpdf(projfolder, namebase, force)]

    for p in pdffiles:
        if p and not workspace_fs.exists(p):
            workspace_fs.makedir(path.dirname(p),
                                 recursive=True, allow_recreate=True)
            copyfile(refdoc_fs, p, workspace_fs, p)

    workspace_pdffiles = [workspace_fs.getsyspath(x)
                          for x in pdffiles if x is not None]

    workspace_outpath = workspace_fs.getsyspath(confdocfile)
    workspace_fs.makedir(path.dirname(confdocfile),
                         recursive=True, allow_recreate=True)
    pdf.merge_pdf(workspace_pdffiles, workspace_outpath)
    copyfile(workspace_fs, confdocfile,
             refdoc_fs, confdocfile,
             overwrite=True)
    return confdocfile
Пример #13
0
def gen_masterdoc(projfolder, namebase, force=False):
    """
    Generates a PDF file of the project's Master documentation. It uses
    other document generator functions to make the various parts of the
    master document and then merges them.

    .. note:: Due to the way groups and motifs are handled, an
              unconfigured BOM is somewhat meaningless. Therefore,
              no BOM is included in the masterdoc.

    :param projfolder: The gEDA project folder.
    :type projfolder: str
    :param namebase: The project name.
    :type namebase: str
    :param force: Regenerate even if up-to-date.
    :type force: bool
    :return: The output file path.

    .. rubric:: Paths

    * Output File :  ``<project_doc_folder>/<namebase>-masterdoc.pdf``
    * Source Files : The project's schematic folder.

    .. rubric:: Included Documents

    * Config Documentation, generated by :func:`gen_configsdoc`
    * Schematic PDF, generated by :func:`gen_schpdf`

    """
    gpf = projfile.GedaProjectFile(projfolder)
    sch_mtime = fsutils.get_folder_mtime(gpf.schfolder)

    docfolder = get_project_doc_folder(projfolder)
    masterdocfile = path.join(docfolder, namebase + '-masterdoc.pdf')
    outf_mtime = fsutils.get_file_mtime(masterdocfile, fs=refdoc_fs)

    if not force and outf_mtime is not None and outf_mtime > sch_mtime:
        logger.debug('Skipping up-to-date ' + masterdocfile)
        return masterdocfile

    logger.info('Regnerating ' + masterdocfile + os.linesep +
                'Last modified : ' + str(sch_mtime) +
                '; Last Created : ' + str(outf_mtime))

    pdffiles = [gen_configsdoc(projfolder, namebase, force=False),
                gen_schpdf(projfolder, namebase, force=False)]

    for p in pdffiles:
        if p and not workspace_fs.exists(p):
            workspace_fs.makedir(path.dirname(p),
                                 recursive=True, allow_recreate=True)
            copyfile(refdoc_fs, p, workspace_fs, p)

    workspace_pdffiles = [workspace_fs.getsyspath(x)
                          for x in pdffiles if x is not None]

    workspace_outpath = workspace_fs.getsyspath(masterdocfile)
    workspace_fs.makedir(path.dirname(masterdocfile),
                         recursive=True, allow_recreate=True)
    pdf.merge_pdf(workspace_pdffiles, workspace_outpath)
    copyfile(workspace_fs, masterdocfile,
             refdoc_fs, masterdocfile,
             overwrite=True)
    return masterdocfile
Пример #14
0
def gen_confdoc(projfolder, configname, force=False):
    """
    Generate a PDF documenting a single configuration of the project. The
    document should include a reasonably thorough representation of the
    contents of the configuration related sections of the
    `tendril.gedaif.conffile.ConfigsFile``.

    :param projfolder: The gEDA project folder
    :type projfolder: str
    :param configname: The configuration name for which the BOM should be
                       generated.
    :type configname: str
    :param force: Regenerate even if up-to-date.
    :type force: bool
    :return: The output file path.

    .. rubric:: Paths

    * Output File :  ``<project_doc_folder>/confdocs/<configname>-doc.pdf``
    * Source Files : The project's schematic folder.

    .. rubric:: Template Used

    ``tendril/dox/templates/projects/geda-conf-doc.tex``
    (:download:`Included version
    <../../tendril/dox/templates/projects/geda-conf-doc.tex>`)

    .. rubric:: Stage Keys Provided
    .. list-table::

        * - ``configname``
          - The name of the configuration (a card or cable name).
        * - ``desc``
          - The description of the configuration.
        * - ``pcbname``
          - The name of the base PCB.
        * - ``obom``
          - An :mod:`tendril.boms.outputbase.OutputBom` instance

    """
    gpf = projfile.GedaProjectFile(projfolder)
    sch_mtime = fsutils.get_folder_mtime(gpf.schfolder)

    docfolder = get_project_doc_folder(projfolder)
    outpath = path.join(docfolder, 'confdocs', configname + '-doc.pdf')
    outf_mtime = fsutils.get_file_mtime(outpath, fs=refdoc_fs)

    if not force and outf_mtime is not None and outf_mtime > sch_mtime:
        logger.debug('Skipping up-to-date ' + outpath)
        return outpath

    logger.info('Regenerating ' + outpath + os.linesep +
                'Last modified : ' + str(sch_mtime) +
                '; Last Created : ' + str(outf_mtime))
    bom = boms_electronics.import_pcb(projfolder)
    obom = bom.create_output_bom(configname)
    group_oboms = bom.get_group_boms(configname)
    stage = {'configname': obom.descriptor.configname,
             'pcbname': obom.descriptor.pcbname,
             'bom': bom,
             'obom': obom,
             'group_oboms': group_oboms}

    config = obom.descriptor.configurations.configuration(configname)
    stage['desc'] = config['desc']

    template = 'projects/geda-conf-doc.tex'

    workspace_outpath = workspace_fs.getsyspath(outpath)
    workspace_fs.makedir(path.dirname(outpath),
                         recursive=True, allow_recreate=True)
    render.render_pdf(stage, template, workspace_outpath)
    copyfile(workspace_fs, outpath, refdoc_fs, outpath, overwrite=True)

    return outpath