Skip to content

Commit

Permalink
New distribution [0.1.1]
Browse files Browse the repository at this point in the history
 * fixed classvar conversion error
 * revised linting system
 * revised packaging
 * revised unittest
  • Loading branch information
JarryShaw committed Nov 26, 2019
1 parent 71d7ed2 commit 394dccd
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 43 deletions.
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ prune .vscode

prune scripts
prune share
prune tests
prune Tap
6 changes: 3 additions & 3 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
long_desc = file.read()

# version string
__version__ = '0.1.0'
__version__ = '0.1.1'

# set-up script for pip distribution
setup(
Expand Down
2 changes: 1 addition & 1 deletion share/walrus.1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH WALRUS 1 "November 25, 2019" "v0.1.0" ""
.TH WALRUS 1 "November 26, 2019" "v0.1.1" ""
.SH NAME
walrus \- back-port compiler for Python 3.8 assignment expression
.
Expand Down
4 changes: 2 additions & 2 deletions share/walrus.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ walrus
back-port compiler for Python 3.8 assignment expression
-------------------------------------------------------

:Version: v0.1.0
:Date: November 25, 2019
:Version: v0.1.1
:Date: November 26, 2019
:Manual section: 1
:Author:
Jarry Shaw, a newbie programmer, is the author, owner and maintainer
Expand Down
24 changes: 24 additions & 0 deletions tests/test.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# -*- coding: utf-8 -*-
"""Unittest cases."""

import os
import shutil
import subprocess
Expand All @@ -7,6 +10,7 @@

from walrus import get_parser
from walrus import main as main_func
from walrus import walrus as core_func

# root path
ROOT = os.path.dirname(os.path.realpath(__file__))
Expand All @@ -18,11 +22,14 @@


def read_text_file(filename, encoding='utf-8'):
"""Read text file."""
with open(filename, 'r', encoding=encoding) as file:
return file.read()


class TestWalrus(unittest.TestCase):
"""Test case."""

def test_get_parser(self):
"""Test the argument parser."""
parser = get_parser()
Expand Down Expand Up @@ -59,6 +66,23 @@ def test_main(self):
converted_output = subprocess.check_output([sys.executable, os.path.join(tmpdir, test_case + '.py')], universal_newlines=True) # pylint: disable=line-too-long
self.assertEqual(original_output, converted_output)

def test_core(self):
"""Test the core function."""
with tempfile.TemporaryDirectory(prefix='walrus-test') as tmpdir:
all_test_cases = [fn[:-3] for fn in os.listdir(os.path.join(ROOT, 'sample')) if fn.endswith('.py')]

for test_case in all_test_cases:
shutil.copy(os.path.join(ROOT, 'sample', test_case + '.py'), tmpdir)

for entry in os.scandir(tmpdir):
core_func(entry.path)

for test_case in all_test_cases:
with self.subTest(test_case=test_case):
original_output = read_text_file(os.path.join(ROOT, 'sample', test_case + '.out'))
converted_output = subprocess.check_output([sys.executable, os.path.join(tmpdir, test_case + '.py')], universal_newlines=True) # pylint: disable=line-too-long
self.assertEqual(original_output, converted_output)


if __name__ == '__main__':
sys.exit(unittest.main())
114 changes: 78 additions & 36 deletions walrus.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
del multiprocessing

# version string
__version__ = '0.1.0'
__version__ = '0.1.1'

# from configparser
BOOLEAN_STATES = {'1': True, '0': False,
Expand Down Expand Up @@ -92,12 +92,12 @@ def __walrus_wrapper_%(name)s_%(uuid)s(expr):

# special templates for ClassVar
## locals dict
LCL_DICT_TEMPLATE = 'walrus_wrapper_%(cls)s_dict = dict()'
LCL_NAME_TEMPLATE = 'walrus_wrapper_%(cls)s_dict[%(name)r]'
LCL_DICT_TEMPLATE = '_walrus_wrapper_%(cls)s_dict = dict()'
LCL_NAME_TEMPLATE = '_walrus_wrapper_%(cls)s_dict[%(name)r]'
LCL_CALL_TEMPLATE = '__WalrusWrapper%(cls)s.get_%(name)s_%(uuid)s(locals())'
LCL_VARS_TEMPLATE = '''\
[setattr(%(cls)s, k, v) for k, v in walrus_wrapper_%(cls)s_dict.items()]
del walrus_wrapper_%(cls)s_dict
[setattr(%(cls)s, k, v) for k, v in _walrus_wrapper_%(cls)s_dict.items()]
del _walrus_wrapper_%(cls)s_dict
'''.splitlines() # `str.splitlines` will remove trailing newline
## class clause
CLS_CALL_TEMPLATE = '__WalrusWrapper%(cls)s.set_%(name)s_%(uuid)s(%(expr)s)'
Expand All @@ -109,15 +109,15 @@ class __WalrusWrapper%(cls)s:
%(tabsize)s@staticmethod
%(tabsize)sdef set_%(name)s_%(uuid)s(expr):
%(tabsize)s%(tabsize)s"""Wrapper function for assignment expression."""
%(tabsize)s%(tabsize)swalrus_wrapper_%(cls)s_dict[%(name)r] = expr
%(tabsize)s%(tabsize)sreturn walrus_wrapper_%(cls)s_dict[%(name)r]
%(tabsize)s%(tabsize)s_walrus_wrapper_%(cls)s_dict[%(name)r] = expr
%(tabsize)s%(tabsize)sreturn _walrus_wrapper_%(cls)s_dict[%(name)r]
%(tabsize)s@staticmethod
%(tabsize)sdef get_%(name)s_%(uuid)s(locals_=locals()):
%(tabsize)s%(tabsize)s"""Wrapper function for assignment expression."""
%(tabsize)s%(tabsize)s# get value from buffer dict
%(tabsize)s%(tabsize)stry:
%(tabsize)s%(tabsize)s%(tabsize)sreturn walrus_wrapper_%(cls)s_dict[%(name)r]
%(tabsize)s%(tabsize)s%(tabsize)sreturn _walrus_wrapper_%(cls)s_dict[%(name)r]
%(tabsize)s%(tabsize)sexcept KeyError:
%(tabsize)s%(tabsize)s%(tabsize)spass
Expand Down Expand Up @@ -393,17 +393,27 @@ def _process_classdef(self, node):
"""
flag = self.has_walrus(node)
code = node.get_code()

# <Name: ...>
name = node.name
if flag:
if self._linting:
buffer = self._prefix if self._prefix_or_suffix else self._suffix

self += self._linesep * self.missing_whitespaces(prefix=buffer, suffix=code,
blank=1, linesep=self._linesep)

self += '\t'.expandtabs(self._column) \
+ LCL_DICT_TEMPLATE % dict(cls=name.value) \
+ self._linesep

if self._linting:
count = self.missing_whitespaces(node.get_code(), blank=2, direction=True)
self += self._linesep * count
blank = 2 if self._column == 0 else 1
buffer = self._prefix if self._prefix_or_suffix else self._suffix

self += self._linesep * self.missing_whitespaces(prefix=buffer, suffix=code,
blank=1, linesep=self._linesep)

# <Keyword: class>
# <Name: ...>
Expand All @@ -421,14 +431,25 @@ def _process_classdef(self, node):
tabsize = '\t'.expandtabs(self._tabsize)

if self._linting:
self += self._linesep * self.missing_whitespaces(node.get_code(), blank=2, direction=False)
blank = 2 if self._column == 0 else 1
buffer = self._prefix if self._prefix_or_suffix else self._suffix
self += self._linesep * self.missing_whitespaces(prefix=buffer, suffix='',
blank=blank, linesep=self._linesep)

self += indent \
+ ('%s%s' % (self._linesep, indent)).join(LCL_VARS_TEMPLATE) % dict(tabsize=tabsize, cls=name.value) \
+ self._linesep

if self._linting:
self += self._linesep * self.missing_whitespaces(node.get_code(), blank=1, direction=True)
buffer = self._prefix if self._prefix_or_suffix else self._suffix

code = ''
leaf = node.get_next_leaf()
while leaf is not None:
code += leaf.get_code()
leaf = leaf.get_next_leaf()
self += self._linesep * self.missing_whitespaces(prefix=buffer, suffix=code,
blank=1, linesep=self._linesep)

def _process_funcdef(self, node):
"""Process function definition (``funcdef``).
Expand Down Expand Up @@ -639,14 +660,15 @@ def _concat(self):

# first, the prefix codes
self._buffer += self._prefix + prefix
if self._linting:
if self._node_before_walrus is None:
blank = 0
elif self._node_before_walrus.type in ('funcdef', 'classdef'):
if flag and self._linting and self._vars:
if (self._node_before_walrus is not None \
and self._node_before_walrus.type in ('funcdef', 'classdef') \
and self._column == 0):
blank = 2
else:
blank = 1
self._buffer += self._linesep * self.missing_whitespaces(self._buffer, blank=blank, direction=False)
self._buffer += self._linesep * self.missing_whitespaces(prefix=self._buffer, suffix='',
blank=blank, linesep=self._linesep)

# then, the variables and functions
indent = '\t'.expandtabs(self._column)
Expand All @@ -665,8 +687,10 @@ def _concat(self):
).join(FUNC_TEMPLATE) % dict(tabsize=tabsize, **func) + self._linesep

# finally, the suffix codes
if flag and self._linting:
self._buffer += self._linesep * self.missing_whitespaces(suffix, blank=2, direction=True)
if flag and self._linting and self._vars:
blank = 2 if self._column == 0 else 1
self._buffer += self._linesep * self.missing_whitespaces(prefix=self._buffer, suffix=suffix,
blank=blank, linesep=self._linesep)
self._buffer += suffix

def _strip(self):
Expand Down Expand Up @@ -821,28 +845,35 @@ def is_walrus(node):
return False

@staticmethod
def missing_whitespaces(code, blank, direction):
def missing_whitespaces(prefix, suffix, blank, linesep):
"""Count missing preceding or succeeding blank lines.
Args:
- `code` -- `str`, source code
- `direction` -- `bool`, `True` for preceding; `False` for succeeding
- `prefix` -- `str`, preceding source code
- `suffix` -- `str`, succeeding source code
- `blank` -- `int`, number of expecting blank lines
- `linesep` -- `str`, line seperator
Returns:
- `int` -- number of preceding blank lines
"""
lines = code.splitlines()
if not direction:
lines = reversed(code.splitlines())

count = 0
for line in lines:
if line.strip():
break
count += 1

count = -1 # keep trailing newline in `prefix`
if prefix:
for line in reversed(prefix.split(linesep)):
if line.strip():
break
count += 1
if suffix:
for line in suffix.split(linesep):
if line.strip():
break
count += 1

if count < 0:
count = 0
missing = blank - count

if missing > 0:
return missing
return 0
Expand Down Expand Up @@ -1051,6 +1082,8 @@ def _process_name(self, node):

def _concat(self):
"""Concatenate final string."""
flag = self.has_walrus(self._root)

# strip suffix comments
prefix, suffix = self._strip()

Expand All @@ -1061,9 +1094,16 @@ def _concat(self):
indent = '\t'.expandtabs(self._column)
tabsize = '\t'.expandtabs(self._tabsize)
linesep = self._linesep
if self.has_walrus(self._root):
if flag:
if self._linting:
self._buffer += self._linesep * self.missing_whitespaces(self._buffer, blank=1, direction=False)
if (self._node_before_walrus is not None
and self._node_before_walrus.type in ('funcdef', 'classdef')
and self._column == 0):
blank = 2
else:
blank = 1
self._buffer += self._linesep * self.missing_whitespaces(prefix=self._buffer, suffix='',
blank=blank, linesep=self._linesep)
self._buffer += indent + (
'%s%s' % (self._linesep, indent)
).join(CLS_NAME_TEMPLATE) % dict(tabsize=tabsize, cls=self._cls_ctx) + linesep
Expand All @@ -1073,8 +1113,10 @@ def _concat(self):
).join(CLS_FUNC_TEMPLATE) % dict(tabsize=tabsize, cls=self._cls_ctx, **func) + linesep

# finally, the suffix codes
if self._linting:
self._buffer += self._linesep * self.missing_whitespaces(suffix, blank=1, direction=True)
if flag and self._linting:
blank = 2 if self._column == 0 else 1
self._buffer += self._linesep * self.missing_whitespaces(prefix=self._buffer, suffix=suffix,
blank=blank, linesep=self._linesep)
self._buffer += suffix


Expand Down

0 comments on commit 394dccd

Please sign in to comment.