Skip to content

Commit

Permalink
Merge pull request #20 from yuchdev/code-19-html
Browse files Browse the repository at this point in the history
Code 19 html
  • Loading branch information
yuchdev authored Jan 31, 2023
2 parents 5216601 + 0bf267e commit c364751
Show file tree
Hide file tree
Showing 20 changed files with 1,946 additions and 1,043 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,7 @@ jobs:
- name: Run test
run: |
python release_package.py --mode install
python tests/test_cpp_generator.py
python tests/test_cpp_file.py
python tests/test_cpp_function_string.py
python tests/test_cpp_variable_string.py
python tests/test_html_generator.py
31 changes: 30 additions & 1 deletion release_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,23 @@ def tmp_release_notes():
return os.path.abspath(release_md)


def increment_minor_version(file_path: str):
"""
Increment minor package version number, e.g. 2.2.9 -> 2.2.10
:return: New version number
"""
config = ConfigParser()
config.read(file_path)
version = config['metadata']['version']
major, minor, patch = [int(v) for v in version.split('.')]
patch += 1
new_version = f"{major}.{minor}.{patch}"
config['metadata']['version'] = new_version
with open(file_path, 'w') as f:
config.write(f)
return new_version


def main():
parser = argparse.ArgumentParser(description='Command-line params')
parser.add_argument('--mode',
Expand All @@ -246,16 +263,28 @@ def main():
action='store_true',
required=False)
parser.add_argument('--publish-pypi',
help='Publish the package to PyPI',
help='Publish the package to PyPI server',
action='store_true',
default=False,
required=False)
parser.add_argument('--increment-version',
help='Increment minor version number, e.g. 2.2.9 -> 2.2.10',
action='store_true',
default=False,
required=False)
args = parser.parse_args()

global VERSION
print(f'Package name: {PACKAGE_NAME}')
print(f'Package name2: {PACKAGE_NAME_DASH}')
print(f'Version: {VERSION}')
sanity_check(args)

if args.increment_version:
new_version = increment_minor_version('setup.cfg')
VERSION = new_version
print(f'Increment version to {new_version}')

if args.mode == "build":
build_wheel()
elif args.mode == "install":
Expand Down
5 changes: 3 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
[metadata]
name = code_generation
version = 2.1.1
version = 2.2.44

[options]
packages = find:
python_requires = >=3.4
python_requires = >=3.8

[options.packages.find]
where = src

7 changes: 7 additions & 0 deletions src/code_generation/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
from . import cpp_array
from . import cpp_class
from . import cpp_enum
from . import cpp_function
from . import cpp_generator
from . import cpp_variable
from . import html_generator
from pathlib import Path
PACKAGE_ROOT = Path(__file__).parent
99 changes: 38 additions & 61 deletions src/code_generation/code_generator.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import sys
from code_generation.code_style import ANSICodeStyle

__doc__ = """
Simple and straightforward code generator that could be used for generating code
on any programming language and to be a 'building block' for creating more complicated
code generator.
Thanks to Eric Reynolds, the code mainly based on his article published on
http://www.codeproject.com/Articles/571645/Really-simple-Cplusplus-code-generation-in-Python
However, it was both simplified and extended
https://www.codeproject.com/Articles/571645/Really-simple-Cplusplus-code-generation-in-Python
However, it was both significantly extended since then and also simplified.
Used under the Code Project Open License
http://www.codeproject.com/info/cpol10.aspx
https://www.codeproject.com/info/cpol10.aspx
Examples of usage:
Expand All @@ -23,7 +26,7 @@
# Python code
cpp = CppFile('example.cpp')
with cpp.block('class A', ';'):
cpp.label('public:')
cpp.label('public')
cpp('int m_classMember1;')
cpp('double m_classMember2;')
Expand All @@ -41,56 +44,6 @@ class A
"""


class ANSICodeStyle:
"""
Class represents C++ {} close and its formatting style.
It supports ANSI C style with braces on the new lines, like that:
// C++ code
{
// C++ code
};
finishing postfix is optional (e.g. necessary for classes, unnecessary for namespaces)
"""

# EOL symbol
endline = "\n"

# Tab (indentation) symbol
indent = "\t"

def __init__(self, owner, text, postfix):
"""
@param: owner - CodeFile where text is written to
@param: text - text opening C++ close
@param: postfix - optional terminating symbol (e.g. ; for classes)
"""
self.owner = owner
if self.owner.last is not None:
with self.owner.last:
pass
self.owner.write("".join(text))
self.owner.last = self
self.postfix = postfix

