Changeset - 6a3d64ff2250
[Not reviewed]
0 3 0
Brett Smith - 3 years ago 2021-01-09 15:49:04
brettcsmith@brettcsmith.org
fields: Change FieldType capitalization.

This is friendlier to the YAML input and consistent with FieldFlags.
Less consistent with the rest of the codebase, but local consistency matters
more IMO.
3 files changed with 10 insertions and 11 deletions:
0 comments (0 inline, 0 general)
conservancy_beancount/pdfforms/fields.py
Show inline comments
...
 
@@ -32,90 +32,89 @@ from typing import (
 
FieldSource = MutableMapping[str, Any]
 

	
 
class FieldFlags(enum.IntFlag):
 
    # Flags for all fields
 
    ReadOnly = 2 ** 0
 
    Required = 2 ** 1
 
    NoExport = 2 ** 2
 
    # Flags for buttons
 
    NoToggleToOff = 2 ** 14
 
    Radio = 2 ** 15
 
    Pushbutton = 2 ** 16
 
    RadiosInUnison = 2 ** 25
 
    # Flags for text
 
    Multiline = 2 ** 12
 
    Password = 2 ** 13
 
    FileSelect = 2 ** 20
 
    DoNotSpellCheck = 2 ** 22
 
    DoNotScroll = 2 ** 23
 
    Comb = 2 ** 24
 
    RichText = 2 ** 25
 

	
 

	
 
class FieldType(enum.Enum):
 
    Btn = 'Btn'
 
    BUTTON = Btn
 
    Button = Btn
 
    Ch = 'Ch'
 
    CHOICE = Ch
 
    Choice = Ch
 
    Sig = 'Sig'
 
    SIG = Sig
 
    SIGNATURE = Sig
 
    Signature = Sig
 
    Tx = 'Tx'
 
    TEXT = Tx
 
    Text = Tx
 

	
 

	
 
class FormField:
 
    __slots__ = ['_source']
 
    _SENTINEL = object()
 
    DEFAULT_FILL: object = None
 
    INHERITABLE = frozenset([
 
        'DV',
 
        'Ff',
 
        'FT',
 
        'MaxLen',
 
        'Opt',
 
        'V',
 
    ])
 

	
 
    def __init__(self, source: FieldSource) -> None:
 
        self._source = source
 

	
 
    @classmethod
 
    def by_type(cls, source: FieldSource) -> 'FormField':
 
        retval = cls(source)
 
        try:
 
            field_type = retval.field_type()
 
        except ValueError:
 
            return retval
 
        flags = retval.flags()
 
        if field_type is FieldType.BUTTON:
 
        if field_type is FieldType.Button:
 
            if flags & FieldFlags.Radio:
 
                pass
 
            elif flags & FieldFlags.Pushbutton:
 
                pass
 
            else:
 
                retval.__class__ = CheckboxField
 
        elif field_type is FieldType.TEXT:
 
        elif field_type is FieldType.Text:
 
            retval.__class__ = TextField
 
        return retval
 

	
 
    def _get_value(self, key: str, default: Any=_SENTINEL) -> Any:
 
        can_inherit = key in self.INHERITABLE
 
        source: Optional[FieldSource] = self._source
 
        while source is not None:
 
            try:
 
                return resolve1(source[key])
 
            except KeyError:
 
                source = resolve1(source.get('Parent')) if can_inherit else None
 
        if default is self._SENTINEL:
 
            raise PDFKeyError(key)
 
        else:
 
            return default
 

	
 
    def field_type(self) -> FieldType:
 
        try:
 
            source = self._get_value('FT')
 
        except KeyError:
 
            raise PDFSpecError("field does not specify a field type") from None
 
        try:
 
            return FieldType[source.name]
 
        except (AttributeError, KeyError):
setup.py
Show inline comments
 
#!/usr/bin/env python3
 

	
 
from setuptools import setup
 

	
 
setup(
 
    name='conservancy_beancount',
 
    description="Plugin, library, and reports for reading Conservancy's books",
 
    version='1.15.0',
 
    version='1.15.1',
 
    author='Software Freedom Conservancy',
 
    author_email='info@sfconservancy.org',
 
    license='GNU AGPLv3+',
 

	
 
    install_requires=[
 
        'babel>=2.6',  # Debian:python3-babel
 
        'beancount>=2.2',  # Debian:beancount
 
        'GitPython>=2.0',  # Debian:python3-git
 
        # 1.4.1 crashes when trying to save some documents.
 
        'odfpy>=1.4.0,!=1.4.1',  # Debian:python3-odf
 
        'pdfminer.six>=20200101',
 
        'PyYAML>=3.0',  # Debian:python3-yaml
 
        'regex',  # Debian:python3-regex
 
        'rt>=2.0',
 
    ],
 
    setup_requires=[
 
        'pytest-mypy',
 
        'pytest-runner',  # Debian:python3-pytest-runner
 
    ],
 
    tests_require=[
 
        'mypy>=0.770',  # Debian:python3-mypy
 
        'pytest',  # Debian:python3-pytest
 
    ],
 

	
tests/test_pdfforms_fields.py
Show inline comments
...
 
@@ -44,98 +44,98 @@ def field_source(
 
    if parent is not None:
 
        retval['Parent'] = parent
 
    if kids is not None:
 
        retval['Kids'] = list(kids)
 
    return retval
 

	
 
def appearance_states(*names):
 
    return {key: object() for key in names if key is not None}
 

	
 
def test_empty_field():
 
    source = field_source()
 
    field = fieldsmod.FormField(source)
 
    assert not field.name()
 
    assert field.value() is None
 
    assert field.parent() is None
 
    assert not list(field.kids())
 
    assert field.flags() == 0
 
    assert field.is_terminal()
 
    with pytest.raises(ValueError):
 
        field.field_type()
 

	
 
def test_text_field_base():
 
    source = field_source(b's', b'string of text', 'Tx')
 
    field = fieldsmod.FormField(source)
 
    assert field.field_type() is fieldsmod.FieldType.TEXT
 
    assert field.field_type() is fieldsmod.FieldType.Text
 
    assert field.name() == 's'
 
    assert field.value() == b'string of text'
 

	
 
@pytest.mark.parametrize('value', ['Off', 'Yes', 'On'])
 
def test_checkbox_field_base(value):
 
    source = field_source(b'cb', value, 'Btn', literal=True)
 
    field = fieldsmod.FormField(source)
 
    assert field.field_type() is fieldsmod.FieldType.BUTTON
 
    assert field.field_type() is fieldsmod.FieldType.Button
 
    assert field.name() == 'cb'
 
    assert field.value().name == value
 

	
 
@pytest.mark.parametrize('flags', range(4))
 
def test_readonly_flag(flags):
 
    source = field_source(flags=flags)
 
    field = fieldsmod.FormField(source)
 
    assert field.flags() == flags
 
    assert field.is_readonly() == flags % 2
 

	
 
@pytest.mark.parametrize('kid_count', range(3))
 
def test_kids(kid_count):
 
    kids = [field_source(f'kid{n}', field_type='Ch') for n in range(kid_count)]
 
    source = field_source(kids=iter(kids))
 
    field = fieldsmod.FormField(source)
 
    got_kids = list(field.kids())
 
    assert len(got_kids) == len(kids)
 
    assert field.is_terminal() == (not kids)
 
    for actual, expected in zip(got_kids, kids):
 
        assert actual.name() == expected['T'].decode('ascii')
 

	
 
def test_kids_by_type():
 
    kids = [field_source(field_type='Tx'), field_source(field_type='Btn')]
 
    source = field_source('topform', kids=iter(kids))
 
    actual = fieldsmod.FormField.by_type(source).kids()
 
    assert isinstance(next(actual), fieldsmod.TextField)
 
    assert isinstance(next(actual), fieldsmod.CheckboxField)
 
    assert next(actual, None) is None
 

	
 
def test_inheritance():
 
    parent_source = field_source(b'parent', 'parent value', 'Tx', 17)
 
    kid_source = field_source('kid', parent=parent_source)
 
    parent_source['Kids'] = [kid_source]
 
    field = fieldsmod.FormField(kid_source)
 
    parent = field.parent()
 
    assert parent is not None
 
    assert parent.name() == 'parent'
 
    assert not parent.is_terminal()
 
    assert field.is_terminal()
 
    assert field.name() == 'kid'
 
    assert field.field_type() is fieldsmod.FieldType.TEXT
 
    assert field.field_type() is fieldsmod.FieldType.Text
 
    assert field.value() == 'parent value'
 
    assert field.flags() == 17
 
    assert not list(field.kids())
 

	
 
@pytest.mark.parametrize('field_type,value', [
 
    ('Tx', b'new value'),
 
    ('Btn', PSLiteral('Yes')),
 
])
 
def test_set_value(field_type, value):
 
    source = field_source(field_type=field_type)
 
    field = fieldsmod.FormField(source)
 
    assert field.value() is None
 
    field.set_value(value)
 
    assert field.value() == value
 

	
 
@pytest.mark.parametrize('field_type,expected', [
 
    ('Tx', fieldsmod.TextField),
 
    ('Btn', fieldsmod.CheckboxField),
 
])
 
def test_by_type(field_type, expected):
 
    source = field_source(field_type=field_type)
 
    field = fieldsmod.FormField.by_type(source)
 
    assert isinstance(field, expected)
 

	
0 comments (0 inline, 0 general)