From 2bb2bd203455ec1df15f6f4fd3069a3649a59c12 Mon Sep 17 00:00:00 2001 From: "Salvador E. Tropea" Date: Mon, 22 Jun 2020 19:47:37 -0300 Subject: [PATCH] Added preliminary tests to add "automagic" documenation for the output options --- experiments/__doc__/doc.py | 23 ++++++++ experiments/__doc__/macropy/application.py | 24 +++++++++ experiments/__doc__/macropy/mymacros.py | 57 ++++++++++++++++++++ experiments/__doc__/macropy/test_mymacros.py | 3 ++ experiments/__doc__/mcpy/application.py | 24 +++++++++ experiments/__doc__/mcpy/mymacros.py | 53 ++++++++++++++++++ experiments/__doc__/mcpy/test_mymacros.py | 3 ++ kiplot/config_reader.py | 1 + kiplot/macros.py | 47 ++++++++++++++++ kiplot/out_gerber.py | 19 ++++--- 10 files changed, 246 insertions(+), 8 deletions(-) create mode 100644 experiments/__doc__/doc.py create mode 100644 experiments/__doc__/macropy/application.py create mode 100644 experiments/__doc__/macropy/mymacros.py create mode 100755 experiments/__doc__/macropy/test_mymacros.py create mode 100644 experiments/__doc__/mcpy/application.py create mode 100644 experiments/__doc__/mcpy/mymacros.py create mode 100755 experiments/__doc__/mcpy/test_mymacros.py create mode 100644 kiplot/macros.py diff --git a/experiments/__doc__/doc.py b/experiments/__doc__/doc.py new file mode 100644 index 00000000..54dee3fb --- /dev/null +++ b/experiments/__doc__/doc.py @@ -0,0 +1,23 @@ +def my_decorator(func): + def wrapper(): + print("Something is happening before the function is called.") + func() + print("Something is happening after the function is called.") + return wrapper + +@my_decorator +def say_whee(): + print("Whee!") + +class PP(object): + """ Class PP bla bla """ + def __init__(self): + """ __init__ ble ble ble """ + self.m1 = True + """ Not for m1 """ + + +print(PP.__doc__) +a = PP() +print(a.__init__.__doc__) +print(a.m1.__doc__) diff --git a/experiments/__doc__/macropy/application.py b/experiments/__doc__/macropy/application.py new file mode 100644 index 00000000..cd088a21 --- /dev/null +++ b/experiments/__doc__/macropy/application.py @@ -0,0 +1,24 @@ +from mymacros import macros, document + +with document: + # comentario a + a = "5.1" + """ docu a """ + b = False + """ docu b """ + c = 3 + """ docu c """ + +class d(object): + def __init__(self): + with document: + self.at1 = 4.5 + """ documenting d.at1 """ + + +print("a = "+str(a)+" # "+_help_a) +print("b = "+str(b)+" # "+_help_b) +print("c = "+str(c)+" # "+_help_c) +e = d() +print("e.at1 = "+str(e.at1)+" # "+e._help_at1) + diff --git a/experiments/__doc__/macropy/mymacros.py b/experiments/__doc__/macropy/mymacros.py new file mode 100644 index 00000000..d31e816a --- /dev/null +++ b/experiments/__doc__/macropy/mymacros.py @@ -0,0 +1,57 @@ +from macropy.core.macros import Macros +from ast import * + +macros = Macros() + +@macros.block +def document(tree, **kw): + """ This macro takes literal strings and converts them into: + _help_ID = type_hint+STRING + where: + ID is the first target of the last assignment. + type_hint is the assigned type and default value (only works for a few types) + STRING is the literal string """ + for n in range(len(tree)): + s = tree[n] + if not n: + prev = s + continue + # The whole sentence is a string? + if (isinstance(s, Expr) and isinstance(s.value, Str) and + # and the previous is an assign + isinstance(prev, Assign)): + # Apply it to the first target + target = prev.targets[0] + value = prev.value + # Extract its name + # variables and attributes are supported + if isinstance(target, Name): + name = target.id + is_attr = False + elif isinstance(target, Attribute): + name = target.attr + is_attr = True + else: + continue + # Remove starting underscore + if name[0] == '_': + name = name[1:] + # Create a _help_ID + doc_id = '_help_'+name + # Create the type hint for numbers, strings and booleans + type_hint = '' + if isinstance(value, Num): + type_hint = '[number={}]'.format(value.n) + elif isinstance(value, Str): + type_hint = "[string='{}']".format(value.s) + elif isinstance(value, NameConstant) and isinstance(value.value, bool): + type_hint = '[boolean={}]'.format(str(value.value).lower()) + # Transform the string into an assign for _help_ID + if is_attr: + target = Attribute(value=Name(id='self', ctx=Load()), attr=doc_id, ctx=Store()) + else: + target = Name(id=doc_id, ctx=Store()) + tree[n] = Assign(targets=[target], value=Str(s=type_hint+s.value.s)) + prev = s + # Return the modified AST + return tree diff --git a/experiments/__doc__/macropy/test_mymacros.py b/experiments/__doc__/macropy/test_mymacros.py new file mode 100755 index 00000000..8cdbd3e8 --- /dev/null +++ b/experiments/__doc__/macropy/test_mymacros.py @@ -0,0 +1,3 @@ +#!/usr/bin/python3 +import macropy.activate +import application diff --git a/experiments/__doc__/mcpy/application.py b/experiments/__doc__/mcpy/application.py new file mode 100644 index 00000000..cd088a21 --- /dev/null +++ b/experiments/__doc__/mcpy/application.py @@ -0,0 +1,24 @@ +from mymacros import macros, document + +with document: + # comentario a + a = "5.1" + """ docu a """ + b = False + """ docu b """ + c = 3 + """ docu c """ + +class d(object): + def __init__(self): + with document: + self.at1 = 4.5 + """ documenting d.at1 """ + + +print("a = "+str(a)+" # "+_help_a) +print("b = "+str(b)+" # "+_help_b) +print("c = "+str(c)+" # "+_help_c) +e = d() +print("e.at1 = "+str(e.at1)+" # "+e._help_at1) + diff --git a/experiments/__doc__/mcpy/mymacros.py b/experiments/__doc__/mcpy/mymacros.py new file mode 100644 index 00000000..78961d93 --- /dev/null +++ b/experiments/__doc__/mcpy/mymacros.py @@ -0,0 +1,53 @@ +from ast import * + +def document(sentences, to_source, **kw): + """ This macro takes literal strings and converts them into: + _help_ID = type_hint+STRING + where: + ID is the first target of the last assignment. + type_hint is the assigned type and default value (only works for a few types) + STRING is the literal string """ + for n in range(len(sentences)): + s = sentences[n] + if not n: + prev = s + continue + # The whole sentence is a string? + if (isinstance(s, Expr) and isinstance(s.value, Str) and + # and the previous is an assign + isinstance(prev, Assign)): + # Apply it to the first target + target = prev.targets[0] + value = prev.value + # Extract its name + # variables and attributes are supported + if isinstance(target, Name): + name = target.id + is_attr = False + elif isinstance(target, Attribute): + name = target.attr + is_attr = True + else: + continue + # Remove starting underscore + if name[0] == '_': + name = name[1:] + # Create a _help_ID + doc_id = '_help_'+name + # Create the type hint for numbers, strings and booleans + type_hint = '' + if isinstance(value, Num): + type_hint = '[number={}]'.format(value.n) + elif isinstance(value, Str): + type_hint = "[string='{}']".format(value.s) + elif isinstance(value, NameConstant) and isinstance(value.value, bool): + type_hint = '[boolean={}]'.format(str(value.value).lower()) + # Transform the string into an assign for _help_ID + if is_attr: + target = Attribute(value=Name(id='self', ctx=Load()), attr=doc_id, ctx=Store()) + else: + target = Name(id=doc_id, ctx=Store()) + sentences[n] = Assign(targets=[target], value=Str(s=type_hint+s.value.s)) + prev = s + # Return the modified AST + return sentences diff --git a/experiments/__doc__/mcpy/test_mymacros.py b/experiments/__doc__/mcpy/test_mymacros.py new file mode 100755 index 00000000..c9c7e312 --- /dev/null +++ b/experiments/__doc__/mcpy/test_mymacros.py @@ -0,0 +1,3 @@ +#!/usr/bin/python3 +import mcpy.activate +import application diff --git a/kiplot/config_reader.py b/kiplot/config_reader.py index 077a4c47..565cabd2 100644 --- a/kiplot/config_reader.py +++ b/kiplot/config_reader.py @@ -10,6 +10,7 @@ import pcbnew from .error import (KiPlotConfigurationError) from .kiplot import (Layer, get_layer_id_from_pcb) from .misc import (NO_YAML_MODULE, EXIT_BAD_CONFIG) +from mcpy import activate # Output classes from .out_base import BaseOutput from . import out_gerber # noqa: F401 diff --git a/kiplot/macros.py b/kiplot/macros.py new file mode 100644 index 00000000..72a4afe9 --- /dev/null +++ b/kiplot/macros.py @@ -0,0 +1,47 @@ +from ast import * + +def document(sentences, to_source, **kw): + """ This macro takes literal strings and converts them into: + _help_ID = type_hint+STRING + where: + ID is the first target of the last assignment. + type_hint is the assigned type and default value (only works for a few types) + STRING is the literal string """ + cur_attr = None + cur_value = None + for n in range(len(sentences)): + s = sentences[n] + if isinstance(s, Assign): + cur_target = s.targets[0] + if isinstance(cur_target, Name): + cur_attr = cur_target.id + is_attr = False + elif isinstance(cur_target, Attribute): + cur_attr = cur_target.attr + is_attr = True + else: + raise TypeError + cur_value = s.value + elif cur_attr and isinstance(s, Expr): + if isinstance(s.value, Str): + # Remove starting underscore + if cur_attr[0] == '_': + cur_attr = cur_attr[1:] + # Create a _help_ID + doc_id = '_help_'+cur_attr + # Create the type hint for numbers, strings and booleans + type_hint = '' + if isinstance(cur_value, Num): + type_hint = '[number={}]'.format(cur_value.n) + elif isinstance(cur_value, Str): + type_hint = "[string='{}']".format(cur_value.s) + elif isinstance(cur_value, NameConstant) and isinstance(cur_value.value, bool): + type_hint = '[boolean={}]'.format(str(cur_value.value).lower()) + # Transform the string into an assign for _help_ID + if is_attr: + cur_target = Attribute(value=Name(id='self', ctx=Load()), attr=doc_id, ctx=Store()) + else: + cur_target = Name(id=doc_id, ctx=Store()) + sentences[n] = Assign(targets=[cur_target], value=Str(s=type_hint+s.value.s)) + # Return the modified AST + return sentences diff --git a/kiplot/out_gerber.py b/kiplot/out_gerber.py index 3afed001..51c27b53 100644 --- a/kiplot/out_gerber.py +++ b/kiplot/out_gerber.py @@ -2,6 +2,7 @@ from pcbnew import (PLOT_FORMAT_GERBER) from .out_base import (BaseOutput) from .out_any_layer import (AnyLayer) from .error import KiPlotConfigurationError +from kiplot.macros import macros, document class Gerber(AnyLayer): @@ -9,14 +10,16 @@ class Gerber(AnyLayer): super(Gerber, self).__init__(name, type, description) self._plot_format = PLOT_FORMAT_GERBER # Options - self.use_aux_axis_as_origin = False - self.line_width = 0.1 - self.subtract_mask_from_silk = False - self.use_protel_extensions = False - self._gerber_precision = 4.6 - self.create_gerber_job_file = True - self.use_gerber_x2_attributes = True - self.use_gerber_net_attributes = True + with document: + self.use_aux_axis_as_origin = False + """ Auxiliar origin """ + self.line_width = 0.1 + self.subtract_mask_from_silk = False + self.use_protel_extensions = False + self._gerber_precision = 4.6 + self.create_gerber_job_file = True + self.use_gerber_x2_attributes = True + self.use_gerber_net_attributes = True @property def gerber_precision(self):