Skip to content

yex.output.Output

yex.output.Output(doc, filename) #

A driver which can write a Document to disk, in a given file format.

Source code in yex/output/output.py
 8
 9
10
11
12
13
def __init__(self,
             doc: 'yex.document.Document',
             filename: str,
             ):
    self.doc = doc
    self.filename = filename

can_handle(format) classmethod #

Whether this driver can handle files of this format.

This is an abstract method: override it in all subclasses.

Parameters:

Name Type Description Default
format str

the kind of file we'll be writing to. This is always a possible extension for that file format. Examples might be "pdf" or "html". Use all lowercase, and omit the leading dot.

required
Source code in yex/output/output.py
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
@classmethod
def can_handle(cls,
               format: str,
               ) -> bool:
    """
    Whether this driver can handle files of this format.

    This is an abstract method: override it in all subclasses.

    Args:
        format: the kind of file we'll be writing to.
            This is always a possible extension for that file format.
            Examples might be "pdf" or "html".
            Use all lowercase, and omit the leading dot.
    """
    raise NotImplementedError()

driver_for(doc, filename, format=None) classmethod #

Creates an instance of an output driver.

Parameters:

Name Type Description Default
doc yex.output.null.yex.document.Document

the current Document; this is passed through to the new driver

required
filename str

the name of the file we'll be writing to

required
format typing.Union[str, None]

the name of the file format; if this is omitted or None, we take the filename extension.

None

Returns:

Type Description
typing.Self

an instance of one of Output's subclasses, instantiated to write the given Document to the given filename.

Source code in yex/output/output.py
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
@classmethod
def driver_for(cls,
               doc: 'yex.document.Document',
               filename: str,
               format: Union[str, None] = None,
               ) -> Self:
    """
    Creates an instance of an output driver.

    Args:
        doc: the current Document; this is passed through
            to the new driver
        filename: the name of the file we'll be writing to
        format: the name of the file format; if this
            is omitted or None, we take the filename extension.

    Returns:
        an instance of one of Output's subclasses, instantiated to
            write the given Document to the given filename.
    """

    import os, yex, logging, inspect

    logger = yex.logging.getLogger('output')

    logger.debug(
            ('Output.driver_for: looking up output driver for '
                'filename=%s, format=%s'),
            filename, format)

    if filename is None:
        result = yex.output.Null(doc=doc, filename=filename)
        logger.debug('  -- returning null output driver: %s',
                result)
        return result

    if format is None:
        _, format = os.path.splitext(filename)

        if format.startswith('.'):
            format = format[1:]

        logger.debug('  -- deducing format from filename: %s', format)

    logger.debug('  -- asking all drivers about their capability')

    def _can_handle_it(driver_class):
        logger.debug('    -- can %s handle %s?', driver_class, format)

        result = driver_class.can_handle(format)
        if result:
            logger.debug('      -- yes')
        else:
            logger.debug('      -- no')

        return result


    capable = [
        driver for name, driver in inspect.getmembers(yex.output)
        if driver.__class__==type and
        issubclass(driver, cls)
        and driver!=cls
        and _can_handle_it(driver)
        ]

    logger.debug('  -- found: %s', capable)

    if len(capable)==0:
        logger.debug('  -- %s is unknown; bail', format)
        raise yex.exception.WeirdFormatError(
                format = format,
                )
    elif len(capable)>1:
        logger.debug('  -- warning the user that there are several')
        print(f'warning: there are multiple drivers which '
                f'can handle {format}:',
            ', '.join([x.__class__.__name__ for x in capable]),
            '-- using ',capable[0].__class__.__name__,
                )

    result = capable[0](
            doc = doc,
            filename = filename,
            )

    logger.debug('  -- result: %s', result)
    return result

render() #

Writes the document out to disk.

The document and filename were given to this object's constructor earlier.

Once you have called this argument, don't call it again.

This is an abstract method: override it in all subclasses.

Source code in yex/output/output.py
15
16
17
18
19
20
21
22
23
24
25
26
def render(self) -> None:
    """
    Writes the document out to disk.

    The document and filename were given to this object's constructor
    earlier.

    Once you have called this argument, don't call it again.

    This is an abstract method: override it in all subclasses.
    """
    raise NotImplementedError()