Skip to content

Commit c82e19e

Browse files
author
Tom Reitz
committed
partial implementation of new lightbeam create functionality
1 parent 0e839be commit c82e19e

3 files changed

Lines changed: 115 additions & 0 deletions

File tree

lightbeam/__main__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ def emit(self, record):
2323
"truncate": "truncate",
2424
"count": "count",
2525
"fetch": "fetch",
26+
"create": "create"
2627
}
2728
command_list = ', '.join(f"'{c}'" for c in ALLOWED_COMMANDS.values())
2829

@@ -163,6 +164,7 @@ def main(argv=None):
163164
try:
164165
logger.info("starting...")
165166
if args.command==ALLOWED_COMMANDS['count']: lb.counter.count()
167+
if args.command==ALLOWED_COMMANDS['create']: lb.creator.create()
166168
elif args.command==ALLOWED_COMMANDS['fetch']: lb.fetcher.fetch()
167169
elif args.command==ALLOWED_COMMANDS['validate']: lb.validator.validate()
168170
elif args.command==ALLOWED_COMMANDS['send']: lb.sender.send()

lightbeam/create.py

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import os
2+
import json
3+
import yaml
4+
from lightbeam import util
5+
6+
class Creator:
7+
8+
def __init__(self, lightbeam=None):
9+
self.lightbeam = lightbeam
10+
self.logger = self.lightbeam.logger
11+
self.template_folder = "templates/"
12+
self.earthmover_file = "earthmover.yml"
13+
14+
def create(self):
15+
os.makedirs(self.template_folder, exist_ok=True)
16+
earthmover_yaml = {}
17+
# check if file exists!
18+
if os.path.isfile(self.earthmover_file):
19+
with open(self.earthmover_file) as file:
20+
earthmover_yaml = yaml.safe_load(file)
21+
for endpoint in self.lightbeam.endpoints:
22+
if endpoint in (earthmover_yaml.get("destinations", {}) or {}).keys():
23+
self.logger.critical(f"The file `{self.earthmover_file}` already exists in the current directory and contains `$destinations.{endpoint}`; to re-create it, please first manually remove it (and `{self.template_folder}{endpoint}.jsont`).")
24+
self.create_jsont(endpoint)
25+
# write out earthmover_yaml
26+
if not os.path.isfile(self.earthmover_file):
27+
self.logger.info(f"creating file `{self.earthmover_file}`...")
28+
with open(self.earthmover_file, 'w+') as file:
29+
file.write("""version: 2.0
30+
31+
# This is an earthmover.yml file, generated with `lightbeam create`, for creating Ed-Fi JSON payloads
32+
# using earthmover. See https://github.com/edanalytics/earthmover for documentation.
33+
34+
# Define your source data here:
35+
sources:
36+
# Example:
37+
# mysource:
38+
# file: path/to/myfile.csv
39+
# ...
40+
41+
# (If needed, define your data transformations here:)
42+
# transformations:
43+
44+
destinations:""")
45+
for endpoint in self.lightbeam.endpoints:
46+
file.write(self.create_em_destination_node(endpoint))
47+
else:
48+
self.logger.info(f"appending to file `{self.earthmover_file}`...")
49+
with open(self.earthmover_file, 'a+') as file:
50+
for endpoint in self.lightbeam.endpoints:
51+
file.write(self.create_em_destination_node(endpoint))
52+
53+
def create_em_destination_node(self, endpoint):
54+
return f"""
55+
{endpoint}:
56+
source: $transformations.{endpoint}
57+
template: {self.template_folder}{endpoint}.jsont
58+
extension: jsonl
59+
linearize: True"""
60+
61+
def create_jsont(self, endpoint):
62+
template_file = f"{self.template_folder}{endpoint}.jsont"
63+
# check if file exists!
64+
if os.path.isfile(template_file):
65+
self.logger.critical(f"The file `{template_file}` already exists in the current directory; to re-create it, please first manually delete it.")
66+
# write out json template
67+
self.logger.info(f"creating file `{template_file}`...")
68+
with open(template_file, 'w+') as file:
69+
# TODO: implement a function in `lightbeam/api.py` that constructs a "sample" payload for the endpoint
70+
# Example:
71+
# {
72+
# "property_bool": true,
73+
# "property_int": 1,
74+
# "property_float": 1.0,
75+
# "property_string": "string",
76+
# "property_date": "date",
77+
# "property_descriptor": "uri://ed-fi.org/SomeDescriptor#SomeValue",
78+
# "property_object": {
79+
# "property_object_1": "string",
80+
# "property_object_2": "string"
81+
# },
82+
# "property_array": [
83+
# {
84+
# "property_array_1": "string",
85+
# "property_array_2": "string"
86+
# }
87+
# ]
88+
# }
89+
# TODO: turn the "sample" payload into a Jinja template
90+
# Example:
91+
# {
92+
# "property_bool": {{property_bool}},
93+
# "property_int": {{property_int}},
94+
# "property_float": {{property_float}},
95+
# "property_string": "{{property_string}}",
96+
# "property_date": "{{property_date}}",
97+
# "property_descriptor": "uri://ed-fi.org/SomeDescriptor#{{property_descriptor}}",
98+
# "property_object": {
99+
# "property_object_1": "{{property_object_1}}",
100+
# "property_object_2": "{{property_object_2}}"
101+
# },
102+
# "property_array": [
103+
# {% for item in property_array %}
104+
# {
105+
# "property_array_1": "{{item.property_array_1}}",
106+
# "property_array_2": "{{item.property_array_2}}"
107+
# } {% if not loop.last %},{% endif %}
108+
# {% endfor %}
109+
# ]
110+
# }
111+
file.write("coming soon...") # (for now)

lightbeam/lightbeam.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from lightbeam import util
1212
from lightbeam.api import EdFiAPI
1313
from lightbeam.count import Counter
14+
from lightbeam.create import Creator
1415
from lightbeam.fetch import Fetcher
1516
from lightbeam.validate import Validator
1617
from lightbeam.send import Sender
@@ -73,6 +74,7 @@ def __init__(self, config_file, logger=None, selector="*", exclude="", keep_keys
7374
self.endpoints = []
7475
self.results = []
7576
self.counter = Counter(self)
77+
self.creator = Creator(self)
7678
self.fetcher = Fetcher(self)
7779
self.validator = Validator(self)
7880
self.sender = Sender(self)

0 commit comments

Comments
 (0)