Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
cervelas committed Feb 28, 2023
1 parent 80c71ca commit 930fe23
Show file tree
Hide file tree
Showing 64 changed files with 1,615 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,5 @@ dmypy.json

# Pyre type checker
.pyre/

dcp_tests/
2 changes: 2 additions & 0 deletions movx/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from h2o_wave import main
import movx.ui.main
4 changes: 4 additions & 0 deletions movx/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from movx import cli

if __name__ == "__main__":
cli.main()
54 changes: 54 additions & 0 deletions movx/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import click
import os
import pprint
import subprocess
import uvicorn
import webbrowser

from h2o_wave import app
from movx.core.movx import movx

def start_waved(logs=False):
print("starting Wave Server")
os.environ["H2O_WAVE_NO_LOG"] = "0" if logs else "1"
cwd = os.getcwd()
waved_path = os.path.join(os.path.dirname(__file__), "./vendor/wave-0.24.2-windows-amd64/")
os.chdir(waved_path)
subprocess.Popen(os.path.join(waved_path, "waved.exe"))
os.chdir(cwd)

def start_serve(reload=False):
uvicorn.run("movx.ui.main:main", log_level="warning", reload=reload)

@click.group()
def main():
pass

@main.command()
def serve():
start_waved()
print("Starting application")
start_serve()

@main.command()
def run():
start_waved()
print("Starting application")
webbrowser.open("http://127.0.0.1:10101/movx")
uvicorn.run("movx.ui.main:main", log_level="warning", reload=True)

@main.command()
@click.argument("path")
def scan(path):
movx.update_locations("NEW", path)
movx.scan()
movx.pretty_print()


@main.command()
@click.argument("path")
def check(path):
movx.update_locations("NEW", path)
movx.scan()
movx.check()
movx.pretty_print()
Empty file added movx/config.json
Empty file.
Empty file added movx/core/__init__.py
Empty file.
72 changes: 72 additions & 0 deletions movx/core/dcp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import pprint
import json
import uuid
from pathlib import Path

import clairmeta

class DCP:
def __init__(self, folder, rel_to, location):
self.path = Path(folder)
self.rel_to = rel_to
self.rel_path = self.path.relative_to(rel_to)
self.location = location
self.full_title = self.path.name
self.uri = uuid.uuid5(uuid.NAMESPACE_X500, str(self.path.absolute)) #"%s-%s-%s" % (self.location, self.rel_path, self.full_title)
self.title = self.full_title.split('_')[0]
self.package_type = self.full_title.split('_')[-1]
self.status = None
self.dcp_metadata = {}
self.ov_path = None
self.parse()

def asset(self, id):
for a in self.assets:
if a.id == str(id):
return a
return None

def parse(self):
try:
self.dcp = clairmeta.DCP(self.path)
self.dcp_metadata = self.dcp.parse()
self.package_type = self.dcp_metadata.get("package_type", None)
except Exception as e:
print(e)

def check(self, ov=None, cb=None):
status, report = self.dcp.check( ov_path=ov,
hash_callback=cb)

for c in report.checks_failed():
pprint.pprint(c.short_desc())
pprint.pprint([ e.message for e in c.errors ])

self.report = report

return report

def print(self):
print(self.title)

def to_dict(self):
return {
"title": str(self.title),
"path": str(self.path),
"rel_to": str(self.rel_to),
"location": str(self.location),
"package_type": self.package_type,
"status": self.status,
"metadata": json.dump(self.dcp_metadata),
"ov_path": str(self.ov_path),
"uri": str(self.uri),
}

def from_dict(dic):
dcp = DCP(dic["path"], dic["rel_to"], dic["location"])
dcp.uri = uuid.UUID(dic["uri"])
dcp.package_type = dic["package_type"]
dcp.status = dic["status"]
dcp.metadata = json.parse(dic["metadata"])
dcp.ov_path = dic["ov_path"]

38 changes: 38 additions & 0 deletions movx/core/location.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import os
from pathlib import Path

class Location:
def __init__(self, name, path) -> None:
self.name = name
self.path = Path(path)
self.enabled = True
self.db = self.check_for_db()
self.dcps = {}
self.dcps_found = 0

def check_for_db(self):
parents = self.path.parents
for p in parents[::-1]:
db_file = p / "dcps.db"
if db_file.is_file() and os.access(db_file, W_OK):
return db_file
return None

def scan_dcps(self):
self.dcps_found = 0
print("scan for dcp in %s" % self.path.absolute())
assetmaps = list(self.path.glob("**/ASSETMAP*"))
self.dcps_founds = len(list(assetmaps))
return list(assetmaps)

def to_dict(self):
return {
"path": str(self.path),
"name": str(self.name),
"enabled": self.enabled,
}

