pyexcel2mustache 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,74 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyexcel2mustache
3
+ Version: 0.1.1
4
+ Summary: Convert Excel files to Mustache templates based on a defined schema.
5
+ Author-email: oNsemy <onsemy@gmail.com>
6
+ Requires-Python: >=3.8
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: openpyxl>=3.1.0
9
+ Requires-Dist: pystache>=0.6.0
10
+
11
+ # pyexcel2mustache
12
+
13
+ Convert Excel (`xlsx`) sheets into Mustache templates based on a defined schema. This is now a distributable Python package.
14
+
15
+ ## Features
16
+
17
+ - Convert multiple sheets at once using customizable schemas.
18
+ - Skip sheets starting with an underscore (`_`).
19
+ - Robust and modular architecture following SOLID principles.
20
+ - Easy installation via `pip`.
21
+
22
+ ## Installation
23
+
24
+ Install the package from the local directory:
25
+
26
+ ```bash
27
+ pip install .
28
+ ```
29
+
30
+ Once published to PyPI, you can install it using:
31
+
32
+ ```bash
33
+ pip install pyexcel2mustache
34
+ ```
35
+
36
+ ## Requirements
37
+
38
+ - Python 3.8+
39
+ - Dependencies (automatically installed): `openpyxl`, `pystache`
40
+
41
+ ## Excel Schema Rules
42
+
43
+ Each sheet must follow a strict schema for the first 5 rows:
44
+
45
+ 1. **Row 1**: Column Description
46
+ 2. **Row 2**: Usage / PrimaryKey indicator (`'PrimaryKey'` string marks it as primary)
47
+ 3. **Row 3**: Attribute name
48
+ 4. **Row 4**: Data Type
49
+ 5. **Row 5**: Variable Name (the actual identifier used in the template)
50
+
51
+ *Note: Sheets starting with an underscore (`_`) will be skipped.*
52
+
53
+ ## Usage
54
+
55
+ Once installed, use the `pyexcel2mustache` command in your terminal:
56
+
57
+ ```bash
58
+ pyexcel2mustache -i <input_excel> -t <template_mustache> -o <output_path> [-c]
59
+ ```
60
+
61
+ ### Arguments
62
+
63
+ - `-i`, `--input`: Path to the input Excel file. (**Required**)
64
+ - `-t`, `--template`: Path to the Mustache template file. (**Required**)
65
+ - `-o`, `--output`: Path for the generated output file. (**Required**)
66
+ - `-c`, `--clean`: Clean up/remove existing output file before writing.
67
+
68
+ ## Project Structure (Refactored)
69
+
70
+ The project follows a modular structure:
71
+ - `src/pyexcel2mustache/domain`: Data models.
72
+ - `src/pyexcel2mustache/parsers`: Excel parsing logic.
73
+ - `src/pyexcel2mustache/renderers`: Mustache rendering engine.
74
+ - `src/pyexcel2mustache/cli`: Command line argument handling.
@@ -0,0 +1,64 @@
1
+ # pyexcel2mustache
2
+
3
+ Convert Excel (`xlsx`) sheets into Mustache templates based on a defined schema. This is now a distributable Python package.
4
+
5
+ ## Features
6
+
7
+ - Convert multiple sheets at once using customizable schemas.
8
+ - Skip sheets starting with an underscore (`_`).
9
+ - Robust and modular architecture following SOLID principles.
10
+ - Easy installation via `pip`.
11
+
12
+ ## Installation
13
+
14
+ Install the package from the local directory:
15
+
16
+ ```bash
17
+ pip install .
18
+ ```
19
+
20
+ Once published to PyPI, you can install it using:
21
+
22
+ ```bash
23
+ pip install pyexcel2mustache
24
+ ```
25
+
26
+ ## Requirements
27
+
28
+ - Python 3.8+
29
+ - Dependencies (automatically installed): `openpyxl`, `pystache`
30
+
31
+ ## Excel Schema Rules
32
+
33
+ Each sheet must follow a strict schema for the first 5 rows:
34
+
35
+ 1. **Row 1**: Column Description
36
+ 2. **Row 2**: Usage / PrimaryKey indicator (`'PrimaryKey'` string marks it as primary)
37
+ 3. **Row 3**: Attribute name
38
+ 4. **Row 4**: Data Type
39
+ 5. **Row 5**: Variable Name (the actual identifier used in the template)
40
+
41
+ *Note: Sheets starting with an underscore (`_`) will be skipped.*
42
+
43
+ ## Usage
44
+
45
+ Once installed, use the `pyexcel2mustache` command in your terminal:
46
+
47
+ ```bash
48
+ pyexcel2mustache -i <input_excel> -t <template_mustache> -o <output_path> [-c]
49
+ ```
50
+
51
+ ### Arguments
52
+
53
+ - `-i`, `--input`: Path to the input Excel file. (**Required**)
54
+ - `-t`, `--template`: Path to the Mustache template file. (**Required**)
55
+ - `-o`, `--output`: Path for the generated output file. (**Required**)
56
+ - `-c`, `--clean`: Clean up/remove existing output file before writing.
57
+
58
+ ## Project Structure (Refactored)
59
+
60
+ The project follows a modular structure:
61
+ - `src/pyexcel2mustache/domain`: Data models.
62
+ - `src/pyexcel2mustache/parsers`: Excel parsing logic.
63
+ - `src/pyexcel2mustache/renderers`: Mustache rendering engine.
64
+ - `src/pyexcel2mustache/cli`: Command line argument handling.
@@ -0,0 +1,20 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "pyexcel2mustache"
7
+ version = "0.1.1"
8
+ description = "Convert Excel files to Mustache templates based on a defined schema."
9
+ authors = [
10
+ {name = "oNsemy", email = "onsemy@gmail.com"}
11
+ ]
12
+ readme = "README.md"
13
+ requires-python = ">=3.8"
14
+ dependencies = [
15
+ "openpyxl>=3.1.0",
16
+ "pystache>=0.6.0"
17
+ ]
18
+
19
+ [project.scripts]
20
+ pyexcel2mustache = "pyexcel2mustache.main:run"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,28 @@
1
+ import argparse
2
+
3
+
4
+ def parse_arguments() -> argparse.Namespace:
5
+ """
6
+ Parses command-line arguments for the application.
7
+
8
+ Returns:
9
+ argparse.Namespace: An object containing the parsed arguments.
10
+ """
11
+ parser = argparse.ArgumentParser(
12
+ description="Convert Excel files to Mustache templates."
13
+ )
14
+ parser.add_argument(
15
+ "-i", "--input", help="Path of the input Excel file", required=True
16
+ )
17
+ parser.add_argument(
18
+ "-t", "--template", help="Path of the Mustache template file", required=True
19
+ )
20
+ parser.add_argument("-o", "--output", help="Path of the output file", required=True)
21
+ parser.add_argument(
22
+ "-c",
23
+ "--clean",
24
+ help="Clean up the output if it already exists",
25
+ action="store_true",
26
+ )
27
+
28
+ return parser.parse_args()
@@ -0,0 +1,87 @@
1
+ import datetime
2
+ from typing import List
3
+
4
+
5
+ class Attribute:
6
+ """Represents a single attribute within a class member."""
7
+
8
+ def __init__(self, name: str):
9
+ self._name = name
10
+
11
+ @property
12
+ def property(self) -> str:
13
+ return self._name
14
+
15
+
16
+ class ClassMember:
17
+ """Represents a field or variable defined in the Excel schema."""
18
+
19
+ def __init__(
20
+ self,
21
+ attributes: List[Attribute],
22
+ data_type: str,
23
+ name: str,
24
+ is_primary_key: bool,
25
+ ):
26
+ self._attributes = attributes
27
+ self._type = data_type
28
+ self._name = name
29
+ self._is_primary_key = is_primary_key
30
+
31
+ @property
32
+ def type_name(self) -> str:
33
+ return self._type
34
+
35
+ @property
36
+ def var_name(self) -> str:
37
+ return self._name
38
+
39
+ @property
40
+ def attributes(self) -> List[Attribute]:
41
+ return self._attributes
42
+
43
+ @property
44
+ def IsPrimaryKey(self) -> bool:
45
+ return self._is_primary_key
46
+
47
+
48
+ class ClassDeclare:
49
+ """Represents a fully defined class structure."""
50
+
51
+ def __init__(
52
+ self, name: str, date: datetime.datetime, class_members: List[ClassMember]
53
+ ):
54
+ self._name = name
55
+ self._date = date
56
+ self._classMembers = class_members
57
+
58
+ @property
59
+ def name(self) -> str:
60
+ return self._name
61
+
62
+ @property
63
+ def class_members(self) -> List[ClassMember]:
64
+ return self._classMembers
65
+
66
+ @property
67
+ def date(self) -> datetime.datetime:
68
+ return self._date
69
+
70
+
71
+ class ClassList:
72
+ """A collection of defined classes, used for template rendering."""
73
+
74
+ def __init__(self, date: datetime.datetime):
75
+ self._class_list = []
76
+ self._date = date
77
+
78
+ def add(self, class_declare: ClassDeclare) -> None:
79
+ self._class_list.append(class_declare)
80
+
81
+ @property
82
+ def class_list(self) -> List[ClassDeclare]:
83
+ return self._class_list
84
+
85
+ @property
86
+ def date(self) -> datetime.datetime:
87
+ return self._date
@@ -0,0 +1,57 @@
1
+ import os
2
+ import logging
3
+ from pyexcel2mustache.cli.args_parser import parse_arguments
4
+ from pyexcel2mustache.parsers.excel_parser import ExcelParser
5
+ from pyexcel2mustache.renderers.mustache_renderer import MustacheRenderer
6
+
7
+ # Configure logger for the package
8
+ logger = logging.getLogger("pyexcel2mustache")
9
+
10
+
11
+ def run():
12
+ """
13
+ The main entry point for the excel2mustache CLI tool.
14
+ This function is called by the entry point defined in pyproject.toml.
15
+ """
16
+ args = parse_arguments()
17
+
18
+ if args.clean and os.path.exists(args.output):
19
+ os.remove(args.output)
20
+
21
+ try:
22
+ with open(args.template, "r") as f:
23
+ template_content = f.read()
24
+ if not template_content:
25
+ logger.error("Template file is empty.")
26
+ return
27
+ except Exception as e:
28
+ logger.error(f"Error reading template: {e}")
29
+ return
30
+
31
+ parser = ExcelParser()
32
+ try:
33
+ class_list = parser.parse(args.input)
34
+ except Exception as e:
35
+ logger.error(f"Error parsing Excel file: {e}")
36
+ return
37
+
38
+ renderer = MustacheRenderer()
39
+ try:
40
+ result = renderer.render(template_content, class_list)
41
+ except Exception as e:
42
+ logger.error(f"Error rendering template: {e}")
43
+ return
44
+
45
+ try:
46
+ with open(args.output, "w") as f:
47
+ f.write(result)
48
+ logger.info(f"Successfully generated: {args.output}")
49
+ except Exception as e:
50
+ logger.error(f"Error writing output file: {e}")
51
+ return
52
+
53
+
54
+ if __name__ == "__main__":
55
+ # Default logging configuration for CLI usage
56
+ logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
57
+ run()
@@ -0,0 +1,21 @@
1
+ from abc import ABC, abstractmethod
2
+ from pyexcel2mustache.domain.models import ClassList
3
+
4
+
5
+ class BaseParser(ABC):
6
+ """
7
+ Abstract base class for all parsers.
8
+ """
9
+
10
+ @abstractmethod
11
+ def parse(self, file_path: str) -> ClassList:
12
+ """
13
+ Parses a file and returns a ClassList object.
14
+
15
+ Args:
16
+ file_path (str): Path to the input file.
17
+
18
+ Returns:
19
+ ClassList: The parsed domain models.
20
+ """
21
+ pass
@@ -0,0 +1,92 @@
1
+ import datetime
2
+ from openpyxl import load_workbook
3
+ from pyexcel2mustache.domain.models import (
4
+ ClassList,
5
+ ClassDeclare,
6
+ ClassMember,
7
+ Attribute,
8
+ )
9
+ from pyexcel2mustache.parsers.base_parser import BaseParser
10
+
11
+
12
+ class ExcelParser(BaseParser):
13
+ """
14
+ A parser that reads Excel (.xlsx) files and converts them into domain models.
15
+ """
16
+
17
+ def parse(self, file_path: str) -> ClassList:
18
+ wb = load_workbook(filename=file_path, data_only=True)
19
+ class_list = ClassList(datetime.datetime.now())
20
+
21
+ for sheet in wb:
22
+ if sheet.title.startswith("_"):
23
+ continue
24
+
25
+ class_declare = self._parse_sheet(sheet)
26
+ if class_declare:
27
+ class_list.add(class_declare)
28
+
29
+ return class_list
30
+
31
+ def _parse_sheet(self, sheet) -> ClassDeclare:
32
+ # According to AGENTS.md requirements and original logic:
33
+ # Row 1 (idx 0): Column Description
34
+ # Row 2 (idx 1): Usage / PrimaryKey check ('PrimaryKey' string here)
35
+ # Row 3 (idx 2): Attribute (Not used for data, but part of schema)
36
+ # Row 4 (idx 3): Data Type
37
+ # Row 5 (idx 4): Variable Name
38
+
39
+ primary_index = -1
40
+ data_types = []
41
+ variable_names = []
42
+ attributes_list = [] # To hold the 'PrimaryKey' attribute if needed
43
+
44
+ # We need to iterate through rows or access them by index.
45
+ # Since it's a strict schema, we can use sheet.iter_rows()
46
+ # and check row indices (1-based). Or convert to list of rows.
47
+ rows = list(sheet.iter_rows())
48
+
49
+ if len(rows) < 5:
50
+ return None # Sheet too small for the required schema
51
+
52
+ # Row 2 (idx 1): Find PrimaryKey index
53
+ row_2 = rows[1]
54
+ for idx, cell in enumerate(row_2):
55
+ if cell.value == "PrimaryKey":
56
+ primary_index = idx
57
+ break
58
+
59
+ # Row 4 (idx 3): Data Types
60
+ row_4 = rows[3]
61
+ for cell in row_4:
62
+ data_types.append(str(cell.value) if cell.value is not None else "")
63
+
64
+ # Row 5 (idx 4): Variable Names
65
+ row_5 = rows[4]
66
+ for cell in row_5:
67
+ variable_names.append(str(cell.value) if cell.value is not None else "")
68
+
69
+ class_members = []
70
+ # Iterate through the columns collected from data type and name rows
71
+ for i in range(len(data_types)):
72
+ if i >= len(variable_names):
73
+ break
74
+
75
+ name = variable_names[i]
76
+ dtype = data_types[i]
77
+
78
+ # Skip if no name is provided (treating it as end of columns)
79
+ if not name:
80
+ continue
81
+
82
+ is_primary = i == primary_index
83
+ attrs = []
84
+ if is_primary:
85
+ attrs.append(Attribute("PrimaryKey"))
86
+
87
+ member = ClassMember(
88
+ attributes=attrs, data_type=dtype, name=name, is_primary_key=is_primary
89
+ )
90
+ class_members.append(member)
91
+
92
+ return ClassDeclare(sheet.title, datetime.datetime.now(), class_members)
@@ -0,0 +1,21 @@
1
+ import pystache
2
+ from pyexcel2mustache.domain.models import ClassList
3
+
4
+
5
+ class MustacheRenderer:
6
+ """
7
+ A renderer that uses Mustache templates to render domain models as strings.
8
+ """
9
+
10
+ def render(self, template_content: str, data: ClassList) -> str:
11
+ """
12
+ Renders the provided template content with the given data.
13
+
14
+ Args:
15
+ template_content (str): The mustache template string.
16
+ data (ClassList): The domain models to be rendered.
17
+
18
+ Returns:
19
+ str: The rendered output string.
20
+ """
21
+ return pystache.render(template_content, data)
@@ -0,0 +1,74 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyexcel2mustache
3
+ Version: 0.1.1
4
+ Summary: Convert Excel files to Mustache templates based on a defined schema.
5
+ Author-email: oNsemy <onsemy@gmail.com>
6
+ Requires-Python: >=3.8
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: openpyxl>=3.1.0
9
+ Requires-Dist: pystache>=0.6.0
10
+
11
+ # pyexcel2mustache
12
+
13
+ Convert Excel (`xlsx`) sheets into Mustache templates based on a defined schema. This is now a distributable Python package.
14
+
15
+ ## Features
16
+
17
+ - Convert multiple sheets at once using customizable schemas.
18
+ - Skip sheets starting with an underscore (`_`).
19
+ - Robust and modular architecture following SOLID principles.
20
+ - Easy installation via `pip`.
21
+
22
+ ## Installation
23
+
24
+ Install the package from the local directory:
25
+
26
+ ```bash
27
+ pip install .
28
+ ```
29
+
30
+ Once published to PyPI, you can install it using:
31
+
32
+ ```bash
33
+ pip install pyexcel2mustache
34
+ ```
35
+
36
+ ## Requirements
37
+
38
+ - Python 3.8+
39
+ - Dependencies (automatically installed): `openpyxl`, `pystache`
40
+
41
+ ## Excel Schema Rules
42
+
43
+ Each sheet must follow a strict schema for the first 5 rows:
44
+
45
+ 1. **Row 1**: Column Description
46
+ 2. **Row 2**: Usage / PrimaryKey indicator (`'PrimaryKey'` string marks it as primary)
47
+ 3. **Row 3**: Attribute name
48
+ 4. **Row 4**: Data Type
49
+ 5. **Row 5**: Variable Name (the actual identifier used in the template)
50
+
51
+ *Note: Sheets starting with an underscore (`_`) will be skipped.*
52
+
53
+ ## Usage
54
+
55
+ Once installed, use the `pyexcel2mustache` command in your terminal:
56
+
57
+ ```bash
58
+ pyexcel2mustache -i <input_excel> -t <template_mustache> -o <output_path> [-c]
59
+ ```
60
+
61
+ ### Arguments
62
+
63
+ - `-i`, `--input`: Path to the input Excel file. (**Required**)
64
+ - `-t`, `--template`: Path to the Mustache template file. (**Required**)
65
+ - `-o`, `--output`: Path for the generated output file. (**Required**)
66
+ - `-c`, `--clean`: Clean up/remove existing output file before writing.
67
+
68
+ ## Project Structure (Refactored)
69
+
70
+ The project follows a modular structure:
71
+ - `src/pyexcel2mustache/domain`: Data models.
72
+ - `src/pyexcel2mustache/parsers`: Excel parsing logic.
73
+ - `src/pyexcel2mustache/renderers`: Mustache rendering engine.
74
+ - `src/pyexcel2mustache/cli`: Command line argument handling.
@@ -0,0 +1,19 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/pyexcel2mustache/__init__.py
4
+ src/pyexcel2mustache/main.py
5
+ src/pyexcel2mustache.egg-info/PKG-INFO
6
+ src/pyexcel2mustache.egg-info/SOURCES.txt
7
+ src/pyexcel2mustache.egg-info/dependency_links.txt
8
+ src/pyexcel2mustache.egg-info/entry_points.txt
9
+ src/pyexcel2mustache.egg-info/requires.txt
10
+ src/pyexcel2mustache.egg-info/top_level.txt
11
+ src/pyexcel2mustache/cli/__init__.py
12
+ src/pyexcel2mustache/cli/args_parser.py
13
+ src/pyexcel2mustache/domain/__init__.py
14
+ src/pyexcel2mustache/domain/models.py
15
+ src/pyexcel2mustache/parsers/__init__.py
16
+ src/pyexcel2mustache/parsers/base_parser.py
17
+ src/pyexcel2mustache/parsers/excel_parser.py
18
+ src/pyexcel2mustache/renderers/__init__.py
19
+ src/pyexcel2mustache/renderers/mustache_renderer.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ pyexcel2mustache = pyexcel2mustache.main:run
@@ -0,0 +1,2 @@
1
+ openpyxl>=3.1.0
2
+ pystache>=0.6.0
@@ -0,0 +1 @@
1
+ pyexcel2mustache