diff --git a/Package/Python/README.md b/Package/Python/README.md index 887d165..2984480 100644 --- a/Package/Python/README.md +++ b/Package/Python/README.md @@ -10,3 +10,27 @@ parsed_data = bellande_formatter.parse_bellande("path/to/your/file.bellande") data_to_write = {"key": "value", "list": [1, 2, 3]} bellande_formatter.write_bellande(data_to_write, "path/to/output/file.bellande") ``` + +## Website PYPI +- https://pypi.org/project/bellande_format + +### Installation +- `$ pip install bellande_format` + +### Upgrade (if not upgraded) +- `$ pip install --upgrade bellande_format` + +``` +Name: bellande_robot_step +Version: 0.3.0 +Summary: Computes the next step towards a target node +Home-page: github.com/RonaldsonBellande/bellande_robot_step +Author: Ronaldson Bellande +Author-email: ronaldsonbellande@gmail.com +License: GNU General Public License v3.0 +Requires: numpy +Required-by: +``` + +## License +This Algorithm or Models is distributed under the [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/), see [LICENSE](https://github.com/RonaldsonBellande/bellande_format/blob/main/LICENSE) and [NOTICE](https://github.com/RonaldsonBellande/bellande_format/blob/main/LICENSE) for more information. diff --git a/Package/Python/setup.py b/Package/Python/setup.py new file mode 100644 index 0000000..cc6e6ec --- /dev/null +++ b/Package/Python/setup.py @@ -0,0 +1,40 @@ +from setuptools import setup, find_packages + +with open("README.md", "r", encoding="utf-8") as fh: + long_description = fh.read() + +setup( + name="bellande_format", + version="0.1.0", + description="Robots Format", + long_description=long_description, + long_description_content_type="text/markdown", + author="RonaldsonBellande", + author_email="ronaldsonbellande@gmail.com", + packages=find_packages(where="src"), + package_dir={"": "src"}, + include_package_data=True, + install_requires=[ + "numpy", + ], + classifiers=[ + "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", + "Programming Language :: Python", + ], + keywords=["package", "setuptools"], + python_requires=">=3.0", + extras_require={ + "dev": ["pytest", "pytest-cov[all]", "mypy", "black"], + }, + entry_points={ + 'console_scripts': [ + 'bellande_format = bellande_parser:bellande_format', + ], + }, + project_urls={ + "Home": "https://github.com/RonaldsonBellande/bellande_format", + "Homepage": "https://github.com/RonaldsonBellande/bellande_format", + "documentation": "https://github.com/RonaldsonBellande/bellande_format", + "repository": "https://github.com/RonaldsonBellande/bellande_format", + }, +) diff --git a/Package/Python/src/bellande_parser.py b/Package/Python/src/bellande_parser.py new file mode 100644 index 0000000..6170547 --- /dev/null +++ b/Package/Python/src/bellande_parser.py @@ -0,0 +1,115 @@ +# Copyright (C) 2024 Bellande Algorithm Model Research Innovation Center, Ronaldson Bellande + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +#!/usr/bin/env python3 + +import re +from typing import Dict, List, Union, Any + +class bellande_format: + def parse_bellande(self, file_path: str) -> Dict: + with open(file_path, 'r') as file: + lines = file.readlines() + return self.parse_lines(lines) + + def parse_lines(self, lines: List[str]) -> Dict: + result = {} + stack = [(-1, result)] + + for line in lines: + stripped = line.strip() + if not stripped or stripped.startswith('#'): + continue + + indent = len(line) - len(line.lstrip()) + while stack and indent <= stack[-1][0]: + stack.pop() + + parent = stack[-1][1] + + if ':' in stripped: + key, value = map(str.strip, stripped.split(':', 1)) + if value: + parent[key] = self.parse_value(value) + else: + new_dict = {} + parent[key] = new_dict + stack.append((indent, new_dict)) + elif stripped.startswith('-'): + value = stripped[1:].strip() + + if isinstance(parent, list): + parent.append(self.parse_value(value)) + else: + new_list = [self.parse_value(value)] + last_key = list(parent.keys())[-1] + parent[last_key] = new_list + stack.append((indent, new_list)) + + return result + + def parse_value(self, value: str) -> Union[str, int, float, bool, None]: + if value.lower() == 'true': + return True + elif value.lower() == 'false': + return False + elif value.lower() == 'null': + return None + elif value.startswith('"') and value.endswith('"'): + return value[1:-1] + elif re.match(r'^-?\d+$', value): + return int(value) + elif re.match(r'^-?\d*\.\d+$', value): + return float(value) + else: + return value + + def write_bellande(self, data: Any, file_path: str): + with open(file_path, 'w') as file: + file.write(self.to_bellande_string(data)) + + def to_bellande_string(self, data: Any, indent: int = 0) -> str: + if isinstance(data, dict): + lines = [] + for key, value in data.items(): + if isinstance(value, (dict, list)): + lines.append(f"{' ' * indent}{key}:") + lines.append(self.to_bellande_string(value, indent + 4)) + else: + lines.append(f"{' ' * indent}{key}: {self.format_value(value)}") + return '\n'.join(lines) + elif isinstance(data, list): + lines = [] + for item in data: + if isinstance(item, (dict, list)): + lines.append(f"{' ' * indent}-") + lines.append(self.to_bellande_string(item, indent + 4)) + else: + lines.append(f"{' ' * indent}- {self.format_value(item)}") + return '\n'.join(lines) + else: + return f"{' ' * indent}{self.format_value(data)}" + + def format_value(self, value: Any) -> str: + if isinstance(value, str): + if ' ' in value or ':' in value: + return f'"{value}"' + return value + elif isinstance(value, bool): + return str(value).lower() + elif value is None: + return 'null' + else: + return str(value)