Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
alexprodan99 committed May 18, 2024
1 parent f1e4c88 commit 386a1ff
Show file tree
Hide file tree
Showing 25 changed files with 661 additions and 3 deletions.
31 changes: 31 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: Attach using Process Id",
"type": "debugpy",
"request": "attach",
"processId": "${command:pickProcess}",
"justMyCode": false
},
{
"name": "Python Debugger: Current File",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"purpose": [
"debug-test"
],
"console": "integratedTerminal",
"justMyCode": false,
// If coverage report is generated(see pyproject.toml), then the breakpoints will be ignored and there's not possible to debug step by step.
// So we override the pyproject.toml coverage option here
"env": {
"PYTEST_ADDOPTS": "--no-cov"
},
}
]
}
7 changes: 7 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"python.testing.pytestArgs": [
"tests"
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true
}
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# PyDataGenerator Docs
13 changes: 13 additions & 0 deletions docs/reference/reference.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Reference
## Data
::: src.pydatagenerator.data.abstract.abstract_dataset
::: src.pydatagenerator.data.abstract.abstract_dataset_handler_factory
::: src.pydatagenerator.data.impl.dataset_handler_factory
::: src.pydatagenerator.data.impl.random_number_data_set
::: src.pydatagenerator.data.impl.sequence_data_set


## Xml
::: src.pydatagenerator.xml.abstract.abstract_xml_parser
::: src.pydatagenerator.xml.impl.xml_parser
::: src.pydatagenerator.xml.impl.xml_parser_util
10 changes: 10 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
site_name: Pydatagenerator Docs

theme:
name: "material"

nav:
- PyDataGenerator Docs: index.md
- Reference: reference/reference.md
plugins:
- mkdocstrings
38 changes: 37 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src"]
packages = ["src/pydatagenerator"]

