Skip to content

Commit

Permalink
docs: improve docstring
Browse files Browse the repository at this point in the history
  • Loading branch information
mostaphaRoudsari committed Jan 1, 2021
1 parent a6dcc33 commit 1562f12
Show file tree
Hide file tree
Showing 11 changed files with 503 additions and 163 deletions.
1 change: 1 addition & 0 deletions queenbee_dsl/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Queenbee Python DSL."""
76 changes: 76 additions & 0 deletions queenbee_dsl/common.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,80 @@
from dataclasses import dataclass
from typing import NamedTuple
import importlib
from collections import namedtuple


def camel_to_snake(name: str) -> str:
"""Change name from CamelCase to snake-case."""
return name[0].lower() + \
''.join(['-' + x.lower() if x.isupper() else x for x in name][1:])


@dataclass
class _BaseClass:
"""Base class for Queenbee DSL Function and DAG.
Do not use this class directly.
"""
_cached_queenbee = None
_cached_outputs = None
_cached_package = None
_cached_inputs = None

@property
def queenbee(self):
raise NotImplementedError

@property
def _outputs(self) -> NamedTuple:
raise NotImplementedError

@property
def _inputs(self) -> NamedTuple:
"""Return inputs as a simple object with dot notation.
Use this property to access the inputs when creating a DAG.
The name starts with a _ not to conflict with a possible member of the class
with the name inputs.
"""
if self._cached_inputs:
return self._cached_inputs
cls_name = camel_to_snake(self.__class__.__name__)
mapper = {
inp.name.replace('-', '_'): {
'name': inp.name.replace('-', '_'),
'parent': cls_name,
'value': inp
} for inp in self.queenbee.inputs
}

inputs = namedtuple('Inputs', list(mapper.keys()))
self._cached_inputs = inputs(*list(mapper.values()))

return self._cached_inputs

@property
def _package(self) -> dict:
"""Queenbee package information.
This information will only be available if the function is part of a Python
package.
"""
if self._cached_package:
return self._cached_package

module = importlib.import_module(self._python_package)
assert hasattr(module, '__queenbee__'), \
'Failed to find __queenbee__ info in __init__.py'
self._cached_package = getattr(module, '__queenbee__')
return self._cached_package

@property
def _python_package(self) -> str:
"""Python package information for this function.
This information will only be available if the function is part of a Python
package.
"""
return self.__module__.split('.')[0]
72 changes: 16 additions & 56 deletions queenbee_dsl/dag/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,27 @@
from typing import NamedTuple
import inspect
from collections import namedtuple
import importlib

from queenbee.recipe.dag import DAG as QBDAG

from ..common import camel_to_snake
from ..common import _BaseClass


@dataclass
class DAG:
"""Baseclass for DSL DAG classes."""
class DAG(_BaseClass):
"""Baseclass for DSL DAG classes.
Every Queenbee DAG must subclass from this class.
Attributes:
queenbee
_dependencies
_inputs
_outputs
_package
_python_package
"""
__decorator__ = 'dag'
_cached_queenbee = None
_cached_inputs = None
Expand All @@ -20,7 +31,7 @@ class DAG:

@property
def queenbee(self) -> QBDAG:
"""Convert this class to a Queenbee class."""
"""Convert this class to a Queenbee DAG."""
# cache the DAG since it always stays the same for each instance
if self._cached_queenbee:
return self._cached_queenbee
Expand Down Expand Up @@ -65,32 +76,6 @@ def queenbee(self) -> QBDAG:
)
return self._cached_queenbee

@property
def _inputs(self) -> NamedTuple:
"""Return function inputs as a simple object with dot notation.
Use this property to access the inputs when creating a DAG.
The name starts with a _ not to conflict with a possible member of the class
with the name inputs.
"""
if self._cached_inputs:
return self._cached_inputs

cls_name = camel_to_snake(self.__class__.__name__)
mapper = {
inp.name.replace('-', '_'): {
'name': inp.name.replace('-', '_'),
'parent': cls_name,
'value': inp
} for inp in self.queenbee.inputs
}

inputs = namedtuple('Inputs', list(mapper.keys()))
self._cached_inputs = inputs(*list(mapper.values()))

return self._cached_inputs

@property
def _outputs(self) -> NamedTuple:
"""Return dag outputs as a simple object with dot notation.
Expand All @@ -109,31 +94,6 @@ def _outputs(self) -> NamedTuple:

return self._cached_outputs

@property
def _package(self) -> dict:
"""Queenbee package information.
This information will only be available if the dag is part of a Python
package.
"""
if self._cached_package:
return self._cached_package

module = importlib.import_module(self._python_package)
assert hasattr(module, '__queenbee__'), \
f'Failed to find __queenbee__ info in {module.__name__}\'s __init__.py'
self._cached_package = getattr(module, '__queenbee__')
return self._cached_package

@property
def _python_package(self) -> str:
"""Python package information for this dag.
This information will only be available if the dag is part of a Python
package.
"""
return self.__module__.split('.')[0]

@property
def _dependencies(self):
"""DAG dependencies.
Expand Down
75 changes: 74 additions & 1 deletion queenbee_dsl/dag/_inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,30 +55,83 @@ def reference_type(self):


class StringInput(_InputBase):
""" A DAG string input.
Args:
annotations: An optional annotation dictionary.
description: Input description.
default: Default value.
spec: A JSONSchema specification to validate input values.
"""
annotations: Dict = None
description: str = None
default: str = None
spec: Dict = None


class IntegerInput(StringInput):
""" A DAG integer input.
Args:
annotations: An optional annotation dictionary.
description: Input description.
default: Default value.
spec: A JSONSchema specification to validate input values.
"""
default: int = None


class NumberInput(StringInput):
""" A DAG number input.
Args:
annotations: An optional annotation dictionary.
description: Input description.
default: Default value.
spec: A JSONSchema specification to validate input values.
"""
default: float = None


class BooleanInput(StringInput):
""" A DAG boolean input.
Args:
annotations: An optional annotation dictionary.
description: Input description.
default: Default value.
spec: A JSONSchema specification to validate input values.
"""
default: bool = None


class DictInput(StringInput):
""" A DAG dictionary input.
Args:
annotations: An optional annotation dictionary.
description: Input description.
default: Default value.
spec: A JSONSchema specification to validate input values.
"""
default: Dict = None


class FolderInput(StringInput):
""" A DAG folder input.
Args:
annotations: An optional annotation dictionary.
description: Input description.
default: Default value.
spec: A JSONSchema specification to validate input values.
"""
@property
def is_artifact(self):
return True
Expand All @@ -89,6 +142,16 @@ def reference_type(self):


class FileInput(FolderInput):
""" A DAG file input.
Args:
annotations: An optional annotation dictionary.
description: Input description.
default: Default value.
extensions: An optional list of valid extensions for input file.
spec: A JSONSchema specification to validate input values.
"""
extensions: List[str] = None

@property
Expand All @@ -97,6 +160,16 @@ def reference_type(self):


class PathInput(FileInput):
""" A DAG path input. A path can be a file or a folder.
Args:
annotations: An optional annotation dictionary.
description: Input description.
default: Default value.
extensions: An optional list of valid extensions for input file.
spec: A JSONSchema specification to validate input values.
"""

@property
def reference_type(self):
Expand All @@ -105,7 +178,7 @@ def reference_type(self):

@dataclass
class Inputs:
"""DAG inputs."""
"""DAG inputs enumeration."""
str = StringInput
int = IntegerInput
float = NumberInput
Expand Down
Loading

0 comments on commit 1562f12

Please sign in to comment.