Repository: h2oai/wave
File: studio/studio.py (Python)

Code before:
    )
    q.page['header'].items[1].button.disabled = False
    q.page['header'].items[1].button.path = f'{project.server_adress}{path}'


async def on_startup():
    file_utils.create_folder(project.dir)
    app_path = Path(project.entry_point)
    if not app_path.exists():
        shutil.copy('starter.py', app_path)
    start(os.path.join(Path(__file__).parent, 'landing.py'), False).communicate()


async def on_shutdown():
    file_utils.remove_folder(project.dir)


async def export(q: Q):
    shutil.make_archive('app', 'zip', '.', project.dir)
    q.app.zip_path, = await q.site.upload(['app.zip'])
    q.page["meta"].script = ui.inline_script(f'window.open("{q.app.zip_path}", "_blank");')
    os.remove("app.zip")


def get_package_dialog_items():
    file = open('project/requirements.txt', 'r') if os.path.exists('project/requirements.txt') else None
    packages_installed = os.stat("project/requirements.txt").st_size > 0 if file else False
    return [
        ui.text_l('Installed packages'),
        ui.inline(
            direction='column', align='start',
            # List of installed packages.
            items=[
                ui.inline(align='end', items=[
                    ui.textbox(name='package_name', value=package_name, readonly=True),
                    ui.textbox(name='package_version', value=package_version, readonly=True),
                    ui.button('remove_package', label='Remove', value=package_name),
                ]) for package_name, package_version in
                [package.removesuffix('\n').split('==') for package in file.readlines()]
            ],
        ) if packages_installed else ui.text(name='no_packages', content='No packages installed.'),
        ui.inline(
            align='end',
            justify='center',
            height='60px',
            items=[ui.buttons(items=[
                ui.button(name='show_add_package_fields', label='Add package', icon='Add', primary=True, width='200px'),
                ui.button(name='show_add_requirements', label='Add from requirements', icon='AddToShoppingList',
                          width='200px')
            ], justify='center')]
        ),

Review comment (performance):
This introduces a memory leak. Use a proper context manager instead. See the [docs](https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files).

Code after:
    )
    q.page['header'].items[1].button.disabled = False
    q.page['header'].items[1].button.path = f'{project.server_adress}{path}'


async def on_startup():
    file_utils.create_folder(project.dir)
    app_path = Path(project.entry_point)
    if not app_path.exists():
        shutil.copy('starter.py', app_path)
    start(os.path.join(Path(__file__).parent, 'landing.py'), False).communicate()


async def on_shutdown():
    file_utils.remove_folder(project.dir)


async def export(q: Q):
    shutil.make_archive('app', 'zip', '.', project.dir)
    q.app.zip_path, = await q.site.upload(['app.zip'])
    q.page["meta"].script = ui.inline_script(f'window.open("{q.app.zip_path}", "_blank");')
    os.remove("app.zip")


def get_tab_items(tab_name: str):
    if tab_name == 'installed':
        packages_installed = []
        if os.path.exists('project/requirements.txt'):
            with open('project/requirements.txt', 'r') as file:
                for line in file.readlines():
                    package_name, package_version = line.strip().split('==') if "==" in line else [line, '']
                    packages_installed.append((package_name, package_version))
        return [
            ui.button(name='remove_selected', label='Remove selected', icon='Delete', width='200px', disabled=True, visible=bool(packages_installed)),
            ui.table(
                name='table',
                multiple=True,
                events=['select'],
                height='calc(100vh - 200px)',
                columns=[
                    ui.table_column(name='package_name', label='Package name'),
                    ui.table_column(name='package_version', label='Version'),
                ],
                rows=[ui.table_row(name=package_name, cells=[package_name, package_version]) for
                    package_name, package_version in packages_installed],
            ) if packages_installed else ui.text(name='no_packages', content='No packages installed.'),
        ]
    elif tab_name == 'add_single':
        return [
            ui.textbox(name='package_name', label='Package name', required=True, trigger=True),
            ui.textbox(name='package_version', label='Version', placeholder='(latest)'),