-
+
{t('exit_confirmation_body')}
diff --git a/opentrons-ai-client/src/organisms/ApplicationSection/__tests__/ApplicationSection.test.tsx b/opentrons-ai-client/src/organisms/ApplicationSection/__tests__/ApplicationSection.test.tsx
index 50e01fcb66f..477c871b7c5 100644
--- a/opentrons-ai-client/src/organisms/ApplicationSection/__tests__/ApplicationSection.test.tsx
+++ b/opentrons-ai-client/src/organisms/ApplicationSection/__tests__/ApplicationSection.test.tsx
@@ -13,6 +13,8 @@ const TestFormProviderComponent = () => {
return (
+
+ {`form is ${methods.formState.isValid ? 'valid' : 'invalid'}`}
)
}
@@ -33,7 +35,6 @@ describe('ApplicationSection', () => {
expect(
screen.getByText('Describe what you are trying to do')
).toBeInTheDocument()
- expect(screen.getByText('Confirm')).toBeInTheDocument()
})
it('should not render other application dropdown if Other option is not selected', () => {
@@ -54,10 +55,10 @@ describe('ApplicationSection', () => {
expect(screen.getByText('Other application')).toBeInTheDocument()
})
- it('should enable confirm button when all fields are filled', async () => {
+ it('should update the form state to valid when all fields are filled', async () => {
render()
- expect(screen.getByRole('button', { name: 'Confirm' })).toBeDisabled()
+ expect(screen.getByText('form is invalid')).toBeInTheDocument()
const applicationDropdown = screen.getByText('Select an option')
fireEvent.click(applicationDropdown)
@@ -69,14 +70,13 @@ describe('ApplicationSection', () => {
fireEvent.change(describeInput, { target: { value: 'Test description' } })
await waitFor(() => {
- expect(screen.getByRole('button', { name: 'Confirm' })).toBeEnabled()
+ expect(screen.getByText('form is valid')).toBeInTheDocument()
})
})
- it('should disable confirm button when all fields are not filled', () => {
+ it('should update the form state to invalid when not all fields are filled', () => {
render()
- const confirmButton = screen.getByRole('button')
- expect(confirmButton).toBeDisabled()
+ expect(screen.getByText('form is invalid')).toBeInTheDocument()
})
})
diff --git a/opentrons-ai-client/src/organisms/ApplicationSection/index.tsx b/opentrons-ai-client/src/organisms/ApplicationSection/index.tsx
index 5e3cc523f68..54819e99a3a 100644
--- a/opentrons-ai-client/src/organisms/ApplicationSection/index.tsx
+++ b/opentrons-ai-client/src/organisms/ApplicationSection/index.tsx
@@ -1,19 +1,8 @@
-import {
- DIRECTION_COLUMN,
- DISPLAY_FLEX,
- Flex,
- JUSTIFY_FLEX_END,
- LargeButton,
- SPACING,
-} from '@opentrons/components'
+import { DIRECTION_COLUMN, Flex, SPACING } from '@opentrons/components'
import { useFormContext } from 'react-hook-form'
import { useTranslation } from 'react-i18next'
-import styled from 'styled-components'
import { ControlledDropdownMenu } from '../../atoms/ControlledDropdownMenu'
import { ControlledInputField } from '../../atoms/ControlledInputField'
-import { useAtom } from 'jotai'
-import { createProtocolAtom } from '../../resources/atoms'
-import { APPLICATION_STEP } from '../ProtocolSectionsContainer'
export const BASIC_ALIQUOTING = 'basic_aliquoting'
export const PCR = 'pcr'
@@ -25,11 +14,7 @@ export const APPLICATION_DESCRIBE = 'application.description'
export function ApplicationSection(): JSX.Element | null {
const { t } = useTranslation('create_protocol')
- const {
- watch,
- formState: { isValid },
- } = useFormContext()
- const [{ currentStep }, setCreateProtocolAtom] = useAtom(createProtocolAtom)
+ const { watch } = useFormContext()
const options = [
{ name: t(BASIC_ALIQUOTING), value: BASIC_ALIQUOTING },
@@ -39,16 +24,6 @@ export function ApplicationSection(): JSX.Element | null {
const isOtherSelected = watch(APPLICATION_SCIENTIFIC_APPLICATION) === OTHER
- function handleConfirmButtonClick(): void {
- const step =
- currentStep > APPLICATION_STEP ? currentStep : APPLICATION_STEP + 1
-
- setCreateProtocolAtom({
- currentStep: step,
- focusStep: step,
- })
- }
-
return (
-
-
-
-
)
}
-
-const ButtonContainer = styled.div`
- display: ${DISPLAY_FLEX};
- justify-content: ${JUSTIFY_FLEX_END};
-`
diff --git a/opentrons-ai-client/src/organisms/InstrumentsSection/__tests__/InstrumentsSection.test.tsx b/opentrons-ai-client/src/organisms/InstrumentsSection/__tests__/InstrumentsSection.test.tsx
index 11e6bceaf45..0712ede4757 100644
--- a/opentrons-ai-client/src/organisms/InstrumentsSection/__tests__/InstrumentsSection.test.tsx
+++ b/opentrons-ai-client/src/organisms/InstrumentsSection/__tests__/InstrumentsSection.test.tsx
@@ -13,6 +13,8 @@ const TestFormProviderComponent = () => {
return (
+
+ {`form is ${methods.formState.isValid ? 'valid' : 'invalid'}`}
)
}
@@ -24,7 +26,7 @@ const render = (): ReturnType => {
}
describe('ApplicationSection', () => {
- it('should render robot, pipette, flex gripper radios, mounts dropdowns, and confirm button', async () => {
+ it('should render robot, pipette, flex gripper radios and mounts dropdowns', async () => {
render()
expect(
@@ -40,7 +42,6 @@ describe('ApplicationSection', () => {
expect(
screen.getByText('Do you want to use the Flex Gripper?')
).toBeInTheDocument()
- expect(screen.getByText('Confirm')).toBeInTheDocument()
})
it('should not render left and right mount dropdowns if 96-Channel 1000µL pipette radio is selected', () => {
@@ -80,7 +81,7 @@ describe('ApplicationSection', () => {
render()
await waitFor(() => {
- expect(screen.getByRole('button', { name: 'Confirm' })).toBeDisabled()
+ expect(screen.getByText('form is invalid')).toBeInTheDocument()
})
const leftMount = screen.getAllByText('Choose pipette')[0]
@@ -96,14 +97,14 @@ describe('ApplicationSection', () => {
})
expect(screen.getByText('None')).toBeInTheDocument()
- expect(screen.getByRole('button', { name: 'Confirm' })).toBeEnabled()
+ expect(screen.getByText('form is valid')).toBeInTheDocument()
})
it('should not be able to select two pipettes with none value', async () => {
render()
await waitFor(() => {
- expect(screen.getByRole('button', { name: 'Confirm' })).toBeDisabled()
+ expect(screen.getByText('form is invalid')).toBeInTheDocument()
})
const leftMount = screen.getAllByText('Choose pipette')[0]
@@ -115,15 +116,15 @@ describe('ApplicationSection', () => {
fireEvent.click(screen.getAllByText('None')[1])
await waitFor(() => {
- expect(screen.getByRole('button', { name: 'Confirm' })).toBeDisabled()
+ expect(screen.getByText('form is invalid')).toBeInTheDocument()
})
})
- it('should enable confirm button when all fields are filled', async () => {
+ it('should update the form state to valid when all fields are filled', async () => {
render()
await waitFor(() => {
- expect(screen.getByRole('button', { name: 'Confirm' })).toBeDisabled()
+ expect(screen.getByText('form is invalid')).toBeInTheDocument()
})
const leftMount = screen.getAllByText('Choose pipette')[0]
@@ -135,16 +136,7 @@ describe('ApplicationSection', () => {
fireEvent.click(screen.getByText('Flex 8-Channel 50 μL'))
await waitFor(() => {
- expect(screen.getByRole('button', { name: 'Confirm' })).toBeEnabled()
- })
- })
-
- it('should disable confirm button when all fields are not filled', async () => {
- render()
-
- const confirmButton = screen.getByRole('button')
- await waitFor(() => {
- expect(confirmButton).not.toBeEnabled()
+ expect(screen.getByText('form is valid')).toBeInTheDocument()
})
})
})
diff --git a/opentrons-ai-client/src/organisms/InstrumentsSection/index.tsx b/opentrons-ai-client/src/organisms/InstrumentsSection/index.tsx
index c56276e1dfa..6f815b45a5d 100644
--- a/opentrons-ai-client/src/organisms/InstrumentsSection/index.tsx
+++ b/opentrons-ai-client/src/organisms/InstrumentsSection/index.tsx
@@ -1,19 +1,13 @@
import {
COLORS,
DIRECTION_COLUMN,
- DISPLAY_FLEX,
Flex,
- JUSTIFY_FLEX_END,
- LargeButton,
SPACING,
StyledText,
} from '@opentrons/components'
import { useFormContext } from 'react-hook-form'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'
-import { useAtom } from 'jotai'
-import { createProtocolAtom } from '../../resources/atoms'
-import { INSTRUMENTS_STEP } from '../ProtocolSectionsContainer'
import { ControlledDropdownMenu } from '../../atoms/ControlledDropdownMenu'
import { ControlledRadioButtonGroup } from '../../molecules/ControlledRadioButtonGroup'
import { useMemo } from 'react'
@@ -21,7 +15,6 @@ import {
getAllPipetteNames,
getPipetteSpecsV2,
OT2_PIPETTES,
- OT2_ROBOT_TYPE,
OT3_PIPETTES,
} from '@opentrons/shared-data'
@@ -40,11 +33,7 @@ export const NO_PIPETTES = 'none'
export function InstrumentsSection(): JSX.Element | null {
const { t } = useTranslation('create_protocol')
- const {
- formState: { isValid },
- watch,
- } = useFormContext()
- const [{ currentStep }, setCreateProtocolAtom] = useAtom(createProtocolAtom)
+ const { watch } = useFormContext()
const robotType = watch(ROBOT_FIELD_NAME)
const isOtherPipettesSelected = watch(PIPETTES_FIELD_NAME) === TWO_PIPETTES
const isOpentronsOT2Selected = robotType === OPENTRONS_OT2
@@ -91,7 +80,7 @@ export function InstrumentsSection(): JSX.Element | null {
const pipetteOptions = useMemo(() => {
const allPipetteOptions = getAllPipetteNames('maxVolume', 'channels')
.filter(name =>
- (robotType === OT2_ROBOT_TYPE ? OT2_PIPETTES : OT3_PIPETTES).includes(
+ (robotType === OPENTRONS_OT2 ? OT2_PIPETTES : OT3_PIPETTES).includes(
name
)
)
@@ -103,16 +92,6 @@ export function InstrumentsSection(): JSX.Element | null {
return [{ name: t('none'), value: NO_PIPETTES }, ...allPipetteOptions]
}, [robotType])
- function handleConfirmButtonClick(): void {
- const step =
- currentStep > INSTRUMENTS_STEP ? currentStep : INSTRUMENTS_STEP + 1
-
- setCreateProtocolAtom({
- currentStep: step,
- focusStep: step,
- })
- }
-
return (
)}
-
-
-
-
)
}
-const ButtonContainer = styled.div`
- display: ${DISPLAY_FLEX};
- justify-content: ${JUSTIFY_FLEX_END};
-`
-
const PipettesDropdown = styled.div<{ isOpentronsOT2Selected?: boolean }>`
display: flex;
flex-direction: column;
diff --git a/opentrons-ai-client/src/organisms/LabwareLiquidsSection/__tests__/LabwareLiquidsSection.test.tsx b/opentrons-ai-client/src/organisms/LabwareLiquidsSection/__tests__/LabwareLiquidsSection.test.tsx
index ce5f40e8e52..9e4d76391f0 100644
--- a/opentrons-ai-client/src/organisms/LabwareLiquidsSection/__tests__/LabwareLiquidsSection.test.tsx
+++ b/opentrons-ai-client/src/organisms/LabwareLiquidsSection/__tests__/LabwareLiquidsSection.test.tsx
@@ -1,4 +1,4 @@
-import { fireEvent, screen } from '@testing-library/react'
+import { fireEvent, screen, waitFor } from '@testing-library/react'
import { describe, it, expect } from 'vitest'
import { renderWithProviders } from '../../../__testing-utils__'
import { i18n } from '../../../i18n'
@@ -15,6 +15,8 @@ const TestFormProviderComponent = () => {
return (
+
+ {`form is ${methods.formState.isValid ? 'valid' : 'invalid'}`}
)
}
@@ -31,7 +33,6 @@ describe('LabwareLiquidsSection', () => {
expect(screen.getByText('Add Opentrons labware')).toBeInTheDocument()
expect(screen.getByText('No labware added yet')).toBeInTheDocument()
- expect(screen.getByText('Confirm')).toBeInTheDocument()
})
it('should not display the no labware added message if labwares have been added', async () => {
@@ -51,20 +52,27 @@ describe('LabwareLiquidsSection', () => {
expect(screen.queryByText('No labware added yet')).not.toBeInTheDocument()
})
- // it('should enable the confirm button when labwares have been added', async () => {
- // render()
+ it('should update form state to valid when labwares and liquids have been added', async () => {
+ render()
- // expect(screen.getByText('Confirm')).toBeDisabled()
+ await waitFor(() => {
+ expect(screen.getByText('form is invalid')).toBeInTheDocument()
+ })
+ const addButton = screen.getByText('Add Opentrons labware')
+ fireEvent.click(addButton)
- // const addButton = screen.getByText('Add Opentrons labware')
- // fireEvent.click(addButton)
+ fireEvent.click(screen.getByText('Tip rack'))
+ fireEvent.click(
+ await screen.findByText('Opentrons Flex 96 Tip Rack 1000 µL')
+ )
+ fireEvent.click(screen.getByText('Save'))
- // fireEvent.click(screen.getByText('Tip rack'))
- // fireEvent.click(
- // await screen.findByText('Opentrons Flex 96 Tip Rack 1000 µL')
- // )
- // fireEvent.click(screen.getByText('Save'))
+ fireEvent.change(screen.getByRole('textbox'), {
+ target: { value: 'test liquid' },
+ })
- // expect(screen.getByText('Confirm')).toBeEnabled()
- // })
+ await waitFor(() => {
+ expect(screen.getByText('form is valid')).toBeInTheDocument()
+ })
+ })
})
diff --git a/opentrons-ai-client/src/organisms/LabwareLiquidsSection/index.tsx b/opentrons-ai-client/src/organisms/LabwareLiquidsSection/index.tsx
index 627b3a5ea76..24d50e32f21 100644
--- a/opentrons-ai-client/src/organisms/LabwareLiquidsSection/index.tsx
+++ b/opentrons-ai-client/src/organisms/LabwareLiquidsSection/index.tsx
@@ -1,21 +1,14 @@
import {
COLORS,
DIRECTION_COLUMN,
- DISPLAY_FLEX,
EmptySelectorButton,
Flex,
InfoScreen,
- JUSTIFY_FLEX_END,
- LargeButton,
SPACING,
StyledText,
} from '@opentrons/components'
import { useFormContext } from 'react-hook-form'
import { useTranslation } from 'react-i18next'
-import styled from 'styled-components'
-import { useAtom } from 'jotai'
-import { createProtocolAtom } from '../../resources/atoms'
-import { LABWARE_LIQUIDS_STEP } from '../ProtocolSectionsContainer'
import { useState } from 'react'
import { LabwareModal } from '../LabwareModal'
import { ControlledLabwareListItems } from '../../molecules/ControlledLabwareListItems'
@@ -31,29 +24,12 @@ export const LIQUIDS_FIELD_NAME = 'liquids'
export function LabwareLiquidsSection(): JSX.Element | null {
const { t } = useTranslation('create_protocol')
- const {
- formState: { isValid },
- setValue,
- watch,
- } = useFormContext()
- const [{ currentStep }, setCreateProtocolAtom] = useAtom(createProtocolAtom)
+ const { setValue, watch } = useFormContext()
const [displayLabwareModal, setDisplayLabwareModal] = useState(false)
const labwares: DisplayLabware[] = watch(LABWARES_FIELD_NAME) ?? []
const liquids: string[] = watch(LIQUIDS_FIELD_NAME) ?? []
- function handleConfirmButtonClick(): void {
- const step =
- currentStep > LABWARE_LIQUIDS_STEP
- ? currentStep
- : LABWARE_LIQUIDS_STEP + 1
-
- setCreateProtocolAtom({
- currentStep: step,
- focusStep: step,
- })
- }
-
return (
-
-
-
-
)
}
-
-const ButtonContainer = styled.div`
- display: ${DISPLAY_FLEX};
- justify-content: ${JUSTIFY_FLEX_END};
-`
diff --git a/opentrons-ai-client/src/organisms/LabwareModal/index.tsx b/opentrons-ai-client/src/organisms/LabwareModal/index.tsx
index baf83087877..28324b18dee 100644
--- a/opentrons-ai-client/src/organisms/LabwareModal/index.tsx
+++ b/opentrons-ai-client/src/organisms/LabwareModal/index.tsx
@@ -229,10 +229,18 @@ export function LabwareModal({
setValue(
LABWARES_FIELD_NAME,
[
- ...selectedLabwares.map(labwareURI => ({
- labwareURI,
- count: 1,
- })),
+ ...selectedLabwares.map(labwareURI => {
+ const existingLabware = labwares.find(
+ lw => lw.labwareURI === labwareURI
+ )
+ return {
+ labwareURI,
+ count:
+ existingLabware != null
+ ? existingLabware.count
+ : 1,
+ }
+ }),
],
{ shouldValidate: true }
)
diff --git a/opentrons-ai-client/src/organisms/ModulesSection/__tests__/ModulesSection.test.tsx b/opentrons-ai-client/src/organisms/ModulesSection/__tests__/ModulesSection.test.tsx
index 16c7046f152..652df2a1b95 100644
--- a/opentrons-ai-client/src/organisms/ModulesSection/__tests__/ModulesSection.test.tsx
+++ b/opentrons-ai-client/src/organisms/ModulesSection/__tests__/ModulesSection.test.tsx
@@ -15,6 +15,8 @@ const TestFormProviderComponent = () => {
return (
+
+ {`form is ${methods.formState.isValid ? 'valid' : 'invalid'}`}
)
}
@@ -26,12 +28,11 @@ const render = (): ReturnType => {
}
describe('ModulesSection', () => {
- it('should render modules buttons, no modules added yet, and confirm button', async () => {
+ it('should render modules buttons and no modules added yet', async () => {
render()
- expect(screen.getAllByRole('button').length).toBe(5)
+ expect(screen.getAllByRole('button').length).toBe(4)
expect(screen.getByText('No modules added yet')).toBeInTheDocument()
- expect(screen.getByText('Confirm')).toBeInTheDocument()
})
it('should render a list item with the selected module if user clicks the module button', () => {
@@ -71,20 +72,11 @@ describe('ModulesSection', () => {
expect(screen.getAllByText('Heater-Shaker Module GEN1').length).toBe(1)
})
- it('should disable confirm button when all fields are not filled', async () => {
- render()
-
- const confirmButton = screen.getByRole('button', { name: 'Confirm' })
- await waitFor(() => {
- expect(confirmButton).not.toBeEnabled()
- })
- })
-
- it('should render with Confirm button enabled, modules are not required', async () => {
+ it('should render with form state valid, modules are not required', async () => {
render()
await waitFor(() => {
- expect(screen.getByRole('button', { name: 'Confirm' })).toBeEnabled()
+ expect(screen.getByText('form is valid')).toBeInTheDocument()
})
})
})
diff --git a/opentrons-ai-client/src/organisms/ModulesSection/index.tsx b/opentrons-ai-client/src/organisms/ModulesSection/index.tsx
index 85f068bc226..2531d9aab37 100644
--- a/opentrons-ai-client/src/organisms/ModulesSection/index.tsx
+++ b/opentrons-ai-client/src/organisms/ModulesSection/index.tsx
@@ -1,18 +1,11 @@
import {
DIRECTION_COLUMN,
- DISPLAY_FLEX,
Flex,
InfoScreen,
- JUSTIFY_FLEX_END,
- LargeButton,
SPACING,
} from '@opentrons/components'
import { useFormContext } from 'react-hook-form'
import { useTranslation } from 'react-i18next'
-import styled from 'styled-components'
-import { useAtom } from 'jotai'
-import { createProtocolAtom } from '../../resources/atoms'
-import { MODULES_STEP } from '../ProtocolSectionsContainer'
import { ControlledEmptySelectorButtonGroup } from '../../molecules/ControlledEmptySelectorButtonGroup'
import { ModuleListItemGroup } from '../../molecules/ModuleListItemGroup'
import type { ModuleType, ModuleModel } from '@opentrons/shared-data'
@@ -31,11 +24,7 @@ export const MODULES_FIELD_NAME = 'modules'
export function ModulesSection(): JSX.Element | null {
const { t } = useTranslation('create_protocol')
- const {
- formState: { isValid },
- watch,
- } = useFormContext()
- const [{ currentStep }, setCreateProtocolAtom] = useAtom(createProtocolAtom)
+ const { watch } = useFormContext()
const modules: DisplayModules[] = [
{
@@ -60,15 +49,6 @@ export function ModulesSection(): JSX.Element | null {
},
]
- function handleConfirmButtonClick(): void {
- const step = currentStep > MODULES_STEP ? currentStep : MODULES_STEP + 1
-
- setCreateProtocolAtom({
- currentStep: step,
- focusStep: step,
- })
- }
-
const modulesWatch: DisplayModules[] = watch(MODULES_FIELD_NAME) ?? []
return (
@@ -84,19 +64,6 @@ export function ModulesSection(): JSX.Element | null {
)}
-
-
-
-
)
}
-
-const ButtonContainer = styled.div`
- display: ${DISPLAY_FLEX};
- justify-content: ${JUSTIFY_FLEX_END};
-`
diff --git a/opentrons-ai-client/src/organisms/ProtocolSectionsContainer/index.tsx b/opentrons-ai-client/src/organisms/ProtocolSectionsContainer/index.tsx
index 7240a83ae4f..3946d6a5cf5 100644
--- a/opentrons-ai-client/src/organisms/ProtocolSectionsContainer/index.tsx
+++ b/opentrons-ai-client/src/organisms/ProtocolSectionsContainer/index.tsx
@@ -1,15 +1,23 @@
-import { DIRECTION_COLUMN, Flex, SPACING } from '@opentrons/components'
+import {
+ DIRECTION_COLUMN,
+ DISPLAY_FLEX,
+ Flex,
+ JUSTIFY_FLEX_END,
+ LargeButton,
+ SPACING,
+} from '@opentrons/components'
import { useTranslation } from 'react-i18next'
import { Accordion } from '../../molecules/Accordion'
import styled from 'styled-components'
import { ApplicationSection } from '../../organisms/ApplicationSection'
import { createProtocolAtom } from '../../resources/atoms'
import { useAtom } from 'jotai'
-import { useFormContext } from 'react-hook-form'
import { InstrumentsSection } from '../InstrumentsSection'
import { ModulesSection } from '../ModulesSection'
import { LabwareLiquidsSection } from '../LabwareLiquidsSection'
import { StepsSection } from '../StepsSection'
+import { useFormContext } from 'react-hook-form'
+import { COLUMN } from '@opentrons/shared-data'
export const APPLICATION_STEP = 0
export const INSTRUMENTS_STEP = 1
@@ -22,62 +30,83 @@ export function ProtocolSectionsContainer(): JSX.Element | null {
const {
formState: { isValid },
} = useFormContext()
- const [{ currentStep, focusStep }, setCreateProtocolAtom] = useAtom(
+ const [{ currentSection, focusSection }, setCreateProtocolAtom] = useAtom(
createProtocolAtom
)
function handleSectionClick(stepNumber: number): void {
- currentStep >= stepNumber &&
+ currentSection >= stepNumber &&
isValid &&
setCreateProtocolAtom({
- currentStep,
- focusStep: stepNumber,
+ currentSection,
+ focusSection: stepNumber,
})
}
function displayCheckmark(stepNumber: number): boolean {
- return currentStep > stepNumber && focusStep !== stepNumber
+ return currentSection > stepNumber && focusSection !== stepNumber
+ }
+
+ function handleConfirmButtonClick(): void {
+ const step =
+ currentSection > focusSection ? currentSection : focusSection + 1
+
+ setCreateProtocolAtom({
+ currentSection: step,
+ focusSection: step,
+ })
}
return (
{[
{
- stepNumber: APPLICATION_STEP,
+ sectionNumber: APPLICATION_STEP,
title: 'application_title',
Component: ApplicationSection,
},
{
- stepNumber: INSTRUMENTS_STEP,
+ sectionNumber: INSTRUMENTS_STEP,
title: 'instruments_title',
Component: InstrumentsSection,
},
{
- stepNumber: MODULES_STEP,
+ sectionNumber: MODULES_STEP,
title: 'modules_title',
Component: ModulesSection,
},
{
- stepNumber: LABWARE_LIQUIDS_STEP,
+ sectionNumber: LABWARE_LIQUIDS_STEP,
title: 'labware_liquids_title',
Component: LabwareLiquidsSection,
},
{
- stepNumber: STEPS_STEP,
+ sectionNumber: STEPS_STEP,
title: 'steps_title',
Component: StepsSection,
},
- ].map(({ stepNumber, title, Component }) => (
+ ].map(({ sectionNumber, title, Component }) => (
{
- handleSectionClick(stepNumber)
+ handleSectionClick(sectionNumber)
}}
- isCompleted={displayCheckmark(stepNumber)}
+ isCompleted={displayCheckmark(sectionNumber)}
>
- {focusStep === stepNumber && }
+ {focusSection === sectionNumber && (
+
+
+
+
+
+
+ )}
))}
@@ -89,3 +118,8 @@ const ProtocolSections = styled(Flex)`
width: 100%;
gap: ${SPACING.spacing16};
`
+
+const ButtonContainer = styled.div`
+ display: ${DISPLAY_FLEX};
+ justify-content: ${JUSTIFY_FLEX_END};
+`
diff --git a/opentrons-ai-client/src/organisms/StepsSection/__tests__/StepsSection.test.tsx b/opentrons-ai-client/src/organisms/StepsSection/__tests__/StepsSection.test.tsx
index 8ef93100bc0..06fc8b30741 100644
--- a/opentrons-ai-client/src/organisms/StepsSection/__tests__/StepsSection.test.tsx
+++ b/opentrons-ai-client/src/organisms/StepsSection/__tests__/StepsSection.test.tsx
@@ -23,6 +23,8 @@ const TestFormProviderComponent = () => {
) : (
{steps}
)}
+
+ {`form is ${methods.formState.isValid ? 'valid' : 'invalid'}`}
)
}
@@ -113,17 +115,17 @@ describe('StepsSection', () => {
expect(screen.getAllByText('description test')[1]).toBeInTheDocument()
})
- it('should enable the confirm button when steps have been added', async () => {
+ it('should update form state to valid when steps have been added', async () => {
render()
- expect(screen.getByRole('button', { name: 'Confirm' })).toBeDisabled()
+ expect(screen.getByText('form is invalid')).toBeInTheDocument()
fireEvent.change(screen.getByRole('textbox'), {
target: { value: 'description test' },
})
await waitFor(() => {
- expect(screen.getByRole('button', { name: 'Confirm' })).toBeEnabled()
+ expect(screen.getByText('form is valid')).toBeInTheDocument()
})
})
})
diff --git a/opentrons-ai-client/src/organisms/StepsSection/index.tsx b/opentrons-ai-client/src/organisms/StepsSection/index.tsx
index b44d0985039..f2fe7dd8024 100644
--- a/opentrons-ai-client/src/organisms/StepsSection/index.tsx
+++ b/opentrons-ai-client/src/organisms/StepsSection/index.tsx
@@ -1,11 +1,8 @@
import {
COLORS,
DIRECTION_COLUMN,
- DISPLAY_FLEX,
EmptySelectorButton,
Flex,
- JUSTIFY_FLEX_END,
- LargeButton,
SPACING,
StyledText,
Tabs,
@@ -13,9 +10,6 @@ import {
import { useFormContext } from 'react-hook-form'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'
-import { useAtom } from 'jotai'
-import { createProtocolAtom } from '../../resources/atoms'
-import { STEPS_STEP } from '../ProtocolSectionsContainer'
import { useState } from 'react'
import { COLUMN } from '@opentrons/shared-data'
import { ControlledAddTextAreaFields } from '../../molecules/ControlledAddTextAreaFields'
@@ -25,25 +19,11 @@ export const STEPS_FIELD_NAME = 'steps'
export function StepsSection(): JSX.Element | null {
const { t } = useTranslation('create_protocol')
- const {
- formState: { isValid },
- setValue,
- watch,
- } = useFormContext()
- const [{ currentStep }, setCreateProtocolAtom] = useAtom(createProtocolAtom)
+ const { setValue, watch } = useFormContext()
const [isIndividualStep, setIsIndividualStep] = useState(true)
const steps = watch(STEPS_FIELD_NAME) ?? []
- function handleConfirmButtonClick(): void {
- const step = currentStep > STEPS_STEP ? currentStep : STEPS_STEP + 1
-
- setCreateProtocolAtom({
- currentStep: step,
- focusStep: step,
- })
- }
-
return (
)}
-
-
-
-
)
}
-const ButtonContainer = styled.div`
- display: ${DISPLAY_FLEX};
- justify-content: ${JUSTIFY_FLEX_END};
-`
-
const ExampleOrderedList = styled.ol`
margin-left: ${SPACING.spacing20};
font-size: 14px;
diff --git a/opentrons-ai-client/src/organisms/UpdateProtocol/index.tsx b/opentrons-ai-client/src/organisms/UpdateProtocol/index.tsx
index 9b47ce4c251..4e13e5dfc98 100644
--- a/opentrons-ai-client/src/organisms/UpdateProtocol/index.tsx
+++ b/opentrons-ai-client/src/organisms/UpdateProtocol/index.tsx
@@ -4,7 +4,6 @@ import {
DIRECTION_COLUMN,
DIRECTION_ROW,
Flex,
- InputField,
JUSTIFY_CENTER,
JUSTIFY_END,
LargeButton,
@@ -28,6 +27,7 @@ import {
import { CSSTransition } from 'react-transition-group'
import { useAtom } from 'jotai'
import { useTrackEvent } from '../../resources/hooks/useTrackEvent'
+import { TextAreaField } from '../../atoms/TextAreaField'
interface UpdateOptionsDropdown extends DropdownOption {
value: UpdateOptions
@@ -156,7 +156,7 @@ export function UpdateProtocol(): JSX.Element {
setHeaderWithMeterAtom,
])
- const handleInputChange = (event: ChangeEvent): void => {
+ const handleInputChange = (event: ChangeEvent): void => {
setDetailsValue(event.target.value)
}
@@ -171,7 +171,6 @@ export function UpdateProtocol(): JSX.Element {
if (typeof text === 'string' && text !== '') {
setErrorText(null)
- console.log('File read successfully:\n', text)
setPythonTextValue(text)
} else {
setErrorText(t('file_length_error'))
@@ -194,8 +193,6 @@ export function UpdateProtocol(): JSX.Element {
const chatPrompt = `${introText}${originalCodeText}${updateTypeText}${detailsText}`
- console.log(chatPrompt)
-
setUpdatePromptAtom({
prompt: chatPrompt,
protocol_text: pythonText,
@@ -310,10 +307,10 @@ export function UpdateProtocol(): JSX.Element {
/>
{t('provide_details_of_changes')}
-
{
return () => {
@@ -106,8 +108,8 @@ export function CreateProtocol(): JSX.Element | null {
methods.reset()
setCreateProtocolAtom({
- currentStep: 0,
- focusStep: 0,
+ currentSection: 0,
+ focusSection: 0,
})
}
}, [])
@@ -138,7 +140,7 @@ export function CreateProtocol(): JSX.Element | null {
}, [isResizing])
function calculateProgress(): number {
- return currentStep > 0 ? currentStep / TOTAL_STEPS : 0
+ return currentSection > 0 ? currentSection / TOTAL_STEPS : 0
}
function handleMouseDown(
@@ -209,7 +211,7 @@ export function CreateProtocol(): JSX.Element | null {
diff --git a/opentrons-ai-client/src/resources/atoms.ts b/opentrons-ai-client/src/resources/atoms.ts
index 01018abfe08..40ddce7fc53 100644
--- a/opentrons-ai-client/src/resources/atoms.ts
+++ b/opentrons-ai-client/src/resources/atoms.ts
@@ -4,7 +4,7 @@ import type {
Chat,
ChatData,
CreatePrompt,
- createProtocolAtomProps,
+ CreateProtocolAtomProps,
HeaderWithMeterAtomProps,
Mixpanel,
UpdatePrompt,
@@ -59,9 +59,9 @@ export const headerWithMeterAtom = atom({
progress: 0,
})
-export const createProtocolAtom = atom({
- currentStep: 0,
- focusStep: 0,
+export const createProtocolAtom = atom({
+ currentSection: 0,
+ focusSection: 0,
})
export const displayExitConfirmModalAtom = atom(false)
diff --git a/opentrons-ai-client/src/resources/types.ts b/opentrons-ai-client/src/resources/types.ts
index 7a84eba1054..516f87e9354 100644
--- a/opentrons-ai-client/src/resources/types.ts
+++ b/opentrons-ai-client/src/resources/types.ts
@@ -84,9 +84,9 @@ export interface HeaderWithMeterAtomProps {
progress: number
}
-export interface createProtocolAtomProps {
- currentStep: number
- focusStep: number
+export interface CreateProtocolAtomProps {
+ currentSection: number
+ focusSection: number
}
export interface PromptData {
diff --git a/opentrons-ai-client/src/resources/utils/createProtocolUtils.tsx b/opentrons-ai-client/src/resources/utils/createProtocolUtils.tsx
index 1c5899a7d0e..3b574e11f10 100644
--- a/opentrons-ai-client/src/resources/utils/createProtocolUtils.tsx
+++ b/opentrons-ai-client/src/resources/utils/createProtocolUtils.tsx
@@ -95,7 +95,11 @@ export function generatePromptPreviewLabwareLiquidsItems(
const defs = getAllDefinitions()
labwares?.forEach(labware => {
- items.push(getLabwareDisplayName(defs[labware.labwareURI]) as string)
+ items.push(
+ `${labware.count} x ${
+ getLabwareDisplayName(defs[labware.labwareURI]) as string
+ }`
+ )
})
liquids?.forEach(liquid => {
From 5f9d2a3d1795a95f60b812bdec34e51d80f88375 Mon Sep 17 00:00:00 2001
From: Seth Foster
Date: Thu, 14 Nov 2024 09:07:48 -0500
Subject: [PATCH 02/31] feat(api): add monadic error passing to protocol engine
(#16788)
Let's make an intermediate layer of command execution, inside the
command domain so we don't have to move a bunch of types, that calls
execution layer functions and returns a new Maybe class that has nice
monadic chaining calls like a JS promise or some other burrito-style
implementations.
As an example, let's use it for overpressure errors in
PrepareToAspirate.
## reviews
- does this seem worth it? in your mind's eye, imagine doing this for a
new `gantry_common.move_to()` that wraps `gantry_mover.move_to()` and
returns a stall defined error.
## testing
- none, this is a refactor that passes tests with few changes
Closes EXEC-830
---
.../protocol_engine/commands/command.py | 246 +++++++++++++++++-
.../commands/pipetting_common.py | 51 +++-
.../commands/prepare_to_aspirate.py | 68 ++---
.../commands/test_prepare_to_aspirate.py | 7 +-
4 files changed, 326 insertions(+), 46 deletions(-)
diff --git a/api/src/opentrons/protocol_engine/commands/command.py b/api/src/opentrons/protocol_engine/commands/command.py
index 1fefcbf7315..fe47c9dbbcc 100644
--- a/api/src/opentrons/protocol_engine/commands/command.py
+++ b/api/src/opentrons/protocol_engine/commands/command.py
@@ -6,8 +6,9 @@
import dataclasses
from abc import ABC, abstractmethod
from datetime import datetime
-from enum import Enum
+import enum
from typing import (
+ cast,
TYPE_CHECKING,
Generic,
Optional,
@@ -15,6 +16,11 @@
List,
Type,
Union,
+ Callable,
+ Awaitable,
+ Literal,
+ Final,
+ TypeAlias,
)
from pydantic import BaseModel, Field
@@ -41,7 +47,7 @@
_ErrorT_co = TypeVar("_ErrorT_co", bound=ErrorOccurrence, covariant=True)
-class CommandStatus(str, Enum):
+class CommandStatus(str, enum.Enum):
"""Command execution status."""
QUEUED = "queued"
@@ -50,7 +56,7 @@ class CommandStatus(str, Enum):
FAILED = "failed"
-class CommandIntent(str, Enum):
+class CommandIntent(str, enum.Enum):
"""Run intent for a given command.
Props:
@@ -242,6 +248,240 @@ class BaseCommand(
]
+class IsErrorValue(Exception):
+ """Panic exception if a Maybe contains an Error."""
+
+ pass
+
+
+class _NothingEnum(enum.Enum):
+ _NOTHING = enum.auto()
+
+
+NOTHING: Final = _NothingEnum._NOTHING
+NothingT: TypeAlias = Literal[_NothingEnum._NOTHING]
+
+
+class _UnknownEnum(enum.Enum):
+ _UNKNOWN = enum.auto()
+
+
+UNKNOWN: Final = _UnknownEnum._UNKNOWN
+UnknownT: TypeAlias = Literal[_UnknownEnum._UNKNOWN]
+
+_ResultT_co_general = TypeVar("_ResultT_co_general", covariant=True)
+_ErrorT_co_general = TypeVar("_ErrorT_co_general", covariant=True)
+
+
+_SecondResultT_co_general = TypeVar("_SecondResultT_co_general", covariant=True)
+_SecondErrorT_co_general = TypeVar("_SecondErrorT_co_general", covariant=True)
+
+
+@dataclasses.dataclass
+class Maybe(Generic[_ResultT_co_general, _ErrorT_co_general]):
+ """Represents an possibly completed, possibly errored result.
+
+ By using this class's chaining methods like and_then or or_else, you can build
+ functions that preserve previous defined errors and augment them or transform them
+ and transform the results.
+
+ Build objects of this type using from_result or from_error on fully type-qualified
+ aliases. For instance,
+
+ MyFunctionReturn = Maybe[SuccessData[SomeSuccessModel], DefinedErrorData[SomeErrorKind]]
+
+ def my_function(args...) -> MyFunctionReturn:
+ try:
+ do_thing(args...)
+ except SomeException as e:
+ return MyFunctionReturn.from_error(ErrorOccurrence.from_error(e))
+ else:
+ return MyFunctionReturn.from_result(SuccessData(SomeSuccessModel(args...)))
+
+ Then, in the calling function, you can react to the results and unwrap to a union:
+
+ OuterMaybe = Maybe[SuccessData[SomeOtherModel], DefinedErrorData[SomeErrors]]
+ OuterReturn = Union[SuccessData[SomeOtherModel], DefinedErrorData[SomeErrors]]
+
+ def my_calling_function(args...) -> OuterReturn:
+ def handle_result(result: SuccessData[SomeSuccessModel]) -> OuterMaybe:
+ return OuterMaybe.from_result(result=some_result_transformer(result))
+ return do_thing.and_then(handle_result).unwrap()
+ """
+
+ _contents: tuple[_ResultT_co_general, NothingT] | tuple[
+ NothingT, _ErrorT_co_general
+ ]
+
+ _CtorErrorT = TypeVar("_CtorErrorT")
+ _CtorResultT = TypeVar("_CtorResultT")
+
+ @classmethod
+ def from_result(
+ cls: Type[Maybe[_CtorResultT, _CtorErrorT]], result: _CtorResultT
+ ) -> Maybe[_CtorResultT, _CtorErrorT]:
+ """Build a Maybe from a valid result."""
+ return cls(_contents=(result, NOTHING))
+
+ @classmethod
+ def from_error(
+ cls: Type[Maybe[_CtorResultT, _CtorErrorT]], error: _CtorErrorT
+ ) -> Maybe[_CtorResultT, _CtorErrorT]:
+ """Build a Maybe from a known error."""
+ return cls(_contents=(NOTHING, error))
+
+ def result_or_panic(self) -> _ResultT_co_general:
+ """Unwrap to a result or throw if the Maybe is an error."""
+ contents = self._contents
+ if contents[1] is NOTHING:
+ # https://github.com/python/mypy/issues/12364
+ return cast(_ResultT_co_general, contents[0])
+ else:
+ raise IsErrorValue()
+
+ def unwrap(self) -> _ResultT_co_general | _ErrorT_co_general:
+ """Unwrap to a union, which is useful for command returns."""
+ # https://github.com/python/mypy/issues/12364
+ if self._contents[1] is NOTHING:
+ return cast(_ResultT_co_general, self._contents[0])
+ else:
+ return self._contents[1]
+
+ # note: casts in these methods are because of https://github.com/python/mypy/issues/11730
+ def and_then(
+ self,
+ functor: Callable[
+ [_ResultT_co_general],
+ Maybe[_SecondResultT_co_general, _SecondErrorT_co_general],
+ ],
+ ) -> Maybe[
+ _SecondResultT_co_general, _ErrorT_co_general | _SecondErrorT_co_general
+ ]:
+ """Conditionally execute functor if the Maybe contains a result.
+
+ Functor should take the result type and return a new Maybe. Since this function returns
+ a Maybe, it can be chained. The result type will have only the Result type of the Maybe
+ returned by the functor, but the error type is the union of the error type in the Maybe
+ returned by the functor and the error type in this Maybe, since the functor may not have
+ actually been called.
+ """
+ match self._contents:
+ case (result, _NothingEnum._NOTHING):
+ return cast(
+ Maybe[
+ _SecondResultT_co_general,
+ _ErrorT_co_general | _SecondErrorT_co_general,
+ ],
+ functor(cast(_ResultT_co_general, result)),
+ )
+ case _:
+ return cast(
+ Maybe[
+ _SecondResultT_co_general,
+ _ErrorT_co_general | _SecondErrorT_co_general,
+ ],
+ self,
+ )
+
+ def or_else(
+ self,
+ functor: Callable[
+ [_ErrorT_co_general],
+ Maybe[_SecondResultT_co_general, _SecondErrorT_co_general],
+ ],
+ ) -> Maybe[
+ _SecondResultT_co_general | _ResultT_co_general, _SecondErrorT_co_general
+ ]:
+ """Conditionally execute functor if the Maybe contains an error.
+
+ The functor should take the error type and return a new Maybe. Since this function returns
+ a Maybe, it can be chained. The result type will have only the Error type of the Maybe
+ returned by the functor, but the result type is the union of the Result of the Maybe returned
+ by the functor and the Result of this Maybe, since the functor may not have been called.
+ """
+ match self._contents:
+ case (_NothingEnum._NOTHING, error):
+ return cast(
+ Maybe[
+ _ResultT_co_general | _SecondResultT_co_general,
+ _SecondErrorT_co_general,
+ ],
+ functor(cast(_ErrorT_co_general, error)),
+ )
+ case _:
+ return cast(
+ Maybe[
+ _ResultT_co_general | _SecondResultT_co_general,
+ _SecondErrorT_co_general,
+ ],
+ self,
+ )
+
+ async def and_then_async(
+ self,
+ functor: Callable[
+ [_ResultT_co_general],
+ Awaitable[Maybe[_SecondResultT_co_general, _SecondErrorT_co_general]],
+ ],
+ ) -> Awaitable[
+ Maybe[_SecondResultT_co_general, _ErrorT_co_general | _SecondErrorT_co_general]
+ ]:
+ """As and_then, but for an async functor."""
+ match self._contents:
+ case (result, _NothingEnum._NOTHING):
+ return cast(
+ Awaitable[
+ Maybe[
+ _SecondResultT_co_general,
+ _ErrorT_co_general | _SecondErrorT_co_general,
+ ]
+ ],
+ await functor(cast(_ResultT_co_general, result)),
+ )
+ case _:
+ return cast(
+ Awaitable[
+ Maybe[
+ _SecondResultT_co_general,
+ _ErrorT_co_general | _SecondErrorT_co_general,
+ ]
+ ],
+ self,
+ )
+
+ async def or_else_async(
+ self,
+ functor: Callable[
+ [_ErrorT_co_general],
+ Awaitable[Maybe[_SecondResultT_co_general, _SecondErrorT_co_general]],
+ ],
+ ) -> Awaitable[
+ Maybe[_SecondResultT_co_general | _ResultT_co_general, _SecondErrorT_co_general]
+ ]:
+ """As or_else, but for an async functor."""
+ match self._contents:
+ case (_NothingEnum._NOTHING, error):
+ return cast(
+ Awaitable[
+ Maybe[
+ _ResultT_co_general | _SecondResultT_co_general,
+ _SecondErrorT_co_general,
+ ]
+ ],
+ await functor(cast(_ErrorT_co_general, error)),
+ )
+ case _:
+ return cast(
+ Awaitable[
+ Maybe[
+ _ResultT_co_general | _SecondResultT_co_general,
+ _SecondErrorT_co_general,
+ ]
+ ],
+ self,
+ )
+
+
_ExecuteReturnT_co = TypeVar(
"_ExecuteReturnT_co",
bound=Union[
diff --git a/api/src/opentrons/protocol_engine/commands/pipetting_common.py b/api/src/opentrons/protocol_engine/commands/pipetting_common.py
index 2dafb4c81b2..6e0064211fa 100644
--- a/api/src/opentrons/protocol_engine/commands/pipetting_common.py
+++ b/api/src/opentrons/protocol_engine/commands/pipetting_common.py
@@ -1,12 +1,20 @@
"""Common pipetting command base models."""
+from __future__ import annotations
from opentrons_shared_data.errors import ErrorCodes
from pydantic import BaseModel, Field
-from typing import Literal, Optional, Tuple, TypedDict
+from typing import Literal, Optional, Tuple, TypedDict, TYPE_CHECKING
from opentrons.protocol_engine.errors.error_occurrence import ErrorOccurrence
+from opentrons_shared_data.errors.exceptions import PipetteOverpressureError
+from .command import Maybe, DefinedErrorData, SuccessData
+from opentrons.protocol_engine.state.update_types import StateUpdate
from ..types import WellLocation, LiquidHandlingWellLocation, DeckPoint
+if TYPE_CHECKING:
+ from ..execution.pipetting import PipettingHandler
+ from ..resources import ModelUtils
+
class PipetteIdMixin(BaseModel):
"""Mixin for command requests that take a pipette ID."""
@@ -201,3 +209,44 @@ class TipPhysicallyAttachedError(ErrorOccurrence):
errorCode: str = ErrorCodes.TIP_DROP_FAILED.value.code
detail: str = ErrorCodes.TIP_DROP_FAILED.value.detail
+
+
+PrepareForAspirateReturn = Maybe[
+ SuccessData[BaseModel], DefinedErrorData[OverpressureError]
+]
+
+
+async def prepare_for_aspirate(
+ pipette_id: str,
+ pipetting: PipettingHandler,
+ model_utils: ModelUtils,
+ location_if_error: ErrorLocationInfo,
+) -> PrepareForAspirateReturn:
+ """Execute pipetting.prepare_for_aspirate, handle errors, and marshal success."""
+ state_update = StateUpdate()
+ try:
+ await pipetting.prepare_for_aspirate(pipette_id)
+ except PipetteOverpressureError as e:
+ state_update.set_fluid_unknown(pipette_id=pipette_id)
+ return PrepareForAspirateReturn.from_error(
+ DefinedErrorData(
+ public=OverpressureError(
+ id=model_utils.generate_id(),
+ createdAt=model_utils.get_timestamp(),
+ wrappedErrors=[
+ ErrorOccurrence.from_failed(
+ id=model_utils.generate_id(),
+ createdAt=model_utils.get_timestamp(),
+ error=e,
+ )
+ ],
+ errorInfo=location_if_error,
+ ),
+ state_update=state_update,
+ )
+ )
+ else:
+ state_update.set_fluid_empty(pipette_id=pipette_id)
+ return PrepareForAspirateReturn.from_result(
+ SuccessData(public=BaseModel(), state_update=state_update)
+ )
diff --git a/api/src/opentrons/protocol_engine/commands/prepare_to_aspirate.py b/api/src/opentrons/protocol_engine/commands/prepare_to_aspirate.py
index f5525b3c90e..38f3a60516a 100644
--- a/api/src/opentrons/protocol_engine/commands/prepare_to_aspirate.py
+++ b/api/src/opentrons/protocol_engine/commands/prepare_to_aspirate.py
@@ -1,24 +1,20 @@
"""Prepare to aspirate command request, result, and implementation models."""
from __future__ import annotations
-from opentrons_shared_data.errors.exceptions import PipetteOverpressureError
from pydantic import BaseModel
from typing import TYPE_CHECKING, Optional, Type, Union
from typing_extensions import Literal
-from .pipetting_common import (
- OverpressureError,
- PipetteIdMixin,
-)
+from .pipetting_common import OverpressureError, PipetteIdMixin, prepare_for_aspirate
from .command import (
AbstractCommandImpl,
BaseCommand,
BaseCommandCreate,
DefinedErrorData,
SuccessData,
+ Maybe,
)
from ..errors.error_occurrence import ErrorOccurrence
-from ..state import update_types
if TYPE_CHECKING:
from ..execution import PipettingHandler, GantryMover
@@ -46,6 +42,11 @@ class PrepareToAspirateResult(BaseModel):
]
+_ExecuteMaybe = Maybe[
+ SuccessData[PrepareToAspirateResult], DefinedErrorData[OverpressureError]
+]
+
+
class PrepareToAspirateImplementation(
AbstractCommandImpl[PrepareToAspirateParams, _ExecuteReturn]
):
@@ -62,44 +63,29 @@ def __init__(
self._model_utils = model_utils
self._gantry_mover = gantry_mover
+ def _transform_result(self, result: SuccessData[BaseModel]) -> _ExecuteMaybe:
+ return _ExecuteMaybe.from_result(
+ SuccessData(
+ public=PrepareToAspirateResult(), state_update=result.state_update
+ )
+ )
+
async def execute(self, params: PrepareToAspirateParams) -> _ExecuteReturn:
"""Prepare the pipette to aspirate."""
current_position = await self._gantry_mover.get_position(params.pipetteId)
- state_update = update_types.StateUpdate()
- try:
- await self._pipetting_handler.prepare_for_aspirate(
- pipette_id=params.pipetteId,
- )
- except PipetteOverpressureError as e:
- state_update.set_fluid_unknown(pipette_id=params.pipetteId)
- return DefinedErrorData(
- public=OverpressureError(
- id=self._model_utils.generate_id(),
- createdAt=self._model_utils.get_timestamp(),
- wrappedErrors=[
- ErrorOccurrence.from_failed(
- id=self._model_utils.generate_id(),
- createdAt=self._model_utils.get_timestamp(),
- error=e,
- )
- ],
- errorInfo=(
- {
- "retryLocation": (
- current_position.x,
- current_position.y,
- current_position.z,
- )
- }
- ),
- ),
- state_update=state_update,
- )
- else:
- state_update.set_fluid_empty(pipette_id=params.pipetteId)
- return SuccessData(
- public=PrepareToAspirateResult(), state_update=state_update
- )
+ prepare_result = await prepare_for_aspirate(
+ pipette_id=params.pipetteId,
+ pipetting=self._pipetting_handler,
+ model_utils=self._model_utils,
+ location_if_error={
+ "retryLocation": (
+ current_position.x,
+ current_position.y,
+ current_position.z,
+ )
+ },
+ )
+ return prepare_result.and_then(self._transform_result).unwrap()
class PrepareToAspirate(
diff --git a/api/tests/opentrons/protocol_engine/commands/test_prepare_to_aspirate.py b/api/tests/opentrons/protocol_engine/commands/test_prepare_to_aspirate.py
index 2de35e38332..f9eded1ffa0 100644
--- a/api/tests/opentrons/protocol_engine/commands/test_prepare_to_aspirate.py
+++ b/api/tests/opentrons/protocol_engine/commands/test_prepare_to_aspirate.py
@@ -34,14 +34,19 @@ def subject(
async def test_prepare_to_aspirate_implementation(
- decoy: Decoy, subject: PrepareToAspirateImplementation, pipetting: PipettingHandler
+ decoy: Decoy,
+ gantry_mover: GantryMover,
+ subject: PrepareToAspirateImplementation,
+ pipetting: PipettingHandler,
) -> None:
"""A PrepareToAspirate command should have an executing implementation."""
data = PrepareToAspirateParams(pipetteId="some id")
+ position = Point(x=1, y=2, z=3)
decoy.when(await pipetting.prepare_for_aspirate(pipette_id="some id")).then_return(
None
)
+ decoy.when(await gantry_mover.get_position("some id")).then_return(position)
result = await subject.execute(data)
assert result == SuccessData(
From 2f016e09eed4ff9db605e518d37b554e024be980 Mon Sep 17 00:00:00 2001
From: Josh McVey
Date: Thu, 14 Nov 2024 09:09:00 -0500
Subject: [PATCH 03/31] feat(ai-server): integrate google sheets and update
deployment (#16808)
---
opentrons-ai-server/Makefile | 13 +-
opentrons-ai-server/Pipfile | 3 +
opentrons-ai-server/Pipfile.lock | 2329 +++++++++--------
opentrons-ai-server/README.md | 54 +
opentrons-ai-server/api/handler/fast.py | 69 +-
opentrons-ai-server/api/integration/auth.py | 12 +-
.../api/integration/google_sheets.py | 75 +
.../api/models/error_response.py | 5 +
.../api/models/feedback_request.py | 15 +
opentrons-ai-server/api/models/user.py | 16 +
opentrons-ai-server/api/settings.py | 4 +
opentrons-ai-server/deploy.py | 120 +-
opentrons-ai-server/tests/helpers/client.py | 15 +-
.../tests/test_google_sheets_sanatize.py | 23 +
opentrons-ai-server/tests/test_live.py | 31 +-
15 files changed, 1566 insertions(+), 1218 deletions(-)
create mode 100644 opentrons-ai-server/api/integration/google_sheets.py
create mode 100644 opentrons-ai-server/api/models/error_response.py
create mode 100644 opentrons-ai-server/api/models/feedback_request.py
create mode 100644 opentrons-ai-server/api/models/user.py
create mode 100644 opentrons-ai-server/tests/test_google_sheets_sanatize.py
diff --git a/opentrons-ai-server/Makefile b/opentrons-ai-server/Makefile
index ecc643d9cd0..2bc7170e931 100644
--- a/opentrons-ai-server/Makefile
+++ b/opentrons-ai-server/Makefile
@@ -75,6 +75,12 @@ deploy: gen-requirements
@echo "Deploying to environment: $(ENV)"
python -m pipenv run python deploy.py --env $(ENV) $(if $(TAG),--tag $(TAG),)
+.PHONY: dry-deploy
+dry-deploy: gen-requirements
+ @echo "Dry run deploying to environment: $(ENV)"
+ @echo "Data is retrieved from AWS but no changes are made"
+ python -m pipenv run python deploy.py --dry --env $(ENV) $(if $(TAG),--tag $(TAG),)
+
.PHONY: prompted-deploy
prompted-deploy: gen-requirements
python -m pipenv run python deploy.py
@@ -132,4 +138,9 @@ run-shell:
.PHONY: shell
shell:
- docker exec -it $(CONTAINER_NAME) /bin/bash]
+ docker exec -it $(CONTAINER_NAME) /bin/bash
+
+.PHONY: test-googlesheet
+test-googlesheet:
+ @echo "Loading environment variables from .env and running test-googlesheet"
+ pipenv run python -m api.integration.google_sheets
diff --git a/opentrons-ai-server/Pipfile b/opentrons-ai-server/Pipfile
index 34b0b8d32dd..4586798349a 100644
--- a/opentrons-ai-server/Pipfile
+++ b/opentrons-ai-server/Pipfile
@@ -17,6 +17,9 @@ beautifulsoup4 = "==4.12.3"
markdownify = "==0.13.1"
structlog = "==24.4.0"
asgi-correlation-id = "==4.3.3"
+gspread = "==6.1.4"
+google-auth = "==2.36.0"
+google-auth-oauthlib = "==1.2.1"
[dev-packages]
docker = "==7.1.0"
diff --git a/opentrons-ai-server/Pipfile.lock b/opentrons-ai-server/Pipfile.lock
index 55811db04cf..a4b9ba0dca5 100644
--- a/opentrons-ai-server/Pipfile.lock
+++ b/opentrons-ai-server/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "20b9e324d809f68cb0465d5e3d98467ceb5860f583fddc347ade1e5ad6a3b6ab"
+ "sha256": "56aef120fbddf42f146e054b7d59ee0f59be75aa6e43f332f86b7ba8fa2499e0"
},
"pipfile-spec": 6,
"requires": {
@@ -26,100 +26,85 @@
},
"aiohttp": {
"hashes": [
- "sha256:02d1d6610588bcd743fae827bd6f2e47e0d09b346f230824b4c6fb85c6065f9c",
- "sha256:03690541e4cc866eef79626cfa1ef4dd729c5c1408600c8cb9e12e1137eed6ab",
- "sha256:0bc059ecbce835630e635879f5f480a742e130d9821fbe3d2f76610a6698ee25",
- "sha256:0c21c82df33b264216abffff9f8370f303dab65d8eee3767efbbd2734363f677",
- "sha256:1298b854fd31d0567cbb916091be9d3278168064fca88e70b8468875ef9ff7e7",
- "sha256:1321658f12b6caffafdc35cfba6c882cb014af86bef4e78c125e7e794dfb927b",
- "sha256:143b0026a9dab07a05ad2dd9e46aa859bffdd6348ddc5967b42161168c24f857",
- "sha256:16e6a51d8bc96b77f04a6764b4ad03eeef43baa32014fce71e882bd71302c7e4",
- "sha256:172ad884bb61ad31ed7beed8be776eb17e7fb423f1c1be836d5cb357a096bf12",
- "sha256:17c272cfe7b07a5bb0c6ad3f234e0c336fb53f3bf17840f66bd77b5815ab3d16",
- "sha256:1a0ee6c0d590c917f1b9629371fce5f3d3f22c317aa96fbdcce3260754d7ea21",
- "sha256:2746d8994ebca1bdc55a1e998feff4e94222da709623bb18f6e5cfec8ec01baf",
- "sha256:2914caa46054f3b5ff910468d686742ff8cff54b8a67319d75f5d5945fd0a13d",
- "sha256:2bbf94d4a0447705b7775417ca8bb8086cc5482023a6e17cdc8f96d0b1b5aba6",
- "sha256:2bd9f3eac515c16c4360a6a00c38119333901b8590fe93c3257a9b536026594d",
- "sha256:2c33fa6e10bb7ed262e3ff03cc69d52869514f16558db0626a7c5c61dde3c29f",
- "sha256:2d37f4718002863b82c6f391c8efd4d3a817da37030a29e2682a94d2716209de",
- "sha256:3668d0c2a4d23fb136a753eba42caa2c0abbd3d9c5c87ee150a716a16c6deec1",
- "sha256:36d4fba838be5f083f5490ddd281813b44d69685db910907636bc5dca6322316",
- "sha256:40ff5b7660f903dc587ed36ef08a88d46840182d9d4b5694e7607877ced698a1",
- "sha256:42775de0ca04f90c10c5c46291535ec08e9bcc4756f1b48f02a0657febe89b10",
- "sha256:482c85cf3d429844396d939b22bc2a03849cb9ad33344689ad1c85697bcba33a",
- "sha256:4e6cb75f8ddd9c2132d00bc03c9716add57f4beff1263463724f6398b813e7eb",
- "sha256:4edc3fd701e2b9a0d605a7b23d3de4ad23137d23fc0dbab726aa71d92f11aaaf",
- "sha256:4fd16b30567c5b8e167923be6e027eeae0f20cf2b8a26b98a25115f28ad48ee0",
- "sha256:5002a02c17fcfd796d20bac719981d2fca9c006aac0797eb8f430a58e9d12431",
- "sha256:51d0a4901b27272ae54e42067bc4b9a90e619a690b4dc43ea5950eb3070afc32",
- "sha256:558b3d223fd631ad134d89adea876e7fdb4c93c849ef195049c063ada82b7d08",
- "sha256:5c070430fda1a550a1c3a4c2d7281d3b8cfc0c6715f616e40e3332201a253067",
- "sha256:5f392ef50e22c31fa49b5a46af7f983fa3f118f3eccb8522063bee8bfa6755f8",
- "sha256:60555211a006d26e1a389222e3fab8cd379f28e0fbf7472ee55b16c6c529e3a6",
- "sha256:608cecd8d58d285bfd52dbca5b6251ca8d6ea567022c8a0eaae03c2589cd9af9",
- "sha256:60ad5b8a7452c0f5645c73d4dad7490afd6119d453d302cd5b72b678a85d6044",
- "sha256:63649309da83277f06a15bbdc2a54fbe75efb92caa2c25bb57ca37762789c746",
- "sha256:6ebdc3b3714afe1b134b3bbeb5f745eed3ecbcff92ab25d80e4ef299e83a5465",
- "sha256:6f3c6648aa123bcd73d6f26607d59967b607b0da8ffcc27d418a4b59f4c98c7c",
- "sha256:7003f33f5f7da1eb02f0446b0f8d2ccf57d253ca6c2e7a5732d25889da82b517",
- "sha256:776e9f3c9b377fcf097c4a04b241b15691e6662d850168642ff976780609303c",
- "sha256:85711eec2d875cd88c7eb40e734c4ca6d9ae477d6f26bd2b5bb4f7f60e41b156",
- "sha256:87d1e4185c5d7187684d41ebb50c9aeaaaa06ca1875f4c57593071b0409d2444",
- "sha256:8a3f063b41cc06e8d0b3fcbbfc9c05b7420f41287e0cd4f75ce0a1f3d80729e6",
- "sha256:8b3fb28a9ac8f2558760d8e637dbf27aef1e8b7f1d221e8669a1074d1a266bb2",
- "sha256:8bd9125dd0cc8ebd84bff2be64b10fdba7dc6fd7be431b5eaf67723557de3a31",
- "sha256:8be1a65487bdfc285bd5e9baf3208c2132ca92a9b4020e9f27df1b16fab998a9",
- "sha256:8cc0d13b4e3b1362d424ce3f4e8c79e1f7247a00d792823ffd640878abf28e56",
- "sha256:8d9d10d10ec27c0d46ddaecc3c5598c4db9ce4e6398ca872cdde0525765caa2f",
- "sha256:8debb45545ad95b58cc16c3c1cc19ad82cffcb106db12b437885dbee265f0ab5",
- "sha256:91aa966858593f64c8a65cdefa3d6dc8fe3c2768b159da84c1ddbbb2c01ab4ef",
- "sha256:9331dd34145ff105177855017920dde140b447049cd62bb589de320fd6ddd582",
- "sha256:99f9678bf0e2b1b695e8028fedac24ab6770937932eda695815d5a6618c37e04",
- "sha256:9fdf5c839bf95fc67be5794c780419edb0dbef776edcfc6c2e5e2ffd5ee755fa",
- "sha256:a14e4b672c257a6b94fe934ee62666bacbc8e45b7876f9dd9502d0f0fe69db16",
- "sha256:a19caae0d670771ea7854ca30df76f676eb47e0fd9b2ee4392d44708f272122d",
- "sha256:a35ed3d03910785f7d9d6f5381f0c24002b2b888b298e6f941b2fc94c5055fcd",
- "sha256:a61df62966ce6507aafab24e124e0c3a1cfbe23c59732987fc0fd0d71daa0b88",
- "sha256:a6e00c8a92e7663ed2be6fcc08a2997ff06ce73c8080cd0df10cc0321a3168d7",
- "sha256:ac3196952c673822ebed8871cf8802e17254fff2a2ed4835d9c045d9b88c5ec7",
- "sha256:ac74e794e3aee92ae8f571bfeaa103a141e409863a100ab63a253b1c53b707eb",
- "sha256:ad3675c126f2a95bde637d162f8231cff6bc0bc9fbe31bd78075f9ff7921e322",
- "sha256:aeebd3061f6f1747c011e1d0b0b5f04f9f54ad1a2ca183e687e7277bef2e0da2",
- "sha256:ba1a599255ad6a41022e261e31bc2f6f9355a419575b391f9655c4d9e5df5ff5",
- "sha256:bbdb8def5268f3f9cd753a265756f49228a20ed14a480d151df727808b4531dd",
- "sha256:c2555e4949c8d8782f18ef20e9d39730d2656e218a6f1a21a4c4c0b56546a02e",
- "sha256:c2695c61cf53a5d4345a43d689f37fc0f6d3a2dc520660aec27ec0f06288d1f9",
- "sha256:c2b627d3c8982691b06d89d31093cee158c30629fdfebe705a91814d49b554f8",
- "sha256:c46131c6112b534b178d4e002abe450a0a29840b61413ac25243f1291613806a",
- "sha256:c54dc329cd44f7f7883a9f4baaefe686e8b9662e2c6c184ea15cceee587d8d69",
- "sha256:c7d7cafc11d70fdd8801abfc2ff276744ae4cb39d8060b6b542c7e44e5f2cfc2",
- "sha256:cb0b2d5d51f96b6cc19e6ab46a7b684be23240426ae951dcdac9639ab111b45e",
- "sha256:d15a29424e96fad56dc2f3abed10a89c50c099f97d2416520c7a543e8fddf066",
- "sha256:d1f5c9169e26db6a61276008582d945405b8316aae2bb198220466e68114a0f5",
- "sha256:d271f770b52e32236d945911b2082f9318e90ff835d45224fa9e28374303f729",
- "sha256:d646fdd74c25bbdd4a055414f0fe32896c400f38ffbdfc78c68e62812a9e0257",
- "sha256:d6e395c3d1f773cf0651cd3559e25182eb0c03a2777b53b4575d8adc1149c6e9",
- "sha256:d7c071235a47d407b0e93aa6262b49422dbe48d7d8566e1158fecc91043dd948",
- "sha256:d97273a52d7f89a75b11ec386f786d3da7723d7efae3034b4dda79f6f093edc1",
- "sha256:dcf354661f54e6a49193d0b5653a1b011ba856e0b7a76bda2c33e4c6892f34ea",
- "sha256:e3e7fabedb3fe06933f47f1538df7b3a8d78e13d7167195f51ca47ee12690373",
- "sha256:e525b69ee8a92c146ae5b4da9ecd15e518df4d40003b01b454ad694a27f498b5",
- "sha256:e709d6ac598c5416f879bb1bae3fd751366120ac3fa235a01de763537385d036",
- "sha256:e83dfefb4f7d285c2d6a07a22268344a97d61579b3e0dce482a5be0251d672ab",
- "sha256:e86260b76786c28acf0b5fe31c8dca4c2add95098c709b11e8c35b424ebd4f5b",
- "sha256:e883b61b75ca6efc2541fcd52a5c8ccfe288b24d97e20ac08fdf343b8ac672ea",
- "sha256:f0a44bb40b6aaa4fb9a5c1ee07880570ecda2065433a96ccff409c9c20c1624a",
- "sha256:f82ace0ec57c94aaf5b0e118d4366cff5889097412c75aa14b4fd5fc0c44ee3e",
- "sha256:f9ca09414003c0e96a735daa1f071f7d7ed06962ef4fa29ceb6c80d06696d900",
- "sha256:fa430b871220dc62572cef9c69b41e0d70fcb9d486a4a207a5de4c1f25d82593",
- "sha256:fc262c3df78c8ff6020c782d9ce02e4bcffe4900ad71c0ecdad59943cba54442",
- "sha256:fcd546782d03181b0b1d20b43d612429a90a68779659ba8045114b867971ab71",
- "sha256:fd4ceeae2fb8cabdd1b71c82bfdd39662473d3433ec95b962200e9e752fb70d0",
- "sha256:fec5fac7aea6c060f317f07494961236434928e6f4374e170ef50b3001e14581"
- ],
- "markers": "python_version >= '3.8'",
- "version": "==3.10.9"
+ "sha256:024409c1b1d6076d0ed933dcebd7e4fc6f3320a227bfa0c1b6b93a8b5a146f04",
+ "sha256:04b24497b3baf15035730de5f207ade88a67d4483a5f16ced7ece348933a5b47",
+ "sha256:08474e71772a516ba2e2167b4707af8361d2c452b3d8a5364c984f4867869499",
+ "sha256:0e7a0762cc29cd3acd01a4d2b547b3af7956ad230ebb80b529a8e4f3e4740fe8",
+ "sha256:104deb7873681273c5daa13c41924693df394043a118dae90387d35bc5531788",
+ "sha256:104ea21994b1403e4c1b398866f1187c1694fa291314ad7216ec1d8ec6b49f38",
+ "sha256:113bf06b029143e94a47c4f36e11a8b7e396e9d1f1fc8cea58e6b7e370cfed38",
+ "sha256:12071dd2cc95ba81e0f2737bebcb98b2a8656015e87772e84e8fb9e635b5da6e",
+ "sha256:170fb2324826bb9f08055a8291f42192ae5ee2f25b2966c8f0f4537c61d73a7b",
+ "sha256:21b4545e8d96870da9652930c5198366605ff8f982757030e2148cf341e5746b",
+ "sha256:229ae13959a5f499d90ffbb4b9eac2255d8599315027d6f7c22fa9803a94d5b1",
+ "sha256:2ec5efbc872b00ddd85e3904059d274f284cff314e13f48776050ca2c58f451d",
+ "sha256:31b91ff3a1fcb206a1fa76e0de1f08c9ffb1dc0deb7296fa2618adfe380fc676",
+ "sha256:329f5059e0bf6983dceebac8e6ed20e75eaff6163b3414f4a4cb59e0d7037672",
+ "sha256:37f8cf3c43f292d9bb3e6760476c2b55b9663a581fad682a586a410c43a7683e",
+ "sha256:3e1ed8d152cccceffb1ee7a2ac227c16372e453fb11b3aeaa56783049b85d3f6",
+ "sha256:3ed360d6672a9423aad39902a4e9fe305464d20ed7931dbdba30a4625782d875",
+ "sha256:40dc9446cff326672fcbf93efdb8ef7e949824de1097624efe4f61ac7f0d2c43",
+ "sha256:4d218d3eca40196384ad3b481309c56fd60e664128885d1734da0a8aa530d433",
+ "sha256:4e4e155968040e32c124a89852a1a5426d0e920a35f4331e1b3949037bfe93a3",
+ "sha256:4f698aa61879df64425191d41213dfd99efdc1627e6398e6d7aa5c312fac9702",
+ "sha256:508cfcc99534b1282595357592d8367b44392b21f6eb5d4dc021f8d0d809e94d",
+ "sha256:577c7429f8869fa30186fc2c9eee64d75a30b51b61f26aac9725866ae5985cfd",
+ "sha256:57e17c6d71f2dc857a8a1d09be1be7802e35d90fb4ba4b06cf1aab6414a57894",
+ "sha256:5ecc2fb1a0a9d48cf773add34196cddf7e488e48e9596e090849751bf43098f4",
+ "sha256:600b1d9f86a130131915e2f2127664311b33902c486b21a747d626f5144b4471",
+ "sha256:62502b8ffee8c6a4b5c6bf99d1de277d42bf51b2fb713975d9b63b560150b7ac",
+ "sha256:62a2f5268b672087c45b33479ba1bb1d5a48c6d76c133cfce3a4f77410c200d1",
+ "sha256:6362f50a6f0e5482c4330d2151cb682779230683da0e155c15ec9fc58cb50b6a",
+ "sha256:6533dd06df3d17d1756829b68b365b1583929b54082db8f65083a4184bf68322",
+ "sha256:6c5a6958f4366496004cf503d847093d464814543f157ef3b738bbf604232415",
+ "sha256:72cd984f7f14e8c01b3e38f18f39ea85dba84e52ea05e37116ba5e2a72eef396",
+ "sha256:76d6ee8bb132f8ee0fcb0e205b4708ddb6fba524eb515ee168113063d825131b",
+ "sha256:7867d0808614f04e78e0a8d5a2c1f8ac6bc626a0c0e2f62be48be6b749e2f8b2",
+ "sha256:7d664e5f937c08adb7908ea9f391fbf2928a9b09cb412ac0aba602bde9e499e4",
+ "sha256:85ae6f182be72c3531915e90625cc65afce4df8a0fc4988bd52d8a5d5faaeb68",
+ "sha256:89a96a0696dc67d548f69cb518c581a7a33cc1f26ab42229dea1709217c9d926",
+ "sha256:8b323b5d3aef7dd811424c269322eec58a977c0c8152e650159e47210d900504",
+ "sha256:8c47a0ba6c2b3d3e5715f8338d657badd21f778c6be16701922c65521c5ecfc9",
+ "sha256:8fef105113d56e817cb9bcc609667ee461321413a7b972b03f5b4939f40f307c",
+ "sha256:900ff74d78eb580ae4aa5883242893b123a0c442a46570902500f08d6a7e6696",
+ "sha256:9095580806d9ed07c0c29b23364a0b1fb78258ef9f4bddf7e55bac0e475d4edf",
+ "sha256:91d3991fad8b65e5dbc13cd95669ea689fe0a96ff63e4e64ac24ed724e4f8103",
+ "sha256:9231d610754724273a6ac05a1f177979490bfa6f84d49646df3928af2e88cfd5",
+ "sha256:97056d3422594e0787733ac4c45bef58722d452f4dc6615fee42f59fe51707dd",
+ "sha256:a896059b6937d1a22d8ee8377cdcd097bd26cd8c653b8f972051488b9baadee9",
+ "sha256:aabc4e92cb153636d6be54e84dad1b252ddb9aebe077942b6dcffe5e468d476a",
+ "sha256:ad14cdc0fba4df31c0f6e06c21928c5b924725cbf60d0ccc5f6e7132636250e9",
+ "sha256:ae36ae52b0c22fb69fb8b744eff82a20db512a29eafc6e3a4ab43b17215b219d",
+ "sha256:b3e4fb7f5354d39490d8209aefdf5830b208d01c7293a2164e404312c3d8bc55",
+ "sha256:b40c304ab01e89ad0aeeecf91bbaa6ae3b00e27b796c9e8d50b71a4a7e885cc8",
+ "sha256:b7349205bb163318dcc102329d30be59a647a3d24c82c3d91ed35b7e7301ea7e",
+ "sha256:b8b95a63a8e8b5f0464bd8b1b0d59d2bec98a59b6aacc71e9be23df6989b3dfb",
+ "sha256:bb2e82e515e268b965424ecabebd91834a41b36260b6ef5db015ee12ddb28ef3",
+ "sha256:c0315978b2a4569e03fb59100f6a7e7d23f718a4521491f5c13d946d37549f3d",
+ "sha256:c1828e10c3a49e2b234b87600ecb68a92b8a8dcf8b99bca9447f16c4baaa1630",
+ "sha256:c1c49bc393d854d4421ebc174a0a41f9261f50d3694d8ca277146cbbcfd24ee7",
+ "sha256:c415b9601ff50709d6050c8a9281733a9b042b9e589265ac40305b875cf9c463",
+ "sha256:c54c635d1f52490cde7ef3a423645167a8284e452a35405d5c7dc1242a8e75c9",
+ "sha256:c5e6a1f8b0268ffa1c84d7c3558724956002ba8361176e76406233e704bbcffb",
+ "sha256:c98a596ac20e8980cc6f34c0c92a113e98eb08f3997c150064d26d2aeb043e5a",
+ "sha256:cd0834e4260eab78671b81d34f110fbaac449563e48d419cec0030d9a8e58693",
+ "sha256:cdad66685fcf2ad14ce522cf849d4a025f4fd206d6cfc3f403d9873e4c243b03",
+ "sha256:d1ea006426edf7e1299c52a58b0443158012f7a56fed3515164b60bfcb1503a9",
+ "sha256:d33b4490026968bdc7f0729b9d87a3a6b1e09043557d2fc1c605c6072deb2f11",
+ "sha256:d5cae4cd271e20b7ab757e966cc919186b9f02535418ab36c471a5377ef4deaa",
+ "sha256:dd505a1121ad5b666191840b7bd1d8cb917df2647deeca6f3474331b72452362",
+ "sha256:e1668ef2f3a7ec9881f4b6a917e5f97c87a343fa6b0d5fc826b7b0297ddd0887",
+ "sha256:e7bcfcede95531589295f56e924702cef7f9685c9e4e5407592e04ded6a65bf3",
+ "sha256:ebf610c37df4f09c71c9bbf8309b4b459107e6fe889ac0d7e16f6e4ebd975f86",
+ "sha256:f3bf5c132eb48002bcc3825702d241d35b4e9585009e65e9dcf9c4635d0b7424",
+ "sha256:f40380c96dd407dfa84eb2d264e68aa47717b53bdbe210a59cc3c35a4635f195",
+ "sha256:f57a0de48dda792629e7952d34a0c7b81ea336bb9b721391c7c58145b237fe55",
+ "sha256:f6b925c7775ab857bdc1e52e1f5abcae7d18751c09b751aeb641a5276d9b990e",
+ "sha256:f8f0d79b923070f25674e4ea8f3d61c9d89d24d9598d50ff32c5b9b23c79a25b",
+ "sha256:feca9fafa4385aea6759c171cd25ea82f7375312fca04178dae35331be45e538"
+ ],
+ "markers": "python_version >= '3.9'",
+ "version": "==3.11.0"
},
"aiosignal": {
"hashes": [
@@ -139,11 +124,11 @@
},
"anyio": {
"hashes": [
- "sha256:137b4559cbb034c477165047febb6ff83f390fc3b20bf181c1fc0a728cb8beeb",
- "sha256:c7d2e9d63e31599eeb636c8c5c03a7e108d73b345f064f1c19fdc87b79036a9a"
+ "sha256:4c8bc31ccdb51c7f7bd251f51c609e038d63e34219b44aa86e47576389880b4c",
+ "sha256:6d170c36fba3bdd840c73d3868c1e777e33676a69c3a72cf0a0d5d6d8009b61d"
],
"markers": "python_version >= '3.9'",
- "version": "==4.6.0"
+ "version": "==4.6.2.post1"
},
"asgi-correlation-id": {
"hashes": [
@@ -173,11 +158,19 @@
},
"bytecode": {
"hashes": [
- "sha256:0a1dc340cac823cff605609b8b214f7f9bf80418c6b9e0fc8c6db1793c27137d",
- "sha256:7263239a8d3f70fc7c303862b20cd2c6788052e37ce0a26e67309d280e985984"
+ "sha256:06676a3c3bccc9d3dc73ee625650ea57df2bc117358826f4f290f0e1faa42292",
+ "sha256:76080b7c0eb9e7e17f961d61fd06e933aa47f3b753770a3249537439d8203a25"
],
"markers": "python_version >= '3.12'",
- "version": "==0.15.1"
+ "version": "==0.16.0"
+ },
+ "cachetools": {
+ "hashes": [
+ "sha256:02134e8439cdc2ffb62023ce1debca2944c3f289d66bb17ead3ab3dede74b292",
+ "sha256:2cc24fb4cbe39633fb7badd9db9ca6295d766d9c2995f245725a46715d050f2a"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==5.5.0"
},
"cattrs": {
"hashes": [
@@ -270,99 +263,114 @@
},
"charset-normalizer": {
"hashes": [
- "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027",
- "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087",
- "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786",
- "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8",
- "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09",
- "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185",
- "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574",
- "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e",
- "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519",
- "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898",
- "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269",
- "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3",
- "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f",
- "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6",
- "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8",
- "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a",
- "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73",
- "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc",
- "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714",
- "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2",
- "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc",
- "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce",
- "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d",
- "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e",
- "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6",
- "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269",
- "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96",
- "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d",
- "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a",
- "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4",
- "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77",
- "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d",
- "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0",
- "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed",
- "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068",
- "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac",
- "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25",
- "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8",
- "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab",
- "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26",
- "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2",
- "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db",
- "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f",
- "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5",
- "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99",
- "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c",
- "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d",
- "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811",
- "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa",
- "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a",
- "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03",
- "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b",
- "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04",
- "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c",
- "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001",
- "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458",
- "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389",
- "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99",
- "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985",
- "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537",
- "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238",
- "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f",
- "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d",
- "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796",
- "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a",
- "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143",
- "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8",
- "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c",
- "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5",
- "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5",
- "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711",
- "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4",
- "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6",
- "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c",
- "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7",
- "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4",
- "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b",
- "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae",
- "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12",
- "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c",
- "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae",
- "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8",
- "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887",
- "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b",
- "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4",
- "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f",
- "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5",
- "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33",
- "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519",
- "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"
+ "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621",
+ "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6",
+ "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8",
+ "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912",
+ "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c",
+ "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b",
+ "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d",
+ "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d",
+ "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95",
+ "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e",
+ "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565",
+ "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64",
+ "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab",
+ "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be",
+ "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e",
+ "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907",
+ "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0",
+ "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2",
+ "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62",
+ "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62",
+ "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23",
+ "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc",
+ "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284",
+ "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca",
+ "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455",
+ "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858",
+ "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b",
+ "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594",
+ "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc",
+ "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db",
+ "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b",
+ "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea",
+ "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6",
+ "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920",
+ "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749",
+ "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7",
+ "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd",
+ "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99",
+ "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242",
+ "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee",
+ "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129",
+ "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2",
+ "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51",
+ "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee",
+ "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8",
+ "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b",
+ "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613",
+ "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742",
+ "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe",
+ "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3",
+ "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5",
+ "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631",
+ "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7",
+ "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15",
+ "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c",
+ "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea",
+ "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417",
+ "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250",
+ "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88",
+ "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca",
+ "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa",
+ "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99",
+ "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149",
+ "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41",
+ "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574",
+ "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0",
+ "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f",
+ "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d",
+ "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654",
+ "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3",
+ "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19",
+ "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90",
+ "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578",
+ "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9",
+ "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1",
+ "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51",
+ "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719",
+ "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236",
+ "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a",
+ "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c",
+ "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade",
+ "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944",
+ "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc",
+ "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6",
+ "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6",
+ "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27",
+ "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6",
+ "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2",
+ "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12",
+ "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf",
+ "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114",
+ "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7",
+ "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf",
+ "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d",
+ "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b",
+ "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed",
+ "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03",
+ "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4",
+ "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67",
+ "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365",
+ "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a",
+ "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748",
+ "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b",
+ "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079",
+ "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"
],
"markers": "python_full_version >= '3.7.0'",
- "version": "==3.3.2"
+ "version": "==3.4.0"
},
"click": {
"hashes": [
@@ -374,35 +382,35 @@
},
"cryptography": {
"hashes": [
- "sha256:014f58110f53237ace6a408b5beb6c427b64e084eb451ef25a28308270086494",
- "sha256:1bbcce1a551e262dfbafb6e6252f1ae36a248e615ca44ba302df077a846a8806",
- "sha256:203e92a75716d8cfb491dc47c79e17d0d9207ccffcbcb35f598fbe463ae3444d",
- "sha256:27e613d7077ac613e399270253259d9d53872aaf657471473ebfc9a52935c062",
- "sha256:2bd51274dcd59f09dd952afb696bf9c61a7a49dfc764c04dd33ef7a6b502a1e2",
- "sha256:38926c50cff6f533f8a2dae3d7f19541432610d114a70808f0926d5aaa7121e4",
- "sha256:511f4273808ab590912a93ddb4e3914dfd8a388fed883361b02dea3791f292e1",
- "sha256:58d4e9129985185a06d849aa6df265bdd5a74ca6e1b736a77959b498e0505b85",
- "sha256:5b43d1ea6b378b54a1dc99dd8a2b5be47658fe9a7ce0a58ff0b55f4b43ef2b84",
- "sha256:61ec41068b7b74268fa86e3e9e12b9f0c21fcf65434571dbb13d954bceb08042",
- "sha256:666ae11966643886c2987b3b721899d250855718d6d9ce41b521252a17985f4d",
- "sha256:68aaecc4178e90719e95298515979814bda0cbada1256a4485414860bd7ab962",
- "sha256:7c05650fe8023c5ed0d46793d4b7d7e6cd9c04e68eabe5b0aeea836e37bdcec2",
- "sha256:80eda8b3e173f0f247f711eef62be51b599b5d425c429b5d4ca6a05e9e856baa",
- "sha256:8385d98f6a3bf8bb2d65a73e17ed87a3ba84f6991c155691c51112075f9ffc5d",
- "sha256:88cce104c36870d70c49c7c8fd22885875d950d9ee6ab54df2745f83ba0dc365",
- "sha256:9d3cdb25fa98afdd3d0892d132b8d7139e2c087da1712041f6b762e4f807cc96",
- "sha256:a575913fb06e05e6b4b814d7f7468c2c660e8bb16d8d5a1faf9b33ccc569dd47",
- "sha256:ac119bb76b9faa00f48128b7f5679e1d8d437365c5d26f1c2c3f0da4ce1b553d",
- "sha256:c1332724be35d23a854994ff0b66530119500b6053d0bd3363265f7e5e77288d",
- "sha256:d03a475165f3134f773d1388aeb19c2d25ba88b6a9733c5c590b9ff7bbfa2e0c",
- "sha256:d75601ad10b059ec832e78823b348bfa1a59f6b8d545db3a24fd44362a1564cb",
- "sha256:de41fd81a41e53267cb020bb3a7212861da53a7d39f863585d13ea11049cf277",
- "sha256:e710bf40870f4db63c3d7d929aa9e09e4e7ee219e703f949ec4073b4294f6172",
- "sha256:ea25acb556320250756e53f9e20a4177515f012c9eaea17eb7587a8c4d8ae034",
- "sha256:f98bf604c82c416bc829e490c700ca1553eafdf2912a91e23a79d97d9801372a",
- "sha256:fba1007b3ef89946dbbb515aeeb41e30203b004f0b4b00e5e16078b518563289"
- ],
- "version": "==43.0.1"
+ "sha256:0c580952eef9bf68c4747774cde7ec1d85a6e61de97281f2dba83c7d2c806362",
+ "sha256:0f996e7268af62598f2fc1204afa98a3b5712313a55c4c9d434aef49cadc91d4",
+ "sha256:1ec0bcf7e17c0c5669d881b1cd38c4972fade441b27bda1051665faaa89bdcaa",
+ "sha256:281c945d0e28c92ca5e5930664c1cefd85efe80e5c0d2bc58dd63383fda29f83",
+ "sha256:2ce6fae5bdad59577b44e4dfed356944fbf1d925269114c28be377692643b4ff",
+ "sha256:315b9001266a492a6ff443b61238f956b214dbec9910a081ba5b6646a055a805",
+ "sha256:443c4a81bb10daed9a8f334365fe52542771f25aedaf889fd323a853ce7377d6",
+ "sha256:4a02ded6cd4f0a5562a8887df8b3bd14e822a90f97ac5e544c162899bc467664",
+ "sha256:53a583b6637ab4c4e3591a15bc9db855b8d9dee9a669b550f311480acab6eb08",
+ "sha256:63efa177ff54aec6e1c0aefaa1a241232dcd37413835a9b674b6e3f0ae2bfd3e",
+ "sha256:74f57f24754fe349223792466a709f8e0c093205ff0dca557af51072ff47ab18",
+ "sha256:7e1ce50266f4f70bf41a2c6dc4358afadae90e2a1e5342d3c08883df1675374f",
+ "sha256:81ef806b1fef6b06dcebad789f988d3b37ccaee225695cf3e07648eee0fc6b73",
+ "sha256:846da004a5804145a5f441b8530b4bf35afbf7da70f82409f151695b127213d5",
+ "sha256:8ac43ae87929a5982f5948ceda07001ee5e83227fd69cf55b109144938d96984",
+ "sha256:9762ea51a8fc2a88b70cf2995e5675b38d93bf36bd67d91721c309df184f49bd",
+ "sha256:a2a431ee15799d6db9fe80c82b055bae5a752bef645bba795e8e52687c69efe3",
+ "sha256:bf7a1932ac4176486eab36a19ed4c0492da5d97123f1406cf15e41b05e787d2e",
+ "sha256:c2e6fc39c4ab499049df3bdf567f768a723a5e8464816e8f009f121a5a9f4405",
+ "sha256:cbeb489927bd7af4aa98d4b261af9a5bc025bd87f0e3547e11584be9e9427be2",
+ "sha256:d03b5621a135bffecad2c73e9f4deb1a0f977b9a8ffe6f8e002bf6c9d07b918c",
+ "sha256:d56e96520b1020449bbace2b78b603442e7e378a9b3bd68de65c782db1507995",
+ "sha256:df6b6c6d742395dd77a23ea3728ab62f98379eff8fb61be2744d4679ab678f73",
+ "sha256:e1be4655c7ef6e1bbe6b5d0403526601323420bcf414598955968c9ef3eb7d16",
+ "sha256:f18c716be16bc1fea8e95def49edf46b82fccaa88587a45f8dc0ff6ab5d8e0a7",
+ "sha256:f46304d6f0c6ab8e52770addfa2fc41e6629495548862279641972b6215451cd",
+ "sha256:f7b178f11ed3664fd0e995a47ed2b5ff0a12d893e41dd0494f406d1cf555cab7"
+ ],
+ "version": "==43.0.3"
},
"dataclasses-json": {
"hashes": [
@@ -528,11 +536,11 @@
},
"envier": {
"hashes": [
- "sha256:4e7e398cb09a8dd360508ef7e12511a152355426d2544b8487a34dad27cc20ad",
- "sha256:65099cf3aa9b3b3b4b92db2f7d29e2910672e085b76f7e587d2167561a834add"
+ "sha256:3309a01bb3d8850c9e7a31a5166d5a836846db2faecb79b9cb32654dd50ca9f9",
+ "sha256:73609040a76be48bbcb97074d9969666484aa0de706183a6e9ef773156a8a6a9"
],
"markers": "python_version >= '3.7'",
- "version": "==0.5.2"
+ "version": "==0.6.1"
},
"fastapi": {
"hashes": [
@@ -553,94 +561,127 @@
},
"frozenlist": {
"hashes": [
- "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7",
- "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98",
- "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad",
- "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5",
- "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae",
- "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e",
- "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a",
- "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701",
- "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d",
- "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6",
- "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6",
- "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106",
- "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75",
- "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868",
- "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a",
- "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0",
- "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1",
- "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826",
- "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec",
- "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6",
- "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950",
- "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19",
- "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0",
- "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8",
- "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a",
- "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09",
- "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86",
- "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c",
- "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5",
- "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b",
- "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b",
- "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d",
- "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0",
- "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea",
- "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776",
- "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a",
- "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897",
- "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7",
- "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09",
- "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9",
- "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe",
- "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd",
- "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742",
- "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09",
- "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0",
- "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932",
- "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1",
- "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a",
- "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49",
- "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d",
- "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7",
- "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480",
- "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89",
- "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e",
- "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b",
- "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82",
- "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb",
- "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068",
- "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8",
- "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b",
- "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb",
- "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2",
- "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11",
- "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b",
- "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc",
- "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0",
- "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497",
- "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17",
- "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0",
- "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2",
- "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439",
- "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5",
- "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac",
- "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825",
- "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887",
- "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced",
- "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"
- ],
- "markers": "python_version >= '3.8'",
- "version": "==1.4.1"
+ "sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e",
+ "sha256:03d33c2ddbc1816237a67f66336616416e2bbb6beb306e5f890f2eb22b959cdf",
+ "sha256:04a5c6babd5e8fb7d3c871dc8b321166b80e41b637c31a995ed844a6139942b6",
+ "sha256:0996c66760924da6e88922756d99b47512a71cfd45215f3570bf1e0b694c206a",
+ "sha256:0cc974cc93d32c42e7b0f6cf242a6bd941c57c61b618e78b6c0a96cb72788c1d",
+ "sha256:0f253985bb515ecd89629db13cb58d702035ecd8cfbca7d7a7e29a0e6d39af5f",
+ "sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28",
+ "sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b",
+ "sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9",
+ "sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2",
+ "sha256:15538c0cbf0e4fa11d1e3a71f823524b0c46299aed6e10ebb4c2089abd8c3bec",
+ "sha256:15b731db116ab3aedec558573c1a5eec78822b32292fe4f2f0345b7f697745c2",
+ "sha256:17dcc32fc7bda7ce5875435003220a457bcfa34ab7924a49a1c19f55b6ee185c",
+ "sha256:1893f948bf6681733aaccf36c5232c231e3b5166d607c5fa77773611df6dc336",
+ "sha256:189f03b53e64144f90990d29a27ec4f7997d91ed3d01b51fa39d2dbe77540fd4",
+ "sha256:1a8ea951bbb6cacd492e3948b8da8c502a3f814f5d20935aae74b5df2b19cf3d",
+ "sha256:1b96af8c582b94d381a1c1f51ffaedeb77c821c690ea5f01da3d70a487dd0a9b",
+ "sha256:1e76bfbc72353269c44e0bc2cfe171900fbf7f722ad74c9a7b638052afe6a00c",
+ "sha256:2150cc6305a2c2ab33299453e2968611dacb970d2283a14955923062c8d00b10",
+ "sha256:226d72559fa19babe2ccd920273e767c96a49b9d3d38badd7c91a0fdeda8ea08",
+ "sha256:237f6b23ee0f44066219dae14c70ae38a63f0440ce6750f868ee08775073f942",
+ "sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8",
+ "sha256:2b5e23253bb709ef57a8e95e6ae48daa9ac5f265637529e4ce6b003a37b2621f",
+ "sha256:2d0da8bbec082bf6bf18345b180958775363588678f64998c2b7609e34719b10",
+ "sha256:2f3f7a0fbc219fb4455264cae4d9f01ad41ae6ee8524500f381de64ffaa077d5",
+ "sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6",
+ "sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21",
+ "sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c",
+ "sha256:366d8f93e3edfe5a918c874702f78faac300209a4d5bf38352b2c1bdc07a766d",
+ "sha256:374ca2dabdccad8e2a76d40b1d037f5bd16824933bf7bcea3e59c891fd4a0923",
+ "sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608",
+ "sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de",
+ "sha256:498524025a5b8ba81695761d78c8dd7382ac0b052f34e66939c42df860b8ff17",
+ "sha256:50cf5e7ee9b98f22bdecbabf3800ae78ddcc26e4a435515fc72d97903e8488e0",
+ "sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f",
+ "sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641",
+ "sha256:5a3ba5f9a0dfed20337d3e966dc359784c9f96503674c2faf015f7fe8e96798c",
+ "sha256:5b6a66c18b5b9dd261ca98dffcb826a525334b2f29e7caa54e182255c5f6a65a",
+ "sha256:5c28f4b5dbef8a0d8aad0d4de24d1e9e981728628afaf4ea0792f5d0939372f0",
+ "sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9",
+ "sha256:6321899477db90bdeb9299ac3627a6a53c7399c8cd58d25da094007402b039ab",
+ "sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f",
+ "sha256:666534d15ba8f0fda3f53969117383d5dc021266b3c1a42c9ec4855e4b58b9d3",
+ "sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a",
+ "sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784",
+ "sha256:73f2e31ea8dd7df61a359b731716018c2be196e5bb3b74ddba107f694fbd7604",
+ "sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d",
+ "sha256:76e4753701248476e6286f2ef492af900ea67d9706a0155335a40ea21bf3b2f5",
+ "sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03",
+ "sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e",
+ "sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953",
+ "sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee",
+ "sha256:7f3c8c1dacd037df16e85227bac13cca58c30da836c6f936ba1df0c05d046d8d",
+ "sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817",
+ "sha256:828afae9f17e6de596825cf4228ff28fbdf6065974e5ac1410cecc22f699d2b3",
+ "sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039",
+ "sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f",
+ "sha256:90646abbc7a5d5c7c19461d2e3eeb76eb0b204919e6ece342feb6032c9325ae9",
+ "sha256:91d6c171862df0a6c61479d9724f22efb6109111017c87567cfeb7b5d1449fdf",
+ "sha256:9272fa73ca71266702c4c3e2d4a28553ea03418e591e377a03b8e3659d94fa76",
+ "sha256:92b5278ed9d50fe610185ecd23c55d8b307d75ca18e94c0e7de328089ac5dcba",
+ "sha256:97160e245ea33d8609cd2b8fd997c850b56db147a304a262abc2b3be021a9171",
+ "sha256:977701c081c0241d0955c9586ffdd9ce44f7a7795df39b9151cd9a6fd0ce4cfb",
+ "sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439",
+ "sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631",
+ "sha256:9bbcdfaf4af7ce002694a4e10a0159d5a8d20056a12b05b45cea944a4953f972",
+ "sha256:9c2623347b933fcb9095841f1cc5d4ff0b278addd743e0e966cb3d460278840d",
+ "sha256:a2fe128eb4edeabe11896cb6af88fca5346059f6c8d807e3b910069f39157869",
+ "sha256:a72b7a6e3cd2725eff67cd64c8f13335ee18fc3c7befc05aed043d24c7b9ccb9",
+ "sha256:a9fe0f1c29ba24ba6ff6abf688cb0b7cf1efab6b6aa6adc55441773c252f7411",
+ "sha256:b97f7b575ab4a8af9b7bc1d2ef7f29d3afee2226bd03ca3875c16451ad5a7723",
+ "sha256:bdac3c7d9b705d253b2ce370fde941836a5f8b3c5c2b8fd70940a3ea3af7f4f2",
+ "sha256:c03eff4a41bd4e38415cbed054bbaff4a075b093e2394b6915dca34a40d1e38b",
+ "sha256:c16d2fa63e0800723139137d667e1056bee1a1cf7965153d2d104b62855e9b99",
+ "sha256:c1fac3e2ace2eb1052e9f7c7db480818371134410e1f5c55d65e8f3ac6d1407e",
+ "sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840",
+ "sha256:cee6798eaf8b1416ef6909b06f7dc04b60755206bddc599f52232606e18179d3",
+ "sha256:d1b3eb7b05ea246510b43a7e53ed1653e55c2121019a97e60cad7efb881a97bb",
+ "sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3",
+ "sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0",
+ "sha256:dd94994fc91a6177bfaafd7d9fd951bc8689b0a98168aa26b5f543868548d3ca",
+ "sha256:de537c11e4aa01d37db0d403b57bd6f0546e71a82347a97c6a9f0dcc532b3a45",
+ "sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e",
+ "sha256:e66cc454f97053b79c2ab09c17fbe3c825ea6b4de20baf1be28919460dd7877f",
+ "sha256:e79225373c317ff1e35f210dd5f1344ff31066ba8067c307ab60254cd3a78ad5",
+ "sha256:f1577515d35ed5649d52ab4319db757bb881ce3b2b796d7283e6634d99ace307",
+ "sha256:f1e6540b7fa044eee0bb5111ada694cf3dc15f2b0347ca125ee9ca984d5e9e6e",
+ "sha256:f2ac49a9bedb996086057b75bf93538240538c6d9b38e57c82d51f75a73409d2",
+ "sha256:f47c9c9028f55a04ac254346e92977bf0f166c483c74b4232bee19a6697e4778",
+ "sha256:f5f9da7f5dbc00a604fe74aa02ae7c98bcede8a3b8b9666f9f86fc13993bc71a",
+ "sha256:fd74520371c3c4175142d02a976aee0b4cb4a7cc912a60586ffd8d5929979b30",
+ "sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a"
+ ],
+ "markers": "python_version >= '3.8'",
+ "version": "==1.5.0"
},
"fsspec": {
"hashes": [
- "sha256:4b0afb90c2f21832df142f292649035d80b421f60a9e1c027802e5a0da2b04e8",
- "sha256:a0947d552d8a6efa72cc2c730b12c41d043509156966cca4fb157b0f2a0c574b"
+ "sha256:03b9a6785766a4de40368b88906366755e2819e758b83705c88cd7cb5fe81871",
+ "sha256:eda2d8a4116d4f2429db8550f2457da57279247dd930bb12f821b58391359493"
],
"markers": "python_version >= '3.8'",
- "version": "==2024.9.0"
+ "version": "==2024.10.0"
+ },
+ "google-auth": {
+ "hashes": [
+ "sha256:51a15d47028b66fd36e5c64a82d2d57480075bccc7da37cde257fc94177a61fb",
+ "sha256:545e9618f2df0bcbb7dcbc45a546485b1212624716975a1ea5ae8149ce769ab1"
+ ],
+ "index": "pypi",
+ "markers": "python_version >= '3.7'",
+ "version": "==2.36.0"
+ },
+ "google-auth-oauthlib": {
+ "hashes": [
+ "sha256:2d58a27262d55aa1b87678c3ba7142a080098cbc2024f903c62355deb235d91f",
+ "sha256:afd0cad092a2eaa53cd8e8298557d6de1034c6cb4a740500b5357b648af97263"
+ ],
+ "index": "pypi",
+ "markers": "python_version >= '3.6'",
+ "version": "==1.2.1"
},
"greenlet": {
"hashes": [
@@ -721,6 +762,15 @@
"markers": "python_version < '3.13' and platform_machine == 'aarch64' or (platform_machine == 'ppc64le' or (platform_machine == 'x86_64' or (platform_machine == 'amd64' or (platform_machine == 'AMD64' or (platform_machine == 'win32' or platform_machine == 'WIN32')))))",
"version": "==3.1.1"
},
+ "gspread": {
+ "hashes": [
+ "sha256:b8eec27de7cadb338bb1b9f14a9be168372dee8965c0da32121816b5050ac1de",
+ "sha256:c34781c426031a243ad154952b16f21ac56a5af90687885fbee3d1fba5280dcd"
+ ],
+ "index": "pypi",
+ "markers": "python_version >= '3.8'",
+ "version": "==6.1.4"
+ },
"h11": {
"hashes": [
"sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d",
@@ -739,44 +789,51 @@
},
"httptools": {
"hashes": [
- "sha256:00d5d4b68a717765b1fabfd9ca755bd12bf44105eeb806c03d1962acd9b8e563",
- "sha256:0ac5a0ae3d9f4fe004318d64b8a854edd85ab76cffbf7ef5e32920faef62f142",
- "sha256:0cf2372e98406efb42e93bfe10f2948e467edfd792b015f1b4ecd897903d3e8d",
- "sha256:1ed99a373e327f0107cb513b61820102ee4f3675656a37a50083eda05dc9541b",
- "sha256:3c3b214ce057c54675b00108ac42bacf2ab8f85c58e3f324a4e963bbc46424f4",
- "sha256:3e802e0b2378ade99cd666b5bffb8b2a7cc8f3d28988685dc300469ea8dd86cb",
- "sha256:3f30d3ce413088a98b9db71c60a6ada2001a08945cb42dd65a9a9fe228627658",
- "sha256:405784577ba6540fa7d6ff49e37daf104e04f4b4ff2d1ac0469eaa6a20fde084",
- "sha256:48ed8129cd9a0d62cf4d1575fcf90fb37e3ff7d5654d3a5814eb3d55f36478c2",
- "sha256:4bd3e488b447046e386a30f07af05f9b38d3d368d1f7b4d8f7e10af85393db97",
- "sha256:4f0f8271c0a4db459f9dc807acd0eadd4839934a4b9b892f6f160e94da309837",
- "sha256:5cceac09f164bcba55c0500a18fe3c47df29b62353198e4f37bbcc5d591172c3",
- "sha256:639dc4f381a870c9ec860ce5c45921db50205a37cc3334e756269736ff0aac58",
- "sha256:678fcbae74477a17d103b7cae78b74800d795d702083867ce160fc202104d0da",
- "sha256:6a4f5ccead6d18ec072ac0b84420e95d27c1cdf5c9f1bc8fbd8daf86bd94f43d",
- "sha256:6f58e335a1402fb5a650e271e8c2d03cfa7cea46ae124649346d17bd30d59c90",
- "sha256:75c8022dca7935cba14741a42744eee13ba05db00b27a4b940f0d646bd4d56d0",
- "sha256:7a7ea483c1a4485c71cb5f38be9db078f8b0e8b4c4dc0210f531cdd2ddac1ef1",
- "sha256:7d9ceb2c957320def533671fc9c715a80c47025139c8d1f3797477decbc6edd2",
- "sha256:7ebaec1bf683e4bf5e9fbb49b8cc36da482033596a415b3e4ebab5a4c0d7ec5e",
- "sha256:85ed077c995e942b6f1b07583e4eb0a8d324d418954fc6af913d36db7c05a5a0",
- "sha256:8ae5b97f690badd2ca27cbf668494ee1b6d34cf1c464271ef7bfa9ca6b83ffaf",
- "sha256:8b0bb634338334385351a1600a73e558ce619af390c2b38386206ac6a27fecfc",
- "sha256:8e216a038d2d52ea13fdd9b9c9c7459fb80d78302b257828285eca1c773b99b3",
- "sha256:93ad80d7176aa5788902f207a4e79885f0576134695dfb0fefc15b7a4648d503",
- "sha256:95658c342529bba4e1d3d2b1a874db16c7cca435e8827422154c9da76ac4e13a",
- "sha256:95fb92dd3649f9cb139e9c56604cc2d7c7bf0fc2e7c8d7fbd58f96e35eddd2a3",
- "sha256:97662ce7fb196c785344d00d638fc9ad69e18ee4bfb4000b35a52efe5adcc949",
- "sha256:9bb68d3a085c2174c2477eb3ffe84ae9fb4fde8792edb7bcd09a1d8467e30a84",
- "sha256:b512aa728bc02354e5ac086ce76c3ce635b62f5fbc32ab7082b5e582d27867bb",
- "sha256:c6e26c30455600b95d94b1b836085138e82f177351454ee841c148f93a9bad5a",
- "sha256:d2f6c3c4cb1948d912538217838f6e9960bc4a521d7f9b323b3da579cd14532f",
- "sha256:dcbab042cc3ef272adc11220517278519adf8f53fd3056d0e68f0a6f891ba94e",
- "sha256:e0b281cf5a125c35f7f6722b65d8542d2e57331be573e9e88bc8b0115c4a7a81",
- "sha256:e57997ac7fb7ee43140cc03664de5f268813a481dff6245e0075925adc6aa185",
- "sha256:fe467eb086d80217b7584e61313ebadc8d187a4d95bb62031b7bab4b205c3ba3"
- ],
- "version": "==0.6.1"
+ "sha256:0614154d5454c21b6410fdf5262b4a3ddb0f53f1e1721cfd59d55f32138c578a",
+ "sha256:0e563e54979e97b6d13f1bbc05a96109923e76b901f786a5eae36e99c01237bd",
+ "sha256:16e603a3bff50db08cd578d54f07032ca1631450ceb972c2f834c2b860c28ea2",
+ "sha256:288cd628406cc53f9a541cfaf06041b4c71d751856bab45e3702191f931ccd17",
+ "sha256:28908df1b9bb8187393d5b5db91435ccc9c8e891657f9cbb42a2541b44c82fc8",
+ "sha256:322d20ea9cdd1fa98bd6a74b77e2ec5b818abdc3d36695ab402a0de8ef2865a3",
+ "sha256:342dd6946aa6bda4b8f18c734576106b8a31f2fe31492881a9a160ec84ff4bd5",
+ "sha256:345c288418f0944a6fe67be8e6afa9262b18c7626c3ef3c28adc5eabc06a68da",
+ "sha256:3c73ce323711a6ffb0d247dcd5a550b8babf0f757e86a52558fe5b86d6fefcc0",
+ "sha256:40a5ec98d3f49904b9fe36827dcf1aadfef3b89e2bd05b0e35e94f97c2b14721",
+ "sha256:40b0f7fe4fd38e6a507bdb751db0379df1e99120c65fbdc8ee6c1d044897a636",
+ "sha256:40dc6a8e399e15ea525305a2ddba998b0af5caa2566bcd79dcbe8948181eeaff",
+ "sha256:4b36913ba52008249223042dca46e69967985fb4051951f94357ea681e1f5dc0",
+ "sha256:4d87b29bd4486c0093fc64dea80231f7c7f7eb4dc70ae394d70a495ab8436071",
+ "sha256:4e93eee4add6493b59a5c514da98c939b244fce4a0d8879cd3f466562f4b7d5c",
+ "sha256:59e724f8b332319e2875efd360e61ac07f33b492889284a3e05e6d13746876f4",
+ "sha256:69422b7f458c5af875922cdb5bd586cc1f1033295aa9ff63ee196a87519ac8e1",
+ "sha256:703c346571fa50d2e9856a37d7cd9435a25e7fd15e236c397bf224afaa355fe9",
+ "sha256:85071a1e8c2d051b507161f6c3e26155b5c790e4e28d7f236422dbacc2a9cc44",
+ "sha256:856f4bc0478ae143bad54a4242fccb1f3f86a6e1be5548fecfd4102061b3a083",
+ "sha256:85797e37e8eeaa5439d33e556662cc370e474445d5fab24dcadc65a8ffb04003",
+ "sha256:90d96a385fa941283ebd231464045187a31ad932ebfa541be8edf5b3c2328959",
+ "sha256:94978a49b8f4569ad607cd4946b759d90b285e39c0d4640c6b36ca7a3ddf2efc",
+ "sha256:aafe0f1918ed07b67c1e838f950b1c1fabc683030477e60b335649b8020e1076",
+ "sha256:ab9ba8dcf59de5181f6be44a77458e45a578fc99c31510b8c65b7d5acc3cf490",
+ "sha256:ade273d7e767d5fae13fa637f4d53b6e961fb7fd93c7797562663f0171c26660",
+ "sha256:b799de31416ecc589ad79dd85a0b2657a8fe39327944998dea368c1d4c9e55e6",
+ "sha256:c26f313951f6e26147833fc923f78f95604bbec812a43e5ee37f26dc9e5a686c",
+ "sha256:ca80b7485c76f768a3bc83ea58373f8db7b015551117375e4918e2aa77ea9b50",
+ "sha256:d1ffd262a73d7c28424252381a5b854c19d9de5f56f075445d33919a637e3547",
+ "sha256:d3f0d369e7ffbe59c4b6116a44d6a8eb4783aae027f2c0b366cf0aa964185dba",
+ "sha256:d54efd20338ac52ba31e7da78e4a72570cf729fac82bc31ff9199bedf1dc7440",
+ "sha256:dacdd3d10ea1b4ca9df97a0a303cbacafc04b5cd375fa98732678151643d4988",
+ "sha256:db353d22843cf1028f43c3651581e4bb49374d85692a85f95f7b9a130e1b2cab",
+ "sha256:db78cb9ca56b59b016e64b6031eda5653be0589dba2b1b43453f6e8b405a0970",
+ "sha256:deee0e3343f98ee8047e9f4c5bc7cedbf69f5734454a94c38ee829fb2d5fa3c1",
+ "sha256:df017d6c780287d5c80601dafa31f17bddb170232d85c066604d8558683711a2",
+ "sha256:df959752a0c2748a65ab5387d08287abf6779ae9165916fe053e68ae1fbdc47f",
+ "sha256:ec4f178901fa1834d4a060320d2f3abc5c9e39766953d038f1458cb885f47e81",
+ "sha256:f47f8ed67cc0ff862b84a1189831d1d33c963fb3ce1ee0c65d3b0cbe7b711069",
+ "sha256:f8787367fbdfccae38e35abf7641dafc5310310a5987b689f4c32cc8cc3ee975",
+ "sha256:f9eb89ecf8b290f2e293325c646a211ff1c2493222798bb80a530c5e7502494f",
+ "sha256:fc411e1c0a7dcd2f902c7c48cf079947a7e65b5485dea9decb82b9105ca71a43"
+ ],
+ "version": "==0.6.4"
},
"httpx": {
"hashes": [
@@ -797,11 +854,11 @@
},
"importlib-metadata": {
"hashes": [
- "sha256:66f342cc6ac9818fc6ff340576acd24d65ba0b3efabb2b4ac08b598965a4a2f1",
- "sha256:9a547d3bc3608b025f93d403fdd1aae741c24fbb8314df4b155675742ce303c5"
+ "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b",
+ "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"
],
"markers": "python_version >= '3.8'",
- "version": "==8.4.0"
+ "version": "==8.5.0"
},
"jinja2": {
"hashes": [
@@ -878,11 +935,11 @@
},
"llama-index-legacy": {
"hashes": [
- "sha256:04221320d84d96ba9ee3e21e5055bd8527cbd769e8f1c60cf0368ed907e012a2",
- "sha256:f6969f1085efb0abebd6367e46f3512020f3f6b9c086f458a519830dd61e8206"
+ "sha256:4b817d7c343fb5f7f00c4410eff519f320013b8d5f24c4fedcf270c471f92038",
+ "sha256:f8a9764e7e134a52bfef5e53d2d62561bfc01fc09874c51cc001df6f5302ae30"
],
"markers": "python_version < '4.0' and python_full_version >= '3.8.1'",
- "version": "==0.9.48.post3"
+ "version": "==0.9.48.post4"
},
"llama-index-llms-openai": {
"hashes": [
@@ -958,78 +1015,78 @@
},
"markupsafe": {
"hashes": [
- "sha256:0778de17cff1acaeccc3ff30cd99a3fd5c50fc58ad3d6c0e0c4c58092b859396",
- "sha256:0f84af7e813784feb4d5e4ff7db633aba6c8ca64a833f61d8e4eade234ef0c38",
- "sha256:17b2aea42a7280db02ac644db1d634ad47dcc96faf38ab304fe26ba2680d359a",
- "sha256:242d6860f1fd9191aef5fae22b51c5c19767f93fb9ead4d21924e0bcb17619d8",
- "sha256:244dbe463d5fb6d7ce161301a03a6fe744dac9072328ba9fc82289238582697b",
- "sha256:26627785a54a947f6d7336ce5963569b5d75614619e75193bdb4e06e21d447ad",
- "sha256:2a4b34a8d14649315c4bc26bbfa352663eb51d146e35eef231dd739d54a5430a",
- "sha256:2ae99f31f47d849758a687102afdd05bd3d3ff7dbab0a8f1587981b58a76152a",
- "sha256:312387403cd40699ab91d50735ea7a507b788091c416dd007eac54434aee51da",
- "sha256:3341c043c37d78cc5ae6e3e305e988532b072329639007fd408a476642a89fd6",
- "sha256:33d1c36b90e570ba7785dacd1faaf091203d9942bc036118fab8110a401eb1a8",
- "sha256:3e683ee4f5d0fa2dde4db77ed8dd8a876686e3fc417655c2ece9a90576905344",
- "sha256:3ffb4a8e7d46ed96ae48805746755fadd0909fea2306f93d5d8233ba23dda12a",
- "sha256:40621d60d0e58aa573b68ac5e2d6b20d44392878e0bfc159012a5787c4e35bc8",
- "sha256:40f1e10d51c92859765522cbd79c5c8989f40f0419614bcdc5015e7b6bf97fc5",
- "sha256:45d42d132cff577c92bfba536aefcfea7e26efb975bd455db4e6602f5c9f45e7",
- "sha256:48488d999ed50ba8d38c581d67e496f955821dc183883550a6fbc7f1aefdc170",
- "sha256:4935dd7883f1d50e2ffecca0aa33dc1946a94c8f3fdafb8df5c330e48f71b132",
- "sha256:4c2d64fdba74ad16138300815cfdc6ab2f4647e23ced81f59e940d7d4a1469d9",
- "sha256:4c8817557d0de9349109acb38b9dd570b03cc5014e8aabf1cbddc6e81005becd",
- "sha256:4ffaaac913c3f7345579db4f33b0020db693f302ca5137f106060316761beea9",
- "sha256:5a4cb365cb49b750bdb60b846b0c0bc49ed62e59a76635095a179d440540c346",
- "sha256:62fada2c942702ef8952754abfc1a9f7658a4d5460fabe95ac7ec2cbe0d02abc",
- "sha256:67c519635a4f64e495c50e3107d9b4075aec33634272b5db1cde839e07367589",
- "sha256:6a54c43d3ec4cf2a39f4387ad044221c66a376e58c0d0e971d47c475ba79c6b5",
- "sha256:7044312a928a66a4c2a22644147bc61a199c1709712069a344a3fb5cfcf16915",
- "sha256:730d86af59e0e43ce277bb83970530dd223bf7f2a838e086b50affa6ec5f9295",
- "sha256:800100d45176652ded796134277ecb13640c1a537cad3b8b53da45aa96330453",
- "sha256:80fcbf3add8790caddfab6764bde258b5d09aefbe9169c183f88a7410f0f6dea",
- "sha256:82b5dba6eb1bcc29cc305a18a3c5365d2af06ee71b123216416f7e20d2a84e5b",
- "sha256:852dc840f6d7c985603e60b5deaae1d89c56cb038b577f6b5b8c808c97580f1d",
- "sha256:8ad4ad1429cd4f315f32ef263c1342166695fad76c100c5d979c45d5570ed58b",
- "sha256:8ae369e84466aa70f3154ee23c1451fda10a8ee1b63923ce76667e3077f2b0c4",
- "sha256:93e8248d650e7e9d49e8251f883eed60ecbc0e8ffd6349e18550925e31bd029b",
- "sha256:973a371a55ce9ed333a3a0f8e0bcfae9e0d637711534bcb11e130af2ab9334e7",
- "sha256:9ba25a71ebf05b9bb0e2ae99f8bc08a07ee8e98c612175087112656ca0f5c8bf",
- "sha256:a10860e00ded1dd0a65b83e717af28845bb7bd16d8ace40fe5531491de76b79f",
- "sha256:a4792d3b3a6dfafefdf8e937f14906a51bd27025a36f4b188728a73382231d91",
- "sha256:a7420ceda262dbb4b8d839a4ec63d61c261e4e77677ed7c66c99f4e7cb5030dd",
- "sha256:ad91738f14eb8da0ff82f2acd0098b6257621410dcbd4df20aaa5b4233d75a50",
- "sha256:b6a387d61fe41cdf7ea95b38e9af11cfb1a63499af2759444b99185c4ab33f5b",
- "sha256:b954093679d5750495725ea6f88409946d69cfb25ea7b4c846eef5044194f583",
- "sha256:bbde71a705f8e9e4c3e9e33db69341d040c827c7afa6789b14c6e16776074f5a",
- "sha256:beeebf760a9c1f4c07ef6a53465e8cfa776ea6a2021eda0d0417ec41043fe984",
- "sha256:c91b394f7601438ff79a4b93d16be92f216adb57d813a78be4446fe0f6bc2d8c",
- "sha256:c97ff7fedf56d86bae92fa0a646ce1a0ec7509a7578e1ed238731ba13aabcd1c",
- "sha256:cb53e2a99df28eee3b5f4fea166020d3ef9116fdc5764bc5117486e6d1211b25",
- "sha256:cbf445eb5628981a80f54087f9acdbf84f9b7d862756110d172993b9a5ae81aa",
- "sha256:d06b24c686a34c86c8c1fba923181eae6b10565e4d80bdd7bc1c8e2f11247aa4",
- "sha256:d98e66a24497637dd31ccab090b34392dddb1f2f811c4b4cd80c230205c074a3",
- "sha256:db15ce28e1e127a0013dfb8ac243a8e392db8c61eae113337536edb28bdc1f97",
- "sha256:db842712984e91707437461930e6011e60b39136c7331e971952bb30465bc1a1",
- "sha256:e24bfe89c6ac4c31792793ad9f861b8f6dc4546ac6dc8f1c9083c7c4f2b335cd",
- "sha256:e81c52638315ff4ac1b533d427f50bc0afc746deb949210bc85f05d4f15fd772",
- "sha256:e9393357f19954248b00bed7c56f29a25c930593a77630c719653d51e7669c2a",
- "sha256:ee3941769bd2522fe39222206f6dd97ae83c442a94c90f2b7a25d847d40f4729",
- "sha256:f31ae06f1328595d762c9a2bf29dafd8621c7d3adc130cbb46278079758779ca",
- "sha256:f94190df587738280d544971500b9cafc9b950d32efcb1fba9ac10d84e6aa4e6",
- "sha256:fa7d686ed9883f3d664d39d5a8e74d3c5f63e603c2e3ff0abcba23eac6542635",
- "sha256:fb532dd9900381d2e8f48172ddc5a59db4c445a11b9fab40b3b786da40d3b56b",
- "sha256:fe32482b37b4b00c7a52a07211b479653b7fe4f22b2e481b9a9b099d8a430f2f"
+ "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4",
+ "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30",
+ "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0",
+ "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9",
+ "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396",
+ "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13",
+ "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028",
+ "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca",
+ "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557",
+ "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832",
+ "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0",
+ "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b",
+ "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579",
+ "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a",
+ "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c",
+ "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff",
+ "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c",
+ "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22",
+ "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094",
+ "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb",
+ "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e",
+ "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5",
+ "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a",
+ "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d",
+ "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a",
+ "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b",
+ "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8",
+ "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225",
+ "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c",
+ "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144",
+ "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f",
+ "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87",
+ "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d",
+ "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93",
+ "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf",
+ "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158",
+ "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84",
+ "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb",
+ "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48",
+ "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171",
+ "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c",
+ "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6",
+ "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd",
+ "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d",
+ "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1",
+ "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d",
+ "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca",
+ "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a",
+ "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29",
+ "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe",
+ "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798",
+ "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c",
+ "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8",
+ "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f",
+ "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f",
+ "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a",
+ "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178",
+ "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0",
+ "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79",
+ "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430",
+ "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"
],
"markers": "python_version >= '3.9'",
- "version": "==3.0.1"
+ "version": "==3.0.2"
},
"marshmallow": {
"hashes": [
- "sha256:4972f529104a220bb8637d595aa4c9762afbe7f7a77d82dc58c1615d70c5823e",
- "sha256:71a2dce49ef901c3f97ed296ae5051135fd3febd2bf43afe0ae9a82143a494d9"
+ "sha256:3a8dfda6edd8dcdbf216c0ede1d1e78d230a6dc9c5a088f58c4083b974a0d468",
+ "sha256:fece2eb2c941180ea1b7fcbd4a83c51bfdd50093fdd3ad2585ee5e1df2508491"
],
- "markers": "python_version >= '3.8'",
- "version": "==3.22.0"
+ "markers": "python_version >= '3.9'",
+ "version": "==3.23.1"
},
"mdurl": {
"hashes": [
@@ -1155,11 +1212,11 @@
},
"networkx": {
"hashes": [
- "sha256:0c127d8b2f4865f59ae9cb8aafcd60b5c70f3241ebd66f7defad7c4ab90126c9",
- "sha256:28575580c6ebdaf4505b22c6256a2b9de86b316dc63ba9e93abde3d78dfdbcf2"
+ "sha256:307c3669428c5362aab27c8a1260aa8f47c4e91d3891f48be0141738d8d053e1",
+ "sha256:df5d4365b724cf81b8c6a7312509d0c22386097011ad1abe274afd5e9d3bbc5f"
],
"markers": "python_version >= '3.10'",
- "version": "==3.3"
+ "version": "==3.4.2"
},
"nltk": {
"hashes": [
@@ -1211,6 +1268,14 @@
"markers": "python_version >= '3.9'",
"version": "==1.26.4"
},
+ "oauthlib": {
+ "hashes": [
+ "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca",
+ "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.2.2"
+ },
"openai": {
"hashes": [
"sha256:aa2f381f476f5fa4df8728a34a3e454c321caa064b7b68ab6e9daa1ed082dbf9",
@@ -1222,82 +1287,83 @@
},
"opentelemetry-api": {
"hashes": [
- "sha256:953d5871815e7c30c81b56d910c707588000fff7a3ca1c73e6531911d53065e7",
- "sha256:ed673583eaa5f81b5ce5e86ef7cdaf622f88ef65f0b9aab40b843dcae5bef342"
+ "sha256:6fa7295a12c707f5aebef82da3d9ec5afe6992f3e42bfe7bec0339a44b3518e7",
+ "sha256:bfe86c95576cf19a914497f439fd79c9553a38de0adbdc26f7cfc46b0c00b16c"
],
"markers": "python_version >= '3.8'",
- "version": "==1.27.0"
+ "version": "==1.28.1"
},
"orjson": {
"hashes": [
- "sha256:084e537806b458911137f76097e53ce7bf5806dda33ddf6aaa66a028f8d43a23",
- "sha256:09b2d92fd95ad2402188cf51573acde57eb269eddabaa60f69ea0d733e789fe9",
- "sha256:0fa5886854673222618638c6df7718ea7fe2f3f2384c452c9ccedc70b4a510a5",
- "sha256:11748c135f281203f4ee695b7f80bb1358a82a63905f9f0b794769483ea854ad",
- "sha256:1193b2416cbad1a769f868b1749535d5da47626ac29445803dae7cc64b3f5c98",
- "sha256:144888c76f8520e39bfa121b31fd637e18d4cc2f115727865fdf9fa325b10412",
- "sha256:1d9c0e733e02ada3ed6098a10a8ee0052dd55774de3d9110d29868d24b17faa1",
- "sha256:23820a1563a1d386414fef15c249040042b8e5d07b40ab3fe3efbfbbcbcb8864",
- "sha256:33cfb96c24034a878d83d1a9415799a73dc77480e6c40417e5dda0710d559ee6",
- "sha256:348bdd16b32556cf8d7257b17cf2bdb7ab7976af4af41ebe79f9796c218f7e91",
- "sha256:34a566f22c28222b08875b18b0dfbf8a947e69df21a9ed5c51a6bf91cfb944ac",
- "sha256:3dcfbede6737fdbef3ce9c37af3fb6142e8e1ebc10336daa05872bfb1d87839c",
- "sha256:430ee4d85841e1483d487e7b81401785a5dfd69db5de01314538f31f8fbf7ee1",
- "sha256:44a96f2d4c3af51bfac6bc4ef7b182aa33f2f054fd7f34cc0ee9a320d051d41f",
- "sha256:479fd0844ddc3ca77e0fd99644c7fe2de8e8be1efcd57705b5c92e5186e8a250",
- "sha256:480f455222cb7a1dea35c57a67578848537d2602b46c464472c995297117fa09",
- "sha256:4829cf2195838e3f93b70fd3b4292156fc5e097aac3739859ac0dcc722b27ac0",
- "sha256:4b6146e439af4c2472c56f8540d799a67a81226e11992008cb47e1267a9b3225",
- "sha256:4e6c3da13e5a57e4b3dca2de059f243ebec705857522f188f0180ae88badd354",
- "sha256:5b24a579123fa884f3a3caadaed7b75eb5715ee2b17ab5c66ac97d29b18fe57f",
- "sha256:6b0dd04483499d1de9c8f6203f8975caf17a6000b9c0c54630cef02e44ee624e",
- "sha256:6ea2b2258eff652c82652d5e0f02bd5e0463a6a52abb78e49ac288827aaa1469",
- "sha256:7122a99831f9e7fe977dc45784d3b2edc821c172d545e6420c375e5a935f5a1c",
- "sha256:74f4544f5a6405b90da8ea724d15ac9c36da4d72a738c64685003337401f5c12",
- "sha256:75ef0640403f945f3a1f9f6400686560dbfb0fb5b16589ad62cd477043c4eee3",
- "sha256:76ac14cd57df0572453543f8f2575e2d01ae9e790c21f57627803f5e79b0d3c3",
- "sha256:77d325ed866876c0fa6492598ec01fe30e803272a6e8b10e992288b009cbe149",
- "sha256:7c4c17f8157bd520cdb7195f75ddbd31671997cbe10aee559c2d613592e7d7eb",
- "sha256:7db8539039698ddfb9a524b4dd19508256107568cdad24f3682d5773e60504a2",
- "sha256:8272527d08450ab16eb405f47e0f4ef0e5ff5981c3d82afe0efd25dcbef2bcd2",
- "sha256:82763b46053727a7168d29c772ed5c870fdae2f61aa8a25994c7984a19b1021f",
- "sha256:8a9c9b168b3a19e37fe2778c0003359f07822c90fdff8f98d9d2a91b3144d8e0",
- "sha256:8de062de550f63185e4c1c54151bdddfc5625e37daf0aa1e75d2a1293e3b7d9a",
- "sha256:974683d4618c0c7dbf4f69c95a979734bf183d0658611760017f6e70a145af58",
- "sha256:9ea2c232deedcb605e853ae1db2cc94f7390ac776743b699b50b071b02bea6fe",
- "sha256:a0c6a008e91d10a2564edbb6ee5069a9e66df3fbe11c9a005cb411f441fd2c09",
- "sha256:a763bc0e58504cc803739e7df040685816145a6f3c8a589787084b54ebc9f16e",
- "sha256:a7e19150d215c7a13f39eb787d84db274298d3f83d85463e61d277bbd7f401d2",
- "sha256:ac7cf6222b29fbda9e3a472b41e6a5538b48f2c8f99261eecd60aafbdb60690c",
- "sha256:b48b3db6bb6e0a08fa8c83b47bc169623f801e5cc4f24442ab2b6617da3b5313",
- "sha256:b58d3795dafa334fc8fd46f7c5dc013e6ad06fd5b9a4cc98cb1456e7d3558bd6",
- "sha256:bdbb61dcc365dd9be94e8f7df91975edc9364d6a78c8f7adb69c1cdff318ec93",
- "sha256:bf6ba8ebc8ef5792e2337fb0419f8009729335bb400ece005606336b7fd7bab7",
- "sha256:c31008598424dfbe52ce8c5b47e0752dca918a4fdc4a2a32004efd9fab41d866",
- "sha256:cb61938aec8b0ffb6eef484d480188a1777e67b05d58e41b435c74b9d84e0b9c",
- "sha256:d2d9f990623f15c0ae7ac608103c33dfe1486d2ed974ac3f40b693bad1a22a7b",
- "sha256:d352ee8ac1926d6193f602cbe36b1643bbd1bbcb25e3c1a657a4390f3000c9a5",
- "sha256:d374d36726746c81a49f3ff8daa2898dccab6596864ebe43d50733275c629175",
- "sha256:de817e2f5fc75a9e7dd350c4b0f54617b280e26d1631811a43e7e968fa71e3e9",
- "sha256:e724cebe1fadc2b23c6f7415bad5ee6239e00a69f30ee423f319c6af70e2a5c0",
- "sha256:e72591bcfe7512353bd609875ab38050efe3d55e18934e2f18950c108334b4ff",
- "sha256:e76be12658a6fa376fcd331b1ea4e58f5a06fd0220653450f0d415b8fd0fbe20",
- "sha256:eb8d384a24778abf29afb8e41d68fdd9a156cf6e5390c04cc07bbc24b89e98b5",
- "sha256:ed350d6978d28b92939bfeb1a0570c523f6170efc3f0a0ef1f1df287cd4f4960",
- "sha256:eef44224729e9525d5261cc8d28d6b11cafc90e6bd0be2157bde69a52ec83024",
- "sha256:f4db56635b58cd1a200b0a23744ff44206ee6aa428185e2b6c4a65b3197abdcd",
- "sha256:fdf5197a21dd660cf19dfd2a3ce79574588f8f5e2dbf21bda9ee2d2b46924d84"
- ],
- "markers": "python_version >= '3.8'",
- "version": "==3.10.7"
+ "sha256:03246774131701de8e7059b2e382597da43144a9a7400f178b2a32feafc54bd5",
+ "sha256:0efabbf839388a1dab5b72b5d3baedbd6039ac83f3b55736eb9934ea5494d258",
+ "sha256:10f416b2a017c8bd17f325fb9dee1fb5cdd7a54e814284896b7c3f2763faa017",
+ "sha256:1444f9cb7c14055d595de1036f74ecd6ce15f04a715e73f33bb6326c9cef01b6",
+ "sha256:1789d9db7968d805f3d94aae2c25d04014aae3a2fa65b1443117cd462c6da647",
+ "sha256:19b3763e8bbf8ad797df6b6b5e0fc7c843ec2e2fc0621398534e0c6400098f87",
+ "sha256:1a1222ffcee8a09476bbdd5d4f6f33d06d0d6642df2a3d78b7a195ca880d669b",
+ "sha256:1be83a13312e5e58d633580c5eb8d0495ae61f180da2722f20562974188af205",
+ "sha256:1f39728c7f7d766f1f5a769ce4d54b5aaa4c3f92d5b84817053cc9995b977acc",
+ "sha256:360a4e2c0943da7c21505e47cf6bd725588962ff1d739b99b14e2f7f3545ba51",
+ "sha256:461311b693d3d0a060439aa669c74f3603264d4e7a08faa68c47ae5a863f352d",
+ "sha256:496e2cb45de21c369079ef2d662670a4892c81573bcc143c4205cae98282ba97",
+ "sha256:4bfb30c891b530f3f80e801e3ad82ef150b964e5c38e1fb8482441c69c35c61c",
+ "sha256:4d83f87582d223e54efb2242a79547611ba4ebae3af8bae1e80fa9a0af83bb7f",
+ "sha256:4eed32f33a0ea6ef36ccc1d37f8d17f28a1d6e8eefae5928f76aff8f1df85e67",
+ "sha256:51f3382415747e0dbda9dade6f1e1a01a9d37f630d8c9049a8ed0e385b7a90c0",
+ "sha256:52ca832f17d86a78cbab86cdc25f8c13756ebe182b6fc1a97d534051c18a08de",
+ "sha256:52e5834d7d6e58a36846e059d00559cb9ed20410664f3ad156cd2cc239a11230",
+ "sha256:5576b1e5a53a5ba8f8df81872bb0878a112b3ebb1d392155f00f54dd86c83ff6",
+ "sha256:63fc9d5fe1d4e8868f6aae547a7b8ba0a2e592929245fff61d633f4caccdcdd6",
+ "sha256:655a493bac606655db9a47fe94d3d84fc7f3ad766d894197c94ccf0c5408e7d3",
+ "sha256:65cd3e3bb4fbb4eddc3c1e8dce10dc0b73e808fcb875f9fab40c81903dd9323e",
+ "sha256:677f23e32491520eebb19c99bb34675daf5410c449c13416f7f0d93e2cf5f981",
+ "sha256:6dade64687f2bd7c090281652fe18f1151292d567a9302b34c2dbb92a3872f1f",
+ "sha256:6f67c570602300c4befbda12d153113b8974a3340fdcf3d6de095ede86c06d92",
+ "sha256:705f03cee0cb797256d54de6695ef219e5bc8c8120b6654dd460848d57a9af3d",
+ "sha256:77b0fed6f209d76c1c39f032a70df2d7acf24b1812ca3e6078fd04e8972685a3",
+ "sha256:7dfa8db55c9792d53c5952900c6a919cfa377b4f4534c7a786484a6a4a350c19",
+ "sha256:80c00d4acded0c51c98754fe8218cb49cb854f0f7eb39ea4641b7f71732d2cb7",
+ "sha256:80df27dd8697242b904f4ea54820e2d98d3f51f91e97e358fc13359721233e4b",
+ "sha256:82f07c550a6ccd2b9290849b22316a609023ed851a87ea888c0456485a7d196a",
+ "sha256:86b9dd983857970c29e4c71bb3e95ff085c07d3e83e7c46ebe959bac07ebd80b",
+ "sha256:8b5759063a6c940a69c728ea70d7c33583991c6982915a839c8da5f957e0103a",
+ "sha256:96ed1de70fcb15d5fed529a656df29f768187628727ee2788344e8a51e1c1350",
+ "sha256:9fd0ad1c129bc9beb1154c2655f177620b5beaf9a11e0d10bac63ef3fce96950",
+ "sha256:a11225d7b30468dcb099498296ffac36b4673a8398ca30fdaec1e6c20df6aa55",
+ "sha256:a2fc947e5350fdce548bfc94f434e8760d5cafa97fb9c495d2fef6757aa02ec0",
+ "sha256:a3f29634260708c200c4fe148e42b4aae97d7b9fee417fbdd74f8cfc265f15b0",
+ "sha256:afacfd1ab81f46dedd7f6001b6d4e8de23396e4884cd3c3436bd05defb1a6446",
+ "sha256:b592597fe551d518f42c5a2eb07422eb475aa8cfdc8c51e6da7054b836b26782",
+ "sha256:b7fcfc6f7ca046383fb954ba528587e0f9336828b568282b27579c49f8e16aad",
+ "sha256:b9546b278c9fb5d45380f4809e11b4dd9844ca7aaf1134024503e134ed226161",
+ "sha256:bc274ac261cc69260913b2d1610760e55d3c0801bb3457ba7b9004420b6b4270",
+ "sha256:bd9a187742d3ead9df2e49240234d728c67c356516cf4db018833a86f20ec18c",
+ "sha256:c46294faa4e4d0eb73ab68f1a794d2cbf7bab33b1dda2ac2959ffb7c61591899",
+ "sha256:c95f2ecafe709b4e5c733b5e2768ac569bed308623c85806c395d9cca00e08af",
+ "sha256:cb4d0bea56bba596723d73f074c420aec3b2e5d7d30698bc56e6048066bd560c",
+ "sha256:cdec57fe3b4bdebcc08a946db3365630332dbe575125ff3d80a3272ebd0ddafe",
+ "sha256:d496c74fc2b61341e3cefda7eec21b7854c5f672ee350bc55d9a4997a8a95204",
+ "sha256:d4a62c49c506d4d73f59514986cadebb7e8d186ad510c518f439176cf8d5359d",
+ "sha256:df8c677df2f9f385fcc85ab859704045fa88d4668bc9991a527c86e710392bec",
+ "sha256:dfbb2d460a855c9744bbc8e36f9c3a997c4b27d842f3d5559ed54326e6911f9b",
+ "sha256:e2f3b7c5803138e67028dde33450e054c87e0703afbe730c105f1fcd873496d5",
+ "sha256:e35b6d730de6384d5b2dab5fd23f0d76fae8bbc8c353c2f78210aa5fa4beb3ef",
+ "sha256:f1eec3421a558ff7a9b010a6c7effcfa0ade65327a71bb9b02a1c3b77a247284",
+ "sha256:f35a1b9f50a219f470e0e497ca30b285c9f34948d3c8160d5ad3a755d9299433",
+ "sha256:f4c57ea78a753812f528178aa2f1c57da633754c91d2124cb28991dab4c79a54",
+ "sha256:f91d9eb554310472bd09f5347950b24442600594c2edc1421403d7610a0998fd"
+ ],
+ "markers": "python_version >= '3.8'",
+ "version": "==3.10.11"
},
"packaging": {
"hashes": [
- "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002",
- "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"
+ "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759",
+ "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"
],
"markers": "python_version >= '3.8'",
- "version": "==24.1"
+ "version": "==24.2"
},
"pandas": {
"hashes": [
@@ -1349,89 +1415,84 @@
},
"pillow": {
"hashes": [
- "sha256:02a2be69f9c9b8c1e97cf2713e789d4e398c751ecfd9967c18d0ce304efbf885",
- "sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea",
- "sha256:06b2f7898047ae93fad74467ec3d28fe84f7831370e3c258afa533f81ef7f3df",
- "sha256:0755ffd4a0c6f267cccbae2e9903d95477ca2f77c4fcf3a3a09570001856c8a5",
- "sha256:0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c",
- "sha256:0ae24a547e8b711ccaaf99c9ae3cd975470e1a30caa80a6aaee9a2f19c05701d",
- "sha256:134ace6dc392116566980ee7436477d844520a26a4b1bd4053f6f47d096997fd",
- "sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06",
- "sha256:1b5dea9831a90e9d0721ec417a80d4cbd7022093ac38a568db2dd78363b00908",
- "sha256:1d846aea995ad352d4bdcc847535bd56e0fd88d36829d2c90be880ef1ee4668a",
- "sha256:1ef61f5dd14c300786318482456481463b9d6b91ebe5ef12f405afbba77ed0be",
- "sha256:297e388da6e248c98bc4a02e018966af0c5f92dfacf5a5ca22fa01cb3179bca0",
- "sha256:298478fe4f77a4408895605f3482b6cc6222c018b2ce565c2b6b9c354ac3229b",
- "sha256:29dbdc4207642ea6aad70fbde1a9338753d33fb23ed6956e706936706f52dd80",
- "sha256:2db98790afc70118bd0255c2eeb465e9767ecf1f3c25f9a1abb8ffc8cfd1fe0a",
- "sha256:32cda9e3d601a52baccb2856b8ea1fc213c90b340c542dcef77140dfa3278a9e",
- "sha256:37fb69d905be665f68f28a8bba3c6d3223c8efe1edf14cc4cfa06c241f8c81d9",
- "sha256:416d3a5d0e8cfe4f27f574362435bc9bae57f679a7158e0096ad2beb427b8696",
- "sha256:43efea75eb06b95d1631cb784aa40156177bf9dd5b4b03ff38979e048258bc6b",
- "sha256:4b35b21b819ac1dbd1233317adeecd63495f6babf21b7b2512d244ff6c6ce309",
- "sha256:4d9667937cfa347525b319ae34375c37b9ee6b525440f3ef48542fcf66f2731e",
- "sha256:5161eef006d335e46895297f642341111945e2c1c899eb406882a6c61a4357ab",
- "sha256:543f3dc61c18dafb755773efc89aae60d06b6596a63914107f75459cf984164d",
- "sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060",
- "sha256:59291fb29317122398786c2d44427bbd1a6d7ff54017075b22be9d21aa59bd8d",
- "sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d",
- "sha256:5b4815f2e65b30f5fbae9dfffa8636d992d49705723fe86a3661806e069352d4",
- "sha256:5dc6761a6efc781e6a1544206f22c80c3af4c8cf461206d46a1e6006e4429ff3",
- "sha256:5e84b6cc6a4a3d76c153a6b19270b3526a5a8ed6b09501d3af891daa2a9de7d6",
- "sha256:6209bb41dc692ddfee4942517c19ee81b86c864b626dbfca272ec0f7cff5d9fb",
- "sha256:673655af3eadf4df6b5457033f086e90299fdd7a47983a13827acf7459c15d94",
- "sha256:6c762a5b0997f5659a5ef2266abc1d8851ad7749ad9a6a5506eb23d314e4f46b",
- "sha256:7086cc1d5eebb91ad24ded9f58bec6c688e9f0ed7eb3dbbf1e4800280a896496",
- "sha256:73664fe514b34c8f02452ffb73b7a92c6774e39a647087f83d67f010eb9a0cf0",
- "sha256:76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319",
- "sha256:780c072c2e11c9b2c7ca37f9a2ee8ba66f44367ac3e5c7832afcfe5104fd6d1b",
- "sha256:7928ecbf1ece13956b95d9cbcfc77137652b02763ba384d9ab508099a2eca856",
- "sha256:7970285ab628a3779aecc35823296a7869f889b8329c16ad5a71e4901a3dc4ef",
- "sha256:7a8d4bade9952ea9a77d0c3e49cbd8b2890a399422258a77f357b9cc9be8d680",
- "sha256:7c1ee6f42250df403c5f103cbd2768a28fe1a0ea1f0f03fe151c8741e1469c8b",
- "sha256:7dfecdbad5c301d7b5bde160150b4db4c659cee2b69589705b6f8a0c509d9f42",
- "sha256:812f7342b0eee081eaec84d91423d1b4650bb9828eb53d8511bcef8ce5aecf1e",
- "sha256:866b6942a92f56300012f5fbac71f2d610312ee65e22f1aa2609e491284e5597",
- "sha256:86dcb5a1eb778d8b25659d5e4341269e8590ad6b4e8b44d9f4b07f8d136c414a",
- "sha256:87dd88ded2e6d74d31e1e0a99a726a6765cda32d00ba72dc37f0651f306daaa8",
- "sha256:8bc1a764ed8c957a2e9cacf97c8b2b053b70307cf2996aafd70e91a082e70df3",
- "sha256:8d4d5063501b6dd4024b8ac2f04962d661222d120381272deea52e3fc52d3736",
- "sha256:8f0aef4ef59694b12cadee839e2ba6afeab89c0f39a3adc02ed51d109117b8da",
- "sha256:930044bb7679ab003b14023138b50181899da3f25de50e9dbee23b61b4de2126",
- "sha256:950be4d8ba92aca4b2bb0741285a46bfae3ca699ef913ec8416c1b78eadd64cd",
- "sha256:961a7293b2457b405967af9c77dcaa43cc1a8cd50d23c532e62d48ab6cdd56f5",
- "sha256:9b885f89040bb8c4a1573566bbb2f44f5c505ef6e74cec7ab9068c900047f04b",
- "sha256:9f4727572e2918acaa9077c919cbbeb73bd2b3ebcfe033b72f858fc9fbef0026",
- "sha256:a02364621fe369e06200d4a16558e056fe2805d3468350df3aef21e00d26214b",
- "sha256:a985e028fc183bf12a77a8bbf36318db4238a3ded7fa9df1b9a133f1cb79f8fc",
- "sha256:ac1452d2fbe4978c2eec89fb5a23b8387aba707ac72810d9490118817d9c0b46",
- "sha256:b15e02e9bb4c21e39876698abf233c8c579127986f8207200bc8a8f6bb27acf2",
- "sha256:b2724fdb354a868ddf9a880cb84d102da914e99119211ef7ecbdc613b8c96b3c",
- "sha256:bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe",
- "sha256:bcd5e41a859bf2e84fdc42f4edb7d9aba0a13d29a2abadccafad99de3feff984",
- "sha256:bd2880a07482090a3bcb01f4265f1936a903d70bc740bfcb1fd4e8a2ffe5cf5a",
- "sha256:bee197b30783295d2eb680b311af15a20a8b24024a19c3a26431ff83eb8d1f70",
- "sha256:bf2342ac639c4cf38799a44950bbc2dfcb685f052b9e262f446482afaf4bffca",
- "sha256:c76e5786951e72ed3686e122d14c5d7012f16c8303a674d18cdcd6d89557fc5b",
- "sha256:cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91",
- "sha256:cfdd747216947628af7b259d274771d84db2268ca062dd5faf373639d00113a3",
- "sha256:d7480af14364494365e89d6fddc510a13e5a2c3584cb19ef65415ca57252fb84",
- "sha256:dbc6ae66518ab3c5847659e9988c3b60dc94ffb48ef9168656e0019a93dbf8a1",
- "sha256:dc3e2db6ba09ffd7d02ae9141cfa0ae23393ee7687248d46a7507b75d610f4f5",
- "sha256:dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be",
- "sha256:e4d49b85c4348ea0b31ea63bc75a9f3857869174e2bf17e7aba02945cd218e6f",
- "sha256:e4db64794ccdf6cb83a59d73405f63adbe2a1887012e308828596100a0b2f6cc",
- "sha256:e553cad5179a66ba15bb18b353a19020e73a7921296a7979c4a2b7f6a5cd57f9",
- "sha256:e88d5e6ad0d026fba7bdab8c3f225a69f063f116462c49892b0149e21b6c0a0e",
- "sha256:ecd85a8d3e79cd7158dec1c9e5808e821feea088e2f69a974db5edf84dc53141",
- "sha256:f5b92f4d70791b4a67157321c4e8225d60b119c5cc9aee8ecf153aace4aad4ef",
- "sha256:f5f0c3e969c8f12dd2bb7e0b15d5c468b51e5017e01e2e867335c81903046a22",
- "sha256:f7baece4ce06bade126fb84b8af1c33439a76d8a6fd818970215e0560ca28c27",
- "sha256:ff25afb18123cea58a591ea0244b92eb1e61a1fd497bf6d6384f09bc3262ec3e",
- "sha256:ff337c552345e95702c5fde3158acb0625111017d0e5f24bf3acdb9cc16b90d1"
- ],
- "markers": "python_version >= '3.8'",
- "version": "==10.4.0"
+ "sha256:00177a63030d612148e659b55ba99527803288cea7c75fb05766ab7981a8c1b7",
+ "sha256:006bcdd307cc47ba43e924099a038cbf9591062e6c50e570819743f5607404f5",
+ "sha256:084a07ef0821cfe4858fe86652fffac8e187b6ae677e9906e192aafcc1b69903",
+ "sha256:0ae08bd8ffc41aebf578c2af2f9d8749d91f448b3bfd41d7d9ff573d74f2a6b2",
+ "sha256:0e038b0745997c7dcaae350d35859c9715c71e92ffb7e0f4a8e8a16732150f38",
+ "sha256:1187739620f2b365de756ce086fdb3604573337cc28a0d3ac4a01ab6b2d2a6d2",
+ "sha256:16095692a253047fe3ec028e951fa4221a1f3ed3d80c397e83541a3037ff67c9",
+ "sha256:1a61b54f87ab5786b8479f81c4b11f4d61702830354520837f8cc791ebba0f5f",
+ "sha256:1c1d72714f429a521d8d2d018badc42414c3077eb187a59579f28e4270b4b0fc",
+ "sha256:1e2688958a840c822279fda0086fec1fdab2f95bf2b717b66871c4ad9859d7e8",
+ "sha256:20ec184af98a121fb2da42642dea8a29ec80fc3efbaefb86d8fdd2606619045d",
+ "sha256:21a0d3b115009ebb8ac3d2ebec5c2982cc693da935f4ab7bb5c8ebe2f47d36f2",
+ "sha256:224aaa38177597bb179f3ec87eeefcce8e4f85e608025e9cfac60de237ba6316",
+ "sha256:2679d2258b7f1192b378e2893a8a0a0ca472234d4c2c0e6bdd3380e8dfa21b6a",
+ "sha256:27a7860107500d813fcd203b4ea19b04babe79448268403172782754870dac25",
+ "sha256:290f2cc809f9da7d6d622550bbf4c1e57518212da51b6a30fe8e0a270a5b78bd",
+ "sha256:2e46773dc9f35a1dd28bd6981332fd7f27bec001a918a72a79b4133cf5291dba",
+ "sha256:3107c66e43bda25359d5ef446f59c497de2b5ed4c7fdba0894f8d6cf3822dafc",
+ "sha256:375b8dd15a1f5d2feafff536d47e22f69625c1aa92f12b339ec0b2ca40263273",
+ "sha256:45c566eb10b8967d71bf1ab8e4a525e5a93519e29ea071459ce517f6b903d7fa",
+ "sha256:499c3a1b0d6fc8213519e193796eb1a86a1be4b1877d678b30f83fd979811d1a",
+ "sha256:4ad70c4214f67d7466bea6a08061eba35c01b1b89eaa098040a35272a8efb22b",
+ "sha256:4b60c9520f7207aaf2e1d94de026682fc227806c6e1f55bba7606d1c94dd623a",
+ "sha256:5178952973e588b3f1360868847334e9e3bf49d19e169bbbdfaf8398002419ae",
+ "sha256:52a2d8323a465f84faaba5236567d212c3668f2ab53e1c74c15583cf507a0291",
+ "sha256:598b4e238f13276e0008299bd2482003f48158e2b11826862b1eb2ad7c768b97",
+ "sha256:5bd2d3bdb846d757055910f0a59792d33b555800813c3b39ada1829c372ccb06",
+ "sha256:5c39ed17edea3bc69c743a8dd3e9853b7509625c2462532e62baa0732163a904",
+ "sha256:5d203af30149ae339ad1b4f710d9844ed8796e97fda23ffbc4cc472968a47d0b",
+ "sha256:5ddbfd761ee00c12ee1be86c9c0683ecf5bb14c9772ddbd782085779a63dd55b",
+ "sha256:607bbe123c74e272e381a8d1957083a9463401f7bd01287f50521ecb05a313f8",
+ "sha256:61b887f9ddba63ddf62fd02a3ba7add935d053b6dd7d58998c630e6dbade8527",
+ "sha256:6619654954dc4936fcff82db8eb6401d3159ec6be81e33c6000dfd76ae189947",
+ "sha256:674629ff60030d144b7bca2b8330225a9b11c482ed408813924619c6f302fdbb",
+ "sha256:6ec0d5af64f2e3d64a165f490d96368bb5dea8b8f9ad04487f9ab60dc4bb6003",
+ "sha256:6f4dba50cfa56f910241eb7f883c20f1e7b1d8f7d91c750cd0b318bad443f4d5",
+ "sha256:70fbbdacd1d271b77b7721fe3cdd2d537bbbd75d29e6300c672ec6bb38d9672f",
+ "sha256:72bacbaf24ac003fea9bff9837d1eedb6088758d41e100c1552930151f677739",
+ "sha256:7326a1787e3c7b0429659e0a944725e1b03eeaa10edd945a86dead1913383944",
+ "sha256:73853108f56df97baf2bb8b522f3578221e56f646ba345a372c78326710d3830",
+ "sha256:73e3a0200cdda995c7e43dd47436c1548f87a30bb27fb871f352a22ab8dcf45f",
+ "sha256:75acbbeb05b86bc53cbe7b7e6fe00fbcf82ad7c684b3ad82e3d711da9ba287d3",
+ "sha256:8069c5179902dcdce0be9bfc8235347fdbac249d23bd90514b7a47a72d9fecf4",
+ "sha256:846e193e103b41e984ac921b335df59195356ce3f71dcfd155aa79c603873b84",
+ "sha256:8594f42df584e5b4bb9281799698403f7af489fba84c34d53d1c4bfb71b7c4e7",
+ "sha256:86510e3f5eca0ab87429dd77fafc04693195eec7fd6a137c389c3eeb4cfb77c6",
+ "sha256:8853a3bf12afddfdf15f57c4b02d7ded92c7a75a5d7331d19f4f9572a89c17e6",
+ "sha256:88a58d8ac0cc0e7f3a014509f0455248a76629ca9b604eca7dc5927cc593c5e9",
+ "sha256:8ba470552b48e5835f1d23ecb936bb7f71d206f9dfeee64245f30c3270b994de",
+ "sha256:8c676b587da5673d3c75bd67dd2a8cdfeb282ca38a30f37950511766b26858c4",
+ "sha256:8ec4a89295cd6cd4d1058a5e6aec6bf51e0eaaf9714774e1bfac7cfc9051db47",
+ "sha256:94f3e1780abb45062287b4614a5bc0874519c86a777d4a7ad34978e86428b8dd",
+ "sha256:9a0f748eaa434a41fccf8e1ee7a3eed68af1b690e75328fd7a60af123c193b50",
+ "sha256:a5629742881bcbc1f42e840af185fd4d83a5edeb96475a575f4da50d6ede337c",
+ "sha256:a65149d8ada1055029fcb665452b2814fe7d7082fcb0c5bed6db851cb69b2086",
+ "sha256:b3c5ac4bed7519088103d9450a1107f76308ecf91d6dabc8a33a2fcfb18d0fba",
+ "sha256:b4fd7bd29610a83a8c9b564d457cf5bd92b4e11e79a4ee4716a63c959699b306",
+ "sha256:bcd1fb5bb7b07f64c15618c89efcc2cfa3e95f0e3bcdbaf4642509de1942a699",
+ "sha256:c12b5ae868897c7338519c03049a806af85b9b8c237b7d675b8c5e089e4a618e",
+ "sha256:c26845094b1af3c91852745ae78e3ea47abf3dbcd1cf962f16b9a5fbe3ee8488",
+ "sha256:c6a660307ca9d4867caa8d9ca2c2658ab685de83792d1876274991adec7b93fa",
+ "sha256:c809a70e43c7977c4a42aefd62f0131823ebf7dd73556fa5d5950f5b354087e2",
+ "sha256:c8b2351c85d855293a299038e1f89db92a2f35e8d2f783489c6f0b2b5f3fe8a3",
+ "sha256:cb929ca942d0ec4fac404cbf520ee6cac37bf35be479b970c4ffadf2b6a1cad9",
+ "sha256:d2c0a187a92a1cb5ef2c8ed5412dd8d4334272617f532d4ad4de31e0495bd923",
+ "sha256:d69bfd8ec3219ae71bcde1f942b728903cad25fafe3100ba2258b973bd2bc1b2",
+ "sha256:daffdf51ee5db69a82dd127eabecce20729e21f7a3680cf7cbb23f0829189790",
+ "sha256:e58876c91f97b0952eb766123bfef372792ab3f4e3e1f1a2267834c2ab131734",
+ "sha256:eda2616eb2313cbb3eebbe51f19362eb434b18e3bb599466a1ffa76a033fb916",
+ "sha256:ee217c198f2e41f184f3869f3e485557296d505b5195c513b2bfe0062dc537f1",
+ "sha256:f02541ef64077f22bf4924f225c0fd1248c168f86e4b7abdedd87d6ebaceab0f",
+ "sha256:f1b82c27e89fffc6da125d5eb0ca6e68017faf5efc078128cfaa42cf5cb38798",
+ "sha256:fba162b8872d30fea8c52b258a542c5dfd7b235fb5cb352240c8d63b414013eb",
+ "sha256:fbbcb7b57dc9c794843e3d1258c0fbf0f48656d46ffe9e09b63bbd6e8cd5d0a2",
+ "sha256:fcb4621042ac4b7865c179bb972ed0da0218a076dc1820ffc48b1d74c1e37fe9"
+ ],
+ "markers": "python_version >= '3.9'",
+ "version": "==11.0.0"
},
"propcache": {
"hashes": [
@@ -1539,20 +1600,36 @@
},
"protobuf": {
"hashes": [
- "sha256:2c69461a7fcc8e24be697624c09a839976d82ae75062b11a0972e41fd2cd9132",
- "sha256:35cfcb15f213449af7ff6198d6eb5f739c37d7e4f1c09b5d0641babf2cc0c68f",
- "sha256:52235802093bd8a2811abbe8bf0ab9c5f54cca0a751fdd3f6ac2a21438bffece",
- "sha256:59379674ff119717404f7454647913787034f03fe7049cbef1d74a97bb4593f0",
- "sha256:5e8a95246d581eef20471b5d5ba010d55f66740942b95ba9b872d918c459452f",
- "sha256:87317e9bcda04a32f2ee82089a204d3a2f0d3c8aeed16568c7daf4756e4f1fe0",
- "sha256:8ddc60bf374785fb7cb12510b267f59067fa10087325b8e1855b898a0d81d276",
- "sha256:a8b9403fc70764b08d2f593ce44f1d2920c5077bf7d311fefec999f8c40f78b7",
- "sha256:c0ea0123dac3399a2eeb1a1443d82b7afc9ff40241433296769f7da42d142ec3",
- "sha256:ca53faf29896c526863366a52a8f4d88e69cd04ec9571ed6082fa117fac3ab36",
- "sha256:eeea10f3dc0ac7e6b4933d32db20662902b4ab81bf28df12218aa389e9c2102d"
+ "sha256:0c4eec6f987338617072592b97943fdbe30d019c56126493111cf24344c1cc24",
+ "sha256:135658402f71bbd49500322c0f736145731b16fc79dc8f367ab544a17eab4535",
+ "sha256:27b246b3723692bf1068d5734ddaf2fccc2cdd6e0c9b47fe099244d80200593b",
+ "sha256:3e6101d095dfd119513cde7259aa703d16c6bbdfae2554dfe5cfdbe94e32d548",
+ "sha256:3fa2de6b8b29d12c61911505d893afe7320ce7ccba4df913e2971461fa36d584",
+ "sha256:64badbc49180a5e401f373f9ce7ab1d18b63f7dd4a9cdc43c92b9f0b481cef7b",
+ "sha256:70585a70fc2dd4818c51287ceef5bdba6387f88a578c86d47bb34669b5552c36",
+ "sha256:712319fbdddb46f21abb66cd33cb9e491a5763b2febd8f228251add221981135",
+ "sha256:91fba8f445723fcf400fdbe9ca796b19d3b1242cd873907979b9ed71e4afe868",
+ "sha256:a3f6857551e53ce35e60b403b8a27b0295f7d6eb63d10484f12bc6879c715687",
+ "sha256:cee1757663fa32a1ee673434fcf3bf24dd54763c79690201208bafec62f19eed"
+ ],
+ "markers": "python_version >= '3.8'",
+ "version": "==5.28.3"
+ },
+ "pyasn1": {
+ "hashes": [
+ "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629",
+ "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034"
+ ],
+ "markers": "python_version >= '3.8'",
+ "version": "==0.6.1"
+ },
+ "pyasn1-modules": {
+ "hashes": [
+ "sha256:49bfa96b45a292b711e986f222502c1c9a5e1f4e568fc30e2574a6c7d07838fd",
+ "sha256:c28e2dbf9c06ad61c71a075c7e0f9fd0f1b0bb2d2ad4377f240d33ac2ab60a7c"
],
"markers": "python_version >= '3.8'",
- "version": "==5.28.2"
+ "version": "==0.4.1"
},
"pycparser": {
"hashes": [
@@ -1711,11 +1788,11 @@
},
"python-multipart": {
"hashes": [
- "sha256:045e1f98d719c1ce085ed7f7e1ef9d8ccc8c02ba02b5566d5f7521410ced58cb",
- "sha256:43dcf96cf65888a9cd3423544dd0d75ac10f7aa0c3c28a175bbcd00c9ce1aebf"
+ "sha256:15dc4f487e0a9476cc1201261188ee0940165cffc94429b6fc565c4d3045cb5d",
+ "sha256:41330d831cae6e2f22902704ead2826ea038d0419530eadff3ea80175aec5538"
],
"markers": "python_version >= '3.8'",
- "version": "==0.0.12"
+ "version": "==0.0.17"
},
"pytz": {
"hashes": [
@@ -1785,103 +1862,103 @@
},
"regex": {
"hashes": [
- "sha256:01c2acb51f8a7d6494c8c5eafe3d8e06d76563d8a8a4643b37e9b2dd8a2ff623",
- "sha256:02087ea0a03b4af1ed6ebab2c54d7118127fee8d71b26398e8e4b05b78963199",
- "sha256:040562757795eeea356394a7fb13076ad4f99d3c62ab0f8bdfb21f99a1f85664",
- "sha256:042c55879cfeb21a8adacc84ea347721d3d83a159da6acdf1116859e2427c43f",
- "sha256:079400a8269544b955ffa9e31f186f01d96829110a3bf79dc338e9910f794fca",
- "sha256:07f45f287469039ffc2c53caf6803cd506eb5f5f637f1d4acb37a738f71dd066",
- "sha256:09d77559e80dcc9d24570da3745ab859a9cf91953062e4ab126ba9d5993688ca",
- "sha256:0cbff728659ce4bbf4c30b2a1be040faafaa9eca6ecde40aaff86f7889f4ab39",
- "sha256:0e12c481ad92d129c78f13a2a3662317e46ee7ef96c94fd332e1c29131875b7d",
- "sha256:0ea51dcc0835eea2ea31d66456210a4e01a076d820e9039b04ae8d17ac11dee6",
- "sha256:0ffbcf9221e04502fc35e54d1ce9567541979c3fdfb93d2c554f0ca583a19b35",
- "sha256:1494fa8725c285a81d01dc8c06b55287a1ee5e0e382d8413adc0a9197aac6408",
- "sha256:16e13a7929791ac1216afde26f712802e3df7bf0360b32e4914dca3ab8baeea5",
- "sha256:18406efb2f5a0e57e3a5881cd9354c1512d3bb4f5c45d96d110a66114d84d23a",
- "sha256:18e707ce6c92d7282dfce370cd205098384b8ee21544e7cb29b8aab955b66fa9",
- "sha256:220e92a30b426daf23bb67a7962900ed4613589bab80382be09b48896d211e92",
- "sha256:23b30c62d0f16827f2ae9f2bb87619bc4fba2044911e2e6c2eb1af0161cdb766",
- "sha256:23f9985c8784e544d53fc2930fc1ac1a7319f5d5332d228437acc9f418f2f168",
- "sha256:297f54910247508e6e5cae669f2bc308985c60540a4edd1c77203ef19bfa63ca",
- "sha256:2b08fce89fbd45664d3df6ad93e554b6c16933ffa9d55cb7e01182baaf971508",
- "sha256:2cce2449e5927a0bf084d346da6cd5eb016b2beca10d0013ab50e3c226ffc0df",
- "sha256:313ea15e5ff2a8cbbad96ccef6be638393041b0a7863183c2d31e0c6116688cf",
- "sha256:323c1f04be6b2968944d730e5c2091c8c89767903ecaa135203eec4565ed2b2b",
- "sha256:35f4a6f96aa6cb3f2f7247027b07b15a374f0d5b912c0001418d1d55024d5cb4",
- "sha256:3b37fa423beefa44919e009745ccbf353d8c981516e807995b2bd11c2c77d268",
- "sha256:3ce4f1185db3fbde8ed8aa223fc9620f276c58de8b0d4f8cc86fd1360829edb6",
- "sha256:46989629904bad940bbec2106528140a218b4a36bb3042d8406980be1941429c",
- "sha256:4838e24ee015101d9f901988001038f7f0d90dc0c3b115541a1365fb439add62",
- "sha256:49b0e06786ea663f933f3710a51e9385ce0cba0ea56b67107fd841a55d56a231",
- "sha256:4db21ece84dfeefc5d8a3863f101995de646c6cb0536952c321a2650aa202c36",
- "sha256:54c4a097b8bc5bb0dfc83ae498061d53ad7b5762e00f4adaa23bee22b012e6ba",
- "sha256:54d9ff35d4515debf14bc27f1e3b38bfc453eff3220f5bce159642fa762fe5d4",
- "sha256:55b96e7ce3a69a8449a66984c268062fbaa0d8ae437b285428e12797baefce7e",
- "sha256:57fdd2e0b2694ce6fc2e5ccf189789c3e2962916fb38779d3e3521ff8fe7a822",
- "sha256:587d4af3979376652010e400accc30404e6c16b7df574048ab1f581af82065e4",
- "sha256:5b513b6997a0b2f10e4fd3a1313568e373926e8c252bd76c960f96fd039cd28d",
- "sha256:5ddcd9a179c0a6fa8add279a4444015acddcd7f232a49071ae57fa6e278f1f71",
- "sha256:6113c008a7780792efc80f9dfe10ba0cd043cbf8dc9a76ef757850f51b4edc50",
- "sha256:635a1d96665f84b292e401c3d62775851aedc31d4f8784117b3c68c4fcd4118d",
- "sha256:64ce2799bd75039b480cc0360907c4fb2f50022f030bf9e7a8705b636e408fad",
- "sha256:69dee6a020693d12a3cf892aba4808fe168d2a4cef368eb9bf74f5398bfd4ee8",
- "sha256:6a2644a93da36c784e546de579ec1806bfd2763ef47babc1b03d765fe560c9f8",
- "sha256:6b41e1adc61fa347662b09398e31ad446afadff932a24807d3ceb955ed865cc8",
- "sha256:6c188c307e8433bcb63dc1915022deb553b4203a70722fc542c363bf120a01fd",
- "sha256:6edd623bae6a737f10ce853ea076f56f507fd7726bee96a41ee3d68d347e4d16",
- "sha256:73d6d2f64f4d894c96626a75578b0bf7d9e56dcda8c3d037a2118fdfe9b1c664",
- "sha256:7a22ccefd4db3f12b526eccb129390942fe874a3a9fdbdd24cf55773a1faab1a",
- "sha256:7fb89ee5d106e4a7a51bce305ac4efb981536301895f7bdcf93ec92ae0d91c7f",
- "sha256:846bc79ee753acf93aef4184c040d709940c9d001029ceb7b7a52747b80ed2dd",
- "sha256:85ab7824093d8f10d44330fe1e6493f756f252d145323dd17ab6b48733ff6c0a",
- "sha256:8dee5b4810a89447151999428fe096977346cf2f29f4d5e29609d2e19e0199c9",
- "sha256:8e5fb5f77c8745a60105403a774fe2c1759b71d3e7b4ca237a5e67ad066c7199",
- "sha256:98eeee2f2e63edae2181c886d7911ce502e1292794f4c5ee71e60e23e8d26b5d",
- "sha256:9d4a76b96f398697fe01117093613166e6aa8195d63f1b4ec3f21ab637632963",
- "sha256:9e8719792ca63c6b8340380352c24dcb8cd7ec49dae36e963742a275dfae6009",
- "sha256:a0b2b80321c2ed3fcf0385ec9e51a12253c50f146fddb2abbb10f033fe3d049a",
- "sha256:a4cc92bb6db56ab0c1cbd17294e14f5e9224f0cc6521167ef388332604e92679",
- "sha256:a738b937d512b30bf75995c0159c0ddf9eec0775c9d72ac0202076c72f24aa96",
- "sha256:a8f877c89719d759e52783f7fe6e1c67121076b87b40542966c02de5503ace42",
- "sha256:a906ed5e47a0ce5f04b2c981af1c9acf9e8696066900bf03b9d7879a6f679fc8",
- "sha256:ae2941333154baff9838e88aa71c1d84f4438189ecc6021a12c7573728b5838e",
- "sha256:b0d0a6c64fcc4ef9c69bd5b3b3626cc3776520a1637d8abaa62b9edc147a58f7",
- "sha256:b5b029322e6e7b94fff16cd120ab35a253236a5f99a79fb04fda7ae71ca20ae8",
- "sha256:b7aaa315101c6567a9a45d2839322c51c8d6e81f67683d529512f5bcfb99c802",
- "sha256:be1c8ed48c4c4065ecb19d882a0ce1afe0745dfad8ce48c49586b90a55f02366",
- "sha256:c0256beda696edcf7d97ef16b2a33a8e5a875affd6fa6567b54f7c577b30a137",
- "sha256:c157bb447303070f256e084668b702073db99bbb61d44f85d811025fcf38f784",
- "sha256:c57d08ad67aba97af57a7263c2d9006d5c404d721c5f7542f077f109ec2a4a29",
- "sha256:c69ada171c2d0e97a4b5aa78fbb835e0ffbb6b13fc5da968c09811346564f0d3",
- "sha256:c94bb0a9f1db10a1d16c00880bdebd5f9faf267273b8f5bd1878126e0fbde771",
- "sha256:cb130fccd1a37ed894824b8c046321540263013da72745d755f2d35114b81a60",
- "sha256:ced479f601cd2f8ca1fd7b23925a7e0ad512a56d6e9476f79b8f381d9d37090a",
- "sha256:d05ac6fa06959c4172eccd99a222e1fbf17b5670c4d596cb1e5cde99600674c4",
- "sha256:d552c78411f60b1fdaafd117a1fca2f02e562e309223b9d44b7de8be451ec5e0",
- "sha256:dd4490a33eb909ef5078ab20f5f000087afa2a4daa27b4c072ccb3cb3050ad84",
- "sha256:df5cbb1fbc74a8305b6065d4ade43b993be03dbe0f8b30032cced0d7740994bd",
- "sha256:e28f9faeb14b6f23ac55bfbbfd3643f5c7c18ede093977f1df249f73fd22c7b1",
- "sha256:e464b467f1588e2c42d26814231edecbcfe77f5ac414d92cbf4e7b55b2c2a776",
- "sha256:e4c22e1ac1f1ec1e09f72e6c44d8f2244173db7eb9629cc3a346a8d7ccc31142",
- "sha256:e53b5fbab5d675aec9f0c501274c467c0f9a5d23696cfc94247e1fb56501ed89",
- "sha256:e93f1c331ca8e86fe877a48ad64e77882c0c4da0097f2212873a69bbfea95d0c",
- "sha256:e997fd30430c57138adc06bba4c7c2968fb13d101e57dd5bb9355bf8ce3fa7e8",
- "sha256:e9a091b0550b3b0207784a7d6d0f1a00d1d1c8a11699c1a4d93db3fbefc3ad35",
- "sha256:eab4bb380f15e189d1313195b062a6aa908f5bd687a0ceccd47c8211e9cf0d4a",
- "sha256:eb1ae19e64c14c7ec1995f40bd932448713d3c73509e82d8cd7744dc00e29e86",
- "sha256:ecea58b43a67b1b79805f1a0255730edaf5191ecef84dbc4cc85eb30bc8b63b9",
- "sha256:ee439691d8c23e76f9802c42a95cfeebf9d47cf4ffd06f18489122dbb0a7ad64",
- "sha256:eee9130eaad130649fd73e5cd92f60e55708952260ede70da64de420cdcad554",
- "sha256:f47cd43a5bfa48f86925fe26fbdd0a488ff15b62468abb5d2a1e092a4fb10e85",
- "sha256:f6fff13ef6b5f29221d6904aa816c34701462956aa72a77f1f151a8ec4f56aeb",
- "sha256:f745ec09bc1b0bd15cfc73df6fa4f726dcc26bb16c23a03f9e3367d357eeedd0",
- "sha256:f8404bf61298bb6f8224bb9176c1424548ee1181130818fcd2cbffddc768bed8",
- "sha256:f9268774428ec173654985ce55fc6caf4c6d11ade0f6f914d48ef4719eb05ebb",
- "sha256:faa3c142464efec496967359ca99696c896c591c56c53506bac1ad465f66e919"
- ],
- "markers": "python_version >= '3.8'",
- "version": "==2024.9.11"
+ "sha256:02a02d2bb04fec86ad61f3ea7f49c015a0681bf76abb9857f945d26159d2968c",
+ "sha256:02e28184be537f0e75c1f9b2f8847dc51e08e6e171c6bde130b2687e0c33cf60",
+ "sha256:040df6fe1a5504eb0f04f048e6d09cd7c7110fef851d7c567a6b6e09942feb7d",
+ "sha256:068376da5a7e4da51968ce4c122a7cd31afaaec4fccc7856c92f63876e57b51d",
+ "sha256:06eb1be98df10e81ebaded73fcd51989dcf534e3c753466e4b60c4697a003b67",
+ "sha256:072623554418a9911446278f16ecb398fb3b540147a7828c06e2011fa531e773",
+ "sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0",
+ "sha256:08986dce1339bc932923e7d1232ce9881499a0e02925f7402fb7c982515419ef",
+ "sha256:0a86e7eeca091c09e021db8eb72d54751e527fa47b8d5787caf96d9831bd02ad",
+ "sha256:0c32f75920cf99fe6b6c539c399a4a128452eaf1af27f39bce8909c9a3fd8cbe",
+ "sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3",
+ "sha256:1062b39a0a2b75a9c694f7a08e7183a80c63c0d62b301418ffd9c35f55aaa114",
+ "sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4",
+ "sha256:149f5008d286636e48cd0b1dd65018548944e495b0265b45e1bffecce1ef7f39",
+ "sha256:164d8b7b3b4bcb2068b97428060b2a53be050085ef94eca7f240e7947f1b080e",
+ "sha256:167ed4852351d8a750da48712c3930b031f6efdaa0f22fa1933716bfcd6bf4a3",
+ "sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7",
+ "sha256:202eb32e89f60fc147a41e55cb086db2a3f8cb82f9a9a88440dcfc5d37faae8d",
+ "sha256:220902c3c5cc6af55d4fe19ead504de80eb91f786dc102fbd74894b1551f095e",
+ "sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a",
+ "sha256:2c89a8cc122b25ce6945f0423dc1352cb9593c68abd19223eebbd4e56612c5b7",
+ "sha256:2d548dafee61f06ebdb584080621f3e0c23fff312f0de1afc776e2a2ba99a74f",
+ "sha256:2e34b51b650b23ed3354b5a07aab37034d9f923db2a40519139af34f485f77d0",
+ "sha256:32f9a4c643baad4efa81d549c2aadefaeba12249b2adc5af541759237eee1c54",
+ "sha256:3a51ccc315653ba012774efca4f23d1d2a8a8f278a6072e29c7147eee7da446b",
+ "sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c",
+ "sha256:40291b1b89ca6ad8d3f2b82782cc33807f1406cf68c8d440861da6304d8ffbbd",
+ "sha256:41758407fc32d5c3c5de163888068cfee69cb4c2be844e7ac517a52770f9af57",
+ "sha256:4181b814e56078e9b00427ca358ec44333765f5ca1b45597ec7446d3a1ef6e34",
+ "sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d",
+ "sha256:50153825ee016b91549962f970d6a4442fa106832e14c918acd1c8e479916c4f",
+ "sha256:5056b185ca113c88e18223183aa1a50e66507769c9640a6ff75859619d73957b",
+ "sha256:5071b2093e793357c9d8b2929dfc13ac5f0a6c650559503bb81189d0a3814519",
+ "sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4",
+ "sha256:52fb28f528778f184f870b7cf8f225f5eef0a8f6e3778529bdd40c7b3920796a",
+ "sha256:5478c6962ad548b54a591778e93cd7c456a7a29f8eca9c49e4f9a806dcc5d638",
+ "sha256:5670bce7b200273eee1840ef307bfa07cda90b38ae56e9a6ebcc9f50da9c469b",
+ "sha256:5704e174f8ccab2026bd2f1ab6c510345ae8eac818b613d7d73e785f1310f839",
+ "sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07",
+ "sha256:5e7e351589da0850c125f1600a4c4ba3c722efefe16b297de54300f08d734fbf",
+ "sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff",
+ "sha256:658f90550f38270639e83ce492f27d2c8d2cd63805c65a13a14d36ca126753f0",
+ "sha256:684d7a212682996d21ca12ef3c17353c021fe9de6049e19ac8481ec35574a70f",
+ "sha256:69ab78f848845569401469da20df3e081e6b5a11cb086de3eed1d48f5ed57c95",
+ "sha256:6f44ec28b1f858c98d3036ad5d7d0bfc568bdd7a74f9c24e25f41ef1ebfd81a4",
+ "sha256:70b7fa6606c2881c1db9479b0eaa11ed5dfa11c8d60a474ff0e095099f39d98e",
+ "sha256:764e71f22ab3b305e7f4c21f1a97e1526a25ebdd22513e251cf376760213da13",
+ "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519",
+ "sha256:805e6b60c54bf766b251e94526ebad60b7de0c70f70a4e6210ee2891acb70bf2",
+ "sha256:8447d2d39b5abe381419319f942de20b7ecd60ce86f16a23b0698f22e1b70008",
+ "sha256:86fddba590aad9208e2fa8b43b4c098bb0ec74f15718bb6a704e3c63e2cef3e9",
+ "sha256:89d75e7293d2b3e674db7d4d9b1bee7f8f3d1609428e293771d1a962617150cc",
+ "sha256:93c0b12d3d3bc25af4ebbf38f9ee780a487e8bf6954c115b9f015822d3bb8e48",
+ "sha256:94d87b689cdd831934fa3ce16cc15cd65748e6d689f5d2b8f4f4df2065c9fa20",
+ "sha256:9714398225f299aa85267fd222f7142fcb5c769e73d7733344efc46f2ef5cf89",
+ "sha256:982e6d21414e78e1f51cf595d7f321dcd14de1f2881c5dc6a6e23bbbbd68435e",
+ "sha256:997d6a487ff00807ba810e0f8332c18b4eb8d29463cfb7c820dc4b6e7562d0cf",
+ "sha256:a03e02f48cd1abbd9f3b7e3586d97c8f7a9721c436f51a5245b3b9483044480b",
+ "sha256:a36fdf2af13c2b14738f6e973aba563623cb77d753bbbd8d414d18bfaa3105dd",
+ "sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84",
+ "sha256:a7c2155f790e2fb448faed6dd241386719802296ec588a8b9051c1f5c481bc29",
+ "sha256:a93c194e2df18f7d264092dc8539b8ffb86b45b899ab976aa15d48214138e81b",
+ "sha256:abfa5080c374a76a251ba60683242bc17eeb2c9818d0d30117b4486be10c59d3",
+ "sha256:ac10f2c4184420d881a3475fb2c6f4d95d53a8d50209a2500723d831036f7c45",
+ "sha256:ad182d02e40de7459b73155deb8996bbd8e96852267879396fb274e8700190e3",
+ "sha256:b2837718570f95dd41675328e111345f9b7095d821bac435aac173ac80b19983",
+ "sha256:b489578720afb782f6ccf2840920f3a32e31ba28a4b162e13900c3e6bd3f930e",
+ "sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7",
+ "sha256:b85c2530be953a890eaffde05485238f07029600e8f098cdf1848d414a8b45e4",
+ "sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e",
+ "sha256:ba9b72e5643641b7d41fa1f6d5abda2c9a263ae835b917348fc3c928182ad467",
+ "sha256:bb26437975da7dc36b7efad18aa9dd4ea569d2357ae6b783bf1118dabd9ea577",
+ "sha256:bb8f74f2f10dbf13a0be8de623ba4f9491faf58c24064f32b65679b021ed0001",
+ "sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0",
+ "sha256:bec9931dfb61ddd8ef2ebc05646293812cb6b16b60cf7c9511a832b6f1854b55",
+ "sha256:c36f9b6f5f8649bb251a5f3f66564438977b7ef8386a52460ae77e6070d309d9",
+ "sha256:cdf58d0e516ee426a48f7b2c03a332a4114420716d55769ff7108c37a09951bf",
+ "sha256:d1cee317bfc014c2419a76bcc87f071405e3966da434e03e13beb45f8aced1a6",
+ "sha256:d22326fcdef5e08c154280b71163ced384b428343ae16a5ab2b3354aed12436e",
+ "sha256:d3660c82f209655a06b587d55e723f0b813d3a7db2e32e5e7dc64ac2a9e86fde",
+ "sha256:da8f5fc57d1933de22a9e23eec290a0d8a5927a5370d24bda9a6abe50683fe62",
+ "sha256:df951c5f4a1b1910f1a99ff42c473ff60f8225baa1cdd3539fe2819d9543e9df",
+ "sha256:e5364a4502efca094731680e80009632ad6624084aff9a23ce8c8c6820de3e51",
+ "sha256:ea1bfda2f7162605f6e8178223576856b3d791109f15ea99a9f95c16a7636fb5",
+ "sha256:f02f93b92358ee3f78660e43b4b0091229260c5d5c408d17d60bf26b6c900e86",
+ "sha256:f056bf21105c2515c32372bbc057f43eb02aae2fda61052e2f7622c801f0b4e2",
+ "sha256:f1ac758ef6aebfc8943560194e9fd0fa18bcb34d89fd8bd2af18183afd8da3a2",
+ "sha256:f2a19f302cd1ce5dd01a9099aaa19cae6173306d1302a43b627f62e21cf18ac0",
+ "sha256:f654882311409afb1d780b940234208a252322c24a93b442ca714d119e68086c",
+ "sha256:f65557897fc977a44ab205ea871b690adaef6b9da6afda4790a2484b04293a5f",
+ "sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6",
+ "sha256:fdabbfc59f2c6edba2a6622c647b716e34e8e3867e0ab975412c5c2f79b82da2",
+ "sha256:fdd6028445d2460f33136c55eeb1f601ab06d74cb3347132e1c24250187500d9",
+ "sha256:ff590880083d60acc0433f9c3f713c51f7ac6ebb9adf889c79a261ecf541aa91"
+ ],
+ "markers": "python_version >= '3.8'",
+ "version": "==2024.11.6"
},
"requests": {
"hashes": [
@@ -1891,21 +1968,37 @@
"markers": "python_version >= '3.8'",
"version": "==2.32.3"
},
+ "requests-oauthlib": {
+ "hashes": [
+ "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36",
+ "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9"
+ ],
+ "markers": "python_version >= '3.4'",
+ "version": "==2.0.0"
+ },
"rich": {
"hashes": [
- "sha256:51a2c62057461aaf7152b4d611168f93a9fc73068f8ded2790f29fe2b5366d0c",
- "sha256:8c82a3d3f8dcfe9e734771313e606b39d8247bb6b826e196f4914b333b743cf1"
+ "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098",
+ "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90"
],
"markers": "python_full_version >= '3.8.0'",
- "version": "==13.9.2"
+ "version": "==13.9.4"
+ },
+ "rsa": {
+ "hashes": [
+ "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7",
+ "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"
+ ],
+ "markers": "python_version >= '3.6' and python_version < '4'",
+ "version": "==4.9"
},
"setuptools": {
"hashes": [
- "sha256:35ab7fd3bcd95e6b7fd704e4a1539513edad446c097797f2985e0e4b960772f2",
- "sha256:d59a21b17a275fb872a9c3dae73963160ae079f1049ed956880cd7c09b120538"
+ "sha256:5c4ccb41111392671f02bb5f8436dfc5a9a7185e80500531b133f5775c4163ef",
+ "sha256:87cb777c3b96d638ca02031192d40390e0ad97737e27b6b4fa831bea86f2f829"
],
"markers": "python_version >= '3.12'",
- "version": "==75.1.0"
+ "version": "==75.5.0"
},
"shellingham": {
"hashes": [
@@ -1944,58 +2037,66 @@
"asyncio"
],
"hashes": [
- "sha256:016b2e665f778f13d3c438651dd4de244214b527a275e0acf1d44c05bc6026a9",
- "sha256:032d979ce77a6c2432653322ba4cbeabf5a6837f704d16fa38b5a05d8e21fa00",
- "sha256:0375a141e1c0878103eb3d719eb6d5aa444b490c96f3fedab8471c7f6ffe70ee",
- "sha256:042622a5306c23b972192283f4e22372da3b8ddf5f7aac1cc5d9c9b222ab3ff6",
- "sha256:05c3f58cf91683102f2f0265c0db3bd3892e9eedabe059720492dbaa4f922da1",
- "sha256:0630774b0977804fba4b6bbea6852ab56c14965a2b0c7fc7282c5f7d90a1ae72",
- "sha256:0f9f3f9a3763b9c4deb8c5d09c4cc52ffe49f9876af41cc1b2ad0138878453cf",
- "sha256:1b56961e2d31389aaadf4906d453859f35302b4eb818d34a26fab72596076bb8",
- "sha256:22b83aed390e3099584b839b93f80a0f4a95ee7f48270c97c90acd40ee646f0b",
- "sha256:25b0f63e7fcc2a6290cb5f7f5b4fc4047843504983a28856ce9b35d8f7de03cc",
- "sha256:2a275a806f73e849e1c309ac11108ea1a14cd7058577aba962cd7190e27c9e3c",
- "sha256:2ab3f0336c0387662ce6221ad30ab3a5e6499aab01b9790879b6578fd9b8faa1",
- "sha256:2e795c2f7d7249b75bb5f479b432a51b59041580d20599d4e112b5f2046437a3",
- "sha256:3655af10ebcc0f1e4e06c5900bb33e080d6a1fa4228f502121f28a3b1753cde5",
- "sha256:4668bd8faf7e5b71c0319407b608f278f279668f358857dbfd10ef1954ac9f90",
- "sha256:4c31943b61ed8fdd63dfd12ccc919f2bf95eefca133767db6fbbd15da62078ec",
- "sha256:4fdcd72a789c1c31ed242fd8c1bcd9ea186a98ee8e5408a50e610edfef980d71",
- "sha256:627dee0c280eea91aed87b20a1f849e9ae2fe719d52cbf847c0e0ea34464b3f7",
- "sha256:67219632be22f14750f0d1c70e62f204ba69d28f62fd6432ba05ab295853de9b",
- "sha256:6921ee01caf375363be5e9ae70d08ce7ca9d7e0e8983183080211a062d299468",
- "sha256:69683e02e8a9de37f17985905a5eca18ad651bf592314b4d3d799029797d0eb3",
- "sha256:6a93c5a0dfe8d34951e8a6f499a9479ffb9258123551fa007fc708ae2ac2bc5e",
- "sha256:732e026240cdd1c1b2e3ac515c7a23820430ed94292ce33806a95869c46bd139",
- "sha256:7befc148de64b6060937231cbff8d01ccf0bfd75aa26383ffdf8d82b12ec04ff",
- "sha256:890da8cd1941fa3dab28c5bac3b9da8502e7e366f895b3b8e500896f12f94d11",
- "sha256:89b64cd8898a3a6f642db4eb7b26d1b28a497d4022eccd7717ca066823e9fb01",
- "sha256:8a6219108a15fc6d24de499d0d515c7235c617b2540d97116b663dade1a54d62",
- "sha256:8cdf1a0dbe5ced887a9b127da4ffd7354e9c1a3b9bb330dce84df6b70ccb3a8d",
- "sha256:8d625eddf7efeba2abfd9c014a22c0f6b3796e0ffb48f5d5ab106568ef01ff5a",
- "sha256:93a71c8601e823236ac0e5d087e4f397874a421017b3318fd92c0b14acf2b6db",
- "sha256:9509c4123491d0e63fb5e16199e09f8e262066e58903e84615c301dde8fa2e87",
- "sha256:a29762cd3d116585278ffb2e5b8cc311fb095ea278b96feef28d0b423154858e",
- "sha256:a62dd5d7cc8626a3634208df458c5fe4f21200d96a74d122c83bc2015b333bc1",
- "sha256:ada603db10bb865bbe591939de854faf2c60f43c9b763e90f653224138f910d9",
- "sha256:aee110e4ef3c528f3abbc3c2018c121e708938adeeff9006428dd7c8555e9b3f",
- "sha256:b76d63495b0508ab9fc23f8152bac63205d2a704cd009a2b0722f4c8e0cba8e0",
- "sha256:c0d8326269dbf944b9201911b0d9f3dc524d64779a07518199a58384c3d37a44",
- "sha256:c41411e192f8d3ea39ea70e0fae48762cd11a2244e03751a98bd3c0ca9a4e936",
- "sha256:c68fe3fcde03920c46697585620135b4ecfdfc1ed23e75cc2c2ae9f8502c10b8",
- "sha256:cb8bea573863762bbf45d1e13f87c2d2fd32cee2dbd50d050f83f87429c9e1ea",
- "sha256:cc32b2990fc34380ec2f6195f33a76b6cdaa9eecf09f0c9404b74fc120aef36f",
- "sha256:ccae5de2a0140d8be6838c331604f91d6fafd0735dbdcee1ac78fc8fbaba76b4",
- "sha256:d299797d75cd747e7797b1b41817111406b8b10a4f88b6e8fe5b5e59598b43b0",
- "sha256:e04b622bb8a88f10e439084486f2f6349bf4d50605ac3e445869c7ea5cf0fa8c",
- "sha256:e11d7ea4d24f0a262bccf9a7cd6284c976c5369dac21db237cff59586045ab9f",
- "sha256:e21f66748ab725ade40fa7af8ec8b5019c68ab00b929f6643e1b1af461eddb60",
- "sha256:eb60b026d8ad0c97917cb81d3662d0b39b8ff1335e3fabb24984c6acd0c900a2",
- "sha256:f021d334f2ca692523aaf7bbf7592ceff70c8594fad853416a81d66b35e3abf9",
- "sha256:f552023710d4b93d8fb29a91fadf97de89c5926c6bd758897875435f2a939f33"
+ "sha256:03e08af7a5f9386a43919eda9de33ffda16b44eb11f3b313e6822243770e9763",
+ "sha256:0572f4bd6f94752167adfd7c1bed84f4b240ee6203a95e05d1e208d488d0d436",
+ "sha256:07b441f7d03b9a66299ce7ccf3ef2900abc81c0db434f42a5694a37bd73870f2",
+ "sha256:1bc330d9d29c7f06f003ab10e1eaced295e87940405afe1b110f2eb93a233588",
+ "sha256:1e0d612a17581b6616ff03c8e3d5eff7452f34655c901f75d62bd86449d9750e",
+ "sha256:23623166bfefe1487d81b698c423f8678e80df8b54614c2bf4b4cfcd7c711959",
+ "sha256:2519f3a5d0517fc159afab1015e54bb81b4406c278749779be57a569d8d1bb0d",
+ "sha256:28120ef39c92c2dd60f2721af9328479516844c6b550b077ca450c7d7dc68575",
+ "sha256:37350015056a553e442ff672c2d20e6f4b6d0b2495691fa239d8aa18bb3bc908",
+ "sha256:39769a115f730d683b0eb7b694db9789267bcd027326cccc3125e862eb03bfd8",
+ "sha256:3c01117dd36800f2ecaa238c65365b7b16497adc1522bf84906e5710ee9ba0e8",
+ "sha256:3d6718667da04294d7df1670d70eeddd414f313738d20a6f1d1f379e3139a545",
+ "sha256:3dbb986bad3ed5ceaf090200eba750b5245150bd97d3e67343a3cfed06feecf7",
+ "sha256:4557e1f11c5f653ebfdd924f3f9d5ebfc718283b0b9beebaa5dd6b77ec290971",
+ "sha256:46331b00096a6db1fdc052d55b101dbbfc99155a548e20a0e4a8e5e4d1362855",
+ "sha256:4a121d62ebe7d26fec9155f83f8be5189ef1405f5973ea4874a26fab9f1e262c",
+ "sha256:4f5e9cd989b45b73bd359f693b935364f7e1f79486e29015813c338450aa5a71",
+ "sha256:50aae840ebbd6cdd41af1c14590e5741665e5272d2fee999306673a1bb1fdb4d",
+ "sha256:59b1ee96617135f6e1d6f275bbe988f419c5178016f3d41d3c0abb0c819f75bb",
+ "sha256:59b8f3adb3971929a3e660337f5dacc5942c2cdb760afcabb2614ffbda9f9f72",
+ "sha256:66bffbad8d6271bb1cc2f9a4ea4f86f80fe5e2e3e501a5ae2a3dc6a76e604e6f",
+ "sha256:69f93723edbca7342624d09f6704e7126b152eaed3cdbb634cb657a54332a3c5",
+ "sha256:6a440293d802d3011028e14e4226da1434b373cbaf4a4bbb63f845761a708346",
+ "sha256:72c28b84b174ce8af8504ca28ae9347d317f9dba3999e5981a3cd441f3712e24",
+ "sha256:79d2e78abc26d871875b419e1fd3c0bca31a1cb0043277d0d850014599626c2e",
+ "sha256:7f2767680b6d2398aea7082e45a774b2b0767b5c8d8ffb9c8b683088ea9b29c5",
+ "sha256:8318f4776c85abc3f40ab185e388bee7a6ea99e7fa3a30686580b209eaa35c08",
+ "sha256:8958b10490125124463095bbdadda5aa22ec799f91958e410438ad6c97a7b793",
+ "sha256:8c78ac40bde930c60e0f78b3cd184c580f89456dd87fc08f9e3ee3ce8765ce88",
+ "sha256:90812a8933df713fdf748b355527e3af257a11e415b613dd794512461eb8a686",
+ "sha256:9bc633f4ee4b4c46e7adcb3a9b5ec083bf1d9a97c1d3854b92749d935de40b9b",
+ "sha256:9e46ed38affdfc95d2c958de328d037d87801cfcbea6d421000859e9789e61c2",
+ "sha256:9fe53b404f24789b5ea9003fc25b9a3988feddebd7e7b369c8fac27ad6f52f28",
+ "sha256:a4e46a888b54be23d03a89be510f24a7652fe6ff660787b96cd0e57a4ebcb46d",
+ "sha256:a86bfab2ef46d63300c0f06936bd6e6c0105faa11d509083ba8f2f9d237fb5b5",
+ "sha256:ac9dfa18ff2a67b09b372d5db8743c27966abf0e5344c555d86cc7199f7ad83a",
+ "sha256:af148a33ff0349f53512a049c6406923e4e02bf2f26c5fb285f143faf4f0e46a",
+ "sha256:b11d0cfdd2b095e7b0686cf5fabeb9c67fae5b06d265d8180715b8cfa86522e3",
+ "sha256:b2985c0b06e989c043f1dc09d4fe89e1616aadd35392aea2844f0458a989eacf",
+ "sha256:b544ad1935a8541d177cb402948b94e871067656b3a0b9e91dbec136b06a2ff5",
+ "sha256:b5cc79df7f4bc3d11e4b542596c03826063092611e481fcf1c9dfee3c94355ef",
+ "sha256:b817d41d692bf286abc181f8af476c4fbef3fd05e798777492618378448ee689",
+ "sha256:b81ee3d84803fd42d0b154cb6892ae57ea6b7c55d8359a02379965706c7efe6c",
+ "sha256:be9812b766cad94a25bc63bec11f88c4ad3629a0cec1cd5d4ba48dc23860486b",
+ "sha256:c245b1fbade9c35e5bd3b64270ab49ce990369018289ecfde3f9c318411aaa07",
+ "sha256:c3f3631693003d8e585d4200730616b78fafd5a01ef8b698f6967da5c605b3fa",
+ "sha256:c4ae3005ed83f5967f961fd091f2f8c5329161f69ce8480aa8168b2d7fe37f06",
+ "sha256:c54a1e53a0c308a8e8a7dffb59097bff7facda27c70c286f005327f21b2bd6b1",
+ "sha256:d0ddd9db6e59c44875211bc4c7953a9f6638b937b0a88ae6d09eb46cced54eff",
+ "sha256:dc022184d3e5cacc9579e41805a681187650e170eb2fd70e28b86192a479dcaa",
+ "sha256:e32092c47011d113dc01ab3e1d3ce9f006a47223b18422c5c0d150af13a00687",
+ "sha256:f7b64e6ec3f02c35647be6b4851008b26cff592a95ecb13b6788a54ef80bbdd4",
+ "sha256:f942a799516184c855e1a32fbc7b29d7e571b52612647866d4ec1c3242578fcb",
+ "sha256:f9511d8dd4a6e9271d07d150fb2f81874a3c8c95e11ff9af3a2dfc35fe42ee44",
+ "sha256:fd3a55deef00f689ce931d4d1b23fa9f04c880a48ee97af488fd215cf24e2a6c",
+ "sha256:fddbe92b4760c6f5d48162aef14824add991aeda8ddadb3c31d56eb15ca69f8e",
+ "sha256:fdf3386a801ea5aba17c6410dd1dc8d39cf454ca2565541b5ac42a84e1e28f53"
],
"markers": "python_version >= '3.7'",
- "version": "==2.0.35"
+ "version": "==2.0.36"
},
"starlette": {
"hashes": [
@@ -2068,19 +2169,19 @@
},
"tqdm": {
"hashes": [
- "sha256:90279a3770753eafc9194a0364852159802111925aa30eb3f9d85b0e805ac7cd",
- "sha256:e1020aef2e5096702d8a025ac7d16b1577279c9d63f8375b63083e9a5f0fcbad"
+ "sha256:0cd8af9d56911acab92182e88d763100d4788bdf421d251616040cc4d44863be",
+ "sha256:fe5a6f95e6fe0b9755e9469b77b9c3cf850048224ecaa8293d7d2d31f97d869a"
],
"markers": "python_version >= '3.7'",
- "version": "==4.66.5"
+ "version": "==4.67.0"
},
"typer": {
"hashes": [
- "sha256:62fe4e471711b147e3365034133904df3e235698399bc4de2b36c8579298d52b",
- "sha256:f592f089bedcc8ec1b974125d64851029c3b1af145f04aca64d69410f0c9b722"
+ "sha256:d85fe0b777b2517cc99c8055ed735452f2659cd45e451507c76f48ce5c1d00e2",
+ "sha256:f1c7198347939361eec90139ffa0fd8b3df3a2259d5852a0f7400e476d95985c"
],
"markers": "python_version >= '3.7'",
- "version": "==0.12.5"
+ "version": "==0.13.0"
},
"typing-extensions": {
"hashes": [
@@ -2202,47 +2303,53 @@
"standard"
],
"hashes": [
- "sha256:13bc21373d103859f68fe739608e2eb054a816dea79189bc3ca08ea89a275906",
- "sha256:cac7be4dd4d891c363cd942160a7b02e69150dcbc7a36be04d5f4af4b17c8ced"
+ "sha256:60b8f3a5ac027dcd31448f411ced12b5ef452c646f76f02f8cc3f25d8d26fd82",
+ "sha256:f78b36b143c16f54ccdb8190d0a26b5f1901fe5a3c777e1ab29f26391af8551e"
],
"markers": "python_version >= '3.8'",
- "version": "==0.31.0"
+ "version": "==0.32.0"
},
"uvloop": {
"hashes": [
- "sha256:265a99a2ff41a0fd56c19c3838b29bf54d1d177964c300dad388b27e84fd7847",
- "sha256:2beee18efd33fa6fdb0976e18475a4042cd31c7433c866e8a09ab604c7c22ff2",
- "sha256:35968fc697b0527a06e134999eef859b4034b37aebca537daeb598b9d45a137b",
- "sha256:36c530d8fa03bfa7085af54a48f2ca16ab74df3ec7108a46ba82fd8b411a2315",
- "sha256:3a609780e942d43a275a617c0839d85f95c334bad29c4c0918252085113285b5",
- "sha256:4603ca714a754fc8d9b197e325db25b2ea045385e8a3ad05d3463de725fdf469",
- "sha256:4b75f2950ddb6feed85336412b9a0c310a2edbcf4cf931aa5cfe29034829676d",
- "sha256:4f44af67bf39af25db4c1ac27e82e9665717f9c26af2369c404be865c8818dcf",
- "sha256:6462c95f48e2d8d4c993a2950cd3d31ab061864d1c226bbf0ee2f1a8f36674b9",
- "sha256:649c33034979273fa71aa25d0fe120ad1777c551d8c4cd2c0c9851d88fcb13ab",
- "sha256:746242cd703dc2b37f9d8b9f173749c15e9a918ddb021575a0205ec29a38d31e",
- "sha256:77fbc69c287596880ecec2d4c7a62346bef08b6209749bf6ce8c22bbaca0239e",
- "sha256:80dc1b139516be2077b3e57ce1cb65bfed09149e1d175e0478e7a987863b68f0",
- "sha256:82edbfd3df39fb3d108fc079ebc461330f7c2e33dbd002d146bf7c445ba6e756",
- "sha256:89e8d33bb88d7263f74dc57d69f0063e06b5a5ce50bb9a6b32f5fcbe655f9e73",
- "sha256:94707205efbe809dfa3a0d09c08bef1352f5d3d6612a506f10a319933757c006",
- "sha256:95720bae002ac357202e0d866128eb1ac82545bcf0b549b9abe91b5178d9b541",
- "sha256:9b04d96188d365151d1af41fa2d23257b674e7ead68cfd61c725a422764062ae",
- "sha256:9d0fba61846f294bce41eb44d60d58136090ea2b5b99efd21cbdf4e21927c56a",
- "sha256:9ebafa0b96c62881d5cafa02d9da2e44c23f9f0cd829f3a32a6aff771449c996",
- "sha256:a0fac7be202596c7126146660725157d4813aa29a4cc990fe51346f75ff8fde7",
- "sha256:aea15c78e0d9ad6555ed201344ae36db5c63d428818b4b2a42842b3870127c00",
- "sha256:b10c2956efcecb981bf9cfb8184d27d5d64b9033f917115a960b83f11bfa0d6b",
- "sha256:b16696f10e59d7580979b420eedf6650010a4a9c3bd8113f24a103dfdb770b10",
- "sha256:d8c36fdf3e02cec92aed2d44f63565ad1522a499c654f07935c8f9d04db69e95",
- "sha256:e237f9c1e8a00e7d9ddaa288e535dc337a39bcbf679f290aee9d26df9e72bce9",
- "sha256:e50289c101495e0d1bb0bfcb4a60adde56e32f4449a67216a1ab2750aa84f037",
- "sha256:e7d61fe8e8d9335fac1bf8d5d82820b4808dd7a43020c149b63a1ada953d48a6",
- "sha256:e97152983442b499d7a71e44f29baa75b3b02e65d9c44ba53b10338e98dedb66",
- "sha256:f0e94b221295b5e69de57a1bd4aeb0b3a29f61be6e1b478bb8a69a73377db7ba",
- "sha256:fee6044b64c965c425b65a4e17719953b96e065c5b7e09b599ff332bb2744bdf"
- ],
- "version": "==0.20.0"
+ "sha256:0878c2640cf341b269b7e128b1a5fed890adc4455513ca710d77d5e93aa6d6a0",
+ "sha256:10d66943def5fcb6e7b37310eb6b5639fd2ccbc38df1177262b0640c3ca68c1f",
+ "sha256:10da8046cc4a8f12c91a1c39d1dd1585c41162a15caaef165c2174db9ef18bdc",
+ "sha256:17df489689befc72c39a08359efac29bbee8eee5209650d4b9f34df73d22e414",
+ "sha256:183aef7c8730e54c9a3ee3227464daed66e37ba13040bb3f350bc2ddc040f22f",
+ "sha256:196274f2adb9689a289ad7d65700d37df0c0930fd8e4e743fa4834e850d7719d",
+ "sha256:221f4f2a1f46032b403bf3be628011caf75428ee3cc204a22addf96f586b19fd",
+ "sha256:2d1f581393673ce119355d56da84fe1dd9d2bb8b3d13ce792524e1607139feff",
+ "sha256:359ec2c888397b9e592a889c4d72ba3d6befba8b2bb01743f72fffbde663b59c",
+ "sha256:3bf12b0fda68447806a7ad847bfa591613177275d35b6724b1ee573faa3704e3",
+ "sha256:4509360fcc4c3bd2c70d87573ad472de40c13387f5fda8cb58350a1d7475e58d",
+ "sha256:460def4412e473896ef179a1671b40c039c7012184b627898eea5072ef6f017a",
+ "sha256:461d9ae6660fbbafedd07559c6a2e57cd553b34b0065b6550685f6653a98c1cb",
+ "sha256:46923b0b5ee7fc0020bef24afe7836cb068f5050ca04caf6b487c513dc1a20b2",
+ "sha256:53e420a3afe22cdcf2a0f4846e377d16e718bc70103d7088a4f7623567ba5fb0",
+ "sha256:5ee4d4ef48036ff6e5cfffb09dd192c7a5027153948d85b8da7ff705065bacc6",
+ "sha256:67dd654b8ca23aed0a8e99010b4c34aca62f4b7fce88f39d452ed7622c94845c",
+ "sha256:787ae31ad8a2856fc4e7c095341cccc7209bd657d0e71ad0dc2ea83c4a6fa8af",
+ "sha256:86975dca1c773a2c9864f4c52c5a55631038e387b47eaf56210f873887b6c8dc",
+ "sha256:87c43e0f13022b998eb9b973b5e97200c8b90823454d4bc06ab33829e09fb9bb",
+ "sha256:88cb67cdbc0e483da00af0b2c3cdad4b7c61ceb1ee0f33fe00e09c81e3a6cb75",
+ "sha256:8a375441696e2eda1c43c44ccb66e04d61ceeffcd76e4929e527b7fa401b90fb",
+ "sha256:a5c39f217ab3c663dc699c04cbd50c13813e31d917642d459fdcec07555cc553",
+ "sha256:b9fb766bb57b7388745d8bcc53a359b116b8a04c83a2288069809d2b3466c37e",
+ "sha256:baa0e6291d91649c6ba4ed4b2f982f9fa165b5bbd50a9e203c416a2797bab3c6",
+ "sha256:baa4dcdbd9ae0a372f2167a207cd98c9f9a1ea1188a8a526431eef2f8116cc8d",
+ "sha256:bc09f0ff191e61c2d592a752423c767b4ebb2986daa9ed62908e2b1b9a9ae206",
+ "sha256:bd53ecc9a0f3d87ab847503c2e1552b690362e005ab54e8a48ba97da3924c0dc",
+ "sha256:bfd55dfcc2a512316e65f16e503e9e450cab148ef11df4e4e679b5e8253a5281",
+ "sha256:c097078b8031190c934ed0ebfee8cc5f9ba9642e6eb88322b9958b649750f72b",
+ "sha256:c0f3fa6200b3108919f8bdabb9a7f87f20e7097ea3c543754cabc7d717d95cf8",
+ "sha256:e678ad6fe52af2c58d2ae3c73dc85524ba8abe637f134bf3564ed07f555c5e79",
+ "sha256:ec7e6b09a6fdded42403182ab6b832b71f4edaf7f37a9a0e371a01db5f0cb45f",
+ "sha256:f0ce1b49560b1d2d8a2977e3ba4afb2414fb46b86a1b64056bc4ab929efdafbe",
+ "sha256:f38b2e090258d051d68a5b14d1da7203a3c3677321cf32a95a6f4db4dd8b6f26",
+ "sha256:f3df876acd7ec037a3d005b3ab85a7e4110422e4d9c1571d4fc89b0fc41b6816",
+ "sha256:f7089d2dc73179ce5ac255bdf37c236a9f914b264825fdaacaded6990a7fb4c2"
+ ],
+ "version": "==0.21.0"
},
"watchfiles": {
"hashes": [
@@ -2334,94 +2441,77 @@
},
"websockets": {
"hashes": [
- "sha256:004280a140f220c812e65f36944a9ca92d766b6cc4560be652a0a3883a79ed8a",
- "sha256:035233b7531fb92a76beefcbf479504db8c72eb3bff41da55aecce3a0f729e54",
- "sha256:149e622dc48c10ccc3d2760e5f36753db9cacf3ad7bc7bbbfd7d9c819e286f23",
- "sha256:163e7277e1a0bd9fb3c8842a71661ad19c6aa7bb3d6678dc7f89b17fbcc4aeb7",
- "sha256:18503d2c5f3943e93819238bf20df71982d193f73dcecd26c94514f417f6b135",
- "sha256:1971e62d2caa443e57588e1d82d15f663b29ff9dfe7446d9964a4b6f12c1e700",
- "sha256:204e5107f43095012b00f1451374693267adbb832d29966a01ecc4ce1db26faf",
- "sha256:2510c09d8e8df777177ee3d40cd35450dc169a81e747455cc4197e63f7e7bfe5",
- "sha256:25c35bf84bf7c7369d247f0b8cfa157f989862c49104c5cf85cb5436a641d93e",
- "sha256:2f85cf4f2a1ba8f602298a853cec8526c2ca42a9a4b947ec236eaedb8f2dc80c",
- "sha256:308e20f22c2c77f3f39caca508e765f8725020b84aa963474e18c59accbf4c02",
- "sha256:325b1ccdbf5e5725fdcb1b0e9ad4d2545056479d0eee392c291c1bf76206435a",
- "sha256:327b74e915cf13c5931334c61e1a41040e365d380f812513a255aa804b183418",
- "sha256:346bee67a65f189e0e33f520f253d5147ab76ae42493804319b5716e46dddf0f",
- "sha256:38377f8b0cdeee97c552d20cf1865695fcd56aba155ad1b4ca8779a5b6ef4ac3",
- "sha256:3c78383585f47ccb0fcf186dcb8a43f5438bd7d8f47d69e0b56f71bf431a0a68",
- "sha256:4059f790b6ae8768471cddb65d3c4fe4792b0ab48e154c9f0a04cefaabcd5978",
- "sha256:459bf774c754c35dbb487360b12c5727adab887f1622b8aed5755880a21c4a20",
- "sha256:463e1c6ec853202dd3657f156123d6b4dad0c546ea2e2e38be2b3f7c5b8e7295",
- "sha256:4676df3fe46956fbb0437d8800cd5f2b6d41143b6e7e842e60554398432cf29b",
- "sha256:485307243237328c022bc908b90e4457d0daa8b5cf4b3723fd3c4a8012fce4c6",
- "sha256:48a2ef1381632a2f0cb4efeff34efa97901c9fbc118e01951ad7cfc10601a9bb",
- "sha256:4b889dbd1342820cc210ba44307cf75ae5f2f96226c0038094455a96e64fb07a",
- "sha256:586a356928692c1fed0eca68b4d1c2cbbd1ca2acf2ac7e7ebd3b9052582deefa",
- "sha256:58cf7e75dbf7e566088b07e36ea2e3e2bd5676e22216e4cad108d4df4a7402a0",
- "sha256:5993260f483d05a9737073be197371940c01b257cc45ae3f1d5d7adb371b266a",
- "sha256:5dd6da9bec02735931fccec99d97c29f47cc61f644264eb995ad6c0c27667238",
- "sha256:5f2e75431f8dc4a47f31565a6e1355fb4f2ecaa99d6b89737527ea917066e26c",
- "sha256:5f9fee94ebafbc3117c30be1844ed01a3b177bb6e39088bc6b2fa1dc15572084",
- "sha256:61fc0dfcda609cda0fc9fe7977694c0c59cf9d749fbb17f4e9483929e3c48a19",
- "sha256:624459daabeb310d3815b276c1adef475b3e6804abaf2d9d2c061c319f7f187d",
- "sha256:62d516c325e6540e8a57b94abefc3459d7dab8ce52ac75c96cad5549e187e3a7",
- "sha256:6548f29b0e401eea2b967b2fdc1c7c7b5ebb3eeb470ed23a54cd45ef078a0db9",
- "sha256:6d2aad13a200e5934f5a6767492fb07151e1de1d6079c003ab31e1823733ae79",
- "sha256:6d6855bbe70119872c05107e38fbc7f96b1d8cb047d95c2c50869a46c65a8e96",
- "sha256:70c5be9f416aa72aab7a2a76c90ae0a4fe2755c1816c153c1a2bcc3333ce4ce6",
- "sha256:730f42125ccb14602f455155084f978bd9e8e57e89b569b4d7f0f0c17a448ffe",
- "sha256:7a43cfdcddd07f4ca2b1afb459824dd3c6d53a51410636a2c7fc97b9a8cf4842",
- "sha256:7bd6abf1e070a6b72bfeb71049d6ad286852e285f146682bf30d0296f5fbadfa",
- "sha256:7c1e90228c2f5cdde263253fa5db63e6653f1c00e7ec64108065a0b9713fa1b3",
- "sha256:7c65ffa900e7cc958cd088b9a9157a8141c991f8c53d11087e6fb7277a03f81d",
- "sha256:80c421e07973a89fbdd93e6f2003c17d20b69010458d3a8e37fb47874bd67d51",
- "sha256:82d0ba76371769d6a4e56f7e83bb8e81846d17a6190971e38b5de108bde9b0d7",
- "sha256:83f91d8a9bb404b8c2c41a707ac7f7f75b9442a0a876df295de27251a856ad09",
- "sha256:87c6e35319b46b99e168eb98472d6c7d8634ee37750d7693656dc766395df096",
- "sha256:8d23b88b9388ed85c6faf0e74d8dec4f4d3baf3ecf20a65a47b836d56260d4b9",
- "sha256:9156c45750b37337f7b0b00e6248991a047be4aa44554c9886fe6bdd605aab3b",
- "sha256:91a0fa841646320ec0d3accdff5b757b06e2e5c86ba32af2e0815c96c7a603c5",
- "sha256:95858ca14a9f6fa8413d29e0a585b31b278388aa775b8a81fa24830123874678",
- "sha256:95df24ca1e1bd93bbca51d94dd049a984609687cb2fb08a7f2c56ac84e9816ea",
- "sha256:9b37c184f8b976f0c0a231a5f3d6efe10807d41ccbe4488df8c74174805eea7d",
- "sha256:9b6f347deb3dcfbfde1c20baa21c2ac0751afaa73e64e5b693bb2b848efeaa49",
- "sha256:9d75baf00138f80b48f1eac72ad1535aac0b6461265a0bcad391fc5aba875cfc",
- "sha256:9ef8aa8bdbac47f4968a5d66462a2a0935d044bf35c0e5a8af152d58516dbeb5",
- "sha256:a11e38ad8922c7961447f35c7b17bffa15de4d17c70abd07bfbe12d6faa3e027",
- "sha256:a1b54689e38d1279a51d11e3467dd2f3a50f5f2e879012ce8f2d6943f00e83f0",
- "sha256:a3b3366087c1bc0a2795111edcadddb8b3b59509d5db5d7ea3fdd69f954a8878",
- "sha256:a569eb1b05d72f9bce2ebd28a1ce2054311b66677fcd46cf36204ad23acead8c",
- "sha256:a7affedeb43a70351bb811dadf49493c9cfd1ed94c9c70095fd177e9cc1541fa",
- "sha256:a9a396a6ad26130cdae92ae10c36af09d9bfe6cafe69670fd3b6da9b07b4044f",
- "sha256:a9ab1e71d3d2e54a0aa646ab6d4eebfaa5f416fe78dfe4da2839525dc5d765c6",
- "sha256:a9cd1af7e18e5221d2878378fbc287a14cd527fdd5939ed56a18df8a31136bb2",
- "sha256:a9dcaf8b0cc72a392760bb8755922c03e17a5a54e08cca58e8b74f6902b433cf",
- "sha256:b9d7439d7fab4dce00570bb906875734df13d9faa4b48e261c440a5fec6d9708",
- "sha256:bcc03c8b72267e97b49149e4863d57c2d77f13fae12066622dc78fe322490fe6",
- "sha256:c11d4d16e133f6df8916cc5b7e3e96ee4c44c936717d684a94f48f82edb7c92f",
- "sha256:c1dca61c6db1166c48b95198c0b7d9c990b30c756fc2923cc66f68d17dc558fd",
- "sha256:c518e84bb59c2baae725accd355c8dc517b4a3ed8db88b4bc93c78dae2974bf2",
- "sha256:c7934fd0e920e70468e676fe7f1b7261c1efa0d6c037c6722278ca0228ad9d0d",
- "sha256:c7e72ce6bda6fb9409cc1e8164dd41d7c91466fb599eb047cfda72fe758a34a7",
- "sha256:c90d6dec6be2c7d03378a574de87af9b1efea77d0c52a8301dd831ece938452f",
- "sha256:ceec59f59d092c5007e815def4ebb80c2de330e9588e101cf8bd94c143ec78a5",
- "sha256:cf1781ef73c073e6b0f90af841aaf98501f975d306bbf6221683dd594ccc52b6",
- "sha256:d04f13a1d75cb2b8382bdc16ae6fa58c97337253826dfe136195b7f89f661557",
- "sha256:d6d300f8ec35c24025ceb9b9019ae9040c1ab2f01cddc2bcc0b518af31c75c14",
- "sha256:d8dbb1bf0c0a4ae8b40bdc9be7f644e2f3fb4e8a9aca7145bfa510d4a374eeb7",
- "sha256:de58647e3f9c42f13f90ac7e5f58900c80a39019848c5547bc691693098ae1bd",
- "sha256:deeb929efe52bed518f6eb2ddc00cc496366a14c726005726ad62c2dd9017a3c",
- "sha256:df01aea34b6e9e33572c35cd16bae5a47785e7d5c8cb2b54b2acdb9678315a17",
- "sha256:e2620453c075abeb0daa949a292e19f56de518988e079c36478bacf9546ced23",
- "sha256:e4450fc83a3df53dec45922b576e91e94f5578d06436871dce3a6be38e40f5db",
- "sha256:e54affdeb21026329fb0744ad187cf812f7d3c2aa702a5edb562b325191fcab6",
- "sha256:e9875a0143f07d74dc5e1ded1c4581f0d9f7ab86c78994e2ed9e95050073c94d",
- "sha256:f1c3cf67185543730888b20682fb186fc8d0fa6f07ccc3ef4390831ab4b388d9",
- "sha256:f48c749857f8fb598fb890a75f540e3221d0976ed0bf879cf3c7eef34151acee",
- "sha256:f779498eeec470295a2b1a5d97aa1bc9814ecd25e1eb637bd9d1c73a327387f6"
- ],
- "version": "==13.1"
+ "sha256:00fe5da3f037041da1ee0cf8e308374e236883f9842c7c465aa65098b1c9af59",
+ "sha256:01bb2d4f0a6d04538d3c5dfd27c0643269656c28045a53439cbf1c004f90897a",
+ "sha256:034feb9f4286476f273b9a245fb15f02c34d9586a5bc936aff108c3ba1b21beb",
+ "sha256:04a97aca96ca2acedf0d1f332c861c5a4486fdcba7bcef35873820f940c4231e",
+ "sha256:0d4290d559d68288da9f444089fd82490c8d2744309113fc26e2da6e48b65da6",
+ "sha256:1288369a6a84e81b90da5dbed48610cd7e5d60af62df9851ed1d1d23a9069f10",
+ "sha256:14839f54786987ccd9d03ed7f334baec0f02272e7ec4f6e9d427ff584aeea8b4",
+ "sha256:1d045cbe1358d76b24d5e20e7b1878efe578d9897a25c24e6006eef788c0fdf0",
+ "sha256:1f874ba705deea77bcf64a9da42c1f5fc2466d8f14daf410bc7d4ceae0a9fcb0",
+ "sha256:205f672a6c2c671a86d33f6d47c9b35781a998728d2c7c2a3e1cf3333fcb62b7",
+ "sha256:2177ee3901075167f01c5e335a6685e71b162a54a89a56001f1c3e9e3d2ad250",
+ "sha256:219c8187b3ceeadbf2afcf0f25a4918d02da7b944d703b97d12fb01510869078",
+ "sha256:25225cc79cfebc95ba1d24cd3ab86aaa35bcd315d12fa4358939bd55e9bd74a5",
+ "sha256:3630b670d5057cd9e08b9c4dab6493670e8e762a24c2c94ef312783870736ab9",
+ "sha256:368a05465f49c5949e27afd6fbe0a77ce53082185bbb2ac096a3a8afaf4de52e",
+ "sha256:36ebd71db3b89e1f7b1a5deaa341a654852c3518ea7a8ddfdf69cc66acc2db1b",
+ "sha256:39450e6215f7d9f6f7bc2a6da21d79374729f5d052333da4d5825af8a97e6735",
+ "sha256:398b10c77d471c0aab20a845e7a60076b6390bfdaac7a6d2edb0d2c59d75e8d8",
+ "sha256:3c3deac3748ec73ef24fc7be0b68220d14d47d6647d2f85b2771cb35ea847aa1",
+ "sha256:3f14a96a0034a27f9d47fd9788913924c89612225878f8078bb9d55f859272b0",
+ "sha256:3fc753451d471cff90b8f467a1fc0ae64031cf2d81b7b34e1811b7e2691bc4bc",
+ "sha256:414ffe86f4d6f434a8c3b7913655a1a5383b617f9bf38720e7c0799fac3ab1c6",
+ "sha256:449d77d636f8d9c17952628cc7e3b8faf6e92a17ec581ec0c0256300717e1512",
+ "sha256:4b6caec8576e760f2c7dd878ba817653144d5f369200b6ddf9771d64385b84d4",
+ "sha256:4d4fc827a20abe6d544a119896f6b78ee13fe81cbfef416f3f2ddf09a03f0e2e",
+ "sha256:5a42d3ecbb2db5080fc578314439b1d79eef71d323dc661aa616fb492436af5d",
+ "sha256:5b918d288958dc3fa1c5a0b9aa3256cb2b2b84c54407f4813c45d52267600cd3",
+ "sha256:5ef440054124728cc49b01c33469de06755e5a7a4e83ef61934ad95fc327fbb0",
+ "sha256:660c308dabd2b380807ab64b62985eaccf923a78ebc572bd485375b9ca2b7dc7",
+ "sha256:6a6c9bcf7cdc0fd41cc7b7944447982e8acfd9f0d560ea6d6845428ed0562058",
+ "sha256:6d24fc337fc055c9e83414c94e1ee0dee902a486d19d2a7f0929e49d7d604b09",
+ "sha256:7048eb4415d46368ef29d32133134c513f507fff7d953c18c91104738a68c3b3",
+ "sha256:77569d19a13015e840b81550922056acabc25e3f52782625bc6843cfa034e1da",
+ "sha256:8149a0f5a72ca36720981418eeffeb5c2729ea55fa179091c81a0910a114a5d2",
+ "sha256:836bef7ae338a072e9d1863502026f01b14027250a4545672673057997d5c05a",
+ "sha256:8621a07991add373c3c5c2cf89e1d277e49dc82ed72c75e3afc74bd0acc446f0",
+ "sha256:87e31011b5c14a33b29f17eb48932e63e1dcd3fa31d72209848652310d3d1f0d",
+ "sha256:88cf9163ef674b5be5736a584c999e98daf3aabac6e536e43286eb74c126b9c7",
+ "sha256:8fda642151d5affdee8a430bd85496f2e2517be3a2b9d2484d633d5712b15c56",
+ "sha256:90b5d9dfbb6d07a84ed3e696012610b6da074d97453bd01e0e30744b472c8179",
+ "sha256:90f4c7a069c733d95c308380aae314f2cb45bd8a904fb03eb36d1a4983a4993f",
+ "sha256:9481a6de29105d73cf4515f2bef8eb71e17ac184c19d0b9918a3701c6c9c4f23",
+ "sha256:9607b9a442392e690a57909c362811184ea429585a71061cd5d3c2b98065c199",
+ "sha256:9777564c0a72a1d457f0848977a1cbe15cfa75fa2f67ce267441e465717dcf1a",
+ "sha256:a032855dc7db987dff813583d04f4950d14326665d7e714d584560b140ae6b8b",
+ "sha256:a0adf84bc2e7c86e8a202537b4fd50e6f7f0e4a6b6bf64d7ccb96c4cd3330b29",
+ "sha256:a35f704be14768cea9790d921c2c1cc4fc52700410b1c10948511039be824aac",
+ "sha256:a3dfff83ca578cada2d19e665e9c8368e1598d4e787422a460ec70e531dbdd58",
+ "sha256:a4c805c6034206143fbabd2d259ec5e757f8b29d0a2f0bf3d2fe5d1f60147a4a",
+ "sha256:a655bde548ca98f55b43711b0ceefd2a88a71af6350b0c168aa77562104f3f45",
+ "sha256:ad2ab2547761d79926effe63de21479dfaf29834c50f98c4bf5b5480b5838434",
+ "sha256:b1f3628a0510bd58968c0f60447e7a692933589b791a6b572fcef374053ca280",
+ "sha256:b7e7ea2f782408c32d86b87a0d2c1fd8871b0399dd762364c731d86c86069a78",
+ "sha256:bc6ccf7d54c02ae47a48ddf9414c54d48af9c01076a2e1023e3b486b6e72c707",
+ "sha256:bea45f19b7ca000380fbd4e02552be86343080120d074b87f25593ce1700ad58",
+ "sha256:cc1fc87428c1d18b643479caa7b15db7d544652e5bf610513d4a3478dbe823d0",
+ "sha256:cd7c11968bc3860d5c78577f0dbc535257ccec41750675d58d8dc66aa47fe52c",
+ "sha256:ceada5be22fa5a5a4cdeec74e761c2ee7db287208f54c718f2df4b7e200b8d4a",
+ "sha256:cf5201a04550136ef870aa60ad3d29d2a59e452a7f96b94193bee6d73b8ad9a9",
+ "sha256:d9fd19ecc3a4d5ae82ddbfb30962cf6d874ff943e56e0c81f5169be2fda62979",
+ "sha256:ddaa4a390af911da6f680be8be4ff5aaf31c4c834c1a9147bc21cbcbca2d4370",
+ "sha256:df174ece723b228d3e8734a6f2a6febbd413ddec39b3dc592f5a4aa0aff28098",
+ "sha256:e0744623852f1497d825a49a99bfbec9bea4f3f946df6eb9d8a2f0c37a2fec2e",
+ "sha256:e5dc25a9dbd1a7f61eca4b7cb04e74ae4b963d658f9e4f9aad9cd00b688692c8",
+ "sha256:e7591d6f440af7f73c4bd9404f3772bfee064e639d2b6cc8c94076e71b2471c1",
+ "sha256:eb6d38971c800ff02e4a6afd791bbe3b923a9a57ca9aeab7314c21c84bf9ff05",
+ "sha256:ed907449fe5e021933e46a3e65d651f641975a768d0649fee59f10c2985529ed",
+ "sha256:f6cf0ad281c979306a6a34242b371e90e891bce504509fb6bb5246bbbf31e7b6",
+ "sha256:f95ba34d71e2fa0c5d225bde3b3bdb152e957150100e75c86bc7f3964c450d89"
+ ],
+ "version": "==14.1"
},
"wrapt": {
"hashes": [
@@ -2501,117 +2591,107 @@
},
"xmltodict": {
"hashes": [
- "sha256:341595a488e3e01a85a9d8911d8912fd922ede5fecc4dce437eb4b6c8d037e56",
- "sha256:aa89e8fd76320154a40d19a0df04a4695fb9dc5ba977cbb68ab3e4eb225e7852"
+ "sha256:201e7c28bb210e374999d1dde6382923ab0ed1a8a5faeece48ab525b7810a553",
+ "sha256:20cc7d723ed729276e808f26fb6b3599f786cbc37e06c65e192ba77c40f20aac"
],
- "markers": "python_version >= '3.4'",
- "version": "==0.13.0"
+ "markers": "python_version >= '3.6'",
+ "version": "==0.14.2"
},
"yarl": {
"hashes": [
- "sha256:047b258e00b99091b6f90355521f026238c63bd76dcf996d93527bb13320eefd",
- "sha256:06ff23462398333c78b6f4f8d3d70410d657a471c2c5bbe6086133be43fc8f1a",
- "sha256:07f9eaf57719d6721ab15805d85f4b01a5b509a0868d7320134371bcb652152d",
- "sha256:0aa92e3e30a04f9462a25077db689c4ac5ea9ab6cc68a2e563881b987d42f16d",
- "sha256:0cf21f46a15d445417de8fc89f2568852cf57fe8ca1ab3d19ddb24d45c0383ae",
- "sha256:0fd7b941dd1b00b5f0acb97455fea2c4b7aac2dd31ea43fb9d155e9bc7b78664",
- "sha256:147e36331f6f63e08a14640acf12369e041e0751bb70d9362df68c2d9dcf0c87",
- "sha256:16a682a127930f3fc4e42583becca6049e1d7214bcad23520c590edd741d2114",
- "sha256:176110bff341b6730f64a1eb3a7070e12b373cf1c910a9337e7c3240497db76f",
- "sha256:19268b4fec1d7760134f2de46ef2608c2920134fb1fa61e451f679e41356dc55",
- "sha256:1b16f6c75cffc2dc0616ea295abb0e1967601bd1fb1e0af6a1de1c6c887f3439",
- "sha256:1bfc25aa6a7c99cf86564210f79a0b7d4484159c67e01232b116e445b3036547",
- "sha256:1ca3894e9e9f72da93544f64988d9c052254a338a9f855165f37f51edb6591de",
- "sha256:1dda53508df0de87b6e6b0a52d6718ff6c62a5aca8f5552748404963df639269",
- "sha256:217a782020b875538eebf3948fac3a7f9bbbd0fd9bf8538f7c2ad7489e80f4e8",
- "sha256:2192f718db4a8509f63dd6d950f143279211fa7e6a2c612edc17d85bf043d36e",
- "sha256:29a84a46ec3ebae7a1c024c055612b11e9363a8a23238b3e905552d77a2bc51b",
- "sha256:3007a5b75cb50140708420fe688c393e71139324df599434633019314ceb8b59",
- "sha256:30600ba5db60f7c0820ef38a2568bb7379e1418ecc947a0f76fd8b2ff4257a97",
- "sha256:337912bcdcf193ade64b9aae5a4017a0a1950caf8ca140362e361543c6773f21",
- "sha256:37001e5d4621cef710c8dc1429ca04e189e572f128ab12312eab4e04cf007132",
- "sha256:3d569f877ed9a708e4c71a2d13d2940cb0791da309f70bd970ac1a5c088a0a92",
- "sha256:4009def9be3a7e5175db20aa2d7307ecd00bbf50f7f0f989300710eee1d0b0b9",
- "sha256:46a9772a1efa93f9cd170ad33101c1817c77e0e9914d4fe33e2da299d7cf0f9b",
- "sha256:47eede5d11d669ab3759b63afb70d28d5328c14744b8edba3323e27dc52d298d",
- "sha256:498b3c55087b9d762636bca9b45f60d37e51d24341786dc01b81253f9552a607",
- "sha256:4e0d45ebf975634468682c8bec021618b3ad52c37619e5c938f8f831fa1ac5c0",
- "sha256:4f24f08b6c9b9818fd80612c97857d28f9779f0d1211653ece9844fc7b414df2",
- "sha256:55c144d363ad4626ca744556c049c94e2b95096041ac87098bb363dcc8635e8d",
- "sha256:582cedde49603f139be572252a318b30dc41039bc0b8165f070f279e5d12187f",
- "sha256:587c3cc59bc148a9b1c07a019346eda2549bc9f468acd2f9824d185749acf0a6",
- "sha256:5cd5dad8366e0168e0fd23d10705a603790484a6dbb9eb272b33673b8f2cce72",
- "sha256:5d02d700705d67e09e1f57681f758f0b9d4412eeb70b2eb8d96ca6200b486db3",
- "sha256:625f207b1799e95e7c823f42f473c1e9dbfb6192bd56bba8695656d92be4535f",
- "sha256:659603d26d40dd4463200df9bfbc339fbfaed3fe32e5c432fe1dc2b5d4aa94b4",
- "sha256:689a99a42ee4583fcb0d3a67a0204664aa1539684aed72bdafcbd505197a91c4",
- "sha256:68ac1a09392ed6e3fd14be880d39b951d7b981fd135416db7d18a6208c536561",
- "sha256:6a615cad11ec3428020fb3c5a88d85ce1b5c69fd66e9fcb91a7daa5e855325dd",
- "sha256:73bedd2be05f48af19f0f2e9e1353921ce0c83f4a1c9e8556ecdcf1f1eae4892",
- "sha256:742aef0a99844faaac200564ea6f5e08facb285d37ea18bd1a5acf2771f3255a",
- "sha256:75ff4c819757f9bdb35de049a509814d6ce851fe26f06eb95a392a5640052482",
- "sha256:781e2495e408a81e4eaeedeb41ba32b63b1980dddf8b60dbbeff6036bcd35049",
- "sha256:7a9f917966d27f7ce30039fe8d900f913c5304134096554fd9bea0774bcda6d1",
- "sha256:7e2637d75e92763d1322cb5041573279ec43a80c0f7fbbd2d64f5aee98447b17",
- "sha256:8089d4634d8fa2b1806ce44fefa4979b1ab2c12c0bc7ef3dfa45c8a374811348",
- "sha256:816d24f584edefcc5ca63428f0b38fee00b39fe64e3c5e558f895a18983efe96",
- "sha256:8385ab36bf812e9d37cf7613999a87715f27ef67a53f0687d28c44b819df7cb0",
- "sha256:85cb3e40eaa98489f1e2e8b29f5ad02ee1ee40d6ce6b88d50cf0f205de1d9d2c",
- "sha256:8648180b34faaea4aa5b5ca7e871d9eb1277033fa439693855cf0ea9195f85f1",
- "sha256:8892fa575ac9b1b25fae7b221bc4792a273877b9b56a99ee2d8d03eeb3dbb1d2",
- "sha256:88c7d9d58aab0724b979ab5617330acb1c7030b79379c8138c1c8c94e121d1b3",
- "sha256:8a2f8fb7f944bcdfecd4e8d855f84c703804a594da5123dd206f75036e536d4d",
- "sha256:8f4e475f29a9122f908d0f1f706e1f2fc3656536ffd21014ff8a6f2e1b14d1d8",
- "sha256:8f50eb3837012a937a2b649ec872b66ba9541ad9d6f103ddcafb8231cfcafd22",
- "sha256:91d875f75fabf76b3018c5f196bf3d308ed2b49ddcb46c1576d6b075754a1393",
- "sha256:94b2bb9bcfd5be9d27004ea4398fb640373dd0c1a9e219084f42c08f77a720ab",
- "sha256:9557c9322aaa33174d285b0c1961fb32499d65ad1866155b7845edc876c3c835",
- "sha256:95e16e9eaa2d7f5d87421b8fe694dd71606aa61d74b824c8d17fc85cc51983d1",
- "sha256:96952f642ac69075e44c7d0284528938fdff39422a1d90d3e45ce40b72e5e2d9",
- "sha256:985623575e5c4ea763056ffe0e2d63836f771a8c294b3de06d09480538316b13",
- "sha256:99ff3744f5fe48288be6bc402533b38e89749623a43208e1d57091fc96b783b9",
- "sha256:9abe80ae2c9d37c17599557b712e6515f4100a80efb2cda15f5f070306477cd2",
- "sha256:a152751af7ef7b5d5fa6d215756e508dd05eb07d0cf2ba51f3e740076aa74373",
- "sha256:a2e4725a08cb2b4794db09e350c86dee18202bb8286527210e13a1514dc9a59a",
- "sha256:a56fbe3d7f3bce1d060ea18d2413a2ca9ca814eea7cedc4d247b5f338d54844e",
- "sha256:ab3abc0b78a5dfaa4795a6afbe7b282b6aa88d81cf8c1bb5e394993d7cae3457",
- "sha256:b03384eed107dbeb5f625a99dc3a7de8be04fc8480c9ad42fccbc73434170b20",
- "sha256:b0547ab1e9345dc468cac8368d88ea4c5bd473ebc1d8d755347d7401982b5dd8",
- "sha256:b4c1ecba93e7826dc71ddba75fb7740cdb52e7bd0be9f03136b83f54e6a1f511",
- "sha256:b693c63e7e64b524f54aa4888403c680342d1ad0d97be1707c531584d6aeeb4f",
- "sha256:b6d0147574ce2e7b812c989e50fa72bbc5338045411a836bd066ce5fc8ac0bce",
- "sha256:b9cfef3f14f75bf6aba73a76caf61f9d00865912a04a4393c468a7ce0981b519",
- "sha256:b9f805e37ed16cc212fdc538a608422d7517e7faf539bedea4fe69425bc55d76",
- "sha256:bab03192091681d54e8225c53f270b0517637915d9297028409a2a5114ff4634",
- "sha256:bc24f968b82455f336b79bf37dbb243b7d76cd40897489888d663d4e028f5069",
- "sha256:c14b504a74e58e2deb0378b3eca10f3d076635c100f45b113c18c770b4a47a50",
- "sha256:c2089a9afef887664115f7fa6d3c0edd6454adaca5488dba836ca91f60401075",
- "sha256:c8ed4034f0765f8861620c1f2f2364d2e58520ea288497084dae880424fc0d9f",
- "sha256:cd2660c01367eb3ef081b8fa0a5da7fe767f9427aa82023a961a5f28f0d4af6c",
- "sha256:d8361c7d04e6a264481f0b802e395f647cd3f8bbe27acfa7c12049efea675bd1",
- "sha256:d9baec588f015d0ee564057aa7574313c53a530662ffad930b7886becc85abdf",
- "sha256:dbd9ff43a04f8ffe8a959a944c2dca10d22f5f99fc6a459f49c3ebfb409309d9",
- "sha256:e3f8bfc1db82589ef965ed234b87de30d140db8b6dc50ada9e33951ccd8ec07a",
- "sha256:e6a2c5c5bb2556dfbfffffc2bcfb9c235fd2b566d5006dfb2a37afc7e3278a07",
- "sha256:e749af6c912a7bb441d105c50c1a3da720474e8acb91c89350080dd600228f0e",
- "sha256:e85d86527baebb41a214cc3b45c17177177d900a2ad5783dbe6f291642d4906f",
- "sha256:ee2c68e4f2dd1b1c15b849ba1c96fac105fca6ffdb7c1e8be51da6fabbdeafb9",
- "sha256:f3ab950f8814f3b7b5e3eebc117986f817ec933676f68f0a6c5b2137dd7c9c69",
- "sha256:f4f4547944d4f5cfcdc03f3f097d6f05bbbc915eaaf80a2ee120d0e756de377d",
- "sha256:f72a0d746d38cb299b79ce3d4d60ba0892c84bbc905d0d49c13df5bace1b65f8",
- "sha256:fc2c80bc87fba076e6cbb926216c27fba274dae7100a7b9a0983b53132dd99f2",
- "sha256:fe4d2536c827f508348d7b40c08767e8c7071614250927233bf0c92170451c0a"
- ],
- "markers": "python_version >= '3.8'",
- "version": "==1.14.0"
+ "sha256:06157fb3c58f2736a5e47c8fcbe1afc8b5de6fb28b14d25574af9e62150fcaac",
+ "sha256:067a63fcfda82da6b198fa73079b1ca40b7c9b7994995b6ee38acda728b64d47",
+ "sha256:0b1794853124e2f663f0ea54efb0340b457f08d40a1cef78edfa086576179c91",
+ "sha256:0bdff5e0995522706c53078f531fb586f56de9c4c81c243865dd5c66c132c3b5",
+ "sha256:117ed8b3732528a1e41af3aa6d4e08483c2f0f2e3d3d7dca7cf538b3516d93df",
+ "sha256:14bc88baa44e1f84164a392827b5defb4fa8e56b93fecac3d15315e7c8e5d8b3",
+ "sha256:1654ec814b18be1af2c857aa9000de7a601400bd4c9ca24629b18486c2e35463",
+ "sha256:16bca6678a83657dd48df84b51bd56a6c6bd401853aef6d09dc2506a78484c7b",
+ "sha256:1a3b91c44efa29e6c8ef8a9a2b583347998e2ba52c5d8280dbd5919c02dfc3b5",
+ "sha256:1a52a1ffdd824fb1835272e125385c32fd8b17fbdefeedcb4d543cc23b332d74",
+ "sha256:1ce36ded585f45b1e9bb36d0ae94765c6608b43bd2e7f5f88079f7a85c61a4d3",
+ "sha256:299f11b44d8d3a588234adbe01112126010bd96d9139c3ba7b3badd9829261c3",
+ "sha256:2b24ec55fad43e476905eceaf14f41f6478780b870eda5d08b4d6de9a60b65b4",
+ "sha256:2d374d70fdc36f5863b84e54775452f68639bc862918602d028f89310a034ab0",
+ "sha256:2d9f0606baaec5dd54cb99667fcf85183a7477f3766fbddbe3f385e7fc253299",
+ "sha256:2e7ba4c9377e48fb7b20dedbd473cbcbc13e72e1826917c185157a137dac9df2",
+ "sha256:2f0a6423295a0d282d00e8701fe763eeefba8037e984ad5de44aa349002562ac",
+ "sha256:327828786da2006085a4d1feb2594de6f6d26f8af48b81eb1ae950c788d97f61",
+ "sha256:380e6c38ef692b8fd5a0f6d1fa8774d81ebc08cfbd624b1bca62a4d4af2f9931",
+ "sha256:3b74ff4767d3ef47ffe0cd1d89379dc4d828d4873e5528976ced3b44fe5b0a21",
+ "sha256:3e844be8d536afa129366d9af76ed7cb8dfefec99f5f1c9e4f8ae542279a6dc3",
+ "sha256:459e81c2fb920b5f5df744262d1498ec2c8081acdcfe18181da44c50f51312f7",
+ "sha256:46ddf6e0b975cd680eb83318aa1d321cb2bf8d288d50f1754526230fcf59ba96",
+ "sha256:482c122b72e3c5ec98f11457aeb436ae4aecca75de19b3d1de7cf88bc40db82f",
+ "sha256:561c87fea99545ef7d692403c110b2f99dced6dff93056d6e04384ad3bc46243",
+ "sha256:578d00c9b7fccfa1745a44f4eddfdc99d723d157dad26764538fbdda37209857",
+ "sha256:58c8e9620eb82a189c6c40cb6b59b4e35b2ee68b1f2afa6597732a2b467d7e8f",
+ "sha256:5b29beab10211a746f9846baa39275e80034e065460d99eb51e45c9a9495bcca",
+ "sha256:5d1d42556b063d579cae59e37a38c61f4402b47d70c29f0ef15cee1acaa64488",
+ "sha256:5f236cb5999ccd23a0ab1bd219cfe0ee3e1c1b65aaf6dd3320e972f7ec3a39da",
+ "sha256:62a91aefff3d11bf60e5956d340eb507a983a7ec802b19072bb989ce120cd948",
+ "sha256:64cc6e97f14cf8a275d79c5002281f3040c12e2e4220623b5759ea7f9868d6a5",
+ "sha256:6f4c9156c4d1eb490fe374fb294deeb7bc7eaccda50e23775b2354b6a6739934",
+ "sha256:7294e38f9aa2e9f05f765b28ffdc5d81378508ce6dadbe93f6d464a8c9594473",
+ "sha256:7615058aabad54416ddac99ade09a5510cf77039a3b903e94e8922f25ed203d7",
+ "sha256:7e48cdb8226644e2fbd0bdb0a0f87906a3db07087f4de77a1b1b1ccfd9e93685",
+ "sha256:7f63d176a81555984e91f2c84c2a574a61cab7111cc907e176f0f01538e9ff6e",
+ "sha256:7f6595c852ca544aaeeb32d357e62c9c780eac69dcd34e40cae7b55bc4fb1147",
+ "sha256:7fac95714b09da9278a0b52e492466f773cfe37651cf467a83a1b659be24bf71",
+ "sha256:81713b70bea5c1386dc2f32a8f0dab4148a2928c7495c808c541ee0aae614d67",
+ "sha256:846dd2e1243407133d3195d2d7e4ceefcaa5f5bf7278f0a9bda00967e6326b04",
+ "sha256:84c063af19ef5130084db70ada40ce63a84f6c1ef4d3dbc34e5e8c4febb20822",
+ "sha256:881764d610e3269964fc4bb3c19bb6fce55422828e152b885609ec176b41cf11",
+ "sha256:8994b29c462de9a8fce2d591028b986dbbe1b32f3ad600b2d3e1c482c93abad6",
+ "sha256:8c79e9d7e3d8a32d4824250a9c6401194fb4c2ad9a0cec8f6a96e09a582c2cc0",
+ "sha256:8ee427208c675f1b6e344a1f89376a9613fc30b52646a04ac0c1f6587c7e46ec",
+ "sha256:949681f68e0e3c25377462be4b658500e85ca24323d9619fdc41f68d46a1ffda",
+ "sha256:9e275792097c9f7e80741c36de3b61917aebecc08a67ae62899b074566ff8556",
+ "sha256:9fb815155aac6bfa8d86184079652c9715c812d506b22cfa369196ef4e99d1b4",
+ "sha256:a2a64e62c7a0edd07c1c917b0586655f3362d2c2d37d474db1a509efb96fea1c",
+ "sha256:a7ac5b4984c468ce4f4a553df281450df0a34aefae02e58d77a0847be8d1e11f",
+ "sha256:aa46dce75078fceaf7cecac5817422febb4355fbdda440db55206e3bd288cfb8",
+ "sha256:ae3476e934b9d714aa8000d2e4c01eb2590eee10b9d8cd03e7983ad65dfbfcba",
+ "sha256:b0341e6d9a0c0e3cdc65857ef518bb05b410dbd70d749a0d33ac0f39e81a4258",
+ "sha256:b40d1bf6e6f74f7c0a567a9e5e778bbd4699d1d3d2c0fe46f4b717eef9e96b95",
+ "sha256:b5c4804e4039f487e942c13381e6c27b4b4e66066d94ef1fae3f6ba8b953f383",
+ "sha256:b5d6a6c9602fd4598fa07e0389e19fe199ae96449008d8304bf5d47cb745462e",
+ "sha256:b5f1ac7359e17efe0b6e5fec21de34145caef22b260e978336f325d5c84e6938",
+ "sha256:c0167540094838ee9093ef6cc2c69d0074bbf84a432b4995835e8e5a0d984374",
+ "sha256:c180ac742a083e109c1a18151f4dd8675f32679985a1c750d2ff806796165b55",
+ "sha256:c73df5b6e8fabe2ddb74876fb82d9dd44cbace0ca12e8861ce9155ad3c886139",
+ "sha256:c7e177c619342e407415d4f35dec63d2d134d951e24b5166afcdfd1362828e17",
+ "sha256:cbad927ea8ed814622305d842c93412cb47bd39a496ed0f96bfd42b922b4a217",
+ "sha256:cc353841428d56b683a123a813e6a686e07026d6b1c5757970a877195f880c2d",
+ "sha256:cc7c92c1baa629cb03ecb0c3d12564f172218fb1739f54bf5f3881844daadc6d",
+ "sha256:cc7d768260f4ba4ea01741c1b5fe3d3a6c70eb91c87f4c8761bbcce5181beafe",
+ "sha256:d0eea830b591dbc68e030c86a9569826145df485b2b4554874b07fea1275a199",
+ "sha256:d216e5d9b8749563c7f2c6f7a0831057ec844c68b4c11cb10fc62d4fd373c26d",
+ "sha256:d401f07261dc5aa36c2e4efc308548f6ae943bfff20fcadb0a07517a26b196d8",
+ "sha256:d6324274b4e0e2fa1b3eccb25997b1c9ed134ff61d296448ab8269f5ac068c4c",
+ "sha256:d8a8b74d843c2638f3864a17d97a4acda58e40d3e44b6303b8cc3d3c44ae2d29",
+ "sha256:d9b6b28a57feb51605d6ae5e61a9044a31742db557a3b851a74c13bc61de5172",
+ "sha256:de599af166970d6a61accde358ec9ded821234cbbc8c6413acfec06056b8e860",
+ "sha256:e594b22688d5747b06e957f1ef822060cb5cb35b493066e33ceac0cf882188b7",
+ "sha256:e5b078134f48552c4d9527db2f7da0b5359abd49393cdf9794017baec7506170",
+ "sha256:eb6dce402734575e1a8cc0bb1509afca508a400a57ce13d306ea2c663bad1138",
+ "sha256:f1790a4b1e8e8e028c391175433b9c8122c39b46e1663228158e61e6f915bf06",
+ "sha256:f5efe0661b9fcd6246f27957f6ae1c0eb29bc60552820f01e970b4996e016004",
+ "sha256:f9cbfbc5faca235fbdf531b93aa0f9f005ec7d267d9d738761a4d42b744ea159",
+ "sha256:fbea1751729afe607d84acfd01efd95e3b31db148a181a441984ce9b3d3469da",
+ "sha256:fca4b4307ebe9c3ec77a084da3a9d1999d164693d16492ca2b64594340999988",
+ "sha256:ff5c6771c7e3511a06555afa317879b7db8d640137ba55d6ab0d0c50425cab75"
+ ],
+ "markers": "python_version >= '3.9'",
+ "version": "==1.17.1"
},
"zipp": {
"hashes": [
- "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350",
- "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29"
+ "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4",
+ "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"
],
- "markers": "python_version >= '3.8'",
- "version": "==3.20.2"
+ "markers": "python_version >= '3.9'",
+ "version": "==3.21.0"
}
},
"develop": {
@@ -2672,11 +2752,11 @@
},
"botocore-stubs": {
"hashes": [
- "sha256:b1aebecdfa4f4fc02b0a68a5e438877034b195168809a7202ee32b42245d3ece",
- "sha256:d79a408dfc503a1a0389d10cd29ad22a01450d0d53902ea216815e2ba98913ba"
+ "sha256:1456af3358be1a0e49dd8428bfb81863406659d9fad871362bf18a098eeac90a",
+ "sha256:dd83003963ca957a6e4835d192d7f163fb55312ce3d3f798f625ac9438616e4f"
],
"markers": "python_version >= '3.8'",
- "version": "==1.35.35"
+ "version": "==1.35.59"
},
"certifi": {
"hashes": [
@@ -2761,99 +2841,114 @@
},
"charset-normalizer": {
"hashes": [
- "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027",
- "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087",
- "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786",
- "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8",
- "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09",
- "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185",
- "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574",
- "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e",
- "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519",
- "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898",
- "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269",
- "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3",
- "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f",
- "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6",
- "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8",
- "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a",
- "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73",
- "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc",
- "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714",
- "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2",
- "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc",
- "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce",
- "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d",
- "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e",
- "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6",
- "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269",
- "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96",
- "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d",
- "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a",
- "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4",
- "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77",
- "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d",
- "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0",
- "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed",
- "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068",
- "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac",
- "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25",
- "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8",
- "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab",
- "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26",
- "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2",
- "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db",
- "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f",
- "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5",
- "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99",
- "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c",
- "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d",
- "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811",
- "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa",
- "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a",
- "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03",
- "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b",
- "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04",
- "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c",
- "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001",
- "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458",
- "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389",
- "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99",
- "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985",
- "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537",
- "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238",
- "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f",
- "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d",
- "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796",
- "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a",
- "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143",
- "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8",
- "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c",
- "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5",
- "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5",
- "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711",
- "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4",
- "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6",
- "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c",
- "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7",
- "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4",
- "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b",
- "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae",
- "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12",
- "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c",
- "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae",
- "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8",
- "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887",
- "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b",
- "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4",
- "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f",
- "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5",
- "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33",
- "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519",
- "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"
+ "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621",
+ "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6",
+ "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8",
+ "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912",
+ "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c",
+ "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b",
+ "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d",
+ "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d",
+ "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95",
+ "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e",
+ "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565",
+ "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64",
+ "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab",
+ "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be",
+ "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e",
+ "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907",
+ "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0",
+ "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2",
+ "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62",
+ "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62",
+ "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23",
+ "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc",
+ "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284",
+ "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca",
+ "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455",
+ "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858",
+ "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b",
+ "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594",
+ "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc",
+ "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db",
+ "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b",
+ "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea",
+ "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6",
+ "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920",
+ "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749",
+ "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7",
+ "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd",
+ "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99",
+ "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242",
+ "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee",
+ "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129",
+ "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2",
+ "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51",
+ "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee",
+ "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8",
+ "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b",
+ "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613",
+ "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742",
+ "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe",
+ "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3",
+ "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5",
+ "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631",
+ "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7",
+ "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15",
+ "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c",
+ "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea",
+ "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417",
+ "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250",
+ "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88",
+ "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca",
+ "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa",
+ "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99",
+ "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149",
+ "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41",
+ "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574",
+ "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0",
+ "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f",
+ "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d",
+ "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654",
+ "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3",
+ "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19",
+ "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90",
+ "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578",
+ "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9",
+ "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1",
+ "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51",
+ "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719",
+ "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236",
+ "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a",
+ "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c",
+ "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade",
+ "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944",
+ "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc",
+ "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6",
+ "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6",
+ "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27",
+ "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6",
+ "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2",
+ "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12",
+ "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf",
+ "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114",
+ "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7",
+ "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf",
+ "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d",
+ "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b",
+ "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed",
+ "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03",
+ "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4",
+ "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67",
+ "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365",
+ "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a",
+ "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748",
+ "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b",
+ "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079",
+ "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"
],
"markers": "python_full_version >= '3.7.0'",
- "version": "==3.3.2"
+ "version": "==3.4.0"
},
"click": {
"hashes": [
@@ -2865,35 +2960,35 @@
},
"cryptography": {
"hashes": [
- "sha256:014f58110f53237ace6a408b5beb6c427b64e084eb451ef25a28308270086494",
- "sha256:1bbcce1a551e262dfbafb6e6252f1ae36a248e615ca44ba302df077a846a8806",
- "sha256:203e92a75716d8cfb491dc47c79e17d0d9207ccffcbcb35f598fbe463ae3444d",
- "sha256:27e613d7077ac613e399270253259d9d53872aaf657471473ebfc9a52935c062",
- "sha256:2bd51274dcd59f09dd952afb696bf9c61a7a49dfc764c04dd33ef7a6b502a1e2",
- "sha256:38926c50cff6f533f8a2dae3d7f19541432610d114a70808f0926d5aaa7121e4",
- "sha256:511f4273808ab590912a93ddb4e3914dfd8a388fed883361b02dea3791f292e1",
- "sha256:58d4e9129985185a06d849aa6df265bdd5a74ca6e1b736a77959b498e0505b85",
- "sha256:5b43d1ea6b378b54a1dc99dd8a2b5be47658fe9a7ce0a58ff0b55f4b43ef2b84",
- "sha256:61ec41068b7b74268fa86e3e9e12b9f0c21fcf65434571dbb13d954bceb08042",
- "sha256:666ae11966643886c2987b3b721899d250855718d6d9ce41b521252a17985f4d",
- "sha256:68aaecc4178e90719e95298515979814bda0cbada1256a4485414860bd7ab962",
- "sha256:7c05650fe8023c5ed0d46793d4b7d7e6cd9c04e68eabe5b0aeea836e37bdcec2",
- "sha256:80eda8b3e173f0f247f711eef62be51b599b5d425c429b5d4ca6a05e9e856baa",
- "sha256:8385d98f6a3bf8bb2d65a73e17ed87a3ba84f6991c155691c51112075f9ffc5d",
- "sha256:88cce104c36870d70c49c7c8fd22885875d950d9ee6ab54df2745f83ba0dc365",
- "sha256:9d3cdb25fa98afdd3d0892d132b8d7139e2c087da1712041f6b762e4f807cc96",
- "sha256:a575913fb06e05e6b4b814d7f7468c2c660e8bb16d8d5a1faf9b33ccc569dd47",
- "sha256:ac119bb76b9faa00f48128b7f5679e1d8d437365c5d26f1c2c3f0da4ce1b553d",
- "sha256:c1332724be35d23a854994ff0b66530119500b6053d0bd3363265f7e5e77288d",
- "sha256:d03a475165f3134f773d1388aeb19c2d25ba88b6a9733c5c590b9ff7bbfa2e0c",
- "sha256:d75601ad10b059ec832e78823b348bfa1a59f6b8d545db3a24fd44362a1564cb",
- "sha256:de41fd81a41e53267cb020bb3a7212861da53a7d39f863585d13ea11049cf277",
- "sha256:e710bf40870f4db63c3d7d929aa9e09e4e7ee219e703f949ec4073b4294f6172",
- "sha256:ea25acb556320250756e53f9e20a4177515f012c9eaea17eb7587a8c4d8ae034",
- "sha256:f98bf604c82c416bc829e490c700ca1553eafdf2912a91e23a79d97d9801372a",
- "sha256:fba1007b3ef89946dbbb515aeeb41e30203b004f0b4b00e5e16078b518563289"
- ],
- "version": "==43.0.1"
+ "sha256:0c580952eef9bf68c4747774cde7ec1d85a6e61de97281f2dba83c7d2c806362",
+ "sha256:0f996e7268af62598f2fc1204afa98a3b5712313a55c4c9d434aef49cadc91d4",
+ "sha256:1ec0bcf7e17c0c5669d881b1cd38c4972fade441b27bda1051665faaa89bdcaa",
+ "sha256:281c945d0e28c92ca5e5930664c1cefd85efe80e5c0d2bc58dd63383fda29f83",
+ "sha256:2ce6fae5bdad59577b44e4dfed356944fbf1d925269114c28be377692643b4ff",
+ "sha256:315b9001266a492a6ff443b61238f956b214dbec9910a081ba5b6646a055a805",
+ "sha256:443c4a81bb10daed9a8f334365fe52542771f25aedaf889fd323a853ce7377d6",
+ "sha256:4a02ded6cd4f0a5562a8887df8b3bd14e822a90f97ac5e544c162899bc467664",
+ "sha256:53a583b6637ab4c4e3591a15bc9db855b8d9dee9a669b550f311480acab6eb08",
+ "sha256:63efa177ff54aec6e1c0aefaa1a241232dcd37413835a9b674b6e3f0ae2bfd3e",
+ "sha256:74f57f24754fe349223792466a709f8e0c093205ff0dca557af51072ff47ab18",
+ "sha256:7e1ce50266f4f70bf41a2c6dc4358afadae90e2a1e5342d3c08883df1675374f",
+ "sha256:81ef806b1fef6b06dcebad789f988d3b37ccaee225695cf3e07648eee0fc6b73",
+ "sha256:846da004a5804145a5f441b8530b4bf35afbf7da70f82409f151695b127213d5",
+ "sha256:8ac43ae87929a5982f5948ceda07001ee5e83227fd69cf55b109144938d96984",
+ "sha256:9762ea51a8fc2a88b70cf2995e5675b38d93bf36bd67d91721c309df184f49bd",
+ "sha256:a2a431ee15799d6db9fe80c82b055bae5a752bef645bba795e8e52687c69efe3",
+ "sha256:bf7a1932ac4176486eab36a19ed4c0492da5d97123f1406cf15e41b05e787d2e",
+ "sha256:c2e6fc39c4ab499049df3bdf567f768a723a5e8464816e8f009f121a5a9f4405",
+ "sha256:cbeb489927bd7af4aa98d4b261af9a5bc025bd87f0e3547e11584be9e9427be2",
+ "sha256:d03b5621a135bffecad2c73e9f4deb1a0f977b9a8ffe6f8e002bf6c9d07b918c",
+ "sha256:d56e96520b1020449bbace2b78b603442e7e378a9b3bd68de65c782db1507995",
+ "sha256:df6b6c6d742395dd77a23ea3728ab62f98379eff8fb61be2744d4679ab678f73",
+ "sha256:e1be4655c7ef6e1bbe6b5d0403526601323420bcf414598955968c9ef3eb7d16",
+ "sha256:f18c716be16bc1fea8e95def49edf46b82fccaa88587a45f8dc0ff6ab5d8e0a7",
+ "sha256:f46304d6f0c6ab8e52770addfa2fc41e6629495548862279641972b6215451cd",
+ "sha256:f7b178f11ed3664fd0e995a47ed2b5ff0a12d893e41dd0494f406d1cf555cab7"
+ ],
+ "version": "==43.0.3"
},
"docker": {
"hashes": [
@@ -2988,11 +3083,11 @@
},
"packaging": {
"hashes": [
- "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002",
- "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"
+ "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759",
+ "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"
],
"markers": "python_version >= '3.8'",
- "version": "==24.1"
+ "version": "==24.2"
},
"pathspec": {
"hashes": [
@@ -3061,11 +3156,11 @@
},
"rich": {
"hashes": [
- "sha256:51a2c62057461aaf7152b4d611168f93a9fc73068f8ded2790f29fe2b5366d0c",
- "sha256:8c82a3d3f8dcfe9e734771313e606b39d8247bb6b826e196f4914b333b743cf1"
+ "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098",
+ "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90"
],
"markers": "python_full_version >= '3.8.0'",
- "version": "==13.9.2"
+ "version": "==13.9.4"
},
"ruff": {
"hashes": [
@@ -3093,11 +3188,11 @@
},
"s3transfer": {
"hashes": [
- "sha256:0711534e9356d3cc692fdde846b4a1e4b0cb6519971860796e6bc4c7aea00ef6",
- "sha256:eca1c20de70a39daee580aef4986996620f365c4e0fda6a86100231d62f1bf69"
+ "sha256:263ed587a5803c6c708d3ce44dc4dfedaab4c1a32e8329bab818933d79ddcf5d",
+ "sha256:4f50ed74ab84d474ce614475e0b8d5047ff080810aac5d01ea25231cfc944b0c"
],
"markers": "python_version >= '3.8'",
- "version": "==0.10.2"
+ "version": "==0.10.3"
},
"six": {
"hashes": [
@@ -3109,20 +3204,20 @@
},
"types-awscrt": {
"hashes": [
- "sha256:67a660c90bad360c339f6a79310cc17094d12472042c7ca5a41450aaf5fc9a54",
- "sha256:b2c196bbd3226bab42d80fae13c34548de9ddc195f5a366d79c15d18e5897aa9"
+ "sha256:3fd1edeac923d1956c0e907c973fb83bda465beae7f054716b371b293f9b5fdc",
+ "sha256:517d9d06f19cf58d778ca90ad01e52e0489466bf70dcf78c7f47f74fdf151a60"
],
"markers": "python_version >= '3.8'",
- "version": "==0.22.0"
+ "version": "==0.23.0"
},
"types-beautifulsoup4": {
"hashes": [
- "sha256:32f5ac48514b488f15241afdd7d2f73f0baf3c54e874e23b66708503dd288489",
- "sha256:8d023b86530922070417a1d4c4d91678ab0ff2439b3b2b2cffa3b628b49ebab1"
+ "sha256:158370d08d0cd448bd11b132a50ff5279237a5d4b5837beba074de152a513059",
+ "sha256:c95e66ce15a4f5f0835f7fbc5cd886321ae8294f977c495424eaf4225307fd30"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
- "version": "==4.12.0.20240907"
+ "version": "==4.12.0.20241020"
},
"types-docker": {
"hashes": [
@@ -3135,28 +3230,28 @@
},
"types-html5lib": {
"hashes": [
- "sha256:575c4fd84ba8eeeaa8520c7e4c7042b7791f5ec3e9c0a5d5c418124c42d9e7e4",
- "sha256:8060dc98baf63d6796a765bbbc809fff9f7a383f6e3a9add526f814c086545ef"
+ "sha256:3f1e064d9ed2c289001ae6392c84c93833abb0816165c6ff0abfc304a779f403",
+ "sha256:98042555ff78d9e3a51c77c918b1041acbb7eb6c405408d8a9e150ff5beccafa"
],
"markers": "python_version >= '3.8'",
- "version": "==1.1.11.20240806"
+ "version": "==1.1.11.20241018"
},
"types-requests": {
"hashes": [
- "sha256:2850e178db3919d9bf809e434eef65ba49d0e7e33ac92d588f4a5e295fffd405",
- "sha256:59c2f673eb55f32a99b2894faf6020e1a9f4a402ad0f192bfee0b64469054310"
+ "sha256:0d9cad2f27515d0e3e3da7134a1b6f28fb97129d86b867f24d9c726452634d95",
+ "sha256:4195d62d6d3e043a4eaaf08ff8a62184584d2e8684e9d2aa178c7915a7da3747"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
- "version": "==2.32.0.20240914"
+ "version": "==2.32.0.20241016"
},
"types-s3transfer": {
"hashes": [
- "sha256:60167a3bfb5c536ec6cdb5818f7f9a28edca9dc3e0b5ff85ae374526fc5e576e",
- "sha256:7a3fec8cd632e2b5efb665a355ef93c2a87fdd5a45b74a949f95a9e628a86356"
+ "sha256:d34c5a82f531af95bb550927136ff5b737a1ed3087f90a59d545591dfde5b4cc",
+ "sha256:f761b2876ac4c208e6c6b75cdf5f6939009768be9950c545b11b0225e7703ee7"
],
"markers": "python_version >= '3.8'",
- "version": "==0.10.2"
+ "version": "==0.10.3"
},
"typing-extensions": {
"hashes": [
diff --git a/opentrons-ai-server/README.md b/opentrons-ai-server/README.md
index b072429c41c..041328a5c99 100644
--- a/opentrons-ai-server/README.md
+++ b/opentrons-ai-server/README.md
@@ -60,6 +60,15 @@ In the deployed environments the FastAPI server is run in a docker container. To
Now the API is running at
View the API docs in a browser at
+##### Docker shell
+
+1. make clean
+1. make build
+1. make run-shell
+1. make shell
+
+Now you are in the docker container and can inspect the environment and such.
+
#### Direct API Interaction and Authentication
> There is only 1 endpoint with the potential to call the OpenAI API. This is the `/api/chat/completion` endpoint. This endpoint requires authentication and the steps are outlined below. In the POST request body setting `"fake": true` will short circuit the handling of the call. The OpenAI API will not be hit. Instead, a hard coded response is returned. We plan to extend this capability to allow for live local testing of the UI without calling the OpenAI API.
@@ -117,3 +126,48 @@ The live-test target will run tests against any environment. The default is loca
1. alter the `Pipfile` to the new pinned version
1. run `make setup` to update the `Pipfile.lock`
+
+## Google Sheets Integration
+
+1. Create a Google Cloud Platform project
+1. Enable the Google Sheets and Drive API
+1. Go to APIs & Services > Library and enable the Google Sheets API.
+1. Go to APIs & Services > Credentials and create a Service Account. This account will be used by your application to access the Google Sheets API.
+1. After creating the Service Account, click on it in the Credentials section, go to the Keys tab, and create a JSON key. This will download a JSON file with credentials for your Service Account.
+1. Open the JSON file and store its content securely. You’ll set this JSON content as an environment variable.
+1. Configure Access to the Google Sheet
+1. Open the Google Sheet you want to access.
+1. Click Share and add the Service Account email (found in the JSON file under "client_email") as a collaborator, typically with Editor access. This allows the Service Account to interact with the sheet.
+
+### Test that the credentials work with a direct call to the Integration
+
+```shell
+make test-googlesheet
+```
+
+## Add Secrets or Environment Variables
+
+1. Define the new secret or environment variable in the `api/settings.py` file.
+1. Add the new secret or environment variable to your local `.env` file.
+1. Test locally.
+1. Log into the AWS console and navigate to the Secrets Manager.
+1. Environment variables are added into the json secret named ENV_VARIABLES_SECRET_NAME in deploy.py for a given environment.
+1. Environment variables MUST be named the same as the property in the Settings class.
+1. Secret names MUST be the same as the property in the Settings class but with \_ replaced with - and prefixed with the environment name-.
+1. The deploy script will load the environment variables from the secret and set them in the container definition.
+1. The deploy script will map the secrets from Settings and match them to the container secrets.
+1. If any secrets are missing, the deploy script with retrieve the secret ARN and set the secret in the container definition.
+
+## AWS Deployment
+
+Locally test the deployment script like so:
+
+```shell
+AWS_PROFILE=robotics_ai_staging make dry-deploy ENV=staging
+```
+
+Locally deploy to the staging environment like so:
+
+```shell
+AWS_PROFILE=robotics_ai_staging make deploy ENV=staging
+```
diff --git a/opentrons-ai-server/api/handler/fast.py b/opentrons-ai-server/api/handler/fast.py
index 9534906adbe..9182f827a9a 100644
--- a/opentrons-ai-server/api/handler/fast.py
+++ b/opentrons-ai-server/api/handler/fast.py
@@ -1,14 +1,14 @@
import asyncio
import os
import time
-from typing import Any, Awaitable, Callable, List, Literal, Union
+from typing import Annotated, Any, Awaitable, Callable, List, Literal, Union
import structlog
from asgi_correlation_id import CorrelationIdMiddleware
from asgi_correlation_id.context import correlation_id
from ddtrace import tracer
from ddtrace.contrib.asgi.middleware import TraceMiddleware
-from fastapi import FastAPI, HTTPException, Query, Request, Response, Security, status
+from fastapi import BackgroundTasks, FastAPI, HTTPException, Query, Request, Response, Security, status
from fastapi.exceptions import RequestValidationError
from fastapi.middleware.cors import CORSMiddleware
from fastapi.openapi.docs import get_redoc_html, get_swagger_ui_html
@@ -21,13 +21,17 @@
from api.domain.openai_predict import OpenAIPredict
from api.handler.custom_logging import setup_logging
from api.integration.auth import VerifyToken
+from api.integration.google_sheets import GoogleSheetsClient
from api.models.chat_request import ChatRequest
from api.models.chat_response import ChatResponse
from api.models.create_protocol import CreateProtocol
from api.models.empty_request_error import EmptyRequestError
+from api.models.error_response import ErrorResponse
+from api.models.feedback_request import FeedbackRequest
from api.models.feedback_response import FeedbackResponse
from api.models.internal_server_error import InternalServerError
from api.models.update_protocol import UpdateProtocol
+from api.models.user import User
from api.settings import Settings
settings: Settings = Settings()
@@ -38,6 +42,7 @@
auth: VerifyToken = VerifyToken()
openai: OpenAIPredict = OpenAIPredict(settings)
+google_sheets_client = GoogleSheetsClient(settings)
# Initialize FastAPI app with metadata
@@ -147,10 +152,6 @@ class Status(BaseModel):
version: str
-class ErrorResponse(BaseModel):
- message: str
-
-
class HealthResponse(BaseModel):
status: Status
@@ -175,7 +176,7 @@ class CorsHeadersResponse(BaseModel):
description="Generate a chat response based on the provided prompt.",
)
async def create_chat_completion(
- body: ChatRequest, auth_result: Any = Security(auth.verify) # noqa: B008
+ body: ChatRequest, user: Annotated[User, Security(auth.verify)]
) -> Union[ChatResponse, ErrorResponse]: # noqa: B008
"""
Generate a chat completion response using OpenAI.
@@ -183,7 +184,7 @@ async def create_chat_completion(
- **request**: The HTTP request containing the chat message.
- **returns**: A chat response or an error message.
"""
- logger.info("POST /api/chat/completion", extra={"body": body.model_dump(), "auth_result": auth_result})
+ logger.info("POST /api/chat/completion", extra={"body": body.model_dump(), "user": user})
try:
if not body.message or body.message == "":
raise HTTPException(
@@ -198,9 +199,9 @@ async def create_chat_completion(
response: Union[str, None] = openai.predict(prompt=body.message, chat_completion_message_params=body.history)
if response is None or response == "":
- return ChatResponse(reply="No response was generated", fake=body.fake)
+ return ChatResponse(reply="No response was generated", fake=bool(body.fake))
- return ChatResponse(reply=response, fake=body.fake)
+ return ChatResponse(reply=response, fake=bool(body.fake))
except Exception as e:
logger.exception("Error processing chat completion")
@@ -217,15 +218,15 @@ async def create_chat_completion(
description="Generate a chat response based on the provided prompt that will update an existing protocol with the required changes.",
)
async def update_protocol(
- body: UpdateProtocol, auth_result: Any = Security(auth.verify) # noqa: B008
+ body: UpdateProtocol, user: Annotated[User, Security(auth.verify)]
) -> Union[ChatResponse, ErrorResponse]: # noqa: B008
"""
- Generate an updated protocolusing OpenAI.
+ Generate an updated protocol using OpenAI.
- **request**: The HTTP request containing the existing protocol and other relevant parameters.
- **returns**: A chat response or an error message.
"""
- logger.info("POST /api/chat/updateProtocol", extra={"body": body.model_dump(), "auth_result": auth_result})
+ logger.info("POST /api/chat/updateProtocol", extra={"body": body.model_dump(), "user": user})
try:
if not body.protocol_text or body.protocol_text == "":
raise HTTPException(
@@ -233,14 +234,14 @@ async def update_protocol(
)
if body.fake:
- return ChatResponse(reply="Fake response", fake=body.fake)
+ return ChatResponse(reply="Fake response", fake=bool(body.fake))
response: Union[str, None] = openai.predict(prompt=body.prompt, chat_completion_message_params=None)
if response is None or response == "":
- return ChatResponse(reply="No response was generated", fake=body.fake)
+ return ChatResponse(reply="No response was generated", fake=bool(body.fake))
- return ChatResponse(reply=response, fake=body.fake)
+ return ChatResponse(reply=response, fake=bool(body.fake))
except Exception as e:
logger.exception("Error processing protocol update")
@@ -257,15 +258,15 @@ async def update_protocol(
description="Generate a chat response based on the provided prompt that will create a new protocol with the required changes.",
)
async def create_protocol(
- body: CreateProtocol, auth_result: Any = Security(auth.verify) # noqa: B008
+ body: CreateProtocol, user: Annotated[User, Security(auth.verify)]
) -> Union[ChatResponse, ErrorResponse]: # noqa: B008
"""
- Generate an updated protocolusing OpenAI.
+ Generate an updated protocol using OpenAI.
- **request**: The HTTP request containing the chat message.
- **returns**: A chat response or an error message.
"""
- logger.info("POST /api/chat/createProtocol", extra={"body": body.model_dump(), "auth_result": auth_result})
+ logger.info("POST /api/chat/createProtocol", extra={"body": body.model_dump(), "user": user})
try:
if not body.prompt or body.prompt == "":
@@ -279,9 +280,9 @@ async def create_protocol(
response: Union[str, None] = openai.predict(prompt=str(body.model_dump()), chat_completion_message_params=None)
if response is None or response == "":
- return ChatResponse(reply="No response was generated", fake=body.fake)
+ return ChatResponse(reply="No response was generated", fake=bool(body.fake))
- return ChatResponse(reply=response, fake=body.fake)
+ return ChatResponse(reply=response, fake=bool(body.fake))
except Exception as e:
logger.exception("Error processing protocol creation")
@@ -339,23 +340,19 @@ async def redoc_html() -> HTMLResponse:
summary="Feedback",
description="Send feedback to the team.",
)
-async def feedback(request: Request, auth_result: Any = Security(auth.verify)) -> FeedbackResponse: # noqa: B008
- """
- Send feedback to the team.
-
- - **request**: The HTTP request containing the feedback message.
- - **returns**: A feedback response or an error message.
- """
+async def feedback(
+ body: FeedbackRequest, user: Annotated[User, Security(auth.verify)], background_tasks: BackgroundTasks
+) -> FeedbackResponse:
logger.info("POST /api/feedback")
try:
- body = await request.json()
- if "feedbackText" not in body.keys() or body["feedbackText"] == "":
- logger.info("Feedback empty")
- raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=EmptyRequestError(message="Request body is empty"))
- logger.info(f"Feedback received: {body}")
- feedbackText = body["feedbackText"]
- # todo: Store feedback text in a database
- return FeedbackResponse(reply=f"Feedback Received: {feedbackText}", fake=False)
+ if body.fake:
+ return FeedbackResponse(reply="Fake response", fake=bool(body.fake))
+ feedback_text = body.feedbackText
+ logger.info("Feedback received", user_id=user.sub, feedback=feedback_text)
+ background_tasks.add_task(google_sheets_client.append_feedback_to_sheet, user_id=str(user.sub), feedback=feedback_text)
+ return FeedbackResponse(
+ reply=f"Feedback Received and sanitized: {google_sheets_client.sanitize_for_google_sheets(feedback_text)}", fake=False
+ )
except Exception as e:
logger.exception("Error processing feedback")
diff --git a/opentrons-ai-server/api/integration/auth.py b/opentrons-ai-server/api/integration/auth.py
index 12e8b2a4a9e..addc0abafb8 100644
--- a/opentrons-ai-server/api/integration/auth.py
+++ b/opentrons-ai-server/api/integration/auth.py
@@ -1,10 +1,9 @@
-from typing import Any, Optional
-
import jwt
import structlog
from fastapi import HTTPException, Security, status
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer, SecurityScopes
+from api.models.user import User
from api.settings import Settings
settings: Settings = Settings()
@@ -28,8 +27,8 @@ def __init__(self) -> None:
self.jwks_client = jwt.PyJWKClient(jwks_url)
async def verify(
- self, security_scopes: SecurityScopes, credentials: Optional[HTTPAuthorizationCredentials] = Security(HTTPBearer()) # noqa: B008
- ) -> Any:
+ self, security_scopes: SecurityScopes, credentials: HTTPAuthorizationCredentials = Security(HTTPBearer()) # noqa: B008
+ ) -> User:
if credentials is None:
raise UnauthenticatedException()
@@ -50,8 +49,9 @@ async def verify(
audience=self.config.auth0_api_audience,
issuer=self.config.auth0_issuer,
)
- logger.info("Decoded token", extra={"token": payload})
- return payload
+ user = User(**payload)
+ logger.info("User object", extra={"user": user})
+ return user
except jwt.ExpiredSignatureError:
logger.error("Expired Signature", extra={"credentials": credentials}, exc_info=True)
# Handle token expiration, e.g., refresh token, re-authenticate, etc.
diff --git a/opentrons-ai-server/api/integration/google_sheets.py b/opentrons-ai-server/api/integration/google_sheets.py
new file mode 100644
index 00000000000..e86d4103097
--- /dev/null
+++ b/opentrons-ai-server/api/integration/google_sheets.py
@@ -0,0 +1,75 @@
+import json
+import random
+import re
+
+import gspread
+import structlog
+from google.oauth2.service_account import Credentials
+from gspread import SpreadsheetNotFound # type: ignore
+from gspread.client import Client as GspreadClient
+
+from api.settings import Settings
+
+
+class GoogleSheetsClient:
+ SCOPES = ["https://www.googleapis.com/auth/spreadsheets"]
+
+ def __init__(self, settings: Settings) -> None:
+ self.settings = settings
+ self.logger = structlog.stdlib.get_logger(settings.logger_name)
+ self.client: GspreadClient = self._initialize_client()
+
+ def _initialize_client(self) -> GspreadClient:
+ """Initialize the gspread client with Service Account credentials loaded from the environment."""
+ creds: Credentials = self._get_credentials()
+ return gspread.authorize(creds) # type: ignore
+
+ def _get_credentials(self) -> Credentials:
+ """Load Service Account credentials from an environment variable."""
+ google_credentials_json = self.settings.google_credentials_json.get_secret_value()
+ if not google_credentials_json:
+ raise EnvironmentError("Missing GOOGLE_SHEETS_CREDENTIALS environment variable.")
+
+ creds_info = json.loads(google_credentials_json)
+ creds: Credentials = Credentials.from_service_account_info(info=creds_info, scopes=self.SCOPES) # type: ignore
+ return creds
+
+ @staticmethod
+ def sanitize_for_google_sheets(input_text: str) -> str:
+ """Sanitize input to remove JavaScript and HTML tags, and prevent formulas."""
+ script_pattern = re.compile(r'(javascript:[^"]*|.*?|on\w+=".*?"|on\w+=\'.*?\')', re.IGNORECASE)
+ sanitized_text = re.sub(script_pattern, "", input_text)
+ sanitized_text = re.sub(r"(<.*?>|<.*?>)", "", sanitized_text)
+ sanitized_text = re.sub(r"^\s*=\s*", "", sanitized_text)
+ return sanitized_text.strip()
+
+ def append_feedback_to_sheet(self, user_id: str, feedback: str) -> None:
+ """Append a row of feedback to the Google Sheet."""
+ try:
+ sheet_id = self.settings.google_sheet_id
+ worksheet_name = self.settings.google_sheet_worksheet
+ spreadsheet = self.client.open_by_key(sheet_id)
+ worksheet = spreadsheet.worksheet(worksheet_name)
+
+ feedback = self.sanitize_for_google_sheets(feedback)
+
+ worksheet.append_row([user_id, feedback])
+ self.logger.info("Feedback successfully appended to Google Sheet.")
+ except SpreadsheetNotFound:
+ self.logger.error("Spreadsheet not found or not accessible.")
+ except Exception:
+ self.logger.error("Error appending feedback to Google Sheet.", exc_info=True)
+
+
+# Example usage
+def main() -> None:
+ """Run an example appending feedback to Google Sheets."""
+ settings = Settings()
+ google_sheets_client = GoogleSheetsClient(settings)
+ user_id = str(random.randint(100000, 999999))
+ feedback = f"This is a test feedback for user {user_id}."
+ google_sheets_client.append_feedback_to_sheet(user_id, feedback)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/opentrons-ai-server/api/models/error_response.py b/opentrons-ai-server/api/models/error_response.py
new file mode 100644
index 00000000000..ba52d60547e
--- /dev/null
+++ b/opentrons-ai-server/api/models/error_response.py
@@ -0,0 +1,5 @@
+from pydantic import BaseModel
+
+
+class ErrorResponse(BaseModel):
+ message: str
diff --git a/opentrons-ai-server/api/models/feedback_request.py b/opentrons-ai-server/api/models/feedback_request.py
new file mode 100644
index 00000000000..89a098b0f92
--- /dev/null
+++ b/opentrons-ai-server/api/models/feedback_request.py
@@ -0,0 +1,15 @@
+from typing import Optional
+
+from pydantic import BaseModel, Field, field_validator
+
+
+class FeedbackRequest(BaseModel):
+ feedbackText: str = Field(..., description="The feedback message content")
+ fake: Optional[bool] = Field(False, description="Indicates if this is a fake feedback entry")
+
+ # Validation to ensure feedback_text is populated and not empty
+ @field_validator("feedbackText")
+ def feedback_text_must_not_be_empty(cls, value: str) -> str:
+ if not value or value.strip() == "":
+ raise ValueError("feedback_text must be populated and not empty")
+ return value
diff --git a/opentrons-ai-server/api/models/user.py b/opentrons-ai-server/api/models/user.py
new file mode 100644
index 00000000000..d1d79c2b6d1
--- /dev/null
+++ b/opentrons-ai-server/api/models/user.py
@@ -0,0 +1,16 @@
+from typing import List, Optional, Union
+
+from pydantic import BaseModel, Field
+
+
+class User(BaseModel):
+ aud: Union[str, List[str]] = Field(..., description="Audience URL(s)")
+ azp: str = Field(..., description="Authorized party ID")
+ exp: int = Field(..., description="Expiration timestamp")
+ iat: int = Field(..., description="Issued-at timestamp")
+ iss: str = Field(..., description="Issuer URL")
+ scope: Optional[str] = Field(None, description="Space-separated scopes")
+ sub: str = Field(..., description="Subject identifier for the token")
+
+ class Config:
+ extra = "allow" # Allows additional fields not specified in the model
diff --git a/opentrons-ai-server/api/settings.py b/opentrons-ai-server/api/settings.py
index c59a25c33de..9557b51614b 100644
--- a/opentrons-ai-server/api/settings.py
+++ b/opentrons-ai-server/api/settings.py
@@ -34,11 +34,15 @@ class Settings(BaseSettings):
dd_trace_enabled: str = "false"
cpu: str = "1028"
memory: str = "2048"
+ google_sheet_id: str = "harcoded_default_from_settings"
+ google_sheet_worksheet: str = "Sheet1"
# Secrets
# These come from environment variables in the local and deployed execution environments
openai_api_key: SecretStr = SecretStr("default_openai_api_key")
huggingface_api_key: SecretStr = SecretStr("default_huggingface_api_key")
+ google_credentials_json: SecretStr = SecretStr("default_google_credentials_json")
+ datadog_api_key: SecretStr = SecretStr("default_datadog_api_key")
@property
def json_logging(self) -> bool:
diff --git a/opentrons-ai-server/deploy.py b/opentrons-ai-server/deploy.py
index 61cbc64b9a1..813dc3ccca1 100644
--- a/opentrons-ai-server/deploy.py
+++ b/opentrons-ai-server/deploy.py
@@ -3,7 +3,7 @@
import datetime
import subprocess
from dataclasses import dataclass
-from typing import Dict, List
+from typing import Any, Dict, List
import boto3
import docker
@@ -12,7 +12,7 @@
from rich import print
from rich.prompt import Prompt
-ENVIRONMENTS = ["crt", "dev", "sandbox", "staging", "prod"]
+ENVIRONMENTS = ["staging", "prod"]
def get_aws_account_id() -> str:
@@ -28,6 +28,7 @@ def get_aws_region() -> str:
@dataclass(frozen=True)
class BaseDeploymentConfig:
+ ENV: str
IMAGE_NAME: str # local image name
ECR_URL: str
ECR_REPOSITORY: str
@@ -40,42 +41,9 @@ class BaseDeploymentConfig:
DEPLOYMENT_POLL_INTERVAL_S: int = 20
-@dataclass(frozen=True)
-class CrtDeploymentConfig(BaseDeploymentConfig):
- ECR_REPOSITORY: str = "crt-ecr-repo"
- ECR_URL: str = f"{get_aws_account_id()}.dkr.ecr.{get_aws_region()}.amazonaws.com"
- IMAGE_NAME: str = "crt-ai-server"
- CLUSTER_NAME: str = "crt-ai-cluster"
- SERVICE_NAME: str = "crt-ai-service"
- CONTAINER_NAME: str = "crt-ai-api"
- ENV_VARIABLES_SECRET_NAME: str = "crt-environment-variables"
-
-
-@dataclass(frozen=True)
-class SandboxDeploymentConfig(BaseDeploymentConfig):
- ECR_REPOSITORY: str = "sandbox-ecr-repo"
- ECR_URL: str = f"{get_aws_account_id()}.dkr.ecr.{get_aws_region()}.amazonaws.com"
- IMAGE_NAME: str = "sandbox-ai-server"
- CLUSTER_NAME: str = "sandbox-ai-cluster"
- SERVICE_NAME: str = "sandbox-ai-service"
- CONTAINER_NAME: str = "sandbox-ai-api"
- ENV_VARIABLES_SECRET_NAME: str = "sandbox-environment-variables"
-
-
-@dataclass(frozen=True)
-class DevDeploymentConfig(BaseDeploymentConfig):
- ECR_REPOSITORY: str = "dev-ecr-repo"
- ECR_URL: str = f"{get_aws_account_id()}.dkr.ecr.{get_aws_region()}.amazonaws.com"
- FUNCTION_NAME: str = "dev-api-function"
- IMAGE_NAME: str = "dev-ai-server"
- CLUSTER_NAME: str = "dev-ai-cluster"
- SERVICE_NAME: str = "dev-ai-service"
- CONTAINER_NAME: str = "dev-ai-api"
- ENV_VARIABLES_SECRET_NAME: str = "dev-environment-variables"
-
-
@dataclass(frozen=True)
class StagingDeploymentConfig(BaseDeploymentConfig):
+ ENV: str = "staging"
ECR_REPOSITORY: str = "staging-ecr-repo"
ECR_URL: str = f"{get_aws_account_id()}.dkr.ecr.{get_aws_region()}.amazonaws.com"
IMAGE_NAME: str = "staging-ai-server"
@@ -87,6 +55,7 @@ class StagingDeploymentConfig(BaseDeploymentConfig):
@dataclass(frozen=True)
class ProdDeploymentConfig(BaseDeploymentConfig):
+ ENV: str = "prod"
ECR_REPOSITORY: str = "prod-ecr-repo"
ECR_URL: str = f"{get_aws_account_id()}.dkr.ecr.{get_aws_region()}.amazonaws.com"
IMAGE_NAME: str = "prod-ai-server"
@@ -156,7 +125,43 @@ def update_environment_variables(self, environment_variables: List[Dict[str, str
return updated_environment_variables
- def update_ecs_task(self) -> None:
+ def get_secret_arn(self, secret_name: str) -> str:
+ response = self.secret_manager_client.describe_secret(SecretId=secret_name)
+ return str(response["ARN"])
+
+ def update_secrets_in_container_definition(self, container_definition: dict[str, Any]) -> None:
+ expected_secrets = {field.upper() for field, field_type in self.env_variables.__annotations__.items() if field_type == SecretStr}
+ print(f"Expected secrets: {expected_secrets}")
+
+ task_secrets = {secret["name"].upper() for secret in container_definition.get("secrets", [])}
+ print(f"Existing secrets: {task_secrets}")
+
+ if not task_secrets:
+ raise ValueError("No secrets found in the api container definition ...")
+
+ unexpected_secrets = [secret.upper() for secret in task_secrets if secret not in expected_secrets]
+ if unexpected_secrets:
+ raise ValueError(f"Secrets found in the api container definition that are NOT in Settings: {', '.join(unexpected_secrets)}")
+
+ missing_secrets = [secret.upper() for secret in expected_secrets if secret.upper() not in task_secrets]
+
+ if missing_secrets:
+ print(f"Missing secrets: {missing_secrets}")
+ for secret in missing_secrets:
+ print(f"Adding missing secret: {secret}")
+ # secret name is the same as the property name
+ # of the secret in the Settings class
+ # but with _ replaced with -
+ secret_name = f"{self.config.ENV}-{secret.lower().replace("_", "-")}"
+ value_from = self.get_secret_arn(secret_name)
+ # name is the all caps version of the secret name
+ # valueFrom is the ARN of the secret
+ new_secret = {"name": secret, "valueFrom": value_from}
+ container_definition["secrets"].append(new_secret)
+ else:
+ print("No secrets need to be added.")
+
+ def update_ecs_task(self, dry: bool) -> None:
print(f"Updating ECS task with new image: {self.full_image_name}")
response = self.ecs_client.describe_services(cluster=self.config.CLUSTER_NAME, services=[self.config.SERVICE_NAME])
task_definition_arn = response["services"][0]["taskDefinition"]
@@ -164,6 +169,9 @@ def update_ecs_task(self) -> None:
task_definition = self.ecs_client.describe_task_definition(taskDefinition=task_definition_arn)["taskDefinition"]
container_definitions = task_definition["containerDefinitions"]
for container_definition in container_definitions:
+ # ENV--datadog-agent container has one secret and 2 environment variables
+ # ENV--log-router container has no secrets or environment variables
+ # These are managed in the infra repo, NOT here
if container_definition["name"] == self.config.CONTAINER_NAME:
container_definition["image"] = self.full_image_name
environment_variables = container_definition.get("environment", [])
@@ -171,13 +179,15 @@ def update_ecs_task(self) -> None:
for key, value in self.env_variables.model_dump().items():
if not isinstance(value, SecretStr):
# Secrets are not set here
- # They are set in the secrets key of ECS task definition
+ # They are set in the secrets key of the containerDefinition
environment_variables = self.update_environment_variables(environment_variables, key, value)
# Overwrite the DD_VERSION environment variable
# with the current deployment tag
# this is what we are using for version currently
environment_variables = self.update_environment_variables(environment_variables, "DD_VERSION", self.config.TAG)
container_definition["environment"] = environment_variables
+ # Update the secrets in the container definition
+ self.update_secrets_in_container_definition(container_definition)
print("Updated container definition:")
print(container_definition)
break
@@ -195,6 +205,11 @@ def update_ecs_task(self) -> None:
}
print("New task definition:")
print(new_task_definition)
+
+ if dry:
+ print("Dry run, not updating the ECS task.")
+ return
+
register_response = self.ecs_client.register_task_definition(**new_task_definition)
new_task_definition_arn = register_response["taskDefinition"]["taskDefinitionArn"]
@@ -204,14 +219,21 @@ def update_ecs_task(self) -> None:
taskDefinition=new_task_definition_arn,
forceNewDeployment=True,
)
+ print(f"Deployment to {self.config.ENV} started.")
+ print("The API container definition was updated.")
+ print("A new Task definition was defined and registered.")
+ print("Then we told the ECS service to deploy the new definition.")
+ print("Monitor the deployment in the ECS console.")
def main() -> None:
parser = argparse.ArgumentParser(description="Manage ECS Fargate deployment.")
parser.add_argument("--env", type=str, help=f"Deployment environment {ENVIRONMENTS}")
parser.add_argument("--tag", type=str, help="The tag and therefore version of the container to use")
+ # action="store_true" sets args.dry to True only if --dry is provided on the command line
+ parser.add_argument("--dry", action="store_true", help="Dry run, do not make any changes")
args = parser.parse_args()
- # Determine if the script was called with command-line arguments
+
if args.env:
if args.env.lower() not in ENVIRONMENTS:
print(f"[red]Invalid environment specified: {args.env}[/red]")
@@ -221,7 +243,6 @@ def main() -> None:
tag = args.tag
else:
if args.env:
- # Passing --env alone generates a tag and does not prompt!
tag = str(int(datetime.datetime.now().timestamp()))
else:
# Interactive prompts if env not set
@@ -237,24 +258,17 @@ def main() -> None:
config = ProdDeploymentConfig(TAG=tag)
elif env == "staging":
config = StagingDeploymentConfig(TAG=tag)
- elif env == "crt":
- config = CrtDeploymentConfig(TAG=tag)
- elif env == "dev":
- config = DevDeploymentConfig(TAG=tag)
- elif env == "sandbox":
- config = SandboxDeploymentConfig(TAG=tag)
else:
print(f"[red]Invalid environment specified: {env}[/red]")
exit(1)
aws = Deploy(config)
aws.build_docker_image()
- aws.push_docker_image_to_ecr()
- aws.update_ecs_task()
- print(f"Deployment to {env} started.")
- print(f"A new image was built and pushed to ECR with tag: {tag}")
- print("A new Task definition was defined and registered.")
- print("Then we told the ECS service to deploy the new definition.")
- print("Monitor the deployment in the ECS console.")
+ if args.dry:
+ print("Dry run, not pushing image to ECR.")
+ else:
+ aws.push_docker_image_to_ecr()
+ print(f"A new image was built and pushed to ECR with tag: {tag}")
+ aws.update_ecs_task(dry=args.dry)
if __name__ == "__main__":
diff --git a/opentrons-ai-server/tests/helpers/client.py b/opentrons-ai-server/tests/helpers/client.py
index 7c0d2383ffd..bf5a7febb3c 100644
--- a/opentrons-ai-server/tests/helpers/client.py
+++ b/opentrons-ai-server/tests/helpers/client.py
@@ -3,6 +3,7 @@
from typing import Any, Callable, Optional, TypeVar
from api.models.chat_request import ChatRequest, FakeKeys
+from api.models.feedback_request import FeedbackRequest
from httpx import Client as HttpxClient
from httpx import Response, Timeout
from rich.console import Console, Group
@@ -68,10 +69,13 @@ def get_chat_completion(self, message: str, fake: bool = True, fake_key: Optiona
headers = self.standard_headers if not bad_auth else self.invalid_auth_headers
return self.httpx.post("/chat/completion", headers=headers, json=request.model_dump())
- def get_feedback(self, message: str, fake: bool = True) -> Response:
+ def post_feedback(self, message: str, fake: bool = True, bad_auth: bool = False) -> Response:
"""Call the /chat/feedback endpoint and return the response."""
- request = f'{"feedbackText": "{message}"}'
- return self.httpx.post("/chat/feedback", headers=self.standard_headers, json=request)
+ request: dict[str, Any] = {"message": message, "fake": fake}
+ if message != "":
+ request = FeedbackRequest(feedbackText=message, fake=fake).model_dump()
+ headers = self.standard_headers if not bad_auth else self.invalid_auth_headers
+ return self.httpx.post("/chat/feedback", headers=headers, json=request)
def get_bad_endpoint(self, bad_auth: bool = False) -> Response:
"""Call nonexistent endpoint and return the response."""
@@ -113,6 +117,11 @@ def main() -> None:
response = client.get_health()
print_response(response)
+ console.print(Rule("Submit feedback", style="bold"))
+ feedback_message = Prompt.ask("Enter feedback message")
+ response = client.post_feedback(feedback_message, fake=False)
+ print_response(response)
+
console.print(Rule("Getting chat completion with fake=True and good auth (won't call OpenAI)", style="bold"))
response = client.get_chat_completion("How do I load a pipette?")
print_response(response)
diff --git a/opentrons-ai-server/tests/test_google_sheets_sanatize.py b/opentrons-ai-server/tests/test_google_sheets_sanatize.py
new file mode 100644
index 00000000000..b7b8e3778f0
--- /dev/null
+++ b/opentrons-ai-server/tests/test_google_sheets_sanatize.py
@@ -0,0 +1,23 @@
+import pytest
+from api.integration.google_sheets import GoogleSheetsClient
+
+
+@pytest.mark.unit
+@pytest.mark.parametrize(
+ "input_text, expected_output",
+ [
+ ('Click here!', "Click here!"),
+ ('javascript:alert("Malicious code")', '"Malicious code")'),
+ ("Important message", "Important message"),
+ ("onload=\"alert('Attack')\" Hello!", "Hello!"),
+ ('=IMPORTRANGE("https://example.com/sheet", "Sheet1!A1")', 'IMPORTRANGE("https://example.com/sheet", "Sheet1!A1")'),
+ ("Hello, world!", "Hello, world!"),
+ ("link", "link"),
+ ("=SUM(A1:A10)", "SUM(A1:A10)"),
+ ('', ""),
+ ('<script>alert("test")</script>', 'alert("test")'),
+ ],
+)
+def test_sanitize_for_google_sheets(input_text: str, expected_output: str) -> None:
+ sanitized_text = GoogleSheetsClient.sanitize_for_google_sheets(input_text)
+ assert sanitized_text == expected_output, f"Expected '{expected_output}' but got '{sanitized_text}'"
diff --git a/opentrons-ai-server/tests/test_live.py b/opentrons-ai-server/tests/test_live.py
index ce22f4ff405..797d21fe7b6 100644
--- a/opentrons-ai-server/tests/test_live.py
+++ b/opentrons-ai-server/tests/test_live.py
@@ -1,5 +1,6 @@
import pytest
from api.models.chat_response import ChatResponse
+from api.models.error_response import ErrorResponse
from api.models.feedback_response import FeedbackResponse
from tests.helpers.client import Client
@@ -28,13 +29,39 @@ def test_get_chat_completion_bad_auth(client: Client) -> None:
@pytest.mark.live
-def test_get_feedback_good_auth(client: Client) -> None:
+def test_post_feedback_good_auth(client: Client) -> None:
"""Test the feedback endpoint with good authentication."""
- response = client.get_feedback("How do I load tipracks for my 8 channel pipette on an OT2?", fake=True)
+ response = client.post_feedback("Would be nice if it were faster", fake=False)
assert response.status_code == 200, "Feedback with good auth should return HTTP 200"
+ assert response.json()["reply"] == "Feedback Received and sanitized: Would be nice if it were faster", "Response should contain input"
FeedbackResponse.model_validate(response.json())
+@pytest.mark.live
+def test_post_empty_feedback_good_auth(client: Client) -> None:
+ """Test the feedback endpoint with good authentication."""
+ response = client.post_feedback("", fake=False)
+ assert response.status_code == 422, "Feedback with feebackText = '' should return HTTP 422"
+ ErrorResponse.model_validate(response.json())
+
+
+@pytest.mark.live
+def test_post_feedback_good_auth_fake(client: Client) -> None:
+ """Test the feedback endpoint with good authentication."""
+ response = client.post_feedback("More LLM", fake=True)
+ assert response.status_code == 200, "Fake response"
+ assert response.json()["fake"] is True, "Fake indicator should be True"
+ assert response.json()["reply"] == "Fake response", "Response should be 'Fake response'"
+ FeedbackResponse.model_validate(response.json())
+
+
+@pytest.mark.live
+def test_post_feedback_bad_auth(client: Client) -> None:
+ """Test the feedback endpoint with bad authentication."""
+ response = client.post_feedback("How do I load tipracks for my 8 channel pipette on an OT2?", fake=False, bad_auth=True)
+ assert response.status_code == 401, "Feedback with bad auth should return HTTP 401"
+
+
@pytest.mark.live
def test_get_bad_endpoint_with_good_auth(client: Client) -> None:
"""Test a nonexistent endpoint with good authentication."""
From 15de12be4a800cce313a56e67431e7dc8f281c6d Mon Sep 17 00:00:00 2001
From: connected-znaim <60662281+connected-znaim@users.noreply.github.com>
Date: Thu, 14 Nov 2024 09:28:56 -0500
Subject: [PATCH 04/31] fix(opentrons-ai-client): Fixed protocol regenerate
button (#16807)
# Overview
This functionality was broken as the app didn't know to use the new
update/createnew endpoints when regenerating vs completion endpoint
## Test Plan and Hands on Testing
## Changelog
## Review requests
## Risk assessment
---
opentrons-ai-client/src/OpentronsAIRoutes.tsx | 2 +-
.../src/molecules/ChatDisplay/index.tsx | 33 +++++++++++++++--
.../src/molecules/InputPrompt/index.tsx | 37 +++++++++++++++----
.../src/pages/CreateProtocol/index.tsx | 23 +++++++++++-
.../__tests__/UpdateProtocol.test.tsx | 0
.../UpdateProtocol/index.tsx | 24 ++++++++++--
opentrons-ai-client/src/resources/atoms.ts | 10 +++++
opentrons-ai-client/src/resources/types.ts | 1 +
.../resources/utils/createProtocolUtils.tsx | 1 +
.../api/models/create_protocol.py | 1 +
10 files changed, 117 insertions(+), 15 deletions(-)
rename opentrons-ai-client/src/{organisms => pages}/UpdateProtocol/__tests__/UpdateProtocol.test.tsx (100%)
rename opentrons-ai-client/src/{organisms => pages}/UpdateProtocol/index.tsx (93%)
diff --git a/opentrons-ai-client/src/OpentronsAIRoutes.tsx b/opentrons-ai-client/src/OpentronsAIRoutes.tsx
index 32d09f351cf..1b435ac4138 100644
--- a/opentrons-ai-client/src/OpentronsAIRoutes.tsx
+++ b/opentrons-ai-client/src/OpentronsAIRoutes.tsx
@@ -1,6 +1,6 @@
import { Route, Navigate, Routes } from 'react-router-dom'
import { Landing } from './pages/Landing'
-import { UpdateProtocol } from './organisms/UpdateProtocol'
+import { UpdateProtocol } from './pages/UpdateProtocol'
import type { RouteProps } from './resources/types'
import { Chat } from './pages/Chat'
diff --git a/opentrons-ai-client/src/molecules/ChatDisplay/index.tsx b/opentrons-ai-client/src/molecules/ChatDisplay/index.tsx
index 22dbee37f1a..7ebdf795ab8 100644
--- a/opentrons-ai-client/src/molecules/ChatDisplay/index.tsx
+++ b/opentrons-ai-client/src/molecules/ChatDisplay/index.tsx
@@ -26,7 +26,10 @@ import { useAtom } from 'jotai'
import {
chatDataAtom,
feedbackModalAtom,
+ regenerateProtocolAtom,
scrollToBottomAtom,
+ createProtocolChatAtom,
+ updateProtocolChatAtom,
} from '../../resources/atoms'
import { delay } from 'lodash'
import { useFormContext } from 'react-hook-form'
@@ -56,6 +59,9 @@ const StyledIcon = styled(Icon)`
export function ChatDisplay({ chat, chatId }: ChatDisplayProps): JSX.Element {
const { t } = useTranslation('protocol_generator')
const [isCopied, setIsCopied] = useState(false)
+ const [, setRegenerateProtocol] = useAtom(regenerateProtocolAtom)
+ const [createProtocolChat] = useAtom(createProtocolChatAtom)
+ const [updateProtocolChat] = useAtom(updateProtocolChatAtom)
const [, setShowFeedbackModal] = useAtom(feedbackModalAtom)
const { setValue } = useFormContext()
const [chatdata] = useAtom(chatDataAtom)
@@ -64,9 +70,30 @@ export function ChatDisplay({ chat, chatId }: ChatDisplayProps): JSX.Element {
const isUser = role === 'user'
const setInputFieldToCorrespondingRequest = (): void => {
- const prompt = chatdata.find(
- chat => chat.role === 'user' && chat.requestId === requestId
- )?.reply
+ let prompt = ''
+ if (
+ requestId.includes('NewProtocol') ||
+ requestId.includes('UpdateProtocol')
+ ) {
+ setRegenerateProtocol({
+ isCreateOrUpdateProtocol: true,
+ regenerate: true,
+ })
+ if (createProtocolChat.prompt !== '') {
+ prompt = createProtocolChat.prompt
+ } else {
+ prompt = updateProtocolChat.prompt
+ }
+ } else {
+ setRegenerateProtocol({
+ isCreateOrUpdateProtocol: false,
+ regenerate: true,
+ })
+ prompt =
+ chatdata.find(
+ chat => chat.role === 'user' && chat.requestId === requestId
+ )?.reply ?? ''
+ }
setScrollToBottom(!scrollToBottom)
setValue('userPrompt', prompt)
}
diff --git a/opentrons-ai-client/src/molecules/InputPrompt/index.tsx b/opentrons-ai-client/src/molecules/InputPrompt/index.tsx
index 56114535733..cc0ccd0f0d3 100644
--- a/opentrons-ai-client/src/molecules/InputPrompt/index.tsx
+++ b/opentrons-ai-client/src/molecules/InputPrompt/index.tsx
@@ -20,6 +20,7 @@ import {
chatDataAtom,
chatHistoryAtom,
createProtocolChatAtom,
+ regenerateProtocolAtom,
tokenAtom,
updateProtocolChatAtom,
} from '../../resources/atoms'
@@ -38,7 +39,11 @@ import {
} from '../../resources/constants'
import type { AxiosRequestConfig } from 'axios'
-import type { ChatData } from '../../resources/types'
+import type {
+ ChatData,
+ CreatePrompt,
+ UpdatePrompt,
+} from '../../resources/types'
export function InputPrompt(): JSX.Element {
const { t } = useTranslation('protocol_generator')
@@ -50,6 +55,9 @@ export function InputPrompt(): JSX.Element {
const [sendAutoFilledPrompt, setSendAutoFilledPrompt] = useState(
false
)
+ const [regenerateProtocol, setRegenerateProtocol] = useAtom(
+ regenerateProtocolAtom
+ )
const [, setChatData] = useAtom(chatDataAtom)
const [chatHistory, setChatHistory] = useAtom(chatHistoryAtom)
@@ -78,13 +86,24 @@ export function InputPrompt(): JSX.Element {
}
}, [watchUserPrompt])
+ useEffect(() => {
+ if (regenerateProtocol.regenerate) {
+ handleClick(regenerateProtocol.isCreateOrUpdateProtocol, true)
+ setRegenerateProtocol({
+ isCreateOrUpdateProtocol: false,
+ regenerate: false,
+ })
+ }
+ }, [regenerateProtocol])
+
const handleClick = async (
- isUpdateOrCreateRequest: boolean = false
+ isUpdateOrCreateRequest: boolean = false,
+ isRegenerateRequest: boolean = false
): Promise => {
- setRequestId(uuidv4() + getPreFixText(isUpdateOrCreateRequest))
-
+ const newRequestId = uuidv4() + getPreFixText(isUpdateOrCreateRequest)
+ setRequestId(newRequestId)
const userInput: ChatData = {
- requestId,
+ requestId: newRequestId,
role: 'user',
reply: watchUserPrompt,
}
@@ -106,7 +125,7 @@ export function InputPrompt(): JSX.Element {
method: 'POST',
headers,
data: isUpdateOrCreateRequest
- ? getUpdateOrCreatePrompt()
+ ? getUpdateOrCreatePrompt(isRegenerateRequest)
: {
message: watchUserPrompt,
history: chatHistory,
@@ -126,7 +145,11 @@ export function InputPrompt(): JSX.Element {
}
}
- const getUpdateOrCreatePrompt = (): any => {
+ const getUpdateOrCreatePrompt = (
+ isRegenerateRequest: boolean
+ ): CreatePrompt | UpdatePrompt => {
+ createProtocol.regenerate = isRegenerateRequest
+ updateProtocol.regenerate = isRegenerateRequest
return isNewProtocol ? createProtocol : updateProtocol
}
diff --git a/opentrons-ai-client/src/pages/CreateProtocol/index.tsx b/opentrons-ai-client/src/pages/CreateProtocol/index.tsx
index 050f4eca8e1..5adb9ac07d1 100644
--- a/opentrons-ai-client/src/pages/CreateProtocol/index.tsx
+++ b/opentrons-ai-client/src/pages/CreateProtocol/index.tsx
@@ -9,6 +9,8 @@ import { useEffect, useRef, useState } from 'react'
import { PromptPreview } from '../../molecules/PromptPreview'
import { useForm, FormProvider } from 'react-hook-form'
import {
+ chatDataAtom,
+ chatHistoryAtom,
createProtocolAtom,
createProtocolChatAtom,
headerWithMeterAtom,
@@ -55,6 +57,8 @@ export function CreateProtocol(): JSX.Element | null {
)
const [, setCreateProtocolChatAtom] = useAtom(createProtocolChatAtom)
const [, setUpdateProtocolChatAtom] = useAtom(updateProtocolChatAtom)
+ const [, setChatHistoryAtom] = useAtom(chatHistoryAtom)
+ const [, setChatData] = useAtom(chatDataAtom)
const navigate = useNavigate()
const trackEvent = useTrackEvent()
const [leftWidth, setLeftWidth] = useState(50)
@@ -79,8 +83,23 @@ export function CreateProtocol(): JSX.Element | null {
},
})
- // Reset the update protocol chat atom when navigating to the create protocol page
+ // Reset the chat data atom and protocol atoms when navigating to the update protocol page
useEffect(() => {
+ setCreateProtocolChatAtom({
+ prompt: '',
+ regenerate: false,
+ scientific_application_type: '',
+ description: '',
+ robots: 'opentrons_flex',
+ mounts: [],
+ flexGripper: false,
+ modules: [],
+ labware: [],
+ liquids: [],
+ steps: [],
+ fake: false,
+ fake_id: 0,
+ })
setUpdateProtocolChatAtom({
prompt: '',
protocol_text: '',
@@ -90,6 +109,8 @@ export function CreateProtocol(): JSX.Element | null {
fake: false,
fake_id: 0,
})
+ setChatHistoryAtom([])
+ setChatData([])
}, [])
useEffect(() => {
diff --git a/opentrons-ai-client/src/organisms/UpdateProtocol/__tests__/UpdateProtocol.test.tsx b/opentrons-ai-client/src/pages/UpdateProtocol/__tests__/UpdateProtocol.test.tsx
similarity index 100%
rename from opentrons-ai-client/src/organisms/UpdateProtocol/__tests__/UpdateProtocol.test.tsx
rename to opentrons-ai-client/src/pages/UpdateProtocol/__tests__/UpdateProtocol.test.tsx
diff --git a/opentrons-ai-client/src/organisms/UpdateProtocol/index.tsx b/opentrons-ai-client/src/pages/UpdateProtocol/index.tsx
similarity index 93%
rename from opentrons-ai-client/src/organisms/UpdateProtocol/index.tsx
rename to opentrons-ai-client/src/pages/UpdateProtocol/index.tsx
index 4e13e5dfc98..e1a260113a7 100644
--- a/opentrons-ai-client/src/organisms/UpdateProtocol/index.tsx
+++ b/opentrons-ai-client/src/pages/UpdateProtocol/index.tsx
@@ -20,9 +20,11 @@ import { Trans, useTranslation } from 'react-i18next'
import { FileUpload } from '../../molecules/FileUpload'
import { useNavigate } from 'react-router-dom'
import {
+ chatHistoryAtom,
createProtocolChatAtom,
headerWithMeterAtom,
updateProtocolChatAtom,
+ chatDataAtom,
} from '../../resources/atoms'
import { CSSTransition } from 'react-transition-group'
import { useAtom } from 'jotai'
@@ -105,16 +107,19 @@ export function UpdateProtocol(): JSX.Element {
const [headerState, setHeaderWithMeterAtom] = useAtom(headerWithMeterAtom)
const [updateType, setUpdateType] = useState(null)
const [detailsValue, setDetailsValue] = useState('')
- const [, setUpdatePromptAtom] = useAtom(updateProtocolChatAtom)
+ const [, setUpdateProtocolChatAtom] = useAtom(updateProtocolChatAtom)
const [, setCreateProtocolChatAtom] = useAtom(createProtocolChatAtom)
+ const [, setChatHistoryAtom] = useAtom(chatHistoryAtom)
+ const [, setChatData] = useAtom(chatDataAtom)
const [fileValue, setFile] = useState(null)
const [pythonText, setPythonTextValue] = useState('')
const [errorText, setErrorText] = useState(null)
- // Reset the create protocol chat atom when navigating to the update protocol page
+ // Reset the chat data atom and protocol atoms when navigating to the update protocol page
useEffect(() => {
setCreateProtocolChatAtom({
prompt: '',
+ regenerate: false,
scientific_application_type: '',
description: '',
robots: 'opentrons_flex',
@@ -127,6 +132,17 @@ export function UpdateProtocol(): JSX.Element {
fake: false,
fake_id: 0,
})
+ setUpdateProtocolChatAtom({
+ prompt: '',
+ protocol_text: '',
+ regenerate: false,
+ update_type: 'adapt_python_protocol',
+ update_details: '',
+ fake: false,
+ fake_id: 0,
+ })
+ setChatHistoryAtom([])
+ setChatData([])
}, [])
useEffect(() => {
@@ -193,7 +209,9 @@ export function UpdateProtocol(): JSX.Element {
const chatPrompt = `${introText}${originalCodeText}${updateTypeText}${detailsText}`
- setUpdatePromptAtom({
+ console.log(chatPrompt)
+
+ setUpdateProtocolChatAtom({
prompt: chatPrompt,
protocol_text: pythonText,
regenerate: false,
diff --git a/opentrons-ai-client/src/resources/atoms.ts b/opentrons-ai-client/src/resources/atoms.ts
index 40ddce7fc53..adbd81d010f 100644
--- a/opentrons-ai-client/src/resources/atoms.ts
+++ b/opentrons-ai-client/src/resources/atoms.ts
@@ -16,6 +16,7 @@ export const chatDataAtom = atom([])
/** CreateProtocolChatAtom is for the prefilled userprompt when navigating to the chat page from Create New protocol page */
export const createProtocolChatAtom = atom({
prompt: '',
+ regenerate: false,
scientific_application_type: '',
description: '',
robots: 'opentrons_flex',
@@ -40,6 +41,15 @@ export const updateProtocolChatAtom = atom({
fake_id: 0,
})
+/** Regenerate protocol atom */
+export const regenerateProtocolAtom = atom<{
+ isCreateOrUpdateProtocol: boolean
+ regenerate: boolean
+}>({
+ isCreateOrUpdateProtocol: false,
+ regenerate: false,
+})
+
/** Scroll to bottom of chat atom */
export const scrollToBottomAtom = atom(false)
diff --git a/opentrons-ai-client/src/resources/types.ts b/opentrons-ai-client/src/resources/types.ts
index 516f87e9354..7e16e1a8642 100644
--- a/opentrons-ai-client/src/resources/types.ts
+++ b/opentrons-ai-client/src/resources/types.ts
@@ -15,6 +15,7 @@ export interface ChatData {
export interface CreatePrompt {
/** the prompt that is generated by the create protocol page */
prompt: string
+ regenerate: boolean
scientific_application_type: string
description: string
robots: 'opentrons_flex' | 'opentrons_ot2' | string
diff --git a/opentrons-ai-client/src/resources/utils/createProtocolUtils.tsx b/opentrons-ai-client/src/resources/utils/createProtocolUtils.tsx
index 3b574e11f10..b7483c40610 100644
--- a/opentrons-ai-client/src/resources/utils/createProtocolUtils.tsx
+++ b/opentrons-ai-client/src/resources/utils/createProtocolUtils.tsx
@@ -230,6 +230,7 @@ export function generateChatPrompt(
setCreateProtocolChatAtom({
prompt,
+ regenerate: false,
scientific_application_type: values.application.scientificApplication,
description,
robots: values.instruments.robot,
diff --git a/opentrons-ai-server/api/models/create_protocol.py b/opentrons-ai-server/api/models/create_protocol.py
index 5b011284848..f94d87d2bf8 100644
--- a/opentrons-ai-server/api/models/create_protocol.py
+++ b/opentrons-ai-server/api/models/create_protocol.py
@@ -5,6 +5,7 @@
class CreateProtocol(BaseModel):
prompt: str = Field(..., description="Prompt")
+ regenerate: bool = Field(..., description="Flag to indicate if regeneration is needed")
scientific_application_type: str = Field(..., description="Scientific application type")
description: str = Field(..., description="Description of the protocol")
robots: Literal["opentrons_flex", "opentrons_ot2"] = Field(..., description="List of required robots")
From c918991fef0269395718d5ca35e74d57b4b2a251 Mon Sep 17 00:00:00 2001
From: Nick Diehl <47604184+ncdiehl11@users.noreply.github.com>
Date: Thu, 14 Nov 2024 09:29:13 -0500
Subject: [PATCH 05/31] fix(protocol-designer): fix WellOrderModal image and
reset bugs (#16795)
This PR fixes 2 bugs in the `WellOrderModal` component.
1. The first bug arose when attempting to set both primary and secondary
order to the same axis. This is fixed by filtering secondary order based
on the selected primary order.
2. The second bug stemmed from using a stale state when applying changes
and closing the modal after reset-- our helper function to reset values
to default set state and applied changes in the same render, resulting
in old values being applied. Here, I fix this by directly applying the
new values on reset.
Closes RQA-3531, Closes RQA-3532
---
.../src/organisms/WellOrderModal/index.tsx | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/protocol-designer/src/organisms/WellOrderModal/index.tsx b/protocol-designer/src/organisms/WellOrderModal/index.tsx
index 91a7406104e..cb0d7d64ee4 100644
--- a/protocol-designer/src/organisms/WellOrderModal/index.tsx
+++ b/protocol-designer/src/organisms/WellOrderModal/index.tsx
@@ -92,8 +92,7 @@ export function WellOrderModal(props: WellOrderModalProps): JSX.Element | null {
}
const handleReset = (): void => {
- setWellOrder({ firstValue: DEFAULT_FIRST, secondValue: DEFAULT_SECOND })
- applyChanges()
+ updateValues(DEFAULT_FIRST, DEFAULT_SECOND)
closeModal()
}
@@ -144,6 +143,13 @@ export function WellOrderModal(props: WellOrderModalProps): JSX.Element | null {
if (!isOpen) return null
+ let secondaryOptions = WELL_ORDER_VALUES
+ if (VERTICAL_VALUES.includes(wellOrder.firstValue)) {
+ secondaryOptions = HORIZONTAL_VALUES
+ } else if (HORIZONTAL_VALUES.includes(wellOrder.firstValue)) {
+ secondaryOptions = VERTICAL_VALUES
+ }
+
return createPortal(
({
+ filterOptions={secondaryOptions.map(value => ({
value,
name: t(`step_edit_form.field.well_order.option.${value}`),
disabled: isSecondOptionDisabled(value),
From 22940d1eacea36bcadfef1a9b4109bc4b65662f0 Mon Sep 17 00:00:00 2001
From: connected-znaim <60662281+connected-znaim@users.noreply.github.com>
Date: Thu, 14 Nov 2024 09:42:21 -0500
Subject: [PATCH 06/31] fix(opentrons-ai-client): Stop the spinner from looping
over the texts (#16809)
# Overview
The spinner was initially designed to loop over the progress texts. Now
it stops at finalize and takes 10 seconds to iterate over each progress
text.
## Test Plan and Hands on Testing
## Changelog
## Review requests
## Risk assessment
---
opentrons-ai-client/src/atoms/SendButton/index.tsx | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/opentrons-ai-client/src/atoms/SendButton/index.tsx b/opentrons-ai-client/src/atoms/SendButton/index.tsx
index ed4128e56ca..0bf4ff959ed 100644
--- a/opentrons-ai-client/src/atoms/SendButton/index.tsx
+++ b/opentrons-ai-client/src/atoms/SendButton/index.tsx
@@ -67,11 +67,14 @@ export function SendButton({
if (isLoading) {
const interval = setInterval(() => {
setProgressIndex(prevIndex => {
- const newIndex = (prevIndex + 1) % progressTexts.length
+ let newIndex = prevIndex + 1
+ if (newIndex > progressTexts.length - 1) {
+ newIndex = progressTexts.length - 1
+ }
setButtonText(progressTexts[newIndex])
return newIndex
})
- }, 5000)
+ }, 10000)
return () => {
setProgressIndex(0)
From fb62ffc3f0851ce3f76ee471cc84c79040492441 Mon Sep 17 00:00:00 2001
From: connected-znaim <60662281+connected-znaim@users.noreply.github.com>
Date: Thu, 14 Nov 2024 10:16:11 -0500
Subject: [PATCH 07/31] fix(opentrons-ai-client): Navigate to landing page when
refreshing chat page (#16810)
# Overview
Before the app would just show an empty chat screen when refreshed. Now
it will navigate to the landing page
## Test Plan and Hands on Testing
## Changelog
## Review requests
## Risk assessment
---
.../src/pages/Chat/__tests__/Chat.test.tsx | 17 ++++++++++++++++-
opentrons-ai-client/src/pages/Chat/index.tsx | 8 ++++++++
2 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/opentrons-ai-client/src/pages/Chat/__tests__/Chat.test.tsx b/opentrons-ai-client/src/pages/Chat/__tests__/Chat.test.tsx
index 77874086534..ad17acd26fd 100644
--- a/opentrons-ai-client/src/pages/Chat/__tests__/Chat.test.tsx
+++ b/opentrons-ai-client/src/pages/Chat/__tests__/Chat.test.tsx
@@ -1,15 +1,25 @@
import { screen } from '@testing-library/react'
-import { describe, it, vi, beforeEach } from 'vitest'
+import { describe, it, vi, beforeEach, expect } from 'vitest'
import { renderWithProviders } from '../../../__testing-utils__'
import { i18n } from '../../../i18n'
import { PromptGuide } from '../../../molecules/PromptGuide'
import { ChatFooter } from '../../../molecules/ChatFooter'
import { Chat } from '../index'
+import type { NavigateFunction } from 'react-router-dom'
vi.mock('../../../molecules/PromptGuide')
vi.mock('../../../molecules/ChatFooter')
// Note (kk:05/20/2024) to avoid TypeError: scrollRef.current.scrollIntoView is not a function
window.HTMLElement.prototype.scrollIntoView = vi.fn()
+const mockNavigate = vi.fn()
+
+vi.mock('react-router-dom', async importOriginal => {
+ const reactRouterDom = await importOriginal()
+ return {
+ ...reactRouterDom,
+ useNavigate: () => mockNavigate,
+ }
+})
const render = (): ReturnType => {
return renderWithProviders(, {
@@ -28,6 +38,11 @@ describe('Chat', () => {
screen.getByText('mock ChatFooter')
})
+ it('should navigate to home if chatData is empty', () => {
+ render()
+ expect(mockNavigate).toHaveBeenCalledWith('/')
+ })
+
it.skip('should not show the feedback modal when loading the page', () => {
render()
screen.getByText('Send feedback to Opentrons')
diff --git a/opentrons-ai-client/src/pages/Chat/index.tsx b/opentrons-ai-client/src/pages/Chat/index.tsx
index 7bedeb8dffe..82322996b34 100644
--- a/opentrons-ai-client/src/pages/Chat/index.tsx
+++ b/opentrons-ai-client/src/pages/Chat/index.tsx
@@ -12,6 +12,7 @@ import { ChatDisplay } from '../../molecules/ChatDisplay'
import { ChatFooter } from '../../molecules/ChatFooter'
import styled from 'styled-components'
import { FeedbackModal } from '../../molecules/FeedbackModal'
+import { useNavigate } from 'react-router-dom'
export interface InputType {
userPrompt: string
@@ -28,6 +29,13 @@ export function Chat(): JSX.Element | null {
const scrollRef = useRef(null)
const [showFeedbackModal] = useAtom(feedbackModalAtom)
const [scrollToBottom] = useAtom(scrollToBottomAtom)
+ const navigate = useNavigate()
+
+ useEffect(() => {
+ if (chatData.length === 0) {
+ navigate('/')
+ }
+ }, [])
useEffect(() => {
if (scrollRef.current != null)
From b73476b4effd6ac7222e8181c401063c252dca73 Mon Sep 17 00:00:00 2001
From: Shlok Amin
Date: Thu, 14 Nov 2024 10:25:01 -0500
Subject: [PATCH 08/31] feat(opentrons-ai-client): only load latest labware
defs (#16811)
---
.../ControlledLabwareListItems/index.tsx | 4 +-
.../molecules/ModuleListItemGroup/index.tsx | 4 +-
.../src/organisms/LabwareModal/index.tsx | 4 +-
.../resources/utils/createProtocolUtils.tsx | 6 +--
.../src/resources/utils/labware.ts | 46 +++++++++++++++++--
5 files changed, 50 insertions(+), 14 deletions(-)
diff --git a/opentrons-ai-client/src/molecules/ControlledLabwareListItems/index.tsx b/opentrons-ai-client/src/molecules/ControlledLabwareListItems/index.tsx
index f79f89ca858..507aa0b9392 100644
--- a/opentrons-ai-client/src/molecules/ControlledLabwareListItems/index.tsx
+++ b/opentrons-ai-client/src/molecules/ControlledLabwareListItems/index.tsx
@@ -14,7 +14,7 @@ import { getLabwareDisplayName } from '@opentrons/shared-data'
import { LabwareDiagram } from '../../molecules/LabwareDiagram'
import type { DisplayLabware } from '../../organisms/LabwareLiquidsSection'
import { LABWARES_FIELD_NAME } from '../../organisms/LabwareLiquidsSection'
-import { getAllDefinitions } from '../../resources/utils'
+import { getOnlyLatestDefs } from '../../resources/utils'
export function ControlledLabwareListItems(): JSX.Element | null {
const { t } = useTranslation('create_protocol')
@@ -22,7 +22,7 @@ export function ControlledLabwareListItems(): JSX.Element | null {
const labwares: DisplayLabware[] = watch(LABWARES_FIELD_NAME) ?? []
- const defs = getAllDefinitions()
+ const defs = getOnlyLatestDefs()
return (
Object.values(getAllDefinitions()),
+ () => Object.values(getOnlyLatestDefs()),
[]
)
diff --git a/opentrons-ai-client/src/organisms/LabwareModal/index.tsx b/opentrons-ai-client/src/organisms/LabwareModal/index.tsx
index 28324b18dee..0fcb6b17de1 100644
--- a/opentrons-ai-client/src/organisms/LabwareModal/index.tsx
+++ b/opentrons-ai-client/src/organisms/LabwareModal/index.tsx
@@ -19,7 +19,7 @@ import { createPortal } from 'react-dom'
import { reduce } from 'lodash'
import { ListButtonCheckbox } from '../../atoms/ListButtonCheckbox/ListButtonCheckbox'
import { LABWARES_FIELD_NAME } from '../LabwareLiquidsSection'
-import { getAllDefinitions } from '../../resources/utils'
+import { getOnlyLatestDefs } from '../../resources/utils'
import type { DisplayLabware } from '../LabwareLiquidsSection'
import type {
LabwareDefByDefURI,
@@ -56,7 +56,7 @@ export function LabwareModal({
const searchFilter = (termToCheck: string): boolean =>
termToCheck.toLowerCase().includes(searchTerm.toLowerCase())
- const defs = getAllDefinitions()
+ const defs = getOnlyLatestDefs()
const labwareByCategory: Record<
string,
diff --git a/opentrons-ai-client/src/resources/utils/createProtocolUtils.tsx b/opentrons-ai-client/src/resources/utils/createProtocolUtils.tsx
index b7483c40610..cb59f6e9694 100644
--- a/opentrons-ai-client/src/resources/utils/createProtocolUtils.tsx
+++ b/opentrons-ai-client/src/resources/utils/createProtocolUtils.tsx
@@ -13,7 +13,7 @@ import {
} from '../../organisms/InstrumentsSection'
import type { UseFormWatch } from 'react-hook-form'
import type { CreateProtocolFormData } from '../../pages/CreateProtocol'
-import { getAllDefinitions } from './labware'
+import { getOnlyLatestDefs } from './labware'
import type { CreatePrompt } from '../types'
export function generatePromptPreviewApplicationItems(
@@ -92,7 +92,7 @@ export function generatePromptPreviewLabwareLiquidsItems(
const { labwares, liquids } = watch()
const items: string[] = []
- const defs = getAllDefinitions()
+ const defs = getOnlyLatestDefs()
labwares?.forEach(labware => {
items.push(
@@ -159,7 +159,7 @@ export function generateChatPrompt(
args_0: CreatePrompt | ((prev: CreatePrompt) => CreatePrompt)
) => void
): string {
- const defs = getAllDefinitions()
+ const defs = getOnlyLatestDefs()
const robotType = t(values.instruments.robot)
const scientificApplication = t(values.application.scientificApplication)
diff --git a/opentrons-ai-client/src/resources/utils/labware.ts b/opentrons-ai-client/src/resources/utils/labware.ts
index b0844c57a70..f7bf0ddf427 100644
--- a/opentrons-ai-client/src/resources/utils/labware.ts
+++ b/opentrons-ai-client/src/resources/utils/labware.ts
@@ -2,16 +2,52 @@ import {
LABWAREV2_DO_NOT_LIST,
RETIRED_LABWARE,
getAllDefinitions as _getAllDefinitions,
+ getLabwareDefURI,
+} from '@opentrons/shared-data'
+import { groupBy } from 'lodash'
+import type {
+ LabwareDefByDefURI,
+ LabwareDefinition2,
} from '@opentrons/shared-data'
-import type { LabwareDefByDefURI } from '@opentrons/shared-data'
let _definitions: LabwareDefByDefURI | null = null
+
+const BLOCK_LIST = [...RETIRED_LABWARE, ...LABWAREV2_DO_NOT_LIST]
+
export function getAllDefinitions(): LabwareDefByDefURI {
if (_definitions == null) {
- _definitions = _getAllDefinitions([
- ...RETIRED_LABWARE,
- ...LABWAREV2_DO_NOT_LIST,
- ])
+ _definitions = _getAllDefinitions(BLOCK_LIST)
}
return _definitions
}
+
+// filter out all but the latest version of each labware
+// NOTE: this is similar to labware-library's getOnlyLatestDefs, but this one
+// has the {labwareDefURI: def} shape, instead of an array of labware defs
+let _latestDefs: LabwareDefByDefURI | null = null
+export function getOnlyLatestDefs(): LabwareDefByDefURI {
+ if (!_latestDefs) {
+ const allDefs = getAllDefinitions()
+ const allURIs = Object.keys(allDefs)
+ const labwareDefGroups: Record = groupBy(
+ allURIs.map((uri: string) => allDefs[uri]),
+ d => `${d.namespace}/${d.parameters.loadName}`
+ )
+ _latestDefs = Object.keys(labwareDefGroups).reduce(
+ (acc, groupKey: string) => {
+ const group = labwareDefGroups[groupKey]
+ const allVersions = group.map(d => d.version)
+ const highestVersionNum = Math.max(...allVersions)
+ const resultIdx = group.findIndex(d => d.version === highestVersionNum)
+ const latestDefInGroup = group[resultIdx]
+ return {
+ ...acc,
+ [getLabwareDefURI(latestDefInGroup)]: latestDefInGroup,
+ }
+ },
+ {}
+ )
+ }
+
+ return _latestDefs
+}
From e6524c932bf0f10a1e5314d60199c88836d95ddc Mon Sep 17 00:00:00 2001
From: fbelginetw <167361860+fbelginetw@users.noreply.github.com>
Date: Thu, 14 Nov 2024 10:56:04 -0500
Subject: [PATCH 09/31] fix: send other application correctly in case the
option other is selected (#16812)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
…
# Overview
## Test Plan and Hands on Testing
## Changelog
## Review requests
## Risk assessment
---
opentrons-ai-client/src/pages/CreateProtocol/index.tsx | 2 +-
.../src/resources/utils/createProtocolUtils.tsx | 5 ++++-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/opentrons-ai-client/src/pages/CreateProtocol/index.tsx b/opentrons-ai-client/src/pages/CreateProtocol/index.tsx
index 5adb9ac07d1..674df6419bf 100644
--- a/opentrons-ai-client/src/pages/CreateProtocol/index.tsx
+++ b/opentrons-ai-client/src/pages/CreateProtocol/index.tsx
@@ -31,7 +31,7 @@ import { ResizeBar } from '../../atoms/ResizeBar'
export interface CreateProtocolFormData {
application: {
scientificApplication: string
- otherApplication?: string
+ otherApplication: string
description: string
}
instruments: {
diff --git a/opentrons-ai-client/src/resources/utils/createProtocolUtils.tsx b/opentrons-ai-client/src/resources/utils/createProtocolUtils.tsx
index cb59f6e9694..a2ccffd988b 100644
--- a/opentrons-ai-client/src/resources/utils/createProtocolUtils.tsx
+++ b/opentrons-ai-client/src/resources/utils/createProtocolUtils.tsx
@@ -231,7 +231,10 @@ export function generateChatPrompt(
setCreateProtocolChatAtom({
prompt,
regenerate: false,
- scientific_application_type: values.application.scientificApplication,
+ scientific_application_type:
+ values.application.scientificApplication === OTHER
+ ? values.application.otherApplication
+ : values.application.scientificApplication,
description,
robots: values.instruments.robot,
mounts,
From e569ab48ba4d0064312d9a8785d2c43a796de2bc Mon Sep 17 00:00:00 2001
From: connected-znaim <60662281+connected-znaim@users.noreply.github.com>
Date: Thu, 14 Nov 2024 11:04:00 -0500
Subject: [PATCH 10/31] Revert "fix(opentrons-ai-client): Navigate to landing
page when refreshing chat page" (#16817)
Reverts Opentrons/opentrons#16810
---
.../src/pages/Chat/__tests__/Chat.test.tsx | 17 +----------------
opentrons-ai-client/src/pages/Chat/index.tsx | 8 --------
2 files changed, 1 insertion(+), 24 deletions(-)
diff --git a/opentrons-ai-client/src/pages/Chat/__tests__/Chat.test.tsx b/opentrons-ai-client/src/pages/Chat/__tests__/Chat.test.tsx
index ad17acd26fd..77874086534 100644
--- a/opentrons-ai-client/src/pages/Chat/__tests__/Chat.test.tsx
+++ b/opentrons-ai-client/src/pages/Chat/__tests__/Chat.test.tsx
@@ -1,25 +1,15 @@
import { screen } from '@testing-library/react'
-import { describe, it, vi, beforeEach, expect } from 'vitest'
+import { describe, it, vi, beforeEach } from 'vitest'
import { renderWithProviders } from '../../../__testing-utils__'
import { i18n } from '../../../i18n'
import { PromptGuide } from '../../../molecules/PromptGuide'
import { ChatFooter } from '../../../molecules/ChatFooter'
import { Chat } from '../index'
-import type { NavigateFunction } from 'react-router-dom'
vi.mock('../../../molecules/PromptGuide')
vi.mock('../../../molecules/ChatFooter')
// Note (kk:05/20/2024) to avoid TypeError: scrollRef.current.scrollIntoView is not a function
window.HTMLElement.prototype.scrollIntoView = vi.fn()
-const mockNavigate = vi.fn()
-
-vi.mock('react-router-dom', async importOriginal => {
- const reactRouterDom = await importOriginal()
- return {
- ...reactRouterDom,
- useNavigate: () => mockNavigate,
- }
-})
const render = (): ReturnType => {
return renderWithProviders(, {
@@ -38,11 +28,6 @@ describe('Chat', () => {
screen.getByText('mock ChatFooter')
})
- it('should navigate to home if chatData is empty', () => {
- render()
- expect(mockNavigate).toHaveBeenCalledWith('/')
- })
-
it.skip('should not show the feedback modal when loading the page', () => {
render()
screen.getByText('Send feedback to Opentrons')
diff --git a/opentrons-ai-client/src/pages/Chat/index.tsx b/opentrons-ai-client/src/pages/Chat/index.tsx
index 82322996b34..7bedeb8dffe 100644
--- a/opentrons-ai-client/src/pages/Chat/index.tsx
+++ b/opentrons-ai-client/src/pages/Chat/index.tsx
@@ -12,7 +12,6 @@ import { ChatDisplay } from '../../molecules/ChatDisplay'
import { ChatFooter } from '../../molecules/ChatFooter'
import styled from 'styled-components'
import { FeedbackModal } from '../../molecules/FeedbackModal'
-import { useNavigate } from 'react-router-dom'
export interface InputType {
userPrompt: string
@@ -29,13 +28,6 @@ export function Chat(): JSX.Element | null {
const scrollRef = useRef(null)
const [showFeedbackModal] = useAtom(feedbackModalAtom)
const [scrollToBottom] = useAtom(scrollToBottomAtom)
- const navigate = useNavigate()
-
- useEffect(() => {
- if (chatData.length === 0) {
- navigate('/')
- }
- }, [])
useEffect(() => {
if (scrollRef.current != null)
From 3dfbca055586fd2c893a62de2502fb49ff4752e0 Mon Sep 17 00:00:00 2001
From: koji
Date: Thu, 14 Nov 2024 11:08:47 -0500
Subject: [PATCH 11/31] fix(protocol-designer): fix protocol description text
wrap issue in overview page (#16806)
* fix(protocol-designer): fix protocol description text wrap issue in overview page
---
.../src/pages/ProtocolOverview/ProtocolMetadata.tsx | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/protocol-designer/src/pages/ProtocolOverview/ProtocolMetadata.tsx b/protocol-designer/src/pages/ProtocolOverview/ProtocolMetadata.tsx
index b29cdc1fbc6..d750edaaad5 100644
--- a/protocol-designer/src/pages/ProtocolOverview/ProtocolMetadata.tsx
+++ b/protocol-designer/src/pages/ProtocolOverview/ProtocolMetadata.tsx
@@ -12,7 +12,7 @@ import {
TYPOGRAPHY,
} from '@opentrons/components'
-import { BUTTON_LINK_STYLE } from '../../atoms'
+import { BUTTON_LINK_STYLE, LINE_CLAMP_TEXT_STYLE } from '../../atoms'
const REQUIRED_APP_VERSION = '8.2.0'
@@ -74,7 +74,10 @@ export function ProtocolMetadata({
}
content={
-
+
{value ?? t('na')}
}
From 3db8a402bee2dbf3c528380bad9767990f633e80 Mon Sep 17 00:00:00 2001
From: koji
Date: Thu, 14 Nov 2024 11:32:16 -0500
Subject: [PATCH 12/31] fix(protocol-designer): eppendorf tip names cut off
issue (#16820)
* fix(protocol-designer): eppendorf tip names cut off issue
---
components/src/atoms/Checkbox/index.tsx | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/components/src/atoms/Checkbox/index.tsx b/components/src/atoms/Checkbox/index.tsx
index 02fa36da6d4..8ace61cb0bf 100644
--- a/components/src/atoms/Checkbox/index.tsx
+++ b/components/src/atoms/Checkbox/index.tsx
@@ -13,7 +13,6 @@ import {
} from '../../styles'
import { RESPONSIVENESS, SPACING } from '../../ui-style-constants'
import { StyledText } from '../StyledText'
-import { truncateString } from '../../utils'
export interface CheckboxProps {
/** checkbox is checked if value is true */
@@ -41,7 +40,6 @@ export function Checkbox(props: CheckboxProps): JSX.Element {
width = FLEX_MAX_CONTENT,
type = 'round',
} = props
- const truncatedLabel = truncateString(labelText, 25)
const CHECKBOX_STYLE = css`
width: ${width};
@@ -89,7 +87,7 @@ export function Checkbox(props: CheckboxProps): JSX.Element {
css={CHECKBOX_STYLE}
>
- {truncatedLabel}
+ {labelText}
From cb147fd9bb6532c101bd66cff82d0348c922e6f9 Mon Sep 17 00:00:00 2001
From: koji
Date: Thu, 14 Nov 2024 11:53:50 -0500
Subject: [PATCH 13/31] fix(protocol-designer): fix error msg display in
LiquidToolbox (#16816)
* fix(protocol-designer): fix error msg display in LiquidToolbox
---
.../src/organisms/AssignLiquidsModal/LiquidToolbox.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/protocol-designer/src/organisms/AssignLiquidsModal/LiquidToolbox.tsx b/protocol-designer/src/organisms/AssignLiquidsModal/LiquidToolbox.tsx
index ef5650a6baf..1b2067bf534 100644
--- a/protocol-designer/src/organisms/AssignLiquidsModal/LiquidToolbox.tsx
+++ b/protocol-designer/src/organisms/AssignLiquidsModal/LiquidToolbox.tsx
@@ -53,7 +53,7 @@ interface LiquidToolboxProps {
}
export function LiquidToolbox(props: LiquidToolboxProps): JSX.Element {
const { onClose } = props
- const { t } = useTranslation(['liquids', 'shared'])
+ const { t } = useTranslation(['liquids', 'form', 'shared'])
const dispatch = useDispatch()
const [showDefineLiquidModal, setDefineLiquidModal] = useState(false)
const liquids = useSelector(labwareIngredSelectors.allIngredientNamesIds)
@@ -186,7 +186,7 @@ export function LiquidToolbox(props: LiquidToolboxProps): JSX.Element {
if (volume == null || volume === '0') {
volumeErrors = t('generic.error.more_than_zero')
} else if (parseInt(volume) > selectedWellsMaxVolume) {
- volumeErrors = t('liquid_placement.volume_exceeded', {
+ volumeErrors = t('form:liquid_placement.volume_exceeded', {
volume: selectedWellsMaxVolume,
})
}
From 3c4c33c4dd5d710d10879d37e26648ccc73212f3 Mon Sep 17 00:00:00 2001
From: connected-znaim <60662281+connected-znaim@users.noreply.github.com>
Date: Thu, 14 Nov 2024 12:22:20 -0500
Subject: [PATCH 14/31] fix(opentrons-ai-client): Text fixes (#16821)
# Overview
## Test Plan and Hands on Testing
## Changelog
## Review requests
## Risk assessment
---
.../src/assets/localization/en/protocol_generator.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/opentrons-ai-client/src/assets/localization/en/protocol_generator.json b/opentrons-ai-client/src/assets/localization/en/protocol_generator.json
index 94b1afae702..a4d89e97303 100644
--- a/opentrons-ai-client/src/assets/localization/en/protocol_generator.json
+++ b/opentrons-ai-client/src/assets/localization/en/protocol_generator.json
@@ -30,10 +30,10 @@
"login": "Login",
"logout": "Logout",
"make_sure_your_prompt": "Write a prompt in a natural language for OpentronsAI to generate a protocol using the Opentrons Python Protocol API v2. The better the prompt, the better the quality of the protocol produced by OpentronsAI.",
- "modify_intro": "Modify the following Python code using the Opentrons Python Protocol API v2. Ensure that the new labware and pipettes are compatible with the Flex robot. Ensure that you perform the correct Type of Update use the Details of Changes.\n\n",
+ "modify_intro": "Modify the following Python code using the Opentrons Python Protocol API v2. Ensure that the new labware and pipettes are compatible with the Flex robot.\n\n",
"modify_python_code": "Original Python Code:\n",
"modify_type_of_update": "Type of update:\n- ",
- "modify_details_of_change": "Details of Changes:\n- ",
+ "modify_details_of_change": "Detail of changes:\n- ",
"modules_and_adapters": "Modules and adapters: Specify the modules and labware adapters required by your protocol.",
"notes": "A few important things to note:",
"opentrons": "Opentrons",
From 2daabbff21e133f5f095e73dd3a9d671fb304f8d Mon Sep 17 00:00:00 2001
From: Jethary Alcid <66035149+jerader@users.noreply.github.com>
Date: Thu, 14 Nov 2024 13:26:18 -0500
Subject: [PATCH 15/31] =?UTF-8?q?fix(protocol-designer):=20properly=20sele?=
=?UTF-8?q?ct=20and=20disable=20column=20dropdown=20o=E2=80=A6=20(#16787)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
…ption
closes RQA-3528
---
components/src/molecules/DropdownMenu/index.tsx | 2 +-
.../StepForm/PipetteFields/PartialTipField.tsx | 8 +++++++-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/components/src/molecules/DropdownMenu/index.tsx b/components/src/molecules/DropdownMenu/index.tsx
index 8f0265449e8..851e759abca 100644
--- a/components/src/molecules/DropdownMenu/index.tsx
+++ b/components/src/molecules/DropdownMenu/index.tsx
@@ -285,7 +285,7 @@ export function DropdownMenu(props: DropdownMenuProps): JSX.Element {
{filterOptions.map((option, index) => (
}
confirmButtonText={t('shared:done')}
- onConfirmClick={onClose}
+ onConfirmClick={() => {
+ dispatch(deselectAllWells())
+ onClose()
+ }}
onCloseClick={handleClearSelectedWells}
height="calc(100vh - 64px)"
closeButton={
@@ -245,151 +249,163 @@ export function LiquidToolbox(props: LiquidToolboxProps): JSX.Element {
!(labwareId != null && selectedWells != null && selectionHasLiquids)
}
>
-
+
+
+ ) : (
+
+ )}
>
)
From 112ea831efe62f984a7b67ed1ba2793b0885f503 Mon Sep 17 00:00:00 2001
From: David Chau <46395074+ddcc4@users.noreply.github.com>
Date: Fri, 15 Nov 2024 12:35:35 -0500
Subject: [PATCH 30/31] fix(api): rename TouchTipParams ->
LiquidClassTouchTipParams to avoid name conflict (#16848)
# Overview
Liquid classes defined a new class `TouchTipParams` to configure the
touch-tip settings for a liquid. But there's already an existing class
called [`TouchTipParams`](../blob/edge/api/src/opentrons/protocol_engine/commands/touch_tip.py)
that's used as the argument to the Protocol Engine `touchTip` command.
When we generate the [command schema](../blob/edge/shared-data/command/schemas/11.json),
both classes get pulled in, and the names clash.
This PR renames the liquid class `TouchTipParams` to
`LiquidClassTouchTipParams` to avoid the conflict.
## Test Plan and Hands on Testing
I ran `make -C api test`, everything seems to pass.
## Risk assessment
If this breaks anything, it should only affect our team for now.
---
.../liquid_classes/liquid_class_definition.py | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/shared-data/python/opentrons_shared_data/liquid_classes/liquid_class_definition.py b/shared-data/python/opentrons_shared_data/liquid_classes/liquid_class_definition.py
index 8247bd2b760..0462ac5c0e4 100644
--- a/shared-data/python/opentrons_shared_data/liquid_classes/liquid_class_definition.py
+++ b/shared-data/python/opentrons_shared_data/liquid_classes/liquid_class_definition.py
@@ -82,9 +82,13 @@ def _validate_params(
return v
-class TouchTipParams(BaseModel):
+class LiquidClassTouchTipParams(BaseModel):
"""Parameters for touch-tip."""
+ # Note: Do not call this `TouchTipParams`, because that class name is used by the
+ # unrelated touchTip command in PE. Both classes are exported to things like the
+ # command schema JSON files, so the classes can't have the same name.
+
zOffset: _Number = Field(
...,
description="Offset from the top of the well for touch-tip, in millimeters.",
@@ -101,14 +105,14 @@ class TouchTipProperties(BaseModel):
"""Shared properties for the touch-tip function."""
enable: bool = Field(..., description="Whether touch-tip is enabled.")
- params: Optional[TouchTipParams] = Field(
+ params: Optional[LiquidClassTouchTipParams] = Field(
None, description="Parameters for the touch-tip function."
)
@validator("params")
def _validate_params(
- cls, v: Optional[TouchTipParams], values: Dict[str, Any]
- ) -> Optional[TouchTipParams]:
+ cls, v: Optional[LiquidClassTouchTipParams], values: Dict[str, Any]
+ ) -> Optional[LiquidClassTouchTipParams]:
if v is None and values["enable"]:
raise ValueError(
"If enable is true parameters for touch tip must be defined."
From 0110e172a68414dc0293bea38cb8698dd3a6f48c Mon Sep 17 00:00:00 2001
From: Jethary Alcid <66035149+jerader@users.noreply.github.com>
Date: Fri, 15 Nov 2024 13:41:37 -0500
Subject: [PATCH 31/31] fix(protocol-designer): form warnings always show in
form (#16846)
clsoes RQA-3598
---
.../src/organisms/Alerts/FormAlerts.tsx | 25 ++++++-------------
.../Alerts/__tests__/FormAlerts.test.tsx | 3 +--
.../StepForm/StepFormToolbox.tsx | 22 +++++++---------
.../StepTools/MoveLiquidTools/index.tsx | 6 ++---
.../StepForm/StepTools/PauseTools/index.tsx | 12 +++------
.../StepTools/ThermocyclerTools/index.tsx | 6 ++---
.../Designer/ProtocolSteps/StepForm/types.ts | 2 +-
7 files changed, 29 insertions(+), 47 deletions(-)
diff --git a/protocol-designer/src/organisms/Alerts/FormAlerts.tsx b/protocol-designer/src/organisms/Alerts/FormAlerts.tsx
index f9d7166943d..d51d34ff5d8 100644
--- a/protocol-designer/src/organisms/Alerts/FormAlerts.tsx
+++ b/protocol-designer/src/organisms/Alerts/FormAlerts.tsx
@@ -29,7 +29,7 @@ import type { ProfileFormError } from '../../steplist/formLevel/profileErrors'
import type { MakeAlert } from './types'
interface FormAlertsProps {
- showFormErrorsAndWarnings: boolean
+ showFormErrors: boolean
focusedField?: StepFieldName | null
dirtyFields?: StepFieldName[]
page: number
@@ -41,7 +41,7 @@ interface WarningType {
}
function FormAlertsComponent(props: FormAlertsProps): JSX.Element | null {
- const { showFormErrorsAndWarnings, focusedField, dirtyFields, page } = props
+ const { showFormErrors, focusedField, dirtyFields, page } = props
const { t } = useTranslation('alert')
const dispatch = useDispatch()
@@ -78,7 +78,7 @@ function FormAlertsComponent(props: FormAlertsProps): JSX.Element | null {
dirtyFields: dirtyFields ?? [],
errors: formLevelErrorsForUnsavedForm,
page,
- showErrors: showFormErrorsAndWarnings,
+ showErrors: showFormErrors,
})
const profileItemsById: Record | null | undefined =
@@ -180,28 +180,19 @@ function FormAlertsComponent(props: FormAlertsProps): JSX.Element | null {
}
}
- if (showFormErrorsAndWarnings) {
- return [...formErrors, ...formWarnings].length > 0 ? (
-
- {formErrors.map((error, key) => makeAlert('error', error, key))}
- {formWarnings.map((warning, key) => makeAlert('warning', warning, key))}
-
- ) : null
- }
-
- return timelineWarnings.length > 0 ? (
+ return [...formErrors, ...timelineWarnings, ...formWarnings].length > 0 ? (
+ {showFormErrors
+ ? formErrors.map((error, key) => makeAlert('error', error, key))
+ : null}
{timelineWarnings.map((warning, key) =>
makeAlert('warning', warning, key)
)}
+ {formWarnings.map((warning, key) => makeAlert('warning', warning, key))}
) : null
}
diff --git a/protocol-designer/src/organisms/Alerts/__tests__/FormAlerts.test.tsx b/protocol-designer/src/organisms/Alerts/__tests__/FormAlerts.test.tsx
index 5c7428d6996..14110951a76 100644
--- a/protocol-designer/src/organisms/Alerts/__tests__/FormAlerts.test.tsx
+++ b/protocol-designer/src/organisms/Alerts/__tests__/FormAlerts.test.tsx
@@ -37,7 +37,7 @@ describe('FormAlerts', () => {
props = {
focusedField: null,
dirtyFields: [],
- showFormErrorsAndWarnings: false,
+ showFormErrors: false,
page: 0,
}
vi.mocked(getFormLevelErrorsForUnsavedForm).mockReturnValue([])
@@ -64,7 +64,6 @@ describe('FormAlerts', () => {
expect(vi.mocked(dismissTimelineWarning)).toHaveBeenCalled()
})
it('renders a form level warning that is dismissible', () => {
- props.showFormErrorsAndWarnings = true
vi.mocked(getFormWarningsForSelectedStep).mockReturnValue([
{
type: 'TIP_POSITIONED_LOW_IN_TUBE',
diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepFormToolbox.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepFormToolbox.tsx
index f8cffb8f6a5..b930af715cb 100644
--- a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepFormToolbox.tsx
+++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepFormToolbox.tsx
@@ -122,10 +122,7 @@ export function StepFormToolbox(props: StepFormToolboxProps): JSX.Element {
}))
const timeline = useSelector(getRobotStateTimeline)
const [toolboxStep, setToolboxStep] = useState(0)
- const [
- showFormErrorsAndWarnings,
- setShowFormErrorsAndWarnings,
- ] = useState(false)
+ const [showFormErrors, setShowFormErrors] = useState(false)
const [tab, setTab] = useState('aspirate')
const visibleFormWarnings = getVisibleFormWarnings({
focusedField,
@@ -140,7 +137,7 @@ export function StepFormToolbox(props: StepFormToolboxProps): JSX.Element {
...dynamicFormLevelErrorsForUnsavedForm,
],
page: toolboxStep,
- showErrors: showFormErrorsAndWarnings,
+ showErrors: showFormErrors,
})
const [isRename, setIsRename] = useState(false)
const icon = stepIconsByType[formData.stepType]
@@ -187,7 +184,6 @@ export function StepFormToolbox(props: StepFormToolboxProps): JSX.Element {
})
}
}
-
const handleSaveClick = (): void => {
if (canSave) {
const duration = new Date().getTime() - analyticsStartTime.getTime()
@@ -212,7 +208,7 @@ export function StepFormToolbox(props: StepFormToolboxProps): JSX.Element {
)
dispatch(analyticsEvent(stepDuration))
} else {
- setShowFormErrorsAndWarnings(true)
+ setShowFormErrors(true)
if (tab === 'aspirate' && isDispenseError && !isAspirateError) {
setTab('dispense')
}
@@ -227,9 +223,9 @@ export function StepFormToolbox(props: StepFormToolboxProps): JSX.Element {
if (isMultiStepToolbox && toolboxStep === 0) {
if (!isErrorOnCurrentPage) {
setToolboxStep(1)
- setShowFormErrorsAndWarnings(false)
+ setShowFormErrors(false)
} else {
- setShowFormErrorsAndWarnings(true)
+ setShowFormErrors(true)
handleScrollToTop()
}
} else {
@@ -279,7 +275,7 @@ export function StepFormToolbox(props: StepFormToolboxProps): JSX.Element {
width="100%"
onClick={() => {
setToolboxStep(0)
- setShowFormErrorsAndWarnings(false)
+ setShowFormErrors(false)
}}
>
{i18n.format(t('shared:back'), 'capitalize')}
@@ -308,7 +304,7 @@ export function StepFormToolbox(props: StepFormToolboxProps): JSX.Element {
{
setTab('aspirate')
- setShowFormErrorsAndWarnings?.(false)
+ setShowFormErrors?.(false)
},
}
const dispenseTab = {
@@ -110,7 +110,7 @@ export function MoveLiquidTools(props: StepFormProps): JSX.Element {
isActive: tab === 'dispense',
onClick: () => {
setTab('dispense')
- setShowFormErrorsAndWarnings?.(false)
+ setShowFormErrors?.(false)
},
}
const hideWellOrderField =
diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/PauseTools/index.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/PauseTools/index.tsx
index df3e86b2bcb..0da95e20e01 100644
--- a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/PauseTools/index.tsx
+++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/PauseTools/index.tsx
@@ -34,11 +34,7 @@ import type { ChangeEvent } from 'react'
import type { StepFormProps } from '../../types'
export function PauseTools(props: StepFormProps): JSX.Element {
- const {
- propsForFields,
- visibleFormErrors,
- setShowFormErrorsAndWarnings,
- } = props
+ const { propsForFields, visibleFormErrors, setShowFormErrors } = props
const tempModuleLabwareOptions = useSelector(
uiModuleSelectors.getTemperatureLabwareOptions
@@ -101,7 +97,7 @@ export function PauseTools(props: StepFormProps): JSX.Element {
) => {
propsForFields.pauseAction.updateValue(e.currentTarget.value)
- setShowFormErrorsAndWarnings?.(false)
+ setShowFormErrors?.(false)
}}
buttonLabel={t(
'form:step_edit_form.field.pauseAction.options.untilResume'
@@ -113,7 +109,7 @@ export function PauseTools(props: StepFormProps): JSX.Element {
) => {
propsForFields.pauseAction.updateValue(e.currentTarget.value)
- setShowFormErrorsAndWarnings?.(false)
+ setShowFormErrors?.(false)
}}
buttonLabel={t(
'form:step_edit_form.field.pauseAction.options.untilTime'
@@ -125,7 +121,7 @@ export function PauseTools(props: StepFormProps): JSX.Element {
) => {
propsForFields.pauseAction.updateValue(e.currentTarget.value)
- setShowFormErrorsAndWarnings?.(false)
+ setShowFormErrors?.(false)
}}
buttonLabel={t(
'form:step_edit_form.field.pauseAction.options.untilTemperature'
diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ThermocyclerTools/index.tsx b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ThermocyclerTools/index.tsx
index 96707eaf2f1..3e85004549e 100644
--- a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ThermocyclerTools/index.tsx
+++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/StepTools/ThermocyclerTools/index.tsx
@@ -25,7 +25,7 @@ export function ThermocyclerTools(props: StepFormProps): JSX.Element {
showFormErrors = true,
visibleFormErrors,
focusedField,
- setShowFormErrorsAndWarnings,
+ setShowFormErrors,
} = props
const { t } = useTranslation('form')
@@ -49,7 +49,7 @@ export function ThermocyclerTools(props: StepFormProps): JSX.Element {
onChange={() => {
setContentType('thermocyclerState')
propsForFields.thermocyclerFormType.updateValue('thermocyclerState')
- setShowFormErrorsAndWarnings?.(false)
+ setShowFormErrors?.(false)
}}
isSelected={contentType === 'thermocyclerState'}
/>
@@ -64,7 +64,7 @@ export function ThermocyclerTools(props: StepFormProps): JSX.Element {
propsForFields.thermocyclerFormType.updateValue(
'thermocyclerProfile'
)
- setShowFormErrorsAndWarnings?.(false)
+ setShowFormErrors?.(false)
}}
isSelected={contentType === 'thermocyclerProfile'}
/>
diff --git a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/types.ts b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/types.ts
index ac05085fa31..ffbfd8b32c3 100644
--- a/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/types.ts
+++ b/protocol-designer/src/pages/Designer/ProtocolSteps/StepForm/types.ts
@@ -30,7 +30,7 @@ export interface StepFormProps {
visibleFormErrors: StepFormErrors
showFormErrors: boolean
focusedField?: string | null
- setShowFormErrorsAndWarnings?: React.Dispatch>
+ setShowFormErrors?: React.Dispatch>
tab: LiquidHandlingTab
setTab: React.Dispatch>
}