diff --git a/Makefile b/Makefile index 9a1ee0e..d72f49c 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ DIST_DIR := $(PROJECT_ROOT)/dist PROJECT=plim .PHONY: test -test: +test: typecheck pytest -s --cov=plim --cov-report xml $(PROJECT_ROOT)/tests .PHONY: typecheck diff --git a/plim/console.py b/plim/console.py index 69bf82c..736d05f 100644 --- a/plim/console.py +++ b/plim/console.py @@ -43,7 +43,7 @@ def plimc(args=None, stdout=None): # Add an empty string path, so modules located at the current working dir # are reachable and considered in the first place (see issue #32). sys.path.insert(0, '') - preprocessor = EntryPoint.parse('x={}'.format(preprocessor_path)).load(False) + preprocessor = EntryPoint.parse('x={}'.format(preprocessor_path)).resolve() # Render to html, if requested # ---------------------------- diff --git a/plim/lexer.py b/plim/lexer.py index 6bc00f8..7cf7c71 100644 --- a/plim/lexer.py +++ b/plim/lexer.py @@ -5,6 +5,7 @@ from typing import Optional, Tuple, Any, Mapping, Callable, Iterator import markdown2 +from pyrsistent import v from . import errors from .util import StringIO, MAXSIZE, joined, space_separated, u @@ -62,21 +63,21 @@ INLINE_PYTHON_TERMINATOR = '---' -CSS_ID_SHORTCUT_TERMINATORS = ( +CSS_ID_SHORTCUT_TERMINATORS = v( CSS_CLASS_SHORTCUT_DELIMITER, WHITESPACE, OPEN_BRACE, INLINE_TAG_SEPARATOR ) -CSS_CLASS_SHORTCUT_TERMINATORS = ( +CSS_CLASS_SHORTCUT_TERMINATORS = v( CSS_CLASS_SHORTCUT_DELIMITER, WHITESPACE, OPEN_BRACE, INLINE_TAG_SEPARATOR ) -ATTRIBUTE_TERMINATORS = ( +ATTRIBUTE_TERMINATORS = v( ATTRIBUTE_VALUE_DELIMITER, ATTRIBUTES_DELIMITER, INLINE_TAG_SEPARATOR, @@ -84,13 +85,13 @@ LITERAL_CONTENT_SPACE_PREFIX ) -ATTRIBUTE_TERMINATORS_WITH_PARENTHESES = ( +ATTRIBUTE_TERMINATORS_WITH_PARENTHESES = v( ATTRIBUTE_VALUE_DELIMITER, ATTRIBUTES_DELIMITER, CLOSE_BRACE ) -ATTRIBUTE_VALUE_TERMINATORS = ( +ATTRIBUTE_VALUE_TERMINATORS = v( ATTRIBUTES_DELIMITER, INLINE_TAG_SEPARATOR, LITERAL_CONTENT_PREFIX, @@ -99,7 +100,7 @@ BOOLEAN_ATTRIBUTE_MARKER ) -ATTRIBUTE_VALUE_TERMINATORS_WITH_PARENTHESES = ( +ATTRIBUTE_VALUE_TERMINATORS_WITH_PARENTHESES = v( ATTRIBUTES_DELIMITER, INLINE_TAG_SEPARATOR, LITERAL_CONTENT_PREFIX, @@ -674,13 +675,13 @@ def extract_tag_line(line, source, syntax): if css_id: attributes.append(u('id="{ids}"').format(ids=css_id)) if class_identifiers: - class_identifiers = space_separated(class_identifiers) - attributes.append(u('class="{classes}"').format(classes=class_identifiers)) + class_identifiers_str = space_separated(class_identifiers) + attributes.append(u('class="{classes}"').format(classes=class_identifiers_str)) break - attributes = space_separated(attributes) - components['attributes'] = attributes - if attributes: - tag_composer.extend([' ', attributes]) + attributes_str = space_separated(attributes) + components['attributes'] = attributes_str + if attributes_str: + tag_composer.extend([' ', attributes_str]) # 3.2 syntax check if inside_parentheses: @@ -1285,8 +1286,8 @@ def prepare_result(buf): if align > new_align: align = new_align # remove preceding spaces - line = current_line[align:].rstrip() - buf.extend([line.rstrip(), "\n"]) + ne_line = current_line[align:].rstrip() + buf.extend([ne_line.rstrip(), "\n"]) result = prepare_result(buf) return result, 0, '', source @@ -1331,7 +1332,7 @@ def _parse_embedded_markup(content, syntax): return joined(buf) -def _inject_n_filter(line): +def _inject_n_filter(line: str) -> str: """ This is a helper function for :func:parse_variable @@ -1373,19 +1374,19 @@ def parse_variable(indent_level, __, matched, source, syntax): if not line: continue if indent <= indent_level: - buf = joined(buf) + buf_str = joined(buf) if prevent_escape: - buf = _inject_n_filter(buf) + buf_str = _inject_n_filter(buf_str) # add a closing brace to complete variable expression syntax ("${}" in case of mako). - buf += syntax.VARIABLE_PLACEHOLDER_END_SEQUENCE + explicit_space - return buf, indent, line, source + buf_str += syntax.VARIABLE_PLACEHOLDER_END_SEQUENCE + explicit_space + return buf_str, indent, line, source buf.append(line.strip()) - buf = joined(buf) + buf_str = joined(buf) if prevent_escape: - buf = _inject_n_filter(buf) - buf += syntax.VARIABLE_PLACEHOLDER_END_SEQUENCE + explicit_space - return buf, 0, '', source + buf_str = _inject_n_filter(buf_str) + buf_str += syntax.VARIABLE_PLACEHOLDER_END_SEQUENCE + explicit_space + return buf_str, 0, '', source def parse_early_return(indent_level, __, matched, source, syntax): @@ -1554,14 +1555,13 @@ def enumerate_source(source): return enumerate(StringIO(source), start=1) -def scan_line(line): +def scan_line(line: str) -> Tuple[Optional[int], Optional[str]]: """ Returns a 2-tuple of (length_of_the_indentation, line_without_preceding_indentation) - - :param line: - :type line: str """ match = LINE_PARTS_RE.match(line) - return len(match.group('indent')), match.group('line') + if match: + return len(match.group('indent')), match.group('line') + return None, None def compile_plim_source(source, syntax, strip=True): @@ -1593,10 +1593,10 @@ def compile_plim_source(source, syntax, strip=True): parsed_data, tail_indent, tail_line, source = parse(tail_indent, tail_line, matched_obj, source, syntax) result.append(parsed_data) - result = joined(result) + result_str = joined(result) if strip: - result = result.strip() - return result + result_str = result_str.strip() + return result_str # Acknowledgements diff --git a/plim/syntax.py b/plim/syntax.py index 32539ab..3ff1b08 100644 --- a/plim/syntax.py +++ b/plim/syntax.py @@ -104,8 +104,8 @@ class Django(BaseSyntax): STATEMENT_END_START_SEQUENCE = STATEMENT_START_START_SEQUENCE STATEMENT_END_END_SEQUENCE = STATEMENT_START_END_SEQUENCE - PARSE_MAKO_ONE_LINERS_RE = None - PARSE_MAKO_TEXT_RE = None + PARSE_MAKO_ONE_LINERS_RE = None # type: ignore + PARSE_MAKO_TEXT_RE = None # type: ignore def __str__(self): return 'Django Syntax' diff --git a/plim/util.py b/plim/util.py index 5f4b0e2..6746da6 100644 --- a/plim/util.py +++ b/plim/util.py @@ -1,12 +1,15 @@ import sys -from typing import Sequence +from typing import Sequence, Iterable PY3K = sys.version_info >= (3, 0) from io import StringIO -def joined(buf: Sequence[str], sep: str = '') -> str: +def joined(buf: Iterable[str], sep: str = '') -> str: + """ note: `buf` iterable will be fully consumed, so if you are passing a stream make sure you tee it + if you need to use the `buf` again later + """ return sep.join(buf) diff --git a/requirements.txt b/requirements.txt index bfec571..2ac49ff 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ Mako>=0.9.0 +pyrsistent>=0.18.1 babel>=1.3 # We use reStructuredText (docutils component) for both supporting # the "-rest" extension and project documenting. So, ensure that the docutils diff --git a/setup.py b/setup.py index 47043cc..45b269c 100644 --- a/setup.py +++ b/setup.py @@ -37,7 +37,7 @@ def read(*filenames, **kwargs): setup( name='Plim', - version='1.0.0', + version='1.1.0', packages=find_packages(exclude=['tests', 'nixpkgs', 'node_modules']), install_requires=requires, setup_requires=[],