205 lines
8.4 KiB
Python
205 lines
8.4 KiB
Python
#! /usr/bin/python3
|
|
# -*- coding: UTF-8 -*-
|
|
|
|
"""Constants for the project.
|
|
|
|
It might be better to have them at suitable points in classes
|
|
but then circular imports break some things regurly.
|
|
|
|
Constants:
|
|
COMMENT_SYMBOL = "#":
|
|
symbol to indicate a comment line
|
|
SUBINFO_SEP = "-":
|
|
symbol to separate subinformation, e.g. for commands
|
|
VARIABLE_BEGIN/END/PARTS_SEP = "{", "}", "|":
|
|
symbols used in variable definition
|
|
DATE_BEGIN/END_SEP = "[", "]":
|
|
symbols used in TODAY replacement
|
|
NON_FORMFIELD = "Nonfield":
|
|
FormField with an info NON_FORMFIELD are used for
|
|
something else, e.g. general config. They do not correspond to
|
|
form fields in a pdf.
|
|
CONFIGFIELD = "Mainconfig":
|
|
the FieldName of the main config for the whole form. Should have the
|
|
info NON_FORMFIELD.
|
|
OUTPUTFIELD = "Outputconfig":
|
|
the FieldName of the config: where to save the output pdf.
|
|
Should have the info NON_FORMFIELD.
|
|
FORMOUTPUTFIELD = "Formoutputconfig":
|
|
the FieldName of the config: where to save the output form file.
|
|
Should have the info NON_FORMFIELD.
|
|
ON ([str]): options that mean thought as 'yes, mark this'
|
|
OFF ([str]): options that mean 'no, do not mark this'
|
|
EPILOG (str):
|
|
Text to be displayed as the help for the program.
|
|
GENERALADVICE (str):
|
|
A text that describes how to use the questions.
|
|
|
|
"""
|
|
|
|
import re
|
|
import textwrap
|
|
|
|
|
|
COMMENT_SYMBOL = "#"
|
|
SUBINFO_SEP = "-"
|
|
VARIABLE_BEGIN_SEP = "{"
|
|
VARIABLE_END_SEP = "}"
|
|
DATE_BEGIN_SEP = "["
|
|
DATE_END_SEP = "]"
|
|
VARIABLE_PARTS_SEP = "|"
|
|
VARIABLE_DEFAULT_SEP = "#"
|
|
NON_FORMFIELD = "Nonfield"
|
|
CONFIGFIELD = "Mainconfig"
|
|
OUTPUTFIELD = "Outputconfig"
|
|
FORMOUTPUTFIELD = "Formoutputconfig"
|
|
ON = ["Ja", "On", "ja"]
|
|
OFF = ["Off", "No", "nein", "Nein"]
|
|
|
|
|
|
class ConfigError(Exception):
|
|
"""There are a lot of mistakes one can make in writing config files.
|
|
|
|
This Error indicates that some information is missing or some line is
|
|
malformed.
|
|
|
|
No __init__ supplied because the standard __init__ of Exception does
|
|
a good job.
|
|
|
|
TODO: FormField where this error occured should be part of the error
|
|
and its message
|
|
-> in order to avoid referencing something, this could be moved to
|
|
FormField, which also makes some sense
|
|
|
|
"""
|
|
|
|
|
|
class MobileRegex():
|
|
"""A little util class.
|
|
|
|
To be used as a singleton.
|
|
|
|
Check whether an info should be saved as a list.
|
|
|
|
One could have a list of regex or just one regex but
|
|
then commands.Command.__subclasses__() would be a circular
|
|
import and that's bad.
|
|
|
|
"""
|
|
|
|
def __contains__(self, info):
|
|
"""Return whether this info can appear several times.
|
|
|
|
FieldStateOption: can appear in dump_data_fields from pdftk
|
|
Data: in Mainconfig for data files
|
|
Commands (subclasses):
|
|
TODO:
|
|
Now they are hardcoded because otherwise we would have
|
|
a circular dependance. Better would be a uniform type of reading
|
|
and a possibility for any code to change the access to allow
|
|
proper list handling. (Quite big refactor with speed loss.)
|
|
Commands can appear more than once per field
|
|
(even though seldomly do)
|
|
specifier-If...:
|
|
in one or more commands more than one condition can appear
|
|
(even though seldomly do)
|
|
|
|
Attributes:
|
|
info: the info queried for.
|
|
|
|
"""
|
|
return (info in ["FieldStateOption", "Data"] or
|
|
info in ["Question", "Default", "Choice"] or
|
|
# info in [scls.__name__ for scls in
|
|
# commands.Command.__subclasses__()] or
|
|
re.match(r"[^" + SUBINFO_SEP + r"]" +
|
|
SUBINFO_SEP + r"If.*", info))
|
|
# If clauses for commands
|
|
|
|
|
|
LISTINFOS = MobileRegex()
|
|
GENERALADVICE = "\n".join(["",
|
|
"You will be asked questions.",
|
|
"Type '?' to get a more elaborative explanation" +
|
|
" for the question.",
|
|
"Type Ctrl + D to input nothing at this place.",
|
|
"Type Ctrl + C to end the input, creating the pdf.",
|
|
"When given a choice, you can just hit Enter and " +
|
|
"get the default",
|
|
"or you type one of the options " +
|
|
"(the texts before '=') completely",
|
|
"or you type one of the descriptions " +
|
|
"(the texts after '=') partly." +
|
|
" Any string ignoring case that is the begin" +
|
|
" of exactly one description works"])
|
|
|
|
|
|
EPILOG = textwrap.fill(" ".join(
|
|
["Fillform supports you in filling out pdf forms repeatedly.",
|
|
"For each pdf form you need a config file (see argument",
|
|
"--config). This includes all information about the form fields",
|
|
"that exist in the pdf and how to fill them with data.",
|
|
|
|
"If you started filling out the pdf but did not finish yet,",
|
|
"you can use the .form-file that was created when interrupting",
|
|
"the previous session.",
|
|
"(Interruption of the session by Ctrl+C.)",
|
|
"\n\n",
|
|
"After finishing your input, a pdf (see argument --outputpdf)",
|
|
"with the filled form is created.",
|
|
"Additionally a form-file is created that includes all",
|
|
"information from the config file plus the data that is",
|
|
"written to the form in the pdf.",
|
|
"It can be used for filling other forms:",
|
|
"\n\nAdditional data\n---------------\n",
|
|
"Most information for the form come from you while answering",
|
|
"questions to the program. Some information can be copied from",
|
|
"other forms though. These information are saved in the",
|
|
"beforementioned form-files and must be specified in the config",
|
|
"file or with the"
|
|
"argument --data (see above). In case of duplicated info, use",
|
|
"command line path.",
|
|
"\n\n", "The program uses different ways of collecting the data.",
|
|
"They are called 'Commands':",
|
|
"\n\n1) Question: Many fields just need your input. You will be",
|
|
"asked to type what is to be written into the pdf form field.",
|
|
"To see some more information in case of doubt what to write,",
|
|
"type '?'. If you do not know yet what to enter and you might",
|
|
"want to add information in another run, leave the input empty.",
|
|
"\nIf this field should be empty, type a single whitespace ' '.",
|
|
"\n\n2) Choice: Pdf forms often include checkboxes (also called",
|
|
"Button). For those two or more options will be displayed and you",
|
|
"choose one. Either you type one of the options (usually 1,2,3 in",
|
|
"case of multiple choice or On, Off in case of a single Checkbox)"
|
|
"or you type a few letters of the beginning description that",
|
|
"is displayed together with the option.",
|
|
"\n\n3) Default: A lot of form fields have to be filled with the ",
|
|
"same data over and over again.",
|
|
"Hence some fields have Default values",
|
|
"that get used without you typing anything. Some of them",
|
|
"depend on other field entries.",
|
|
"\n\nErrors:\n-------\n",
|
|
"Sometimes the program might abort due to an Error.",
|
|
"Some of them are so called 'ConfigError' and happen if the",
|
|
"config file is malformed. In this case, get the config file",
|
|
"fixed. The error message should include some information that",
|
|
"should enable you to find the error.",
|
|
"\n\nDocumentation:\n--------------\n",
|
|
"Additionally to this help, the config file syntax is",
|
|
"documented. This documentation can be found in the project",
|
|
"in the directory 'doc'.",
|
|
"\n\nTODOS:\n------",
|
|
"\n• adding text where form form field is (using LaTeχ and pdftk "
|
|
"stamp)",
|
|
"\n• improvement of script for interactive creation of config",
|
|
"files: restructuring, including actions, maybe move it out",
|
|
"of formfields.",
|
|
"\n• config file for Reisekostenantrag + -abrechnung",
|
|
"\n• support for more-line infos, mainly used in FieldValue and",
|
|
"Default value",
|
|
"\n• refactoring: user input with more options, e.g. changing",
|
|
"afterwards, more than one line",
|
|
"\n• internationalization (=translation) of entire program",
|
|
"\n• understanding and maybe using FieldFlags",
|
|
"\n• paying attention",
|
|
"to FieldMaxLength"]), replace_whitespace=False)
|