def from_dict(d):
l = Location(d["name"], d["path"])
l.enabled = d["enabled"]
return l
116 changes: 116 additions & 0 deletions movx/core/movx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import os
import json
import pprint
import uuid
from movx.core.dcp import DCP
from movx.core.location import Location
from pathlib import Path

class MovX:
def __init__(self):
self.local_db = Path.home() / ".movx" / "db.json"
self.locations = {}
self.dcps = {}
self.load()

def save(self):
self.local_db.parent.mkdir(exist_ok=True, parents=True)
db = { "movx_db": {
"locations": { n: l.to_dict() for n, l in self.locations.items() },
"dcps": { dcp.title: dcp.to_dict() for dcp in self.get_all() }
}
}
db_str = json.dumps(db, indent=4)
self.local_db.write_text(db_str)

def load(self):
if self.local_db.exists():
with open(self.local_db) as f:
db = json.load(f)
db = db.get("movx_db", {})
self.locations.update(
{ k: Location.from_dict(v) for k,v in db.get("locations", {}).items() }
)
self.dcps.update(
{ k: DCP.from_dict(v) for k,v in db.get("dcps", {}).items() }
)

def update_locations(self, name, path):
self.locations.update( { name: Location(name, path) })
self.save()

def del_location(self, name):
self.locations.pop(name, None)
self.load()

def scan(self):
'''
Scan for folders with ASSETMAP recursively
'''
self.dcps = {}

for name, loc in self.locations.items():
try:
assetmaps = loc.scan_dcps()
for am in assetmaps:
dcp = DCP(am.parent, loc.path, loc)

if dcp.title not in self.dcps:
self.dcps.update( { dcp.title: [] })

self.dcps[dcp.title].append(dcp)

except Exception as e:
print(e)

for dcp in self.get_all():
if dcp.package_type != "OV":
ovs = self.get_ov_dcps(dcp.title)
if len(ovs) == 1:
dcp.ov = ovs[0]

def check(self, title = None):
'''
Check all the dcp with the given title
'''
dcps = self.dcps.get(title)
if dcps:
for dcp in dcps:
print("\t Check %s (%s)\n\n" % (dcp.uri))
if dcp.check() is False:
return False

def pretty_print(self):
for title, dcps in self.dcps.items():
print(title)
for dcp in dcps:
print("\t%s \n\t\t(%s)\n" % (dcp.full_title, dcp.uri))

def get_all(self):
dcps = []
for t, d in self.dcps.items():
dcps += d

return dcps

def get(self, uri):
dcps = []
for t, d in self.dcps.items():
dcps += d

dcp = None
for d in dcps:
if str(d.uri) == uri:
dcp = d
return dcp

def get_ov_dcps(self, title):
dcps = self.dcps.get(title)
ovs = []
if dcps:
for dcp in dcps:
if dcp.package_type == "OV":
ovs.append(dcp)
return ovs

movx = MovX()
52 changes: 52 additions & 0 deletions movx/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from h2o_wave import main, Q, app, ui

# Define some sample data to populate the tree view
data = {
'Fruits': {
'Apples': {
'Red': ['Fuji', 'Gala', 'Cameo'],
'Green': ['Granny Smith', 'Golden Delicious']
},
'Oranges': ['Navel', 'Cara Cara', 'Blood'],
'Bananas': ['Cavendish', 'Red']
},
'Vegetables': {
'Leafy Greens': ['Spinach', 'Kale', 'Collard Greens'],
'Cruciferous Vegetables': ['Broccoli', 'Cauliflower', 'Brussels Sprouts'],
'Root Vegetables': ['Carrots', 'Potatoes', 'Turnips']
}
}

# Define a function to recursively create the dropdown options
def create_dropdown_options(data, prefix=''):
if isinstance(data, dict):
options = []
for key, value in data.items():
children = create_dropdown_options(value, f'{prefix}{key} / ')
option = ui.checklist(name=f'{prefix}{key}', label=key, choices=children)
options.append(option)
return options
elif isinstance(data, list):
options = [ui.label(name=f'{prefix}{name}', label=name) for name in data]
return options

# Define the Wave app and layout
@app('/demo')
async def serve(q: Q):
if not q.client.initialized:
# Create the dropdown options and add the dropdown to the page
options = create_dropdown_options(data)
dropdown = ui.dropdown(name='treeview', label='Select a category / subcategory / item', value='', options=options)
q.client.initialized = True
q.page['main'] = ui.form_card(box='1 1 12 10', items=[dropdown])
else:
# Handle changes to the dropdown value by updating the dropdown with the appropriate options
value = q.args.treeview
if value:
options = create_dropdown_options(data, f'{value} / ')
q.page['main'].items[0].options = options
await q.page.save()

# Run the Wave app
if __name__ == '__main__':
app()
Loading

0 comments on commit 930fe23

Please sign in to comment.