recipe.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #!/usr/bin/python3
  2. #
  3. # Copyright (c) Daniel Sheffield 2023
  4. #
  5. # All rights reserved
  6. #
  7. # THIS SOFTWARE IS PROVIDED AS IS WITHOUT WARRANTY
  8. from psycopg import Cursor
  9. from urwid import raw_display, WidgetPlaceholder, SolidFill, MainLoop
  10. from app.activities.ActivityManager import ActivityManager, show_or_exit
  11. from app.activities.RecipeEditor import RecipeEditor
  12. from app.data.QueryManager import QueryManager, display_mapper
  13. from app.palette import high_contrast
  14. from app import parse_recipe
  15. import pandas as pd
  16. import sys
  17. try:
  18. from db_credentials import HOST, PASSWORD
  19. host = f'host={HOST}'
  20. password = f'password={PASSWORD}'
  21. except:
  22. host = ''
  23. password = ''
  24. try:
  25. import os
  26. import psycopg
  27. user = os.getenv('USER')
  28. conn = psycopg.connect(f"{host} dbname=grocery user={user} {password}")
  29. cur: Cursor = conn.cursor()
  30. except:
  31. print('Failed to set up db connection. Entering Mock mode')
  32. exit(1)
  33. #from mock import *
  34. class Recipe(WidgetPlaceholder):
  35. def __init__(self, activity_manager):
  36. super().__init__(SolidFill(u'/'))
  37. self.activity_manager = activity_manager
  38. recipe = self.activity_manager.get('recipe_editor')
  39. self.activity_manager.show(self)
  40. self.activity_manager.show(recipe)
  41. cur.execute("BEGIN;")
  42. with open('units.sql') as f:
  43. to_exec = ''
  44. quote = False
  45. conn.add_notice_handler(lambda x: print(f"[{x.severity}] {x.message_primary}"))
  46. for line in filter(lambda x: x.strip() not in ('BEGIN;','ROLLBACK;'), f):
  47. if line.startswith("""$$"""):
  48. quote = True if not quote else False
  49. to_exec += line
  50. if not line.strip().endswith(';'):
  51. continue
  52. if quote:
  53. continue
  54. cur.execute(to_exec)
  55. try:
  56. data = pd.DataFrame(cur.fetchall(), columns=[
  57. x.name for x in cur.description
  58. ])
  59. if not data.empty:
  60. print()
  61. print(cur._last_query)
  62. print(data.to_string(index=False))
  63. except psycopg.ProgrammingError:
  64. pass
  65. to_exec = ''
  66. input("Press enter to continue")
  67. activity_manager = ActivityManager()
  68. query_manager = QueryManager(cur, display_mapper)
  69. fname = sys.argv[1]
  70. with open(fname) as f:
  71. recipe = parse_recipe.parse_recipe(f, query_manager)
  72. activity_manager.create(RecipeEditor,
  73. 'recipe_editor',
  74. activity_manager, query_manager,
  75. fname, recipe,
  76. )
  77. app = Recipe(activity_manager)
  78. def iter_palettes():
  79. palettes = [ v for k,v in high_contrast.theme.items() ]
  80. while True:
  81. p = palettes.pop(0)
  82. palettes.append(p)
  83. yield p
  84. palettes = iter_palettes()
  85. screen = raw_display.Screen()
  86. loop = MainLoop(app, next(palettes), screen=screen,
  87. unhandled_input=lambda k: show_or_exit(k, screen=screen, palettes=palettes),
  88. pop_ups=True)
  89. loop.run()
  90. cur.execute("ROLLBACK")
  91. cur.close()
  92. conn.close()