-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7ff6577
commit 6eba502
Showing
12 changed files
with
364 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,4 @@ | ||
__version__ = 0.0.1 | ||
__version__ = "0.0.1" | ||
|
||
from .blueprint import * | ||
from .utils import * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import glob | ||
import os | ||
|
||
from jinja2 import Environment, FileSystemLoader, PackageLoader, Template | ||
|
||
from antigen import components_dir | ||
|
||
from .utils import files_in_folder, stdout_logger | ||
|
||
log = stdout_logger(__name__) | ||
|
||
jinja_env = Environment(loader=FileSystemLoader(components_dir)) | ||
|
||
############################################################################### | ||
## Blueprint | ||
############################################################################### | ||
|
||
|
||
def component_is_valid(component): | ||
|
||
if "component" not in component: | ||
log.warning("component field missing in definition") | ||
return False | ||
|
||
fields = ["component", "id", "props", "children"] | ||
for f in fields: | ||
if f not in component: | ||
log.warning(f"{f} missing in component: {component['component']}") | ||
return False | ||
return True | ||
|
||
|
||
def create_component(component: dict, path: str, templates: str) -> str: | ||
""" | ||
Args: | ||
component: component definition ('component', 'id', 'props', 'children' keys are used in generation) | ||
path: path to create component js file | ||
templates: path to template folder | ||
Returns: | ||
str: path to component js file | ||
""" | ||
|
||
if os.path.isfile(path): | ||
raise Exception(f"{path} already exists") | ||
|
||
if not component_is_valid(component): | ||
raise Exception(f"invalid component") | ||
|
||
templates = jinja_env.list_templates() | ||
log.debug(templates) | ||
|
||
if f"{component['component']}.js" in templates: | ||
template = f"{component['component']}.js" | ||
elif "Default.js" in templates: | ||
log.debug(f"no template found for f{component['component']} using Default.js") | ||
template = "Default.js" | ||
else: | ||
raise Exception(f"no component templates found for {component['component']}") | ||
|
||
with open(path, "w") as f: | ||
log.debug(f"Generating template {template} -> {path} ...") | ||
f.write( | ||
jinja_env.get_template(template).render( | ||
id=component["id"], | ||
component=component["component"], | ||
children=component["children"], | ||
props=component["props"], | ||
) | ||
) | ||
|
||
return path |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
function {{component}}(props) { | ||
|
||
return ( | ||
<div id="{{id}}">{{children}}</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
components: | ||
|
||
- component: TextBox | ||
props: | ||
id: standard-basic | ||
label: Standard | ||
children: Hello World! |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import logging | ||
import os | ||
import shutil | ||
import sys | ||
|
||
import yaml | ||
|
||
############################################################################### | ||
## Important Paths | ||
############################################################################### | ||
|
||
module_dir = os.path.dirname(sys.modules["antigen"].__file__) | ||
resources_dir = os.path.join(module_dir, "resources") | ||
components_dir = os.path.join(resources_dir, "components") | ||
examples_dir = os.path.join(resources_dir, "examples") | ||
|
||
############################################################################### | ||
## General | ||
############################################################################### | ||
|
||
|
||
def read_yaml(file): | ||
with open(file, "r") as f: | ||
return yaml.load(f, Loader=yaml.FullLoader) | ||
|
||
|
||
def reverse_dictionary(d): | ||
return {v: k for k, v in d.items()} | ||
|
||
|
||
def delete_directory(directory): | ||
if os.path.isdir(directory): | ||
shutil.rmtree(directory) | ||
|
||
|
||
def make_directory(directory, delete=False, exist_ok=True): | ||
if delete: | ||
delete_directory(directory) | ||
if not os.path.isdir(directory): | ||
os.makedirs(directory, exist_ok=exist_ok) | ||
return os.path.abspath(directory) | ||
|
||
|
||
def files_in_folder(folder): | ||
return [ | ||
os.path.join(folder, n) | ||
for n in os.listdir(folder) | ||
if os.path.isfile(os.path.join(folder, n)) | ||
] | ||
|
||
|
||
def folders_in_folder(folder): | ||
return [ | ||
os.path.join(folder, n) | ||
for n in os.listdir(folder) | ||
if os.path.isdir(os.path.join(folder, n)) | ||
] | ||
|
||
|
||
def stdout_logger(name): | ||
""" | ||
Use this logger to standardize log output | ||
""" | ||
log = logging.getLogger(name) | ||
log.propagate = False | ||
stream_handler = logging.StreamHandler(sys.stdout) | ||
formatter = logging.Formatter("%(levelname)-8s %(message)s") | ||
stream_handler.setFormatter(formatter) | ||
stream_handler.setLevel(logging.DEBUG) | ||
log.handlers = [stream_handler] | ||
log.setLevel(logging.DEBUG) | ||
return log | ||
|
||
|
||
class class_or_instance_method(classmethod): | ||
def __get__(self, instance, type_): | ||
descr_get = super().__get__ if instance is None else self.__func__.__get__ | ||
return descr_get(instance, type_) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
#!/usr/bin/env python3 | ||
|
||
import argparse | ||
import os | ||
import re | ||
import shutil | ||
import subprocess | ||
import sys | ||
import tempfile | ||
from glob import glob | ||
from importlib import import_module | ||
|
||
from jinja2 import Environment, FileSystemLoader, PackageLoader, Template | ||
|
||
from antigen import folders_in_folder, read_yaml, stdout_logger | ||
|
||
log = stdout_logger(__name__) | ||
module_folder = os.path.dirname(sys.modules["antigen"].__file__) | ||
resources_folder = os.path.join(module_folder, "resources") | ||
current_folder = os.path.abspath(os.curdir) | ||
|
||
templates = { | ||
os.path.basename(t): t | ||
for t in folders_in_folder(os.path.join(module_folder, "resources", "templates")) | ||
} | ||
|
||
# parsers | ||
parser = argparse.ArgumentParser(description="declarative ui generation") | ||
subparsers = parser.add_subparsers(dest="subcommand") | ||
|
||
# parsers - blueprint | ||
generate_parser = subparsers.add_parser( | ||
"blueprint", description="generate components from blueprint" | ||
) | ||
generate_parser.add_argument("path", help="path to blueprint YAML") | ||
|
||
args = parser.parse_args() | ||
|
||
try: | ||
|
||
if args.subcommand == "blueprint": | ||
log.debug(read_yaml(args.path)) | ||
|
||
else: | ||
parser.print_help() | ||
|
||
except Exception as e: | ||
log.error(e) | ||
parser.print_help() | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,21 @@ | ||
from distutils.core import setup | ||
from antigen import __version__ | ||
|
||
from setuptools import find_packages | ||
|
||
from antigen import __version__ | ||
|
||
setup( | ||
name="antigen", | ||
version=__version__, | ||
author="shirecoding", | ||
author_email="[email protected]", | ||
scripts=["bin/antigen"], | ||
install_requires=["Jinja2"], | ||
install_requires=[ | ||
"Jinja2", | ||
"pytest", | ||
"pytest-html", | ||
"pytest-cov", | ||
], | ||
url="https://github.com/shirecoding/Antigen", | ||
download_url=f"https://github.com/shirecoding/Antigen/archive/{__version__}.tar.gz", | ||
long_description=open("README.md").read(), | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[run] | ||
data_file = reports/.coverage |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
from datetime import datetime | ||
|
||
import pytest | ||
from py.xml import html | ||
|
||
########################################################################################### | ||
## REPORT | ||
########################################################################################### | ||
|
||
|
||
def stringToCellData(string, class_): | ||
return html.td([html.p(s) for s in string.split("\n")], class_=class_) | ||
|
||
|
||
@pytest.mark.optionalhook | ||
def pytest_html_results_table_header(cells): | ||
cells.insert(1, html.th("Specification", class_="spec", col="spec")) | ||
cells.insert(2, html.th("Description")) | ||
cells.insert(3, html.th("Procedure", class_="proc", col="proc")) | ||
cells.insert(4, html.th("Expected", class_="expec", col="expec")) | ||
cells.pop() # remove links column | ||
|
||
|
||
@pytest.mark.optionalhook | ||
def pytest_html_results_table_row(report, cells): | ||
cells.insert(1, stringToCellData(report.specification, class_="col-spec")) | ||
cells.insert(2, stringToCellData(report.description, class_="col-desc")) | ||
cells.insert(3, stringToCellData(report.procedure, class_="col-proc")) | ||
cells.insert(4, stringToCellData(report.expected, class_="col-expec")) | ||
cells.pop() # remove links column | ||
|
||
|
||
@pytest.hookimpl(hookwrapper=True) | ||
def pytest_runtest_makereport(item, call): | ||
outcome = yield | ||
report = outcome.get_result() | ||
report.description = str(item.function.__doc__ if item.function.__doc__ else "") | ||
marker = item.get_closest_marker("report") | ||
|
||
report.specification = ( | ||
marker.kwargs["specification"] | ||
if marker and "specification" in marker.kwargs | ||
else "" | ||
) | ||
|
||
report.procedure = ( | ||
marker.kwargs["procedure"] if marker and "procedure" in marker.kwargs else "" | ||
) | ||
|
||
report.expected = ( | ||
marker.kwargs["expected"] if marker and "expected" in marker.kwargs else "" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
[pytest] | ||
addopts = | ||
--assert='plain' | ||
--html=reports/pytest_report.html | ||
--junitxml=reports/pytest_report.xml | ||
--self-contained-html | ||
--cov=antigen | ||
--cov-report=xml:reports/coverage.xml | ||
--cov-report=html:reports/coverage | ||
--cov-config=tests/.coveragerc | ||
log_cli = true | ||
log_level = DEBUG | ||
markers = | ||
report |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import logging | ||
import os | ||
import re | ||
import tempfile | ||
|
||
import pytest | ||
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
@pytest.mark.report( | ||
specification=""" | ||
""", | ||
procedure=""" | ||
""", | ||
expected=""" | ||
""", | ||
) | ||
def test_valid_component(): | ||
""" | ||
Test component validation function | ||
""" | ||
from antigen import component_is_valid, components_dir, create_component | ||
|
||
c1 = { | ||
"component": "TextField", | ||
"id": "TextField1", | ||
"props": {}, | ||
"children": "Hello World", | ||
} | ||
|
||
assert component_is_valid(c1) == True | ||
|
||
c2 = {"id": "TextField1", "props": {}, "children": "Hello World"} | ||
|
||
assert component_is_valid(c2) == False | ||
|
||
|
||
@pytest.mark.report( | ||
specification=""" | ||
""", | ||
procedure=""" | ||
""", | ||
expected=""" | ||
""", | ||
) | ||
def test_create_component(): | ||
""" | ||
Test component creation function | ||
""" | ||
|
||
from antigen import components_dir, create_component | ||
|
||
c1 = { | ||
"component": "TextField", | ||
"id": "TextField1", | ||
"props": {}, | ||
"children": "Hello World", | ||
} | ||
|
||
with tempfile.TemporaryDirectory() as folder: | ||
component_path = create_component( | ||
c1, os.path.join(folder, "c1"), components_dir | ||
) | ||
|
||
with open(component_path, "r") as file: | ||
data = file.read() | ||
assert re.match(r"^.*id=\"TextField1\".*$", data, re.DOTALL) != None | ||
assert re.match(r"^.*>Hello World<.*$", data, re.DOTALL) != None | ||
assert re.match(r"^.*TextField\(props\).*$", data, re.DOTALL) != None |