[project]
name = "pydatagenerator"
Expand All @@ -17,6 +17,7 @@ version = "0.0.0"
description = "Coming soon"
readme = "README.md"
requires-python = ">=3.6"
dependencies = ["lxml>=5.2.1"]
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
Expand All @@ -25,6 +26,41 @@ classifiers = [
license = { file = "LICENSE" }
keywords = ["pydatagenerator", "data", "data-generator", "template"]

[project.optional-dependencies]
dev = [
"toml>=0.10.2",
"pylint>=3.1.0",
"yapf>=0.40.2",
"flake8>=7.0.0",
"mkdocs>=1.6.0",
"mkdocstrings[python]>=0.18",
"mkdocs-material>=9.5.0",
]
test = ["pytest>=8.2.0", "pytest-cov>=5.0.0"]

[tool.pytest.ini_options]
addopts = "--cov --cov-report html --cov-report term-missing --cov-fail-under 95"

[tool.coverage.run]
source = ["src"]

[tool.yapf]
blank_line_before_nested_class_or_def = true
column_limit = 88


[tool.pylint]
max-line-length = 88
disable = [
"C0103", # (invalid-name)
"C0114", # (missing-module-docstring)
"C0115", # (missing-class-docstring)
"C0116", # (missing-function-docstring)
"R0903", # (too-few-public-methods)
"R0913", # (too-many-arguments)
"W0105", # (pointless-string-statement)
]

[project.urls]
Homepage = "https://github.com/alexprodan99/pydatagenerator"
Documentation = "https://github.com/alexprodan99/pydatagenerator/wiki"
Expand Down
2 changes: 0 additions & 2 deletions src/hello.py

This file was deleted.

Empty file added src/pydatagenerator/__init__.py
Empty file.
Empty file.
2 changes: 2 additions & 0 deletions src/pydatagenerator/data/abstract/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from pydatagenerator.data.abstract.abstract_dataset import AbstractDataSet, DataSetConstants
from pydatagenerator.data.abstract.abstract_dataset_handler_factory import AbstractDataSetHandler
115 changes: 115 additions & 0 deletions src/pydatagenerator/data/abstract/abstract_dataset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import abc
import sys
from typing import Dict, List


class DataSetConstants:
"""DataSetConstants
"""
DEFAULT_REQUIRED_FIELDS = ['name', 'type']


class AbstractDataSet(abc.ABC):
"""AbstractDataSet
"""
type = 'type.abstract-dataset'

def __init__(self, dataset_info: Dict[str, object]):
"""Creates a new data set
"""
self._dataset_info = dataset_info

@property
def dataset_info(self) -> Dict[str, object]:
"""Dataset info getter
Returns:
Dict[str, object]: The dataset_info value
"""
return self._dataset_info

@dataset_info.setter
def dataset_info(self, value: Dict[str, object]):
"""Dataset info setter
Args:
value (Dict[str, object]): The dataset_info value
"""
self._dataset_info = value

@dataset_info.deleter
def dataset_info(self) -> None:
"""Dataset info deleter
"""
del self._dataset_info

def validate_default_required_fields(self) -> None:
"""Validates the default required fields (name and type)
"""
fields = list(self._dataset_info.keys())
fields_set = set(fields)

for field in DataSetConstants.DEFAULT_REQUIRED_FIELDS:
if field not in fields_set:
sys.stderr.write(f'Error: Missing required property {field}')
sys.exit(-1)

def validate_required_fields(self) -> None:
"""Validates the required fields
"""
fields = list(self._dataset_info.keys())
fields_set = set(fields)
req_fields = self.required_fields()
for field in req_fields:
if field not in fields_set:
sys.stderr.write(f'Error: Missing property {field} \n')
sys.exit(-1)

def validate_optional_fields(self) -> None:
"""Validates the optional fields
"""
fields = list(self._dataset_info.keys())
req_fields = set(DataSetConstants.DEFAULT_REQUIRED_FIELDS + self.required_fields())
fields_set = set([field for field in fields if field not in req_fields])
optional_fields = set(self.optional_fields())

diff = fields_set - optional_fields

if len(diff) > 0:
sys.stderr.write(f'Error: Unknown properties {diff} \n')
sys.exit(-1)

def validate_dataset_info(self) -> None:
"""Validates the dataset info
"""
self.validate_default_required_fields()
if self.type == self._dataset_info['type']:
self.validate_required_fields()
self.validate_optional_fields()

@abc.abstractmethod
def required_fields(self) -> List[str]:
"""Returns the required fields for the current data set
Returns:
List[str]: List of required fields for the current data set
"""
return []

@abc.abstractmethod
def optional_fields(self) -> List[str]:
"""Returns the optional fields for the current data set
Returns:
List[str]: List of optional fields for the current data set
"""
return []

@abc.abstractmethod
def handle(self) -> object:
"""Process the given dataset_info and returns a result out of it
Returns:
object: The result obtained after processing the dataset_info
"""
return
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import abc
from pydatagenerator.data.abstract import AbstractDataSet
from typing import Dict


class AbstractDataSetHandler(abc.ABC):
"""Dataset handler contract
"""

@abc.abstractmethod
def get_dataset_handler(self, dataset_info: Dict[str, object]) -> AbstractDataSet:
"""Get dataset handler
Args:
dataset_info (Dict[str, object]): The dataset info to construct the dataset handler for
Returns:
AbstractDataSet: The data set handler constructed from the dataset_info
"""
return
3 changes: 3 additions & 0 deletions src/pydatagenerator/data/impl/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from pydatagenerator.data.impl.random_number_data_set import RandomNumberDataSet
from pydatagenerator.data.impl.sequence_data_set import SequenceDataSet
from pydatagenerator.data.impl.dataset_handler_factory import DatasetHandlerFactory
30 changes: 30 additions & 0 deletions src/pydatagenerator/data/impl/dataset_handler_factory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import sys
from pydatagenerator.data.abstract import AbstractDataSet, AbstractDataSetHandler
from typing import Dict


class DatasetHandlerFactory(AbstractDataSetHandler):
"""Dataset handler factory
"""

def get_dataset_handler(self, dataset_info: Dict[str, object]) -> AbstractDataSet:
"""Get dataset handler
Args:
dataset_info (Dict[str, object]): The dataset info to construct the dataset handler for
Returns:
AbstractDataSet: The data set handler constructed from the dataset_info
"""
type = dataset_info.get('type')
if not type:
sys.stderr.write('Error: No value provided for type')
sys.exit(-1)
handler = self.__classes.get(dataset_info['type'])
if not handler:
sys.stderr.write(f'Error: Unknown type {dataset_info['type']}')
sys.exit(-1)
return handler(dataset_info)

def __init__(self):
self.__classes = {c.type: c for c in AbstractDataSet.__subclasses__()}
35 changes: 35 additions & 0 deletions src/pydatagenerator/data/impl/random_number_data_set.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import random
from pydatagenerator.data.abstract import AbstractDataSet


class RandomNumberDataSet(AbstractDataSet):
"""RandomNumberDataSet
"""
type = 'type.random-number-dataset'

def required_fields(self):
"""Returns the required fields for the current data set
Returns:
List[str]: List of required fields for the current data set
"""
return ['min', 'max']

def optional_fields(self):
"""Returns the optional fields for the current data set
Returns:
List[str]: List of optional fields for the current data set
"""
return ['floating']

def handle(self) -> object:
"""Process the given dataset_info and returns a result out of it
Returns:
object: The result obtained after processing the dataset_info
"""
self.validate_dataset_info()
is_floating = self._dataset_info['floating'] and self._dataset_info['floating'].lower() == 'true'
func = random.uniform if is_floating else random.randint
return func(int(self._dataset_info['min']), int(self._dataset_info['max']))
39 changes: 39 additions & 0 deletions src/pydatagenerator/data/impl/sequence_data_set.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from typing import Dict, List
from pydatagenerator.data.abstract import AbstractDataSet


class SequenceDataSet(AbstractDataSet):
"""SequenceDataSet
"""
type = 'type.sequence-dataset'

def required_fields(self) -> List[str]:
"""Returns the required fields for the current data set
Returns:
List[str]: List of required fields for the current data set
"""
return ['start', 'increment']

def optional_fields(self) -> List[str]:
"""Returns the optional fields for the current data set
Returns:
List[str]: List of optional fields for the current data set
"""
return []

def __init__(self, dataset_info: Dict[str, object]):
super().__init__(dataset_info)
self.__val = int(dataset_info['start']) - int(dataset_info['increment'])

def handle(self) -> object:
"""Process the given dataset_info and returns a result out of it
Returns:
object: The result obtained after processing the dataset_info
"""
self.validate_dataset_info()
increment = int(self._dataset_info['increment'])
self.__val += increment
return self.__val
Empty file.
1 change: 1 addition & 0 deletions src/pydatagenerator/xml/abstract/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from pydatagenerator.xml.abstract.abstract_xml_parser import AbstractXmlParser
Loading

0 comments on commit 386a1ff

Please sign in to comment.