def __enter__(self):
"""
Open code block
"""
self.owner.write("{")
self.owner.current_indent += 1
self.owner.last = None

def __exit__(self, *_):
"""
Close code block
"""
if self.owner.last is not None:
with self.owner.last:
pass
self.owner.current_indent -= 1
self.owner.write("}" + self.postfix)


class CodeFile:
"""
The class is a main instrument of code generation
Expand Down Expand Up @@ -147,27 +100,27 @@ def close(self):
self.out.close()
self.out = None

def write(self, text, indent=0):
def write(self, text, indent=0, endline=True):
"""
Write a new line with line ending
"""
self.out.write('{0}{1}{2}'.format(CodeFile.Formatter.indent * (self.current_indent+indent),
self.out.write('{0}{1}{2}'.format(self.Formatter.indent * (self.current_indent+indent),
text,
CodeFile.Formatter.endline))
self.Formatter.endline if endline else ''))

def append(self, x):
"""
Append to the existing line without line ending
"""
self.out.write(x)
self.out.write(x)

def __call__(self, text):
def __call__(self, text, indent=0, endline=True):
"""
Supports 'object()' semantic, i.e.
cpp('#include <iostream>')
inserts appropriate line
"""
self.write(text)
self.write(text, indent, endline)

def block(self, text, postfix=''):
"""
Expand All @@ -176,7 +129,13 @@ def block(self, text, postfix=''):
cpp.block(class_name, ';'):
"""
return CodeFile.Formatter(self, text, postfix)


def endline(self, count=1):
"""
Insert an endline
"""
self.write(CodeFile.Formatter.endline * count, endline=False)

def newline(self, n=1):
"""
Insert one or several empty lines
Expand All @@ -202,3 +161,21 @@ def label(self, text):
a:
"""
self.write('{0}:'.format(text), -1)


def cpp_example():
cpp = CppFile('example.cpp')
with cpp.block('class A', ';'):
cpp.label('public')
cpp('int m_classMember1;')
cpp('double m_classMember2;')


def main():
cpp_example()
return 0


if __name__ == '__main__':
sys.exit(main())

103 changes: 103 additions & 0 deletions src/code_generation/code_style.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
__doc__ = """Formatters for different styles of code generation
"""


class ANSICodeStyle:
"""
Class represents C++ {} close and its formatting style.
It supports ANSI C style with braces on the new lines, like that:
// C++ code
{
// C++ code
};
finishing postfix is optional (e.g. necessary for classes, unnecessary for namespaces)
"""

# EOL symbol
endline = "\n"

# Tab (indentation) symbol
indent = "\t"

def __init__(self, owner, text, postfix):
"""
@param: owner - CodeFile where text is written to
@param: text - text opening C++ close
@param: postfix - optional terminating symbol (e.g. ; for classes)
"""
self.owner = owner
if self.owner.last is not None:
with self.owner.last:
pass
self.owner.write("".join(text))
self.owner.last = self
self.postfix = postfix

def __enter__(self):
"""
Open code block
"""
self.owner.write("{")
self.owner.current_indent += 1
self.owner.last = None

def __exit__(self, *_):
"""
Close code block
"""
if self.owner.last is not None:
with self.owner.last:
pass
self.owner.current_indent -= 1
self.owner.write("}" + self.postfix)


class HTMLStyle:
"""
Class representing HTML close and its formatting style.
It supports HTML DOM-tree style, like that:
// HTML code
<element attributes>
// HTML content
</element>
"""
# EOL symbol
endline = "\n"

# Tab (indentation) symbol is 2 spaces
indent = " "

def __init__(self, owner, element, *attrs, **kwattrs):
"""
@param: owner - CodeFile where text is written to
@param: element - HTML element name
@param: attrs - optional opening tag content, like attributes ['class="class1"', 'id="id1"']
@param: kwattrs - optional opening tag attributes, like class="class1", id="id1"
"""
self.owner = owner
if self.owner.last is not None:
with self.owner.last:
pass
self.element = element
attributes = "".join(f' {attr}' for attr in attrs)
attributes += "".join(f' {key}="{value}"' for key, value in kwattrs.items())
self.attributes = attributes
self.owner.last = self

def __enter__(self):
"""
Open code block
"""
self.owner.write(f"<{self.element}{self.attributes}>")
self.owner.current_indent += 1
self.owner.last = None

def __exit__(self, *_):
"""
Close code block
"""
if self.owner.last is not None:
with self.owner.last:
pass
self.owner.current_indent -= 1
self.owner.write(f"</{self.element}>")
Loading

0 comments on commit c364751

Please sign in to comment.