diff --git a/.github/workflows/python.yaml b/.github/workflows/python.yaml index 229f5b0232..9cb0e36e8f 100644 --- a/.github/workflows/python.yaml +++ b/.github/workflows/python.yaml @@ -13,6 +13,7 @@ on: - "source-google-sheets-native/**" - "source-hubspot-native/**" - "source-hubspot/**" + - "source-mailchimp/**" - "source-notion/**" - "source-linkedin-pages/**" - "source-linkedin-ads-v2/**" @@ -41,6 +42,7 @@ on: - "source-google-sheets-native/**" - "source-hubspot-native/**" - "source-hubspot/**" + - "source-mailchimp/**" - "source-notion/**" - "source-linkedin-pages/**" - "source-linkedin-ads-v2/**" @@ -105,6 +107,10 @@ jobs: type: capture version: v5 usage_rate: "1.0" + - name: source-mailchimp + type: capture + version: v2 + usage_rate: "1.0" - name: source-notion type: capture version: v2 diff --git a/source-mailchimp/acmeCo/automations.schema.yaml b/source-mailchimp/acmeCo/automations.schema.yaml new file mode 100644 index 0000000000..a517322cc5 --- /dev/null +++ b/source-mailchimp/acmeCo/automations.schema.yaml @@ -0,0 +1,238 @@ +--- +$schema: "http://json-schema.org/draft-07/schema#" +type: object +title: Automations +additionalProperties: true +required: + - id +properties: + id: + type: string + create_time: + type: + - "null" + - string + format: date-time + start_time: + type: + - "null" + - string + format: date-time + status: + type: + - "null" + - string + emails_sent: + type: + - "null" + - number + recipients: + type: + - "null" + - object + properties: + list_id: + type: + - "null" + - string + list_is_active: + type: + - "null" + - boolean + list_name: + type: + - "null" + - string + segment_opts: + type: + - "null" + - object + properties: + saved_segment_id: + type: + - "null" + - number + match: + type: + - "null" + - string + conditions: + type: + - "null" + - array + items: + type: + - "null" + - object + additionalProperties: true + store_id: + type: + - "null" + - string + settings: + type: + - "null" + - object + properties: + title: + type: + - "null" + - string + from_name: + type: + - "null" + - string + reply_to: + type: + - "null" + - string + use_conversation: + type: + - "null" + - boolean + to_name: + type: + - "null" + - string + authenticate: + type: + - "null" + - boolean + auto_footer: + type: + - "null" + - boolean + inline_css: + type: + - "null" + - boolean + tracking: + type: + - "null" + - object + properties: + opens: + type: + - "null" + - boolean + html_clicks: + type: + - "null" + - boolean + text_clicks: + type: + - "null" + - boolean + goal_tracking: + type: + - "null" + - boolean + ecomm360: + type: + - "null" + - boolean + google_analytics: + type: + - "null" + - string + clicktale: + type: + - "null" + - string + salesforce: + type: + - "null" + - object + properties: + campaign: + type: + - "null" + - boolean + notes: + type: + - "null" + - boolean + capsule: + type: + - "null" + - object + properties: + notes: + type: + - "null" + - boolean + trigger_settings: + type: + - "null" + - object + properties: + workflow_type: + type: + - "null" + - string + workflow_title: + type: + - "null" + - string + runtime: + type: + - "null" + - object + properties: + days: + type: + - "null" + - array + items: + type: + - "null" + - string + hours: + type: + - "null" + - object + properties: + type: + type: + - "null" + - string + workflow_emails_count: + type: + - "null" + - number + report_summary: + type: + - "null" + - object + properties: + opens: + type: + - "null" + - number + unique_opens: + type: + - "null" + - number + open_rate: + type: + - "null" + - number + clicks: + type: + - "null" + - number + subscriber_clicks: + type: + - "null" + - number + click_rate: + type: + - "null" + - number + _meta: + type: object + properties: + row_id: + type: integer + required: + - row_id diff --git a/source-mailchimp/acmeCo/campaigns.schema.yaml b/source-mailchimp/acmeCo/campaigns.schema.yaml new file mode 100644 index 0000000000..11711ef60e --- /dev/null +++ b/source-mailchimp/acmeCo/campaigns.schema.yaml @@ -0,0 +1,2173 @@ +--- +type: object +title: Campaign +description: "A summary of an individual campaign's settings and content." +required: + - id +properties: + id: + type: string + title: Campaign ID + description: A string that uniquely identifies this campaign. + readOnly: true + web_id: + type: integer + title: Campaign Web ID + description: "The ID used in the Mailchimp web application. View this campaign in your Mailchimp account at `https://{dc}.admin.mailchimp.com/campaigns/show/?id={web_id}`." + readOnly: true + parent_campaign_id: + type: + - "null" + - string + title: Parent Campaign ID + description: "If this campaign is the child of another campaign, this identifies the parent campaign. For Example, for RSS or Automation children." + readOnly: true + type: + type: string + title: Campaign Type + description: "There are four types of [campaigns](https://mailchimp.com/help/getting-started-with-campaigns/) you can create in Mailchimp. A/B Split campaigns have been deprecated and variate campaigns should be used instead." + enum: + - automation-email + - regular + - plaintext + - absplit + - rss + - variate + create_time: + type: string + title: Create Time + description: The date and time the campaign was created in ISO 8601 format. + readOnly: true + format: date-time + archive_url: + type: + - "null" + - string + title: Archive URL + description: "The link to the campaign's archive version in ISO 8601 format." + readOnly: true + long_archive_url: + type: + - "null" + - string + title: Long Archive URL + description: "The original link to the campaign's archive version." + readOnly: true + status: + type: string + title: Campaign Status + description: The current status of the campaign. + enum: + - save + - paused + - schedule + - sending + - sent + - canceled + - canceling + - archived + readOnly: true + emails_sent: + type: integer + title: Emails Sent + description: The total number of emails sent for this campaign. + readOnly: true + send_time: + type: + - "null" + - string + title: Send Time + description: The date and time a campaign was sent. + readOnly: true + format: date-time + content_type: + type: + - "null" + - string + title: Content Type + description: "How the campaign's content is put together." + enum: + - template + - html + - url + - multichannel + needs_block_refresh: + type: boolean + title: Needs Block Refresh + description: Determines if the campaign needs its blocks refreshed by opening the web-based campaign editor. Deprecated and will always return false. + readOnly: true + resendable: + type: boolean + title: Resendable + description: Determines if the campaign qualifies to be resent to non-openers. + readOnly: true + recipients: + type: object + title: List + description: List settings for the campaign. + properties: + list_id: + type: + - "null" + - string + title: List ID + description: The unique list id. + list_is_active: + type: boolean + title: List Status + description: "The status of the list used, namely if it's deleted or disabled." + readOnly: true + list_name: + type: + - "null" + - string + title: List Name + description: The name of the list. + readOnly: true + segment_text: + type: + - "null" + - string + title: Segment Text + description: "A description of the [segment](https://mailchimp.com/help/create-and-send-to-a-segment/) used for the campaign. Formatted as a string marked up with HTML." + readOnly: true + recipient_count: + type: integer + title: Recipient Count + description: Count of the recipients on the associated list. Formatted as an integer. + readOnly: true + segment_opts: + type: object + title: Segment Options + description: "An object representing all segmentation options. This object should contain a `saved_segment_id` to use an existing segment, or you can create a new segment by including both `match` and `conditions` options." + properties: + saved_segment_id: + type: integer + title: Saved Segment ID + description: The id for an existing saved segment. + prebuilt_segment_id: + type: string + title: Prebuilt Segment Id + description: "The prebuilt segment id, if a prebuilt segment has been designated for this campaign." + example: subscribers-female + match: + type: string + title: Match Type + description: Segment match type. + enum: + - any + - all + conditions: + type: array + title: Segment Type + description: "Segment match conditions. There are multiple possible types, see the [condition types documentation](https://mailchimp.com/developer/marketing/docs/alternative-schemas/#segment-condition-schemas)." + items: + x-discriminator: + propertyName: condition_type + oneOf: + - type: object + title: Aim Segment + description: Segment by interaction with a specific campaign. + properties: + condition_type: + type: string + x-value: Aim + enum: + - Aim + field: + type: string + enum: + - aim + title: Segment Field + description: Segment by interaction with a specific campaign. + example: aim + op: + type: string + enum: + - open + - click + - sent + - noopen + - noclick + - nosent + title: Segment Operator + description: "The status of the member with regard to their campaign interaction. One of the following: opened, clicked, was sent, didn't open, didn't click, or was not sent." + example: open + value: + type: string + title: Segment Data + description: "Either the web id value for a specific campaign or 'any' to account for subscribers who have/have not interacted with any campaigns." + example: any + - type: object + title: Automation Segment + description: Segment by interaction with an Automation workflow. + required: + - field + - op + - value + properties: + condition_type: + type: string + x-value: Automation + enum: + - Automation + field: + type: string + enum: + - automation + title: Segment Field + description: Segment by interaction with an Automation workflow. + example: automation + op: + type: string + enum: + - started + - completed + - not_started + - not_completed + title: Segment Operator + description: "The status of the member with regard to the automation workflow. One of the following: has started the workflow, has completed the workflow, has not started the workflow, or has not completed the workflow." + example: started + value: + type: string + title: Segment Data + description: The web id for the automation workflow to segment against. + example: "2135217" + - type: object + title: Poll Activity Segment + description: Segment by poll activity. + required: + - field + - op + - value + properties: + condition_type: + type: string + x-value: CampaignPoll + enum: + - CampaignPoll + field: + type: string + enum: + - poll + title: Segment Field + description: Segment by poll activity. + example: poll + op: + type: string + enum: + - member + - notmember + title: Segment Operator + description: Members have/have not interacted with a specific poll in a Mailchimp email. + example: member + value: + type: number + title: Segment Operator + description: The id for the poll. + example: 409 + - type: object + title: Conversation Segment + description: Segment by interaction with a campaign via Conversations. + required: + - field + - op + - value + properties: + condition_type: + type: string + x-value: Conversation + enum: + - Conversation + field: + type: string + enum: + - conversation + title: Segment Field + description: Segment by interaction with a campaign via Conversations. + example: conversation + op: + type: string + enum: + - member + - notmember + title: Segment Operator + description: "The status of a member's interaction with a conversation. One of the following: has replied or has not replied." + example: member + value: + type: string + title: Segment Data + description: "The web id value for a specific campaign or 'any' to account for subscribers who have/have not interacted with any campaigns." + example: any + - type: object + title: Date Segment + description: Segment by a specific date field. + required: + - field + - op + - value + properties: + condition_type: + type: string + x-value: Date + enum: + - Date + field: + type: string + enum: + - timestamp_opt + - info_changed + - ecomm_date + title: Segment Field + description: "The type of date field to segment on: The opt-in time for a signup, the date the subscriber was last updated, or the date of their last ecomm purchase." + example: timestamp_opt + op: + type: string + enum: + - greater + - less + - is + - not + - blank + - blank_not + - within + - notwithin + title: Segment Operator + description: "When the event took place: Before, after, is a specific date, is not a specific date, is blank, or is not blank." + example: greater + value: + type: string + title: Segment Data + description: "What type of data to segment on: a specific date, a specific campaign, or the last campaign sent." + example: date + extra: + type: string + title: Segment Extra Value + description: "When segmenting on 'date' or 'campaign', the date for the segment formatted as YYYY-MM-DD or the web id for the campaign." + example: 2015-01-30 + - type: object + title: Email Client Segment + description: Segment by use of a particular email client. + required: + - field + - op + - value + properties: + condition_type: + type: string + x-value: EmailClient + enum: + - EmailClient + field: + type: string + enum: + - email_client + title: Segment Field + description: Segment by use of a particular email client. + example: email_client + op: + type: string + enum: + - client_is + - client_not + title: Segment Operator + description: "The operation to determine whether we select clients that match the value, or clients that do not match the value." + example: client_is + value: + type: string + title: Segment Data + description: The name of the email client. + example: Gmail + - type: object + title: Language Segment + description: Segment by language. + required: + - field + - op + - value + properties: + condition_type: + type: string + x-value: Language + enum: + - Language + field: + type: string + enum: + - language + title: Segment Field + description: "Segmenting based off of a subscriber's language." + example: language + op: + type: string + enum: + - is + - not + title: Segment Operator + description: "Whether the member's language is or is not set to a specific language." + example: is + value: + type: string + title: Segment Data + description: A two-letter language identifier. + example: en + - type: object + title: Member Rating Segment + description: Segment by member rating. + required: + - field + - op + - value + properties: + condition_type: + type: string + x-value: MemberRating + enum: + - MemberRating + field: + type: string + enum: + - rating + title: Segment Field + description: Segment by member rating. + example: rating + op: + type: string + enum: + - is + - not + - greater + - less + title: Segment Operator + description: Members who have have a rating that is/not exactly a given number or members who have a rating greater/less than a given number. + example: greater + value: + type: number + title: Segment Operator + description: The star rating number to segment against. + example: 4 + - type: object + title: Signup Source Segment + description: Segment by signup source. + required: + - field + - condition_type + - op + properties: + condition_type: + type: string + enum: + - SignupSource + x-value: SignupSource + title: Type + field: + type: string + enum: + - source + title: Segment Field + example: source + op: + type: string + enum: + - source_is + - source_not + title: Segment Operator + description: "Whether the member's signup source was/was not a particular value." + example: source_is + value: + type: string + title: Segment Data + description: The signup source. + example: List Import + - type: object + title: SurveyMonkey Segment + description: Segment by interaction with a SurveyMonkey survey. + required: + - field + - op + - value + properties: + condition_type: + type: string + x-value: SurveyMonkey + enum: + - SurveyMonkey + field: + type: string + enum: + - survey_monkey + title: Segment Field + description: Segment by interaction with a SurveyMonkey survey. + example: survey_monkey + op: + type: string + enum: + - started + - completed + - not_started + - not_completed + title: Segment Operator + description: "The status of the member with regard to the survey. One of the following: has started the survey, has completed the survey, has not started the survey, or has not completed the survey." + example: started + value: + type: string + title: Survey ID + description: The unique ID of the SurveyMonkey survey. + example: "32179586" + - type: object + title: VIP Segment + description: Segment by VIP status. + required: + - field + - op + properties: + condition_type: + type: string + x-value: VIP + enum: + - VIP + field: + type: string + enum: + - gmonkey + title: Segment Field + description: Segment by VIP status. + example: gmonkey + op: + type: string + enum: + - member + - notmember + title: Segment Operator + description: Whether the member is or is not marked as VIP. + example: member + - type: object + title: Interests Segment + description: Segment by an interest group merge field. + properties: + condition_type: + type: string + x-value: Interests + enum: + - Interests + field: + type: string + title: Segment Field + description: "Segmenting based on interest group information. This should start with 'interests-' followed by the grouping id. Ex. 'interests-123'." + example: interests-123 + op: + type: string + enum: + - interestcontains + - interestcontainsall + - interestnotcontains + title: Segment Operator + description: "Whether the member is a part of one, all, or none of the groups." + example: interestcontains + value: + type: array + title: Segment Value + description: "An array containing strings, each representing a group id." + items: + type: string + example: + - "44401" + - "44405" + - "44409" + - type: object + title: Ecommerce Category Segment + description: Segment by purchases in specific items or categories. + properties: + condition_type: + type: string + x-value: EcommCategory + enum: + - EcommCategory + field: + type: string + enum: + - ecomm_cat + - ecomm_prod + title: Segment Field + description: Segment by purchases in specific items or categories. + example: ecomm_cat + op: + type: string + enum: + - is + - not + - contains + - notcontain + - starts + - ends + title: Segment Operator + description: "A member who has purchased from a category/specific item that is/is not a specific name, where the category/item name contains/doesn't contain a specific phrase or string, or a category/item name that starts/ends with a string." + example: is + value: + type: string + title: Segment Data + description: The ecommerce category/item information. + example: Product + - type: object + title: Ecommerce Number Segment + description: "Segment by average spent total, number of orders, total number of products purchased, or average number of products per order." + required: + - field + - op + - value + properties: + condition_type: + type: string + x-value: EcommNumber + enum: + - EcommNumber + field: + type: string + enum: + - ecomm_spent_avg + - ecomm_orders + - ecomm_prod_all + - ecomm_avg_ord + title: Segment Field + description: "Segment by average spent total, number of orders, total number of products purchased, or average number of products per order." + example: ecomm_orders + op: + type: string + enum: + - is + - not + - greater + - less + title: Segment Operator + description: "Members who have spent exactly, have not spent exactly, spent more, or spent less than the segment value." + example: greater + value: + type: number + title: Segment Operator + description: "Members who have spent exactly, have not spent exactly, spent more, or spent less than this amount." + example: 42 + - type: object + title: Ecommerce Purchased Segment + description: Segment by whether someone has purchased anything. + properties: + condition_type: + type: string + x-value: EcommPurchased + enum: + - EcommPurchased + field: + type: string + enum: + - ecomm_purchased + title: Segment Field + description: Segment by whether someone has purchased anything. + example: ecomm_purchased + op: + type: string + enum: + - member + - notmember + title: Segment Operator + description: "Members who have have ('member') or have not ('notmember') purchased." + example: member + - type: object + title: Ecommerce Spent Segment + description: Segment by amount spent on a single order or across all orders. + properties: + condition_type: + type: string + x-value: EcommSpent + enum: + - EcommSpent + field: + type: string + enum: + - ecomm_spent_one + - ecomm_spent_all + title: Segment Field + description: Segment by amount spent on a single order or across all orders. + example: ecomm_spent_one + op: + type: string + enum: + - greater + - less + title: Segment Operator + description: "Members who have spent 'more' or 'less' than then specified value." + example: greater + value: + type: integer + title: Segment Data + description: The total amount a member spent. + example: 42 + - type: object + title: Ecommerce Purchased Store Segment + description: Segment by purchases from a specific store. + properties: + condition_type: + type: string + x-value: EcommStore + enum: + - EcommStore + field: + type: string + enum: + - ecomm_store + title: Segment Field + description: Segment by purchases from a specific store. + example: ecomm_store + op: + type: string + enum: + - is + - not + title: Segment Operator + description: Members who have or have not purchased from a specific store. + example: is + value: + type: string + title: Segment Operator + description: The store id to segment against. + example: "289" + - type: object + title: Goal Activity Segment + description: Segment by Goal activity. + required: + - field + - op + - value + properties: + condition_type: + type: string + x-value: GoalActivity + enum: + - GoalActivity + field: + type: string + enum: + - goal + title: Segment Field + description: Segment by Goal activity. + example: goal + op: + type: string + enum: + - is + - goal_not + - contains + - goal_notcontain + - starts + - ends + title: Segment Operator + description: "Whether the website URL is/not exactly, contains/doesn't contain, starts with/ends with a string." + example: is + value: + type: string + title: Segment Value + description: The URL to check Goal activity against. + - type: object + title: Goal Timestamp Segment + description: Segment by most recent interaction with a website. + required: + - field + - op + - value + properties: + condition_type: + type: string + x-value: GoalTimestamp + enum: + - GoalTimestamp + field: + type: string + enum: + - goal_last_visited + title: Segment Field + description: Segment by most recent interaction with a website. + example: goal_last_visited + op: + type: string + enum: + - greater + - less + - is + title: Segment Operator + description: "Whether the website activity happened after, before, or at a given timestamp." + example: greater + value: + type: string + title: Segment Value + description: The date to check Goal activity against. + example: "2015-07-20 19:45:21" + - type: object + title: Similar Subscribers Segment Member Segment + description: Segment by similar subscribers. + required: + - field + - op + - value + properties: + condition_type: + type: string + x-value: FuzzySegment + enum: + - FuzzySegment + field: + type: string + enum: + - fuzzy_segment + title: Segment Field + description: Segment by similar subscribers. + example: fuzzy_segment + op: + type: string + enum: + - fuzzy_is + - fuzzy_not + title: Segment Operator + description: "Members who are/are not apart of a 'similar subscribers' segment." + example: fuzzy_is + value: + type: number + title: Segment Operator + description: "The id for the 'similar subscribers' segment." + example: 48433 + - type: object + title: Static Segment Member Segment + description: Segment by a given static segment. + required: + - field + - op + - value + properties: + condition_type: + type: string + x-value: StaticSegment + enum: + - StaticSegment + field: + type: string + enum: + - static_segment + title: Segment Field + description: Segment by a given static segment. + example: static_segment + op: + type: string + enum: + - static_is + - static_not + title: Segment Operator + description: Members who are/are not apart of a static segment. + example: static_is + value: + type: number + title: Segment Operator + description: The id for the static segment. + example: 48433 + - type: object + title: Location-Based Segment + description: Segment by a specific country or US state. + required: + - field + - op + - value + properties: + condition_type: + type: string + x-value: IPGeoCountryState + enum: + - IPGeoCountryState + field: + type: string + enum: + - ipgeo + title: Segment Field + description: Segmenting subscribers who are within a specific location. + example: ipgeo + op: + type: string + enum: + - ipgeocountry + - ipgeonotcountry + - ipgeostate + - ipgeonotstate + title: Segment Operator + description: Segment members who are within a specific country or US state. + example: ipgeocountry + value: + type: string + title: Segment Data + description: The two-letter country code or US state abbreviation. + example: US + - type: object + title: Geolocation Segment + description: Segment by a specific geographic region. + required: + - field + - op + - value + - addr + - lat + - lng + properties: + condition_type: + type: string + x-value: IPGeoIn + enum: + - IPGeoIn + field: + type: string + enum: + - ipgeo + title: Segment Field + description: Segmenting subscribers who are within a specific location. + example: ipgeo + op: + type: string + enum: + - ipgeoin + - ipgeonotin + title: Segment Operator + description: Segment members who are within a specific geographic region. + example: ipgeoin + value: + type: integer + title: Segment Data + description: The radius of the target location. + example: 42 + addr: + type: string + title: Segment Location Address + description: The address of the target location. + example: "Atlanta, GA, USA" + lat: + type: string + title: Segment Location Latitude + description: The latitude of the target location. + example: "33.7489954" + lng: + type: string + title: Segment Location Longitude + description: The longitude of the target location. + example: "-84.3879824" + - type: object + title: US Zip Code Segment + description: Segment by a specific US ZIP code. + required: + - field + - op + - value + - extra + properties: + condition_type: + type: string + x-value: IPGeoInZip + enum: + - IPGeoInZip + field: + type: string + enum: + - ipgeo + title: Segment Field + description: Segmenting subscribers who are within a specific location. + example: ipgeo + op: + type: string + enum: + - ipgeoinzip + title: Segment Operator + description: Segment members who are within a specific US zip code. + example: ipgeoinzip + value: + type: integer + title: Segment Data + description: The radius of the target location. + example: 25 + extra: + type: integer + title: Extra Data + description: The zip code to segment against. + example: 30318 + - type: object + title: Unknown Location-Based Segment + description: Segment members whose location information is unknown. + required: + - field + - op + properties: + condition_type: + type: string + x-value: IPGeoUnknown + enum: + - IPGeoUnknown + field: + type: string + enum: + - ipgeo + title: Segment Field + description: Segmenting subscribers who are within a specific location. + example: ipgeo + op: + type: string + enum: + - ipgeounknown + title: Segment Operator + description: Segment members for which location information is unknown. + example: ipgeounknown + - type: object + title: Zip Code Location-Based Segment + description: Segment by a specific US ZIP code. + required: + - field + - op + - value + properties: + condition_type: + type: string + x-value: IPGeoZip + enum: + - IPGeoZip + field: + type: string + enum: + - ipgeo + title: Segment Field + description: Segmenting subscribers who are within a specific location. + example: ipgeo + op: + type: string + enum: + - ipgeoiszip + - ipgeonotzip + title: Segment Operator + description: Segment members who are/are not within a specific US zip code. + example: ipgeonotzip + value: + type: integer + title: Segment Data + description: The 5-digit zip code. + example: 30318 + - type: object + title: Social Profiles Age Segment + description: Segment by age ranges in Social Profiles data. + required: + - field + - op + - value + properties: + condition_type: + type: string + x-value: SocialAge + enum: + - SocialAge + field: + type: string + enum: + - social_age + title: Segment Field + description: Segment by age ranges in Social Profiles data. + example: social_age + op: + type: string + enum: + - is + - not + title: Segment Operator + description: Members who are/not the exact criteria listed. + example: is + value: + type: string + enum: + - 18-24 + - 25-34 + - 35-54 + - 55+ + title: Segment Operator + description: The age range to segment. + example: 35-54 + - type: object + title: Social Profiles Gender Segment + description: Segment by listed gender in Social Profiles data. + required: + - field + - op + - value + properties: + condition_type: + type: string + x-value: SocialGender + enum: + - SocialGender + field: + type: string + enum: + - social_gender + title: Segment Field + description: Segment by listed gender in Social Profiles data. + example: social_gender + op: + type: string + enum: + - is + - not + title: Segment Operator + description: Members who are/not the exact criteria listed. + example: is + value: + type: string + enum: + - male + - female + title: Segment Operator + description: The Social Profiles gender to segment. + example: female + - type: object + title: Social Profiles Influence Segment + description: Segment by influence rating in Social Profiles data. + required: + - field + - op + - value + properties: + condition_type: + type: string + x-value: SocialInfluence + enum: + - SocialInfluence + field: + type: string + enum: + - social_influence + title: Segment Field + description: Segment by influence rating in Social Profiles data. + example: social_influence + op: + type: string + enum: + - is + - not + - greater + - less + title: Segment Operator + description: Members who have a rating that is/not or greater/less than the rating provided. + example: greater + value: + type: number + title: Segment Operator + description: The Social Profiles influence rating to segment. + example: 2 + - type: object + title: Social Profiles Social Network Segment + description: Segment by social network in Social Profiles data. + required: + - field + - op + - value + properties: + condition_type: + type: string + x-value: SocialNetworkMember + enum: + - SocialNetworkMember + field: + type: string + enum: + - social_network + title: Segment Field + description: Segment by social network in Social Profiles data. + example: social_network + op: + type: string + enum: + - member + - notmember + title: Segment Operator + description: Members who are/not on a given social network. + example: member + value: + type: string + enum: + - twitter + - facebook + - linkedin + - flickr + - foursquare + - lastfm + - myspace + - quora + - vimeo + - yelp + - youtube + title: Segment Operator + description: The social network to segment against. + example: twitter + - type: object + title: Social Profiles Social Network Follow Segment + description: Segment by social network in Social Profiles data. + required: + - field + - op + - value + properties: + condition_type: + type: string + x-value: SocialNetworkFollow + enum: + - SocialNetworkFollow + field: + type: string + enum: + - social_network + title: Segment Field + description: Segment by social network in Social Profiles data. + example: social_network + op: + type: string + enum: + - follow + - notfollow + title: Segment Operator + description: Members who are/not following a linked account on a given social network. + example: follow + value: + type: string + enum: + - twitter_follow + title: Segment Operator + description: The social network to segment against. + example: twitter_follow + - type: object + title: Address Merge Field Segment + description: Segment by an address-type merge field. + required: + - field + - op + properties: + condition_type: + type: string + x-value: AddressMerge + enum: + - AddressMerge + field: + type: string + title: Segment Field + description: An address-type merge field to segment. + example: MMERGE3 + op: + type: string + enum: + - contains + - notcontain + - blank + - blank_not + title: Segment Operator + description: "Whether the member's address merge field contains/does not contain a value or is/is not blank." + example: contains + value: + type: string + title: Segment Value + description: The value to segment a text merge field with. + example: Atlanta + - type: object + title: Address/Zip Merge Field Segment + description: Segment by an address-type merge field within a given distance. + required: + - field + - op + - value + - extra + properties: + condition_type: + type: string + x-value: ZipMerge + enum: + - ZipMerge + field: + type: string + title: Segment Field + description: An address or zip-type merge field to segment. + example: MMERGE2 + op: + type: string + enum: + - geoin + title: Segment Operator + description: "Whether the member's address merge field is within a given distance from a city or zip." + example: geoin + value: + type: string + title: Segment Value + description: The distance from the city/zip. + example: "25" + extra: + type: string + title: Segment Extra + description: The city or the zip being used to segment against. + example: "30318" + - type: object + title: Birthday Merge Field Segment + description: "Segment by a contact's birthday." + required: + - field + - op + properties: + condition_type: + type: string + x-value: BirthdayMerge + enum: + - BirthdayMerge + field: + type: string + title: Segment Field + description: A date merge field to segment. + example: MMERGE4 + op: + type: string + enum: + - is + - not + - blank + - blank_not + title: Segment Operator + description: "Whether the member's birthday merge information is/is not a certain date or is/is not blank." + example: is + value: + type: string + title: Segment Value + description: A date to segment against (mm/dd). + example: 01/30 + - type: object + title: Date Merge Field Segment + description: Segment by a given date merge field. + required: + - field + - op + properties: + condition_type: + type: string + x-value: DateMerge + enum: + - DateMerge + field: + type: string + title: Segment Field + description: A date merge field to segment. + example: MMERGE5 + op: + type: string + enum: + - is + - not + - less + - blank + - blank_not + - greater + title: Segment Operator + description: "Whether the member's merge information is/is not, is greater/less than a value or is/is not blank." + example: is + value: + type: string + title: Segment Value + description: A date to segment against. + example: 01/30/2015 + - type: object + title: Dropdown/Radio Merge Field Segment + description: An individual segment condition + required: + - field + - op + properties: + condition_type: + type: string + x-value: SelectMerge + enum: + - SelectMerge + field: + type: string + title: Segment Field + description: A merge field to segment. + example: MMERGE6 + op: + type: string + enum: + - is + - not + - blank + - blank_not + - notcontain + - contains + title: Segment Operator + description: "Whether the member's merge information is/is not a value or is/is not blank." + example: is + value: + type: string + title: Segment Value + description: The value to segment a text merge field with. + example: Second Choice + - type: object + title: Text or Number Merge Field Segment + description: Segment by a given text or number merge field. + required: + - field + - op + properties: + condition_type: + type: string + x-value: TextMerge + enum: + - TextMerge + field: + type: string + title: Segment Field + description: A text or number merge field to segment. + example: MMERGE7 + op: + type: string + enum: + - is + - not + - contains + - notcontain + - starts + - ends + - greater + - less + - blank + - blank_not + title: Segment Operator + description: "Whether the member's merge information is/is not, contains/does not contain, starts/ends with, or is greater/less than a value" + example: contains + value: + type: string + title: Segment Value + description: The value to segment a text or number merge field with. + example: "Freddie's Jokes" + - type: object + title: Email Segment + description: Segment by email address. + required: + - field + - op + properties: + condition_type: + type: string + x-value: EmailAddress + enum: + - EmailAddress + field: + type: string + enum: + - merge0 + - EMAIL + title: Segment Field + description: "Segmenting based off of a subscriber's email address." + example: EMAIL + op: + type: string + enum: + - is + - not + - contains + - notcontain + - starts + - ends + - greater + - less + title: Segment Operator + description: "Whether the email address is/not exactly, contains/doesn't contain, starts/ends with a string." + value: + type: string + title: Segment Value + description: The value to compare the email against. + example: urist.mcvankab@freddiesjokes.com + - type: object + title: Predicted Gender Segment + description: Segment by predicted gender. + required: + - field + - op + - value + properties: + condition_type: + type: string + x-value: PredictedGender + enum: + - PredictedGender + field: + type: string + enum: + - predicted_gender + title: Segment Field + description: Segment by predicted gender. + op: + type: string + enum: + - is + - not + title: Segment Operator + description: Members who are/not the exact criteria listed. + example: is + value: + type: string + enum: + - male + - female + title: Segment Operator + description: The predicted gender to segment. + example: female + - type: object + title: Predicted Age Segment + description: Segment by predicted age. + required: + - field + - op + - value + properties: + condition_type: + type: string + x-value: PredictedAge + enum: + - PredictedAge + field: + type: string + enum: + - predicted_age_range + title: Segment Field + description: Segment by predicted age. + op: + type: string + enum: + - is + title: Segment Operator + description: Members who are/not the exact criteria listed. + example: is + value: + type: string + enum: + - 18-24 + - 25-34 + - 35-44 + - 45-54 + - 55-64 + - 65+ + title: Segment Operator + description: The predicted age to segment. + example: female + - type: object + title: New Subscribers Prebuilt Segment + description: Segment by when people subscribed. + properties: + condition_type: + type: string + x-value: NewSubscribers + enum: + - NewSubscribers + field: + type: string + enum: + - timestamp_opt + title: Segment Field + description: Segment by when people subscribed. + op: + type: string + enum: + - date_within + title: Segment Operator + description: "Whe the event took place, namely within a time frame." + value: + type: string + title: Segment Data + description: "What type of data to segment on: a specific date, a specific campaign, or the last campaign sent." + settings: + type: object + title: Campaign Settings + description: "The settings for your campaign, including subject, from name, reply-to address, and more." + properties: + subject_line: + type: + - "null" + - string + title: Campaign Subject Line + description: The subject line for the campaign. + preview_text: + type: + - "null" + - string + title: Campaign Preview Text + description: The preview text for the campaign. + title: + type: + - "null" + - string + title: Campaign Title + description: The title of the campaign. + from_name: + type: + - "null" + - string + title: From Name + description: "The 'from' name on the campaign (not an email address)." + reply_to: + type: + - "null" + - string + title: Reply To Address + description: The reply-to email address for the campaign. + use_conversation: + type: boolean + title: Conversation + description: Use Mailchimp Conversation feature to manage out-of-office replies. + to_name: + type: + - "null" + - string + title: To Name + description: "The campaign's custom 'To' name. Typically the first name [merge field](https://mailchimp.com/help/getting-started-with-merge-tags/)." + folder_id: + type: + - "null" + - string + title: Folder ID + description: "If the campaign is listed in a folder, the id for that folder." + authenticate: + type: boolean + title: Authentication + description: "Whether Mailchimp [authenticated](https://mailchimp.com/help/about-email-authentication/) the campaign. Defaults to `true`." + auto_footer: + type: boolean + title: Auto-Footer + description: "Automatically append Mailchimp's [default footer](https://mailchimp.com/help/about-campaign-footers/) to the campaign." + inline_css: + type: boolean + title: Inline CSS + description: Automatically inline the CSS included with the campaign content. + auto_tweet: + type: boolean + title: Auto-Tweet + description: "Automatically tweet a link to the [campaign archive](https://mailchimp.com/help/about-email-campaign-archives-and-pages/) page when the campaign is sent." + auto_fb_post: + type: array + title: Auto Post to Facebook + description: "An array of [Facebook](https://mailchimp.com/help/connect-or-disconnect-the-facebook-integration/) page ids to auto-post to." + items: + type: + - "null" + - string + fb_comments: + type: boolean + title: Facebook Comments + description: "Allows Facebook comments on the campaign (also force-enables the Campaign Archive toolbar). Defaults to `true`." + timewarp: + type: boolean + title: Timewarp Send + description: "Send this campaign using [Timewarp](https://mailchimp.com/help/use-timewarp/)." + readOnly: true + template_id: + type: integer + title: Template ID + description: The id for the template used in this campaign. + readOnly: false + drag_and_drop: + type: boolean + title: Drag And Drop Campaign + description: Whether the campaign uses the drag-and-drop editor. + readOnly: true + variate_settings: + type: object + title: A/B Test Options + description: The settings specific to A/B test campaigns. + properties: + winning_combination_id: + type: + - "null" + - string + title: Winning Combination ID + description: ID for the winning combination. + readOnly: true + winning_campaign_id: + type: + - "null" + - string + title: Winning Campaign ID + description: ID of the campaign that was sent to the remaining recipients based on the winning combination. + readOnly: true + winner_criteria: + type: + - "null" + - string + title: Winning Criteria + description: "The combination that performs the best. This may be determined automatically by click rate, open rate, or total revenue -- or you may choose manually based on the reporting data you find the most valuable. For Multivariate Campaigns testing send_time, winner_criteria is ignored. For Multivariate Campaigns with 'manual' as the winner_criteria, the winner must be chosen in the Mailchimp web application." + enum: + - opens + - clicks + - manual + - total_revenue + wait_time: + type: integer + title: Wait Time + description: "The number of minutes to wait before choosing the winning campaign. The value of wait_time must be greater than 0 and in whole hours, specified in minutes." + test_size: + type: integer + title: Test Size + description: "The percentage of recipients to send the test combinations to, must be a value between 10 and 100." + subject_lines: + type: array + title: Subject Lines + description: "The possible subject lines to test. If no subject lines are provided, settings.subject_line will be used." + items: + type: + - "null" + - string + send_times: + type: array + title: Send Times + description: "The possible send times to test. The times provided should be in the format YYYY-MM-DD HH:MM:SS. If send_times are provided to test, the test_size will be set to 100% and winner_criteria will be ignored." + items: + type: + - "null" + - string + format: date-time + from_names: + type: array + title: From Names + description: "The possible from names. The number of from_names provided must match the number of reply_to_addresses. If no from_names are provided, settings.from_name will be used." + items: + type: + - "null" + - string + reply_to_addresses: + type: array + title: Reply To Addresses + description: "The possible reply-to addresses. The number of reply_to_addresses provided must match the number of from_names. If no reply_to_addresses are provided, settings.reply_to will be used." + items: + type: + - "null" + - string + contents: + type: array + title: Content Descriptions + description: "Descriptions of possible email contents. To set campaign contents, make a PUT request to /campaigns/{campaign_id}/content with the field 'variate_contents'." + items: + type: + - "null" + - string + readOnly: true + combinations: + type: array + title: Combinations + description: Combinations of possible variables used to build emails. + readOnly: true + items: + type: object + properties: + id: + type: + - "null" + - string + title: ID + description: Unique ID for the combination. + subject_line: + type: integer + title: Subject Line + description: "The index of `variate_settings.subject_lines` used." + send_time: + type: integer + title: Send Time + description: "The index of `variate_settings.send_times` used." + from_name: + type: integer + title: From Name + description: "The index of `variate_settings.from_names` used." + reply_to: + type: integer + title: Reply To + description: "The index of `variate_settings.reply_to_addresses` used." + content_description: + type: integer + title: Content Description + description: "The index of `variate_settings.contents` used." + recipients: + type: integer + title: Recipients + description: The number of recipients for this combination. + tracking: + type: object + title: Campaign Tracking Options + description: The tracking options for a campaign. + properties: + opens: + type: boolean + title: Opens + description: "Whether to [track opens](https://mailchimp.com/help/about-open-tracking/). Defaults to `true`. Cannot be set to false for variate campaigns." + html_clicks: + type: boolean + title: HTML Click Tracking + description: "Whether to [track clicks](https://mailchimp.com/help/enable-and-view-click-tracking/) in the HTML version of the campaign. Defaults to `true`. Cannot be set to false for variate campaigns." + text_clicks: + type: boolean + title: Plain-Text Click Tracking + description: "Whether to [track clicks](https://mailchimp.com/help/enable-and-view-click-tracking/) in the plain-text version of the campaign. Defaults to `true`. Cannot be set to false for variate campaigns." + goal_tracking: + type: boolean + title: Mailchimp Goal Tracking + description: "Whether to enable [Goal](https://mailchimp.com/help/about-connected-sites/) tracking." + ecomm360: + type: boolean + title: E-commerce Tracking + description: "Whether to enable [eCommerce360](https://mailchimp.com/help/connect-your-online-store-to-mailchimp/) tracking." + google_analytics: + type: + - "null" + - string + title: Google Analytics Tracking + description: "The custom slug for [Google Analytics](https://mailchimp.com/help/integrate-google-analytics-with-mailchimp/) tracking (max of 50 bytes)." + clicktale: + type: + - "null" + - string + title: ClickTale Analytics Tracking + description: "The custom slug for [ClickTale](https://mailchimp.com/help/additional-tracking-options-for-campaigns/) tracking (max of 50 bytes)." + salesforce: + type: object + title: Salesforce CRM Tracking + description: "Salesforce tracking options for a campaign. Must be using Mailchimp's built-in [Salesforce integration](https://mailchimp.com/help/integrate-salesforce-with-mailchimp/)." + properties: + campaign: + type: boolean + title: Salesforce Campaign + description: Create a campaign in a connected Salesforce account. + notes: + type: boolean + title: Salesforce Note + description: Update contact notes for a campaign based on subscriber email addresses. + capsule: + type: object + title: Capsule CRM Tracking + description: "Capsule tracking options for a campaign. Must be using Mailchimp's built-in Capsule integration." + properties: + notes: + type: boolean + title: Capsule Note + description: Update contact notes for a campaign based on subscriber email addresses. + rss_opts: + type: object + title: RSS Options + description: "[RSS](https://mailchimp.com/help/share-your-blog-posts-with-mailchimp/) options for a campaign." + properties: + feed_url: + type: + - "null" + - string + title: Feed URL + format: uri + description: The URL for the RSS feed. + frequency: + type: + - "null" + - string + title: Frequency + description: The frequency of the RSS Campaign. + enum: + - daily + - weekly + - monthly + schedule: + type: object + title: Sending Schedule + description: The schedule for sending the RSS Campaign. + properties: + hour: + type: integer + minimum: 0 + maximum: 23 + title: Sending Hour + description: "The hour to send the campaign in local time. Acceptable hours are 0-23. For example, '4' would be 4am in [your account's default time zone](https://mailchimp.com/help/set-account-defaults/)." + daily_send: + type: object + title: Daily Sending Days + description: The days of the week to send a daily RSS Campaign. + properties: + sunday: + type: boolean + title: Sunday + description: Sends the daily RSS Campaign on Sundays. + monday: + type: boolean + title: Monday + description: Sends the daily RSS Campaign on Mondays. + tuesday: + type: boolean + title: tuesday + description: Sends the daily RSS Campaign on Tuesdays. + wednesday: + type: boolean + title: Monday + description: Sends the daily RSS Campaign on Wednesdays. + thursday: + type: boolean + title: Thursday + description: Sends the daily RSS Campaign on Thursdays. + friday: + type: boolean + title: Friday + description: Sends the daily RSS Campaign on Fridays. + saturday: + type: boolean + title: Saturday + description: Sends the daily RSS Campaign on Saturdays. + weekly_send_day: + type: + - "null" + - string + enum: + - sunday + - monday + - tuesday + - wednesday + - thursday + - friday + - saturday + title: Weekly Sending Day + description: The day of the week to send a weekly RSS Campaign. + monthly_send_date: + type: number + minimum: 0 + maximum: 31 + title: Monthly Sending Day + description: "The day of the month to send a monthly RSS Campaign. Acceptable days are 0-31, where '0' is always the last day of a month. Months with fewer than the selected number of days will not have an RSS campaign sent out that day. For example, RSS Campaigns set to send on the 30th will not go out in February." + last_sent: + type: + - "null" + - string + title: Last Sent + description: The date the campaign was last sent. + readOnly: true + format: date-time + constrain_rss_img: + type: boolean + title: Constrain RSS Images + description: Whether to add CSS to images in the RSS feed to constrain their width in campaigns. + ab_split_opts: + type: object + title: A/B Testing Options + description: "[A/B Testing](https://mailchimp.com/help/about-ab-testing-campaigns/) options for a campaign." + readOnly: true + properties: + split_test: + type: + - "null" + - string + title: Split Test + description: The type of AB split to run. + enum: + - subject + - from_name + - schedule + pick_winner: + type: + - "null" + - string + title: Pick Winner + description: "How we should evaluate a winner. Based on 'opens', 'clicks', or 'manual'." + enum: + - opens + - clicks + - manual + wait_units: + type: + - "null" + - string + title: Wait Time + description: "How unit of time for measuring the winner ('hours' or 'days'). This cannot be changed after a campaign is sent." + enum: + - hours + - days + wait_time: + type: integer + title: Wait Time + description: The amount of time to wait before picking a winner. This cannot be changed after a campaign is sent. + split_size: + type: integer + minimum: 1 + maximum: 50 + title: Split Size + description: "The size of the split groups. Campaigns split based on 'schedule' are forced to have a 50/50 split. Valid split integers are between 1-50." + from_name_a: + type: + - "null" + - string + title: From Name Group A + description: "For campaigns split on 'From Name', the name for Group A." + from_name_b: + type: + - "null" + - string + title: From Name Group B + description: "For campaigns split on 'From Name', the name for Group B." + reply_email_a: + type: + - "null" + - string + title: Reply Email Group A + description: "For campaigns split on 'From Name', the reply-to address for Group A." + reply_email_b: + type: + - "null" + - string + title: Reply Email Group B + description: "For campaigns split on 'From Name', the reply-to address for Group B." + subject_a: + type: + - "null" + - string + title: Subject Line Group A + description: "For campaigns split on 'Subject Line', the subject line for Group A." + subject_b: + type: + - "null" + - string + title: Subject Line Group B + description: "For campaigns split on 'Subject Line', the subject line for Group B." + send_time_a: + type: + - "null" + - string + format: date-time + title: Send Time Group A + description: The send time for Group A. + send_time_b: + type: + - "null" + - string + format: date-time + title: Send Time Group B + description: The send time for Group B. + send_time_winner: + type: + - "null" + - string + title: Send Time Winner + description: The send time for the winning version. + social_card: + type: object + title: Campaign Social Card + description: "The preview for the campaign, rendered by social networks like Facebook and Twitter. [Learn more](https://mailchimp.com/help/enable-and-customize-social-cards/)." + properties: + image_url: + type: + - "null" + - string + title: Image URL + description: The url for the header image for the card. + description: + type: + - "null" + - string + title: Campaign Description + description: A short summary of the campaign to display. + title: + type: + - "null" + - string + title: Title + description: The title for the card. Typically the subject line of the campaign. + report_summary: + type: object + title: Campaign Report Summary + description: "For sent campaigns, a summary of opens, clicks, and e-commerce data." + properties: + opens: + type: integer + title: Automation Opens + description: The total number of opens for a campaign. + readOnly: true + unique_opens: + type: integer + title: Unique Opens + description: The number of unique opens. + readOnly: true + open_rate: + type: number + title: Open Rate + description: The number of unique opens divided by the total number of successful deliveries. + readOnly: true + clicks: + type: integer + title: Total Clicks + description: The total number of clicks for an campaign. + readOnly: true + subscriber_clicks: + type: integer + title: Unique Subscriber Clicks + description: The number of unique clicks. + readOnly: true + click_rate: + type: number + title: Click Rate + description: The number of unique clicks divided by the total number of successful deliveries. + readOnly: true + ecommerce: + type: object + title: E-Commerce Report + description: E-Commerce stats for a campaign. + properties: + total_orders: + type: integer + title: Total Orders + description: The total orders for a campaign. + readOnly: true + total_spent: + type: number + title: Total Spent + description: The total spent for a campaign. Calculated as the sum of all order totals with no deductions. + readOnly: true + total_revenue: + type: number + title: Total Revenue + description: The total revenue for a campaign. Calculated as the sum of all order totals minus shipping and tax totals. + readOnly: true + delivery_status: + type: object + title: Campaign Delivery Status + description: Updates on campaigns in the process of sending. + properties: + enabled: + type: boolean + title: Delivery Status Enabled + description: Whether Campaign Delivery Status is enabled for this account and campaign. + readOnly: true + can_cancel: + type: boolean + title: Campaign Cancelable + description: Whether a campaign send can be canceled. + readOnly: true + status: + type: + - "null" + - string + title: Campaign Delivery Status + description: The current state of a campaign delivery. + enum: + - delivering + - delivered + - canceling + - canceled + readOnly: true + emails_sent: + type: integer + title: Emails Sent + description: The total number of emails confirmed sent for this campaign so far. + readOnly: true + emails_canceled: + type: integer + title: Emails Canceled + description: The total number of emails canceled for this campaign. + readOnly: true + _meta: + type: object + properties: + row_id: + type: integer + required: + - row_id diff --git a/source-mailchimp/acmeCo/email_activity.schema.yaml b/source-mailchimp/acmeCo/email_activity.schema.yaml new file mode 100644 index 0000000000..d8e96620e8 --- /dev/null +++ b/source-mailchimp/acmeCo/email_activity.schema.yaml @@ -0,0 +1,70 @@ +--- +type: object +title: Email Activity +description: "A list of member's subscriber activity in a specific campaign." +required: + - timestamp + - email_id + - action +properties: + campaign_id: + type: string + title: The unique id for the campaign. + description: The unique id for the campaign. + list_id: + type: string + title: The unique id for the list. + description: The unique id for the list. + list_is_active: + type: boolean + title: The status of the list used. + description: "The status of the list used, namely if it's deleted or disabled." + email_id: + type: string + title: email MD5 hash. + description: "The MD5 hash of the lowercase version of the list member's email address." + email_address: + type: string + title: Email address for a subscriber. + description: Email address for a subscriber. + action: + type: string + title: action + enum: + - open + - click + - bounce + description: "One of the following actions: 'open', 'click', or 'bounce'" + type: + type: + - string + - "null" + title: Type + enum: + - hard + - soft + description: "If the action is a 'bounce', the type of bounce received: 'hard', 'soft'." + timestamp: + type: string + title: Action date and time + description: The date and time recorded for the action in ISO 8601 format. + format: date-time + url: + type: + - string + - "null" + title: Click url + description: "If the action is a 'click', the URL on which the member clicked." + ip: + type: + - string + - "null" + title: Action ip address + description: The IP address recorded for the action. + _meta: + type: object + properties: + row_id: + type: integer + required: + - row_id diff --git a/source-mailchimp/acmeCo/flow.yaml b/source-mailchimp/acmeCo/flow.yaml new file mode 100644 index 0000000000..922eff01a8 --- /dev/null +++ b/source-mailchimp/acmeCo/flow.yaml @@ -0,0 +1,140 @@ +--- +collections: + acmeCo/automations: + schema: automations.schema.yaml + key: + - /id + acmeCo/campaigns: + schema: campaigns.schema.yaml + key: + - /id + acmeCo/email_activity: + schema: email_activity.schema.yaml + key: + - /timestamp + - /email_id + - /action + acmeCo/interest_categories: + schema: + $schema: "http://json-schema.org/draft-07/schema#" + type: object + required: + - id + properties: + list_id: + type: + - "null" + - string + id: + type: string + title: + type: + - "null" + - string + display_order: + type: + - "null" + - integer + type: + type: + - "null" + - string + _meta: + type: object + properties: + row_id: + type: integer + required: + - row_id + key: + - /id + acmeCo/interests: + schema: + $schema: "http://json-schema.org/draft-07/schema#" + type: object + required: + - id + properties: + category_id: + type: + - "null" + - string + list_id: + type: + - "null" + - string + id: + type: string + name: + type: + - "null" + - string + subscriber_count: + type: + - "null" + - string + display_order: + type: + - "null" + - integer + _meta: + type: object + properties: + row_id: + type: integer + required: + - row_id + key: + - /id + acmeCo/list_members: + schema: list_members.schema.yaml + key: + - /id + acmeCo/lists: + schema: lists.schema.yaml + key: + - /id + acmeCo/reports: + schema: reports.schema.yaml + key: + - /id + acmeCo/segment_members: + schema: segment_members.schema.yaml + key: + - /id + acmeCo/segments: + schema: segments.schema.yaml + key: + - /id + acmeCo/tags: + schema: + $schema: "http://json-schema.org/draft-07/schema#" + type: object + required: + - id + properties: + id: + type: integer + name: + type: + - "null" + - string + list_id: + type: + - "null" + - string + _meta: + type: object + properties: + row_id: + type: integer + required: + - row_id + key: + - /id + acmeCo/unsubscribes: + schema: unsubscribes.schema.yaml + key: + - /campaign_id + - /email_id + - /timestamp diff --git a/source-mailchimp/acmeCo/list_members.schema.yaml b/source-mailchimp/acmeCo/list_members.schema.yaml new file mode 100644 index 0000000000..9461b9151b --- /dev/null +++ b/source-mailchimp/acmeCo/list_members.schema.yaml @@ -0,0 +1,232 @@ +--- +$schema: "http://json-schema.org/draft-07/schema#" +type: object +additionalProperties: true +required: + - id +properties: + id: + type: string + email_address: + type: + - "null" + - string + unique_email_id: + type: + - "null" + - string + contact_id: + type: + - "null" + - string + full_name: + type: + - "null" + - string + web_id: + type: + - "null" + - integer + email_type: + type: + - "null" + - string + status: + type: + - "null" + - string + unsubscribe_reason: + type: + - "null" + - string + consents_to_one_to_one_messaging: + type: + - "null" + - boolean + merge_fields: + type: + - "null" + - object + additionalProperties: true + interests: + type: + - "null" + - object + additionalProperties: true + stats: + type: + - "null" + - object + properties: + avg_open_rate: + type: + - "null" + - number + avg_click_rate: + type: + - "null" + - number + ecommerce_data: + type: + - "null" + - object + properties: + total_revenue: + type: + - "null" + - number + number_of_orders: + type: + - "null" + - number + currency_code: + type: + - "null" + - string + ip_signup: + type: + - "null" + - string + timestamp_signup: + type: + - "null" + - string + format: date-time + ip_opt: + type: + - "null" + - string + timestamp_opt: + type: + - "null" + - string + format: date-time + member_rating: + type: + - "null" + - integer + last_changed: + type: + - "null" + - string + format: date-time + language: + type: + - "null" + - string + vip: + type: + - "null" + - boolean + email_client: + type: + - "null" + - string + location: + type: + - "null" + - object + properties: + latitude: + type: + - "null" + - number + longitude: + type: + - "null" + - number + gmtoff: + type: + - "null" + - integer + dstoff: + type: + - "null" + - integer + country_code: + type: + - "null" + - string + timezone: + type: + - "null" + - string + region: + type: + - "null" + - string + marketing_permissions: + type: + - "null" + - object + properties: + marketing_permission_id: + type: + - "null" + - string + text: + type: + - "null" + - string + enabled: + type: + - "null" + - boolean + last_note: + type: + - "null" + - object + properties: + note_id: + type: + - "null" + - integer + created_at: + type: + - "null" + - string + format: date-time + created_by: + type: + - "null" + - string + note: + type: + - "null" + - string + source: + type: + - "null" + - string + tags_count: + type: + - "null" + - integer + tags: + type: + - "null" + - array + items: + type: + - "null" + - object + properties: + id: + type: + - "null" + - integer + name: + type: + - "null" + - string + list_id: + type: + - "null" + - string + _meta: + type: object + properties: + row_id: + type: integer + required: + - row_id diff --git a/source-mailchimp/acmeCo/lists.schema.yaml b/source-mailchimp/acmeCo/lists.schema.yaml new file mode 100644 index 0000000000..256c713c8d --- /dev/null +++ b/source-mailchimp/acmeCo/lists.schema.yaml @@ -0,0 +1,305 @@ +--- +type: object +title: Subscriber List +description: Information about a specific list. +required: + - id +properties: + id: + type: string + title: List ID + description: A string that uniquely identifies this list. + readOnly: true + web_id: + type: integer + title: List Web ID + description: "The ID used in the Mailchimp web application. View this list in your Mailchimp account at `https://{dc}.admin.mailchimp.com/lists/members/?id={web_id}`." + readOnly: true + name: + type: + - "null" + - string + title: List Name + description: The name of the list. + contact: + type: object + title: List Contact + description: "[Contact information displayed in campaign footers](https://mailchimp.com/help/about-campaign-footers/) to comply with international spam laws." + properties: + company: + type: + - "null" + - string + title: Company Name + description: The company name for the list. + address1: + type: + - "null" + - string + title: Address + description: The street address for the list contact. + address2: + type: + - "null" + - string + title: Address + description: The street address for the list contact. + city: + type: + - "null" + - string + title: City + description: The city for the list contact. + state: + type: + - "null" + - string + title: State + description: The state for the list contact. + zip: + type: + - "null" + - string + title: Postal Code + description: The postal or zip code for the list contact. + country: + type: + - "null" + - string + title: Country Code + description: A two-character ISO3166 country code. Defaults to US if invalid. + phone: + type: + - "null" + - string + title: Phone Number + description: The phone number for the list contact. + permission_reminder: + type: + - "null" + - string + title: Permission Reminder + description: "The [permission reminder](https://mailchimp.com/help/edit-the-permission-reminder/) for the list." + use_archive_bar: + type: boolean + title: Use Archive Bar + description: "Whether campaigns for this list use the [Archive Bar](https://mailchimp.com/help/about-email-campaign-archives-and-pages/) in archives by default." + default: false + campaign_defaults: + type: object + title: Campaign Defaults + description: "[Default values for campaigns](https://mailchimp.com/help/edit-your-emails-subject-preview-text-from-name-or-from-email-address/) created for this list." + properties: + from_name: + type: + - "null" + - string + title: "Sender's Name" + description: The default from name for campaigns sent to this list. + from_email: + type: + - "null" + - string + title: "Sender's Email Address" + description: The default from email for campaigns sent to this list. + subject: + type: + - "null" + - string + title: Subject + description: The default subject line for campaigns sent to this list. + language: + type: + - "null" + - string + title: Language + description: "The default language for this lists's forms." + notify_on_subscribe: + type: + - "null" + - string + title: Notify on Subscribe + description: "The email address to send [subscribe notifications](https://mailchimp.com/help/change-subscribe-and-unsubscribe-notifications/) to." + notify_on_unsubscribe: + type: + - "null" + - string + title: Notify on Unsubscribe + description: "The email address to send [unsubscribe notifications](https://mailchimp.com/help/change-subscribe-and-unsubscribe-notifications/) to." + date_created: + type: string + title: Creation Date + description: The date and time that this list was created in ISO 8601 format. + format: date-time + readOnly: true + list_rating: + type: integer + title: List Rating + description: An auto-generated activity score for the list (0-5). + readOnly: true + email_type_option: + type: boolean + title: Email Type Option + description: "Whether the list supports [multiple formats for emails](https://mailchimp.com/help/change-list-name-and-defaults/). When set to `true`, subscribers can choose whether they want to receive HTML or plain-text emails. When set to `false`, subscribers will receive HTML emails, with a plain-text alternative backup." + subscribe_url_short: + type: + - "null" + - string + title: Subscribe URL Short + description: "Our [EepURL shortened](https://mailchimp.com/help/share-your-signup-form/) version of this list's subscribe form." + readOnly: true + subscribe_url_long: + type: + - "null" + - string + title: Subscribe URL Long + description: "The full version of this list's subscribe form (host will vary)." + readOnly: true + beamer_address: + type: + - "null" + - string + title: Beamer Address + description: "The list's [Email Beamer](https://mailchimp.com/help/use-email-beamer-to-create-a-campaign/) address." + readOnly: true + visibility: + type: + - "null" + - string + title: Visibility + enum: + - pub + - prv + description: "Whether this list is [public or private](https://mailchimp.com/help/about-list-publicity/)." + double_optin: + type: boolean + title: Double Opt In + description: Whether or not to require the subscriber to confirm subscription via email. + default: false + has_welcome: + type: boolean + title: Has Welcome + description: "Whether or not this list has a welcome automation connected. Welcome Automations: welcomeSeries, singleWelcome, emailFollowup." + default: false + example: false + marketing_permissions: + type: boolean + title: Marketing Permissions + description: Whether or not the list has marketing permissions (eg. GDPR) enabled. + default: false + modules: + type: array + title: Modules + description: Any list-specific modules installed for this list. + items: + type: + - "null" + - string + readOnly: true + stats: + type: object + title: Statistics + description: Stats for the list. Many of these are cached for at least five minutes. + readOnly: true + properties: + member_count: + type: integer + title: Member Count + description: The number of active members in the list. + readOnly: true + total_contacts: + type: integer + title: Total Contacts + description: "The number of contacts in the list, including subscribed, unsubscribed, pending, cleaned, deleted, transactional, and those that need to be reconfirmed." + readOnly: true + unsubscribe_count: + type: integer + title: Unsubscribe Count + description: The number of members who have unsubscribed from the list. + readOnly: true + cleaned_count: + type: integer + title: Cleaned Count + description: The number of members cleaned from the list. + readOnly: true + member_count_since_send: + type: integer + title: Member Count Since Send + description: The number of active members in the list since the last campaign was sent. + readOnly: true + unsubscribe_count_since_send: + type: integer + title: Unsubscribe Count Since Send + description: The number of members who have unsubscribed since the last campaign was sent. + readOnly: true + cleaned_count_since_send: + type: integer + title: Cleaned Count Since Send + description: The number of members cleaned from the list since the last campaign was sent. + readOnly: true + campaign_count: + type: integer + title: Campaign Count + description: The number of campaigns in any status that use this list. + readOnly: true + campaign_last_sent: + type: + - "null" + - string + title: Campaign Last Sent + description: The date and time the last campaign was sent to this list in ISO 8601 format. This is updated when a campaign is sent to 10 or more recipients. + readOnly: true + format: date-time + merge_field_count: + type: integer + title: Merge Var Count + description: "The number of merge vars for this list (not EMAIL, which is required)." + readOnly: true + avg_sub_rate: + type: number + title: Average Subscription Rate + description: "The average number of subscriptions per month for the list (not returned if we haven't calculated it yet)." + readOnly: true + avg_unsub_rate: + type: number + title: Average Unsubscription Rate + description: "The average number of unsubscriptions per month for the list (not returned if we haven't calculated it yet)." + readOnly: true + target_sub_rate: + type: number + title: Average Subscription Rate + description: "The target number of subscriptions per month for the list to keep it growing (not returned if we haven't calculated it yet)." + readOnly: true + open_rate: + type: number + title: Open Rate + description: "The average open rate (a percentage represented as a number between 0 and 100) per campaign for the list (not returned if we haven't calculated it yet)." + readOnly: true + click_rate: + type: number + title: Click Rate + description: "The average click rate (a percentage represented as a number between 0 and 100) per campaign for the list (not returned if we haven't calculated it yet)." + readOnly: true + last_sub_date: + type: + - "null" + - string + title: Date of Last List Subscribe + description: The date and time of the last time someone subscribed to this list in ISO 8601 format. + readOnly: true + format: date-time + last_unsub_date: + type: + - "null" + - string + title: Date of Last List Unsubscribe + description: The date and time of the last time someone unsubscribed from this list in ISO 8601 format. + readOnly: true + format: date-time + _meta: + type: object + properties: + row_id: + type: integer + required: + - row_id diff --git a/source-mailchimp/acmeCo/reports.schema.yaml b/source-mailchimp/acmeCo/reports.schema.yaml new file mode 100644 index 0000000000..5f91f03bf6 --- /dev/null +++ b/source-mailchimp/acmeCo/reports.schema.yaml @@ -0,0 +1,496 @@ +--- +type: object +title: Campaign Reports +description: A list of reports containing campaigns marked as Sent. +required: + - id +properties: + id: + type: string + title: Campaign ID + description: A string that uniquely identifies this campaign. + campaign_title: + type: + - "null" + - string + title: Campaign Title + description: The title of the campaign. + readOnly: true + type: + type: + - "null" + - string + title: Campaign Type + description: "The type of campaign (regular, plain-text, ab_split, rss, automation, variate, or auto)." + list_id: + type: string + title: List ID + description: The unique list id. + readOnly: true + list_is_active: + type: boolean + title: List Status + description: "The status of the list used, namely if it's deleted or disabled." + readOnly: true + list_name: + type: + - "null" + - string + title: List Name + description: The name of the list. + readOnly: true + subject_line: + type: + - "null" + - string + title: Campaign Subject Line + description: The subject line for the campaign. + readOnly: true + preview_text: + type: + - "null" + - string + title: Campaign Preview Text + description: The preview text for the campaign. + emails_sent: + type: integer + title: Emails Sent + description: The total number of emails sent for this campaign. + abuse_reports: + type: integer + title: Abuse Reports + description: The number of abuse reports generated for this campaign. + unsubscribed: + type: integer + title: Unsubscribe Count + description: The total number of unsubscribed members for this campaign. + readOnly: true + send_time: + type: + - "null" + - string + format: date-time + title: Send Time + description: The date and time a campaign was sent in ISO 8601 format. + readOnly: true + rss_last_send: + type: + - "null" + - string + format: date-time + title: RSS Last Send + description: "For RSS campaigns, the date and time of the last send in ISO 8601 format." + readOnly: true + bounces: + type: object + title: Bounces + description: An object describing the bounce summary for the campaign. + properties: + hard_bounces: + type: integer + title: Hard Bounces + description: The total number of hard bounced email addresses. + soft_bounces: + type: integer + title: Soft Bounces + description: The total number of soft bounced email addresses. + syntax_errors: + type: integer + title: Syntax Errors + description: The total number of addresses that were syntax-related bounces. + forwards: + type: object + title: Forwards + description: An object describing the forwards and forward activity for the campaign. + properties: + forwards_count: + type: integer + title: Total Forwards + description: How many times the campaign has been forwarded. + forwards_opens: + type: integer + title: Forward Opens + description: How many times the forwarded campaign has been opened. + opens: + type: object + title: Opens + description: An object describing the open activity for the campaign. + properties: + opens_total: + type: integer + title: Total Opens + description: The total number of opens for a campaign. + unique_opens: + type: integer + title: Unique Opens + description: The total number of unique opens. + open_rate: + type: number + title: Open Rate + description: The number of unique opens divided by the total number of successful deliveries. + last_open: + type: + - "null" + - string + format: date-time + title: Last Open + description: The date and time of the last recorded open in ISO 8601 format. + clicks: + type: object + title: Clicks + description: An object describing the click activity for the campaign. + properties: + clicks_total: + type: integer + title: Total Clicks + description: The total number of clicks for the campaign. + unique_clicks: + type: integer + title: Unique Clicks + description: The total number of unique clicks for links across a campaign. + unique_subscriber_clicks: + type: integer + title: Unique Subscriber Clicks + description: The total number of subscribers who clicked on a campaign. + click_rate: + type: number + title: Click Rate + description: The number of unique clicks divided by the total number of successful deliveries. + last_click: + type: + - "null" + - string + format: date-time + title: Last Click + description: The date and time of the last recorded click for the campaign in ISO 8601 format. + facebook_likes: + type: object + title: Facebook Likes + description: An object describing campaign engagement on Facebook. + properties: + recipient_likes: + type: integer + title: Recipient Likes + description: The number of recipients who liked the campaign on Facebook. + unique_likes: + type: integer + title: Unique Likes + description: The number of unique likes. + facebook_likes: + type: integer + title: Facebook Likes + description: The number of Facebook likes for the campaign. + industry_stats: + type: object + title: Industry Stats + description: The average campaign statistics for your industry. + properties: + type: + type: + - "null" + - string + title: Industry Type + description: "The type of business industry associated with your account. For example: retail, education, etc." + open_rate: + type: number + title: Open Rate + description: The industry open rate. + click_rate: + type: number + title: Click Rate + description: The industry click rate. + bounce_rate: + type: number + title: Bounce Rate + description: The industry bounce rate. + unopen_rate: + type: number + title: Unopened Rate + description: The industry unopened rate. + unsub_rate: + type: number + title: Unsubscribe Rate + description: The industry unsubscribe rate. + abuse_rate: + type: number + title: Abuse Rate + description: The industry abuse rate. + list_stats: + type: object + title: List Stats + description: "The average campaign statistics for your list. This won't be present if we haven't calculated it yet for this list." + properties: + sub_rate: + type: number + title: Average Subscription Rate + description: The average number of subscriptions per month for the list. + readOnly: true + unsub_rate: + type: number + title: Average Unsubscription Rate + description: The average number of unsubscriptions per month for the list. + readOnly: true + open_rate: + type: number + title: Open Rate + description: The average open rate (a percentage represented as a number between 0 and 100) per campaign for the list. + readOnly: true + click_rate: + type: number + title: Click Rate + description: The average click rate (a percentage represented as a number between 0 and 100) per campaign for the list. + readOnly: true + ab_split: + type: object + title: A/B Split Stats + description: General stats about different groups of an A/B Split campaign. Does not return information about Multivariate Campaigns. + properties: + a: + type: object + title: Campaign A + description: Stats for Campaign A. + properties: + bounces: + type: integer + title: Bounces + description: Bounces for Campaign A. + abuse_reports: + type: integer + title: Abuse Reports + description: Abuse reports for Campaign A. + unsubs: + type: integer + title: Unsubscribes + description: Unsubscribes for Campaign A. + recipient_clicks: + type: integer + title: Recipient Clicks + description: Recipient Clicks for Campaign A. + forwards: + type: integer + title: Forwards + description: Forwards for Campaign A. + forwards_opens: + type: integer + title: Forward Opens + description: Opens from forwards for Campaign A. + opens: + type: integer + title: Opens + description: Opens for Campaign A. + last_open: + type: + - "null" + - string + title: Last Open + description: The last open for Campaign A. + format: date-time + unique_opens: + type: integer + title: Unique Opens + description: Unique opens for Campaign A. + b: + type: object + title: Campaign B + description: Stats for Campaign B. + properties: + bounces: + type: integer + title: Bounces + description: Bounces for Campaign B. + abuse_reports: + type: integer + title: Abuse Reports + description: Abuse reports for Campaign B. + unsubs: + type: integer + title: Unsubscribes + description: Unsubscribes for Campaign B. + recipient_clicks: + type: integer + title: Recipient Clicks + description: Recipients clicks for Campaign B. + forwards: + type: integer + title: Forwards + description: Forwards for Campaign B. + forwards_opens: + type: integer + title: Forward Opens + description: Opens for forwards from Campaign B. + opens: + type: integer + title: Opens + description: Opens for Campaign B. + last_open: + type: + - "null" + - string + title: Last Open + description: The last open for Campaign B. + format: date-time + unique_opens: + type: integer + title: Unique Opens + description: Unique opens for Campaign B. + timewarp: + type: array + title: Timewarp Stats + description: "An hourly breakdown of sends, opens, and clicks if a campaign is sent using timewarp." + items: + type: object + properties: + gmt_offset: + type: integer + title: GMT Offset + description: "For campaigns sent with timewarp, the time zone group the member is apart of." + opens: + type: integer + title: Opens + description: The number of opens. + last_open: + type: + - "null" + - string + format: date-time + title: Last Open + description: The date and time of the last open in ISO 8601 format. + unique_opens: + type: integer + title: Unique Opens + description: The number of unique opens. + clicks: + type: integer + title: Clicks + description: The number of clicks. + last_click: + type: + - "null" + - string + format: date-time + title: Last Click + description: The date and time of the last click in ISO 8601 format. + unique_clicks: + type: integer + title: Unique Clicks + description: The number of unique clicks. + bounces: + type: integer + title: Bounces + description: The number of bounces. + timeseries: + type: array + title: Timeseries + description: An hourly breakdown of the performance of the campaign over the first 24 hours. + items: + type: object + properties: + timestamp: + type: + - "null" + - string + format: date-time + title: Timestamp + description: The date and time for the series in ISO 8601 format. + emails_sent: + type: integer + title: Emails Sent + description: The number of emails sent in the timeseries. + unique_opens: + type: integer + title: Unique Opens + description: The number of unique opens in the timeseries. + recipients_clicks: + type: integer + title: Recipient Clicks + description: The number of clicks in the timeseries. + share_report: + type: object + title: Share Report + description: "The url and password for the [VIP report](https://mailchimp.com/help/share-a-campaign-report/)." + properties: + share_url: + type: + - "null" + - string + title: Report URL + description: The URL for the VIP report. + readOnly: true + share_password: + type: + - "null" + - string + title: Report Password + description: "If password protected, the password for the VIP report." + readOnly: true + ecommerce: + type: object + title: E-Commerce Report + description: E-Commerce stats for a campaign. + properties: + total_orders: + type: integer + title: Total Orders + description: The total orders for a campaign. + readOnly: true + total_spent: + type: number + title: Total Spent + description: The total spent for a campaign. Calculated as the sum of all order totals with no deductions. + readOnly: true + total_revenue: + type: number + title: Total Revenue + description: The total revenue for a campaign. Calculated as the sum of all order totals minus shipping and tax totals. + readOnly: true + currency_code: + type: + - "null" + - string + title: Three letter currency code for this user + readOnly: true + example: USD + delivery_status: + type: object + title: Campaign Delivery Status + description: Updates on campaigns in the process of sending. + properties: + enabled: + type: boolean + title: Delivery Status Enabled + description: Whether Campaign Delivery Status is enabled for this account and campaign. + readOnly: true + can_cancel: + type: boolean + title: Campaign Cancelable + description: Whether a campaign send can be canceled. + readOnly: true + status: + type: + - "null" + - string + title: Campaign Delivery Status + description: The current state of a campaign delivery. + enum: + - delivering + - delivered + - canceling + - canceled + readOnly: true + emails_sent: + type: integer + title: Emails Sent + description: The total number of emails confirmed sent for this campaign so far. + readOnly: true + emails_canceled: + type: integer + title: Emails Canceled + description: The total number of emails canceled for this campaign. + readOnly: true + _meta: + type: object + properties: + row_id: + type: integer + required: + - row_id diff --git a/source-mailchimp/acmeCo/segment_members.schema.yaml b/source-mailchimp/acmeCo/segment_members.schema.yaml new file mode 100644 index 0000000000..f3ba7a31fd --- /dev/null +++ b/source-mailchimp/acmeCo/segment_members.schema.yaml @@ -0,0 +1,153 @@ +--- +$schema: "http://json-schema.org/draft-07/schema#" +type: object +additionalProperties: true +required: + - id +properties: + id: + type: string + email_address: + type: + - "null" + - string + unique_email_id: + type: + - "null" + - string + email_type: + type: + - "null" + - string + status: + type: + - "null" + - string + merge_fields: + type: + - "null" + - object + additionalProperties: true + interests: + type: + - "null" + - object + additionalProperties: true + stats: + type: + - "null" + - object + properties: + avg_open_rate: + type: + - "null" + - number + avg_click_rate: + type: + - "null" + - number + ip_signup: + type: + - "null" + - string + timestamp_signup: + type: + - "null" + - string + format: date-time + ip_opt: + type: + - "null" + - string + timestamp_opt: + type: + - "null" + - string + format: date-time + member_rating: + type: + - "null" + - integer + last_changed: + type: + - "null" + - string + format: date-time + language: + type: + - "null" + - string + vip: + type: + - "null" + - boolean + email_client: + type: + - "null" + - string + location: + type: + - "null" + - object + properties: + latitude: + type: + - "null" + - number + longitude: + type: + - "null" + - number + gmtoff: + type: + - "null" + - integer + dstoff: + type: + - "null" + - integer + country_code: + type: + - "null" + - string + timezone: + type: + - "null" + - string + last_note: + type: + - "null" + - object + properties: + note_id: + type: + - "null" + - integer + created_at: + type: + - "null" + - string + format: date-time + created_by: + type: + - "null" + - string + note: + type: + - "null" + - string + list_id: + type: + - "null" + - string + segment_id: + type: + - "null" + - integer + _meta: + type: object + properties: + row_id: + type: integer + required: + - row_id diff --git a/source-mailchimp/acmeCo/segments.schema.yaml b/source-mailchimp/acmeCo/segments.schema.yaml new file mode 100644 index 0000000000..4ff4943917 --- /dev/null +++ b/source-mailchimp/acmeCo/segments.schema.yaml @@ -0,0 +1,73 @@ +--- +$schema: "http://json-schema.org/draft-07/schema#" +type: object +additionalProperties: true +required: + - id +properties: + id: + type: integer + name: + type: + - "null" + - string + member_count: + type: + - "null" + - integer + type: + type: + - "null" + - string + created_at: + type: + - "null" + - string + format: date-time + updated_at: + type: + - "null" + - string + format: date-time + options: + type: + - "null" + - object + properties: + match: + type: + - "null" + - string + conditions: + type: + - "null" + - array + items: + type: + - "null" + - object + additionalProperties: true + properties: + condition_type: + type: + - "null" + - string + field: + type: + - "null" + - string + op: + type: + - "null" + - string + list_id: + type: + - "null" + - string + _meta: + type: object + properties: + row_id: + type: integer + required: + - row_id diff --git a/source-mailchimp/acmeCo/unsubscribes.schema.yaml b/source-mailchimp/acmeCo/unsubscribes.schema.yaml new file mode 100644 index 0000000000..de939a331c --- /dev/null +++ b/source-mailchimp/acmeCo/unsubscribes.schema.yaml @@ -0,0 +1,48 @@ +--- +$schema: "http://json-schema.org/draft-07/schema#" +type: object +additionalProperties: true +required: + - campaign_id + - email_id + - timestamp +properties: + email_id: + type: string + email_address: + type: + - "null" + - string + merge_fields: + type: + - "null" + - object + additionalProperties: true + vip: + type: + - "null" + - boolean + timestamp: + type: string + format: date-time + reason: + type: + - "null" + - string + campaign_id: + type: string + list_id: + type: + - "null" + - string + list_is_active: + type: + - "null" + - boolean + _meta: + type: object + properties: + row_id: + type: integer + required: + - row_id diff --git a/source-mailchimp/config.yaml b/source-mailchimp/config.yaml new file mode 100644 index 0000000000..5eaebc7894 --- /dev/null +++ b/source-mailchimp/config.yaml @@ -0,0 +1,17 @@ +credentials: + auth_type: apikey + apikey_sops: ENC[AES256_GCM,data:4B/VTwYCkB2uc3QM0DBRk757/eqaJ1FzAdwbwbgkVzpCtgv3tQ==,iv:CleHnlAI6iCB6oRxIoYVJ4Oaw6QBOBlB8RgwDrDzeSU=,tag:+pdWVoiHyOHh1uczEMGJxg==,type:str] +sops: + kms: [] + gcp_kms: + - resource_id: projects/estuary-theatre/locations/us-central1/keyRings/connector-keyring/cryptoKeys/connector-repository + created_at: "2024-04-26T02:11:51Z" + enc: CiQAdmEdwpe7go7loWHFoP1QD0mqsGfqLq1/3jJuZSlmkJmPhmASSQCSobQjpuhj0SICJqn2EBxhNXDcndy4FOOhsMoxDwj7BbazTokCBtTFI1AA2jjllh0LxVoOa8+C2KJpQxGAQayZ2kq2XIzldCI= + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2024-04-26T02:11:52Z" + mac: ENC[AES256_GCM,data:l2QNjQI5oHC4T93MqB9LQCPkInF4sf2X1CjYTbmIcUgQnniHHNFAHMwT0SbYg0IcQwMJEJoItEoVqhA1dpc9M4n9TbIios2PFPUvdYPeiJb1B9NXGaMQDZ25H7GSG1SQ12Dw4fjGjyGYvyuAgo5Ok/kXuhTsQYE0VWY8vd0gBmM=,iv:y0JMPEGuUcyRS99GSK2qfAwFNCXGdm22xUcplyaLMoY=,tag:L1Gby/By5gJ1DluYUNOg5g==,type:str] + pgp: [] + encrypted_suffix: _sops + version: 3.8.1 diff --git a/source-mailchimp/poetry.lock b/source-mailchimp/poetry.lock new file mode 100644 index 0000000000..4db7c577e4 --- /dev/null +++ b/source-mailchimp/poetry.lock @@ -0,0 +1,1931 @@ +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. + +[[package]] +name = "aiodns" +version = "3.2.0" +description = "Simple DNS resolver for asyncio" +optional = false +python-versions = "*" +files = [ + {file = "aiodns-3.2.0-py3-none-any.whl", hash = "sha256:e443c0c27b07da3174a109fd9e736d69058d808f144d3c9d56dbd1776964c5f5"}, + {file = "aiodns-3.2.0.tar.gz", hash = "sha256:62869b23409349c21b072883ec8998316b234c9a9e36675756e8e317e8768f72"}, +] + +[package.dependencies] +pycares = ">=4.0.0" + +[[package]] +name = "aiohttp" +version = "3.9.5" +description = "Async http client/server framework (asyncio)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "aiohttp-3.9.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fcde4c397f673fdec23e6b05ebf8d4751314fa7c24f93334bf1f1364c1c69ac7"}, + {file = "aiohttp-3.9.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5d6b3f1fabe465e819aed2c421a6743d8debbde79b6a8600739300630a01bf2c"}, + {file = "aiohttp-3.9.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ae79c1bc12c34082d92bf9422764f799aee4746fd7a392db46b7fd357d4a17a"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d3ebb9e1316ec74277d19c5f482f98cc65a73ccd5430540d6d11682cd857430"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84dabd95154f43a2ea80deffec9cb44d2e301e38a0c9d331cc4aa0166fe28ae3"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8a02fbeca6f63cb1f0475c799679057fc9268b77075ab7cf3f1c600e81dd46b"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c26959ca7b75ff768e2776d8055bf9582a6267e24556bb7f7bd29e677932be72"}, + {file = "aiohttp-3.9.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:714d4e5231fed4ba2762ed489b4aec07b2b9953cf4ee31e9871caac895a839c0"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7a6a8354f1b62e15d48e04350f13e726fa08b62c3d7b8401c0a1314f02e3558"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c413016880e03e69d166efb5a1a95d40f83d5a3a648d16486592c49ffb76d0db"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ff84aeb864e0fac81f676be9f4685f0527b660f1efdc40dcede3c251ef1e867f"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ad7f2919d7dac062f24d6f5fe95d401597fbb015a25771f85e692d043c9d7832"}, + {file = "aiohttp-3.9.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:702e2c7c187c1a498a4e2b03155d52658fdd6fda882d3d7fbb891a5cf108bb10"}, + {file = "aiohttp-3.9.5-cp310-cp310-win32.whl", hash = "sha256:67c3119f5ddc7261d47163ed86d760ddf0e625cd6246b4ed852e82159617b5fb"}, + {file = "aiohttp-3.9.5-cp310-cp310-win_amd64.whl", hash = "sha256:471f0ef53ccedec9995287f02caf0c068732f026455f07db3f01a46e49d76bbb"}, + {file = "aiohttp-3.9.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e0ae53e33ee7476dd3d1132f932eeb39bf6125083820049d06edcdca4381f342"}, + {file = "aiohttp-3.9.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c088c4d70d21f8ca5c0b8b5403fe84a7bc8e024161febdd4ef04575ef35d474d"}, + {file = "aiohttp-3.9.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:639d0042b7670222f33b0028de6b4e2fad6451462ce7df2af8aee37dcac55424"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f26383adb94da5e7fb388d441bf09c61e5e35f455a3217bfd790c6b6bc64b2ee"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66331d00fb28dc90aa606d9a54304af76b335ae204d1836f65797d6fe27f1ca2"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4ff550491f5492ab5ed3533e76b8567f4b37bd2995e780a1f46bca2024223233"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f22eb3a6c1080d862befa0a89c380b4dafce29dc6cd56083f630073d102eb595"}, + {file = "aiohttp-3.9.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a81b1143d42b66ffc40a441379387076243ef7b51019204fd3ec36b9f69e77d6"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f64fd07515dad67f24b6ea4a66ae2876c01031de91c93075b8093f07c0a2d93d"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:93e22add827447d2e26d67c9ac0161756007f152fdc5210277d00a85f6c92323"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:55b39c8684a46e56ef8c8d24faf02de4a2b2ac60d26cee93bc595651ff545de9"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4715a9b778f4293b9f8ae7a0a7cef9829f02ff8d6277a39d7f40565c737d3771"}, + {file = "aiohttp-3.9.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:afc52b8d969eff14e069a710057d15ab9ac17cd4b6753042c407dcea0e40bf75"}, + {file = "aiohttp-3.9.5-cp311-cp311-win32.whl", hash = "sha256:b3df71da99c98534be076196791adca8819761f0bf6e08e07fd7da25127150d6"}, + {file = "aiohttp-3.9.5-cp311-cp311-win_amd64.whl", hash = "sha256:88e311d98cc0bf45b62fc46c66753a83445f5ab20038bcc1b8a1cc05666f428a"}, + {file = "aiohttp-3.9.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:c7a4b7a6cf5b6eb11e109a9755fd4fda7d57395f8c575e166d363b9fc3ec4678"}, + {file = "aiohttp-3.9.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:0a158704edf0abcac8ac371fbb54044f3270bdbc93e254a82b6c82be1ef08f3c"}, + {file = "aiohttp-3.9.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d153f652a687a8e95ad367a86a61e8d53d528b0530ef382ec5aaf533140ed00f"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82a6a97d9771cb48ae16979c3a3a9a18b600a8505b1115cfe354dfb2054468b4"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60cdbd56f4cad9f69c35eaac0fbbdf1f77b0ff9456cebd4902f3dd1cf096464c"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8676e8fd73141ded15ea586de0b7cda1542960a7b9ad89b2b06428e97125d4fa"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da00da442a0e31f1c69d26d224e1efd3a1ca5bcbf210978a2ca7426dfcae9f58"}, + {file = "aiohttp-3.9.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18f634d540dd099c262e9f887c8bbacc959847cfe5da7a0e2e1cf3f14dbf2daf"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:320e8618eda64e19d11bdb3bd04ccc0a816c17eaecb7e4945d01deee2a22f95f"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:2faa61a904b83142747fc6a6d7ad8fccff898c849123030f8e75d5d967fd4a81"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:8c64a6dc3fe5db7b1b4d2b5cb84c4f677768bdc340611eca673afb7cf416ef5a"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:393c7aba2b55559ef7ab791c94b44f7482a07bf7640d17b341b79081f5e5cd1a"}, + {file = "aiohttp-3.9.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c671dc117c2c21a1ca10c116cfcd6e3e44da7fcde37bf83b2be485ab377b25da"}, + {file = "aiohttp-3.9.5-cp312-cp312-win32.whl", hash = "sha256:5a7ee16aab26e76add4afc45e8f8206c95d1d75540f1039b84a03c3b3800dd59"}, + {file = "aiohttp-3.9.5-cp312-cp312-win_amd64.whl", hash = "sha256:5ca51eadbd67045396bc92a4345d1790b7301c14d1848feaac1d6a6c9289e888"}, + {file = "aiohttp-3.9.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:694d828b5c41255e54bc2dddb51a9f5150b4eefa9886e38b52605a05d96566e8"}, + {file = "aiohttp-3.9.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0605cc2c0088fcaae79f01c913a38611ad09ba68ff482402d3410bf59039bfb8"}, + {file = "aiohttp-3.9.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4558e5012ee03d2638c681e156461d37b7a113fe13970d438d95d10173d25f78"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dbc053ac75ccc63dc3a3cc547b98c7258ec35a215a92bd9f983e0aac95d3d5b"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4109adee842b90671f1b689901b948f347325045c15f46b39797ae1bf17019de"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6ea1a5b409a85477fd8e5ee6ad8f0e40bf2844c270955e09360418cfd09abac"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3c2890ca8c59ee683fd09adf32321a40fe1cf164e3387799efb2acebf090c11"}, + {file = "aiohttp-3.9.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3916c8692dbd9d55c523374a3b8213e628424d19116ac4308e434dbf6d95bbdd"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8d1964eb7617907c792ca00b341b5ec3e01ae8c280825deadbbd678447b127e1"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d5ab8e1f6bee051a4bf6195e38a5c13e5e161cb7bad83d8854524798bd9fcd6e"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:52c27110f3862a1afbcb2af4281fc9fdc40327fa286c4625dfee247c3ba90156"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:7f64cbd44443e80094309875d4f9c71d0401e966d191c3d469cde4642bc2e031"}, + {file = "aiohttp-3.9.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8b4f72fbb66279624bfe83fd5eb6aea0022dad8eec62b71e7bf63ee1caadeafe"}, + {file = "aiohttp-3.9.5-cp38-cp38-win32.whl", hash = "sha256:6380c039ec52866c06d69b5c7aad5478b24ed11696f0e72f6b807cfb261453da"}, + {file = "aiohttp-3.9.5-cp38-cp38-win_amd64.whl", hash = "sha256:da22dab31d7180f8c3ac7c7635f3bcd53808f374f6aa333fe0b0b9e14b01f91a"}, + {file = "aiohttp-3.9.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1732102949ff6087589408d76cd6dea656b93c896b011ecafff418c9661dc4ed"}, + {file = "aiohttp-3.9.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c6021d296318cb6f9414b48e6a439a7f5d1f665464da507e8ff640848ee2a58a"}, + {file = "aiohttp-3.9.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:239f975589a944eeb1bad26b8b140a59a3a320067fb3cd10b75c3092405a1372"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b7b30258348082826d274504fbc7c849959f1989d86c29bc355107accec6cfb"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd2adf5c87ff6d8b277814a28a535b59e20bfea40a101db6b3bdca7e9926bc24"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e9a3d838441bebcf5cf442700e3963f58b5c33f015341f9ea86dcd7d503c07e2"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e3a1ae66e3d0c17cf65c08968a5ee3180c5a95920ec2731f53343fac9bad106"}, + {file = "aiohttp-3.9.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9c69e77370cce2d6df5d12b4e12bdcca60c47ba13d1cbbc8645dd005a20b738b"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf56238f4bbf49dab8c2dc2e6b1b68502b1e88d335bea59b3f5b9f4c001475"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d1469f228cd9ffddd396d9948b8c9cd8022b6d1bf1e40c6f25b0fb90b4f893ed"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:45731330e754f5811c314901cebdf19dd776a44b31927fa4b4dbecab9e457b0c"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:3fcb4046d2904378e3aeea1df51f697b0467f2aac55d232c87ba162709478c46"}, + {file = "aiohttp-3.9.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8cf142aa6c1a751fcb364158fd710b8a9be874b81889c2bd13aa8893197455e2"}, + {file = "aiohttp-3.9.5-cp39-cp39-win32.whl", hash = "sha256:7b179eea70833c8dee51ec42f3b4097bd6370892fa93f510f76762105568cf09"}, + {file = "aiohttp-3.9.5-cp39-cp39-win_amd64.whl", hash = "sha256:38d80498e2e169bc61418ff36170e0aad0cd268da8b38a17c4cf29d254a8b3f1"}, + {file = "aiohttp-3.9.5.tar.gz", hash = "sha256:edea7d15772ceeb29db4aff55e482d4bcfb6ae160ce144f2682de02f6d693551"}, +] + +[package.dependencies] +aiosignal = ">=1.1.2" +attrs = ">=17.3.0" +frozenlist = ">=1.1.1" +multidict = ">=4.5,<7.0" +yarl = ">=1.0,<2.0" + +[package.extras] +speedups = ["Brotli", "aiodns", "brotlicffi"] + +[[package]] +name = "aiosignal" +version = "1.3.1" +description = "aiosignal: a list of registered asynchronous callbacks" +optional = false +python-versions = ">=3.7" +files = [ + {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, + {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, +] + +[package.dependencies] +frozenlist = ">=1.1.0" + +[[package]] +name = "airbyte-cdk" +version = "0.52.10" +description = "A framework for writing Airbyte Connectors." +optional = false +python-versions = ">=3.8" +files = [ + {file = "airbyte-cdk-0.52.10.tar.gz", hash = "sha256:0daee950fe0d4453e6ceea2633090fc1d2144224e6f170b3c6cb4c6392811b47"}, + {file = "airbyte_cdk-0.52.10-py3-none-any.whl", hash = "sha256:366fd7bbbba317223edc1571d22b91c6f5bcff4ba65b3131e42f9b37e29932f4"}, +] + +[package.dependencies] +airbyte-protocol-models = "0.4.2" +backoff = "*" +cachetools = "*" +Deprecated = ">=1.2,<2.0" +dpath = ">=2.0.1,<2.1.0" +genson = "1.2.2" +isodate = ">=0.6.1,<0.7.0" +Jinja2 = ">=3.1.2,<3.2.0" +jsonref = ">=0.2,<1.0" +jsonschema = ">=3.2.0,<3.3.0" +pendulum = "*" +pydantic = ">=1.10.8,<2.0.0" +python-dateutil = "*" +PyYAML = ">=6.0.1" +requests = "*" +requests-cache = "*" +wcmatch = "8.4" + +[package.extras] +dev = ["avro (>=1.11.2,<1.12.0)", "cohere (==4.21)", "fastavro (>=1.8.0,<1.9.0)", "freezegun", "langchain (==0.0.271)", "markdown", "mypy", "openai[embeddings] (==0.27.9)", "pandas (==2.0.3)", "pdf2image (==1.16.3)", "pdfminer.six (==20221105)", "pyarrow (==12.0.1)", "pytesseract (==0.3.10)", "pytest", "pytest-cov", "pytest-httpserver", "pytest-mock", "requests-mock", "tiktoken (==0.4.0)", "unstructured (==0.10.19)", "unstructured.pytesseract (>=0.3.12)", "unstructured[docx,pptx] (==0.10.19)"] +file-based = ["avro (>=1.11.2,<1.12.0)", "fastavro (>=1.8.0,<1.9.0)", "markdown", "pdf2image (==1.16.3)", "pdfminer.six (==20221105)", "pyarrow (==12.0.1)", "pytesseract (==0.3.10)", "unstructured (==0.10.19)", "unstructured.pytesseract (>=0.3.12)", "unstructured[docx,pptx] (==0.10.19)"] +sphinx-docs = ["Sphinx (>=4.2,<5.0)", "sphinx-rtd-theme (>=1.0,<2.0)"] +vector-db-based = ["cohere (==4.21)", "langchain (==0.0.271)", "openai[embeddings] (==0.27.9)", "tiktoken (==0.4.0)"] + +[[package]] +name = "airbyte-protocol-models" +version = "0.4.2" +description = "Declares the Airbyte Protocol." +optional = false +python-versions = ">=3.8" +files = [ + {file = "airbyte_protocol_models-0.4.2-py3-none-any.whl", hash = "sha256:d3bbb14d4af9483bd7b08f5eb06f87e7113553bf4baed3998af95be873a0d821"}, + {file = "airbyte_protocol_models-0.4.2.tar.gz", hash = "sha256:67b149d4812f8fdb88396b161274aa73cf0e16f22e35ce44f2bfc4d47e51915c"}, +] + +[package.dependencies] +pydantic = ">=1.9.2,<2.0.0" + +[[package]] +name = "attrs" +version = "23.2.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.7" +files = [ + {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, + {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, +] + +[package.extras] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] +tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] + +[[package]] +name = "backoff" +version = "2.2.1" +description = "Function decoration for backoff and retry" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8"}, + {file = "backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba"}, +] + +[[package]] +name = "bracex" +version = "2.4" +description = "Bash style brace expander." +optional = false +python-versions = ">=3.8" +files = [ + {file = "bracex-2.4-py3-none-any.whl", hash = "sha256:efdc71eff95eaff5e0f8cfebe7d01adf2c8637c8c92edaf63ef348c241a82418"}, + {file = "bracex-2.4.tar.gz", hash = "sha256:a27eaf1df42cf561fed58b7a8f3fdf129d1ea16a81e1fadd1d17989bc6384beb"}, +] + +[[package]] +name = "cachetools" +version = "5.3.3" +description = "Extensible memoizing collections and decorators" +optional = false +python-versions = ">=3.7" +files = [ + {file = "cachetools-5.3.3-py3-none-any.whl", hash = "sha256:0abad1021d3f8325b2fc1d2e9c8b9c9d57b04c3932657a72465447332c24d945"}, + {file = "cachetools-5.3.3.tar.gz", hash = "sha256:ba29e2dfa0b8b556606f097407ed1aa62080ee108ab0dc5ec9d6a723a007d105"}, +] + +[[package]] +name = "cattrs" +version = "23.2.3" +description = "Composable complex class support for attrs and dataclasses." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cattrs-23.2.3-py3-none-any.whl", hash = "sha256:0341994d94971052e9ee70662542699a3162ea1e0c62f7ce1b4a57f563685108"}, + {file = "cattrs-23.2.3.tar.gz", hash = "sha256:a934090d95abaa9e911dac357e3a8699e0b4b14f8529bcc7d2b1ad9d51672b9f"}, +] + +[package.dependencies] +attrs = ">=23.1.0" + +[package.extras] +bson = ["pymongo (>=4.4.0)"] +cbor2 = ["cbor2 (>=5.4.6)"] +msgpack = ["msgpack (>=1.0.5)"] +orjson = ["orjson (>=3.9.2)"] +pyyaml = ["pyyaml (>=6.0)"] +tomlkit = ["tomlkit (>=0.11.8)"] +ujson = ["ujson (>=5.7.0)"] + +[[package]] +name = "certifi" +version = "2024.2.2" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, +] + +[[package]] +name = "cffi" +version = "1.16.0" +description = "Foreign Function Interface for Python calling C code." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, + {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, + {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, + {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, + {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, + {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, + {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, + {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, + {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, + {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, + {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, + {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, + {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, + {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, + {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, +] + +[package.dependencies] +pycparser = "*" + +[[package]] +name = "charset-normalizer" +version = "3.3.2" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, +] + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "debugpy" +version = "1.8.1" +description = "An implementation of the Debug Adapter Protocol for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "debugpy-1.8.1-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:3bda0f1e943d386cc7a0e71bfa59f4137909e2ed947fb3946c506e113000f741"}, + {file = "debugpy-1.8.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dda73bf69ea479c8577a0448f8c707691152e6c4de7f0c4dec5a4bc11dee516e"}, + {file = "debugpy-1.8.1-cp310-cp310-win32.whl", hash = "sha256:3a79c6f62adef994b2dbe9fc2cc9cc3864a23575b6e387339ab739873bea53d0"}, + {file = "debugpy-1.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:7eb7bd2b56ea3bedb009616d9e2f64aab8fc7000d481faec3cd26c98a964bcdd"}, + {file = "debugpy-1.8.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:016a9fcfc2c6b57f939673c874310d8581d51a0fe0858e7fac4e240c5eb743cb"}, + {file = "debugpy-1.8.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd97ed11a4c7f6d042d320ce03d83b20c3fb40da892f994bc041bbc415d7a099"}, + {file = "debugpy-1.8.1-cp311-cp311-win32.whl", hash = "sha256:0de56aba8249c28a300bdb0672a9b94785074eb82eb672db66c8144fff673146"}, + {file = "debugpy-1.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:1a9fe0829c2b854757b4fd0a338d93bc17249a3bf69ecf765c61d4c522bb92a8"}, + {file = "debugpy-1.8.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3ebb70ba1a6524d19fa7bb122f44b74170c447d5746a503e36adc244a20ac539"}, + {file = "debugpy-1.8.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2e658a9630f27534e63922ebf655a6ab60c370f4d2fc5c02a5b19baf4410ace"}, + {file = "debugpy-1.8.1-cp312-cp312-win32.whl", hash = "sha256:caad2846e21188797a1f17fc09c31b84c7c3c23baf2516fed5b40b378515bbf0"}, + {file = "debugpy-1.8.1-cp312-cp312-win_amd64.whl", hash = "sha256:edcc9f58ec0fd121a25bc950d4578df47428d72e1a0d66c07403b04eb93bcf98"}, + {file = "debugpy-1.8.1-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:7a3afa222f6fd3d9dfecd52729bc2e12c93e22a7491405a0ecbf9e1d32d45b39"}, + {file = "debugpy-1.8.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d915a18f0597ef685e88bb35e5d7ab968964b7befefe1aaea1eb5b2640b586c7"}, + {file = "debugpy-1.8.1-cp38-cp38-win32.whl", hash = "sha256:92116039b5500633cc8d44ecc187abe2dfa9b90f7a82bbf81d079fcdd506bae9"}, + {file = "debugpy-1.8.1-cp38-cp38-win_amd64.whl", hash = "sha256:e38beb7992b5afd9d5244e96ad5fa9135e94993b0c551ceebf3fe1a5d9beb234"}, + {file = "debugpy-1.8.1-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:bfb20cb57486c8e4793d41996652e5a6a885b4d9175dd369045dad59eaacea42"}, + {file = "debugpy-1.8.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efd3fdd3f67a7e576dd869c184c5dd71d9aaa36ded271939da352880c012e703"}, + {file = "debugpy-1.8.1-cp39-cp39-win32.whl", hash = "sha256:58911e8521ca0c785ac7a0539f1e77e0ce2df753f786188f382229278b4cdf23"}, + {file = "debugpy-1.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:6df9aa9599eb05ca179fb0b810282255202a66835c6efb1d112d21ecb830ddd3"}, + {file = "debugpy-1.8.1-py2.py3-none-any.whl", hash = "sha256:28acbe2241222b87e255260c76741e1fbf04fdc3b6d094fcf57b6c6f75ce1242"}, + {file = "debugpy-1.8.1.zip", hash = "sha256:f696d6be15be87aef621917585f9bb94b1dc9e8aced570db1b8a6fc14e8f9b42"}, +] + +[[package]] +name = "deprecated" +version = "1.2.14" +description = "Python @deprecated decorator to deprecate old python classes, functions or methods." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"}, + {file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"}, +] + +[package.dependencies] +wrapt = ">=1.10,<2" + +[package.extras] +dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] + +[[package]] +name = "dpath" +version = "2.0.8" +description = "Filesystem-like pathing and searching for dictionaries" +optional = false +python-versions = ">=3.7" +files = [ + {file = "dpath-2.0.8-py3-none-any.whl", hash = "sha256:f92f595214dd93a00558d75d4b858beee519f4cffca87f02616ad6cd013f3436"}, + {file = "dpath-2.0.8.tar.gz", hash = "sha256:a3440157ebe80d0a3ad794f1b61c571bef125214800ffdb9afc9424e8250fe9b"}, +] + +[[package]] +name = "estuary-cdk" +version = "0.2.0" +description = "Estuary Connector Development Kit" +optional = false +python-versions = "^3.11" +files = [] +develop = true + +[package.dependencies] +aiodns = "^3.1.1" +aiohttp = "^3.9.3" +orjson = "^3.9.15" +pydantic = ">1.10,<3" +xxhash = "^3.4.1" + +[package.source] +type = "directory" +url = "../estuary-cdk" + +[[package]] +name = "freezegun" +version = "1.5.0" +description = "Let your Python tests travel through time" +optional = false +python-versions = ">=3.7" +files = [ + {file = "freezegun-1.5.0-py3-none-any.whl", hash = "sha256:ec3f4ba030e34eb6cf7e1e257308aee2c60c3d038ff35996d7475760c9ff3719"}, + {file = "freezegun-1.5.0.tar.gz", hash = "sha256:200a64359b363aa3653d8aac289584078386c7c3da77339d257e46a01fb5c77c"}, +] + +[package.dependencies] +python-dateutil = ">=2.7" + +[[package]] +name = "frozenlist" +version = "1.4.1" +description = "A list-like structure which implements collections.abc.MutableSequence" +optional = false +python-versions = ">=3.8" +files = [ + {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"}, + {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"}, + {file = "frozenlist-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc"}, + {file = "frozenlist-1.4.1-cp310-cp310-win32.whl", hash = "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1"}, + {file = "frozenlist-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"}, + {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"}, + {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"}, + {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"}, + {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7"}, + {file = "frozenlist-1.4.1-cp38-cp38-win32.whl", hash = "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497"}, + {file = "frozenlist-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6"}, + {file = "frozenlist-1.4.1-cp39-cp39-win32.whl", hash = "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932"}, + {file = "frozenlist-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0"}, + {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"}, + {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"}, +] + +[[package]] +name = "genson" +version = "1.2.2" +description = "GenSON is a powerful, user-friendly JSON Schema generator." +optional = false +python-versions = "*" +files = [ + {file = "genson-1.2.2.tar.gz", hash = "sha256:8caf69aa10af7aee0e1a1351d1d06801f4696e005f06cedef438635384346a16"}, +] + +[[package]] +name = "idna" +version = "3.7" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, + {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, +] + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "isodate" +version = "0.6.1" +description = "An ISO 8601 date/time/duration parser and formatter" +optional = false +python-versions = "*" +files = [ + {file = "isodate-0.6.1-py2.py3-none-any.whl", hash = "sha256:0751eece944162659049d35f4f549ed815792b38793f07cf73381c1c87cbed96"}, + {file = "isodate-0.6.1.tar.gz", hash = "sha256:48c5881de7e8b0a0d648cb024c8062dc84e7b840ed81e864c7614fd3c127bde9"}, +] + +[package.dependencies] +six = "*" + +[[package]] +name = "jinja2" +version = "3.1.3" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, + {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "jsonref" +version = "0.3.0" +description = "jsonref is a library for automatic dereferencing of JSON Reference objects for Python." +optional = false +python-versions = ">=3.3,<4.0" +files = [ + {file = "jsonref-0.3.0-py3-none-any.whl", hash = "sha256:9480ad1b500f7e795daeb0ef29f9c55ae3a9ab38fb8d6659b6f4868acb5a5bc8"}, + {file = "jsonref-0.3.0.tar.gz", hash = "sha256:68b330c6815dc0d490dbb3d65ccda265ddde9f7856fd2f3322f971d456ea7549"}, +] + +[[package]] +name = "jsonschema" +version = "3.2.0" +description = "An implementation of JSON Schema validation for Python" +optional = false +python-versions = "*" +files = [ + {file = "jsonschema-3.2.0-py2.py3-none-any.whl", hash = "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163"}, + {file = "jsonschema-3.2.0.tar.gz", hash = "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"}, +] + +[package.dependencies] +attrs = ">=17.4.0" +pyrsistent = ">=0.14.0" +setuptools = "*" +six = ">=1.11.0" + +[package.extras] +format = ["idna", "jsonpointer (>1.13)", "rfc3987", "strict-rfc3339", "webcolors"] +format-nongpl = ["idna", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "webcolors"] + +[[package]] +name = "markupsafe" +version = "2.1.5" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.7" +files = [ + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, + {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, +] + +[[package]] +name = "mock" +version = "5.1.0" +description = "Rolling backport of unittest.mock for all Pythons" +optional = false +python-versions = ">=3.6" +files = [ + {file = "mock-5.1.0-py3-none-any.whl", hash = "sha256:18c694e5ae8a208cdb3d2c20a993ca1a7b0efa258c247a1e565150f477f83744"}, + {file = "mock-5.1.0.tar.gz", hash = "sha256:5e96aad5ccda4718e0a229ed94b2024df75cc2d55575ba5762d31f5767b8767d"}, +] + +[package.extras] +build = ["blurb", "twine", "wheel"] +docs = ["sphinx"] +test = ["pytest", "pytest-cov"] + +[[package]] +name = "multidict" +version = "6.0.5" +description = "multidict implementation" +optional = false +python-versions = ">=3.7" +files = [ + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"}, + {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"}, + {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"}, + {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"}, + {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, + {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, + {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, + {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"}, + {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"}, + {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"}, + {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"}, + {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"}, + {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"}, + {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"}, + {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, + {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, +] + +[[package]] +name = "mypy" +version = "1.10.0" +description = "Optional static typing for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy-1.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:da1cbf08fb3b851ab3b9523a884c232774008267b1f83371ace57f412fe308c2"}, + {file = "mypy-1.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:12b6bfc1b1a66095ab413160a6e520e1dc076a28f3e22f7fb25ba3b000b4ef99"}, + {file = "mypy-1.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e36fb078cce9904c7989b9693e41cb9711e0600139ce3970c6ef814b6ebc2b2"}, + {file = "mypy-1.10.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2b0695d605ddcd3eb2f736cd8b4e388288c21e7de85001e9f85df9187f2b50f9"}, + {file = "mypy-1.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:cd777b780312ddb135bceb9bc8722a73ec95e042f911cc279e2ec3c667076051"}, + {file = "mypy-1.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3be66771aa5c97602f382230165b856c231d1277c511c9a8dd058be4784472e1"}, + {file = "mypy-1.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8b2cbaca148d0754a54d44121b5825ae71868c7592a53b7292eeb0f3fdae95ee"}, + {file = "mypy-1.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ec404a7cbe9fc0e92cb0e67f55ce0c025014e26d33e54d9e506a0f2d07fe5de"}, + {file = "mypy-1.10.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e22e1527dc3d4aa94311d246b59e47f6455b8729f4968765ac1eacf9a4760bc7"}, + {file = "mypy-1.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:a87dbfa85971e8d59c9cc1fcf534efe664d8949e4c0b6b44e8ca548e746a8d53"}, + {file = "mypy-1.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a781f6ad4bab20eef8b65174a57e5203f4be627b46291f4589879bf4e257b97b"}, + {file = "mypy-1.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b808e12113505b97d9023b0b5e0c0705a90571c6feefc6f215c1df9381256e30"}, + {file = "mypy-1.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f55583b12156c399dce2df7d16f8a5095291354f1e839c252ec6c0611e86e2e"}, + {file = "mypy-1.10.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4cf18f9d0efa1b16478c4c129eabec36148032575391095f73cae2e722fcf9d5"}, + {file = "mypy-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:bc6ac273b23c6b82da3bb25f4136c4fd42665f17f2cd850771cb600bdd2ebeda"}, + {file = "mypy-1.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9fd50226364cd2737351c79807775136b0abe084433b55b2e29181a4c3c878c0"}, + {file = "mypy-1.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f90cff89eea89273727d8783fef5d4a934be2fdca11b47def50cf5d311aff727"}, + {file = "mypy-1.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fcfc70599efde5c67862a07a1aaf50e55bce629ace26bb19dc17cece5dd31ca4"}, + {file = "mypy-1.10.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:075cbf81f3e134eadaf247de187bd604748171d6b79736fa9b6c9685b4083061"}, + {file = "mypy-1.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:3f298531bca95ff615b6e9f2fc0333aae27fa48052903a0ac90215021cdcfa4f"}, + {file = "mypy-1.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fa7ef5244615a2523b56c034becde4e9e3f9b034854c93639adb667ec9ec2976"}, + {file = "mypy-1.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3236a4c8f535a0631f85f5fcdffba71c7feeef76a6002fcba7c1a8e57c8be1ec"}, + {file = "mypy-1.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a2b5cdbb5dd35aa08ea9114436e0d79aceb2f38e32c21684dcf8e24e1e92821"}, + {file = "mypy-1.10.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:92f93b21c0fe73dc00abf91022234c79d793318b8a96faac147cd579c1671746"}, + {file = "mypy-1.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:28d0e038361b45f099cc086d9dd99c15ff14d0188f44ac883010e172ce86c38a"}, + {file = "mypy-1.10.0-py3-none-any.whl", hash = "sha256:f8c083976eb530019175aabadb60921e73b4f45736760826aa1689dda8208aee"}, + {file = "mypy-1.10.0.tar.gz", hash = "sha256:3d087fcbec056c4ee34974da493a826ce316947485cef3901f511848e687c131"}, +] + +[package.dependencies] +mypy-extensions = ">=1.0.0" +typing-extensions = ">=4.1.0" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +install-types = ["pip"] +mypyc = ["setuptools (>=50)"] +reports = ["lxml"] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "orjson" +version = "3.10.1" +description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" +optional = false +python-versions = ">=3.8" +files = [ + {file = "orjson-3.10.1-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:8ec2fc456d53ea4a47768f622bb709be68acd455b0c6be57e91462259741c4f3"}, + {file = "orjson-3.10.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e900863691d327758be14e2a491931605bd0aded3a21beb6ce133889830b659"}, + {file = "orjson-3.10.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ab6ecbd6fe57785ebc86ee49e183f37d45f91b46fc601380c67c5c5e9c0014a2"}, + {file = "orjson-3.10.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8af7c68b01b876335cccfb4eee0beef2b5b6eae1945d46a09a7c24c9faac7a77"}, + {file = "orjson-3.10.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:915abfb2e528677b488a06eba173e9d7706a20fdfe9cdb15890b74ef9791b85e"}, + {file = "orjson-3.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe3fd4a36eff9c63d25503b439531d21828da9def0059c4f472e3845a081aa0b"}, + {file = "orjson-3.10.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d229564e72cfc062e6481a91977a5165c5a0fdce11ddc19ced8471847a67c517"}, + {file = "orjson-3.10.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9e00495b18304173ac843b5c5fbea7b6f7968564d0d49bef06bfaeca4b656f4e"}, + {file = "orjson-3.10.1-cp310-none-win32.whl", hash = "sha256:fd78ec55179545c108174ba19c1795ced548d6cac4d80d014163033c047ca4ea"}, + {file = "orjson-3.10.1-cp310-none-win_amd64.whl", hash = "sha256:50ca42b40d5a442a9e22eece8cf42ba3d7cd4cd0f2f20184b4d7682894f05eec"}, + {file = "orjson-3.10.1-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:b345a3d6953628df2f42502297f6c1e1b475cfbf6268013c94c5ac80e8abc04c"}, + {file = "orjson-3.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:caa7395ef51af4190d2c70a364e2f42138e0e5fcb4bc08bc9b76997659b27dab"}, + {file = "orjson-3.10.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b01d701decd75ae092e5f36f7b88a1e7a1d3bb7c9b9d7694de850fb155578d5a"}, + {file = "orjson-3.10.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b5028981ba393f443d8fed9049211b979cadc9d0afecf162832f5a5b152c6297"}, + {file = "orjson-3.10.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:31ff6a222ea362b87bf21ff619598a4dc1106aaafaea32b1c4876d692891ec27"}, + {file = "orjson-3.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e852a83d7803d3406135fb7a57cf0c1e4a3e73bac80ec621bd32f01c653849c5"}, + {file = "orjson-3.10.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2567bc928ed3c3fcd90998009e8835de7c7dc59aabcf764b8374d36044864f3b"}, + {file = "orjson-3.10.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4ce98cac60b7bb56457bdd2ed7f0d5d7f242d291fdc0ca566c83fa721b52e92d"}, + {file = "orjson-3.10.1-cp311-none-win32.whl", hash = "sha256:813905e111318acb356bb8029014c77b4c647f8b03f314e7b475bd9ce6d1a8ce"}, + {file = "orjson-3.10.1-cp311-none-win_amd64.whl", hash = "sha256:03a3ca0b3ed52bed1a869163a4284e8a7b0be6a0359d521e467cdef7e8e8a3ee"}, + {file = "orjson-3.10.1-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:f02c06cee680b1b3a8727ec26c36f4b3c0c9e2b26339d64471034d16f74f4ef5"}, + {file = "orjson-3.10.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1aa2f127ac546e123283e437cc90b5ecce754a22306c7700b11035dad4ccf85"}, + {file = "orjson-3.10.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2cf29b4b74f585225196944dffdebd549ad2af6da9e80db7115984103fb18a96"}, + {file = "orjson-3.10.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a1b130c20b116f413caf6059c651ad32215c28500dce9cd029a334a2d84aa66f"}, + {file = "orjson-3.10.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d31f9a709e6114492136e87c7c6da5e21dfedebefa03af85f3ad72656c493ae9"}, + {file = "orjson-3.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d1d169461726f271ab31633cf0e7e7353417e16fb69256a4f8ecb3246a78d6e"}, + {file = "orjson-3.10.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:57c294d73825c6b7f30d11c9e5900cfec9a814893af7f14efbe06b8d0f25fba9"}, + {file = "orjson-3.10.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d7f11dbacfa9265ec76b4019efffabaabba7a7ebf14078f6b4df9b51c3c9a8ea"}, + {file = "orjson-3.10.1-cp312-none-win32.whl", hash = "sha256:d89e5ed68593226c31c76ab4de3e0d35c760bfd3fbf0a74c4b2be1383a1bf123"}, + {file = "orjson-3.10.1-cp312-none-win_amd64.whl", hash = "sha256:aa76c4fe147fd162107ce1692c39f7189180cfd3a27cfbc2ab5643422812da8e"}, + {file = "orjson-3.10.1-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a2c6a85c92d0e494c1ae117befc93cf8e7bca2075f7fe52e32698da650b2c6d1"}, + {file = "orjson-3.10.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9813f43da955197d36a7365eb99bed42b83680801729ab2487fef305b9ced866"}, + {file = "orjson-3.10.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ec917b768e2b34b7084cb6c68941f6de5812cc26c6f1a9fecb728e36a3deb9e8"}, + {file = "orjson-3.10.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5252146b3172d75c8a6d27ebca59c9ee066ffc5a277050ccec24821e68742fdf"}, + {file = "orjson-3.10.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:536429bb02791a199d976118b95014ad66f74c58b7644d21061c54ad284e00f4"}, + {file = "orjson-3.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7dfed3c3e9b9199fb9c3355b9c7e4649b65f639e50ddf50efdf86b45c6de04b5"}, + {file = "orjson-3.10.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2b230ec35f188f003f5b543644ae486b2998f6afa74ee3a98fc8ed2e45960afc"}, + {file = "orjson-3.10.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:01234249ba19c6ab1eb0b8be89f13ea21218b2d72d496ef085cfd37e1bae9dd8"}, + {file = "orjson-3.10.1-cp38-none-win32.whl", hash = "sha256:8a884fbf81a3cc22d264ba780920d4885442144e6acaa1411921260416ac9a54"}, + {file = "orjson-3.10.1-cp38-none-win_amd64.whl", hash = "sha256:dab5f802d52b182163f307d2b1f727d30b1762e1923c64c9c56dd853f9671a49"}, + {file = "orjson-3.10.1-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a51fd55d4486bc5293b7a400f9acd55a2dc3b5fc8420d5ffe9b1d6bb1a056a5e"}, + {file = "orjson-3.10.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53521542a6db1411b3bfa1b24ddce18605a3abdc95a28a67b33f9145f26aa8f2"}, + {file = "orjson-3.10.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:27d610df96ac18ace4931411d489637d20ab3b8f63562b0531bba16011998db0"}, + {file = "orjson-3.10.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79244b1456e5846d44e9846534bd9e3206712936d026ea8e6a55a7374d2c0694"}, + {file = "orjson-3.10.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d751efaa8a49ae15cbebdda747a62a9ae521126e396fda8143858419f3b03610"}, + {file = "orjson-3.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27ff69c620a4fff33267df70cfd21e0097c2a14216e72943bd5414943e376d77"}, + {file = "orjson-3.10.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ebc58693464146506fde0c4eb1216ff6d4e40213e61f7d40e2f0dde9b2f21650"}, + {file = "orjson-3.10.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5be608c3972ed902e0143a5b8776d81ac1059436915d42defe5c6ae97b3137a4"}, + {file = "orjson-3.10.1-cp39-none-win32.whl", hash = "sha256:4ae10753e7511d359405aadcbf96556c86e9dbf3a948d26c2c9f9a150c52b091"}, + {file = "orjson-3.10.1-cp39-none-win_amd64.whl", hash = "sha256:fb5bc4caa2c192077fdb02dce4e5ef8639e7f20bec4e3a834346693907362932"}, + {file = "orjson-3.10.1.tar.gz", hash = "sha256:a883b28d73370df23ed995c466b4f6c708c1f7a9bdc400fe89165c96c7603204"}, +] + +[[package]] +name = "packaging" +version = "24.0" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, + {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, +] + +[[package]] +name = "pendulum" +version = "3.0.0" +description = "Python datetimes made easy" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pendulum-3.0.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2cf9e53ef11668e07f73190c805dbdf07a1939c3298b78d5a9203a86775d1bfd"}, + {file = "pendulum-3.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fb551b9b5e6059377889d2d878d940fd0bbb80ae4810543db18e6f77b02c5ef6"}, + {file = "pendulum-3.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c58227ac260d5b01fc1025176d7b31858c9f62595737f350d22124a9a3ad82d"}, + {file = "pendulum-3.0.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60fb6f415fea93a11c52578eaa10594568a6716602be8430b167eb0d730f3332"}, + {file = "pendulum-3.0.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b69f6b4dbcb86f2c2fe696ba991e67347bcf87fe601362a1aba6431454b46bde"}, + {file = "pendulum-3.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:138afa9c373ee450ede206db5a5e9004fd3011b3c6bbe1e57015395cd076a09f"}, + {file = "pendulum-3.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:83d9031f39c6da9677164241fd0d37fbfc9dc8ade7043b5d6d62f56e81af8ad2"}, + {file = "pendulum-3.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0c2308af4033fa534f089595bcd40a95a39988ce4059ccd3dc6acb9ef14ca44a"}, + {file = "pendulum-3.0.0-cp310-none-win_amd64.whl", hash = "sha256:9a59637cdb8462bdf2dbcb9d389518c0263799189d773ad5c11db6b13064fa79"}, + {file = "pendulum-3.0.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3725245c0352c95d6ca297193192020d1b0c0f83d5ee6bb09964edc2b5a2d508"}, + {file = "pendulum-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6c035f03a3e565ed132927e2c1b691de0dbf4eb53b02a5a3c5a97e1a64e17bec"}, + {file = "pendulum-3.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:597e66e63cbd68dd6d58ac46cb7a92363d2088d37ccde2dae4332ef23e95cd00"}, + {file = "pendulum-3.0.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99a0f8172e19f3f0c0e4ace0ad1595134d5243cf75985dc2233e8f9e8de263ca"}, + {file = "pendulum-3.0.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:77d8839e20f54706aed425bec82a83b4aec74db07f26acd039905d1237a5e1d4"}, + {file = "pendulum-3.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afde30e8146292b059020fbc8b6f8fd4a60ae7c5e6f0afef937bbb24880bdf01"}, + {file = "pendulum-3.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:660434a6fcf6303c4efd36713ca9212c753140107ee169a3fc6c49c4711c2a05"}, + {file = "pendulum-3.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dee9e5a48c6999dc1106eb7eea3e3a50e98a50651b72c08a87ee2154e544b33e"}, + {file = "pendulum-3.0.0-cp311-none-win_amd64.whl", hash = "sha256:d4cdecde90aec2d67cebe4042fd2a87a4441cc02152ed7ed8fb3ebb110b94ec4"}, + {file = "pendulum-3.0.0-cp311-none-win_arm64.whl", hash = "sha256:773c3bc4ddda2dda9f1b9d51fe06762f9200f3293d75c4660c19b2614b991d83"}, + {file = "pendulum-3.0.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:409e64e41418c49f973d43a28afe5df1df4f1dd87c41c7c90f1a63f61ae0f1f7"}, + {file = "pendulum-3.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a38ad2121c5ec7c4c190c7334e789c3b4624798859156b138fcc4d92295835dc"}, + {file = "pendulum-3.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fde4d0b2024b9785f66b7f30ed59281bd60d63d9213cda0eb0910ead777f6d37"}, + {file = "pendulum-3.0.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b2c5675769fb6d4c11238132962939b960fcb365436b6d623c5864287faa319"}, + {file = "pendulum-3.0.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8af95e03e066826f0f4c65811cbee1b3123d4a45a1c3a2b4fc23c4b0dff893b5"}, + {file = "pendulum-3.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2165a8f33cb15e06c67070b8afc87a62b85c5a273e3aaa6bc9d15c93a4920d6f"}, + {file = "pendulum-3.0.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ad5e65b874b5e56bd942546ea7ba9dd1d6a25121db1c517700f1c9de91b28518"}, + {file = "pendulum-3.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:17fe4b2c844bbf5f0ece69cfd959fa02957c61317b2161763950d88fed8e13b9"}, + {file = "pendulum-3.0.0-cp312-none-win_amd64.whl", hash = "sha256:78f8f4e7efe5066aca24a7a57511b9c2119f5c2b5eb81c46ff9222ce11e0a7a5"}, + {file = "pendulum-3.0.0-cp312-none-win_arm64.whl", hash = "sha256:28f49d8d1e32aae9c284a90b6bb3873eee15ec6e1d9042edd611b22a94ac462f"}, + {file = "pendulum-3.0.0-cp37-cp37m-macosx_10_12_x86_64.whl", hash = "sha256:d4e2512f4e1a4670284a153b214db9719eb5d14ac55ada5b76cbdb8c5c00399d"}, + {file = "pendulum-3.0.0-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:3d897eb50883cc58d9b92f6405245f84b9286cd2de6e8694cb9ea5cb15195a32"}, + {file = "pendulum-3.0.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e169cc2ca419517f397811bbe4589cf3cd13fca6dc38bb352ba15ea90739ebb"}, + {file = "pendulum-3.0.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f17c3084a4524ebefd9255513692f7e7360e23c8853dc6f10c64cc184e1217ab"}, + {file = "pendulum-3.0.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:826d6e258052715f64d05ae0fc9040c0151e6a87aae7c109ba9a0ed930ce4000"}, + {file = "pendulum-3.0.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2aae97087872ef152a0c40e06100b3665d8cb86b59bc8471ca7c26132fccd0f"}, + {file = "pendulum-3.0.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ac65eeec2250d03106b5e81284ad47f0d417ca299a45e89ccc69e36130ca8bc7"}, + {file = "pendulum-3.0.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a5346d08f3f4a6e9e672187faa179c7bf9227897081d7121866358af369f44f9"}, + {file = "pendulum-3.0.0-cp37-none-win_amd64.whl", hash = "sha256:235d64e87946d8f95c796af34818c76e0f88c94d624c268693c85b723b698aa9"}, + {file = "pendulum-3.0.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:6a881d9c2a7f85bc9adafcfe671df5207f51f5715ae61f5d838b77a1356e8b7b"}, + {file = "pendulum-3.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d7762d2076b9b1cb718a6631ad6c16c23fc3fac76cbb8c454e81e80be98daa34"}, + {file = "pendulum-3.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e8e36a8130819d97a479a0e7bf379b66b3b1b520e5dc46bd7eb14634338df8c"}, + {file = "pendulum-3.0.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7dc843253ac373358ffc0711960e2dd5b94ab67530a3e204d85c6e8cb2c5fa10"}, + {file = "pendulum-3.0.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0a78ad3635d609ceb1e97d6aedef6a6a6f93433ddb2312888e668365908c7120"}, + {file = "pendulum-3.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b30a137e9e0d1f751e60e67d11fc67781a572db76b2296f7b4d44554761049d6"}, + {file = "pendulum-3.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c95984037987f4a457bb760455d9ca80467be792236b69d0084f228a8ada0162"}, + {file = "pendulum-3.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d29c6e578fe0f893766c0d286adbf0b3c726a4e2341eba0917ec79c50274ec16"}, + {file = "pendulum-3.0.0-cp38-none-win_amd64.whl", hash = "sha256:deaba8e16dbfcb3d7a6b5fabdd5a38b7c982809567479987b9c89572df62e027"}, + {file = "pendulum-3.0.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b11aceea5b20b4b5382962b321dbc354af0defe35daa84e9ff3aae3c230df694"}, + {file = "pendulum-3.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a90d4d504e82ad236afac9adca4d6a19e4865f717034fc69bafb112c320dcc8f"}, + {file = "pendulum-3.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:825799c6b66e3734227756fa746cc34b3549c48693325b8b9f823cb7d21b19ac"}, + {file = "pendulum-3.0.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad769e98dc07972e24afe0cff8d365cb6f0ebc7e65620aa1976fcfbcadc4c6f3"}, + {file = "pendulum-3.0.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6fc26907eb5fb8cc6188cc620bc2075a6c534d981a2f045daa5f79dfe50d512"}, + {file = "pendulum-3.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c717eab1b6d898c00a3e0fa7781d615b5c5136bbd40abe82be100bb06df7a56"}, + {file = "pendulum-3.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3ddd1d66d1a714ce43acfe337190be055cdc221d911fc886d5a3aae28e14b76d"}, + {file = "pendulum-3.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:822172853d7a9cf6da95d7b66a16c7160cb99ae6df55d44373888181d7a06edc"}, + {file = "pendulum-3.0.0-cp39-none-win_amd64.whl", hash = "sha256:840de1b49cf1ec54c225a2a6f4f0784d50bd47f68e41dc005b7f67c7d5b5f3ae"}, + {file = "pendulum-3.0.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3b1f74d1e6ffe5d01d6023870e2ce5c2191486928823196f8575dcc786e107b1"}, + {file = "pendulum-3.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:729e9f93756a2cdfa77d0fc82068346e9731c7e884097160603872686e570f07"}, + {file = "pendulum-3.0.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e586acc0b450cd21cbf0db6bae386237011b75260a3adceddc4be15334689a9a"}, + {file = "pendulum-3.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22e7944ffc1f0099a79ff468ee9630c73f8c7835cd76fdb57ef7320e6a409df4"}, + {file = "pendulum-3.0.0-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fa30af36bd8e50686846bdace37cf6707bdd044e5cb6e1109acbad3277232e04"}, + {file = "pendulum-3.0.0-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:440215347b11914ae707981b9a57ab9c7b6983ab0babde07063c6ee75c0dc6e7"}, + {file = "pendulum-3.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:314c4038dc5e6a52991570f50edb2f08c339debdf8cea68ac355b32c4174e820"}, + {file = "pendulum-3.0.0-pp37-pypy37_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5acb1d386337415f74f4d1955c4ce8d0201978c162927d07df8eb0692b2d8533"}, + {file = "pendulum-3.0.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a789e12fbdefaffb7b8ac67f9d8f22ba17a3050ceaaa635cd1cc4645773a4b1e"}, + {file = "pendulum-3.0.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:860aa9b8a888e5913bd70d819306749e5eb488e6b99cd6c47beb701b22bdecf5"}, + {file = "pendulum-3.0.0-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:5ebc65ea033ef0281368217fbf59f5cb05b338ac4dd23d60959c7afcd79a60a0"}, + {file = "pendulum-3.0.0-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:d9fef18ab0386ef6a9ac7bad7e43ded42c83ff7ad412f950633854f90d59afa8"}, + {file = "pendulum-3.0.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1c134ba2f0571d0b68b83f6972e2307a55a5a849e7dac8505c715c531d2a8795"}, + {file = "pendulum-3.0.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:385680812e7e18af200bb9b4a49777418c32422d05ad5a8eb85144c4a285907b"}, + {file = "pendulum-3.0.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9eec91cd87c59fb32ec49eb722f375bd58f4be790cae11c1b70fac3ee4f00da0"}, + {file = "pendulum-3.0.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4386bffeca23c4b69ad50a36211f75b35a4deb6210bdca112ac3043deb7e494a"}, + {file = "pendulum-3.0.0-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:dfbcf1661d7146d7698da4b86e7f04814221081e9fe154183e34f4c5f5fa3bf8"}, + {file = "pendulum-3.0.0-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:04a1094a5aa1daa34a6b57c865b25f691848c61583fb22722a4df5699f6bf74c"}, + {file = "pendulum-3.0.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5b0ec85b9045bd49dd3a3493a5e7ddfd31c36a2a60da387c419fa04abcaecb23"}, + {file = "pendulum-3.0.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0a15b90129765b705eb2039062a6daf4d22c4e28d1a54fa260892e8c3ae6e157"}, + {file = "pendulum-3.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:bb8f6d7acd67a67d6fedd361ad2958ff0539445ef51cbe8cd288db4306503cd0"}, + {file = "pendulum-3.0.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd69b15374bef7e4b4440612915315cc42e8575fcda2a3d7586a0d88192d0c88"}, + {file = "pendulum-3.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc00f8110db6898360c53c812872662e077eaf9c75515d53ecc65d886eec209a"}, + {file = "pendulum-3.0.0-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:83a44e8b40655d0ba565a5c3d1365d27e3e6778ae2a05b69124db9e471255c4a"}, + {file = "pendulum-3.0.0-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:1a3604e9fbc06b788041b2a8b78f75c243021e0f512447806a6d37ee5214905d"}, + {file = "pendulum-3.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:92c307ae7accebd06cbae4729f0ba9fa724df5f7d91a0964b1b972a22baa482b"}, + {file = "pendulum-3.0.0.tar.gz", hash = "sha256:5d034998dea404ec31fae27af6b22cff1708f830a1ed7353be4d1019bb9f584e"}, +] + +[package.dependencies] +python-dateutil = ">=2.6" +tzdata = ">=2020.1" + +[package.extras] +test = ["time-machine (>=2.6.0)"] + +[[package]] +name = "platformdirs" +version = "4.2.1" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +optional = false +python-versions = ">=3.8" +files = [ + {file = "platformdirs-4.2.1-py3-none-any.whl", hash = "sha256:17d5a1161b3fd67b390023cb2d3b026bbd40abde6fdb052dfbd3a29c3ba22ee1"}, + {file = "platformdirs-4.2.1.tar.gz", hash = "sha256:031cd18d4ec63ec53e82dceaac0417d218a6863f7745dfcc9efe7793b7039bdf"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] +type = ["mypy (>=1.8)"] + +[[package]] +name = "pluggy" +version = "1.5.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pycares" +version = "4.4.0" +description = "Python interface for c-ares" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pycares-4.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:24da119850841d16996713d9c3374ca28a21deee056d609fbbed29065d17e1f6"}, + {file = "pycares-4.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8f64cb58729689d4d0e78f0bfb4c25ce2f851d0274c0273ac751795c04b8798a"}, + {file = "pycares-4.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d33e2a1120887e89075f7f814ec144f66a6ce06a54f5722ccefc62fbeda83cff"}, + {file = "pycares-4.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c680fef1b502ee680f8f0b95a41af4ec2c234e50e16c0af5bbda31999d3584bd"}, + {file = "pycares-4.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fff16b09042ba077f7b8aa5868d1d22456f0002574d0ba43462b10a009331677"}, + {file = "pycares-4.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:229a1675eb33bc9afb1fc463e73ee334950ccc485bc83a43f6ae5839fb4d5fa3"}, + {file = "pycares-4.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3aebc73e5ad70464f998f77f2da2063aa617cbd8d3e8174dd7c5b4518f967153"}, + {file = "pycares-4.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6ef64649eba56448f65e26546d85c860709844d2fc22ef14d324fe0b27f761a9"}, + {file = "pycares-4.4.0-cp310-cp310-win32.whl", hash = "sha256:4afc2644423f4eef97857a9fd61be9758ce5e336b4b0bd3d591238bb4b8b03e0"}, + {file = "pycares-4.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:5ed4e04af4012f875b78219d34434a6d08a67175150ac1b79eb70ab585d4ba8c"}, + {file = "pycares-4.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bce8db2fc6f3174bd39b81405210b9b88d7b607d33e56a970c34a0c190da0490"}, + {file = "pycares-4.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9a0303428d013ccf5c51de59c83f9127aba6200adb7fd4be57eddb432a1edd2a"}, + {file = "pycares-4.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afb91792f1556f97be7f7acb57dc7756d89c5a87bd8b90363a77dbf9ea653817"}, + {file = "pycares-4.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b61579cecf1f4d616e5ea31a6e423a16680ab0d3a24a2ffe7bb1d4ee162477ff"}, + {file = "pycares-4.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7af06968cbf6851566e806bf3e72825b0e6671832a2cbe840be1d2d65350710"}, + {file = "pycares-4.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ceb12974367b0a68a05d52f4162b29f575d241bd53de155efe632bf2c943c7f6"}, + {file = "pycares-4.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:2eeec144bcf6a7b6f2d74d6e70cbba7886a84dd373c886f06cb137a07de4954c"}, + {file = "pycares-4.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e3a6f7cfdfd11eb5493d6d632e582408c8f3b429f295f8799c584c108b28db6f"}, + {file = "pycares-4.4.0-cp311-cp311-win32.whl", hash = "sha256:34736a2ffaa9c08ca9c707011a2d7b69074bbf82d645d8138bba771479b2362f"}, + {file = "pycares-4.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:eb66c30eb11e877976b7ead13632082a8621df648c408b8e15cdb91a452dd502"}, + {file = "pycares-4.4.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:fd644505a8cfd7f6584d33a9066d4e3d47700f050ef1490230c962de5dfb28c6"}, + {file = "pycares-4.4.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:52084961262232ec04bd75f5043aed7e5d8d9695e542ff691dfef0110209f2d4"}, + {file = "pycares-4.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0c5368206057884cde18602580083aeaad9b860e2eac14fd253543158ce1e93"}, + {file = "pycares-4.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:112a4979c695b1c86f6782163d7dec58d57a3b9510536dcf4826550f9053dd9a"}, + {file = "pycares-4.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8d186dafccdaa3409194c0f94db93c1a5d191145a275f19da6591f9499b8e7b8"}, + {file = "pycares-4.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:64965dc19c578a683ea73487a215a8897276224e004d50eeb21f0bc7a0b63c88"}, + {file = "pycares-4.4.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ed2a38e34bec6f2586435f6ff0bc5fe11d14bebd7ed492cf739a424e81681540"}, + {file = "pycares-4.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:94d6962db81541eb0396d2f0dfcbb18cdb8c8b251d165efc2d974ae652c547d4"}, + {file = "pycares-4.4.0-cp312-cp312-win32.whl", hash = "sha256:1168a48a834813aa80f412be2df4abaf630528a58d15c704857448b20b1675c0"}, + {file = "pycares-4.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:db24c4e7fea4a052c6e869cbf387dd85d53b9736cfe1ef5d8d568d1ca925e977"}, + {file = "pycares-4.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:21a5a0468861ec7df7befa69050f952da13db5427ae41ffe4713bc96291d1d95"}, + {file = "pycares-4.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:22c00bf659a9fa44d7b405cf1cd69b68b9d37537899898d8cbe5dffa4016b273"}, + {file = "pycares-4.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23aa3993a352491a47fcf17867f61472f32f874df4adcbb486294bd9fbe8abee"}, + {file = "pycares-4.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:813d661cbe2e37d87da2d16b7110a6860e93ddb11735c6919c8a3545c7b9c8d8"}, + {file = "pycares-4.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:77cf5a2fd5583c670de41a7f4a7b46e5cbabe7180d8029f728571f4d2e864084"}, + {file = "pycares-4.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3eaa6681c0a3e3f3868c77aca14b7760fed35fdfda2fe587e15c701950e7bc69"}, + {file = "pycares-4.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ad58e284a658a8a6a84af2e0b62f2f961f303cedfe551854d7bd40c3cbb61912"}, + {file = "pycares-4.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bfb89ca9e3d0a9b5332deeb666b2ede9d3469107742158f4aeda5ce032d003f4"}, + {file = "pycares-4.4.0-cp38-cp38-win32.whl", hash = "sha256:f36bdc1562142e3695555d2f4ac0cb69af165eddcefa98efc1c79495b533481f"}, + {file = "pycares-4.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:902461a92b6a80fd5041a2ec5235680c7cc35e43615639ec2a40e63fca2dfb51"}, + {file = "pycares-4.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7bddc6adba8f699728f7fc1c9ce8cef359817ad78e2ed52b9502cb5f8dc7f741"}, + {file = "pycares-4.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cb49d5805cd347c404f928c5ae7c35e86ba0c58ffa701dbe905365e77ce7d641"}, + {file = "pycares-4.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56cf3349fa3a2e67ed387a7974c11d233734636fe19facfcda261b411af14d80"}, + {file = "pycares-4.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8bf2eaa83a5987e48fa63302f0fe7ce3275cfda87b34d40fef9ce703fb3ac002"}, + {file = "pycares-4.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82bba2ab77eb5addbf9758d514d9bdef3c1bfe7d1649a47bd9a0d55a23ef478b"}, + {file = "pycares-4.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c6a8bde63106f162fca736e842a916853cad3c8d9d137e11c9ffa37efa818b02"}, + {file = "pycares-4.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f5f646eec041db6ffdbcaf3e0756fb92018f7af3266138c756bb09d2b5baadec"}, + {file = "pycares-4.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9dc04c54c6ea615210c1b9e803d0e2d2255f87a3d5d119b6482c8f0dfa15b26b"}, + {file = "pycares-4.4.0-cp39-cp39-win32.whl", hash = "sha256:97892cced5794d721fb4ff8765764aa4ea48fe8b2c3820677505b96b83d4ef47"}, + {file = "pycares-4.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:917f08f0b5d9324e9a34211e68d27447c552b50ab967044776bbab7e42a553a2"}, + {file = "pycares-4.4.0.tar.gz", hash = "sha256:f47579d508f2f56eddd16ce72045782ad3b1b3b678098699e2b6a1b30733e1c2"}, +] + +[package.dependencies] +cffi = ">=1.5.0" + +[package.extras] +idna = ["idna (>=2.1)"] + +[[package]] +name = "pycparser" +version = "2.22" +description = "C parser in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, +] + +[[package]] +name = "pydantic" +version = "1.10.14" +description = "Data validation and settings management using python type hints" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic-1.10.14-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7f4fcec873f90537c382840f330b90f4715eebc2bc9925f04cb92de593eae054"}, + {file = "pydantic-1.10.14-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e3a76f571970fcd3c43ad982daf936ae39b3e90b8a2e96c04113a369869dc87"}, + {file = "pydantic-1.10.14-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82d886bd3c3fbeaa963692ef6b643159ccb4b4cefaf7ff1617720cbead04fd1d"}, + {file = "pydantic-1.10.14-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:798a3d05ee3b71967844a1164fd5bdb8c22c6d674f26274e78b9f29d81770c4e"}, + {file = "pydantic-1.10.14-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:23d47a4b57a38e8652bcab15a658fdb13c785b9ce217cc3a729504ab4e1d6bc9"}, + {file = "pydantic-1.10.14-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f9f674b5c3bebc2eba401de64f29948ae1e646ba2735f884d1594c5f675d6f2a"}, + {file = "pydantic-1.10.14-cp310-cp310-win_amd64.whl", hash = "sha256:24a7679fab2e0eeedb5a8924fc4a694b3bcaac7d305aeeac72dd7d4e05ecbebf"}, + {file = "pydantic-1.10.14-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9d578ac4bf7fdf10ce14caba6f734c178379bd35c486c6deb6f49006e1ba78a7"}, + {file = "pydantic-1.10.14-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fa7790e94c60f809c95602a26d906eba01a0abee9cc24150e4ce2189352deb1b"}, + {file = "pydantic-1.10.14-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aad4e10efa5474ed1a611b6d7f0d130f4aafadceb73c11d9e72823e8f508e663"}, + {file = "pydantic-1.10.14-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1245f4f61f467cb3dfeced2b119afef3db386aec3d24a22a1de08c65038b255f"}, + {file = "pydantic-1.10.14-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:21efacc678a11114c765eb52ec0db62edffa89e9a562a94cbf8fa10b5db5c046"}, + {file = "pydantic-1.10.14-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:412ab4a3f6dbd2bf18aefa9f79c7cca23744846b31f1d6555c2ee2b05a2e14ca"}, + {file = "pydantic-1.10.14-cp311-cp311-win_amd64.whl", hash = "sha256:e897c9f35281f7889873a3e6d6b69aa1447ceb024e8495a5f0d02ecd17742a7f"}, + {file = "pydantic-1.10.14-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d604be0f0b44d473e54fdcb12302495fe0467c56509a2f80483476f3ba92b33c"}, + {file = "pydantic-1.10.14-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a42c7d17706911199798d4c464b352e640cab4351efe69c2267823d619a937e5"}, + {file = "pydantic-1.10.14-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:596f12a1085e38dbda5cbb874d0973303e34227b400b6414782bf205cc14940c"}, + {file = "pydantic-1.10.14-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bfb113860e9288d0886e3b9e49d9cf4a9d48b441f52ded7d96db7819028514cc"}, + {file = "pydantic-1.10.14-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:bc3ed06ab13660b565eed80887fcfbc0070f0aa0691fbb351657041d3e874efe"}, + {file = "pydantic-1.10.14-cp37-cp37m-win_amd64.whl", hash = "sha256:ad8c2bc677ae5f6dbd3cf92f2c7dc613507eafe8f71719727cbc0a7dec9a8c01"}, + {file = "pydantic-1.10.14-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c37c28449752bb1f47975d22ef2882d70513c546f8f37201e0fec3a97b816eee"}, + {file = "pydantic-1.10.14-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:49a46a0994dd551ec051986806122767cf144b9702e31d47f6d493c336462597"}, + {file = "pydantic-1.10.14-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53e3819bd20a42470d6dd0fe7fc1c121c92247bca104ce608e609b59bc7a77ee"}, + {file = "pydantic-1.10.14-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0fbb503bbbbab0c588ed3cd21975a1d0d4163b87e360fec17a792f7d8c4ff29f"}, + {file = "pydantic-1.10.14-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:336709883c15c050b9c55a63d6c7ff09be883dbc17805d2b063395dd9d9d0022"}, + {file = "pydantic-1.10.14-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4ae57b4d8e3312d486e2498d42aed3ece7b51848336964e43abbf9671584e67f"}, + {file = "pydantic-1.10.14-cp38-cp38-win_amd64.whl", hash = "sha256:dba49d52500c35cfec0b28aa8b3ea5c37c9df183ffc7210b10ff2a415c125c4a"}, + {file = "pydantic-1.10.14-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c66609e138c31cba607d8e2a7b6a5dc38979a06c900815495b2d90ce6ded35b4"}, + {file = "pydantic-1.10.14-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d986e115e0b39604b9eee3507987368ff8148222da213cd38c359f6f57b3b347"}, + {file = "pydantic-1.10.14-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:646b2b12df4295b4c3148850c85bff29ef6d0d9621a8d091e98094871a62e5c7"}, + {file = "pydantic-1.10.14-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282613a5969c47c83a8710cc8bfd1e70c9223feb76566f74683af889faadc0ea"}, + {file = "pydantic-1.10.14-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:466669501d08ad8eb3c4fecd991c5e793c4e0bbd62299d05111d4f827cded64f"}, + {file = "pydantic-1.10.14-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:13e86a19dca96373dcf3190fcb8797d40a6f12f154a244a8d1e8e03b8f280593"}, + {file = "pydantic-1.10.14-cp39-cp39-win_amd64.whl", hash = "sha256:08b6ec0917c30861e3fe71a93be1648a2aa4f62f866142ba21670b24444d7fd8"}, + {file = "pydantic-1.10.14-py3-none-any.whl", hash = "sha256:8ee853cd12ac2ddbf0ecbac1c289f95882b2d4482258048079d13be700aa114c"}, + {file = "pydantic-1.10.14.tar.gz", hash = "sha256:46f17b832fe27de7850896f3afee50ea682220dd218f7e9c88d436788419dca6"}, +] + +[package.dependencies] +typing-extensions = ">=4.2.0" + +[package.extras] +dotenv = ["python-dotenv (>=0.10.4)"] +email = ["email-validator (>=1.0.3)"] + +[[package]] +name = "pyrsistent" +version = "0.20.0" +description = "Persistent/Functional/Immutable data structures" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyrsistent-0.20.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c3aba3e01235221e5b229a6c05f585f344734bd1ad42a8ac51493d74722bbce"}, + {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1beb78af5423b879edaf23c5591ff292cf7c33979734c99aa66d5914ead880f"}, + {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21cc459636983764e692b9eba7144cdd54fdec23ccdb1e8ba392a63666c60c34"}, + {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f5ac696f02b3fc01a710427585c855f65cd9c640e14f52abe52020722bb4906b"}, + {file = "pyrsistent-0.20.0-cp310-cp310-win32.whl", hash = "sha256:0724c506cd8b63c69c7f883cc233aac948c1ea946ea95996ad8b1380c25e1d3f"}, + {file = "pyrsistent-0.20.0-cp310-cp310-win_amd64.whl", hash = "sha256:8441cf9616d642c475684d6cf2520dd24812e996ba9af15e606df5f6fd9d04a7"}, + {file = "pyrsistent-0.20.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0f3b1bcaa1f0629c978b355a7c37acd58907390149b7311b5db1b37648eb6958"}, + {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cdd7ef1ea7a491ae70d826b6cc64868de09a1d5ff9ef8d574250d0940e275b8"}, + {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cae40a9e3ce178415040a0383f00e8d68b569e97f31928a3a8ad37e3fde6df6a"}, + {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6288b3fa6622ad8a91e6eb759cfc48ff3089e7c17fb1d4c59a919769314af224"}, + {file = "pyrsistent-0.20.0-cp311-cp311-win32.whl", hash = "sha256:7d29c23bdf6e5438c755b941cef867ec2a4a172ceb9f50553b6ed70d50dfd656"}, + {file = "pyrsistent-0.20.0-cp311-cp311-win_amd64.whl", hash = "sha256:59a89bccd615551391f3237e00006a26bcf98a4d18623a19909a2c48b8e986ee"}, + {file = "pyrsistent-0.20.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:09848306523a3aba463c4b49493a760e7a6ca52e4826aa100ee99d8d39b7ad1e"}, + {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a14798c3005ec892bbada26485c2eea3b54109cb2533713e355c806891f63c5e"}, + {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b14decb628fac50db5e02ee5a35a9c0772d20277824cfe845c8a8b717c15daa3"}, + {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e2c116cc804d9b09ce9814d17df5edf1df0c624aba3b43bc1ad90411487036d"}, + {file = "pyrsistent-0.20.0-cp312-cp312-win32.whl", hash = "sha256:e78d0c7c1e99a4a45c99143900ea0546025e41bb59ebc10182e947cf1ece9174"}, + {file = "pyrsistent-0.20.0-cp312-cp312-win_amd64.whl", hash = "sha256:4021a7f963d88ccd15b523787d18ed5e5269ce57aa4037146a2377ff607ae87d"}, + {file = "pyrsistent-0.20.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:79ed12ba79935adaac1664fd7e0e585a22caa539dfc9b7c7c6d5ebf91fb89054"}, + {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f920385a11207dc372a028b3f1e1038bb244b3ec38d448e6d8e43c6b3ba20e98"}, + {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f5c2d012671b7391803263419e31b5c7c21e7c95c8760d7fc35602353dee714"}, + {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef3992833fbd686ee783590639f4b8343a57f1f75de8633749d984dc0eb16c86"}, + {file = "pyrsistent-0.20.0-cp38-cp38-win32.whl", hash = "sha256:881bbea27bbd32d37eb24dd320a5e745a2a5b092a17f6debc1349252fac85423"}, + {file = "pyrsistent-0.20.0-cp38-cp38-win_amd64.whl", hash = "sha256:6d270ec9dd33cdb13f4d62c95c1a5a50e6b7cdd86302b494217137f760495b9d"}, + {file = "pyrsistent-0.20.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ca52d1ceae015859d16aded12584c59eb3825f7b50c6cfd621d4231a6cc624ce"}, + {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b318ca24db0f0518630e8b6f3831e9cba78f099ed5c1d65ffe3e023003043ba0"}, + {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fed2c3216a605dc9a6ea50c7e84c82906e3684c4e80d2908208f662a6cbf9022"}, + {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e14c95c16211d166f59c6611533d0dacce2e25de0f76e4c140fde250997b3ca"}, + {file = "pyrsistent-0.20.0-cp39-cp39-win32.whl", hash = "sha256:f058a615031eea4ef94ead6456f5ec2026c19fb5bd6bfe86e9665c4158cf802f"}, + {file = "pyrsistent-0.20.0-cp39-cp39-win_amd64.whl", hash = "sha256:58b8f6366e152092194ae68fefe18b9f0b4f89227dfd86a07770c3d86097aebf"}, + {file = "pyrsistent-0.20.0-py3-none-any.whl", hash = "sha256:c55acc4733aad6560a7f5f818466631f07efc001fd023f34a6c203f8b6df0f0b"}, + {file = "pyrsistent-0.20.0.tar.gz", hash = "sha256:4c48f78f62ab596c679086084d0dd13254ae4f3d6c72a83ffdf5ebdef8f265a4"}, +] + +[[package]] +name = "pytest" +version = "7.4.4" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, + {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" + +[package.extras] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-insta" +version = "0.3.0" +description = "A practical snapshot testing plugin for pytest" +optional = false +python-versions = ">=3.10,<4.0" +files = [ + {file = "pytest_insta-0.3.0-py3-none-any.whl", hash = "sha256:93a105e3850f2887b120a581923b10bb313d722e00d369377a1d91aa535df704"}, + {file = "pytest_insta-0.3.0.tar.gz", hash = "sha256:9e6e1c70a021f68ccc4643360b2c2f8326cf3befba85f942c1da17b9caf713f7"}, +] + +[package.dependencies] +pytest = ">=7.2.0,<9.0.0" +wrapt = ">=1.14.1,<2.0.0" + +[[package]] +name = "pytest-mock" +version = "3.14.0" +description = "Thin-wrapper around the mock package for easier use with pytest" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0"}, + {file = "pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f"}, +] + +[package.dependencies] +pytest = ">=6.2.5" + +[package.extras] +dev = ["pre-commit", "pytest-asyncio", "tox"] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + +[[package]] +name = "requests" +version = "2.31.0" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.7" +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "requests-cache" +version = "1.2.0" +description = "A persistent cache for python requests" +optional = false +python-versions = ">=3.8" +files = [ + {file = "requests_cache-1.2.0-py3-none-any.whl", hash = "sha256:490324301bf0cb924ff4e6324bd2613453e7e1f847353928b08adb0fdfb7f722"}, + {file = "requests_cache-1.2.0.tar.gz", hash = "sha256:db1c709ca343cc1cd5b6c8b1a5387298eceed02306a6040760db538c885e3838"}, +] + +[package.dependencies] +attrs = ">=21.2" +cattrs = ">=22.2" +platformdirs = ">=2.5" +requests = ">=2.22" +url-normalize = ">=1.4" +urllib3 = ">=1.25.5" + +[package.extras] +all = ["boto3 (>=1.15)", "botocore (>=1.18)", "itsdangerous (>=2.0)", "pymongo (>=3)", "pyyaml (>=6.0.1)", "redis (>=3)", "ujson (>=5.4)"] +bson = ["bson (>=0.5)"] +docs = ["furo (>=2023.3,<2024.0)", "linkify-it-py (>=2.0,<3.0)", "myst-parser (>=1.0,<2.0)", "sphinx (>=5.0.2,<6.0.0)", "sphinx-autodoc-typehints (>=1.19)", "sphinx-automodapi (>=0.14)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.2)", "sphinx-notfound-page (>=0.8)", "sphinxcontrib-apidoc (>=0.3)", "sphinxext-opengraph (>=0.9)"] +dynamodb = ["boto3 (>=1.15)", "botocore (>=1.18)"] +json = ["ujson (>=5.4)"] +mongodb = ["pymongo (>=3)"] +redis = ["redis (>=3)"] +security = ["itsdangerous (>=2.0)"] +yaml = ["pyyaml (>=6.0.1)"] + +[[package]] +name = "requests-mock" +version = "1.12.1" +description = "Mock out responses from the requests package" +optional = false +python-versions = ">=3.5" +files = [ + {file = "requests-mock-1.12.1.tar.gz", hash = "sha256:e9e12e333b525156e82a3c852f22016b9158220d2f47454de9cae8a77d371401"}, + {file = "requests_mock-1.12.1-py2.py3-none-any.whl", hash = "sha256:b1e37054004cdd5e56c84454cc7df12b25f90f382159087f4b6915aaeef39563"}, +] + +[package.dependencies] +requests = ">=2.22,<3" + +[package.extras] +fixture = ["fixtures"] + +[[package]] +name = "responses" +version = "0.25.0" +description = "A utility library for mocking out the `requests` Python library." +optional = false +python-versions = ">=3.8" +files = [ + {file = "responses-0.25.0-py3-none-any.whl", hash = "sha256:2f0b9c2b6437db4b528619a77e5d565e4ec2a9532162ac1a131a83529db7be1a"}, + {file = "responses-0.25.0.tar.gz", hash = "sha256:01ae6a02b4f34e39bffceb0fc6786b67a25eae919c6368d05eabc8d9576c2a66"}, +] + +[package.dependencies] +pyyaml = "*" +requests = ">=2.30.0,<3.0" +urllib3 = ">=1.25.10,<3.0" + +[package.extras] +tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "tomli", "tomli-w", "types-PyYAML", "types-requests"] + +[[package]] +name = "setuptools" +version = "69.5.1" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-69.5.1-py3-none-any.whl", hash = "sha256:c636ac361bc47580504644275c9ad802c50415c7522212252c033bd15f301f32"}, + {file = "setuptools-69.5.1.tar.gz", hash = "sha256:6c1fccdac05a97e598fb0ae3bbed5904ccb317337a51139dcd51453611bbb987"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6,!=8.1.1)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "typing-extensions" +version = "4.11.0" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"}, + {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"}, +] + +[[package]] +name = "tzdata" +version = "2024.1" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +files = [ + {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, + {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, +] + +[[package]] +name = "url-normalize" +version = "1.4.3" +description = "URL normalization for Python" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +files = [ + {file = "url-normalize-1.4.3.tar.gz", hash = "sha256:d23d3a070ac52a67b83a1c59a0e68f8608d1cd538783b401bc9de2c0fac999b2"}, + {file = "url_normalize-1.4.3-py2.py3-none-any.whl", hash = "sha256:ec3c301f04e5bb676d333a7fa162fa977ad2ca04b7e652bfc9fac4e405728eed"}, +] + +[package.dependencies] +six = "*" + +[[package]] +name = "urllib3" +version = "2.2.1" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, + {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "wcmatch" +version = "8.4" +description = "Wildcard/glob file name matcher." +optional = false +python-versions = ">=3.7" +files = [ + {file = "wcmatch-8.4-py3-none-any.whl", hash = "sha256:dc7351e5a7f8bbf4c6828d51ad20c1770113f5f3fd3dfe2a03cfde2a63f03f98"}, + {file = "wcmatch-8.4.tar.gz", hash = "sha256:ba4fc5558f8946bf1ffc7034b05b814d825d694112499c86035e0e4d398b6a67"}, +] + +[package.dependencies] +bracex = ">=2.1.1" + +[[package]] +name = "wrapt" +version = "1.16.0" +description = "Module for decorators, wrappers and monkey patching." +optional = false +python-versions = ">=3.6" +files = [ + {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"}, + {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"}, + {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"}, + {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"}, + {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"}, + {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"}, + {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"}, + {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"}, + {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"}, + {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"}, + {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"}, + {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"}, + {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"}, + {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"}, + {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"}, + {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"}, + {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"}, + {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, +] + +[[package]] +name = "xxhash" +version = "3.4.1" +description = "Python binding for xxHash" +optional = false +python-versions = ">=3.7" +files = [ + {file = "xxhash-3.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:91dbfa55346ad3e18e738742236554531a621042e419b70ad8f3c1d9c7a16e7f"}, + {file = "xxhash-3.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:665a65c2a48a72068fcc4d21721510df5f51f1142541c890491afc80451636d2"}, + {file = "xxhash-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb11628470a6004dc71a09fe90c2f459ff03d611376c1debeec2d648f44cb693"}, + {file = "xxhash-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5bef2a7dc7b4f4beb45a1edbba9b9194c60a43a89598a87f1a0226d183764189"}, + {file = "xxhash-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c0f7b2d547d72c7eda7aa817acf8791f0146b12b9eba1d4432c531fb0352228"}, + {file = "xxhash-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00f2fdef6b41c9db3d2fc0e7f94cb3db86693e5c45d6de09625caad9a469635b"}, + {file = "xxhash-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:23cfd9ca09acaf07a43e5a695143d9a21bf00f5b49b15c07d5388cadf1f9ce11"}, + {file = "xxhash-3.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6a9ff50a3cf88355ca4731682c168049af1ca222d1d2925ef7119c1a78e95b3b"}, + {file = "xxhash-3.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f1d7c69a1e9ca5faa75546fdd267f214f63f52f12692f9b3a2f6467c9e67d5e7"}, + {file = "xxhash-3.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:672b273040d5d5a6864a36287f3514efcd1d4b1b6a7480f294c4b1d1ee1b8de0"}, + {file = "xxhash-3.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4178f78d70e88f1c4a89ff1ffe9f43147185930bb962ee3979dba15f2b1cc799"}, + {file = "xxhash-3.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9804b9eb254d4b8cc83ab5a2002128f7d631dd427aa873c8727dba7f1f0d1c2b"}, + {file = "xxhash-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c09c49473212d9c87261d22c74370457cfff5db2ddfc7fd1e35c80c31a8c14ce"}, + {file = "xxhash-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:ebbb1616435b4a194ce3466d7247df23499475c7ed4eb2681a1fa42ff766aff6"}, + {file = "xxhash-3.4.1-cp310-cp310-win_arm64.whl", hash = "sha256:25dc66be3db54f8a2d136f695b00cfe88018e59ccff0f3b8f545869f376a8a46"}, + {file = "xxhash-3.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:58c49083801885273e262c0f5bbeac23e520564b8357fbb18fb94ff09d3d3ea5"}, + {file = "xxhash-3.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b526015a973bfbe81e804a586b703f163861da36d186627e27524f5427b0d520"}, + {file = "xxhash-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36ad4457644c91a966f6fe137d7467636bdc51a6ce10a1d04f365c70d6a16d7e"}, + {file = "xxhash-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:248d3e83d119770f96003271fe41e049dd4ae52da2feb8f832b7a20e791d2920"}, + {file = "xxhash-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2070b6d5bbef5ee031666cf21d4953c16e92c2f8a24a94b5c240f8995ba3b1d0"}, + {file = "xxhash-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2746035f518f0410915e247877f7df43ef3372bf36cfa52cc4bc33e85242641"}, + {file = "xxhash-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a8ba6181514681c2591840d5632fcf7356ab287d4aff1c8dea20f3c78097088"}, + {file = "xxhash-3.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0aac5010869240e95f740de43cd6a05eae180c59edd182ad93bf12ee289484fa"}, + {file = "xxhash-3.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4cb11d8debab1626181633d184b2372aaa09825bde709bf927704ed72765bed1"}, + {file = "xxhash-3.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b29728cff2c12f3d9f1d940528ee83918d803c0567866e062683f300d1d2eff3"}, + {file = "xxhash-3.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:a15cbf3a9c40672523bdb6ea97ff74b443406ba0ab9bca10ceccd9546414bd84"}, + {file = "xxhash-3.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6e66df260fed01ed8ea790c2913271641c58481e807790d9fca8bfd5a3c13844"}, + {file = "xxhash-3.4.1-cp311-cp311-win32.whl", hash = "sha256:e867f68a8f381ea12858e6d67378c05359d3a53a888913b5f7d35fbf68939d5f"}, + {file = "xxhash-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:200a5a3ad9c7c0c02ed1484a1d838b63edcf92ff538770ea07456a3732c577f4"}, + {file = "xxhash-3.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:1d03f1c0d16d24ea032e99f61c552cb2b77d502e545187338bea461fde253583"}, + {file = "xxhash-3.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c4bbba9b182697a52bc0c9f8ec0ba1acb914b4937cd4a877ad78a3b3eeabefb3"}, + {file = "xxhash-3.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9fd28a9da300e64e434cfc96567a8387d9a96e824a9be1452a1e7248b7763b78"}, + {file = "xxhash-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6066d88c9329ab230e18998daec53d819daeee99d003955c8db6fc4971b45ca3"}, + {file = "xxhash-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93805bc3233ad89abf51772f2ed3355097a5dc74e6080de19706fc447da99cd3"}, + {file = "xxhash-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:64da57d5ed586ebb2ecdde1e997fa37c27fe32fe61a656b77fabbc58e6fbff6e"}, + {file = "xxhash-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a97322e9a7440bf3c9805cbaac090358b43f650516486746f7fa482672593df"}, + {file = "xxhash-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bbe750d512982ee7d831838a5dee9e9848f3fb440e4734cca3f298228cc957a6"}, + {file = "xxhash-3.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:fd79d4087727daf4d5b8afe594b37d611ab95dc8e29fe1a7517320794837eb7d"}, + {file = "xxhash-3.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:743612da4071ff9aa4d055f3f111ae5247342931dedb955268954ef7201a71ff"}, + {file = "xxhash-3.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:b41edaf05734092f24f48c0958b3c6cbaaa5b7e024880692078c6b1f8247e2fc"}, + {file = "xxhash-3.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:a90356ead70d715fe64c30cd0969072de1860e56b78adf7c69d954b43e29d9fa"}, + {file = "xxhash-3.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ac56eebb364e44c85e1d9e9cc5f6031d78a34f0092fea7fc80478139369a8b4a"}, + {file = "xxhash-3.4.1-cp312-cp312-win32.whl", hash = "sha256:911035345932a153c427107397c1518f8ce456f93c618dd1c5b54ebb22e73747"}, + {file = "xxhash-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:f31ce76489f8601cc7b8713201ce94b4bd7b7ce90ba3353dccce7e9e1fee71fa"}, + {file = "xxhash-3.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:b5beb1c6a72fdc7584102f42c4d9df232ee018ddf806e8c90906547dfb43b2da"}, + {file = "xxhash-3.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6d42b24d1496deb05dee5a24ed510b16de1d6c866c626c2beb11aebf3be278b9"}, + {file = "xxhash-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b685fab18876b14a8f94813fa2ca80cfb5ab6a85d31d5539b7cd749ce9e3624"}, + {file = "xxhash-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:419ffe34c17ae2df019a4685e8d3934d46b2e0bbe46221ab40b7e04ed9f11137"}, + {file = "xxhash-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0e041ce5714f95251a88670c114b748bca3bf80cc72400e9f23e6d0d59cf2681"}, + {file = "xxhash-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc860d887c5cb2f524899fb8338e1bb3d5789f75fac179101920d9afddef284b"}, + {file = "xxhash-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:312eba88ffe0a05e332e3a6f9788b73883752be63f8588a6dc1261a3eaaaf2b2"}, + {file = "xxhash-3.4.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:e01226b6b6a1ffe4e6bd6d08cfcb3ca708b16f02eb06dd44f3c6e53285f03e4f"}, + {file = "xxhash-3.4.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9f3025a0d5d8cf406a9313cd0d5789c77433ba2004b1c75439b67678e5136537"}, + {file = "xxhash-3.4.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:6d3472fd4afef2a567d5f14411d94060099901cd8ce9788b22b8c6f13c606a93"}, + {file = "xxhash-3.4.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:43984c0a92f06cac434ad181f329a1445017c33807b7ae4f033878d860a4b0f2"}, + {file = "xxhash-3.4.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a55e0506fdb09640a82ec4f44171273eeabf6f371a4ec605633adb2837b5d9d5"}, + {file = "xxhash-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:faec30437919555b039a8bdbaba49c013043e8f76c999670aef146d33e05b3a0"}, + {file = "xxhash-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:c9e1b646af61f1fc7083bb7b40536be944f1ac67ef5e360bca2d73430186971a"}, + {file = "xxhash-3.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:961d948b7b1c1b6c08484bbce3d489cdf153e4122c3dfb07c2039621243d8795"}, + {file = "xxhash-3.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:719a378930504ab159f7b8e20fa2aa1896cde050011af838af7e7e3518dd82de"}, + {file = "xxhash-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74fb5cb9406ccd7c4dd917f16630d2e5e8cbbb02fc2fca4e559b2a47a64f4940"}, + {file = "xxhash-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5dab508ac39e0ab988039bc7f962c6ad021acd81fd29145962b068df4148c476"}, + {file = "xxhash-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c59f3e46e7daf4c589e8e853d700ef6607afa037bfad32c390175da28127e8c"}, + {file = "xxhash-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cc07256eff0795e0f642df74ad096f8c5d23fe66bc138b83970b50fc7f7f6c5"}, + {file = "xxhash-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9f749999ed80f3955a4af0eb18bb43993f04939350b07b8dd2f44edc98ffee9"}, + {file = "xxhash-3.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7688d7c02149a90a3d46d55b341ab7ad1b4a3f767be2357e211b4e893efbaaf6"}, + {file = "xxhash-3.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a8b4977963926f60b0d4f830941c864bed16aa151206c01ad5c531636da5708e"}, + {file = "xxhash-3.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:8106d88da330f6535a58a8195aa463ef5281a9aa23b04af1848ff715c4398fb4"}, + {file = "xxhash-3.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4c76a77dbd169450b61c06fd2d5d436189fc8ab7c1571d39265d4822da16df22"}, + {file = "xxhash-3.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:11f11357c86d83e53719c592021fd524efa9cf024dc7cb1dfb57bbbd0d8713f2"}, + {file = "xxhash-3.4.1-cp38-cp38-win32.whl", hash = "sha256:0c786a6cd74e8765c6809892a0d45886e7c3dc54de4985b4a5eb8b630f3b8e3b"}, + {file = "xxhash-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:aabf37fb8fa27430d50507deeab2ee7b1bcce89910dd10657c38e71fee835594"}, + {file = "xxhash-3.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6127813abc1477f3a83529b6bbcfeddc23162cece76fa69aee8f6a8a97720562"}, + {file = "xxhash-3.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef2e194262f5db16075caea7b3f7f49392242c688412f386d3c7b07c7733a70a"}, + {file = "xxhash-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71be94265b6c6590f0018bbf73759d21a41c6bda20409782d8117e76cd0dfa8b"}, + {file = "xxhash-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10e0a619cdd1c0980e25eb04e30fe96cf8f4324758fa497080af9c21a6de573f"}, + {file = "xxhash-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa122124d2e3bd36581dd78c0efa5f429f5220313479fb1072858188bc2d5ff1"}, + {file = "xxhash-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17032f5a4fea0a074717fe33477cb5ee723a5f428de7563e75af64bfc1b1e10"}, + {file = "xxhash-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca7783b20e3e4f3f52f093538895863f21d18598f9a48211ad757680c3bd006f"}, + {file = "xxhash-3.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d77d09a1113899fad5f354a1eb4f0a9afcf58cefff51082c8ad643ff890e30cf"}, + {file = "xxhash-3.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:21287bcdd299fdc3328cc0fbbdeaa46838a1c05391264e51ddb38a3f5b09611f"}, + {file = "xxhash-3.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:dfd7a6cc483e20b4ad90224aeb589e64ec0f31e5610ab9957ff4314270b2bf31"}, + {file = "xxhash-3.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:543c7fcbc02bbb4840ea9915134e14dc3dc15cbd5a30873a7a5bf66039db97ec"}, + {file = "xxhash-3.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fe0a98d990e433013f41827b62be9ab43e3cf18e08b1483fcc343bda0d691182"}, + {file = "xxhash-3.4.1-cp39-cp39-win32.whl", hash = "sha256:b9097af00ebf429cc7c0e7d2fdf28384e4e2e91008130ccda8d5ae653db71e54"}, + {file = "xxhash-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:d699b921af0dcde50ab18be76c0d832f803034d80470703700cb7df0fbec2832"}, + {file = "xxhash-3.4.1-cp39-cp39-win_arm64.whl", hash = "sha256:2be491723405e15cc099ade1280133ccfbf6322d2ef568494fb7d07d280e7eee"}, + {file = "xxhash-3.4.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:431625fad7ab5649368c4849d2b49a83dc711b1f20e1f7f04955aab86cd307bc"}, + {file = "xxhash-3.4.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc6dbd5fc3c9886a9e041848508b7fb65fd82f94cc793253990f81617b61fe49"}, + {file = "xxhash-3.4.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3ff8dbd0ec97aec842476cb8ccc3e17dd288cd6ce3c8ef38bff83d6eb927817"}, + {file = "xxhash-3.4.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef73a53fe90558a4096e3256752268a8bdc0322f4692ed928b6cd7ce06ad4fe3"}, + {file = "xxhash-3.4.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:450401f42bbd274b519d3d8dcf3c57166913381a3d2664d6609004685039f9d3"}, + {file = "xxhash-3.4.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a162840cf4de8a7cd8720ff3b4417fbc10001eefdd2d21541a8226bb5556e3bb"}, + {file = "xxhash-3.4.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b736a2a2728ba45017cb67785e03125a79d246462dfa892d023b827007412c52"}, + {file = "xxhash-3.4.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d0ae4c2e7698adef58710d6e7a32ff518b66b98854b1c68e70eee504ad061d8"}, + {file = "xxhash-3.4.1-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6322c4291c3ff174dcd104fae41500e75dad12be6f3085d119c2c8a80956c51"}, + {file = "xxhash-3.4.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:dd59ed668801c3fae282f8f4edadf6dc7784db6d18139b584b6d9677ddde1b6b"}, + {file = "xxhash-3.4.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:92693c487e39523a80474b0394645b393f0ae781d8db3474ccdcead0559ccf45"}, + {file = "xxhash-3.4.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4603a0f642a1e8d7f3ba5c4c25509aca6a9c1cc16f85091004a7028607ead663"}, + {file = "xxhash-3.4.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fa45e8cbfbadb40a920fe9ca40c34b393e0b067082d94006f7f64e70c7490a6"}, + {file = "xxhash-3.4.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:595b252943b3552de491ff51e5bb79660f84f033977f88f6ca1605846637b7c6"}, + {file = "xxhash-3.4.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:562d8b8f783c6af969806aaacf95b6c7b776929ae26c0cd941d54644ea7ef51e"}, + {file = "xxhash-3.4.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:41ddeae47cf2828335d8d991f2d2b03b0bdc89289dc64349d712ff8ce59d0647"}, + {file = "xxhash-3.4.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c44d584afdf3c4dbb3277e32321d1a7b01d6071c1992524b6543025fb8f4206f"}, + {file = "xxhash-3.4.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd7bddb3a5b86213cc3f2c61500c16945a1b80ecd572f3078ddbbe68f9dabdfb"}, + {file = "xxhash-3.4.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9ecb6c987b62437c2f99c01e97caf8d25660bf541fe79a481d05732e5236719c"}, + {file = "xxhash-3.4.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:696b4e18b7023527d5c50ed0626ac0520edac45a50ec7cf3fc265cd08b1f4c03"}, + {file = "xxhash-3.4.1.tar.gz", hash = "sha256:0379d6cf1ff987cd421609a264ce025e74f346e3e145dd106c0cc2e3ec3f99a9"}, +] + +[[package]] +name = "yarl" +version = "1.9.4" +description = "Yet another URL library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e"}, + {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2"}, + {file = "yarl-1.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541"}, + {file = "yarl-1.9.4-cp310-cp310-win32.whl", hash = "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d"}, + {file = "yarl-1.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98"}, + {file = "yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31"}, + {file = "yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"}, + {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"}, + {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"}, + {file = "yarl-1.9.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434"}, + {file = "yarl-1.9.4-cp37-cp37m-win32.whl", hash = "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749"}, + {file = "yarl-1.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3"}, + {file = "yarl-1.9.4-cp38-cp38-win32.whl", hash = "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece"}, + {file = "yarl-1.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0"}, + {file = "yarl-1.9.4-cp39-cp39-win32.whl", hash = "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575"}, + {file = "yarl-1.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15"}, + {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"}, + {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"}, +] + +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" + +[metadata] +lock-version = "2.0" +python-versions = "^3.12" +content-hash = "430808daa3ca3ed673e8b6735cd955fc7413cd9c2d1644656416dc5c24789f00" diff --git a/source-mailchimp/pyproject.toml b/source-mailchimp/pyproject.toml new file mode 100644 index 0000000000..2d7f7f6f28 --- /dev/null +++ b/source-mailchimp/pyproject.toml @@ -0,0 +1,26 @@ +[tool.poetry] +name = "source-mailchimp" +version = "0.1.0" +description = "" +authors = ["Luishfs "] + +[tool.poetry.dependencies] +python = "^3.12" +airbyte-cdk = "^0.52" +estuary-cdk = {path="../estuary-cdk", develop = true} +pydantic = "==1.10.14" + +[tool.poetry.group.dev.dependencies] +debugpy = "^1.8.0" +mypy = "^1.8.0" +pytest = "^7.4.3" +pytest-insta = "^0.3.0" +mock = "^5.1.0" +pytest-mock = "^3.6.1" +requests-mock = "^1.9.3" +freezegun = "^1.4.0" +responses = "==0.25" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/source-mailchimp/source_mailchimp/__init__.py b/source-mailchimp/source_mailchimp/__init__.py new file mode 100644 index 0000000000..5087fc54c7 --- /dev/null +++ b/source-mailchimp/source_mailchimp/__init__.py @@ -0,0 +1,3 @@ +from .source import SourceMailchimp + +__all__ = ["SourceMailchimp"] diff --git a/source-mailchimp/source_mailchimp/__main__.py b/source-mailchimp/source_mailchimp/__main__.py new file mode 100644 index 0000000000..973316ee82 --- /dev/null +++ b/source-mailchimp/source_mailchimp/__main__.py @@ -0,0 +1,34 @@ +import estuary_cdk.pydantic_polyfill # Must be first. + +import asyncio +import urllib +from estuary_cdk import shim_airbyte_cdk, flow +from source_mailchimp import SourceMailchimp + +asyncio.run( + shim_airbyte_cdk.CaptureShim( + delegate=SourceMailchimp(), + oauth2=flow.OAuth2Spec( + provider="mailchimp", + authUrlTemplate=( + "https://login.mailchimp.com/oauth2/authorize?response_type=code" + r"&client_id={{#urlencode}}{{{ client_id }}}{{/urlencode}}" + r"&redirect_uri={{#urlencode}}{{{ redirect_uri }}}{{/urlencode}}" + r"&state={{#urlencode}}{{{ state }}}{{/urlencode}}" + ), + accessTokenUrlTemplate="https://login.mailchimp.com/oauth2/token", + accessTokenHeaders={"content-type": "application/x-www-form-urlencoded"}, + accessTokenBody=( + "grant_type=authorization_code" + r"&client_id={{#urlencode}}{{{ client_id }}}{{/urlencode}}" + r"&client_secret={{#urlencode}}{{{ client_secret }}}{{/urlencode}}" + r"&redirect_uri={{#urlencode}}{{{ redirect_uri }}}{{/urlencode}}" + r"&code={{#urlencode}}{{{ code }}}{{/urlencode}}" + ), + accessTokenResponseMap={ + "access_token": "/access_token" + }, + ), + schema_inference=False, + ).serve() +) \ No newline at end of file diff --git a/source-mailchimp/source_mailchimp/run.py b/source-mailchimp/source_mailchimp/run.py new file mode 100644 index 0000000000..15226fdfee --- /dev/null +++ b/source-mailchimp/source_mailchimp/run.py @@ -0,0 +1,14 @@ +# +# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# + + +import sys + +from airbyte_cdk.entrypoint import launch +from source_mailchimp import SourceMailchimp + + +def run(): + source = SourceMailchimp() + launch(source, sys.argv[1:]) diff --git a/source-mailchimp/source_mailchimp/schemas/automations.json b/source-mailchimp/source_mailchimp/schemas/automations.json new file mode 100644 index 0000000000..9a172a10df --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/automations.json @@ -0,0 +1,191 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "title": "Automations", + "additionalProperties": true, + "required": ["id"], + "properties": { + "id": { + "type": "string" + }, + "create_time": { + "type": ["null", "string"], + "format": "date-time" + }, + "start_time": { + "type": ["null", "string"], + "format": "date-time" + }, + "status": { + "type": ["null", "string"] + }, + "emails_sent": { + "type": ["null", "number"] + }, + "recipients": { + "type": ["null", "object"], + "properties": { + "list_id": { + "type": ["null", "string"] + }, + "list_is_active": { + "type": ["null", "boolean"] + }, + "list_name": { + "type": ["null", "string"] + }, + "segment_opts": { + "type": ["null", "object"], + "properties": { + "saved_segment_id": { + "type": ["null", "number"] + }, + "match": { + "type": ["null", "string"] + }, + "conditions": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "additionalProperties": true + } + } + } + }, + "store_id": { + "type": ["null", "string"] + } + } + }, + "settings": { + "type": ["null", "object"], + "properties": { + "title": { + "type": ["null", "string"] + }, + "from_name": { + "type": ["null", "string"] + }, + "reply_to": { + "type": ["null", "string"] + }, + "use_conversation": { + "type": ["null", "boolean"] + }, + "to_name": { + "type": ["null", "string"] + }, + "authenticate": { + "type": ["null", "boolean"] + }, + "auto_footer": { + "type": ["null", "boolean"] + }, + "inline_css": { + "type": ["null", "boolean"] + } + } + }, + "tracking": { + "type": ["null", "object"], + "properties": { + "opens": { + "type": ["null", "boolean"] + }, + "html_clicks": { + "type": ["null", "boolean"] + }, + "text_clicks": { + "type": ["null", "boolean"] + }, + "goal_tracking": { + "type": ["null", "boolean"] + }, + "ecomm360": { + "type": ["null", "boolean"] + }, + "google_analytics": { + "type": ["null", "string"] + }, + "clicktale": { + "type": ["null", "string"] + }, + "salesforce": { + "type": ["null", "object"], + "properties": { + "campaign": { + "type": ["null", "boolean"] + }, + "notes": { + "type": ["null", "boolean"] + } + } + }, + "capsule": { + "type": ["null", "object"], + "properties": { + "notes": { + "type": ["null", "boolean"] + } + } + } + } + }, + "trigger_settings": { + "type": ["null", "object"], + "properties": { + "workflow_type": { + "type": ["null", "string"] + }, + "workflow_title": { + "type": ["null", "string"] + }, + "runtime": { + "type": ["null", "object"], + "properties": { + "days": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + }, + "hours": { + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + } + } + } + } + }, + "workflow_emails_count": { + "type": ["null", "number"] + } + } + }, + "report_summary": { + "type": ["null", "object"], + "properties": { + "opens": { + "type": ["null", "number"] + }, + "unique_opens": { + "type": ["null", "number"] + }, + "open_rate": { + "type": ["null", "number"] + }, + "clicks": { + "type": ["null", "number"] + }, + "subscriber_clicks": { + "type": ["null", "number"] + }, + "click_rate": { + "type": ["null", "number"] + } + } + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/campaigns.json b/source-mailchimp/source_mailchimp/schemas/campaigns.json new file mode 100644 index 0000000000..113a57e5d5 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/campaigns.json @@ -0,0 +1,734 @@ +{ + "type": "object", + "title": "Campaign", + "description": "A summary of an individual campaign's settings and content.", + "required": ["id"], + "properties": { + "id": { + "type": "string", + "title": "Campaign ID", + "description": "A string that uniquely identifies this campaign.", + "readOnly": true + }, + "web_id": { + "type": "integer", + "title": "Campaign Web ID", + "description": "The ID used in the Mailchimp web application. View this campaign in your Mailchimp account at `https://{dc}.admin.mailchimp.com/campaigns/show/?id={web_id}`.", + "readOnly": true + }, + "parent_campaign_id": { + "type": ["null", "string"], + "title": "Parent Campaign ID", + "description": "If this campaign is the child of another campaign, this identifies the parent campaign. For Example, for RSS or Automation children.", + "readOnly": true + }, + "type": { + "$ref": "campaignType.json" + }, + "create_time": { + "type": "string", + "title": "Create Time", + "description": "The date and time the campaign was created in ISO 8601 format.", + "readOnly": true, + "format": "date-time" + }, + "archive_url": { + "type": ["null", "string"], + "title": "Archive URL", + "description": "The link to the campaign's archive version in ISO 8601 format.", + "readOnly": true + }, + "long_archive_url": { + "type": ["null", "string"], + "title": "Long Archive URL", + "description": "The original link to the campaign's archive version.", + "readOnly": true + }, + "status": { + "$ref": "campaignStatus.json" + }, + "emails_sent": { + "type": "integer", + "title": "Emails Sent", + "description": "The total number of emails sent for this campaign.", + "readOnly": true + }, + "send_time": { + "type": ["null", "string"], + "title": "Send Time", + "description": "The date and time a campaign was sent.", + "readOnly": true, + "format": "date-time" + }, + "content_type": { + "type": ["null", "string"], + "title": "Content Type", + "description": "How the campaign's content is put together.", + "enum": ["template", "html", "url", "multichannel"] + }, + "needs_block_refresh": { + "type": "boolean", + "title": "Needs Block Refresh", + "description": "Determines if the campaign needs its blocks refreshed by opening the web-based campaign editor. Deprecated and will always return false.", + "readOnly": true + }, + "resendable": { + "type": "boolean", + "title": "Resendable", + "description": "Determines if the campaign qualifies to be resent to non-openers.", + "readOnly": true + }, + "recipients": { + "type": "object", + "title": "List", + "description": "List settings for the campaign.", + "properties": { + "list_id": { + "type": ["null", "string"], + "title": "List ID", + "description": "The unique list id." + }, + "list_is_active": { + "type": "boolean", + "title": "List Status", + "description": "The status of the list used, namely if it's deleted or disabled.", + "readOnly": true + }, + "list_name": { + "type": ["null", "string"], + "title": "List Name", + "description": "The name of the list.", + "readOnly": true + }, + "segment_text": { + "type": ["null", "string"], + "title": "Segment Text", + "description": "A description of the [segment](https://mailchimp.com/help/create-and-send-to-a-segment/) used for the campaign. Formatted as a string marked up with HTML.", + "readOnly": true + }, + "recipient_count": { + "type": "integer", + "title": "Recipient Count", + "description": "Count of the recipients on the associated list. Formatted as an integer.", + "readOnly": true + }, + "segment_opts": { + "$ref": "segmentationOptions.json" + } + } + }, + "settings": { + "type": "object", + "title": "Campaign Settings", + "description": "The settings for your campaign, including subject, from name, reply-to address, and more.", + "properties": { + "subject_line": { + "type": ["null", "string"], + "title": "Campaign Subject Line", + "description": "The subject line for the campaign." + }, + "preview_text": { + "type": ["null", "string"], + "title": "Campaign Preview Text", + "description": "The preview text for the campaign." + }, + "title": { + "type": ["null", "string"], + "title": "Campaign Title", + "description": "The title of the campaign." + }, + "from_name": { + "type": ["null", "string"], + "title": "From Name", + "description": "The 'from' name on the campaign (not an email address)." + }, + "reply_to": { + "type": ["null", "string"], + "title": "Reply To Address", + "description": "The reply-to email address for the campaign." + }, + "use_conversation": { + "type": "boolean", + "title": "Conversation", + "description": "Use Mailchimp Conversation feature to manage out-of-office replies." + }, + "to_name": { + "type": ["null", "string"], + "title": "To Name", + "description": "The campaign's custom 'To' name. Typically the first name [merge field](https://mailchimp.com/help/getting-started-with-merge-tags/)." + }, + "folder_id": { + "type": ["null", "string"], + "title": "Folder ID", + "description": "If the campaign is listed in a folder, the id for that folder." + }, + "authenticate": { + "type": "boolean", + "title": "Authentication", + "description": "Whether Mailchimp [authenticated](https://mailchimp.com/help/about-email-authentication/) the campaign. Defaults to `true`." + }, + "auto_footer": { + "type": "boolean", + "title": "Auto-Footer", + "description": "Automatically append Mailchimp's [default footer](https://mailchimp.com/help/about-campaign-footers/) to the campaign." + }, + "inline_css": { + "type": "boolean", + "title": "Inline CSS", + "description": "Automatically inline the CSS included with the campaign content." + }, + "auto_tweet": { + "type": "boolean", + "title": "Auto-Tweet", + "description": "Automatically tweet a link to the [campaign archive](https://mailchimp.com/help/about-email-campaign-archives-and-pages/) page when the campaign is sent." + }, + "auto_fb_post": { + "type": "array", + "title": "Auto Post to Facebook", + "description": "An array of [Facebook](https://mailchimp.com/help/connect-or-disconnect-the-facebook-integration/) page ids to auto-post to.", + "items": { + "type": ["null", "string"] + } + }, + "fb_comments": { + "type": "boolean", + "title": "Facebook Comments", + "description": "Allows Facebook comments on the campaign (also force-enables the Campaign Archive toolbar). Defaults to `true`." + }, + "timewarp": { + "type": "boolean", + "title": "Timewarp Send", + "description": "Send this campaign using [Timewarp](https://mailchimp.com/help/use-timewarp/).", + "readOnly": true + }, + "template_id": { + "type": "integer", + "title": "Template ID", + "description": "The id for the template used in this campaign.", + "readOnly": false + }, + "drag_and_drop": { + "type": "boolean", + "title": "Drag And Drop Campaign", + "description": "Whether the campaign uses the drag-and-drop editor.", + "readOnly": true + } + } + }, + "variate_settings": { + "type": "object", + "title": "A/B Test Options", + "description": "The settings specific to A/B test campaigns.", + "properties": { + "winning_combination_id": { + "type": ["null", "string"], + "title": "Winning Combination ID", + "description": "ID for the winning combination.", + "readOnly": true + }, + "winning_campaign_id": { + "type": ["null", "string"], + "title": "Winning Campaign ID", + "description": "ID of the campaign that was sent to the remaining recipients based on the winning combination.", + "readOnly": true + }, + "winner_criteria": { + "type": ["null", "string"], + "title": "Winning Criteria", + "description": "The combination that performs the best. This may be determined automatically by click rate, open rate, or total revenue -- or you may choose manually based on the reporting data you find the most valuable. For Multivariate Campaigns testing send_time, winner_criteria is ignored. For Multivariate Campaigns with 'manual' as the winner_criteria, the winner must be chosen in the Mailchimp web application.", + "enum": ["opens", "clicks", "manual", "total_revenue"] + }, + "wait_time": { + "type": "integer", + "title": "Wait Time", + "description": "The number of minutes to wait before choosing the winning campaign. The value of wait_time must be greater than 0 and in whole hours, specified in minutes." + }, + "test_size": { + "type": "integer", + "title": "Test Size", + "description": "The percentage of recipients to send the test combinations to, must be a value between 10 and 100." + }, + "subject_lines": { + "type": "array", + "title": "Subject Lines", + "description": "The possible subject lines to test. If no subject lines are provided, settings.subject_line will be used.", + "items": { + "type": ["null", "string"] + } + }, + "send_times": { + "type": "array", + "title": "Send Times", + "description": "The possible send times to test. The times provided should be in the format YYYY-MM-DD HH:MM:SS. If send_times are provided to test, the test_size will be set to 100% and winner_criteria will be ignored.", + "items": { + "type": ["null", "string"], + "format": "date-time" + } + }, + "from_names": { + "type": "array", + "title": "From Names", + "description": "The possible from names. The number of from_names provided must match the number of reply_to_addresses. If no from_names are provided, settings.from_name will be used.", + "items": { + "type": ["null", "string"] + } + }, + "reply_to_addresses": { + "type": "array", + "title": "Reply To Addresses", + "description": "The possible reply-to addresses. The number of reply_to_addresses provided must match the number of from_names. If no reply_to_addresses are provided, settings.reply_to will be used.", + "items": { + "type": ["null", "string"] + } + }, + "contents": { + "type": "array", + "title": "Content Descriptions", + "description": "Descriptions of possible email contents. To set campaign contents, make a PUT request to /campaigns/{campaign_id}/content with the field 'variate_contents'.", + "items": { + "type": ["null", "string"] + }, + "readOnly": true + }, + "combinations": { + "type": "array", + "title": "Combinations", + "description": "Combinations of possible variables used to build emails.", + "readOnly": true, + "items": { + "type": "object", + "properties": { + "id": { + "type": ["null", "string"], + "title": "ID", + "description": "Unique ID for the combination." + }, + "subject_line": { + "type": "integer", + "title": "Subject Line", + "description": "The index of `variate_settings.subject_lines` used." + }, + "send_time": { + "type": "integer", + "title": "Send Time", + "description": "The index of `variate_settings.send_times` used." + }, + "from_name": { + "type": "integer", + "title": "From Name", + "description": "The index of `variate_settings.from_names` used." + }, + "reply_to": { + "type": "integer", + "title": "Reply To", + "description": "The index of `variate_settings.reply_to_addresses` used." + }, + "content_description": { + "type": "integer", + "title": "Content Description", + "description": "The index of `variate_settings.contents` used." + }, + "recipients": { + "type": "integer", + "title": "Recipients", + "description": "The number of recipients for this combination." + } + } + } + } + } + }, + "tracking": { + "type": "object", + "title": "Campaign Tracking Options", + "description": "The tracking options for a campaign.", + "properties": { + "opens": { + "type": "boolean", + "title": "Opens", + "description": "Whether to [track opens](https://mailchimp.com/help/about-open-tracking/). Defaults to `true`. Cannot be set to false for variate campaigns." + }, + "html_clicks": { + "type": "boolean", + "title": "HTML Click Tracking", + "description": "Whether to [track clicks](https://mailchimp.com/help/enable-and-view-click-tracking/) in the HTML version of the campaign. Defaults to `true`. Cannot be set to false for variate campaigns." + }, + "text_clicks": { + "type": "boolean", + "title": "Plain-Text Click Tracking", + "description": "Whether to [track clicks](https://mailchimp.com/help/enable-and-view-click-tracking/) in the plain-text version of the campaign. Defaults to `true`. Cannot be set to false for variate campaigns." + }, + "goal_tracking": { + "type": "boolean", + "title": "Mailchimp Goal Tracking", + "description": "Whether to enable [Goal](https://mailchimp.com/help/about-connected-sites/) tracking." + }, + "ecomm360": { + "type": "boolean", + "title": "E-commerce Tracking", + "description": "Whether to enable [eCommerce360](https://mailchimp.com/help/connect-your-online-store-to-mailchimp/) tracking." + }, + "google_analytics": { + "type": ["null", "string"], + "title": "Google Analytics Tracking", + "description": "The custom slug for [Google Analytics](https://mailchimp.com/help/integrate-google-analytics-with-mailchimp/) tracking (max of 50 bytes)." + }, + "clicktale": { + "type": ["null", "string"], + "title": "ClickTale Analytics Tracking", + "description": "The custom slug for [ClickTale](https://mailchimp.com/help/additional-tracking-options-for-campaigns/) tracking (max of 50 bytes)." + }, + "salesforce": { + "type": "object", + "title": "Salesforce CRM Tracking", + "description": "Salesforce tracking options for a campaign. Must be using Mailchimp's built-in [Salesforce integration](https://mailchimp.com/help/integrate-salesforce-with-mailchimp/).", + "properties": { + "campaign": { + "type": "boolean", + "title": "Salesforce Campaign", + "description": "Create a campaign in a connected Salesforce account." + }, + "notes": { + "type": "boolean", + "title": "Salesforce Note", + "description": "Update contact notes for a campaign based on subscriber email addresses." + } + } + }, + "capsule": { + "type": "object", + "title": "Capsule CRM Tracking", + "description": "Capsule tracking options for a campaign. Must be using Mailchimp's built-in Capsule integration.", + "properties": { + "notes": { + "type": "boolean", + "title": "Capsule Note", + "description": "Update contact notes for a campaign based on subscriber email addresses." + } + } + } + } + }, + "rss_opts": { + "type": "object", + "title": "RSS Options", + "description": "[RSS](https://mailchimp.com/help/share-your-blog-posts-with-mailchimp/) options for a campaign.", + "properties": { + "feed_url": { + "type": ["null", "string"], + "title": "Feed URL", + "format": "uri", + "description": "The URL for the RSS feed." + }, + "frequency": { + "type": ["null", "string"], + "title": "Frequency", + "description": "The frequency of the RSS Campaign.", + "enum": ["daily", "weekly", "monthly"] + }, + "schedule": { + "type": "object", + "title": "Sending Schedule", + "description": "The schedule for sending the RSS Campaign.", + "properties": { + "hour": { + "type": "integer", + "minimum": 0, + "maximum": 23, + "title": "Sending Hour", + "description": "The hour to send the campaign in local time. Acceptable hours are 0-23. For example, '4' would be 4am in [your account's default time zone](https://mailchimp.com/help/set-account-defaults/)." + }, + "daily_send": { + "type": "object", + "title": "Daily Sending Days", + "description": "The days of the week to send a daily RSS Campaign.", + "properties": { + "sunday": { + "type": "boolean", + "title": "Sunday", + "description": "Sends the daily RSS Campaign on Sundays." + }, + "monday": { + "type": "boolean", + "title": "Monday", + "description": "Sends the daily RSS Campaign on Mondays." + }, + "tuesday": { + "type": "boolean", + "title": "tuesday", + "description": "Sends the daily RSS Campaign on Tuesdays." + }, + "wednesday": { + "type": "boolean", + "title": "Monday", + "description": "Sends the daily RSS Campaign on Wednesdays." + }, + "thursday": { + "type": "boolean", + "title": "Thursday", + "description": "Sends the daily RSS Campaign on Thursdays." + }, + "friday": { + "type": "boolean", + "title": "Friday", + "description": "Sends the daily RSS Campaign on Fridays." + }, + "saturday": { + "type": "boolean", + "title": "Saturday", + "description": "Sends the daily RSS Campaign on Saturdays." + } + } + }, + "weekly_send_day": { + "type": ["null", "string"], + "enum": [ + "sunday", + "monday", + "tuesday", + "wednesday", + "thursday", + "friday", + "saturday" + ], + "title": "Weekly Sending Day", + "description": "The day of the week to send a weekly RSS Campaign." + }, + "monthly_send_date": { + "type": "number", + "minimum": 0, + "maximum": 31, + "title": "Monthly Sending Day", + "description": "The day of the month to send a monthly RSS Campaign. Acceptable days are 0-31, where '0' is always the last day of a month. Months with fewer than the selected number of days will not have an RSS campaign sent out that day. For example, RSS Campaigns set to send on the 30th will not go out in February." + } + } + }, + "last_sent": { + "type": ["null", "string"], + "title": "Last Sent", + "description": "The date the campaign was last sent.", + "readOnly": true, + "format": "date-time" + }, + "constrain_rss_img": { + "type": "boolean", + "title": "Constrain RSS Images", + "description": "Whether to add CSS to images in the RSS feed to constrain their width in campaigns." + } + } + }, + "ab_split_opts": { + "type": "object", + "title": "A/B Testing Options", + "description": "[A/B Testing](https://mailchimp.com/help/about-ab-testing-campaigns/) options for a campaign.", + "readOnly": true, + "properties": { + "split_test": { + "type": ["null", "string"], + "title": "Split Test", + "description": "The type of AB split to run.", + "enum": ["subject", "from_name", "schedule"] + }, + "pick_winner": { + "type": ["null", "string"], + "title": "Pick Winner", + "description": "How we should evaluate a winner. Based on 'opens', 'clicks', or 'manual'.", + "enum": ["opens", "clicks", "manual"] + }, + "wait_units": { + "type": ["null", "string"], + "title": "Wait Time", + "description": "How unit of time for measuring the winner ('hours' or 'days'). This cannot be changed after a campaign is sent.", + "enum": ["hours", "days"] + }, + "wait_time": { + "type": "integer", + "title": "Wait Time", + "description": "The amount of time to wait before picking a winner. This cannot be changed after a campaign is sent." + }, + "split_size": { + "type": "integer", + "minimum": 1, + "maximum": 50, + "title": "Split Size", + "description": "The size of the split groups. Campaigns split based on 'schedule' are forced to have a 50/50 split. Valid split integers are between 1-50." + }, + "from_name_a": { + "type": ["null", "string"], + "title": "From Name Group A", + "description": "For campaigns split on 'From Name', the name for Group A." + }, + "from_name_b": { + "type": ["null", "string"], + "title": "From Name Group B", + "description": "For campaigns split on 'From Name', the name for Group B." + }, + "reply_email_a": { + "type": ["null", "string"], + "title": "Reply Email Group A", + "description": "For campaigns split on 'From Name', the reply-to address for Group A." + }, + "reply_email_b": { + "type": ["null", "string"], + "title": "Reply Email Group B", + "description": "For campaigns split on 'From Name', the reply-to address for Group B." + }, + "subject_a": { + "type": ["null", "string"], + "title": "Subject Line Group A", + "description": "For campaigns split on 'Subject Line', the subject line for Group A." + }, + "subject_b": { + "type": ["null", "string"], + "title": "Subject Line Group B", + "description": "For campaigns split on 'Subject Line', the subject line for Group B." + }, + "send_time_a": { + "type": ["null", "string"], + "format": "date-time", + "title": "Send Time Group A", + "description": "The send time for Group A." + }, + "send_time_b": { + "type": ["null", "string"], + "format": "date-time", + "title": "Send Time Group B", + "description": "The send time for Group B." + }, + "send_time_winner": { + "type": ["null", "string"], + "title": "Send Time Winner", + "description": "The send time for the winning version." + } + } + }, + "social_card": { + "type": "object", + "title": "Campaign Social Card", + "description": "The preview for the campaign, rendered by social networks like Facebook and Twitter. [Learn more](https://mailchimp.com/help/enable-and-customize-social-cards/).", + "properties": { + "image_url": { + "type": ["null", "string"], + "title": "Image URL", + "description": "The url for the header image for the card." + }, + "description": { + "type": ["null", "string"], + "title": "Campaign Description", + "description": "A short summary of the campaign to display." + }, + "title": { + "type": ["null", "string"], + "title": "Title", + "description": "The title for the card. Typically the subject line of the campaign." + } + } + }, + "report_summary": { + "type": "object", + "title": "Campaign Report Summary", + "description": "For sent campaigns, a summary of opens, clicks, and e-commerce data.", + "properties": { + "opens": { + "type": "integer", + "title": "Automation Opens", + "description": "The total number of opens for a campaign.", + "readOnly": true + }, + "unique_opens": { + "type": "integer", + "title": "Unique Opens", + "description": "The number of unique opens.", + "readOnly": true + }, + "open_rate": { + "type": "number", + "title": "Open Rate", + "description": "The number of unique opens divided by the total number of successful deliveries.", + "readOnly": true + }, + "clicks": { + "type": "integer", + "title": "Total Clicks", + "description": "The total number of clicks for an campaign.", + "readOnly": true + }, + "subscriber_clicks": { + "type": "integer", + "title": "Unique Subscriber Clicks", + "description": "The number of unique clicks.", + "readOnly": true + }, + "click_rate": { + "type": "number", + "title": "Click Rate", + "description": "The number of unique clicks divided by the total number of successful deliveries.", + "readOnly": true + }, + "ecommerce": { + "type": "object", + "title": "E-Commerce Report", + "description": "E-Commerce stats for a campaign.", + "properties": { + "total_orders": { + "type": "integer", + "title": "Total Orders", + "description": "The total orders for a campaign.", + "readOnly": true + }, + "total_spent": { + "type": "number", + "title": "Total Spent", + "description": "The total spent for a campaign. Calculated as the sum of all order totals with no deductions.", + "readOnly": true + }, + "total_revenue": { + "type": "number", + "title": "Total Revenue", + "description": "The total revenue for a campaign. Calculated as the sum of all order totals minus shipping and tax totals.", + "readOnly": true + } + } + } + } + }, + "delivery_status": { + "type": "object", + "title": "Campaign Delivery Status", + "description": "Updates on campaigns in the process of sending.", + "properties": { + "enabled": { + "type": "boolean", + "title": "Delivery Status Enabled", + "description": "Whether Campaign Delivery Status is enabled for this account and campaign.", + "readOnly": true + }, + "can_cancel": { + "type": "boolean", + "title": "Campaign Cancelable", + "description": "Whether a campaign send can be canceled.", + "readOnly": true + }, + "status": { + "type": ["null", "string"], + "title": "Campaign Delivery Status", + "description": "The current state of a campaign delivery.", + "enum": ["delivering", "delivered", "canceling", "canceled"], + "readOnly": true + }, + "emails_sent": { + "type": "integer", + "title": "Emails Sent", + "description": "The total number of emails confirmed sent for this campaign so far.", + "readOnly": true + }, + "emails_canceled": { + "type": "integer", + "title": "Emails Canceled", + "description": "The total number of emails canceled for this campaign.", + "readOnly": true + } + } + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/email_activity.json b/source-mailchimp/source_mailchimp/schemas/email_activity.json new file mode 100644 index 0000000000..a8f2c115e1 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/email_activity.json @@ -0,0 +1,61 @@ +{ + "type": "object", + "title": "Email Activity", + "description": "A list of member's subscriber activity in a specific campaign.", + "required": ["timestamp", "email_id", "action"], + "properties": { + "campaign_id": { + "type": "string", + "title": "The unique id for the campaign.", + "description": "The unique id for the campaign." + }, + "list_id": { + "type": "string", + "title": "The unique id for the list.", + "description": "The unique id for the list." + }, + "list_is_active": { + "type": "boolean", + "title": "The status of the list used.", + "description": "The status of the list used, namely if it's deleted or disabled." + }, + "email_id": { + "type": "string", + "title": "email MD5 hash.", + "description": "The MD5 hash of the lowercase version of the list member's email address." + }, + "email_address": { + "type": "string", + "title": "Email address for a subscriber.", + "description": "Email address for a subscriber." + }, + "action": { + "type": "string", + "title": "action", + "enum": ["open", "click", "bounce"], + "description": "One of the following actions: 'open', 'click', or 'bounce'" + }, + "type": { + "type": ["string", "null"], + "title": "Type", + "enum": ["hard", "soft"], + "description": "If the action is a 'bounce', the type of bounce received: 'hard', 'soft'." + }, + "timestamp": { + "type": "string", + "title": "Action date and time", + "description": "The date and time recorded for the action in ISO 8601 format.", + "format": "date-time" + }, + "url": { + "type": ["string", "null"], + "title": "Click url", + "description": "If the action is a 'click', the URL on which the member clicked." + }, + "ip": { + "type": ["string", "null"], + "title": "Action ip address", + "description": "The IP address recorded for the action." + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/interest_categories.json b/source-mailchimp/source_mailchimp/schemas/interest_categories.json new file mode 100644 index 0000000000..621a63ecdc --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/interest_categories.json @@ -0,0 +1,22 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "required": ["id"], + "properties": { + "list_id": { + "type": ["null", "string"] + }, + "id": { + "type": "string" + }, + "title": { + "type": ["null", "string"] + }, + "display_order": { + "type": ["null", "integer"] + }, + "type": { + "type": ["null", "string"] + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/interests.json b/source-mailchimp/source_mailchimp/schemas/interests.json new file mode 100644 index 0000000000..84ebf4c9d7 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/interests.json @@ -0,0 +1,25 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "required": ["id"], + "properties": { + "category_id": { + "type": ["null", "string"] + }, + "list_id": { + "type": ["null", "string"] + }, + "id": { + "type": "string" + }, + "name": { + "type": ["null", "string"] + }, + "subscriber_count": { + "type": ["null", "string"] + }, + "display_order": { + "type": ["null", "integer"] + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/list_members.json b/source-mailchimp/source_mailchimp/schemas/list_members.json new file mode 100644 index 0000000000..3e369c48e2 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/list_members.json @@ -0,0 +1,182 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "additionalProperties": true, + "required": ["id"], + "properties": { + "id": { + "type": "string" + }, + "email_address": { + "type": ["null", "string"] + }, + "unique_email_id": { + "type": ["null", "string"] + }, + "contact_id": { + "type": ["null", "string"] + }, + "full_name": { + "type": ["null", "string"] + }, + "web_id": { + "type": ["null", "integer"] + }, + "email_type": { + "type": ["null", "string"] + }, + "status": { + "type": ["null", "string"] + }, + "unsubscribe_reason": { + "type": ["null", "string"] + }, + "consents_to_one_to_one_messaging": { + "type": ["null", "boolean"] + }, + "merge_fields": { + "type": ["null", "object"], + "additionalProperties": true + }, + "interests": { + "type": ["null", "object"], + "additionalProperties": true + }, + "stats": { + "type": ["null", "object"], + "properties": { + "avg_open_rate": { + "type": ["null", "number"] + }, + "avg_click_rate": { + "type": ["null", "number"] + }, + "ecommerce_data": { + "type": ["null", "object"], + "properties": { + "total_revenue": { + "type": ["null", "number"] + }, + "number_of_orders": { + "type": ["null", "number"] + }, + "currency_code": { + "type": ["null", "string"] + } + } + } + } + }, + "ip_signup": { + "type": ["null", "string"] + }, + "timestamp_signup": { + "type": ["null", "string"], + "format": "date-time" + }, + "ip_opt": { + "type": ["null", "string"] + }, + "timestamp_opt": { + "type": ["null", "string"], + "format": "date-time" + }, + "member_rating": { + "type": ["null", "integer"] + }, + "last_changed": { + "type": ["null", "string"], + "format": "date-time" + }, + "language": { + "type": ["null", "string"] + }, + "vip": { + "type": ["null", "boolean"] + }, + "email_client": { + "type": ["null", "string"] + }, + "location": { + "type": ["null", "object"], + "properties": { + "latitude": { + "type": ["null", "number"] + }, + "longitude": { + "type": ["null", "number"] + }, + "gmtoff": { + "type": ["null", "integer"] + }, + "dstoff": { + "type": ["null", "integer"] + }, + "country_code": { + "type": ["null", "string"] + }, + "timezone": { + "type": ["null", "string"] + }, + "region": { + "type": ["null", "string"] + } + } + }, + "marketing_permissions": { + "type": ["null", "object"], + "properties": { + "marketing_permission_id": { + "type": ["null", "string"] + }, + "text": { + "type": ["null", "string"] + }, + "enabled": { + "type": ["null", "boolean"] + } + } + }, + "last_note": { + "type": ["null", "object"], + "properties": { + "note_id": { + "type": ["null", "integer"] + }, + "created_at": { + "type": ["null", "string"], + "format": "date-time" + }, + "created_by": { + "type": ["null", "string"] + }, + "note": { + "type": ["null", "string"] + } + } + }, + "source": { + "type": ["null", "string"] + }, + "tags_count": { + "type": ["null", "integer"] + }, + "tags": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "integer"] + }, + "name": { + "type": ["null", "string"] + } + } + } + }, + "list_id": { + "type": ["null", "string"] + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/lists.json b/source-mailchimp/source_mailchimp/schemas/lists.json new file mode 100644 index 0000000000..5343eb9284 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/lists.json @@ -0,0 +1,302 @@ +{ + "type": "object", + "title": "Subscriber List", + "description": "Information about a specific list.", + "required": ["id"], + "properties": { + "id": { + "type": "string", + "title": "List ID", + "description": "A string that uniquely identifies this list.", + "readOnly": true + }, + "web_id": { + "type": "integer", + "title": "List Web ID", + "description": "The ID used in the Mailchimp web application. View this list in your Mailchimp account at `https://{dc}.admin.mailchimp.com/lists/members/?id={web_id}`.", + "readOnly": true + }, + "name": { + "type": ["null", "string"], + "title": "List Name", + "description": "The name of the list." + }, + "contact": { + "type": "object", + "title": "List Contact", + "description": "[Contact information displayed in campaign footers](https://mailchimp.com/help/about-campaign-footers/) to comply with international spam laws.", + "properties": { + "company": { + "type": ["null", "string"], + "title": "Company Name", + "description": "The company name for the list." + }, + "address1": { + "type": ["null", "string"], + "title": "Address", + "description": "The street address for the list contact." + }, + "address2": { + "type": ["null", "string"], + "title": "Address", + "description": "The street address for the list contact." + }, + "city": { + "type": ["null", "string"], + "title": "City", + "description": "The city for the list contact." + }, + "state": { + "type": ["null", "string"], + "title": "State", + "description": "The state for the list contact." + }, + "zip": { + "type": ["null", "string"], + "title": "Postal Code", + "description": "The postal or zip code for the list contact." + }, + "country": { + "type": ["null", "string"], + "title": "Country Code", + "description": "A two-character ISO3166 country code. Defaults to US if invalid." + }, + "phone": { + "type": ["null", "string"], + "title": "Phone Number", + "description": "The phone number for the list contact." + } + } + }, + "permission_reminder": { + "type": ["null", "string"], + "title": "Permission Reminder", + "description": "The [permission reminder](https://mailchimp.com/help/edit-the-permission-reminder/) for the list." + }, + "use_archive_bar": { + "type": "boolean", + "title": "Use Archive Bar", + "description": "Whether campaigns for this list use the [Archive Bar](https://mailchimp.com/help/about-email-campaign-archives-and-pages/) in archives by default.", + "default": false + }, + "campaign_defaults": { + "type": "object", + "title": "Campaign Defaults", + "description": "[Default values for campaigns](https://mailchimp.com/help/edit-your-emails-subject-preview-text-from-name-or-from-email-address/) created for this list.", + "properties": { + "from_name": { + "type": ["null", "string"], + "title": "Sender's Name", + "description": "The default from name for campaigns sent to this list." + }, + "from_email": { + "type": ["null", "string"], + "title": "Sender's Email Address", + "description": "The default from email for campaigns sent to this list." + }, + "subject": { + "type": ["null", "string"], + "title": "Subject", + "description": "The default subject line for campaigns sent to this list." + }, + "language": { + "type": ["null", "string"], + "title": "Language", + "description": "The default language for this lists's forms." + } + } + }, + "notify_on_subscribe": { + "type": ["null", "string"], + "title": "Notify on Subscribe", + "description": "The email address to send [subscribe notifications](https://mailchimp.com/help/change-subscribe-and-unsubscribe-notifications/) to." + }, + "notify_on_unsubscribe": { + "type": ["null", "string"], + "title": "Notify on Unsubscribe", + "description": "The email address to send [unsubscribe notifications](https://mailchimp.com/help/change-subscribe-and-unsubscribe-notifications/) to." }, + "date_created": { + "type": "string", + "title": "Creation Date", + "description": "The date and time that this list was created in ISO 8601 format.", + "format": "date-time", + "readOnly": true + }, + "list_rating": { + "type": "integer", + "title": "List Rating", + "description": "An auto-generated activity score for the list (0-5).", + "readOnly": true + }, + "email_type_option": { + "type": "boolean", + "title": "Email Type Option", + "description": "Whether the list supports [multiple formats for emails](https://mailchimp.com/help/change-list-name-and-defaults/). When set to `true`, subscribers can choose whether they want to receive HTML or plain-text emails. When set to `false`, subscribers will receive HTML emails, with a plain-text alternative backup." + }, + "subscribe_url_short": { + "type": ["null", "string"], + "title": "Subscribe URL Short", + "description": "Our [EepURL shortened](https://mailchimp.com/help/share-your-signup-form/) version of this list's subscribe form.", + "readOnly": true + }, + "subscribe_url_long": { + "type": ["null", "string"], + "title": "Subscribe URL Long", + "description": "The full version of this list's subscribe form (host will vary).", + "readOnly": true + }, + "beamer_address": { + "type": ["null", "string"], + "title": "Beamer Address", + "description": "The list's [Email Beamer](https://mailchimp.com/help/use-email-beamer-to-create-a-campaign/) address.", + "readOnly": true + }, + "visibility": { + "type": ["null", "string"], + "title": "Visibility", + "enum": ["pub", "prv"], + "description": "Whether this list is [public or private](https://mailchimp.com/help/about-list-publicity/)." + }, + "double_optin": { + "type": "boolean", + "title": "Double Opt In", + "description": "Whether or not to require the subscriber to confirm subscription via email.", + "default": false + }, + "has_welcome": { + "type": "boolean", + "title": "Has Welcome", + "description": "Whether or not this list has a welcome automation connected. Welcome Automations: welcomeSeries, singleWelcome, emailFollowup.", + "default": false, + "example": false + }, + "marketing_permissions": { + "type": "boolean", + "title": "Marketing Permissions", + "description": "Whether or not the list has marketing permissions (eg. GDPR) enabled.", + "default": false + }, + "modules": { + "type": "array", + "title": "Modules", + "description": "Any list-specific modules installed for this list.", + "items": { + "type": ["null", "string"] + }, + "readOnly": true + }, + "stats": { + "type": "object", + "title": "Statistics", + "description": "Stats for the list. Many of these are cached for at least five minutes.", + "readOnly": true, + "properties": { + "member_count": { + "type": "integer", + "title": "Member Count", + "description": "The number of active members in the list.", + "readOnly": true + }, + "total_contacts": { + "type": "integer", + "title": "Total Contacts", + "description": "The number of contacts in the list, including subscribed, unsubscribed, pending, cleaned, deleted, transactional, and those that need to be reconfirmed.", + "readOnly": true + }, + "unsubscribe_count": { + "type": "integer", + "title": "Unsubscribe Count", + "description": "The number of members who have unsubscribed from the list.", + "readOnly": true + }, + "cleaned_count": { + "type": "integer", + "title": "Cleaned Count", + "description": "The number of members cleaned from the list.", + "readOnly": true + }, + "member_count_since_send": { + "type": "integer", + "title": "Member Count Since Send", + "description": "The number of active members in the list since the last campaign was sent.", + "readOnly": true + }, + "unsubscribe_count_since_send": { + "type": "integer", + "title": "Unsubscribe Count Since Send", + "description": "The number of members who have unsubscribed since the last campaign was sent.", + "readOnly": true + }, + "cleaned_count_since_send": { + "type": "integer", + "title": "Cleaned Count Since Send", + "description": "The number of members cleaned from the list since the last campaign was sent.", + "readOnly": true + }, + "campaign_count": { + "type": "integer", + "title": "Campaign Count", + "description": "The number of campaigns in any status that use this list.", + "readOnly": true + }, + "campaign_last_sent": { + "type": ["null", "string"], + "title": "Campaign Last Sent", + "description": "The date and time the last campaign was sent to this list in ISO 8601 format. This is updated when a campaign is sent to 10 or more recipients.", + "readOnly": true, + "format": "date-time" + }, + "merge_field_count": { + "type": "integer", + "title": "Merge Var Count", + "description": "The number of merge vars for this list (not EMAIL, which is required).", + "readOnly": true + }, + "avg_sub_rate": { + "type": "number", + "title": "Average Subscription Rate", + "description": "The average number of subscriptions per month for the list (not returned if we haven't calculated it yet).", + "readOnly": true + }, + "avg_unsub_rate": { + "type": "number", + "title": "Average Unsubscription Rate", + "description": "The average number of unsubscriptions per month for the list (not returned if we haven't calculated it yet).", + "readOnly": true + }, + "target_sub_rate": { + "type": "number", + "title": "Average Subscription Rate", + "description": "The target number of subscriptions per month for the list to keep it growing (not returned if we haven't calculated it yet).", + "readOnly": true + }, + "open_rate": { + "type": "number", + "title": "Open Rate", + "description": "The average open rate (a percentage represented as a number between 0 and 100) per campaign for the list (not returned if we haven't calculated it yet).", + "readOnly": true + }, + "click_rate": { + "type": "number", + "title": "Click Rate", + "description": "The average click rate (a percentage represented as a number between 0 and 100) per campaign for the list (not returned if we haven't calculated it yet).", + "readOnly": true + }, + "last_sub_date": { + "type": ["null", "string"], + "title": "Date of Last List Subscribe", + "description": "The date and time of the last time someone subscribed to this list in ISO 8601 format.", + "readOnly": true, + "format": "date-time" + }, + "last_unsub_date": { + "type": ["null", "string"], + "title": "Date of Last List Unsubscribe", + "description": "The date and time of the last time someone unsubscribed from this list in ISO 8601 format.", + "readOnly": true, + "format": "date-time" + } + } + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/reports.json b/source-mailchimp/source_mailchimp/schemas/reports.json new file mode 100644 index 0000000000..f31a2cbda1 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/reports.json @@ -0,0 +1,562 @@ +{ + "type": "object", + "title": "Campaign Reports", + "description": "A list of reports containing campaigns marked as Sent.", + "required": ["id"], + "properties": { + "id": { + "type": "string", + "title": "Campaign ID", + "description": "A string that uniquely identifies this campaign." + }, + "campaign_title": { + "type": ["null", "string"], + "title": "Campaign Title", + "description": "The title of the campaign.", + "readOnly": true + }, + "type": { + "type": ["null", "string"], + "title": "Campaign Type", + "description": "The type of campaign (regular, plain-text, ab_split, rss, automation, variate, or auto)." + }, + "list_id": { + "type": "string", + "title": "List ID", + "description": "The unique list id.", + "readOnly": true + }, + "list_is_active": { + "type": "boolean", + "title": "List Status", + "description": "The status of the list used, namely if it's deleted or disabled.", + "readOnly": true + }, + "list_name": { + "type": ["null", "string"], + "title": "List Name", + "description": "The name of the list.", + "readOnly": true + }, + "subject_line": { + "type": ["null", "string"], + "title": "Campaign Subject Line", + "description": "The subject line for the campaign.", + "readOnly": true + }, + "preview_text": { + "type": ["null", "string"], + "title": "Campaign Preview Text", + "description": "The preview text for the campaign." + }, + "emails_sent": { + "type": "integer", + "title": "Emails Sent", + "description": "The total number of emails sent for this campaign." + }, + "abuse_reports": { + "type": "integer", + "title": "Abuse Reports", + "description": "The number of abuse reports generated for this campaign." + }, + "unsubscribed": { + "type": "integer", + "title": "Unsubscribe Count", + "description": "The total number of unsubscribed members for this campaign.", + "readOnly": true + }, + "send_time": { + "type": ["null", "string"], + "format": "date-time", + "title": "Send Time", + "description": "The date and time a campaign was sent in ISO 8601 format.", + "readOnly": true + }, + "rss_last_send": { + "type": ["null", "string"], + "format": "date-time", + "title": "RSS Last Send", + "description": "For RSS campaigns, the date and time of the last send in ISO 8601 format.", + "readOnly": true + }, + "bounces": { + "type": "object", + "title": "Bounces", + "description": "An object describing the bounce summary for the campaign.", + "properties": { + "hard_bounces": { + "type": "integer", + "title": "Hard Bounces", + "description": "The total number of hard bounced email addresses." + }, + "soft_bounces": { + "type": "integer", + "title": "Soft Bounces", + "description": "The total number of soft bounced email addresses." + }, + "syntax_errors": { + "type": "integer", + "title": "Syntax Errors", + "description": "The total number of addresses that were syntax-related bounces." + } + } + }, + "forwards": { + "type": "object", + "title": "Forwards", + "description": "An object describing the forwards and forward activity for the campaign.", + "properties": { + "forwards_count": { + "type": "integer", + "title": "Total Forwards", + "description": "How many times the campaign has been forwarded." + }, + "forwards_opens": { + "type": "integer", + "title": "Forward Opens", + "description": "How many times the forwarded campaign has been opened." + } + } + }, + "opens": { + "type": "object", + "title": "Opens", + "description": "An object describing the open activity for the campaign.", + "properties": { + "opens_total": { + "type": "integer", + "title": "Total Opens", + "description": "The total number of opens for a campaign." + }, + "unique_opens": { + "type": "integer", + "title": "Unique Opens", + "description": "The total number of unique opens." + }, + "open_rate": { + "type": "number", + "title": "Open Rate", + "description": "The number of unique opens divided by the total number of successful deliveries." + }, + "last_open": { + "type": ["null", "string"], + "format": "date-time", + "title": "Last Open", + "description": "The date and time of the last recorded open in ISO 8601 format." + } + } + }, + "clicks": { + "type": "object", + "title": "Clicks", + "description": "An object describing the click activity for the campaign.", + "properties": { + "clicks_total": { + "type": "integer", + "title": "Total Clicks", + "description": "The total number of clicks for the campaign." + }, + "unique_clicks": { + "type": "integer", + "title": "Unique Clicks", + "description": "The total number of unique clicks for links across a campaign." + }, + "unique_subscriber_clicks": { + "type": "integer", + "title": "Unique Subscriber Clicks", + "description": "The total number of subscribers who clicked on a campaign." + }, + "click_rate": { + "type": "number", + "title": "Click Rate", + "description": "The number of unique clicks divided by the total number of successful deliveries." + }, + "last_click": { + "type": ["null", "string"], + "format": "date-time", + "title": "Last Click", + "description": "The date and time of the last recorded click for the campaign in ISO 8601 format." + } + } + }, + "facebook_likes": { + "type": "object", + "title": "Facebook Likes", + "description": "An object describing campaign engagement on Facebook.", + "properties": { + "recipient_likes": { + "type": "integer", + "title": "Recipient Likes", + "description": "The number of recipients who liked the campaign on Facebook." + }, + "unique_likes": { + "type": "integer", + "title": "Unique Likes", + "description": "The number of unique likes." + }, + "facebook_likes": { + "type": "integer", + "title": "Facebook Likes", + "description": "The number of Facebook likes for the campaign." + } + } + }, + "industry_stats": { + "type": "object", + "title": "Industry Stats", + "description": "The average campaign statistics for your industry.", + "properties": { + "type": { + "type": ["null", "string"], + "title": "Industry Type", + "description": "The type of business industry associated with your account. For example: retail, education, etc." + }, + "open_rate": { + "type": "number", + "title": "Open Rate", + "description": "The industry open rate." + }, + "click_rate": { + "type": "number", + "title": "Click Rate", + "description": "The industry click rate." + }, + "bounce_rate": { + "type": "number", + "title": "Bounce Rate", + "description": "The industry bounce rate." + }, + "unopen_rate": { + "type": "number", + "title": "Unopened Rate", + "description": "The industry unopened rate." + }, + "unsub_rate": { + "type": "number", + "title": "Unsubscribe Rate", + "description": "The industry unsubscribe rate." + }, + "abuse_rate": { + "type": "number", + "title": "Abuse Rate", + "description": "The industry abuse rate." + } + } + }, + "list_stats": { + "type": "object", + "title": "List Stats", + "description": "The average campaign statistics for your list. This won't be present if we haven't calculated it yet for this list.", + "properties": { + "sub_rate": { + "type": "number", + "title": "Average Subscription Rate", + "description": "The average number of subscriptions per month for the list.", + "readOnly": true + }, + "unsub_rate": { + "type": "number", + "title": "Average Unsubscription Rate", + "description": "The average number of unsubscriptions per month for the list.", + "readOnly": true + }, + "open_rate": { + "type": "number", + "title": "Open Rate", + "description": "The average open rate (a percentage represented as a number between 0 and 100) per campaign for the list.", + "readOnly": true + }, + "click_rate": { + "type": "number", + "title": "Click Rate", + "description": "The average click rate (a percentage represented as a number between 0 and 100) per campaign for the list.", + "readOnly": true + } + } + }, + "ab_split": { + "type": "object", + "title": "A/B Split Stats", + "description": "General stats about different groups of an A/B Split campaign. Does not return information about Multivariate Campaigns.", + "properties": { + "a": { + "type": "object", + "title": "Campaign A", + "description": "Stats for Campaign A.", + "properties": { + "bounces": { + "type": "integer", + "title": "Bounces", + "description": "Bounces for Campaign A." + }, + "abuse_reports": { + "type": "integer", + "title": "Abuse Reports", + "description": "Abuse reports for Campaign A." + }, + "unsubs": { + "type": "integer", + "title": "Unsubscribes", + "description": "Unsubscribes for Campaign A." + }, + "recipient_clicks": { + "type": "integer", + "title": "Recipient Clicks", + "description": "Recipient Clicks for Campaign A." + }, + "forwards": { + "type": "integer", + "title": "Forwards", + "description": "Forwards for Campaign A." + }, + "forwards_opens": { + "type": "integer", + "title": "Forward Opens", + "description": "Opens from forwards for Campaign A." + }, + "opens": { + "type": "integer", + "title": "Opens", + "description": "Opens for Campaign A." + }, + "last_open": { + "type": ["null", "string"], + "title": "Last Open", + "description": "The last open for Campaign A.", + "format": "date-time" + }, + "unique_opens": { + "type": "integer", + "title": "Unique Opens", + "description": "Unique opens for Campaign A." + } + } + }, + "b": { + "type": "object", + "title": "Campaign B", + "description": "Stats for Campaign B.", + "properties": { + "bounces": { + "type": "integer", + "title": "Bounces", + "description": "Bounces for Campaign B." + }, + "abuse_reports": { + "type": "integer", + "title": "Abuse Reports", + "description": "Abuse reports for Campaign B." + }, + "unsubs": { + "type": "integer", + "title": "Unsubscribes", + "description": "Unsubscribes for Campaign B." + }, + "recipient_clicks": { + "type": "integer", + "title": "Recipient Clicks", + "description": "Recipients clicks for Campaign B." + }, + "forwards": { + "type": "integer", + "title": "Forwards", + "description": "Forwards for Campaign B." + }, + "forwards_opens": { + "type": "integer", + "title": "Forward Opens", + "description": "Opens for forwards from Campaign B." + }, + "opens": { + "type": "integer", + "title": "Opens", + "description": "Opens for Campaign B." + }, + "last_open": { + "type": ["null", "string"], + "title": "Last Open", + "description": "The last open for Campaign B.", + "format": "date-time" + }, + "unique_opens": { + "type": "integer", + "title": "Unique Opens", + "description": "Unique opens for Campaign B." + } + } + } + } + }, + "timewarp": { + "type": "array", + "title": "Timewarp Stats", + "description": "An hourly breakdown of sends, opens, and clicks if a campaign is sent using timewarp.", + "items": { + "type": "object", + "properties": { + "gmt_offset": { + "type": "integer", + "title": "GMT Offset", + "description": "For campaigns sent with timewarp, the time zone group the member is apart of." + }, + "opens": { + "type": "integer", + "title": "Opens", + "description": "The number of opens." + }, + "last_open": { + "type": ["null", "string"], + "format": "date-time", + "title": "Last Open", + "description": "The date and time of the last open in ISO 8601 format." + }, + "unique_opens": { + "type": "integer", + "title": "Unique Opens", + "description": "The number of unique opens." + }, + "clicks": { + "type": "integer", + "title": "Clicks", + "description": "The number of clicks." + }, + "last_click": { + "type": ["null", "string"], + "format": "date-time", + "title": "Last Click", + "description": "The date and time of the last click in ISO 8601 format." + }, + "unique_clicks": { + "type": "integer", + "title": "Unique Clicks", + "description": "The number of unique clicks." + }, + "bounces": { + "type": "integer", + "title": "Bounces", + "description": "The number of bounces." + } + } + } + }, + "timeseries": { + "type": "array", + "title": "Timeseries", + "description": "An hourly breakdown of the performance of the campaign over the first 24 hours.", + "items": { + "type": "object", + "properties": { + "timestamp": { + "type": ["null", "string"], + "format": "date-time", + "title": "Timestamp", + "description": "The date and time for the series in ISO 8601 format." + }, + "emails_sent": { + "type": "integer", + "title": "Emails Sent", + "description": "The number of emails sent in the timeseries." + }, + "unique_opens": { + "type": "integer", + "title": "Unique Opens", + "description": "The number of unique opens in the timeseries." + }, + "recipients_clicks": { + "type": "integer", + "title": "Recipient Clicks", + "description": "The number of clicks in the timeseries." + } + } + } + }, + "share_report": { + "type": "object", + "title": "Share Report", + "description": "The url and password for the [VIP report](https://mailchimp.com/help/share-a-campaign-report/).", + "properties": { + "share_url": { + "type": ["null", "string"], + "title": "Report URL", + "description": "The URL for the VIP report.", + "readOnly": true + }, + "share_password": { + "type": ["null", "string"], + "title": "Report Password", + "description": "If password protected, the password for the VIP report.", + "readOnly": true + } + } + }, + "ecommerce": { + "type": "object", + "title": "E-Commerce Report", + "description": "E-Commerce stats for a campaign.", + "properties": { + "total_orders": { + "type": "integer", + "title": "Total Orders", + "description": "The total orders for a campaign.", + "readOnly": true + }, + "total_spent": { + "type": "number", + "title": "Total Spent", + "description": "The total spent for a campaign. Calculated as the sum of all order totals with no deductions.", + "readOnly": true + }, + "total_revenue": { + "type": "number", + "title": "Total Revenue", + "description": "The total revenue for a campaign. Calculated as the sum of all order totals minus shipping and tax totals.", + "readOnly": true + }, + "currency_code": { + "type": ["null", "string"], + "title": "Three letter currency code for this user", + "readOnly": true, + "example": "USD" + } + } + }, + "delivery_status": { + "type": "object", + "title": "Campaign Delivery Status", + "description": "Updates on campaigns in the process of sending.", + "properties": { + "enabled": { + "type": "boolean", + "title": "Delivery Status Enabled", + "description": "Whether Campaign Delivery Status is enabled for this account and campaign.", + "readOnly": true + }, + "can_cancel": { + "type": "boolean", + "title": "Campaign Cancelable", + "description": "Whether a campaign send can be canceled.", + "readOnly": true + }, + "status": { + "type": ["null", "string"], + "title": "Campaign Delivery Status", + "description": "The current state of a campaign delivery.", + "enum": ["delivering", "delivered", "canceling", "canceled"], + "readOnly": true + }, + "emails_sent": { + "type": "integer", + "title": "Emails Sent", + "description": "The total number of emails confirmed sent for this campaign so far.", + "readOnly": true + }, + "emails_canceled": { + "type": "integer", + "title": "Emails Canceled", + "description": "The total number of emails canceled for this campaign.", + "readOnly": true + } + } + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/segment_members.json b/source-mailchimp/source_mailchimp/schemas/segment_members.json new file mode 100644 index 0000000000..53acc2bdaf --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/segment_members.json @@ -0,0 +1,119 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "additionalProperties": true, + "required": ["id"], + "properties": { + "id": { + "type": "string" + }, + "email_address": { + "type": ["null", "string"] + }, + "unique_email_id": { + "type": ["null", "string"] + }, + "email_type": { + "type": ["null", "string"] + }, + "status": { + "type": ["null", "string"] + }, + "merge_fields": { + "type": ["null", "object"], + "additionalProperties": true + }, + "interests": { + "type": ["null", "object"], + "additionalProperties": true + }, + "stats": { + "type": ["null", "object"], + "properties": { + "avg_open_rate": { + "type": ["null", "number"] + }, + "avg_click_rate": { + "type": ["null", "number"] + } + } + }, + "ip_signup": { + "type": ["null", "string"] + }, + "timestamp_signup": { + "type": ["null", "string"], + "format": "date-time" + }, + "ip_opt": { + "type": ["null", "string"] + }, + "timestamp_opt": { + "type": ["null", "string"], + "format": "date-time" + }, + "member_rating": { + "type": ["null", "integer"] + }, + "last_changed": { + "type": ["null", "string"], + "format": "date-time" + }, + "language": { + "type": ["null", "string"] + }, + "vip": { + "type": ["null", "boolean"] + }, + "email_client": { + "type": ["null", "string"] + }, + "location": { + "type": ["null", "object"], + "properties": { + "latitude": { + "type": ["null", "number"] + }, + "longitude": { + "type": ["null", "number"] + }, + "gmtoff": { + "type": ["null", "integer"] + }, + "dstoff": { + "type": ["null", "integer"] + }, + "country_code": { + "type": ["null", "string"] + }, + "timezone": { + "type": ["null", "string"] + } + } + }, + "last_note": { + "type": ["null", "object"], + "properties": { + "note_id": { + "type": ["null", "integer"] + }, + "created_at": { + "type": ["null", "string"], + "format": "date-time" + }, + "created_by": { + "type": ["null", "string"] + }, + "note": { + "type": ["null", "string"] + } + } + }, + "list_id": { + "type": ["null", "string"] + }, + "segment_id": { + "type": ["null", "integer"] + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/segments.json b/source-mailchimp/source_mailchimp/schemas/segments.json new file mode 100644 index 0000000000..3806f69a15 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/segments.json @@ -0,0 +1,57 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "additionalProperties": true, + "required": ["id"], + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": ["null", "string"] + }, + "member_count": { + "type": ["null", "integer"] + }, + "type": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"], + "format": "date-time" + }, + "updated_at": { + "type": ["null", "string"], + "format": "date-time" + }, + "options": { + "type": ["null", "object"], + "properties": { + "match": { + "type": ["null", "string"] + }, + "conditions": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "additionalProperties": true, + "properties": { + "condition_type": { + "type": ["null", "string"] + }, + "field": { + "type": ["null", "string"] + }, + "op": { + "type": ["null", "string"] + } + } + } + } + } + }, + "list_id": { + "type": ["null", "string"] + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/addressMergeSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/addressMergeSegment.json new file mode 100644 index 0000000000..11ce44213a --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/addressMergeSegment.json @@ -0,0 +1,32 @@ +{ + "type": "object", + "title": "Address Merge Field Segment", + "description": "Segment by an address-type merge field.", + "required": ["field", "op"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "AddressMerge", + "enum": ["AddressMerge"] + }, + "field": { + "type": "string", + "title": "Segment Field", + "description": "An address-type merge field to segment.", + "example": "MMERGE3" + }, + "op": { + "type": "string", + "enum": ["contains", "notcontain", "blank", "blank_not"], + "title": "Segment Operator", + "description": "Whether the member's address merge field contains/does not contain a value or is/is not blank.", + "example": "contains" + }, + "value": { + "type": "string", + "title": "Segment Value", + "description": "The value to segment a text merge field with.", + "example": "Atlanta" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/addressZipWithinSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/addressZipWithinSegment.json new file mode 100644 index 0000000000..d66ece7c08 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/addressZipWithinSegment.json @@ -0,0 +1,38 @@ +{ + "type": "object", + "title": "Address/Zip Merge Field Segment", + "description": "Segment by an address-type merge field within a given distance.", + "required": ["field", "op", "value", "extra"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "ZipMerge", + "enum": ["ZipMerge"] + }, + "field": { + "type": "string", + "title": "Segment Field", + "description": "An address or zip-type merge field to segment.", + "example": "MMERGE2" + }, + "op": { + "type": "string", + "enum": ["geoin"], + "title": "Segment Operator", + "description": "Whether the member's address merge field is within a given distance from a city or zip.", + "example": "geoin" + }, + "value": { + "type": "string", + "title": "Segment Value", + "description": "The distance from the city/zip.", + "example": "25" + }, + "extra": { + "type": "string", + "title": "Segment Extra", + "description": "The city or the zip being used to segment against.", + "example": "30318" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/aimSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/aimSegment.json new file mode 100644 index 0000000000..52032da15b --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/aimSegment.json @@ -0,0 +1,32 @@ +{ + "type": "object", + "title": "Aim Segment", + "description": "Segment by interaction with a specific campaign.", + "properties": { + "condition_type": { + "type": "string", + "x-value": "Aim", + "enum": ["Aim"] + }, + "field": { + "type": "string", + "enum": ["aim"], + "title": "Segment Field", + "description": "Segment by interaction with a specific campaign.", + "example": "aim" + }, + "op": { + "type": "string", + "enum": ["open", "click", "sent", "noopen", "noclick", "nosent"], + "title": "Segment Operator", + "description": "The status of the member with regard to their campaign interaction. One of the following: opened, clicked, was sent, didn't open, didn't click, or was not sent.", + "example": "open" + }, + "value": { + "type": "string", + "title": "Segment Data", + "description": "Either the web id value for a specific campaign or 'any' to account for subscribers who have/have not interacted with any campaigns.", + "example": "any" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/automationSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/automationSegment.json new file mode 100644 index 0000000000..cdcb7382ce --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/automationSegment.json @@ -0,0 +1,33 @@ +{ + "type": "object", + "title": "Automation Segment", + "description": "Segment by interaction with an Automation workflow.", + "required": ["field", "op", "value"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "Automation", + "enum": ["Automation"] + }, + "field": { + "type": "string", + "enum": ["automation"], + "title": "Segment Field", + "description": "Segment by interaction with an Automation workflow.", + "example": "automation" + }, + "op": { + "type": "string", + "enum": ["started", "completed", "not_started", "not_completed"], + "title": "Segment Operator", + "description": "The status of the member with regard to the automation workflow. One of the following: has started the workflow, has completed the workflow, has not started the workflow, or has not completed the workflow.", + "example": "started" + }, + "value": { + "type": "string", + "title": "Segment Data", + "description": "The web id for the automation workflow to segment against.", + "example": "2135217" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/birthdayMergeSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/birthdayMergeSegment.json new file mode 100644 index 0000000000..cc79ccb7ad --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/birthdayMergeSegment.json @@ -0,0 +1,32 @@ +{ + "type": "object", + "title": "Birthday Merge Field Segment", + "description": "Segment by a contact's birthday.", + "required": ["field", "op"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "BirthdayMerge", + "enum": ["BirthdayMerge"] + }, + "field": { + "type": "string", + "title": "Segment Field", + "description": "A date merge field to segment.", + "example": "MMERGE4" + }, + "op": { + "type": "string", + "enum": ["is", "not", "blank", "blank_not"], + "title": "Segment Operator", + "description": "Whether the member's birthday merge information is/is not a certain date or is/is not blank.", + "example": "is" + }, + "value": { + "type": "string", + "title": "Segment Value", + "description": "A date to segment against (mm/dd).", + "example": "01/30" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/campaignPollSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/campaignPollSegment.json new file mode 100644 index 0000000000..bfa8d9c6e0 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/campaignPollSegment.json @@ -0,0 +1,33 @@ +{ + "type": "object", + "title": "Poll Activity Segment", + "description": "Segment by poll activity.", + "required": ["field", "op", "value"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "CampaignPoll", + "enum": ["CampaignPoll"] + }, + "field": { + "type": "string", + "enum": ["poll"], + "title": "Segment Field", + "description": "Segment by poll activity.", + "example": "poll" + }, + "op": { + "type": "string", + "enum": ["member", "notmember"], + "title": "Segment Operator", + "description": "Members have/have not interacted with a specific poll in a Mailchimp email.", + "example": "member" + }, + "value": { + "type": "number", + "title": "Segment Operator", + "description": "The id for the poll.", + "example": 409 + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/campaignStatus.json b/source-mailchimp/source_mailchimp/schemas/shared/campaignStatus.json new file mode 100644 index 0000000000..3c7eb614a2 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/campaignStatus.json @@ -0,0 +1,16 @@ +{ + "type": "string", + "title": "Campaign Status", + "description": "The current status of the campaign.", + "enum": [ + "save", + "paused", + "schedule", + "sending", + "sent", + "canceled", + "canceling", + "archived" + ], + "readOnly": true +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/campaignType.json b/source-mailchimp/source_mailchimp/schemas/shared/campaignType.json new file mode 100644 index 0000000000..6784e48359 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/campaignType.json @@ -0,0 +1,5 @@ +{ + "type": "string", + "title": "Campaign Type", + "description": "There are four types of [campaigns](https://mailchimp.com/help/getting-started-with-campaigns/) you can create in Mailchimp. A/B Split campaigns have been deprecated and variate campaigns should be used instead." +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/conversationSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/conversationSegment.json new file mode 100644 index 0000000000..999c601945 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/conversationSegment.json @@ -0,0 +1,33 @@ +{ + "type": "object", + "title": "Conversation Segment", + "description": "Segment by interaction with a campaign via Conversations.", + "required": ["field", "op", "value"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "Conversation", + "enum": ["Conversation"] + }, + "field": { + "type": "string", + "enum": ["conversation"], + "title": "Segment Field", + "description": "Segment by interaction with a campaign via Conversations.", + "example": "conversation" + }, + "op": { + "type": "string", + "enum": ["member", "notmember"], + "title": "Segment Operator", + "description": "The status of a member's interaction with a conversation. One of the following: has replied or has not replied.", + "example": "member" + }, + "value": { + "type": "string", + "title": "Segment Data", + "description": "The web id value for a specific campaign or 'any' to account for subscribers who have/have not interacted with any campaigns.", + "example": "any" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/countryStateSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/countryStateSegment.json new file mode 100644 index 0000000000..1eebe6505a --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/countryStateSegment.json @@ -0,0 +1,38 @@ +{ + "type": "object", + "title": "Location-Based Segment", + "description": "Segment by a specific country or US state.", + "required": ["field", "op", "value"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "IPGeoCountryState", + "enum": ["IPGeoCountryState"] + }, + "field": { + "type": "string", + "enum": ["ipgeo"], + "title": "Segment Field", + "description": "Segmenting subscribers who are within a specific location.", + "example": "ipgeo" + }, + "op": { + "type": "string", + "enum": [ + "ipgeocountry", + "ipgeonotcountry", + "ipgeostate", + "ipgeonotstate" + ], + "title": "Segment Operator", + "description": "Segment members who are within a specific country or US state.", + "example": "ipgeocountry" + }, + "value": { + "type": "string", + "title": "Segment Data", + "description": "The two-letter country code or US state abbreviation.", + "example": "US" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/dateMergeSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/dateMergeSegment.json new file mode 100644 index 0000000000..ff04cc1b25 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/dateMergeSegment.json @@ -0,0 +1,32 @@ +{ + "type": "object", + "title": "Date Merge Field Segment", + "description": "Segment by a given date merge field.", + "required": ["field", "op"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "DateMerge", + "enum": ["DateMerge"] + }, + "field": { + "type": "string", + "title": "Segment Field", + "description": "A date merge field to segment.", + "example": "MMERGE5" + }, + "op": { + "type": "string", + "enum": ["is", "not", "less", "blank", "blank_not", "greater"], + "title": "Segment Operator", + "description": "Whether the member's merge information is/is not, is greater/less than a value or is/is not blank.", + "example": "is" + }, + "value": { + "type": "string", + "title": "Segment Value", + "description": "A date to segment against.", + "example": "01/30/2015" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/dateSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/dateSegment.json new file mode 100644 index 0000000000..ded5777752 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/dateSegment.json @@ -0,0 +1,48 @@ +{ + "type": "object", + "title": "Date Segment", + "description": "Segment by a specific date field.", + "required": ["field", "op", "value"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "Date", + "enum": ["Date"] + }, + "field": { + "type": "string", + "enum": ["timestamp_opt", "info_changed", "ecomm_date"], + "title": "Segment Field", + "description": "The type of date field to segment on: The opt-in time for a signup, the date the subscriber was last updated, or the date of their last ecomm purchase.", + "example": "timestamp_opt" + }, + "op": { + "type": "string", + "enum": [ + "greater", + "less", + "is", + "not", + "blank", + "blank_not", + "within", + "notwithin" + ], + "title": "Segment Operator", + "description": "When the event took place: Before, after, is a specific date, is not a specific date, is blank, or is not blank.", + "example": "greater" + }, + "value": { + "type": "string", + "title": "Segment Data", + "description": "What type of data to segment on: a specific date, a specific campaign, or the last campaign sent.", + "example": "date" + }, + "extra": { + "type": "string", + "title": "Segment Extra Value", + "description": "When segmenting on 'date' or 'campaign', the date for the segment formatted as YYYY-MM-DD or the web id for the campaign.", + "example": "2015-01-30" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/dropdownRadioMergeSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/dropdownRadioMergeSegment.json new file mode 100644 index 0000000000..f06f3347f6 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/dropdownRadioMergeSegment.json @@ -0,0 +1,32 @@ +{ + "type": "object", + "title": "Dropdown/Radio Merge Field Segment", + "description": "An individual segment condition", + "required": ["field", "op"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "SelectMerge", + "enum": ["SelectMerge"] + }, + "field": { + "type": "string", + "title": "Segment Field", + "description": "A merge field to segment.", + "example": "MMERGE6" + }, + "op": { + "type": "string", + "enum": ["is", "not", "blank", "blank_not", "notcontain", "contains"], + "title": "Segment Operator", + "description": "Whether the member's merge information is/is not a value or is/is not blank.", + "example": "is" + }, + "value": { + "type": "string", + "title": "Segment Value", + "description": "The value to segment a text merge field with.", + "example": "Second Choice" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/ecommCategorySegment.json b/source-mailchimp/source_mailchimp/schemas/shared/ecommCategorySegment.json new file mode 100644 index 0000000000..af1dafc8dc --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/ecommCategorySegment.json @@ -0,0 +1,32 @@ +{ + "type": "object", + "title": "Ecommerce Category Segment", + "description": "Segment by purchases in specific items or categories.", + "properties": { + "condition_type": { + "type": "string", + "x-value": "EcommCategory", + "enum": ["EcommCategory"] + }, + "field": { + "type": "string", + "enum": ["ecomm_cat", "ecomm_prod"], + "title": "Segment Field", + "description": "Segment by purchases in specific items or categories.", + "example": "ecomm_cat" + }, + "op": { + "type": "string", + "enum": ["is", "not", "contains", "notcontain", "starts", "ends"], + "title": "Segment Operator", + "description": "A member who has purchased from a category/specific item that is/is not a specific name, where the category/item name contains/doesn't contain a specific phrase or string, or a category/item name that starts/ends with a string.", + "example": "is" + }, + "value": { + "type": "string", + "title": "Segment Data", + "description": "The ecommerce category/item information.", + "example": "Product" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/ecommNumberSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/ecommNumberSegment.json new file mode 100644 index 0000000000..aa2edb9e49 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/ecommNumberSegment.json @@ -0,0 +1,38 @@ +{ + "type": "object", + "title": "Ecommerce Number Segment", + "description": "Segment by average spent total, number of orders, total number of products purchased, or average number of products per order.", + "required": ["field", "op", "value"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "EcommNumber", + "enum": ["EcommNumber"] + }, + "field": { + "type": "string", + "enum": [ + "ecomm_spent_avg", + "ecomm_orders", + "ecomm_prod_all", + "ecomm_avg_ord" + ], + "title": "Segment Field", + "description": "Segment by average spent total, number of orders, total number of products purchased, or average number of products per order.", + "example": "ecomm_orders" + }, + "op": { + "type": "string", + "enum": ["is", "not", "greater", "less"], + "title": "Segment Operator", + "description": "Members who have spent exactly, have not spent exactly, spent more, or spent less than the segment value.", + "example": "greater" + }, + "value": { + "type": "number", + "title": "Segment Operator", + "description": "Members who have spent exactly, have not spent exactly, spent more, or spent less than this amount.", + "example": 42 + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/ecommPurchasedSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/ecommPurchasedSegment.json new file mode 100644 index 0000000000..5d4e3823f5 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/ecommPurchasedSegment.json @@ -0,0 +1,26 @@ +{ + "type": "object", + "title": "Ecommerce Purchased Segment", + "description": "Segment by whether someone has purchased anything.", + "properties": { + "condition_type": { + "type": "string", + "x-value": "EcommPurchased", + "enum": ["EcommPurchased"] + }, + "field": { + "type": "string", + "enum": ["ecomm_purchased"], + "title": "Segment Field", + "description": "Segment by whether someone has purchased anything.", + "example": "ecomm_purchased" + }, + "op": { + "type": "string", + "enum": ["member", "notmember"], + "title": "Segment Operator", + "description": "Members who have have ('member') or have not ('notmember') purchased.", + "example": "member" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/ecommSpentSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/ecommSpentSegment.json new file mode 100644 index 0000000000..39d192a6a2 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/ecommSpentSegment.json @@ -0,0 +1,32 @@ +{ + "type": "object", + "title": "Ecommerce Spent Segment", + "description": "Segment by amount spent on a single order or across all orders.", + "properties": { + "condition_type": { + "type": "string", + "x-value": "EcommSpent", + "enum": ["EcommSpent"] + }, + "field": { + "type": "string", + "enum": ["ecomm_spent_one", "ecomm_spent_all"], + "title": "Segment Field", + "description": "Segment by amount spent on a single order or across all orders.", + "example": "ecomm_spent_one" + }, + "op": { + "type": "string", + "enum": ["greater", "less"], + "title": "Segment Operator", + "description": "Members who have spent 'more' or 'less' than then specified value.", + "example": "greater" + }, + "value": { + "type": "integer", + "title": "Segment Data", + "description": "The total amount a member spent.", + "example": 42 + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/ecommStoreSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/ecommStoreSegment.json new file mode 100644 index 0000000000..73d62796d5 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/ecommStoreSegment.json @@ -0,0 +1,32 @@ +{ + "type": "object", + "title": "Ecommerce Purchased Store Segment", + "description": "Segment by purchases from a specific store.", + "properties": { + "condition_type": { + "type": "string", + "x-value": "EcommStore", + "enum": ["EcommStore"] + }, + "field": { + "type": "string", + "enum": ["ecomm_store"], + "title": "Segment Field", + "description": "Segment by purchases from a specific store.", + "example": "ecomm_store" + }, + "op": { + "type": "string", + "enum": ["is", "not"], + "title": "Segment Operator", + "description": "Members who have or have not purchased from a specific store.", + "example": "is" + }, + "value": { + "type": "string", + "title": "Segment Operator", + "description": "The store id to segment against.", + "example": "289" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/emailClientSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/emailClientSegment.json new file mode 100644 index 0000000000..8f3b1d97f2 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/emailClientSegment.json @@ -0,0 +1,33 @@ +{ + "type": "object", + "title": "Email Client Segment", + "description": "Segment by use of a particular email client.", + "required": ["field", "op", "value"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "EmailClient", + "enum": ["EmailClient"] + }, + "field": { + "type": "string", + "enum": ["email_client"], + "title": "Segment Field", + "description": "Segment by use of a particular email client.", + "example": "email_client" + }, + "op": { + "type": "string", + "enum": ["client_is", "client_not"], + "title": "Segment Operator", + "description": "The operation to determine whether we select clients that match the value, or clients that do not match the value.", + "example": "client_is" + }, + "value": { + "type": "string", + "title": "Segment Data", + "description": "The name of the email client.", + "example": "Gmail" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/emailSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/emailSegment.json new file mode 100644 index 0000000000..1ae58bf836 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/emailSegment.json @@ -0,0 +1,41 @@ +{ + "type": "object", + "title": "Email Segment", + "description": "Segment by email address.", + "required": ["field", "op"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "EmailAddress", + "enum": ["EmailAddress"] + }, + "field": { + "type": "string", + "enum": ["merge0", "EMAIL"], + "title": "Segment Field", + "description": "Segmenting based off of a subscriber's email address.", + "example": "EMAIL" + }, + "op": { + "type": "string", + "enum": [ + "is", + "not", + "contains", + "notcontain", + "starts", + "ends", + "greater", + "less" + ], + "title": "Segment Operator", + "description": "Whether the email address is/not exactly, contains/doesn't contain, starts/ends with a string." + }, + "value": { + "type": "string", + "title": "Segment Value", + "description": "The value to compare the email against.", + "example": "urist.mcvankab@freddiesjokes.com" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/fuzzySegment.json b/source-mailchimp/source_mailchimp/schemas/shared/fuzzySegment.json new file mode 100644 index 0000000000..94135fca3b --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/fuzzySegment.json @@ -0,0 +1,33 @@ +{ + "type": "object", + "title": "Similar Subscribers Segment Member Segment", + "description": "Segment by similar subscribers.", + "required": ["field", "op", "value"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "FuzzySegment", + "enum": ["FuzzySegment"] + }, + "field": { + "type": "string", + "enum": ["fuzzy_segment"], + "title": "Segment Field", + "description": "Segment by similar subscribers.", + "example": "fuzzy_segment" + }, + "op": { + "type": "string", + "enum": ["fuzzy_is", "fuzzy_not"], + "title": "Segment Operator", + "description": "Members who are/are not apart of a 'similar subscribers' segment.", + "example": "fuzzy_is" + }, + "value": { + "type": "number", + "title": "Segment Operator", + "description": "The id for the 'similar subscribers' segment.", + "example": 48433 + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/geoInSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/geoInSegment.json new file mode 100644 index 0000000000..a56c67b769 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/geoInSegment.json @@ -0,0 +1,51 @@ +{ + "type": "object", + "title": "Geolocation Segment", + "description": "Segment by a specific geographic region.", + "required": ["field", "op", "value", "addr", "lat", "lng"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "IPGeoIn", + "enum": ["IPGeoIn"] + }, + "field": { + "type": "string", + "enum": ["ipgeo"], + "title": "Segment Field", + "description": "Segmenting subscribers who are within a specific location.", + "example": "ipgeo" + }, + "op": { + "type": "string", + "enum": ["ipgeoin", "ipgeonotin"], + "title": "Segment Operator", + "description": "Segment members who are within a specific geographic region.", + "example": "ipgeoin" + }, + "value": { + "type": "integer", + "title": "Segment Data", + "description": "The radius of the target location.", + "example": 42 + }, + "addr": { + "type": "string", + "title": "Segment Location Address", + "description": "The address of the target location.", + "example": "Atlanta, GA, USA" + }, + "lat": { + "type": "string", + "title": "Segment Location Latitude", + "description": "The latitude of the target location.", + "example": "33.7489954" + }, + "lng": { + "type": "string", + "title": "Segment Location Longitude", + "description": "The longitude of the target location.", + "example": "-84.3879824" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/goalActivitySegment.json b/source-mailchimp/source_mailchimp/schemas/shared/goalActivitySegment.json new file mode 100644 index 0000000000..bf2263238c --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/goalActivitySegment.json @@ -0,0 +1,39 @@ +{ + "type": "object", + "title": "Goal Activity Segment", + "description": "Segment by Goal activity.", + "required": ["field", "op", "value"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "GoalActivity", + "enum": ["GoalActivity"] + }, + "field": { + "type": "string", + "enum": ["goal"], + "title": "Segment Field", + "description": "Segment by Goal activity.", + "example": "goal" + }, + "op": { + "type": "string", + "enum": [ + "is", + "goal_not", + "contains", + "goal_notcontain", + "starts", + "ends" + ], + "title": "Segment Operator", + "description": "Whether the website URL is/not exactly, contains/doesn't contain, starts with/ends with a string.", + "example": "is" + }, + "value": { + "type": "string", + "title": "Segment Value", + "description": "The URL to check Goal activity against." + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/goalTimestampSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/goalTimestampSegment.json new file mode 100644 index 0000000000..b811092ead --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/goalTimestampSegment.json @@ -0,0 +1,33 @@ +{ + "type": "object", + "title": "Goal Timestamp Segment", + "description": "Segment by most recent interaction with a website.", + "required": ["field", "op", "value"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "GoalTimestamp", + "enum": ["GoalTimestamp"] + }, + "field": { + "type": "string", + "enum": ["goal_last_visited"], + "title": "Segment Field", + "description": "Segment by most recent interaction with a website.", + "example": "goal_last_visited" + }, + "op": { + "type": "string", + "enum": ["greater", "less", "is"], + "title": "Segment Operator", + "description": "Whether the website activity happened after, before, or at a given timestamp.", + "example": "greater" + }, + "value": { + "type": "string", + "title": "Segment Value", + "description": "The date to check Goal activity against.", + "example": "2015-07-20 19:45:21" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/interestSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/interestSegment.json new file mode 100644 index 0000000000..cfebde7cb1 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/interestSegment.json @@ -0,0 +1,38 @@ +{ + "type": "object", + "title": "Interests Segment", + "description": "Segment by an interest group merge field.", + "properties": { + "condition_type": { + "type": "string", + "x-value": "Interests", + "enum": ["Interests"] + }, + "field": { + "type": "string", + "title": "Segment Field", + "description": "Segmenting based on interest group information. This should start with 'interests-' followed by the grouping id. Ex. 'interests-123'.", + "example": "interests-123" + }, + "op": { + "type": "string", + "enum": [ + "interestcontains", + "interestcontainsall", + "interestnotcontains" + ], + "title": "Segment Operator", + "description": "Whether the member is a part of one, all, or none of the groups.", + "example": "interestcontains" + }, + "value": { + "type": "array", + "title": "Segment Value", + "description": "An array containing strings, each representing a group id.", + "items": { + "type": "string", + "example": ["44401", "44405", "44409"] + } + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/ipGeoInZipSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/ipGeoInZipSegment.json new file mode 100644 index 0000000000..a69999ab15 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/ipGeoInZipSegment.json @@ -0,0 +1,39 @@ +{ + "type": "object", + "title": "US Zip Code Segment", + "description": "Segment by a specific US ZIP code.", + "required": ["field", "op", "value", "extra"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "IPGeoInZip", + "enum": ["IPGeoInZip"] + }, + "field": { + "type": "string", + "enum": ["ipgeo"], + "title": "Segment Field", + "description": "Segmenting subscribers who are within a specific location.", + "example": "ipgeo" + }, + "op": { + "type": "string", + "enum": ["ipgeoinzip"], + "title": "Segment Operator", + "description": "Segment members who are within a specific US zip code.", + "example": "ipgeoinzip" + }, + "value": { + "type": "integer", + "title": "Segment Data", + "description": "The radius of the target location.", + "example": 25 + }, + "extra": { + "type": "integer", + "title": "Extra Data", + "description": "The zip code to segment against.", + "example": 30318 + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/languageSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/languageSegment.json new file mode 100644 index 0000000000..d9f91b6eab --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/languageSegment.json @@ -0,0 +1,33 @@ +{ + "type": "object", + "title": "Language Segment", + "description": "Segment by language.", + "required": ["field", "op", "value"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "Language", + "enum": ["Language"] + }, + "field": { + "type": "string", + "enum": ["language"], + "title": "Segment Field", + "description": "Segmenting based off of a subscriber's language.", + "example": "language" + }, + "op": { + "type": "string", + "enum": ["is", "not"], + "title": "Segment Operator", + "description": "Whether the member's language is or is not set to a specific language.", + "example": "is" + }, + "value": { + "type": "string", + "title": "Segment Data", + "description": "A two-letter language identifier.", + "example": "en" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/memberRatingSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/memberRatingSegment.json new file mode 100644 index 0000000000..4933d6a8c0 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/memberRatingSegment.json @@ -0,0 +1,33 @@ +{ + "type": "object", + "title": "Member Rating Segment", + "description": "Segment by member rating.", + "required": ["field", "op", "value"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "MemberRating", + "enum": ["MemberRating"] + }, + "field": { + "type": "string", + "enum": ["rating"], + "title": "Segment Field", + "description": "Segment by member rating.", + "example": "rating" + }, + "op": { + "type": "string", + "enum": ["is", "not", "greater", "less"], + "title": "Segment Operator", + "description": "Members who have have a rating that is/not exactly a given number or members who have a rating greater/less than a given number.", + "example": "greater" + }, + "value": { + "type": "number", + "title": "Segment Operator", + "description": "The star rating number to segment against.", + "example": 4 + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/newSubscribers.json b/source-mailchimp/source_mailchimp/schemas/shared/newSubscribers.json new file mode 100644 index 0000000000..d9355aa707 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/newSubscribers.json @@ -0,0 +1,29 @@ +{ + "type": "object", + "title": "New Subscribers Prebuilt Segment", + "description": "Segment by when people subscribed.", + "properties": { + "condition_type": { + "type": "string", + "x-value": "NewSubscribers", + "enum": ["NewSubscribers"] + }, + "field": { + "type": "string", + "enum": ["timestamp_opt"], + "title": "Segment Field", + "description": "Segment by when people subscribed." + }, + "op": { + "type": "string", + "enum": ["date_within"], + "title": "Segment Operator", + "description": "Whe the event took place, namely within a time frame." + }, + "value": { + "type": "string", + "title": "Segment Data", + "description": "What type of data to segment on: a specific date, a specific campaign, or the last campaign sent." + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/predictedAgeSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/predictedAgeSegment.json new file mode 100644 index 0000000000..a7dda4a8e4 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/predictedAgeSegment.json @@ -0,0 +1,33 @@ +{ + "type": "object", + "title": "Predicted Age Segment", + "description": "Segment by predicted age.", + "required": ["field", "op", "value"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "PredictedAge", + "enum": ["PredictedAge"] + }, + "field": { + "type": "string", + "enum": ["predicted_age_range"], + "title": "Segment Field", + "description": "Segment by predicted age." + }, + "op": { + "type": "string", + "enum": ["is"], + "title": "Segment Operator", + "description": "Members who are/not the exact criteria listed.", + "example": "is" + }, + "value": { + "type": "string", + "enum": ["18-24", "25-34", "35-44", "45-54", "55-64", "65+"], + "title": "Segment Operator", + "description": "The predicted age to segment.", + "example": "female" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/predictedGenderSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/predictedGenderSegment.json new file mode 100644 index 0000000000..0f54255083 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/predictedGenderSegment.json @@ -0,0 +1,33 @@ +{ + "type": "object", + "title": "Predicted Gender Segment", + "description": "Segment by predicted gender.", + "required": ["field", "op", "value"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "PredictedGender", + "enum": ["PredictedGender"] + }, + "field": { + "type": "string", + "enum": ["predicted_gender"], + "title": "Segment Field", + "description": "Segment by predicted gender." + }, + "op": { + "type": "string", + "enum": ["is", "not"], + "title": "Segment Operator", + "description": "Members who are/not the exact criteria listed.", + "example": "is" + }, + "value": { + "type": "string", + "enum": ["male", "female"], + "title": "Segment Operator", + "description": "The predicted gender to segment.", + "example": "female" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/segmentCondition.json b/source-mailchimp/source_mailchimp/schemas/shared/segmentCondition.json new file mode 100644 index 0000000000..eba1935986 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/segmentCondition.json @@ -0,0 +1,135 @@ +{ + "type": "array", + "title": "Segment Type", + "description": "Segment match conditions. There are multiple possible types, see the [condition types documentation](https://mailchimp.com/developer/marketing/docs/alternative-schemas/#segment-condition-schemas).", + "items": { + "x-discriminator": { + "propertyName": "condition_type" + }, + "oneOf": [ + { + "$ref": "aimSegment.json" + }, + { + "$ref": "automationSegment.json" + }, + { + "$ref": "campaignPollSegment.json" + }, + { + "$ref": "conversationSegment.json" + }, + { + "$ref": "dateSegment.json" + }, + { + "$ref": "emailClientSegment.json" + }, + { + "$ref": "languageSegment.json" + }, + { + "$ref": "memberRatingSegment.json" + }, + { + "$ref": "signupSourceSegment.json" + }, + { + "$ref": "surveyMonkeySegment.json" + }, + { + "$ref": "vipSegment.json" + }, + { + "$ref": "interestSegment.json" + }, + { + "$ref": "ecommCategorySegment.json" + }, + { + "$ref": "ecommNumberSegment.json" + }, + { + "$ref": "ecommPurchasedSegment.json" + }, + { + "$ref": "ecommSpentSegment.json" + }, + { + "$ref": "ecommStoreSegment.json" + }, + { + "$ref": "goalActivitySegment.json" + }, + { + "$ref": "goalTimestampSegment.json" + }, + { + "$ref": "fuzzySegment.json" + }, + { + "$ref": "staticSegment.json" + }, + { + "$ref": "countryStateSegment.json" + }, + { + "$ref": "geoInSegment.json" + }, + { + "$ref": "ipGeoInZipSegment.json" + }, + { + "$ref": "unknownSegment.json" + }, + { + "$ref": "zipSegment.json" + }, + { + "$ref": "socialAgeSegment.json" + }, + { + "$ref": "socialGenderSegment.json" + }, + { + "$ref": "socialInfluenceSegment.json" + }, + { + "$ref": "socialNetworkSegment.json" + }, + { + "$ref": "socialNetworkFollowSegment.json" + }, + { + "$ref": "addressMergeSegment.json" + }, + { + "$ref": "addressZipWithinSegment.json" + }, + { + "$ref": "birthdayMergeSegment.json" + }, + { + "$ref": "dateMergeSegment.json" + }, + { + "$ref": "dropdownRadioMergeSegment.json" + }, + { + "$ref": "textOrNumberMergeSegment.json" + }, + { + "$ref": "emailSegment.json" + }, + { + "$ref": "predictedGenderSegment.json" + }, + { + "$ref": "predictedAgeSegment.json" + }, + { + "$ref": "newSubscribers.json" + } + ] + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/segmentationOptions.json b/source-mailchimp/source_mailchimp/schemas/shared/segmentationOptions.json new file mode 100644 index 0000000000..18292c74cd --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/segmentationOptions.json @@ -0,0 +1,27 @@ +{ + "type": "object", + "title": "Segment Options", + "description": "An object representing all segmentation options. This object should contain a `saved_segment_id` to use an existing segment, or you can create a new segment by including both `match` and `conditions` options.", + "properties": { + "saved_segment_id": { + "type": "integer", + "title": "Saved Segment ID", + "description": "The id for an existing saved segment." + }, + "prebuilt_segment_id": { + "type": "string", + "title": "Prebuilt Segment Id", + "description": "The prebuilt segment id, if a prebuilt segment has been designated for this campaign.", + "example": "subscribers-female" + }, + "match": { + "type": "string", + "title": "Match Type", + "description": "Segment match type.", + "enum": ["any", "all"] + }, + "conditions": { + "$ref": "segmentCondition.json" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/signupSourceSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/signupSourceSegment.json new file mode 100644 index 0000000000..d9f6f91ff5 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/signupSourceSegment.json @@ -0,0 +1,33 @@ +{ + "type": "object", + "title": "Signup Source Segment", + "description": "Segment by signup source.", + "required": ["field", "condition_type", "op"], + "properties": { + "condition_type": { + "type": "string", + "enum": ["SignupSource"], + "x-value": "SignupSource", + "title": "Type" + }, + "field": { + "type": "string", + "enum": ["source"], + "title": "Segment Field", + "example": "source" + }, + "op": { + "type": "string", + "enum": ["source_is", "source_not"], + "title": "Segment Operator", + "description": "Whether the member's signup source was/was not a particular value.", + "example": "source_is" + }, + "value": { + "type": "string", + "title": "Segment Data", + "description": "The signup source.", + "example": "List Import" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/socialAgeSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/socialAgeSegment.json new file mode 100644 index 0000000000..2be004d924 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/socialAgeSegment.json @@ -0,0 +1,34 @@ +{ + "type": "object", + "title": "Social Profiles Age Segment", + "description": "Segment by age ranges in Social Profiles data.", + "required": ["field", "op", "value"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "SocialAge", + "enum": ["SocialAge"] + }, + "field": { + "type": "string", + "enum": ["social_age"], + "title": "Segment Field", + "description": "Segment by age ranges in Social Profiles data.", + "example": "social_age" + }, + "op": { + "type": "string", + "enum": ["is", "not"], + "title": "Segment Operator", + "description": "Members who are/not the exact criteria listed.", + "example": "is" + }, + "value": { + "type": "string", + "enum": ["18-24", "25-34", "35-54", "55+"], + "title": "Segment Operator", + "description": "The age range to segment.", + "example": "35-54" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/socialGenderSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/socialGenderSegment.json new file mode 100644 index 0000000000..fcbb9d6508 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/socialGenderSegment.json @@ -0,0 +1,34 @@ +{ + "type": "object", + "title": "Social Profiles Gender Segment", + "description": "Segment by listed gender in Social Profiles data.", + "required": ["field", "op", "value"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "SocialGender", + "enum": ["SocialGender"] + }, + "field": { + "type": "string", + "enum": ["social_gender"], + "title": "Segment Field", + "description": "Segment by listed gender in Social Profiles data.", + "example": "social_gender" + }, + "op": { + "type": "string", + "enum": ["is", "not"], + "title": "Segment Operator", + "description": "Members who are/not the exact criteria listed.", + "example": "is" + }, + "value": { + "type": "string", + "enum": ["male", "female"], + "title": "Segment Operator", + "description": "The Social Profiles gender to segment.", + "example": "female" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/socialInfluenceSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/socialInfluenceSegment.json new file mode 100644 index 0000000000..959bca99d9 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/socialInfluenceSegment.json @@ -0,0 +1,33 @@ +{ + "type": "object", + "title": "Social Profiles Influence Segment", + "description": "Segment by influence rating in Social Profiles data.", + "required": ["field", "op", "value"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "SocialInfluence", + "enum": ["SocialInfluence"] + }, + "field": { + "type": "string", + "enum": ["social_influence"], + "title": "Segment Field", + "description": "Segment by influence rating in Social Profiles data.", + "example": "social_influence" + }, + "op": { + "type": "string", + "enum": ["is", "not", "greater", "less"], + "title": "Segment Operator", + "description": "Members who have a rating that is/not or greater/less than the rating provided.", + "example": "greater" + }, + "value": { + "type": "number", + "title": "Segment Operator", + "description": "The Social Profiles influence rating to segment.", + "example": 2 + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/socialNetworkFollowSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/socialNetworkFollowSegment.json new file mode 100644 index 0000000000..2c239fb193 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/socialNetworkFollowSegment.json @@ -0,0 +1,34 @@ +{ + "type": "object", + "title": "Social Profiles Social Network Follow Segment", + "description": "Segment by social network in Social Profiles data.", + "required": ["field", "op", "value"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "SocialNetworkFollow", + "enum": ["SocialNetworkFollow"] + }, + "field": { + "type": "string", + "enum": ["social_network"], + "title": "Segment Field", + "description": "Segment by social network in Social Profiles data.", + "example": "social_network" + }, + "op": { + "type": "string", + "enum": ["follow", "notfollow"], + "title": "Segment Operator", + "description": "Members who are/not following a linked account on a given social network.", + "example": "follow" + }, + "value": { + "type": "string", + "enum": ["twitter_follow"], + "title": "Segment Operator", + "description": "The social network to segment against.", + "example": "twitter_follow" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/socialNetworkSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/socialNetworkSegment.json new file mode 100644 index 0000000000..f28908f4ce --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/socialNetworkSegment.json @@ -0,0 +1,46 @@ +{ + "type": "object", + "title": "Social Profiles Social Network Segment", + "description": "Segment by social network in Social Profiles data.", + "required": ["field", "op", "value"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "SocialNetworkMember", + "enum": ["SocialNetworkMember"] + }, + "field": { + "type": "string", + "enum": ["social_network"], + "title": "Segment Field", + "description": "Segment by social network in Social Profiles data.", + "example": "social_network" + }, + "op": { + "type": "string", + "enum": ["member", "notmember"], + "title": "Segment Operator", + "description": "Members who are/not on a given social network.", + "example": "member" + }, + "value": { + "type": "string", + "enum": [ + "twitter", + "facebook", + "linkedin", + "flickr", + "foursquare", + "lastfm", + "myspace", + "quora", + "vimeo", + "yelp", + "youtube" + ], + "title": "Segment Operator", + "description": "The social network to segment against.", + "example": "twitter" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/staticSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/staticSegment.json new file mode 100644 index 0000000000..c7c1bbc781 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/staticSegment.json @@ -0,0 +1,33 @@ +{ + "type": "object", + "title": "Static Segment Member Segment", + "description": "Segment by a given static segment.", + "required": ["field", "op", "value"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "StaticSegment", + "enum": ["StaticSegment"] + }, + "field": { + "type": "string", + "enum": ["static_segment"], + "title": "Segment Field", + "description": "Segment by a given static segment.", + "example": "static_segment" + }, + "op": { + "type": "string", + "enum": ["static_is", "static_not"], + "title": "Segment Operator", + "description": "Members who are/are not apart of a static segment.", + "example": "static_is" + }, + "value": { + "type": "number", + "title": "Segment Operator", + "description": "The id for the static segment.", + "example": 48433 + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/surveyMonkeySegment.json b/source-mailchimp/source_mailchimp/schemas/shared/surveyMonkeySegment.json new file mode 100644 index 0000000000..c50a402c27 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/surveyMonkeySegment.json @@ -0,0 +1,33 @@ +{ + "type": "object", + "title": "SurveyMonkey Segment", + "description": "Segment by interaction with a SurveyMonkey survey.", + "required": ["field", "op", "value"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "SurveyMonkey", + "enum": ["SurveyMonkey"] + }, + "field": { + "type": "string", + "enum": ["survey_monkey"], + "title": "Segment Field", + "description": "Segment by interaction with a SurveyMonkey survey.", + "example": "survey_monkey" + }, + "op": { + "type": "string", + "enum": ["started", "completed", "not_started", "not_completed"], + "title": "Segment Operator", + "description": "The status of the member with regard to the survey. One of the following: has started the survey, has completed the survey, has not started the survey, or has not completed the survey.", + "example": "started" + }, + "value": { + "type": "string", + "title": "Survey ID", + "description": "The unique ID of the SurveyMonkey survey.", + "example": "32179586" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/textOrNumberMergeSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/textOrNumberMergeSegment.json new file mode 100644 index 0000000000..a313e70810 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/textOrNumberMergeSegment.json @@ -0,0 +1,43 @@ +{ + "type": "object", + "title": "Text or Number Merge Field Segment", + "description": "Segment by a given text or number merge field.", + "required": ["field", "op"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "TextMerge", + "enum": ["TextMerge"] + }, + "field": { + "type": "string", + "title": "Segment Field", + "description": "A text or number merge field to segment.", + "example": "MMERGE7" + }, + "op": { + "type": "string", + "enum": [ + "is", + "not", + "contains", + "notcontain", + "starts", + "ends", + "greater", + "less", + "blank", + "blank_not" + ], + "title": "Segment Operator", + "description": "Whether the member's merge information is/is not, contains/does not contain, starts/ends with, or is greater/less than a value", + "example": "contains" + }, + "value": { + "type": "string", + "title": "Segment Value", + "description": "The value to segment a text or number merge field with.", + "example": "Freddie's Jokes" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/unknownSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/unknownSegment.json new file mode 100644 index 0000000000..008cf86dc3 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/unknownSegment.json @@ -0,0 +1,27 @@ +{ + "type": "object", + "title": "Unknown Location-Based Segment", + "description": "Segment members whose location information is unknown.", + "required": ["field", "op"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "IPGeoUnknown", + "enum": ["IPGeoUnknown"] + }, + "field": { + "type": "string", + "enum": ["ipgeo"], + "title": "Segment Field", + "description": "Segmenting subscribers who are within a specific location.", + "example": "ipgeo" + }, + "op": { + "type": "string", + "enum": ["ipgeounknown"], + "title": "Segment Operator", + "description": "Segment members for which location information is unknown.", + "example": "ipgeounknown" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/vipSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/vipSegment.json new file mode 100644 index 0000000000..08664d5178 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/vipSegment.json @@ -0,0 +1,27 @@ +{ + "type": "object", + "title": "VIP Segment", + "description": "Segment by VIP status.", + "required": ["field", "op"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "VIP", + "enum": ["VIP"] + }, + "field": { + "type": "string", + "enum": ["gmonkey"], + "title": "Segment Field", + "description": "Segment by VIP status.", + "example": "gmonkey" + }, + "op": { + "type": "string", + "enum": ["member", "notmember"], + "title": "Segment Operator", + "description": "Whether the member is or is not marked as VIP.", + "example": "member" + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/shared/zipSegment.json b/source-mailchimp/source_mailchimp/schemas/shared/zipSegment.json new file mode 100644 index 0000000000..78f462f529 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/shared/zipSegment.json @@ -0,0 +1,33 @@ +{ + "type": "object", + "title": "Zip Code Location-Based Segment", + "description": "Segment by a specific US ZIP code.", + "required": ["field", "op", "value"], + "properties": { + "condition_type": { + "type": "string", + "x-value": "IPGeoZip", + "enum": ["IPGeoZip"] + }, + "field": { + "type": "string", + "enum": ["ipgeo"], + "title": "Segment Field", + "description": "Segmenting subscribers who are within a specific location.", + "example": "ipgeo" + }, + "op": { + "type": "string", + "enum": ["ipgeoiszip", "ipgeonotzip"], + "title": "Segment Operator", + "description": "Segment members who are/are not within a specific US zip code.", + "example": "ipgeonotzip" + }, + "value": { + "type": "integer", + "title": "Segment Data", + "description": "The 5-digit zip code.", + "example": 30318 + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/tags.json b/source-mailchimp/source_mailchimp/schemas/tags.json new file mode 100644 index 0000000000..cb86990c71 --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/tags.json @@ -0,0 +1,16 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "required": ["id"], + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": ["null", "string"] + }, + "list_id": { + "type": ["null", "string"] + } + } +} diff --git a/source-mailchimp/source_mailchimp/schemas/unsubscribes.json b/source-mailchimp/source_mailchimp/schemas/unsubscribes.json new file mode 100644 index 0000000000..0ceccd7e2e --- /dev/null +++ b/source-mailchimp/source_mailchimp/schemas/unsubscribes.json @@ -0,0 +1,37 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "additionalProperties": true, + "required": ["campaign_id", "email_id", "timestamp"], + "properties": { + "email_id": { + "type": "string" + }, + "email_address": { + "type": ["null", "string"] + }, + "merge_fields": { + "type": ["null", "object"], + "additionalProperties": true + }, + "vip": { + "type": ["null", "boolean"] + }, + "timestamp": { + "type": "string", + "format": "date-time" + }, + "reason": { + "type": ["null", "string"] + }, + "campaign_id": { + "type": "string" + }, + "list_id": { + "type": ["null", "string"] + }, + "list_is_active": { + "type": ["null", "boolean"] + } + } +} diff --git a/source-mailchimp/source_mailchimp/source.py b/source-mailchimp/source_mailchimp/source.py new file mode 100644 index 0000000000..0edf00993e --- /dev/null +++ b/source-mailchimp/source_mailchimp/source.py @@ -0,0 +1,149 @@ +# +# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# + + +import base64 +import re +from typing import Any, List, Mapping, Tuple + +import pendulum +import requests +from airbyte_cdk import AirbyteLogger +from airbyte_cdk.sources import AbstractSource +from airbyte_cdk.sources.streams import Stream +from airbyte_cdk.sources.streams.http.auth import TokenAuthenticator +from pendulum.parsing.exceptions import ParserError +from requests.auth import AuthBase + +from .streams import ( + Automations, + Campaigns, + EmailActivity, + InterestCategories, + Interests, + ListMembers, + Lists, + Reports, + SegmentMembers, + Segments, + Tags, + Unsubscribes, +) + + +class MailChimpAuthenticator: + @staticmethod + def get_oauth_data_center(access_token: str) -> str: + """ + Every Mailchimp API request must be sent to a specific data center. + The data center is already embedded in API keys, but not OAuth access tokens. + This method retrieves the data center for OAuth credentials. + """ + try: + response = requests.get( + "https://login.mailchimp.com/oauth2/metadata", headers={"Authorization": "OAuth {}".format(access_token)} + ) + + # Requests to this endpoint will return a 200 status code even if the access token is invalid. + error = response.json().get("error") + if error == "invalid_token": + raise ValueError("The access token you provided was invalid. Please check your credentials and try again.") + return response.json()["dc"] + + # Handle any other exceptions that may occur. + except Exception as e: + raise Exception(f"An error occured while retrieving the data center for your account. \n {repr(e)}") + + def get_auth(self, config: Mapping[str, Any]) -> AuthBase: + authorization = config.get("credentials", {}) + auth_type = authorization.get("auth_type") + if auth_type == "apikey" or not authorization: + # API keys have the format -. + # See https://mailchimp.com/developer/marketing/docs/fundamentals/#api-structure + apikey = authorization.get("apikey") or config.get("apikey") + if not apikey: + raise Exception("Please provide a valid API key for authentication.") + auth_string = f"anystring:{apikey}".encode("utf8") + b64_encoded = base64.b64encode(auth_string).decode("utf8") + auth = TokenAuthenticator(token=b64_encoded, auth_method="Basic") + auth.data_center = apikey.split("-").pop() + + elif auth_type == "oauth2.0": + access_token = authorization["access_token"] + auth = TokenAuthenticator(token=access_token, auth_method="Bearer") + auth.data_center = self.get_oauth_data_center(access_token) + + else: + raise Exception(f"Invalid auth type: {auth_type}") + + return auth + + +class SourceMailchimp(AbstractSource): + def _validate_start_date(self, config: Mapping[str, Any]): + start_date = config.get("start_date") + + if start_date: + pattern = re.compile(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z") + if not pattern.match(start_date): # Compare against the pattern descriptor. + return "Please check the format of the start date against the pattern descriptor." + + try: # Handle invalid dates. + parsed_start_date = pendulum.parse(start_date) + except ParserError: + return "The provided start date is not a valid date. Please check the date you input and try again." + + if parsed_start_date > pendulum.now("UTC"): # Handle future start date. + return "The start date cannot be greater than the current date." + + return None + + def check_connection(self, logger: AirbyteLogger, config: Mapping[str, Any]) -> Tuple[bool, Any]: + # First, check for a valid start date if it is provided + start_date_validation_error = self._validate_start_date(config) + if start_date_validation_error: + return False, start_date_validation_error + + try: + authenticator = MailChimpAuthenticator().get_auth(config) + response = requests.get( + f"https://{authenticator.data_center}.api.mailchimp.com/3.0/ping", headers=authenticator.get_auth_header() + ) + + # A successful response will return a simple JSON object with a single key: health_status. + # Otherwise, errors are returned as a JSON object with keys: + # {type, title, status, detail, instance} + + if not response.json().get("health_status"): + error_title = response.json().get("title", "Unknown Error") + error_details = response.json().get("details", "An unknown error occurred. Please verify your credentials and try again.") + return False, f"Encountered an error while connecting to Mailchimp. Type: {error_title}. Details: {error_details}" + return True, None + + # Handle any other exceptions that may occur. + except Exception as e: + return False, repr(e) + + def streams(self, config: Mapping[str, Any]) -> List[Stream]: + authenticator = MailChimpAuthenticator().get_auth(config) + campaign_id = config.get("campaign_id") + start_date = config.get("start_date") + + lists = Lists(authenticator=authenticator, start_date=start_date) + interest_categories = InterestCategories(authenticator=authenticator, parent=lists) + + return [ + Automations(authenticator=authenticator, start_date=start_date), + Campaigns(authenticator=authenticator, start_date=start_date), + EmailActivity(authenticator=authenticator, start_date=start_date, campaign_id=campaign_id), + interest_categories, + Interests(authenticator=authenticator, parent=interest_categories), + lists, + ListMembers(authenticator=authenticator, start_date=start_date), + Reports(authenticator=authenticator, start_date=start_date), + SegmentMembers(authenticator=authenticator, start_date=start_date), + Segments(authenticator=authenticator, start_date=start_date), + Tags(authenticator=authenticator, parent=lists), + Unsubscribes(authenticator=authenticator, start_date=start_date, campaign_id=campaign_id), + ] diff --git a/source-mailchimp/source_mailchimp/spec.json b/source-mailchimp/source_mailchimp/spec.json new file mode 100644 index 0000000000..094e02a377 --- /dev/null +++ b/source-mailchimp/source_mailchimp/spec.json @@ -0,0 +1,127 @@ +{ + "documentationUrl": "https://go.estuary.dev/tmiNoF", + "connectionSpecification": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Mailchimp Spec", + "type": "object", + "required": ["credentials"], + "additionalProperties": true, + "properties": { + "credentials": { + "type": "object", + "title": "Authentication", + "discriminator": { + "propertyName": "auth_type" + }, + "oneOf": [ + { + "title": "OAuth2.0", + "type": "object", + "x-oauth2-provider": "mailchimp", + "required": ["auth_type", "access_token"], + "properties": { + "auth_type": { + "type": "string", + "const": "oauth2.0", + "default": "oauth2.0", + "order": 0 + }, + "client_id": { + "title": "Client ID", + "type": "string", + "description": "The Client ID of your OAuth application.", + "airbyte_secret": true + }, + "client_secret": { + "title": "Client Secret", + "type": "string", + "description": "The Client Secret of your OAuth application.", + "airbyte_secret": true + }, + "access_token": { + "title": "Access Token", + "type": "string", + "description": "An access token generated using the above client ID and secret.", + "airbyte_secret": true + } + } + }, + { + "type": "object", + "title": "API Key", + "required": ["auth_type", "apikey"], + "properties": { + "auth_type": { + "type": "string", + "const": "apikey", + "default": "apikey", + "order": 1 + }, + "apikey": { + "type": "string", + "title": "API Key", + "description": "Mailchimp API Key. See the docs for more information on how to generate this key: https://go.estuary.dev/tmiNoF", + "airbyte_secret": true + } + } + } + ] + }, + "start_date": { + "title": "Incremental Sync Start Date", + "description": "The date from which you want to start syncing data for Incremental streams. Only records that have been created or modified since this date will be synced. If left blank, all data will by synced.", + "type": "string", + "format": "date-time", + "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$", + "examples": ["2020-01-01T00:00:00.000Z"] + }, + "campaign_id": { + "type": "string", + "title": "ID of a campaign to sync email activities" + } + } + }, + "advanced_auth": { + "auth_flow_type": "oauth2.0", + "predicate_key": ["credentials", "auth_type"], + "predicate_value": "oauth2.0", + "oauth_config_specification": { + "complete_oauth_output_specification": { + "type": "object", + "additionalProperties": false, + "properties": { + "access_token": { + "type": "string", + "path_in_connector_config": ["credentials", "access_token"] + } + } + }, + "complete_oauth_server_input_specification": { + "type": "object", + "additionalProperties": false, + "properties": { + "client_id": { + "type": "string" + }, + "client_secret": { + "type": "string" + } + } + }, + "complete_oauth_server_output_specification": { + "type": "object", + "additionalProperties": false, + "properties": { + "client_id": { + "type": "string", + "path_in_connector_config": ["credentials", "client_id"] + }, + "client_secret": { + "type": "string", + "path_in_connector_config": ["credentials", "client_secret"] + } + } + } + } + } +} diff --git a/source-mailchimp/source_mailchimp/streams.py b/source-mailchimp/source_mailchimp/streams.py new file mode 100644 index 0000000000..158eaf1e8b --- /dev/null +++ b/source-mailchimp/source_mailchimp/streams.py @@ -0,0 +1,518 @@ +# +# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# + +import logging +import math +from abc import ABC, abstractmethod +from typing import Any, Iterable, List, Mapping, MutableMapping, Optional + +import pendulum +import requests +from airbyte_cdk.models import SyncMode +from airbyte_cdk.sources.streams.core import StreamData +from airbyte_cdk.sources.streams.http import HttpStream, HttpSubStream + +logger = logging.getLogger("airbyte") + + +class MailChimpStream(HttpStream, ABC): + primary_key = "id" + page_size = 1000 + + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.current_offset = 0 + self.data_center = kwargs["authenticator"].data_center + + @property + def url_base(self) -> str: + return f"https://{self.data_center}.api.mailchimp.com/3.0/" + + def next_page_token(self, response: requests.Response) -> Optional[Mapping[str, Any]]: + decoded_response = response.json() + api_data = decoded_response[self.data_field] + if len(api_data) < self.page_size: + self.current_offset = 0 + return None + else: + self.current_offset += self.page_size + return {"offset": self.current_offset} + + def request_params( + self, + stream_state: Mapping[str, Any], + stream_slice: Mapping[str, Any] = None, + next_page_token: Mapping[str, Any] = None, + ) -> MutableMapping[str, Any]: + + # The ._links field is returned by most Mailchimp endpoints and contains non-relevant schema metadata. + params = {"count": self.page_size, "exclude_fields": f"{self.data_field}._links"} + + # Handle pagination by inserting the next page's token in the request parameters + if next_page_token: + params.update(next_page_token) + return params + + def parse_response(self, response: requests.Response, **kwargs) -> Iterable[Mapping]: + response_json = response.json() + yield from response_json[self.data_field] + + @property + @abstractmethod + def data_field(self) -> str: + """The response entry that contains useful data""" + pass + + def read_records( + self, + sync_mode: SyncMode, + cursor_field: List[str] = None, + stream_slice: Mapping[str, Any] = None, + stream_state: Mapping[str, Any] = None, + ) -> Iterable[StreamData]: + try: + yield from super().read_records( + sync_mode=sync_mode, cursor_field=cursor_field, stream_slice=stream_slice, stream_state=stream_state + ) + except requests.exceptions.JSONDecodeError: + logger.error(f"Unknown error while reading stream {self.name}. Response cannot be read properly. ") + + +class IncrementalMailChimpStream(MailChimpStream, ABC): + state_checkpoint_interval = math.inf + + def __init__(self, **kwargs): + self.start_date = kwargs.pop("start_date", None) + super().__init__(**kwargs) + + @property + @abstractmethod + def cursor_field(self) -> str: + """ + Defining a cursor field indicates that a stream is incremental, so any incremental stream must extend this class + and define a cursor field. + """ + pass + + @property + def filter_field(self): + return f"since_{self.cursor_field}" + + @property + def sort_field(self): + return self.cursor_field + + def filter_empty_fields(self, element: Mapping[str, Any]) -> Mapping[str, Any]: + """ + Many Mailchimp endpoints return empty strings instead of null values. + This causes validation errors on datetime columns, so for safety, we need to check for empty strings and set their value to None/null. + This method recursively traverses each element in a record and replaces any "" values with None, based on three conditions: + + 1. If the element is a dictionary, apply the method recursively to each value in the dictionary. + 2. If the element is a list, apply the method recursively to each item in the list. + 3. If the element is a string, check if it is an empty string. If so, replace it with None. + """ + + if isinstance(element, dict): + element = {k: self.filter_empty_fields(v) if v != "" else None for k, v in element.items()} + elif isinstance(element, list): + element = [self.filter_empty_fields(v) for v in element] + return element + + def get_updated_state(self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any]) -> Mapping[str, Any]: + """ + Return the latest state by comparing the cursor value in the latest record with the stream's most recent state object + and returning an updated state object. + """ + latest_state = latest_record.get(self.cursor_field) + current_state = current_stream_state.get(self.cursor_field) or latest_state + return {self.cursor_field: max(latest_state, current_state)} + + def stream_slices( + self, *, sync_mode: SyncMode, cursor_field: List[str] = None, stream_state: Mapping[str, Any] = None + ) -> Iterable[Optional[Mapping[str, Any]]]: + slice_ = {} + stream_state = stream_state or {} + cursor_value = self.get_filter_date(self.start_date, stream_state.get(self.cursor_field)) + if cursor_value: + slice_[self.filter_field] = cursor_value + yield slice_ + + @staticmethod + def get_filter_date(start_date: str, state_date: str) -> str: + """ + Calculate the filter date to pass in the request parameters by comparing the start_date + with the value of state obtained from the stream_slice. + If only one value exists, use it by default. Otherwise, return None. + If no filter_date is provided, the API will fetch all available records. + """ + + start_date_parsed = pendulum.parse(start_date).to_iso8601_string() if start_date else None + state_date_parsed = pendulum.parse(state_date).to_iso8601_string() if state_date else None + + # Return the max of the two dates if both are present. Otherwise return whichever is present, or None. + if start_date_parsed or state_date_parsed: + return max(filter(None, [start_date_parsed, state_date_parsed]), default=None) + + def filter_old_records(self, records: Iterable, filter_date) -> Iterable: + """ + Filters out records with older cursor_values than the filter_date. + This can be used to enforce the filter for incremental streams that do not support sorting/filtering via query params. + """ + for record in records: + record_cursor_value = record.get(self.cursor_field) + if not filter_date or record_cursor_value >= filter_date: + yield record + + def request_params(self, stream_state=None, stream_slice=None, **kwargs): + stream_state = stream_state or {} + stream_slice = stream_slice or {} + params = super().request_params(stream_state=stream_state, stream_slice=stream_slice, **kwargs) + default_params = {"sort_field": self.sort_field, "sort_dir": "ASC", **stream_slice} + params.update(default_params) + return params + + def parse_response(self, response: requests.Response, **kwargs) -> Iterable[Mapping]: + response = super().parse_response(response, **kwargs) + for record in response: + yield self.filter_empty_fields(record) + + +class MailChimpListSubStream(IncrementalMailChimpStream): + """ + Base class for incremental Mailchimp streams that are children of the Lists stream. + """ + + def stream_slices(self, stream_state: Mapping[str, Any] = None, **kwargs) -> Iterable[Optional[Mapping[str, Any]]]: + stream_state = stream_state or {} + parent = Lists(authenticator=self.authenticator).read_records(sync_mode=SyncMode.full_refresh) + for parent_record in parent: + slice = {"list_id": parent_record["id"]} + cursor_value = self.get_filter_date(self.start_date, stream_state.get(parent_record["id"], {}).get(self.cursor_field)) + if cursor_value: + slice[self.filter_field] = cursor_value + yield slice + + def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: + list_id = stream_slice.get("list_id") + return f"lists/{list_id}/{self.data_field}" + + def request_params(self, stream_state=None, stream_slice=None, **kwargs) -> MutableMapping[str, Any]: + params = super().request_params(stream_state=stream_state, stream_slice=stream_slice, **kwargs) + + # Get the current state value for this list_id, if it exists + # Then, use the value in state to filter the request + current_slice = stream_slice.get("list_id") + filter_date = stream_state.get(current_slice) + if filter_date: + params[self.filter_field] = filter_date.get(self.cursor_field) + return params + + def get_updated_state(self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any]) -> Mapping[str, Any]: + current_stream_state = current_stream_state or {} + list_id = latest_record.get("list_id") + latest_cursor_value = latest_record.get(self.cursor_field) + + # Get the current state value for this list, if it exists + list_state = current_stream_state.get(list_id, {}) + current_cursor_value = list_state.get(self.cursor_field, latest_cursor_value) + + # Update the cursor value and set it in state + updated_cursor_value = max(current_cursor_value, latest_cursor_value) + current_stream_state[list_id] = {self.cursor_field: updated_cursor_value} + + return current_stream_state + + +class Lists(IncrementalMailChimpStream): + cursor_field = "date_created" + data_field = "lists" + + def path(self, **kwargs) -> str: + return "lists" + + +class Campaigns(IncrementalMailChimpStream): + cursor_field = "create_time" + data_field = "campaigns" + + def path(self, **kwargs) -> str: + return "campaigns" + + +class Automations(IncrementalMailChimpStream): + """Doc Link: https://mailchimp.com/developer/marketing/api/automation/get-automation-info/""" + + cursor_field = "create_time" + data_field = "automations" + + def path(self, **kwargs) -> str: + return "automations" + + +class EmailActivity(IncrementalMailChimpStream): + cursor_field = "timestamp" + filter_field = "since" + sort_field = "create_time" + data_field = "emails" + primary_key = ["timestamp", "email_id", "action"] + + def __init__(self, campaign_id: Optional[str] = None, **kwargs): + super().__init__(**kwargs) + self.campaign_id = campaign_id + + def stream_slices( + self, *, sync_mode: SyncMode, cursor_field: List[str] = None, stream_state: Mapping[str, Any] = None + ) -> Iterable[Optional[Mapping[str, Any]]]: + stream_state = stream_state or {} + if self.campaign_id: + # this is a workaround to speed up SATs and enable incremental tests + campaigns = [{"id": self.campaign_id}] + else: + campaigns = Campaigns(authenticator=self.authenticator).read_records(sync_mode=SyncMode.full_refresh) + for campaign in campaigns: + slice_ = {"campaign_id": campaign["id"]} + state_value = stream_state.get(campaign["id"], {}).get(self.cursor_field) + cursor_value = self.get_filter_date(self.start_date, state_value) + if cursor_value: + slice_[self.filter_field] = cursor_value + yield slice_ + + def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: + campaign_id = stream_slice["campaign_id"] + return f"reports/{campaign_id}/email-activity" + + def get_updated_state(self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any]) -> Mapping[str, Any]: + """ + Return the latest state by comparing the campaign_id and cursor value in the latest record with the stream's most recent state object + and returning an updated state object. + """ + campaign_id = latest_record.get("campaign_id") + latest_cursor_value = latest_record.get(self.cursor_field) + current_stream_state = current_stream_state or {} + current_state = current_stream_state.get(campaign_id) if current_stream_state else None + if current_state: + current_state = current_state.get(self.cursor_field) + current_state_value = current_state or latest_cursor_value + max_value = max(current_state_value, latest_cursor_value) + new_value = {self.cursor_field: max_value} + + current_stream_state[campaign_id] = new_value + return current_stream_state + + def parse_response(self, response: requests.Response, **kwargs) -> Iterable[Mapping]: + try: + response_json = response.json() + except requests.exceptions.JSONDecodeError: + logger.error(f"Response returned with {response.status_code=}, {response.content=}") + response_json = {} + # transform before save + # [{'campaign_id', 'list_id', 'list_is_active', 'email_id', 'email_address', 'activity[array[object]]', '_links'}] -> + # -> [[{'campaign_id', 'list_id', 'list_is_active', 'email_id', 'email_address', '**activity[i]', '_links'}, ...]] + data = response_json.get(self.data_field, []) + for item in data: + for activity_item in item.pop("activity", []): + yield {**item, **activity_item} + + +class InterestCategories(MailChimpStream, HttpSubStream): + """ + Get information about interest categories for a specific list. + Docs link: https://mailchimp.com/developer/marketing/api/interest-categories/list-interest-categories/ + """ + + data_field = "categories" + + def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: + """ + Get the list_id from the parent stream slice and use it to construct the path. + """ + list_id = stream_slice.get("parent").get("id") + return f"lists/{list_id}/interest-categories" + + +class Interests(MailChimpStream, HttpSubStream): + """ + Get a list of interests for a specific interest category. + Docs link: https://mailchimp.com/developer/marketing/api/interests/list-interests-in-category/ + """ + + data_field = "interests" + + def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: + """ + Get the list_id from the parent stream slice and use it to construct the path. + """ + list_id = stream_slice.get("parent").get("list_id") + category_id = stream_slice.get("parent").get("id") + return f"lists/{list_id}/interest-categories/{category_id}/interests" + + +class ListMembers(MailChimpListSubStream): + """ + Get information about members in a specific Mailchimp list. + Docs link: https://mailchimp.com/developer/marketing/api/list-members/list-members-info/ + """ + + cursor_field = "last_changed" + data_field = "members" + + +class Reports(IncrementalMailChimpStream): + cursor_field = "send_time" + data_field = "reports" + + def path(self, **kwargs) -> str: + return "reports" + + +class SegmentMembers(MailChimpListSubStream): + """ + Get information about members in a specific segment. + Docs link: https://mailchimp.com/developer/marketing/api/list-segment-members/list-members-in-segment/ + """ + + cursor_field = "last_changed" + data_field = "members" + + def stream_slices(self, **kwargs) -> Iterable[Optional[Mapping[str, Any]]]: + """ + Each slice consists of a list_id and segment_id pair + """ + segments_slices = Segments(authenticator=self.authenticator).stream_slices(sync_mode=SyncMode.full_refresh) + + for slice in segments_slices: + segment_records = Segments(authenticator=self.authenticator).read_records(sync_mode=SyncMode.full_refresh, stream_slice=slice) + + for segment in segment_records: + yield {"list_id": segment["list_id"], "segment_id": segment["id"]} + + def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: + list_id = stream_slice.get("list_id") + segment_id = stream_slice.get("segment_id") + return f"lists/{list_id}/segments/{segment_id}/members" + + def parse_response(self, response: requests.Response, stream_state: Mapping[str, Any], stream_slice, **kwargs) -> Iterable[Mapping]: + """ + The SegmentMembers endpoint does not support sorting or filtering, + so we need to apply our own filtering logic before reading. + The foreign key "segment_id" is also added to each record before being read. + """ + response = super().parse_response(response, **kwargs) + + # Calculate the filter date to compare all records against in this slice + slice_cursor_value = stream_state.get(str(stream_slice.get("segment_id")), {}).get(self.cursor_field) + filter_date = self.get_filter_date(self.start_date, slice_cursor_value) + + for record in self.filter_old_records(response, filter_date): + # Add the segment_id foreign_key to each record + record["segment_id"] = stream_slice.get("segment_id") + yield record + + def get_updated_state(self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any]) -> Mapping[str, Any]: + current_stream_state = current_stream_state or {} + segment_id = str(latest_record.get("segment_id")) + latest_cursor_value = latest_record.get(self.cursor_field) + + # Get the current state value for this list, if it exists + segment_state = current_stream_state.get(segment_id, {}) + current_cursor_value = segment_state.get(self.cursor_field, latest_cursor_value) + + # Update the cursor value and set it in state + updated_cursor_value = max(current_cursor_value, latest_cursor_value) + current_stream_state[segment_id] = {self.cursor_field: updated_cursor_value} + return current_stream_state + + +class Segments(MailChimpListSubStream): + """ + Get information about all available segments for a specific list. + Docs link: https://mailchimp.com/developer/marketing/api/list-segments/list-segments/ + """ + + cursor_field = "updated_at" + data_field = "segments" + + +class Tags(MailChimpStream, HttpSubStream): + """ + Get information about tags for a specific list. + Docs link: https://mailchimp.com/developer/marketing/api/list-tags/list-tags-for-list/ + """ + + data_field = "tags" + + def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: + list_id = stream_slice.get("parent").get("id") + return f"lists/{list_id}/tag-search" + + def parse_response(self, response: requests.Response, stream_slice, **kwargs) -> Iterable[Mapping]: + """ + Tags do not reference parent_ids, so we need to add the list_id to each record. + """ + response = super().parse_response(response, **kwargs) + + for record in response: + record["list_id"] = stream_slice.get("parent").get("id") + yield record + + +class Unsubscribes(IncrementalMailChimpStream): + """ + List of members who have unsubscribed from a specific campaign. + Docs link: https://mailchimp.com/developer/marketing/api/unsub-reports/list-unsubscribed-members/ + """ + + cursor_field = "timestamp" + data_field = "unsubscribes" + # There is no unique identifier for unsubscribes, so we use a composite key + # consisting of the campaign_id, email_id, and timestamp. + primary_key = ["campaign_id", "email_id", "timestamp"] + + def __init__(self, campaign_id: Optional[str] = None, **kwargs): + super().__init__(**kwargs) + self.campaign_id = campaign_id + + def stream_slices( + self, *, sync_mode: SyncMode, cursor_field: List[str] = None, stream_state: Mapping[str, Any] = None + ) -> Iterable[Optional[Mapping[str, Any]]]: + + if self.campaign_id: + # Similar to EmailActivity stream, this is a workaround to speed up SATs + # and enable incremental tests by reading from a single campaign + campaigns = [{"id": self.campaign_id}] + else: + campaigns = Campaigns(authenticator=self.authenticator).read_records(sync_mode=SyncMode.full_refresh) + for campaign in campaigns: + yield {"campaign_id": campaign["id"]} + + def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str: + campaign_id = stream_slice.get("campaign_id") + return f"reports/{campaign_id}/unsubscribed" + + def parse_response(self, response: requests.Response, stream_state: Mapping[str, Any], stream_slice, **kwargs) -> Iterable[Mapping]: + """ + The Unsubscribes endpoint does not support sorting or filtering, + so we need to apply our own filtering logic before reading. + """ + + response = super().parse_response(response, **kwargs) + + slice_cursor_value = stream_state.get(stream_slice.get("campaign_id", {}), {}).get(self.cursor_field) + filter_date = self.get_filter_date(self.start_date, slice_cursor_value) + yield from self.filter_old_records(response, filter_date) + + def get_updated_state(self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any]) -> Mapping[str, Any]: + current_stream_state = current_stream_state or {} + campaign_id = latest_record.get("campaign_id") + latest_cursor_value = latest_record.get(self.cursor_field) + + # Get the current state value for this campaign, if it exists + campaign_state = current_stream_state.get(campaign_id, {}) + current_cursor_value = campaign_state.get(self.cursor_field, latest_cursor_value) + + # Update the cursor value and set it in state + updated_cursor_value = max(current_cursor_value, latest_cursor_value) + current_stream_state[campaign_id] = {self.cursor_field: updated_cursor_value} + return current_stream_state diff --git a/source-mailchimp/test.flow.yaml b/source-mailchimp/test.flow.yaml new file mode 100644 index 0000000000..e201120069 --- /dev/null +++ b/source-mailchimp/test.flow.yaml @@ -0,0 +1,79 @@ +--- +import: + - acmeCo/flow.yaml +captures: + acmeCo/source-mailchimp: + endpoint: + local: + command: + - python + - "-m" + - source_mailchimp + config: config.yaml + bindings: + - resource: + stream: automations + syncMode: incremental + cursorField: + - create_time + target: acmeCo/automations + - resource: + stream: campaigns + syncMode: incremental + cursorField: + - create_time + target: acmeCo/campaigns + - resource: + stream: email_activity + syncMode: incremental + cursorField: + - timestamp + target: acmeCo/email_activity + - resource: + stream: interest_categories + syncMode: full_refresh + target: acmeCo/interest_categories + - resource: + stream: interests + syncMode: full_refresh + target: acmeCo/interests + - resource: + stream: lists + syncMode: incremental + cursorField: + - date_created + target: acmeCo/lists + - resource: + stream: list_members + syncMode: incremental + cursorField: + - last_changed + target: acmeCo/list_members + - resource: + stream: reports + syncMode: incremental + cursorField: + - send_time + target: acmeCo/reports + - resource: + stream: segment_members + syncMode: incremental + cursorField: + - last_changed + target: acmeCo/segment_members + - resource: + stream: segments + syncMode: incremental + cursorField: + - updated_at + target: acmeCo/segments + - resource: + stream: tags + syncMode: full_refresh + target: acmeCo/tags + - resource: + stream: unsubscribes + syncMode: incremental + cursorField: + - timestamp + target: acmeCo/unsubscribes diff --git a/source-mailchimp/tests/__init__.py b/source-mailchimp/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/source-mailchimp/tests/conftest.py b/source-mailchimp/tests/conftest.py new file mode 100644 index 0000000000..5305f0dada --- /dev/null +++ b/source-mailchimp/tests/conftest.py @@ -0,0 +1,77 @@ +# +# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# + +from pytest import fixture +from source_mailchimp.source import MailChimpAuthenticator +from source_mailchimp.streams import Campaigns, Unsubscribes + + +@fixture(name="data_center") +def data_center_fixture(): + return "some_dc" + + +@fixture(name="config") +def config_fixture(data_center): + return {"apikey": f"API_KEY-{data_center}", "start_date": "2022-01-01T00:00:00.000Z"} + + +@fixture(name="access_token") +def access_token_fixture(): + return "some_access_token" + + +@fixture(name="oauth_config") +def oauth_config_fixture(access_token): + return { + "credentials": { + "auth_type": "oauth2.0", + "client_id": "111111111", + "client_secret": "secret_1111111111", + "access_token": access_token, + } + } + + +@fixture(name="apikey_config") +def apikey_config_fixture(data_center): + return {"credentials": {"auth_type": "apikey", "apikey": f"some_api_key-{data_center}"}} + + +@fixture(name="wrong_config") +def wrong_config_fixture(): + return {"credentials": {"auth_type": "not auth_type"}} + + +@fixture(name="auth") +def authenticator_fixture(apikey_config): + return MailChimpAuthenticator().get_auth(apikey_config) + + +@fixture(name="campaigns_stream") +def campaigns_stream_fixture(auth): + return Campaigns(authenticator=auth) + + +@fixture(name="unsubscribes_stream") +def unsubscribes_stream_fixture(auth): + return Unsubscribes(authenticator=auth) + + +@fixture(name="mock_campaigns_response") +def mock_campaigns_response_fixture(): + return [ + {"id": "campaign_1", "web_id": 1, "type": "regular", "create_time": "2022-01-01T00:00:00Z"}, + {"id": "campaign_2", "web_id": 2, "type": "plaintext", "create_time": "2022-01-02T00:00:00Z"}, + {"id": "campaign_3", "web_id": 3, "type": "variate", "create_time": "2022-01-03T00:00:00Z"}, + ] + + +@fixture(name="mock_unsubscribes_state") +def mock_unsubscribes_state_fixture(): + return { + "campaign_1": {"timestamp": "2022-01-01T00:00:00Z"}, + "campaign_2": {"timestamp": "2022-01-02T00:00:00Z"}, + "campaign_3": {"timestamp": "2022-01-03T00:00:00Z"}, + } diff --git a/source-mailchimp/tests/snapshots/snapshots__capture__capture.stdout.json b/source-mailchimp/tests/snapshots/snapshots__capture__capture.stdout.json new file mode 100644 index 0000000000..b603d97a5d --- /dev/null +++ b/source-mailchimp/tests/snapshots/snapshots__capture__capture.stdout.json @@ -0,0 +1,369 @@ +[ + [ + "acmeCo/campaigns", + { + "_meta": { + "op": "u", + "row_id": 0 + }, + "archive_url": "http://eepurl.com/iO2fCY", + "content_type": "multichannel", + "create_time": "2024-04-29T14:56:01+00:00", + "delivery_status": { + "enabled": false + }, + "emails_sent": 2, + "id": "52b74e95ee", + "long_archive_url": "https://mailchi.mp/30fdc4b30708/teste", + "needs_block_refresh": false, + "recipients": { + "list_id": "7a1cbe4b72", + "list_is_active": true, + "list_name": "Penguins", + "recipient_count": 2, + "segment_text": null + }, + "report_summary": { + "click_rate": 0, + "clicks": 0, + "ecommerce": { + "total_orders": 0, + "total_revenue": 0, + "total_spent": 0 + }, + "open_rate": 0, + "opens": 0, + "subscriber_clicks": 0, + "unique_opens": 0 + }, + "resendable": true, + "send_time": "2024-04-29T14:57:00+00:00", + "settings": { + "authenticate": true, + "auto_footer": false, + "auto_tweet": false, + "drag_and_drop": false, + "fb_comments": true, + "folder_id": null, + "from_name": "Estu", + "inline_css": false, + "preview_text": "Teste", + "reply_to": "leofs123@gmail.com", + "subject_line": "Teste", + "template_id": 13, + "timewarp": false, + "title": null, + "to_name": null, + "use_conversation": false + }, + "status": "sent", + "tracking": { + "clicktale": null, + "ecomm360": false, + "goal_tracking": false, + "google_analytics": null, + "html_clicks": true, + "opens": true, + "text_clicks": false + }, + "type": "regular", + "web_id": 6290 + } + ], + [ + "acmeCo/lists", + { + "_meta": { + "op": "u", + "row_id": 0 + }, + "beamer_address": "us22-eb203924dd-18076968e2@inbound.mailchimp.com", + "campaign_defaults": { + "from_email": "leofs123@gmail.com", + "from_name": "Estu", + "language": "en", + "subject": null + }, + "contact": "redacted", + "date_created": "2024-03-22T20:01:48+00:00", + "double_optin": false, + "email_type_option": false, + "has_welcome": false, + "id": "7a1cbe4b72", + "list_rating": 0, + "marketing_permissions": false, + "modules": [], + "name": "Penguins", + "notify_on_subscribe": null, + "notify_on_unsubscribe": null, + "permission_reminder": "Voc\u00ea est\u00e1 recebendo este e-mail porque se inscreveu em nosso site.", + "stats": { + "avg_sub_rate": 0, + "avg_unsub_rate": 0, + "campaign_count": 1, + "campaign_last_sent": null, + "cleaned_count": 0, + "cleaned_count_since_send": 0, + "click_rate": 0, + "last_sub_date": "redacted", + "last_unsub_date": null, + "member_count": 2, + "member_count_since_send": 0, + "merge_field_count": 5, + "open_rate": 0, + "target_sub_rate": 0, + "unsubscribe_count": 0, + "unsubscribe_count_since_send": 0 + }, + "subscribe_url_long": "https://gmail.us22.list-manage.com/subscribe?u=ae90d8c414dc11cf841a0c191&id=7a1cbe4b72", + "subscribe_url_short": "http://eepurl.com/iOREaU", + "use_archive_bar": true, + "visibility": "prv", + "web_id": 1174 + } + ], + [ + "acmeCo/list_members", + { + "_meta": { + "op": "u", + "row_id": 0 + }, + "consents_to_one_to_one_messaging": true, + "contact_id": "857bca141e5cc997988fa0ce172ece26", + "email_address": "leofs123@gmail.com", + "email_client": null, + "email_type": "html", + "full_name": "Estu", + "id": "65eb1560cc6c0c8156369f06e143f3db", + "ip_opt": "177.34.243.176", + "ip_signup": null, + "language": null, + "last_changed": "2024-03-22T20:01:48+00:00", + "list_id": "7a1cbe4b72", + "location": { + "country_code": null, + "dstoff": 0, + "gmtoff": 0, + "latitude": 0, + "longitude": 0, + "region": null, + "timezone": null + }, + "member_rating": 2, + "merge_fields": { + "ADDRESS": { + "addr1": "Penguins\nRua Neo Alves Martins, 1552\nMaringa, PR 87013-060\nBrazil", + "addr2": null, + "city": null, + "country": "US", + "state": null, + "zip": null + }, + "BIRTHDAY": null, + "FNAME": "Estu", + "LNAME": "Ary", + "PHONE": null + }, + "sms_phone_number": null, + "sms_subscription_last_updated": null, + "sms_subscription_status": null, + "source": "Admin Add", + "stats": { + "avg_click_rate": 0, + "avg_open_rate": 0 + }, + "status": "subscribed", + "tags": [], + "tags_count": 0, + "timestamp_opt": "2024-03-22T20:01:48+00:00", + "timestamp_signup": null, + "unique_email_id": "024245a424", + "vip": false, + "web_id": 557562 + } + ], + [ + "acmeCo/list_members", + { + "_meta": { + "op": "u", + "row_id": 1 + }, + "consents_to_one_to_one_messaging": true, + "contact_id": "354277a363e306205348a85112c500bc", + "email_address": "luish1980@hotmail.com", + "email_client": null, + "email_type": "html", + "full_name": "Luis", + "id": "8b04baf128b1c48ff4bb18dbb6bba2ce", + "ip_opt": "177.34.243.176", + "ip_signup": null, + "language": null, + "last_changed": "2024-04-26T02:19:01+00:00", + "list_id": "7a1cbe4b72", + "location": { + "country_code": null, + "dstoff": 0, + "gmtoff": 0, + "latitude": 0, + "longitude": 0, + "region": null, + "timezone": null + }, + "member_rating": 2, + "merge_fields": { + "ADDRESS": null, + "BIRTHDAY": "11/23", + "FNAME": "Luis", + "LNAME": "Salomao", + "PHONE": "+55 44 0000-0000" + }, + "sms_phone_number": null, + "sms_subscription_last_updated": null, + "sms_subscription_status": null, + "source": "Admin Add", + "stats": { + "avg_click_rate": 0, + "avg_open_rate": 0 + }, + "status": "subscribed", + "tags": [ + { + "id": 3389, + "name": "test_tag" + } + ], + "tags_count": 1, + "timestamp_opt": "2024-04-26T02:19:01+00:00", + "timestamp_signup": null, + "unique_email_id": "3942f2eb78", + "vip": false, + "web_id": 1970495 + } + ], + [ + "acmeCo/reports", + { + "_meta": { + "op": "u", + "row_id": 0 + }, + "abuse_reports": 0, + "bounces": { + "hard_bounces": 0, + "soft_bounces": 0, + "syntax_errors": 0 + }, + "campaign_title": null, + "clicks": { + "click_rate": 0, + "clicks_total": 0, + "last_click": null, + "unique_clicks": 0, + "unique_subscriber_clicks": 0 + }, + "delivery_status": { + "enabled": false + }, + "ecommerce": { + "currency_code": "USD", + "total_orders": 0, + "total_revenue": 0, + "total_spent": 0 + }, + "emails_sent": 2, + "facebook_likes": { + "facebook_likes": 0, + "recipient_likes": 0, + "unique_likes": 0 + }, + "forwards": { + "forwards_count": 0, + "forwards_opens": 0 + }, + "id": "52b74e95ee", + "list_id": "7a1cbe4b72", + "list_is_active": true, + "list_name": "Penguins", + "list_stats": { + "click_rate": 0, + "open_rate": 0, + "sub_rate": 0, + "unsub_rate": 0 + }, + "opens": { + "last_open": null, + "open_rate": 0, + "opens_total": 0, + "unique_opens": 0 + }, + "preview_text": "Teste", + "send_time": "2024-04-29T14:57:00+00:00", + "subject_line": "Teste", + "timeseries": "redacted", + "type": "regular", + "unsubscribed": 0 + } + ], + [ + "acmeCo/segment_members", + { + "_meta": { + "op": "u", + "row_id": 0 + }, + "email_address": "luish1980@hotmail.com", + "email_client": null, + "email_type": "html", + "id": "8b04baf128b1c48ff4bb18dbb6bba2ce", + "ip_opt": "redacted", + "ip_signup": null, + "language": null, + "last_changed": "2024-04-26T02:19:01+00:00", + "list_id": "7a1cbe4b72", + "location": { + "country_code": null, + "dstoff": 0, + "gmtoff": 0, + "latitude": 0, + "longitude": 0, + "timezone": null + }, + "member_rating": 2, + "merge_fields": { + "ADDRESS": null, + "BIRTHDAY": "11/23", + "FNAME": "Luis", + "LNAME": "Salomao", + "PHONE": "+55 44 0000-0000" + }, + "segment_id": 3389, + "stats": { + "avg_click_rate": 0, + "avg_open_rate": 0 + }, + "status": "subscribed", + "timestamp_opt": "2024-04-26T02:19:01+00:00", + "timestamp_signup": null, + "unique_email_id": "3942f2eb78", + "vip": false + } + ], + [ + "acmeCo/segments", + { + "_meta": { + "op": "u", + "row_id": 0 + }, + "created_at": "2024-04-26T02:17:50+00:00", + "id": 3389, + "list_id": "7a1cbe4b72", + "member_count": 1, + "name": "test_tag", + "type": "static", + "updated_at": "2024-04-26T02:17:50+00:00" + } + ] +] diff --git a/source-mailchimp/tests/snapshots/snapshots__discover__capture.stdout.json b/source-mailchimp/tests/snapshots/snapshots__discover__capture.stdout.json new file mode 100644 index 0000000000..bffe659c39 --- /dev/null +++ b/source-mailchimp/tests/snapshots/snapshots__discover__capture.stdout.json @@ -0,0 +1,5354 @@ +[ + { + "documentSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "properties": { + "_meta": { + "properties": { + "row_id": { + "type": "integer" + } + }, + "required": [ + "row_id" + ], + "type": "object" + }, + "create_time": { + "format": "date-time", + "type": [ + "null", + "string" + ] + }, + "emails_sent": { + "type": [ + "null", + "number" + ] + }, + "id": { + "type": "string" + }, + "recipients": { + "properties": { + "list_id": { + "type": [ + "null", + "string" + ] + }, + "list_is_active": { + "type": [ + "null", + "boolean" + ] + }, + "list_name": { + "type": [ + "null", + "string" + ] + }, + "segment_opts": { + "properties": { + "conditions": { + "items": { + "additionalProperties": true, + "type": [ + "null", + "object" + ] + }, + "type": [ + "null", + "array" + ] + }, + "match": { + "type": [ + "null", + "string" + ] + }, + "saved_segment_id": { + "type": [ + "null", + "number" + ] + } + }, + "type": [ + "null", + "object" + ] + }, + "store_id": { + "type": [ + "null", + "string" + ] + } + }, + "type": [ + "null", + "object" + ] + }, + "report_summary": { + "properties": { + "click_rate": { + "type": [ + "null", + "number" + ] + }, + "clicks": { + "type": [ + "null", + "number" + ] + }, + "open_rate": { + "type": [ + "null", + "number" + ] + }, + "opens": { + "type": [ + "null", + "number" + ] + }, + "subscriber_clicks": { + "type": [ + "null", + "number" + ] + }, + "unique_opens": { + "type": [ + "null", + "number" + ] + } + }, + "type": [ + "null", + "object" + ] + }, + "settings": { + "properties": { + "authenticate": { + "type": [ + "null", + "boolean" + ] + }, + "auto_footer": { + "type": [ + "null", + "boolean" + ] + }, + "from_name": { + "type": [ + "null", + "string" + ] + }, + "inline_css": { + "type": [ + "null", + "boolean" + ] + }, + "reply_to": { + "type": [ + "null", + "string" + ] + }, + "title": { + "type": [ + "null", + "string" + ] + }, + "to_name": { + "type": [ + "null", + "string" + ] + }, + "use_conversation": { + "type": [ + "null", + "boolean" + ] + } + }, + "type": [ + "null", + "object" + ] + }, + "start_time": { + "format": "date-time", + "type": [ + "null", + "string" + ] + }, + "status": { + "type": [ + "null", + "string" + ] + }, + "tracking": { + "properties": { + "capsule": { + "properties": { + "notes": { + "type": [ + "null", + "boolean" + ] + } + }, + "type": [ + "null", + "object" + ] + }, + "clicktale": { + "type": [ + "null", + "string" + ] + }, + "ecomm360": { + "type": [ + "null", + "boolean" + ] + }, + "goal_tracking": { + "type": [ + "null", + "boolean" + ] + }, + "google_analytics": { + "type": [ + "null", + "string" + ] + }, + "html_clicks": { + "type": [ + "null", + "boolean" + ] + }, + "opens": { + "type": [ + "null", + "boolean" + ] + }, + "salesforce": { + "properties": { + "campaign": { + "type": [ + "null", + "boolean" + ] + }, + "notes": { + "type": [ + "null", + "boolean" + ] + } + }, + "type": [ + "null", + "object" + ] + }, + "text_clicks": { + "type": [ + "null", + "boolean" + ] + } + }, + "type": [ + "null", + "object" + ] + }, + "trigger_settings": { + "properties": { + "runtime": { + "properties": { + "days": { + "items": { + "type": [ + "null", + "string" + ] + }, + "type": [ + "null", + "array" + ] + }, + "hours": { + "properties": { + "type": { + "type": [ + "null", + "string" + ] + } + }, + "type": [ + "null", + "object" + ] + } + }, + "type": [ + "null", + "object" + ] + }, + "workflow_emails_count": { + "type": [ + "null", + "number" + ] + }, + "workflow_title": { + "type": [ + "null", + "string" + ] + }, + "workflow_type": { + "type": [ + "null", + "string" + ] + } + }, + "type": [ + "null", + "object" + ] + } + }, + "required": [ + "id" + ], + "title": "Automations", + "type": "object" + }, + "key": [ + "/id" + ], + "recommendedName": "automations", + "resourceConfig": { + "cursorField": [ + "create_time" + ], + "stream": "automations", + "syncMode": "incremental" + } + }, + { + "documentSchema": { + "description": "A summary of an individual campaign's settings and content.", + "properties": { + "_meta": { + "properties": { + "row_id": { + "type": "integer" + } + }, + "required": [ + "row_id" + ], + "type": "object" + }, + "ab_split_opts": { + "description": "[A/B Testing](https://mailchimp.com/help/about-ab-testing-campaigns/) options for a campaign.", + "properties": { + "from_name_a": { + "description": "For campaigns split on 'From Name', the name for Group A.", + "title": "From Name Group A", + "type": [ + "null", + "string" + ] + }, + "from_name_b": { + "description": "For campaigns split on 'From Name', the name for Group B.", + "title": "From Name Group B", + "type": [ + "null", + "string" + ] + }, + "pick_winner": { + "description": "How we should evaluate a winner. Based on 'opens', 'clicks', or 'manual'.", + "enum": [ + "opens", + "clicks", + "manual" + ], + "title": "Pick Winner", + "type": [ + "null", + "string" + ] + }, + "reply_email_a": { + "description": "For campaigns split on 'From Name', the reply-to address for Group A.", + "title": "Reply Email Group A", + "type": [ + "null", + "string" + ] + }, + "reply_email_b": { + "description": "For campaigns split on 'From Name', the reply-to address for Group B.", + "title": "Reply Email Group B", + "type": [ + "null", + "string" + ] + }, + "send_time_a": { + "description": "The send time for Group A.", + "format": "date-time", + "title": "Send Time Group A", + "type": [ + "null", + "string" + ] + }, + "send_time_b": { + "description": "The send time for Group B.", + "format": "date-time", + "title": "Send Time Group B", + "type": [ + "null", + "string" + ] + }, + "send_time_winner": { + "description": "The send time for the winning version.", + "title": "Send Time Winner", + "type": [ + "null", + "string" + ] + }, + "split_size": { + "description": "The size of the split groups. Campaigns split based on 'schedule' are forced to have a 50/50 split. Valid split integers are between 1-50.", + "maximum": 50, + "minimum": 1, + "title": "Split Size", + "type": "integer" + }, + "split_test": { + "description": "The type of AB split to run.", + "enum": [ + "subject", + "from_name", + "schedule" + ], + "title": "Split Test", + "type": [ + "null", + "string" + ] + }, + "subject_a": { + "description": "For campaigns split on 'Subject Line', the subject line for Group A.", + "title": "Subject Line Group A", + "type": [ + "null", + "string" + ] + }, + "subject_b": { + "description": "For campaigns split on 'Subject Line', the subject line for Group B.", + "title": "Subject Line Group B", + "type": [ + "null", + "string" + ] + }, + "wait_time": { + "description": "The amount of time to wait before picking a winner. This cannot be changed after a campaign is sent.", + "title": "Wait Time", + "type": "integer" + }, + "wait_units": { + "description": "How unit of time for measuring the winner ('hours' or 'days'). This cannot be changed after a campaign is sent.", + "enum": [ + "hours", + "days" + ], + "title": "Wait Time", + "type": [ + "null", + "string" + ] + } + }, + "readOnly": true, + "title": "A/B Testing Options", + "type": "object" + }, + "archive_url": { + "description": "The link to the campaign's archive version in ISO 8601 format.", + "readOnly": true, + "title": "Archive URL", + "type": [ + "null", + "string" + ] + }, + "content_type": { + "description": "How the campaign's content is put together.", + "enum": [ + "template", + "html", + "url", + "multichannel" + ], + "title": "Content Type", + "type": [ + "null", + "string" + ] + }, + "create_time": { + "description": "The date and time the campaign was created in ISO 8601 format.", + "format": "date-time", + "readOnly": true, + "title": "Create Time", + "type": "string" + }, + "delivery_status": { + "description": "Updates on campaigns in the process of sending.", + "properties": { + "can_cancel": { + "description": "Whether a campaign send can be canceled.", + "readOnly": true, + "title": "Campaign Cancelable", + "type": "boolean" + }, + "emails_canceled": { + "description": "The total number of emails canceled for this campaign.", + "readOnly": true, + "title": "Emails Canceled", + "type": "integer" + }, + "emails_sent": { + "description": "The total number of emails confirmed sent for this campaign so far.", + "readOnly": true, + "title": "Emails Sent", + "type": "integer" + }, + "enabled": { + "description": "Whether Campaign Delivery Status is enabled for this account and campaign.", + "readOnly": true, + "title": "Delivery Status Enabled", + "type": "boolean" + }, + "status": { + "description": "The current state of a campaign delivery.", + "enum": [ + "delivering", + "delivered", + "canceling", + "canceled" + ], + "readOnly": true, + "title": "Campaign Delivery Status", + "type": [ + "null", + "string" + ] + } + }, + "title": "Campaign Delivery Status", + "type": "object" + }, + "emails_sent": { + "description": "The total number of emails sent for this campaign.", + "readOnly": true, + "title": "Emails Sent", + "type": "integer" + }, + "id": { + "description": "A string that uniquely identifies this campaign.", + "readOnly": true, + "title": "Campaign ID", + "type": "string" + }, + "long_archive_url": { + "description": "The original link to the campaign's archive version.", + "readOnly": true, + "title": "Long Archive URL", + "type": [ + "null", + "string" + ] + }, + "needs_block_refresh": { + "description": "Determines if the campaign needs its blocks refreshed by opening the web-based campaign editor. Deprecated and will always return false.", + "readOnly": true, + "title": "Needs Block Refresh", + "type": "boolean" + }, + "parent_campaign_id": { + "description": "If this campaign is the child of another campaign, this identifies the parent campaign. For Example, for RSS or Automation children.", + "readOnly": true, + "title": "Parent Campaign ID", + "type": [ + "null", + "string" + ] + }, + "recipients": { + "description": "List settings for the campaign.", + "properties": { + "list_id": { + "description": "The unique list id.", + "title": "List ID", + "type": [ + "null", + "string" + ] + }, + "list_is_active": { + "description": "The status of the list used, namely if it's deleted or disabled.", + "readOnly": true, + "title": "List Status", + "type": "boolean" + }, + "list_name": { + "description": "The name of the list.", + "readOnly": true, + "title": "List Name", + "type": [ + "null", + "string" + ] + }, + "recipient_count": { + "description": "Count of the recipients on the associated list. Formatted as an integer.", + "readOnly": true, + "title": "Recipient Count", + "type": "integer" + }, + "segment_opts": { + "description": "An object representing all segmentation options. This object should contain a `saved_segment_id` to use an existing segment, or you can create a new segment by including both `match` and `conditions` options.", + "properties": { + "conditions": { + "description": "Segment match conditions. There are multiple possible types, see the [condition types documentation](https://mailchimp.com/developer/marketing/docs/alternative-schemas/#segment-condition-schemas).", + "items": { + "oneOf": [ + { + "description": "Segment by interaction with a specific campaign.", + "properties": { + "condition_type": { + "enum": [ + "Aim" + ], + "type": "string", + "x-value": "Aim" + }, + "field": { + "description": "Segment by interaction with a specific campaign.", + "enum": [ + "aim" + ], + "example": "aim", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "The status of the member with regard to their campaign interaction. One of the following: opened, clicked, was sent, didn't open, didn't click, or was not sent.", + "enum": [ + "open", + "click", + "sent", + "noopen", + "noclick", + "nosent" + ], + "example": "open", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "Either the web id value for a specific campaign or 'any' to account for subscribers who have/have not interacted with any campaigns.", + "example": "any", + "title": "Segment Data", + "type": "string" + } + }, + "title": "Aim Segment", + "type": "object" + }, + { + "description": "Segment by interaction with an Automation workflow.", + "properties": { + "condition_type": { + "enum": [ + "Automation" + ], + "type": "string", + "x-value": "Automation" + }, + "field": { + "description": "Segment by interaction with an Automation workflow.", + "enum": [ + "automation" + ], + "example": "automation", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "The status of the member with regard to the automation workflow. One of the following: has started the workflow, has completed the workflow, has not started the workflow, or has not completed the workflow.", + "enum": [ + "started", + "completed", + "not_started", + "not_completed" + ], + "example": "started", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The web id for the automation workflow to segment against.", + "example": "2135217", + "title": "Segment Data", + "type": "string" + } + }, + "required": [ + "field", + "op", + "value" + ], + "title": "Automation Segment", + "type": "object" + }, + { + "description": "Segment by poll activity.", + "properties": { + "condition_type": { + "enum": [ + "CampaignPoll" + ], + "type": "string", + "x-value": "CampaignPoll" + }, + "field": { + "description": "Segment by poll activity.", + "enum": [ + "poll" + ], + "example": "poll", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Members have/have not interacted with a specific poll in a Mailchimp email.", + "enum": [ + "member", + "notmember" + ], + "example": "member", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The id for the poll.", + "example": 409, + "title": "Segment Operator", + "type": "number" + } + }, + "required": [ + "field", + "op", + "value" + ], + "title": "Poll Activity Segment", + "type": "object" + }, + { + "description": "Segment by interaction with a campaign via Conversations.", + "properties": { + "condition_type": { + "enum": [ + "Conversation" + ], + "type": "string", + "x-value": "Conversation" + }, + "field": { + "description": "Segment by interaction with a campaign via Conversations.", + "enum": [ + "conversation" + ], + "example": "conversation", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "The status of a member's interaction with a conversation. One of the following: has replied or has not replied.", + "enum": [ + "member", + "notmember" + ], + "example": "member", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The web id value for a specific campaign or 'any' to account for subscribers who have/have not interacted with any campaigns.", + "example": "any", + "title": "Segment Data", + "type": "string" + } + }, + "required": [ + "field", + "op", + "value" + ], + "title": "Conversation Segment", + "type": "object" + }, + { + "description": "Segment by a specific date field.", + "properties": { + "condition_type": { + "enum": [ + "Date" + ], + "type": "string", + "x-value": "Date" + }, + "extra": { + "description": "When segmenting on 'date' or 'campaign', the date for the segment formatted as YYYY-MM-DD or the web id for the campaign.", + "example": "2015-01-30", + "title": "Segment Extra Value", + "type": "string" + }, + "field": { + "description": "The type of date field to segment on: The opt-in time for a signup, the date the subscriber was last updated, or the date of their last ecomm purchase.", + "enum": [ + "timestamp_opt", + "info_changed", + "ecomm_date" + ], + "example": "timestamp_opt", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "When the event took place: Before, after, is a specific date, is not a specific date, is blank, or is not blank.", + "enum": [ + "greater", + "less", + "is", + "not", + "blank", + "blank_not", + "within", + "notwithin" + ], + "example": "greater", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "What type of data to segment on: a specific date, a specific campaign, or the last campaign sent.", + "example": "date", + "title": "Segment Data", + "type": "string" + } + }, + "required": [ + "field", + "op", + "value" + ], + "title": "Date Segment", + "type": "object" + }, + { + "description": "Segment by use of a particular email client.", + "properties": { + "condition_type": { + "enum": [ + "EmailClient" + ], + "type": "string", + "x-value": "EmailClient" + }, + "field": { + "description": "Segment by use of a particular email client.", + "enum": [ + "email_client" + ], + "example": "email_client", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "The operation to determine whether we select clients that match the value, or clients that do not match the value.", + "enum": [ + "client_is", + "client_not" + ], + "example": "client_is", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The name of the email client.", + "example": "Gmail", + "title": "Segment Data", + "type": "string" + } + }, + "required": [ + "field", + "op", + "value" + ], + "title": "Email Client Segment", + "type": "object" + }, + { + "description": "Segment by language.", + "properties": { + "condition_type": { + "enum": [ + "Language" + ], + "type": "string", + "x-value": "Language" + }, + "field": { + "description": "Segmenting based off of a subscriber's language.", + "enum": [ + "language" + ], + "example": "language", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Whether the member's language is or is not set to a specific language.", + "enum": [ + "is", + "not" + ], + "example": "is", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "A two-letter language identifier.", + "example": "en", + "title": "Segment Data", + "type": "string" + } + }, + "required": [ + "field", + "op", + "value" + ], + "title": "Language Segment", + "type": "object" + }, + { + "description": "Segment by member rating.", + "properties": { + "condition_type": { + "enum": [ + "MemberRating" + ], + "type": "string", + "x-value": "MemberRating" + }, + "field": { + "description": "Segment by member rating.", + "enum": [ + "rating" + ], + "example": "rating", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Members who have have a rating that is/not exactly a given number or members who have a rating greater/less than a given number.", + "enum": [ + "is", + "not", + "greater", + "less" + ], + "example": "greater", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The star rating number to segment against.", + "example": 4, + "title": "Segment Operator", + "type": "number" + } + }, + "required": [ + "field", + "op", + "value" + ], + "title": "Member Rating Segment", + "type": "object" + }, + { + "description": "Segment by signup source.", + "properties": { + "condition_type": { + "enum": [ + "SignupSource" + ], + "title": "Type", + "type": "string", + "x-value": "SignupSource" + }, + "field": { + "enum": [ + "source" + ], + "example": "source", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Whether the member's signup source was/was not a particular value.", + "enum": [ + "source_is", + "source_not" + ], + "example": "source_is", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The signup source.", + "example": "List Import", + "title": "Segment Data", + "type": "string" + } + }, + "required": [ + "field", + "condition_type", + "op" + ], + "title": "Signup Source Segment", + "type": "object" + }, + { + "description": "Segment by interaction with a SurveyMonkey survey.", + "properties": { + "condition_type": { + "enum": [ + "SurveyMonkey" + ], + "type": "string", + "x-value": "SurveyMonkey" + }, + "field": { + "description": "Segment by interaction with a SurveyMonkey survey.", + "enum": [ + "survey_monkey" + ], + "example": "survey_monkey", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "The status of the member with regard to the survey. One of the following: has started the survey, has completed the survey, has not started the survey, or has not completed the survey.", + "enum": [ + "started", + "completed", + "not_started", + "not_completed" + ], + "example": "started", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The unique ID of the SurveyMonkey survey.", + "example": "32179586", + "title": "Survey ID", + "type": "string" + } + }, + "required": [ + "field", + "op", + "value" + ], + "title": "SurveyMonkey Segment", + "type": "object" + }, + { + "description": "Segment by VIP status.", + "properties": { + "condition_type": { + "enum": [ + "VIP" + ], + "type": "string", + "x-value": "VIP" + }, + "field": { + "description": "Segment by VIP status.", + "enum": [ + "gmonkey" + ], + "example": "gmonkey", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Whether the member is or is not marked as VIP.", + "enum": [ + "member", + "notmember" + ], + "example": "member", + "title": "Segment Operator", + "type": "string" + } + }, + "required": [ + "field", + "op" + ], + "title": "VIP Segment", + "type": "object" + }, + { + "description": "Segment by an interest group merge field.", + "properties": { + "condition_type": { + "enum": [ + "Interests" + ], + "type": "string", + "x-value": "Interests" + }, + "field": { + "description": "Segmenting based on interest group information. This should start with 'interests-' followed by the grouping id. Ex. 'interests-123'.", + "example": "interests-123", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Whether the member is a part of one, all, or none of the groups.", + "enum": [ + "interestcontains", + "interestcontainsall", + "interestnotcontains" + ], + "example": "interestcontains", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "An array containing strings, each representing a group id.", + "items": { + "example": [ + "44401", + "44405", + "44409" + ], + "type": "string" + }, + "title": "Segment Value", + "type": "array" + } + }, + "title": "Interests Segment", + "type": "object" + }, + { + "description": "Segment by purchases in specific items or categories.", + "properties": { + "condition_type": { + "enum": [ + "EcommCategory" + ], + "type": "string", + "x-value": "EcommCategory" + }, + "field": { + "description": "Segment by purchases in specific items or categories.", + "enum": [ + "ecomm_cat", + "ecomm_prod" + ], + "example": "ecomm_cat", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "A member who has purchased from a category/specific item that is/is not a specific name, where the category/item name contains/doesn't contain a specific phrase or string, or a category/item name that starts/ends with a string.", + "enum": [ + "is", + "not", + "contains", + "notcontain", + "starts", + "ends" + ], + "example": "is", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The ecommerce category/item information.", + "example": "Product", + "title": "Segment Data", + "type": "string" + } + }, + "title": "Ecommerce Category Segment", + "type": "object" + }, + { + "description": "Segment by average spent total, number of orders, total number of products purchased, or average number of products per order.", + "properties": { + "condition_type": { + "enum": [ + "EcommNumber" + ], + "type": "string", + "x-value": "EcommNumber" + }, + "field": { + "description": "Segment by average spent total, number of orders, total number of products purchased, or average number of products per order.", + "enum": [ + "ecomm_spent_avg", + "ecomm_orders", + "ecomm_prod_all", + "ecomm_avg_ord" + ], + "example": "ecomm_orders", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Members who have spent exactly, have not spent exactly, spent more, or spent less than the segment value.", + "enum": [ + "is", + "not", + "greater", + "less" + ], + "example": "greater", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "Members who have spent exactly, have not spent exactly, spent more, or spent less than this amount.", + "example": 42, + "title": "Segment Operator", + "type": "number" + } + }, + "required": [ + "field", + "op", + "value" + ], + "title": "Ecommerce Number Segment", + "type": "object" + }, + { + "description": "Segment by whether someone has purchased anything.", + "properties": { + "condition_type": { + "enum": [ + "EcommPurchased" + ], + "type": "string", + "x-value": "EcommPurchased" + }, + "field": { + "description": "Segment by whether someone has purchased anything.", + "enum": [ + "ecomm_purchased" + ], + "example": "ecomm_purchased", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Members who have have ('member') or have not ('notmember') purchased.", + "enum": [ + "member", + "notmember" + ], + "example": "member", + "title": "Segment Operator", + "type": "string" + } + }, + "title": "Ecommerce Purchased Segment", + "type": "object" + }, + { + "description": "Segment by amount spent on a single order or across all orders.", + "properties": { + "condition_type": { + "enum": [ + "EcommSpent" + ], + "type": "string", + "x-value": "EcommSpent" + }, + "field": { + "description": "Segment by amount spent on a single order or across all orders.", + "enum": [ + "ecomm_spent_one", + "ecomm_spent_all" + ], + "example": "ecomm_spent_one", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Members who have spent 'more' or 'less' than then specified value.", + "enum": [ + "greater", + "less" + ], + "example": "greater", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The total amount a member spent.", + "example": 42, + "title": "Segment Data", + "type": "integer" + } + }, + "title": "Ecommerce Spent Segment", + "type": "object" + }, + { + "description": "Segment by purchases from a specific store.", + "properties": { + "condition_type": { + "enum": [ + "EcommStore" + ], + "type": "string", + "x-value": "EcommStore" + }, + "field": { + "description": "Segment by purchases from a specific store.", + "enum": [ + "ecomm_store" + ], + "example": "ecomm_store", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Members who have or have not purchased from a specific store.", + "enum": [ + "is", + "not" + ], + "example": "is", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The store id to segment against.", + "example": "289", + "title": "Segment Operator", + "type": "string" + } + }, + "title": "Ecommerce Purchased Store Segment", + "type": "object" + }, + { + "description": "Segment by Goal activity.", + "properties": { + "condition_type": { + "enum": [ + "GoalActivity" + ], + "type": "string", + "x-value": "GoalActivity" + }, + "field": { + "description": "Segment by Goal activity.", + "enum": [ + "goal" + ], + "example": "goal", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Whether the website URL is/not exactly, contains/doesn't contain, starts with/ends with a string.", + "enum": [ + "is", + "goal_not", + "contains", + "goal_notcontain", + "starts", + "ends" + ], + "example": "is", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The URL to check Goal activity against.", + "title": "Segment Value", + "type": "string" + } + }, + "required": [ + "field", + "op", + "value" + ], + "title": "Goal Activity Segment", + "type": "object" + }, + { + "description": "Segment by most recent interaction with a website.", + "properties": { + "condition_type": { + "enum": [ + "GoalTimestamp" + ], + "type": "string", + "x-value": "GoalTimestamp" + }, + "field": { + "description": "Segment by most recent interaction with a website.", + "enum": [ + "goal_last_visited" + ], + "example": "goal_last_visited", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Whether the website activity happened after, before, or at a given timestamp.", + "enum": [ + "greater", + "less", + "is" + ], + "example": "greater", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The date to check Goal activity against.", + "example": "2015-07-20 19:45:21", + "title": "Segment Value", + "type": "string" + } + }, + "required": [ + "field", + "op", + "value" + ], + "title": "Goal Timestamp Segment", + "type": "object" + }, + { + "description": "Segment by similar subscribers.", + "properties": { + "condition_type": { + "enum": [ + "FuzzySegment" + ], + "type": "string", + "x-value": "FuzzySegment" + }, + "field": { + "description": "Segment by similar subscribers.", + "enum": [ + "fuzzy_segment" + ], + "example": "fuzzy_segment", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Members who are/are not apart of a 'similar subscribers' segment.", + "enum": [ + "fuzzy_is", + "fuzzy_not" + ], + "example": "fuzzy_is", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The id for the 'similar subscribers' segment.", + "example": 48433, + "title": "Segment Operator", + "type": "number" + } + }, + "required": [ + "field", + "op", + "value" + ], + "title": "Similar Subscribers Segment Member Segment", + "type": "object" + }, + { + "description": "Segment by a given static segment.", + "properties": { + "condition_type": { + "enum": [ + "StaticSegment" + ], + "type": "string", + "x-value": "StaticSegment" + }, + "field": { + "description": "Segment by a given static segment.", + "enum": [ + "static_segment" + ], + "example": "static_segment", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Members who are/are not apart of a static segment.", + "enum": [ + "static_is", + "static_not" + ], + "example": "static_is", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The id for the static segment.", + "example": 48433, + "title": "Segment Operator", + "type": "number" + } + }, + "required": [ + "field", + "op", + "value" + ], + "title": "Static Segment Member Segment", + "type": "object" + }, + { + "description": "Segment by a specific country or US state.", + "properties": { + "condition_type": { + "enum": [ + "IPGeoCountryState" + ], + "type": "string", + "x-value": "IPGeoCountryState" + }, + "field": { + "description": "Segmenting subscribers who are within a specific location.", + "enum": [ + "ipgeo" + ], + "example": "ipgeo", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Segment members who are within a specific country or US state.", + "enum": [ + "ipgeocountry", + "ipgeonotcountry", + "ipgeostate", + "ipgeonotstate" + ], + "example": "ipgeocountry", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The two-letter country code or US state abbreviation.", + "example": "US", + "title": "Segment Data", + "type": "string" + } + }, + "required": [ + "field", + "op", + "value" + ], + "title": "Location-Based Segment", + "type": "object" + }, + { + "description": "Segment by a specific geographic region.", + "properties": { + "addr": { + "description": "The address of the target location.", + "example": "Atlanta, GA, USA", + "title": "Segment Location Address", + "type": "string" + }, + "condition_type": { + "enum": [ + "IPGeoIn" + ], + "type": "string", + "x-value": "IPGeoIn" + }, + "field": { + "description": "Segmenting subscribers who are within a specific location.", + "enum": [ + "ipgeo" + ], + "example": "ipgeo", + "title": "Segment Field", + "type": "string" + }, + "lat": { + "description": "The latitude of the target location.", + "example": "33.7489954", + "title": "Segment Location Latitude", + "type": "string" + }, + "lng": { + "description": "The longitude of the target location.", + "example": "-84.3879824", + "title": "Segment Location Longitude", + "type": "string" + }, + "op": { + "description": "Segment members who are within a specific geographic region.", + "enum": [ + "ipgeoin", + "ipgeonotin" + ], + "example": "ipgeoin", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The radius of the target location.", + "example": 42, + "title": "Segment Data", + "type": "integer" + } + }, + "required": [ + "field", + "op", + "value", + "addr", + "lat", + "lng" + ], + "title": "Geolocation Segment", + "type": "object" + }, + { + "description": "Segment by a specific US ZIP code.", + "properties": { + "condition_type": { + "enum": [ + "IPGeoInZip" + ], + "type": "string", + "x-value": "IPGeoInZip" + }, + "extra": { + "description": "The zip code to segment against.", + "example": 30318, + "title": "Extra Data", + "type": "integer" + }, + "field": { + "description": "Segmenting subscribers who are within a specific location.", + "enum": [ + "ipgeo" + ], + "example": "ipgeo", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Segment members who are within a specific US zip code.", + "enum": [ + "ipgeoinzip" + ], + "example": "ipgeoinzip", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The radius of the target location.", + "example": 25, + "title": "Segment Data", + "type": "integer" + } + }, + "required": [ + "field", + "op", + "value", + "extra" + ], + "title": "US Zip Code Segment", + "type": "object" + }, + { + "description": "Segment members whose location information is unknown.", + "properties": { + "condition_type": { + "enum": [ + "IPGeoUnknown" + ], + "type": "string", + "x-value": "IPGeoUnknown" + }, + "field": { + "description": "Segmenting subscribers who are within a specific location.", + "enum": [ + "ipgeo" + ], + "example": "ipgeo", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Segment members for which location information is unknown.", + "enum": [ + "ipgeounknown" + ], + "example": "ipgeounknown", + "title": "Segment Operator", + "type": "string" + } + }, + "required": [ + "field", + "op" + ], + "title": "Unknown Location-Based Segment", + "type": "object" + }, + { + "description": "Segment by a specific US ZIP code.", + "properties": { + "condition_type": { + "enum": [ + "IPGeoZip" + ], + "type": "string", + "x-value": "IPGeoZip" + }, + "field": { + "description": "Segmenting subscribers who are within a specific location.", + "enum": [ + "ipgeo" + ], + "example": "ipgeo", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Segment members who are/are not within a specific US zip code.", + "enum": [ + "ipgeoiszip", + "ipgeonotzip" + ], + "example": "ipgeonotzip", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The 5-digit zip code.", + "example": 30318, + "title": "Segment Data", + "type": "integer" + } + }, + "required": [ + "field", + "op", + "value" + ], + "title": "Zip Code Location-Based Segment", + "type": "object" + }, + { + "description": "Segment by age ranges in Social Profiles data.", + "properties": { + "condition_type": { + "enum": [ + "SocialAge" + ], + "type": "string", + "x-value": "SocialAge" + }, + "field": { + "description": "Segment by age ranges in Social Profiles data.", + "enum": [ + "social_age" + ], + "example": "social_age", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Members who are/not the exact criteria listed.", + "enum": [ + "is", + "not" + ], + "example": "is", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The age range to segment.", + "enum": [ + "18-24", + "25-34", + "35-54", + "55+" + ], + "example": "35-54", + "title": "Segment Operator", + "type": "string" + } + }, + "required": [ + "field", + "op", + "value" + ], + "title": "Social Profiles Age Segment", + "type": "object" + }, + { + "description": "Segment by listed gender in Social Profiles data.", + "properties": { + "condition_type": { + "enum": [ + "SocialGender" + ], + "type": "string", + "x-value": "SocialGender" + }, + "field": { + "description": "Segment by listed gender in Social Profiles data.", + "enum": [ + "social_gender" + ], + "example": "social_gender", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Members who are/not the exact criteria listed.", + "enum": [ + "is", + "not" + ], + "example": "is", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The Social Profiles gender to segment.", + "enum": [ + "male", + "female" + ], + "example": "female", + "title": "Segment Operator", + "type": "string" + } + }, + "required": [ + "field", + "op", + "value" + ], + "title": "Social Profiles Gender Segment", + "type": "object" + }, + { + "description": "Segment by influence rating in Social Profiles data.", + "properties": { + "condition_type": { + "enum": [ + "SocialInfluence" + ], + "type": "string", + "x-value": "SocialInfluence" + }, + "field": { + "description": "Segment by influence rating in Social Profiles data.", + "enum": [ + "social_influence" + ], + "example": "social_influence", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Members who have a rating that is/not or greater/less than the rating provided.", + "enum": [ + "is", + "not", + "greater", + "less" + ], + "example": "greater", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The Social Profiles influence rating to segment.", + "example": 2, + "title": "Segment Operator", + "type": "number" + } + }, + "required": [ + "field", + "op", + "value" + ], + "title": "Social Profiles Influence Segment", + "type": "object" + }, + { + "description": "Segment by social network in Social Profiles data.", + "properties": { + "condition_type": { + "enum": [ + "SocialNetworkMember" + ], + "type": "string", + "x-value": "SocialNetworkMember" + }, + "field": { + "description": "Segment by social network in Social Profiles data.", + "enum": [ + "social_network" + ], + "example": "social_network", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Members who are/not on a given social network.", + "enum": [ + "member", + "notmember" + ], + "example": "member", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The social network to segment against.", + "enum": [ + "twitter", + "facebook", + "linkedin", + "flickr", + "foursquare", + "lastfm", + "myspace", + "quora", + "vimeo", + "yelp", + "youtube" + ], + "example": "twitter", + "title": "Segment Operator", + "type": "string" + } + }, + "required": [ + "field", + "op", + "value" + ], + "title": "Social Profiles Social Network Segment", + "type": "object" + }, + { + "description": "Segment by social network in Social Profiles data.", + "properties": { + "condition_type": { + "enum": [ + "SocialNetworkFollow" + ], + "type": "string", + "x-value": "SocialNetworkFollow" + }, + "field": { + "description": "Segment by social network in Social Profiles data.", + "enum": [ + "social_network" + ], + "example": "social_network", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Members who are/not following a linked account on a given social network.", + "enum": [ + "follow", + "notfollow" + ], + "example": "follow", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The social network to segment against.", + "enum": [ + "twitter_follow" + ], + "example": "twitter_follow", + "title": "Segment Operator", + "type": "string" + } + }, + "required": [ + "field", + "op", + "value" + ], + "title": "Social Profiles Social Network Follow Segment", + "type": "object" + }, + { + "description": "Segment by an address-type merge field.", + "properties": { + "condition_type": { + "enum": [ + "AddressMerge" + ], + "type": "string", + "x-value": "AddressMerge" + }, + "field": { + "description": "An address-type merge field to segment.", + "example": "MMERGE3", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Whether the member's address merge field contains/does not contain a value or is/is not blank.", + "enum": [ + "contains", + "notcontain", + "blank", + "blank_not" + ], + "example": "contains", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The value to segment a text merge field with.", + "example": "Atlanta", + "title": "Segment Value", + "type": "string" + } + }, + "required": [ + "field", + "op" + ], + "title": "Address Merge Field Segment", + "type": "object" + }, + { + "description": "Segment by an address-type merge field within a given distance.", + "properties": { + "condition_type": { + "enum": [ + "ZipMerge" + ], + "type": "string", + "x-value": "ZipMerge" + }, + "extra": { + "description": "The city or the zip being used to segment against.", + "example": "30318", + "title": "Segment Extra", + "type": "string" + }, + "field": { + "description": "An address or zip-type merge field to segment.", + "example": "MMERGE2", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Whether the member's address merge field is within a given distance from a city or zip.", + "enum": [ + "geoin" + ], + "example": "geoin", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The distance from the city/zip.", + "example": "25", + "title": "Segment Value", + "type": "string" + } + }, + "required": [ + "field", + "op", + "value", + "extra" + ], + "title": "Address/Zip Merge Field Segment", + "type": "object" + }, + { + "description": "Segment by a contact's birthday.", + "properties": { + "condition_type": { + "enum": [ + "BirthdayMerge" + ], + "type": "string", + "x-value": "BirthdayMerge" + }, + "field": { + "description": "A date merge field to segment.", + "example": "MMERGE4", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Whether the member's birthday merge information is/is not a certain date or is/is not blank.", + "enum": [ + "is", + "not", + "blank", + "blank_not" + ], + "example": "is", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "A date to segment against (mm/dd).", + "example": "01/30", + "title": "Segment Value", + "type": "string" + } + }, + "required": [ + "field", + "op" + ], + "title": "Birthday Merge Field Segment", + "type": "object" + }, + { + "description": "Segment by a given date merge field.", + "properties": { + "condition_type": { + "enum": [ + "DateMerge" + ], + "type": "string", + "x-value": "DateMerge" + }, + "field": { + "description": "A date merge field to segment.", + "example": "MMERGE5", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Whether the member's merge information is/is not, is greater/less than a value or is/is not blank.", + "enum": [ + "is", + "not", + "less", + "blank", + "blank_not", + "greater" + ], + "example": "is", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "A date to segment against.", + "example": "01/30/2015", + "title": "Segment Value", + "type": "string" + } + }, + "required": [ + "field", + "op" + ], + "title": "Date Merge Field Segment", + "type": "object" + }, + { + "description": "An individual segment condition", + "properties": { + "condition_type": { + "enum": [ + "SelectMerge" + ], + "type": "string", + "x-value": "SelectMerge" + }, + "field": { + "description": "A merge field to segment.", + "example": "MMERGE6", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Whether the member's merge information is/is not a value or is/is not blank.", + "enum": [ + "is", + "not", + "blank", + "blank_not", + "notcontain", + "contains" + ], + "example": "is", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The value to segment a text merge field with.", + "example": "Second Choice", + "title": "Segment Value", + "type": "string" + } + }, + "required": [ + "field", + "op" + ], + "title": "Dropdown/Radio Merge Field Segment", + "type": "object" + }, + { + "description": "Segment by a given text or number merge field.", + "properties": { + "condition_type": { + "enum": [ + "TextMerge" + ], + "type": "string", + "x-value": "TextMerge" + }, + "field": { + "description": "A text or number merge field to segment.", + "example": "MMERGE7", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Whether the member's merge information is/is not, contains/does not contain, starts/ends with, or is greater/less than a value", + "enum": [ + "is", + "not", + "contains", + "notcontain", + "starts", + "ends", + "greater", + "less", + "blank", + "blank_not" + ], + "example": "contains", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The value to segment a text or number merge field with.", + "example": "Freddie's Jokes", + "title": "Segment Value", + "type": "string" + } + }, + "required": [ + "field", + "op" + ], + "title": "Text or Number Merge Field Segment", + "type": "object" + }, + { + "description": "Segment by email address.", + "properties": { + "condition_type": { + "enum": [ + "EmailAddress" + ], + "type": "string", + "x-value": "EmailAddress" + }, + "field": { + "description": "Segmenting based off of a subscriber's email address.", + "enum": [ + "merge0", + "EMAIL" + ], + "example": "EMAIL", + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Whether the email address is/not exactly, contains/doesn't contain, starts/ends with a string.", + "enum": [ + "is", + "not", + "contains", + "notcontain", + "starts", + "ends", + "greater", + "less" + ], + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The value to compare the email against.", + "example": "urist.mcvankab@freddiesjokes.com", + "title": "Segment Value", + "type": "string" + } + }, + "required": [ + "field", + "op" + ], + "title": "Email Segment", + "type": "object" + }, + { + "description": "Segment by predicted gender.", + "properties": { + "condition_type": { + "enum": [ + "PredictedGender" + ], + "type": "string", + "x-value": "PredictedGender" + }, + "field": { + "description": "Segment by predicted gender.", + "enum": [ + "predicted_gender" + ], + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Members who are/not the exact criteria listed.", + "enum": [ + "is", + "not" + ], + "example": "is", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The predicted gender to segment.", + "enum": [ + "male", + "female" + ], + "example": "female", + "title": "Segment Operator", + "type": "string" + } + }, + "required": [ + "field", + "op", + "value" + ], + "title": "Predicted Gender Segment", + "type": "object" + }, + { + "description": "Segment by predicted age.", + "properties": { + "condition_type": { + "enum": [ + "PredictedAge" + ], + "type": "string", + "x-value": "PredictedAge" + }, + "field": { + "description": "Segment by predicted age.", + "enum": [ + "predicted_age_range" + ], + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Members who are/not the exact criteria listed.", + "enum": [ + "is" + ], + "example": "is", + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "The predicted age to segment.", + "enum": [ + "18-24", + "25-34", + "35-44", + "45-54", + "55-64", + "65+" + ], + "example": "female", + "title": "Segment Operator", + "type": "string" + } + }, + "required": [ + "field", + "op", + "value" + ], + "title": "Predicted Age Segment", + "type": "object" + }, + { + "description": "Segment by when people subscribed.", + "properties": { + "condition_type": { + "enum": [ + "NewSubscribers" + ], + "type": "string", + "x-value": "NewSubscribers" + }, + "field": { + "description": "Segment by when people subscribed.", + "enum": [ + "timestamp_opt" + ], + "title": "Segment Field", + "type": "string" + }, + "op": { + "description": "Whe the event took place, namely within a time frame.", + "enum": [ + "date_within" + ], + "title": "Segment Operator", + "type": "string" + }, + "value": { + "description": "What type of data to segment on: a specific date, a specific campaign, or the last campaign sent.", + "title": "Segment Data", + "type": "string" + } + }, + "title": "New Subscribers Prebuilt Segment", + "type": "object" + } + ], + "x-discriminator": { + "propertyName": "condition_type" + } + }, + "title": "Segment Type", + "type": "array" + }, + "match": { + "description": "Segment match type.", + "enum": [ + "any", + "all" + ], + "title": "Match Type", + "type": "string" + }, + "prebuilt_segment_id": { + "description": "The prebuilt segment id, if a prebuilt segment has been designated for this campaign.", + "example": "subscribers-female", + "title": "Prebuilt Segment Id", + "type": "string" + }, + "saved_segment_id": { + "description": "The id for an existing saved segment.", + "title": "Saved Segment ID", + "type": "integer" + } + }, + "title": "Segment Options", + "type": "object" + }, + "segment_text": { + "description": "A description of the [segment](https://mailchimp.com/help/create-and-send-to-a-segment/) used for the campaign. Formatted as a string marked up with HTML.", + "readOnly": true, + "title": "Segment Text", + "type": [ + "null", + "string" + ] + } + }, + "title": "List", + "type": "object" + }, + "report_summary": { + "description": "For sent campaigns, a summary of opens, clicks, and e-commerce data.", + "properties": { + "click_rate": { + "description": "The number of unique clicks divided by the total number of successful deliveries.", + "readOnly": true, + "title": "Click Rate", + "type": "number" + }, + "clicks": { + "description": "The total number of clicks for an campaign.", + "readOnly": true, + "title": "Total Clicks", + "type": "integer" + }, + "ecommerce": { + "description": "E-Commerce stats for a campaign.", + "properties": { + "total_orders": { + "description": "The total orders for a campaign.", + "readOnly": true, + "title": "Total Orders", + "type": "integer" + }, + "total_revenue": { + "description": "The total revenue for a campaign. Calculated as the sum of all order totals minus shipping and tax totals.", + "readOnly": true, + "title": "Total Revenue", + "type": "number" + }, + "total_spent": { + "description": "The total spent for a campaign. Calculated as the sum of all order totals with no deductions.", + "readOnly": true, + "title": "Total Spent", + "type": "number" + } + }, + "title": "E-Commerce Report", + "type": "object" + }, + "open_rate": { + "description": "The number of unique opens divided by the total number of successful deliveries.", + "readOnly": true, + "title": "Open Rate", + "type": "number" + }, + "opens": { + "description": "The total number of opens for a campaign.", + "readOnly": true, + "title": "Automation Opens", + "type": "integer" + }, + "subscriber_clicks": { + "description": "The number of unique clicks.", + "readOnly": true, + "title": "Unique Subscriber Clicks", + "type": "integer" + }, + "unique_opens": { + "description": "The number of unique opens.", + "readOnly": true, + "title": "Unique Opens", + "type": "integer" + } + }, + "title": "Campaign Report Summary", + "type": "object" + }, + "resendable": { + "description": "Determines if the campaign qualifies to be resent to non-openers.", + "readOnly": true, + "title": "Resendable", + "type": "boolean" + }, + "rss_opts": { + "description": "[RSS](https://mailchimp.com/help/share-your-blog-posts-with-mailchimp/) options for a campaign.", + "properties": { + "constrain_rss_img": { + "description": "Whether to add CSS to images in the RSS feed to constrain their width in campaigns.", + "title": "Constrain RSS Images", + "type": "boolean" + }, + "feed_url": { + "description": "The URL for the RSS feed.", + "format": "uri", + "title": "Feed URL", + "type": [ + "null", + "string" + ] + }, + "frequency": { + "description": "The frequency of the RSS Campaign.", + "enum": [ + "daily", + "weekly", + "monthly" + ], + "title": "Frequency", + "type": [ + "null", + "string" + ] + }, + "last_sent": { + "description": "The date the campaign was last sent.", + "format": "date-time", + "readOnly": true, + "title": "Last Sent", + "type": [ + "null", + "string" + ] + }, + "schedule": { + "description": "The schedule for sending the RSS Campaign.", + "properties": { + "daily_send": { + "description": "The days of the week to send a daily RSS Campaign.", + "properties": { + "friday": { + "description": "Sends the daily RSS Campaign on Fridays.", + "title": "Friday", + "type": "boolean" + }, + "monday": { + "description": "Sends the daily RSS Campaign on Mondays.", + "title": "Monday", + "type": "boolean" + }, + "saturday": { + "description": "Sends the daily RSS Campaign on Saturdays.", + "title": "Saturday", + "type": "boolean" + }, + "sunday": { + "description": "Sends the daily RSS Campaign on Sundays.", + "title": "Sunday", + "type": "boolean" + }, + "thursday": { + "description": "Sends the daily RSS Campaign on Thursdays.", + "title": "Thursday", + "type": "boolean" + }, + "tuesday": { + "description": "Sends the daily RSS Campaign on Tuesdays.", + "title": "tuesday", + "type": "boolean" + }, + "wednesday": { + "description": "Sends the daily RSS Campaign on Wednesdays.", + "title": "Monday", + "type": "boolean" + } + }, + "title": "Daily Sending Days", + "type": "object" + }, + "hour": { + "description": "The hour to send the campaign in local time. Acceptable hours are 0-23. For example, '4' would be 4am in [your account's default time zone](https://mailchimp.com/help/set-account-defaults/).", + "maximum": 23, + "minimum": 0, + "title": "Sending Hour", + "type": "integer" + }, + "monthly_send_date": { + "description": "The day of the month to send a monthly RSS Campaign. Acceptable days are 0-31, where '0' is always the last day of a month. Months with fewer than the selected number of days will not have an RSS campaign sent out that day. For example, RSS Campaigns set to send on the 30th will not go out in February.", + "maximum": 31, + "minimum": 0, + "title": "Monthly Sending Day", + "type": "number" + }, + "weekly_send_day": { + "description": "The day of the week to send a weekly RSS Campaign.", + "enum": [ + "sunday", + "monday", + "tuesday", + "wednesday", + "thursday", + "friday", + "saturday" + ], + "title": "Weekly Sending Day", + "type": [ + "null", + "string" + ] + } + }, + "title": "Sending Schedule", + "type": "object" + } + }, + "title": "RSS Options", + "type": "object" + }, + "send_time": { + "description": "The date and time a campaign was sent.", + "format": "date-time", + "readOnly": true, + "title": "Send Time", + "type": [ + "null", + "string" + ] + }, + "settings": { + "description": "The settings for your campaign, including subject, from name, reply-to address, and more.", + "properties": { + "authenticate": { + "description": "Whether Mailchimp [authenticated](https://mailchimp.com/help/about-email-authentication/) the campaign. Defaults to `true`.", + "title": "Authentication", + "type": "boolean" + }, + "auto_fb_post": { + "description": "An array of [Facebook](https://mailchimp.com/help/connect-or-disconnect-the-facebook-integration/) page ids to auto-post to.", + "items": { + "type": [ + "null", + "string" + ] + }, + "title": "Auto Post to Facebook", + "type": "array" + }, + "auto_footer": { + "description": "Automatically append Mailchimp's [default footer](https://mailchimp.com/help/about-campaign-footers/) to the campaign.", + "title": "Auto-Footer", + "type": "boolean" + }, + "auto_tweet": { + "description": "Automatically tweet a link to the [campaign archive](https://mailchimp.com/help/about-email-campaign-archives-and-pages/) page when the campaign is sent.", + "title": "Auto-Tweet", + "type": "boolean" + }, + "drag_and_drop": { + "description": "Whether the campaign uses the drag-and-drop editor.", + "readOnly": true, + "title": "Drag And Drop Campaign", + "type": "boolean" + }, + "fb_comments": { + "description": "Allows Facebook comments on the campaign (also force-enables the Campaign Archive toolbar). Defaults to `true`.", + "title": "Facebook Comments", + "type": "boolean" + }, + "folder_id": { + "description": "If the campaign is listed in a folder, the id for that folder.", + "title": "Folder ID", + "type": [ + "null", + "string" + ] + }, + "from_name": { + "description": "The 'from' name on the campaign (not an email address).", + "title": "From Name", + "type": [ + "null", + "string" + ] + }, + "inline_css": { + "description": "Automatically inline the CSS included with the campaign content.", + "title": "Inline CSS", + "type": "boolean" + }, + "preview_text": { + "description": "The preview text for the campaign.", + "title": "Campaign Preview Text", + "type": [ + "null", + "string" + ] + }, + "reply_to": { + "description": "The reply-to email address for the campaign.", + "title": "Reply To Address", + "type": [ + "null", + "string" + ] + }, + "subject_line": { + "description": "The subject line for the campaign.", + "title": "Campaign Subject Line", + "type": [ + "null", + "string" + ] + }, + "template_id": { + "description": "The id for the template used in this campaign.", + "readOnly": false, + "title": "Template ID", + "type": "integer" + }, + "timewarp": { + "description": "Send this campaign using [Timewarp](https://mailchimp.com/help/use-timewarp/).", + "readOnly": true, + "title": "Timewarp Send", + "type": "boolean" + }, + "title": { + "description": "The title of the campaign.", + "title": "Campaign Title", + "type": [ + "null", + "string" + ] + }, + "to_name": { + "description": "The campaign's custom 'To' name. Typically the first name [merge field](https://mailchimp.com/help/getting-started-with-merge-tags/).", + "title": "To Name", + "type": [ + "null", + "string" + ] + }, + "use_conversation": { + "description": "Use Mailchimp Conversation feature to manage out-of-office replies.", + "title": "Conversation", + "type": "boolean" + } + }, + "title": "Campaign Settings", + "type": "object" + }, + "social_card": { + "description": "The preview for the campaign, rendered by social networks like Facebook and Twitter. [Learn more](https://mailchimp.com/help/enable-and-customize-social-cards/).", + "properties": { + "description": { + "description": "A short summary of the campaign to display.", + "title": "Campaign Description", + "type": [ + "null", + "string" + ] + }, + "image_url": { + "description": "The url for the header image for the card.", + "title": "Image URL", + "type": [ + "null", + "string" + ] + }, + "title": { + "description": "The title for the card. Typically the subject line of the campaign.", + "title": "Title", + "type": [ + "null", + "string" + ] + } + }, + "title": "Campaign Social Card", + "type": "object" + }, + "status": { + "description": "The current status of the campaign.", + "enum": [ + "save", + "paused", + "schedule", + "sending", + "sent", + "canceled", + "canceling", + "archived" + ], + "readOnly": true, + "title": "Campaign Status", + "type": "string" + }, + "tracking": { + "description": "The tracking options for a campaign.", + "properties": { + "capsule": { + "description": "Capsule tracking options for a campaign. Must be using Mailchimp's built-in Capsule integration.", + "properties": { + "notes": { + "description": "Update contact notes for a campaign based on subscriber email addresses.", + "title": "Capsule Note", + "type": "boolean" + } + }, + "title": "Capsule CRM Tracking", + "type": "object" + }, + "clicktale": { + "description": "The custom slug for [ClickTale](https://mailchimp.com/help/additional-tracking-options-for-campaigns/) tracking (max of 50 bytes).", + "title": "ClickTale Analytics Tracking", + "type": [ + "null", + "string" + ] + }, + "ecomm360": { + "description": "Whether to enable [eCommerce360](https://mailchimp.com/help/connect-your-online-store-to-mailchimp/) tracking.", + "title": "E-commerce Tracking", + "type": "boolean" + }, + "goal_tracking": { + "description": "Whether to enable [Goal](https://mailchimp.com/help/about-connected-sites/) tracking.", + "title": "Mailchimp Goal Tracking", + "type": "boolean" + }, + "google_analytics": { + "description": "The custom slug for [Google Analytics](https://mailchimp.com/help/integrate-google-analytics-with-mailchimp/) tracking (max of 50 bytes).", + "title": "Google Analytics Tracking", + "type": [ + "null", + "string" + ] + }, + "html_clicks": { + "description": "Whether to [track clicks](https://mailchimp.com/help/enable-and-view-click-tracking/) in the HTML version of the campaign. Defaults to `true`. Cannot be set to false for variate campaigns.", + "title": "HTML Click Tracking", + "type": "boolean" + }, + "opens": { + "description": "Whether to [track opens](https://mailchimp.com/help/about-open-tracking/). Defaults to `true`. Cannot be set to false for variate campaigns.", + "title": "Opens", + "type": "boolean" + }, + "salesforce": { + "description": "Salesforce tracking options for a campaign. Must be using Mailchimp's built-in [Salesforce integration](https://mailchimp.com/help/integrate-salesforce-with-mailchimp/).", + "properties": { + "campaign": { + "description": "Create a campaign in a connected Salesforce account.", + "title": "Salesforce Campaign", + "type": "boolean" + }, + "notes": { + "description": "Update contact notes for a campaign based on subscriber email addresses.", + "title": "Salesforce Note", + "type": "boolean" + } + }, + "title": "Salesforce CRM Tracking", + "type": "object" + }, + "text_clicks": { + "description": "Whether to [track clicks](https://mailchimp.com/help/enable-and-view-click-tracking/) in the plain-text version of the campaign. Defaults to `true`. Cannot be set to false for variate campaigns.", + "title": "Plain-Text Click Tracking", + "type": "boolean" + } + }, + "title": "Campaign Tracking Options", + "type": "object" + }, + "type": { + "description": "There are four types of [campaigns](https://mailchimp.com/help/getting-started-with-campaigns/) you can create in Mailchimp. A/B Split campaigns have been deprecated and variate campaigns should be used instead.", + "title": "Campaign Type", + "type": "string" + }, + "variate_settings": { + "description": "The settings specific to A/B test campaigns.", + "properties": { + "combinations": { + "description": "Combinations of possible variables used to build emails.", + "items": { + "properties": { + "content_description": { + "description": "The index of `variate_settings.contents` used.", + "title": "Content Description", + "type": "integer" + }, + "from_name": { + "description": "The index of `variate_settings.from_names` used.", + "title": "From Name", + "type": "integer" + }, + "id": { + "description": "Unique ID for the combination.", + "title": "ID", + "type": [ + "null", + "string" + ] + }, + "recipients": { + "description": "The number of recipients for this combination.", + "title": "Recipients", + "type": "integer" + }, + "reply_to": { + "description": "The index of `variate_settings.reply_to_addresses` used.", + "title": "Reply To", + "type": "integer" + }, + "send_time": { + "description": "The index of `variate_settings.send_times` used.", + "title": "Send Time", + "type": "integer" + }, + "subject_line": { + "description": "The index of `variate_settings.subject_lines` used.", + "title": "Subject Line", + "type": "integer" + } + }, + "type": "object" + }, + "readOnly": true, + "title": "Combinations", + "type": "array" + }, + "contents": { + "description": "Descriptions of possible email contents. To set campaign contents, make a PUT request to /campaigns/{campaign_id}/content with the field 'variate_contents'.", + "items": { + "type": [ + "null", + "string" + ] + }, + "readOnly": true, + "title": "Content Descriptions", + "type": "array" + }, + "from_names": { + "description": "The possible from names. The number of from_names provided must match the number of reply_to_addresses. If no from_names are provided, settings.from_name will be used.", + "items": { + "type": [ + "null", + "string" + ] + }, + "title": "From Names", + "type": "array" + }, + "reply_to_addresses": { + "description": "The possible reply-to addresses. The number of reply_to_addresses provided must match the number of from_names. If no reply_to_addresses are provided, settings.reply_to will be used.", + "items": { + "type": [ + "null", + "string" + ] + }, + "title": "Reply To Addresses", + "type": "array" + }, + "send_times": { + "description": "The possible send times to test. The times provided should be in the format YYYY-MM-DD HH:MM:SS. If send_times are provided to test, the test_size will be set to 100% and winner_criteria will be ignored.", + "items": { + "format": "date-time", + "type": [ + "null", + "string" + ] + }, + "title": "Send Times", + "type": "array" + }, + "subject_lines": { + "description": "The possible subject lines to test. If no subject lines are provided, settings.subject_line will be used.", + "items": { + "type": [ + "null", + "string" + ] + }, + "title": "Subject Lines", + "type": "array" + }, + "test_size": { + "description": "The percentage of recipients to send the test combinations to, must be a value between 10 and 100.", + "title": "Test Size", + "type": "integer" + }, + "wait_time": { + "description": "The number of minutes to wait before choosing the winning campaign. The value of wait_time must be greater than 0 and in whole hours, specified in minutes.", + "title": "Wait Time", + "type": "integer" + }, + "winner_criteria": { + "description": "The combination that performs the best. This may be determined automatically by click rate, open rate, or total revenue -- or you may choose manually based on the reporting data you find the most valuable. For Multivariate Campaigns testing send_time, winner_criteria is ignored. For Multivariate Campaigns with 'manual' as the winner_criteria, the winner must be chosen in the Mailchimp web application.", + "enum": [ + "opens", + "clicks", + "manual", + "total_revenue" + ], + "title": "Winning Criteria", + "type": [ + "null", + "string" + ] + }, + "winning_campaign_id": { + "description": "ID of the campaign that was sent to the remaining recipients based on the winning combination.", + "readOnly": true, + "title": "Winning Campaign ID", + "type": [ + "null", + "string" + ] + }, + "winning_combination_id": { + "description": "ID for the winning combination.", + "readOnly": true, + "title": "Winning Combination ID", + "type": [ + "null", + "string" + ] + } + }, + "title": "A/B Test Options", + "type": "object" + }, + "web_id": { + "description": "The ID used in the Mailchimp web application. View this campaign in your Mailchimp account at `https://{dc}.admin.mailchimp.com/campaigns/show/?id={web_id}`.", + "readOnly": true, + "title": "Campaign Web ID", + "type": "integer" + } + }, + "required": [ + "id" + ], + "title": "Campaign", + "type": "object" + }, + "key": [ + "/id" + ], + "recommendedName": "campaigns", + "resourceConfig": { + "cursorField": [ + "create_time" + ], + "stream": "campaigns", + "syncMode": "incremental" + } + }, + { + "documentSchema": { + "description": "A list of member's subscriber activity in a specific campaign.", + "properties": { + "_meta": { + "properties": { + "row_id": { + "type": "integer" + } + }, + "required": [ + "row_id" + ], + "type": "object" + }, + "action": { + "description": "One of the following actions: 'open', 'click', or 'bounce'", + "enum": [ + "open", + "click", + "bounce" + ], + "title": "action", + "type": "string" + }, + "campaign_id": { + "description": "The unique id for the campaign.", + "title": "The unique id for the campaign.", + "type": "string" + }, + "email_address": { + "description": "Email address for a subscriber.", + "title": "Email address for a subscriber.", + "type": "string" + }, + "email_id": { + "description": "The MD5 hash of the lowercase version of the list member's email address.", + "title": "email MD5 hash.", + "type": "string" + }, + "ip": { + "description": "The IP address recorded for the action.", + "title": "Action ip address", + "type": [ + "string", + "null" + ] + }, + "list_id": { + "description": "The unique id for the list.", + "title": "The unique id for the list.", + "type": "string" + }, + "list_is_active": { + "description": "The status of the list used, namely if it's deleted or disabled.", + "title": "The status of the list used.", + "type": "boolean" + }, + "timestamp": { + "description": "The date and time recorded for the action in ISO 8601 format.", + "format": "date-time", + "title": "Action date and time", + "type": "string" + }, + "type": { + "description": "If the action is a 'bounce', the type of bounce received: 'hard', 'soft'.", + "enum": [ + "hard", + "soft" + ], + "title": "Type", + "type": [ + "string", + "null" + ] + }, + "url": { + "description": "If the action is a 'click', the URL on which the member clicked.", + "title": "Click url", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "timestamp", + "email_id", + "action" + ], + "title": "Email Activity", + "type": "object" + }, + "key": [ + "/timestamp", + "/email_id", + "/action" + ], + "recommendedName": "email_activity", + "resourceConfig": { + "cursorField": [ + "timestamp" + ], + "stream": "email_activity", + "syncMode": "incremental" + } + }, + { + "documentSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "_meta": { + "properties": { + "row_id": { + "type": "integer" + } + }, + "required": [ + "row_id" + ], + "type": "object" + }, + "display_order": { + "type": [ + "null", + "integer" + ] + }, + "id": { + "type": "string" + }, + "list_id": { + "type": [ + "null", + "string" + ] + }, + "title": { + "type": [ + "null", + "string" + ] + }, + "type": { + "type": [ + "null", + "string" + ] + } + }, + "required": [ + "id" + ], + "type": "object" + }, + "key": [ + "/id" + ], + "recommendedName": "interest_categories", + "resourceConfig": { + "stream": "interest_categories", + "syncMode": "full_refresh" + } + }, + { + "documentSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "_meta": { + "properties": { + "row_id": { + "type": "integer" + } + }, + "required": [ + "row_id" + ], + "type": "object" + }, + "category_id": { + "type": [ + "null", + "string" + ] + }, + "display_order": { + "type": [ + "null", + "integer" + ] + }, + "id": { + "type": "string" + }, + "list_id": { + "type": [ + "null", + "string" + ] + }, + "name": { + "type": [ + "null", + "string" + ] + }, + "subscriber_count": { + "type": [ + "null", + "string" + ] + } + }, + "required": [ + "id" + ], + "type": "object" + }, + "key": [ + "/id" + ], + "recommendedName": "interests", + "resourceConfig": { + "stream": "interests", + "syncMode": "full_refresh" + } + }, + { + "documentSchema": { + "description": "Information about a specific list.", + "properties": { + "_meta": { + "properties": { + "row_id": { + "type": "integer" + } + }, + "required": [ + "row_id" + ], + "type": "object" + }, + "beamer_address": { + "description": "The list's [Email Beamer](https://mailchimp.com/help/use-email-beamer-to-create-a-campaign/) address.", + "readOnly": true, + "title": "Beamer Address", + "type": [ + "null", + "string" + ] + }, + "campaign_defaults": { + "description": "[Default values for campaigns](https://mailchimp.com/help/edit-your-emails-subject-preview-text-from-name-or-from-email-address/) created for this list.", + "properties": { + "from_email": { + "description": "The default from email for campaigns sent to this list.", + "title": "Sender's Email Address", + "type": [ + "null", + "string" + ] + }, + "from_name": { + "description": "The default from name for campaigns sent to this list.", + "title": "Sender's Name", + "type": [ + "null", + "string" + ] + }, + "language": { + "description": "The default language for this lists's forms.", + "title": "Language", + "type": [ + "null", + "string" + ] + }, + "subject": { + "description": "The default subject line for campaigns sent to this list.", + "title": "Subject", + "type": [ + "null", + "string" + ] + } + }, + "title": "Campaign Defaults", + "type": "object" + }, + "contact": { + "description": "[Contact information displayed in campaign footers](https://mailchimp.com/help/about-campaign-footers/) to comply with international spam laws.", + "properties": { + "address1": { + "description": "The street address for the list contact.", + "title": "Address", + "type": [ + "null", + "string" + ] + }, + "address2": { + "description": "The street address for the list contact.", + "title": "Address", + "type": [ + "null", + "string" + ] + }, + "city": { + "description": "The city for the list contact.", + "title": "City", + "type": [ + "null", + "string" + ] + }, + "company": { + "description": "The company name for the list.", + "title": "Company Name", + "type": [ + "null", + "string" + ] + }, + "country": { + "description": "A two-character ISO3166 country code. Defaults to US if invalid.", + "title": "Country Code", + "type": [ + "null", + "string" + ] + }, + "phone": { + "description": "The phone number for the list contact.", + "title": "Phone Number", + "type": [ + "null", + "string" + ] + }, + "state": { + "description": "The state for the list contact.", + "title": "State", + "type": [ + "null", + "string" + ] + }, + "zip": { + "description": "The postal or zip code for the list contact.", + "title": "Postal Code", + "type": [ + "null", + "string" + ] + } + }, + "title": "List Contact", + "type": "object" + }, + "date_created": { + "description": "The date and time that this list was created in ISO 8601 format.", + "format": "date-time", + "readOnly": true, + "title": "Creation Date", + "type": "string" + }, + "double_optin": { + "default": false, + "description": "Whether or not to require the subscriber to confirm subscription via email.", + "title": "Double Opt In", + "type": "boolean" + }, + "email_type_option": { + "description": "Whether the list supports [multiple formats for emails](https://mailchimp.com/help/change-list-name-and-defaults/). When set to `true`, subscribers can choose whether they want to receive HTML or plain-text emails. When set to `false`, subscribers will receive HTML emails, with a plain-text alternative backup.", + "title": "Email Type Option", + "type": "boolean" + }, + "has_welcome": { + "default": false, + "description": "Whether or not this list has a welcome automation connected. Welcome Automations: welcomeSeries, singleWelcome, emailFollowup.", + "example": false, + "title": "Has Welcome", + "type": "boolean" + }, + "id": { + "description": "A string that uniquely identifies this list.", + "readOnly": true, + "title": "List ID", + "type": "string" + }, + "list_rating": { + "description": "An auto-generated activity score for the list (0-5).", + "readOnly": true, + "title": "List Rating", + "type": "integer" + }, + "marketing_permissions": { + "default": false, + "description": "Whether or not the list has marketing permissions (eg. GDPR) enabled.", + "title": "Marketing Permissions", + "type": "boolean" + }, + "modules": { + "description": "Any list-specific modules installed for this list.", + "items": { + "type": [ + "null", + "string" + ] + }, + "readOnly": true, + "title": "Modules", + "type": "array" + }, + "name": { + "description": "The name of the list.", + "title": "List Name", + "type": [ + "null", + "string" + ] + }, + "notify_on_subscribe": { + "description": "The email address to send [subscribe notifications](https://mailchimp.com/help/change-subscribe-and-unsubscribe-notifications/) to.", + "title": "Notify on Subscribe", + "type": [ + "null", + "string" + ] + }, + "notify_on_unsubscribe": { + "description": "The email address to send [unsubscribe notifications](https://mailchimp.com/help/change-subscribe-and-unsubscribe-notifications/) to.", + "title": "Notify on Unsubscribe", + "type": [ + "null", + "string" + ] + }, + "permission_reminder": { + "description": "The [permission reminder](https://mailchimp.com/help/edit-the-permission-reminder/) for the list.", + "title": "Permission Reminder", + "type": [ + "null", + "string" + ] + }, + "stats": { + "description": "Stats for the list. Many of these are cached for at least five minutes.", + "properties": { + "avg_sub_rate": { + "description": "The average number of subscriptions per month for the list (not returned if we haven't calculated it yet).", + "readOnly": true, + "title": "Average Subscription Rate", + "type": "number" + }, + "avg_unsub_rate": { + "description": "The average number of unsubscriptions per month for the list (not returned if we haven't calculated it yet).", + "readOnly": true, + "title": "Average Unsubscription Rate", + "type": "number" + }, + "campaign_count": { + "description": "The number of campaigns in any status that use this list.", + "readOnly": true, + "title": "Campaign Count", + "type": "integer" + }, + "campaign_last_sent": { + "description": "The date and time the last campaign was sent to this list in ISO 8601 format. This is updated when a campaign is sent to 10 or more recipients.", + "format": "date-time", + "readOnly": true, + "title": "Campaign Last Sent", + "type": [ + "null", + "string" + ] + }, + "cleaned_count": { + "description": "The number of members cleaned from the list.", + "readOnly": true, + "title": "Cleaned Count", + "type": "integer" + }, + "cleaned_count_since_send": { + "description": "The number of members cleaned from the list since the last campaign was sent.", + "readOnly": true, + "title": "Cleaned Count Since Send", + "type": "integer" + }, + "click_rate": { + "description": "The average click rate (a percentage represented as a number between 0 and 100) per campaign for the list (not returned if we haven't calculated it yet).", + "readOnly": true, + "title": "Click Rate", + "type": "number" + }, + "last_sub_date": { + "description": "The date and time of the last time someone subscribed to this list in ISO 8601 format.", + "format": "date-time", + "readOnly": true, + "title": "Date of Last List Subscribe", + "type": [ + "null", + "string" + ] + }, + "last_unsub_date": { + "description": "The date and time of the last time someone unsubscribed from this list in ISO 8601 format.", + "format": "date-time", + "readOnly": true, + "title": "Date of Last List Unsubscribe", + "type": [ + "null", + "string" + ] + }, + "member_count": { + "description": "The number of active members in the list.", + "readOnly": true, + "title": "Member Count", + "type": "integer" + }, + "member_count_since_send": { + "description": "The number of active members in the list since the last campaign was sent.", + "readOnly": true, + "title": "Member Count Since Send", + "type": "integer" + }, + "merge_field_count": { + "description": "The number of merge vars for this list (not EMAIL, which is required).", + "readOnly": true, + "title": "Merge Var Count", + "type": "integer" + }, + "open_rate": { + "description": "The average open rate (a percentage represented as a number between 0 and 100) per campaign for the list (not returned if we haven't calculated it yet).", + "readOnly": true, + "title": "Open Rate", + "type": "number" + }, + "target_sub_rate": { + "description": "The target number of subscriptions per month for the list to keep it growing (not returned if we haven't calculated it yet).", + "readOnly": true, + "title": "Average Subscription Rate", + "type": "number" + }, + "total_contacts": { + "description": "The number of contacts in the list, including subscribed, unsubscribed, pending, cleaned, deleted, transactional, and those that need to be reconfirmed.", + "readOnly": true, + "title": "Total Contacts", + "type": "integer" + }, + "unsubscribe_count": { + "description": "The number of members who have unsubscribed from the list.", + "readOnly": true, + "title": "Unsubscribe Count", + "type": "integer" + }, + "unsubscribe_count_since_send": { + "description": "The number of members who have unsubscribed since the last campaign was sent.", + "readOnly": true, + "title": "Unsubscribe Count Since Send", + "type": "integer" + } + }, + "readOnly": true, + "title": "Statistics", + "type": "object" + }, + "subscribe_url_long": { + "description": "The full version of this list's subscribe form (host will vary).", + "readOnly": true, + "title": "Subscribe URL Long", + "type": [ + "null", + "string" + ] + }, + "subscribe_url_short": { + "description": "Our [EepURL shortened](https://mailchimp.com/help/share-your-signup-form/) version of this list's subscribe form.", + "readOnly": true, + "title": "Subscribe URL Short", + "type": [ + "null", + "string" + ] + }, + "use_archive_bar": { + "default": false, + "description": "Whether campaigns for this list use the [Archive Bar](https://mailchimp.com/help/about-email-campaign-archives-and-pages/) in archives by default.", + "title": "Use Archive Bar", + "type": "boolean" + }, + "visibility": { + "description": "Whether this list is [public or private](https://mailchimp.com/help/about-list-publicity/).", + "enum": [ + "pub", + "prv" + ], + "title": "Visibility", + "type": [ + "null", + "string" + ] + }, + "web_id": { + "description": "The ID used in the Mailchimp web application. View this list in your Mailchimp account at `https://{dc}.admin.mailchimp.com/lists/members/?id={web_id}`.", + "readOnly": true, + "title": "List Web ID", + "type": "integer" + } + }, + "required": [ + "id" + ], + "title": "Subscriber List", + "type": "object" + }, + "key": [ + "/id" + ], + "recommendedName": "lists", + "resourceConfig": { + "cursorField": [ + "date_created" + ], + "stream": "lists", + "syncMode": "incremental" + } + }, + { + "documentSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "properties": { + "_meta": { + "properties": { + "row_id": { + "type": "integer" + } + }, + "required": [ + "row_id" + ], + "type": "object" + }, + "consents_to_one_to_one_messaging": { + "type": [ + "null", + "boolean" + ] + }, + "contact_id": { + "type": [ + "null", + "string" + ] + }, + "email_address": { + "type": [ + "null", + "string" + ] + }, + "email_client": { + "type": [ + "null", + "string" + ] + }, + "email_type": { + "type": [ + "null", + "string" + ] + }, + "full_name": { + "type": [ + "null", + "string" + ] + }, + "id": { + "type": "string" + }, + "interests": { + "additionalProperties": true, + "type": [ + "null", + "object" + ] + }, + "ip_opt": { + "type": [ + "null", + "string" + ] + }, + "ip_signup": { + "type": [ + "null", + "string" + ] + }, + "language": { + "type": [ + "null", + "string" + ] + }, + "last_changed": { + "format": "date-time", + "type": [ + "null", + "string" + ] + }, + "last_note": { + "properties": { + "created_at": { + "format": "date-time", + "type": [ + "null", + "string" + ] + }, + "created_by": { + "type": [ + "null", + "string" + ] + }, + "note": { + "type": [ + "null", + "string" + ] + }, + "note_id": { + "type": [ + "null", + "integer" + ] + } + }, + "type": [ + "null", + "object" + ] + }, + "list_id": { + "type": [ + "null", + "string" + ] + }, + "location": { + "properties": { + "country_code": { + "type": [ + "null", + "string" + ] + }, + "dstoff": { + "type": [ + "null", + "integer" + ] + }, + "gmtoff": { + "type": [ + "null", + "integer" + ] + }, + "latitude": { + "type": [ + "null", + "number" + ] + }, + "longitude": { + "type": [ + "null", + "number" + ] + }, + "region": { + "type": [ + "null", + "string" + ] + }, + "timezone": { + "type": [ + "null", + "string" + ] + } + }, + "type": [ + "null", + "object" + ] + }, + "marketing_permissions": { + "properties": { + "enabled": { + "type": [ + "null", + "boolean" + ] + }, + "marketing_permission_id": { + "type": [ + "null", + "string" + ] + }, + "text": { + "type": [ + "null", + "string" + ] + } + }, + "type": [ + "null", + "object" + ] + }, + "member_rating": { + "type": [ + "null", + "integer" + ] + }, + "merge_fields": { + "additionalProperties": true, + "type": [ + "null", + "object" + ] + }, + "source": { + "type": [ + "null", + "string" + ] + }, + "stats": { + "properties": { + "avg_click_rate": { + "type": [ + "null", + "number" + ] + }, + "avg_open_rate": { + "type": [ + "null", + "number" + ] + }, + "ecommerce_data": { + "properties": { + "currency_code": { + "type": [ + "null", + "string" + ] + }, + "number_of_orders": { + "type": [ + "null", + "number" + ] + }, + "total_revenue": { + "type": [ + "null", + "number" + ] + } + }, + "type": [ + "null", + "object" + ] + } + }, + "type": [ + "null", + "object" + ] + }, + "status": { + "type": [ + "null", + "string" + ] + }, + "tags": { + "items": { + "properties": { + "id": { + "type": [ + "null", + "integer" + ] + }, + "name": { + "type": [ + "null", + "string" + ] + } + }, + "type": [ + "null", + "object" + ] + }, + "type": [ + "null", + "array" + ] + }, + "tags_count": { + "type": [ + "null", + "integer" + ] + }, + "timestamp_opt": { + "format": "date-time", + "type": [ + "null", + "string" + ] + }, + "timestamp_signup": { + "format": "date-time", + "type": [ + "null", + "string" + ] + }, + "unique_email_id": { + "type": [ + "null", + "string" + ] + }, + "unsubscribe_reason": { + "type": [ + "null", + "string" + ] + }, + "vip": { + "type": [ + "null", + "boolean" + ] + }, + "web_id": { + "type": [ + "null", + "integer" + ] + } + }, + "required": [ + "id" + ], + "type": "object" + }, + "key": [ + "/id" + ], + "recommendedName": "list_members", + "resourceConfig": { + "cursorField": [ + "last_changed" + ], + "stream": "list_members", + "syncMode": "incremental" + } + }, + { + "documentSchema": { + "description": "A list of reports containing campaigns marked as Sent.", + "properties": { + "_meta": { + "properties": { + "row_id": { + "type": "integer" + } + }, + "required": [ + "row_id" + ], + "type": "object" + }, + "ab_split": { + "description": "General stats about different groups of an A/B Split campaign. Does not return information about Multivariate Campaigns.", + "properties": { + "a": { + "description": "Stats for Campaign A.", + "properties": { + "abuse_reports": { + "description": "Abuse reports for Campaign A.", + "title": "Abuse Reports", + "type": "integer" + }, + "bounces": { + "description": "Bounces for Campaign A.", + "title": "Bounces", + "type": "integer" + }, + "forwards": { + "description": "Forwards for Campaign A.", + "title": "Forwards", + "type": "integer" + }, + "forwards_opens": { + "description": "Opens from forwards for Campaign A.", + "title": "Forward Opens", + "type": "integer" + }, + "last_open": { + "description": "The last open for Campaign A.", + "format": "date-time", + "title": "Last Open", + "type": [ + "null", + "string" + ] + }, + "opens": { + "description": "Opens for Campaign A.", + "title": "Opens", + "type": "integer" + }, + "recipient_clicks": { + "description": "Recipient Clicks for Campaign A.", + "title": "Recipient Clicks", + "type": "integer" + }, + "unique_opens": { + "description": "Unique opens for Campaign A.", + "title": "Unique Opens", + "type": "integer" + }, + "unsubs": { + "description": "Unsubscribes for Campaign A.", + "title": "Unsubscribes", + "type": "integer" + } + }, + "title": "Campaign A", + "type": "object" + }, + "b": { + "description": "Stats for Campaign B.", + "properties": { + "abuse_reports": { + "description": "Abuse reports for Campaign B.", + "title": "Abuse Reports", + "type": "integer" + }, + "bounces": { + "description": "Bounces for Campaign B.", + "title": "Bounces", + "type": "integer" + }, + "forwards": { + "description": "Forwards for Campaign B.", + "title": "Forwards", + "type": "integer" + }, + "forwards_opens": { + "description": "Opens for forwards from Campaign B.", + "title": "Forward Opens", + "type": "integer" + }, + "last_open": { + "description": "The last open for Campaign B.", + "format": "date-time", + "title": "Last Open", + "type": [ + "null", + "string" + ] + }, + "opens": { + "description": "Opens for Campaign B.", + "title": "Opens", + "type": "integer" + }, + "recipient_clicks": { + "description": "Recipients clicks for Campaign B.", + "title": "Recipient Clicks", + "type": "integer" + }, + "unique_opens": { + "description": "Unique opens for Campaign B.", + "title": "Unique Opens", + "type": "integer" + }, + "unsubs": { + "description": "Unsubscribes for Campaign B.", + "title": "Unsubscribes", + "type": "integer" + } + }, + "title": "Campaign B", + "type": "object" + } + }, + "title": "A/B Split Stats", + "type": "object" + }, + "abuse_reports": { + "description": "The number of abuse reports generated for this campaign.", + "title": "Abuse Reports", + "type": "integer" + }, + "bounces": { + "description": "An object describing the bounce summary for the campaign.", + "properties": { + "hard_bounces": { + "description": "The total number of hard bounced email addresses.", + "title": "Hard Bounces", + "type": "integer" + }, + "soft_bounces": { + "description": "The total number of soft bounced email addresses.", + "title": "Soft Bounces", + "type": "integer" + }, + "syntax_errors": { + "description": "The total number of addresses that were syntax-related bounces.", + "title": "Syntax Errors", + "type": "integer" + } + }, + "title": "Bounces", + "type": "object" + }, + "campaign_title": { + "description": "The title of the campaign.", + "readOnly": true, + "title": "Campaign Title", + "type": [ + "null", + "string" + ] + }, + "clicks": { + "description": "An object describing the click activity for the campaign.", + "properties": { + "click_rate": { + "description": "The number of unique clicks divided by the total number of successful deliveries.", + "title": "Click Rate", + "type": "number" + }, + "clicks_total": { + "description": "The total number of clicks for the campaign.", + "title": "Total Clicks", + "type": "integer" + }, + "last_click": { + "description": "The date and time of the last recorded click for the campaign in ISO 8601 format.", + "format": "date-time", + "title": "Last Click", + "type": [ + "null", + "string" + ] + }, + "unique_clicks": { + "description": "The total number of unique clicks for links across a campaign.", + "title": "Unique Clicks", + "type": "integer" + }, + "unique_subscriber_clicks": { + "description": "The total number of subscribers who clicked on a campaign.", + "title": "Unique Subscriber Clicks", + "type": "integer" + } + }, + "title": "Clicks", + "type": "object" + }, + "delivery_status": { + "description": "Updates on campaigns in the process of sending.", + "properties": { + "can_cancel": { + "description": "Whether a campaign send can be canceled.", + "readOnly": true, + "title": "Campaign Cancelable", + "type": "boolean" + }, + "emails_canceled": { + "description": "The total number of emails canceled for this campaign.", + "readOnly": true, + "title": "Emails Canceled", + "type": "integer" + }, + "emails_sent": { + "description": "The total number of emails confirmed sent for this campaign so far.", + "readOnly": true, + "title": "Emails Sent", + "type": "integer" + }, + "enabled": { + "description": "Whether Campaign Delivery Status is enabled for this account and campaign.", + "readOnly": true, + "title": "Delivery Status Enabled", + "type": "boolean" + }, + "status": { + "description": "The current state of a campaign delivery.", + "enum": [ + "delivering", + "delivered", + "canceling", + "canceled" + ], + "readOnly": true, + "title": "Campaign Delivery Status", + "type": [ + "null", + "string" + ] + } + }, + "title": "Campaign Delivery Status", + "type": "object" + }, + "ecommerce": { + "description": "E-Commerce stats for a campaign.", + "properties": { + "currency_code": { + "example": "USD", + "readOnly": true, + "title": "Three letter currency code for this user", + "type": [ + "null", + "string" + ] + }, + "total_orders": { + "description": "The total orders for a campaign.", + "readOnly": true, + "title": "Total Orders", + "type": "integer" + }, + "total_revenue": { + "description": "The total revenue for a campaign. Calculated as the sum of all order totals minus shipping and tax totals.", + "readOnly": true, + "title": "Total Revenue", + "type": "number" + }, + "total_spent": { + "description": "The total spent for a campaign. Calculated as the sum of all order totals with no deductions.", + "readOnly": true, + "title": "Total Spent", + "type": "number" + } + }, + "title": "E-Commerce Report", + "type": "object" + }, + "emails_sent": { + "description": "The total number of emails sent for this campaign.", + "title": "Emails Sent", + "type": "integer" + }, + "facebook_likes": { + "description": "An object describing campaign engagement on Facebook.", + "properties": { + "facebook_likes": { + "description": "The number of Facebook likes for the campaign.", + "title": "Facebook Likes", + "type": "integer" + }, + "recipient_likes": { + "description": "The number of recipients who liked the campaign on Facebook.", + "title": "Recipient Likes", + "type": "integer" + }, + "unique_likes": { + "description": "The number of unique likes.", + "title": "Unique Likes", + "type": "integer" + } + }, + "title": "Facebook Likes", + "type": "object" + }, + "forwards": { + "description": "An object describing the forwards and forward activity for the campaign.", + "properties": { + "forwards_count": { + "description": "How many times the campaign has been forwarded.", + "title": "Total Forwards", + "type": "integer" + }, + "forwards_opens": { + "description": "How many times the forwarded campaign has been opened.", + "title": "Forward Opens", + "type": "integer" + } + }, + "title": "Forwards", + "type": "object" + }, + "id": { + "description": "A string that uniquely identifies this campaign.", + "title": "Campaign ID", + "type": "string" + }, + "industry_stats": { + "description": "The average campaign statistics for your industry.", + "properties": { + "abuse_rate": { + "description": "The industry abuse rate.", + "title": "Abuse Rate", + "type": "number" + }, + "bounce_rate": { + "description": "The industry bounce rate.", + "title": "Bounce Rate", + "type": "number" + }, + "click_rate": { + "description": "The industry click rate.", + "title": "Click Rate", + "type": "number" + }, + "open_rate": { + "description": "The industry open rate.", + "title": "Open Rate", + "type": "number" + }, + "type": { + "description": "The type of business industry associated with your account. For example: retail, education, etc.", + "title": "Industry Type", + "type": [ + "null", + "string" + ] + }, + "unopen_rate": { + "description": "The industry unopened rate.", + "title": "Unopened Rate", + "type": "number" + }, + "unsub_rate": { + "description": "The industry unsubscribe rate.", + "title": "Unsubscribe Rate", + "type": "number" + } + }, + "title": "Industry Stats", + "type": "object" + }, + "list_id": { + "description": "The unique list id.", + "readOnly": true, + "title": "List ID", + "type": "string" + }, + "list_is_active": { + "description": "The status of the list used, namely if it's deleted or disabled.", + "readOnly": true, + "title": "List Status", + "type": "boolean" + }, + "list_name": { + "description": "The name of the list.", + "readOnly": true, + "title": "List Name", + "type": [ + "null", + "string" + ] + }, + "list_stats": { + "description": "The average campaign statistics for your list. This won't be present if we haven't calculated it yet for this list.", + "properties": { + "click_rate": { + "description": "The average click rate (a percentage represented as a number between 0 and 100) per campaign for the list.", + "readOnly": true, + "title": "Click Rate", + "type": "number" + }, + "open_rate": { + "description": "The average open rate (a percentage represented as a number between 0 and 100) per campaign for the list.", + "readOnly": true, + "title": "Open Rate", + "type": "number" + }, + "sub_rate": { + "description": "The average number of subscriptions per month for the list.", + "readOnly": true, + "title": "Average Subscription Rate", + "type": "number" + }, + "unsub_rate": { + "description": "The average number of unsubscriptions per month for the list.", + "readOnly": true, + "title": "Average Unsubscription Rate", + "type": "number" + } + }, + "title": "List Stats", + "type": "object" + }, + "opens": { + "description": "An object describing the open activity for the campaign.", + "properties": { + "last_open": { + "description": "The date and time of the last recorded open in ISO 8601 format.", + "format": "date-time", + "title": "Last Open", + "type": [ + "null", + "string" + ] + }, + "open_rate": { + "description": "The number of unique opens divided by the total number of successful deliveries.", + "title": "Open Rate", + "type": "number" + }, + "opens_total": { + "description": "The total number of opens for a campaign.", + "title": "Total Opens", + "type": "integer" + }, + "unique_opens": { + "description": "The total number of unique opens.", + "title": "Unique Opens", + "type": "integer" + } + }, + "title": "Opens", + "type": "object" + }, + "preview_text": { + "description": "The preview text for the campaign.", + "title": "Campaign Preview Text", + "type": [ + "null", + "string" + ] + }, + "rss_last_send": { + "description": "For RSS campaigns, the date and time of the last send in ISO 8601 format.", + "format": "date-time", + "readOnly": true, + "title": "RSS Last Send", + "type": [ + "null", + "string" + ] + }, + "send_time": { + "description": "The date and time a campaign was sent in ISO 8601 format.", + "format": "date-time", + "readOnly": true, + "title": "Send Time", + "type": [ + "null", + "string" + ] + }, + "share_report": { + "description": "The url and password for the [VIP report](https://mailchimp.com/help/share-a-campaign-report/).", + "properties": { + "share_password": { + "description": "If password protected, the password for the VIP report.", + "readOnly": true, + "title": "Report Password", + "type": [ + "null", + "string" + ] + }, + "share_url": { + "description": "The URL for the VIP report.", + "readOnly": true, + "title": "Report URL", + "type": [ + "null", + "string" + ] + } + }, + "title": "Share Report", + "type": "object" + }, + "subject_line": { + "description": "The subject line for the campaign.", + "readOnly": true, + "title": "Campaign Subject Line", + "type": [ + "null", + "string" + ] + }, + "timeseries": { + "description": "An hourly breakdown of the performance of the campaign over the first 24 hours.", + "items": { + "properties": { + "emails_sent": { + "description": "The number of emails sent in the timeseries.", + "title": "Emails Sent", + "type": "integer" + }, + "recipients_clicks": { + "description": "The number of clicks in the timeseries.", + "title": "Recipient Clicks", + "type": "integer" + }, + "timestamp": { + "description": "The date and time for the series in ISO 8601 format.", + "format": "date-time", + "title": "Timestamp", + "type": [ + "null", + "string" + ] + }, + "unique_opens": { + "description": "The number of unique opens in the timeseries.", + "title": "Unique Opens", + "type": "integer" + } + }, + "type": "object" + }, + "title": "Timeseries", + "type": "array" + }, + "timewarp": { + "description": "An hourly breakdown of sends, opens, and clicks if a campaign is sent using timewarp.", + "items": { + "properties": { + "bounces": { + "description": "The number of bounces.", + "title": "Bounces", + "type": "integer" + }, + "clicks": { + "description": "The number of clicks.", + "title": "Clicks", + "type": "integer" + }, + "gmt_offset": { + "description": "For campaigns sent with timewarp, the time zone group the member is apart of.", + "title": "GMT Offset", + "type": "integer" + }, + "last_click": { + "description": "The date and time of the last click in ISO 8601 format.", + "format": "date-time", + "title": "Last Click", + "type": [ + "null", + "string" + ] + }, + "last_open": { + "description": "The date and time of the last open in ISO 8601 format.", + "format": "date-time", + "title": "Last Open", + "type": [ + "null", + "string" + ] + }, + "opens": { + "description": "The number of opens.", + "title": "Opens", + "type": "integer" + }, + "unique_clicks": { + "description": "The number of unique clicks.", + "title": "Unique Clicks", + "type": "integer" + }, + "unique_opens": { + "description": "The number of unique opens.", + "title": "Unique Opens", + "type": "integer" + } + }, + "type": "object" + }, + "title": "Timewarp Stats", + "type": "array" + }, + "type": { + "description": "The type of campaign (regular, plain-text, ab_split, rss, automation, variate, or auto).", + "title": "Campaign Type", + "type": [ + "null", + "string" + ] + }, + "unsubscribed": { + "description": "The total number of unsubscribed members for this campaign.", + "readOnly": true, + "title": "Unsubscribe Count", + "type": "integer" + } + }, + "required": [ + "id" + ], + "title": "Campaign Reports", + "type": "object" + }, + "key": [ + "/id" + ], + "recommendedName": "reports", + "resourceConfig": { + "cursorField": [ + "send_time" + ], + "stream": "reports", + "syncMode": "incremental" + } + }, + { + "documentSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "properties": { + "_meta": { + "properties": { + "row_id": { + "type": "integer" + } + }, + "required": [ + "row_id" + ], + "type": "object" + }, + "email_address": { + "type": [ + "null", + "string" + ] + }, + "email_client": { + "type": [ + "null", + "string" + ] + }, + "email_type": { + "type": [ + "null", + "string" + ] + }, + "id": { + "type": "string" + }, + "interests": { + "additionalProperties": true, + "type": [ + "null", + "object" + ] + }, + "ip_opt": { + "type": [ + "null", + "string" + ] + }, + "ip_signup": { + "type": [ + "null", + "string" + ] + }, + "language": { + "type": [ + "null", + "string" + ] + }, + "last_changed": { + "format": "date-time", + "type": [ + "null", + "string" + ] + }, + "last_note": { + "properties": { + "created_at": { + "format": "date-time", + "type": [ + "null", + "string" + ] + }, + "created_by": { + "type": [ + "null", + "string" + ] + }, + "note": { + "type": [ + "null", + "string" + ] + }, + "note_id": { + "type": [ + "null", + "integer" + ] + } + }, + "type": [ + "null", + "object" + ] + }, + "list_id": { + "type": [ + "null", + "string" + ] + }, + "location": { + "properties": { + "country_code": { + "type": [ + "null", + "string" + ] + }, + "dstoff": { + "type": [ + "null", + "integer" + ] + }, + "gmtoff": { + "type": [ + "null", + "integer" + ] + }, + "latitude": { + "type": [ + "null", + "number" + ] + }, + "longitude": { + "type": [ + "null", + "number" + ] + }, + "timezone": { + "type": [ + "null", + "string" + ] + } + }, + "type": [ + "null", + "object" + ] + }, + "member_rating": { + "type": [ + "null", + "integer" + ] + }, + "merge_fields": { + "additionalProperties": true, + "type": [ + "null", + "object" + ] + }, + "segment_id": { + "type": [ + "null", + "integer" + ] + }, + "stats": { + "properties": { + "avg_click_rate": { + "type": [ + "null", + "number" + ] + }, + "avg_open_rate": { + "type": [ + "null", + "number" + ] + } + }, + "type": [ + "null", + "object" + ] + }, + "status": { + "type": [ + "null", + "string" + ] + }, + "timestamp_opt": { + "format": "date-time", + "type": [ + "null", + "string" + ] + }, + "timestamp_signup": { + "format": "date-time", + "type": [ + "null", + "string" + ] + }, + "unique_email_id": { + "type": [ + "null", + "string" + ] + }, + "vip": { + "type": [ + "null", + "boolean" + ] + } + }, + "required": [ + "id" + ], + "type": "object" + }, + "key": [ + "/id" + ], + "recommendedName": "segment_members", + "resourceConfig": { + "cursorField": [ + "last_changed" + ], + "stream": "segment_members", + "syncMode": "incremental" + } + }, + { + "documentSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "properties": { + "_meta": { + "properties": { + "row_id": { + "type": "integer" + } + }, + "required": [ + "row_id" + ], + "type": "object" + }, + "created_at": { + "format": "date-time", + "type": [ + "null", + "string" + ] + }, + "id": { + "type": "integer" + }, + "list_id": { + "type": [ + "null", + "string" + ] + }, + "member_count": { + "type": [ + "null", + "integer" + ] + }, + "name": { + "type": [ + "null", + "string" + ] + }, + "options": { + "properties": { + "conditions": { + "items": { + "additionalProperties": true, + "properties": { + "condition_type": { + "type": [ + "null", + "string" + ] + }, + "field": { + "type": [ + "null", + "string" + ] + }, + "op": { + "type": [ + "null", + "string" + ] + } + }, + "type": [ + "null", + "object" + ] + }, + "type": [ + "null", + "array" + ] + }, + "match": { + "type": [ + "null", + "string" + ] + } + }, + "type": [ + "null", + "object" + ] + }, + "type": { + "type": [ + "null", + "string" + ] + }, + "updated_at": { + "format": "date-time", + "type": [ + "null", + "string" + ] + } + }, + "required": [ + "id" + ], + "type": "object" + }, + "key": [ + "/id" + ], + "recommendedName": "segments", + "resourceConfig": { + "cursorField": [ + "updated_at" + ], + "stream": "segments", + "syncMode": "incremental" + } + }, + { + "documentSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "_meta": { + "properties": { + "row_id": { + "type": "integer" + } + }, + "required": [ + "row_id" + ], + "type": "object" + }, + "id": { + "type": "integer" + }, + "list_id": { + "type": [ + "null", + "string" + ] + }, + "name": { + "type": [ + "null", + "string" + ] + } + }, + "required": [ + "id" + ], + "type": "object" + }, + "key": [ + "/id" + ], + "recommendedName": "tags", + "resourceConfig": { + "stream": "tags", + "syncMode": "full_refresh" + } + }, + { + "documentSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "properties": { + "_meta": { + "properties": { + "row_id": { + "type": "integer" + } + }, + "required": [ + "row_id" + ], + "type": "object" + }, + "campaign_id": { + "type": "string" + }, + "email_address": { + "type": [ + "null", + "string" + ] + }, + "email_id": { + "type": "string" + }, + "list_id": { + "type": [ + "null", + "string" + ] + }, + "list_is_active": { + "type": [ + "null", + "boolean" + ] + }, + "merge_fields": { + "additionalProperties": true, + "type": [ + "null", + "object" + ] + }, + "reason": { + "type": [ + "null", + "string" + ] + }, + "timestamp": { + "format": "date-time", + "type": "string" + }, + "vip": { + "type": [ + "null", + "boolean" + ] + } + }, + "required": [ + "campaign_id", + "email_id", + "timestamp" + ], + "type": "object" + }, + "key": [ + "/campaign_id", + "/email_id", + "/timestamp" + ], + "recommendedName": "unsubscribes", + "resourceConfig": { + "cursorField": [ + "timestamp" + ], + "stream": "unsubscribes", + "syncMode": "incremental" + } + } +] diff --git a/source-mailchimp/tests/snapshots/snapshots__spec__capture.stdout.json b/source-mailchimp/tests/snapshots/snapshots__spec__capture.stdout.json new file mode 100644 index 0000000000..fd7e12ee7f --- /dev/null +++ b/source-mailchimp/tests/snapshots/snapshots__spec__capture.stdout.json @@ -0,0 +1,151 @@ +[ + { + "configSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "properties": { + "campaign_id": { + "title": "ID of a campaign to sync email activities", + "type": "string" + }, + "credentials": { + "discriminator": { + "propertyName": "auth_type" + }, + "oneOf": [ + { + "properties": { + "access_token": { + "airbyte_secret": true, + "description": "An access token generated using the above client ID and secret.", + "title": "Access Token", + "type": "string" + }, + "auth_type": { + "const": "oauth2.0", + "default": "oauth2.0", + "order": 0, + "type": "string" + }, + "client_id": { + "airbyte_secret": true, + "description": "The Client ID of your OAuth application.", + "title": "Client ID", + "type": "string" + }, + "client_secret": { + "airbyte_secret": true, + "description": "The Client Secret of your OAuth application.", + "title": "Client Secret", + "type": "string" + } + }, + "required": [ + "auth_type", + "access_token" + ], + "title": "OAuth2.0", + "type": "object", + "x-oauth2-provider": "mailchimp" + }, + { + "properties": { + "apikey": { + "airbyte_secret": true, + "description": "Mailchimp API Key. See the docs for more information on how to generate this key: https://go.estuary.dev/tmiNoF", + "title": "API Key", + "type": "string" + }, + "auth_type": { + "const": "apikey", + "default": "apikey", + "order": 1, + "type": "string" + } + }, + "required": [ + "auth_type", + "apikey" + ], + "title": "API Key", + "type": "object" + } + ], + "title": "Authentication", + "type": "object" + }, + "start_date": { + "description": "The date from which you want to start syncing data for Incremental streams. Only records that have been created or modified since this date will be synced. If left blank, all data will by synced.", + "examples": [ + "2020-01-01T00:00:00.000Z" + ], + "format": "date-time", + "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$", + "title": "Incremental Sync Start Date", + "type": "string" + } + }, + "required": [ + "credentials" + ], + "title": "Mailchimp Spec", + "type": "object" + }, + "documentationUrl": "https://go.estuary.dev/tmiNoF", + "oauth2": { + "accessTokenBody": "grant_type=authorization_code&client_id={{#urlencode}}{{{ client_id }}}{{/urlencode}}&client_secret={{#urlencode}}{{{ client_secret }}}{{/urlencode}}&redirect_uri={{#urlencode}}{{{ redirect_uri }}}{{/urlencode}}&code={{#urlencode}}{{{ code }}}{{/urlencode}}", + "accessTokenHeaders": { + "content-type": "application/x-www-form-urlencoded" + }, + "accessTokenResponseMap": { + "access_token": "/access_token" + }, + "accessTokenUrlTemplate": "https://login.mailchimp.com/oauth2/token", + "authUrlTemplate": "https://login.mailchimp.com/oauth2/authorize?response_type=code&client_id={{#urlencode}}{{{ client_id }}}{{/urlencode}}&redirect_uri={{#urlencode}}{{{ redirect_uri }}}{{/urlencode}}&state={{#urlencode}}{{{ state }}}{{/urlencode}}", + "provider": "mailchimp" + }, + "protocol": 3032023, + "resourceConfigSchema": { + "additionalProperties": false, + "description": "ResourceConfig encodes a configured resource stream", + "properties": { + "cursorField": { + "items": { + "type": "string" + }, + "title": "Cursor Field", + "type": "array" + }, + "namespace": { + "description": "Enclosing schema namespace of this resource", + "title": "Namespace", + "type": "string" + }, + "stream": { + "description": "Name of this stream", + "title": "Stream", + "type": "string" + }, + "syncMode": { + "description": "Sync this resource incrementally, or fully refresh it every run", + "enum": [ + "full_refresh", + "incremental" + ], + "title": "Sync Mode", + "type": "string" + } + }, + "required": [ + "stream", + "syncMode" + ], + "title": "ResourceConfig", + "type": "object" + }, + "resourcePathPointers": [ + "/namespace", + "/stream" + ] + } +] diff --git a/source-mailchimp/tests/test_snapshots.py b/source-mailchimp/tests/test_snapshots.py new file mode 100644 index 0000000000..d403ae699e --- /dev/null +++ b/source-mailchimp/tests/test_snapshots.py @@ -0,0 +1,76 @@ +import json +import subprocess + +import pytest_insta.format as insta_format +insta_format.FmtJson.dump = lambda _self, path, value: path.write_text(json.dumps(value, sort_keys=True, indent=2) + "\n", "utf-8") + +def test_capture(request, snapshot): + result = subprocess.run( + [ + "flowctl", + "preview", + "--source", + request.fspath.dirname + "/../test.flow.yaml", + "--sessions", + "1", + "--delay", + "20s", + ], + stdout=subprocess.PIPE, + text=True, + ) + assert result.returncode == 0 + lines = [json.loads(l) for l in result.stdout.splitlines()[:50]] + + for l in lines: + typ, rec = l[0], l[1] + + if typ == "acmeCo/lists": + rec["contact"] = "redacted" # removing address info from tests + rec["stats"]["last_sub_date"] = "redacted" + + elif typ == "acmeCo/segment_members": + rec["ip_opt"] = "redacted" + + elif typ == "acmeCo/reports": + rec["timeseries"] = "redacted" + + assert snapshot("capture.stdout.json") == lines + +def test_discover(request, snapshot): + result = subprocess.run( + [ + "flowctl", + "raw", + "discover", + "--source", + request.config.rootdir + "/source-mailchimp/test.flow.yaml", + "-o", + "json", + "--emit-raw" + ], + stdout=subprocess.PIPE, + text=True, + ) + assert result.returncode == 0 + lines = [json.loads(l) for l in result.stdout.splitlines()] + + assert snapshot("capture.stdout.json") == lines + +def test_spec(request, snapshot): + result = subprocess.run( + [ + "flowctl", + "raw", + "spec", + "--source", + request.config.rootdir + "/source-mailchimp/test.flow.yaml" + ], + stdout=subprocess.PIPE, + text=True, + ) + assert result.returncode == 0 + lines = [json.loads(l) for l in result.stdout.splitlines()] + + assert snapshot("capture.stdout.json") == lines + diff --git a/source-mailchimp/tests/test_source.py b/source-mailchimp/tests/test_source.py new file mode 100644 index 0000000000..b1ccfcddac --- /dev/null +++ b/source-mailchimp/tests/test_source.py @@ -0,0 +1,116 @@ +# +# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# + +import logging + +import pytest +from source_mailchimp.source import MailChimpAuthenticator, SourceMailchimp + +logger = logging.getLogger("airbyte") + + +def test_check_connection_ok(requests_mock, config, data_center): + responses = [ + {"json": {"health_status": "Everything's Chimpy!"}}, + ] + requests_mock.register_uri("GET", f"https://{data_center}.api.mailchimp.com/3.0/ping", responses) + ok, error_msg = SourceMailchimp().check_connection(logger, config=config) + + assert ok + assert not error_msg + + +@pytest.mark.parametrize( + "response, expected_message", + [ + ( + { + "json": { + "title": "API Key Invalid", + "details": "Your API key may be invalid, or you've attempted to access the wrong datacenter.", + } + }, + "Encountered an error while connecting to Mailchimp. Type: API Key Invalid. Details: Your API key may be invalid, or you've attempted to access the wrong datacenter.", + ), + ( + {"json": {"title": "Forbidden", "details": "You don't have permission to access this resource."}}, + "Encountered an error while connecting to Mailchimp. Type: Forbidden. Details: You don't have permission to access this resource.", + ), + ( + {"json": {}}, + "Encountered an error while connecting to Mailchimp. Type: Unknown Error. Details: An unknown error occurred. Please verify your credentials and try again.", + ), + ], + ids=["API Key Invalid", "Forbidden", "Unknown Error"], +) +def test_check_connection_error(requests_mock, config, data_center, response, expected_message): + requests_mock.register_uri("GET", f"https://{data_center}.api.mailchimp.com/3.0/ping", json=response["json"]) + ok, error_msg = SourceMailchimp().check_connection(logger, config=config) + + assert not ok + assert error_msg == expected_message + + +def test_get_oauth_data_center_ok(requests_mock, access_token, data_center): + responses = [ + {"json": {"dc": data_center}, "status_code": 200}, + ] + requests_mock.register_uri("GET", "https://login.mailchimp.com/oauth2/metadata", responses) + assert MailChimpAuthenticator().get_oauth_data_center(access_token) == data_center + + +def test_get_oauth_data_center_exception(requests_mock, access_token): + responses = [ + {"json": {}, "status_code": 200}, + {"json": {"error": "invalid_token"}, "status_code": 200}, + {"status_code": 403}, + ] + requests_mock.register_uri("GET", "https://login.mailchimp.com/oauth2/metadata", responses) + with pytest.raises(Exception): + MailChimpAuthenticator().get_oauth_data_center(access_token) + + +def test_oauth_config(requests_mock, oauth_config, data_center): + responses = [ + {"json": {"dc": data_center}, "status_code": 200}, + ] + requests_mock.register_uri("GET", "https://login.mailchimp.com/oauth2/metadata", responses) + assert MailChimpAuthenticator().get_auth(oauth_config) + + +def test_apikey_config(apikey_config): + assert MailChimpAuthenticator().get_auth(apikey_config) + + +def test_wrong_config(wrong_config): + with pytest.raises(Exception): + MailChimpAuthenticator().get_auth(wrong_config) + + +@pytest.mark.parametrize( + "config, expected_return", + [ + ({}, None), + ({"start_date": "2021-01-01T00:00:00.000Z"}, None), + ({"start_date": "2021-99-99T79:89:99.123Z"}, "The provided start date is not a valid date. Please check the date you input and try again."), + ({"start_date": "2021-01-01T00:00:00.000"}, "Please check the format of the start date against the pattern descriptor."), + ({"start_date": "2025-01-25T00:00:00.000Z"}, "The start date cannot be greater than the current date."), + ], + ids=[ + "No start date", + "Valid start date", + "Invalid start date", + "Invalid format", + "Future start date", + ] +) +def test_validate_start_date(config, expected_return): + source = SourceMailchimp() + result = source._validate_start_date(config) + assert result == expected_return + + +def test_streams_count(config): + streams = SourceMailchimp().streams(config) + assert len(streams) == 12 diff --git a/source-mailchimp/tests/test_streams.py b/source-mailchimp/tests/test_streams.py new file mode 100644 index 0000000000..60c22963d1 --- /dev/null +++ b/source-mailchimp/tests/test_streams.py @@ -0,0 +1,696 @@ +# +# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# + +import logging +from unittest.mock import MagicMock + +import pytest +import requests +import responses +from airbyte_cdk.models import SyncMode +from requests.exceptions import HTTPError +from source_mailchimp.streams import ( + Automations, + Campaigns, + EmailActivity, + InterestCategories, + Interests, + ListMembers, + Lists, + Reports, + SegmentMembers, + Segments, + Tags, + Unsubscribes, +) +from .utils import read_full_refresh, read_incremental + + +@pytest.mark.parametrize( + "stream, endpoint", + [ + (Lists, "lists"), + (Campaigns, "campaigns"), + (Segments, "lists/123/segments"), + ], +) +def test_stream_read(requests_mock, auth, stream, endpoint): + args = {"authenticator": auth} + stream = stream(**args) + stream_responses = [ + { + "json": { + stream.data_field: [{"id": "test_id"}], + } + } + ] + stream_url = stream.url_base + endpoint + requests_mock.register_uri("GET", stream_url, stream_responses) + + # Mock the 'lists' endpoint as Segments stream_slice + lists_url = stream.url_base + "lists" + lists_response = {"json": {"lists": [{"id": "123"}]}} + requests_mock.register_uri("GET", lists_url, [lists_response]) + records = read_full_refresh(stream) + + assert records + + +def test_next_page_token(auth): + args = {"authenticator": auth} + stream = Lists(**args) + inputs = {"response": MagicMock()} + expected_token = None + assert stream.next_page_token(**inputs) == expected_token + + resp = {"lists": [{"id": i} for i in range(1001)]} + inputs = {"response": MagicMock(json=MagicMock(return_value=resp))} + expected_token = {"offset": 1000} + assert stream.next_page_token(**inputs) == expected_token + + +@pytest.mark.parametrize( + "stream, inputs, expected_params", + [ + ( + Lists, + {"stream_slice": None, "stream_state": None, "next_page_token": None}, + {"count": 1000, "sort_dir": "ASC", "sort_field": "date_created", "exclude_fields": "lists._links"}, + ), + ( + Lists, + {"stream_slice": None, "stream_state": None, "next_page_token": {"offset": 1000}}, + {"count": 1000, "sort_dir": "ASC", "sort_field": "date_created", "offset": 1000, "exclude_fields": "lists._links"}, + ), + ( + InterestCategories, + {"stream_slice": {"parent": {"id": "123"}}, "stream_state": None, "next_page_token": None}, + {"count": 1000, "exclude_fields": "categories._links"}, + ), + ( + Interests, + {"stream_slice": {"parent": {"id": "123"}}, "stream_state": None, "next_page_token": {"offset": 2000}}, + {"count": 1000, "exclude_fields": "interests._links", "offset": 2000}, + ), + ], + ids=[ + "Lists: no next_page_token or state to add to request params", + "Lists: next_page_token added to request params", + "InterestCategories: no next_page_token to add to request params", + "Interests: next_page_token added to request params", + ], +) +def test_request_params(auth, stream, inputs, expected_params): + args = {"authenticator": auth} + if stream == InterestCategories: + args["parent"] = Lists(**args) + elif stream == Interests: + args["parent"] = InterestCategories(authenticator=auth, parent=Lists(authenticator=auth)) + stream = stream(**args) + assert stream.request_params(**inputs) == expected_params + + +@pytest.mark.parametrize( + "current_state_stream, latest_record, expected_state", + [ + ({}, {"date_created": "2020-01-01"}, {"date_created": "2020-01-01"}), + ({"date_created": "2020-01-01"}, {"date_created": "2021-01-01"}, {"date_created": "2021-01-01"}), + ({"date_created": "2021-01-01"}, {"date_created": "2022-01-01"}, {"date_created": "2022-01-01"}), + ], +) +def test_get_updated_state(auth, current_state_stream, latest_record, expected_state): + args = {"authenticator": auth} + stream = Lists(**args) + + new_stream_state = stream.get_updated_state(current_state_stream, latest_record) + assert new_stream_state == expected_state + + +@responses.activate +def test_stream_teams_read(auth): + args = {"authenticator": auth} + stream = EmailActivity(**args) + stream_url = stream.url_base + "reports/123/email-activity" + campaigns_stream_url = stream.url_base + "campaigns" + responses.add("GET", campaigns_stream_url, json={"campaigns": [{"id": 123}]}) + + response = {"emails": [{"campaign_id": 123, "activity": [{"action": "q", "timestamp": "2021-08-24T14:15:22Z"}]}]} + responses.add("GET", stream_url, json=response) + records = read_incremental(stream, {}) + + assert records + assert records == [{"campaign_id": 123, "action": "q", "timestamp": "2021-08-24T14:15:22Z"}] + assert len(responses.calls) == 2 + + +@responses.activate +def test_stream_parse_json_error(auth, caplog): + args = {"authenticator": auth} + stream = EmailActivity(**args) + stream_url = stream.url_base + "reports/123/email-activity" + campaigns_stream_url = stream.url_base + "campaigns" + responses.add("GET", campaigns_stream_url, json={"campaigns": [{"id": 123}]}) + responses.add("GET", stream_url, body="not_valid_json") + read_incremental(stream, {}) + assert "response.content=b'not_valid_json'" in caplog.text + + +@pytest.mark.parametrize( + "stream_class, stream_slice, stream_state, next_page_token, expected_params", + [ + # Test case 1: no state, no next_page_token + ( + Segments, + {"list_id": "123"}, + {}, + None, + {"count": 1000, "sort_dir": "ASC", "sort_field": "updated_at", "list_id": "123", "exclude_fields": "segments._links"}, + ), + # Test case 2: state and next_page_token + ( + ListMembers, + {"list_id": "123", "since_last_changed": "2023-10-15T00:00:00Z"}, + {"123": {"last_changed": "2023-10-15T00:00:00Z"}}, + {"offset": 1000}, + { + "count": 1000, + "sort_dir": "ASC", + "sort_field": "last_changed", + "list_id": "123", + "offset": 1000, + "exclude_fields": "members._links", + "since_last_changed": "2023-10-15T00:00:00Z", + }, + ), + ], + ids=[ + "Segments: no next_page_token or state to add to request params", + "ListMembers: next_page_token and state filter added to request params", + ], +) +def test_list_child_request_params(auth, stream_class, stream_slice, stream_state, next_page_token, expected_params): + """ + Tests the request_params method for the shared MailChimpListSubStream class. + """ + stream = stream_class(authenticator=auth) + params = stream.request_params(stream_slice=stream_slice, stream_state=stream_state, next_page_token=next_page_token) + assert params == expected_params + + +@pytest.mark.parametrize( + "stream_class, current_stream_state,latest_record,expected_state", + [ + # Test case 1: current_stream_state is empty + (Segments, {}, {"list_id": "list_1", "updated_at": "2023-10-15T00:00:00Z"}, {"list_1": {"updated_at": "2023-10-15T00:00:00Z"}}), + # Test case 2: latest_record's cursor is higher than current_stream_state for list_1 and updates it + ( + Segments, + {"list_1": {"updated_at": "2023-10-14T00:00:00Z"}, "list_2": {"updated_at": "2023-10-15T00:00:00Z"}}, + {"list_id": "list_1", "updated_at": "2023-10-15T00:00:00Z"}, + {"list_1": {"updated_at": "2023-10-15T00:00:00Z"}, "list_2": {"updated_at": "2023-10-15T00:00:00Z"}}, + ), + # Test case 3: latest_record's cursor is lower than current_stream_state for list_2, no state update + ( + ListMembers, + {"list_1": {"last_changed": "2023-10-15T00:00:00Z"}, "list_2": {"last_changed": "2023-10-15T00:00:00Z"}}, + {"list_id": "list_2", "last_changed": "2023-10-14T00:00:00Z"}, + {"list_1": {"last_changed": "2023-10-15T00:00:00Z"}, "list_2": {"last_changed": "2023-10-15T00:00:00Z"}}, + ), + ( + SegmentMembers, + {"segment_1": {"last_changed": "2023-10-15T00:00:00Z"}, "segment_2": {"last_changed": "2023-10-15T00:00:00Z"}}, + {"segment_id": "segment_1", "last_changed": "2023-10-16T00:00:00Z"}, + {"segment_1": {"last_changed": "2023-10-16T00:00:00Z"}, "segment_2": {"last_changed": "2023-10-15T00:00:00Z"}}, + ), + ( + SegmentMembers, + {"segment_1": {"last_changed": "2023-10-15T00:00:00Z"}}, + {"segment_id": "segment_2", "last_changed": "2023-10-16T00:00:00Z"}, + {"segment_1": {"last_changed": "2023-10-15T00:00:00Z"}, "segment_2": {"last_changed": "2023-10-16T00:00:00Z"}}, + ) + ], + ids=[ + "Segments: no current_stream_state", + "Segments: latest_record's cursor > than current_stream_state for list_1", + "ListMembers: latest_record's cursor < current_stream_state for list_2", + "SegmentMembers: latest_record's cursor > current_stream_state for segment_1", + "SegmentMembers: no stream_state for current slice, new slice added to state" + ], +) +def test_list_child_get_updated_state(auth, stream_class, current_stream_state, latest_record, expected_state): + """ + Tests that the get_updated_state method for the shared MailChimpListSubStream class + correctly updates state only for its slice. + """ + segments_stream = stream_class(authenticator=auth) + updated_state = segments_stream.get_updated_state(current_stream_state, latest_record) + assert updated_state == expected_state + + +@pytest.mark.parametrize( + "stream_state, records, expected", + [ + # Test case 1: No stream state, all records should be yielded + ( + {}, + {"members": [ + {"id": 1, "segment_id": "segment_1", "last_changed": "2021-01-01T00:00:00Z"}, + {"id": 2, "segment_id": "segment_1", "last_changed": "2021-01-02T00:00:00Z"} + ]}, + [ + {"id": 1, "segment_id": "segment_1", "last_changed": "2021-01-01T00:00:00Z"}, + {"id": 2, "segment_id": "segment_1", "last_changed": "2021-01-02T00:00:00Z"} + ] + ), + + # Test case 2: Records older than stream state should be filtered out + ( + {"segment_1": {"last_changed": "2021-02-01T00:00:00Z"}}, + {"members": [ + {"id": 1, "segment_id": "segment_1", "last_changed": "2021-01-01T00:00:00Z"}, + {"id": 2, "segment_id": "segment_1", "last_changed": "2021-03-01T00:00:00Z"} + ]}, + [{"id": 2, "segment_id": "segment_1", "last_changed": "2021-03-01T00:00:00Z"}] + ), + + # Test case 3: Two lists in stream state, only state for segment_id_1 determines filtering + ( + {"segment_1": {"last_changed": "2021-01-02T00:00:00Z"}, "segment_2": {"last_changed": "2022-01-01T00:00:00Z"}}, + {"members": [ + {"id": 1, "segment_id": "segment_1", "last_changed": "2021-01-01T00:00:00Z"}, + {"id": 2, "segment_id": "segment_1", "last_changed": "2021-03-01T00:00:00Z"} + ]}, + [{"id": 2, "segment_id": "segment_1", "last_changed": "2021-03-01T00:00:00Z"}] + ), + ], + ids=[ + "No stream state, all records should be yielded", + "Record < stream state, should be filtered out", + "Record >= stream state, should be yielded", + ] +) +def test_segment_members_parse_response(auth, stream_state, records, expected): + segment_members_stream = SegmentMembers(authenticator=auth) + response = MagicMock() + response.json.return_value = records + parsed_records = list(segment_members_stream.parse_response(response, stream_state, stream_slice={"segment_id": "segment_1"})) + assert parsed_records == expected, f"Expected: {expected}, Actual: {parsed_records}" + + +@pytest.mark.parametrize( + "stream, record, expected_record", + [ + ( + SegmentMembers, + {"id": 1, "email_address": "a@gmail.com", "email_type": "html", "opt_timestamp": ""}, + {"id": 1, "email_address": "a@gmail.com", "email_type": "html", "opt_timestamp": None} + ), + ( + SegmentMembers, + {"id": 1, "email_address": "a@gmail.com", "email_type": "html", "opt_timestamp": "2022-01-01T00:00:00.000Z", "merge_fields": {"FNAME": "Bob", "LNAME": "", "ADDRESS": "", "PHONE": ""}}, + {"id": 1, "email_address": "a@gmail.com", "email_type": "html", "opt_timestamp": "2022-01-01T00:00:00.000Z", "merge_fields": {"FNAME": "Bob", "LNAME": None, "ADDRESS": None, "PHONE": None}} + ), + ( + Campaigns, + {"id": "1", "web_id": 2, "email_type": "html", "create_time": "2022-01-01T00:00:00.000Z", "send_time": ""}, + {"id": "1", "web_id": 2, "email_type": "html", "create_time": "2022-01-01T00:00:00.000Z", "send_time": None} + ), + ( + Reports, + {"id": "1", "type": "rss", "clicks": {"clicks_total": 1, "last_click": "2022-01-01T00:00:00Z"}, "opens": {"opens_total": 0, "last_open": ""}}, + {"id": "1", "type": "rss", "clicks": {"clicks_total": 1, "last_click": "2022-01-01T00:00:00Z"}, "opens": {"opens_total": 0, "last_open": None}} + ), + ( + Lists, + {"id": "1", "name": "Santa's List", "stats": {"last_sub_date": "2022-01-01T00:00:00Z", "last_unsub_date": ""}}, + {"id": "1", "name": "Santa's List", "stats": {"last_sub_date": "2022-01-01T00:00:00Z", "last_unsub_date": None}} + ) + ], + ids=[ + "segment_members: opt_timestamp nullified", + "segment_members: nested merge_fields nullified", + "campaigns: send_time nullified", + "reports: nested opens.last_open nullified", + "lists: stats.last_unsub_date nullified" + ] +) +def test_filter_empty_fields(auth, stream, record, expected_record): + """ + Tests that empty string values are converted to None. + """ + stream = stream(authenticator=auth) + assert stream.filter_empty_fields(record) == expected_record + + +def test_unsubscribes_stream_slices(requests_mock, unsubscribes_stream, campaigns_stream, mock_campaigns_response): + campaigns_url = campaigns_stream.url_base + campaigns_stream.path() + requests_mock.register_uri("GET", campaigns_url, json={"campaigns": mock_campaigns_response}) + + expected_slices = [{"campaign_id": "campaign_1"}, {"campaign_id": "campaign_2"}, {"campaign_id": "campaign_3"}] + slices = list(unsubscribes_stream.stream_slices(sync_mode=SyncMode.incremental)) + assert slices == expected_slices + + +@pytest.mark.parametrize( + "stream_state, expected_records", + [ + ( # Test case 1: all records >= state + {"campaign_1": {"timestamp": "2022-01-01T00:00:00Z"}}, + [ + {"campaign_id": "campaign_1", "email_id": "email_1", "timestamp": "2022-01-02T00:00:00Z"}, + {"campaign_id": "campaign_1", "email_id": "email_2", "timestamp": "2022-01-02T00:00:00Z"}, + {"campaign_id": "campaign_1", "email_id": "email_3", "timestamp": "2022-01-01T00:00:00Z"}, + {"campaign_id": "campaign_1", "email_id": "email_4", "timestamp": "2022-01-03T00:00:00Z"}, + ], + ), + ( # Test case 2: one record < state + {"campaign_1": {"timestamp": "2022-01-02T00:00:00Z"}}, + [ + {"campaign_id": "campaign_1", "email_id": "email_1", "timestamp": "2022-01-02T00:00:00Z"}, + {"campaign_id": "campaign_1", "email_id": "email_2", "timestamp": "2022-01-02T00:00:00Z"}, + {"campaign_id": "campaign_1", "email_id": "email_4", "timestamp": "2022-01-03T00:00:00Z"}, + ], + ), + ( # Test case 3: one record >= state + {"campaign_1": {"timestamp": "2022-01-03T00:00:00Z"}}, + [ + {"campaign_id": "campaign_1", "email_id": "email_4", "timestamp": "2022-01-03T00:00:00Z"}, + ], + ), + ( # Test case 4: no state, all records returned + {}, + [ + {"campaign_id": "campaign_1", "email_id": "email_1", "timestamp": "2022-01-02T00:00:00Z"}, + {"campaign_id": "campaign_1", "email_id": "email_2", "timestamp": "2022-01-02T00:00:00Z"}, + {"campaign_id": "campaign_1", "email_id": "email_3", "timestamp": "2022-01-01T00:00:00Z"}, + {"campaign_id": "campaign_1", "email_id": "email_4", "timestamp": "2022-01-03T00:00:00Z"}, + ], + ), + ], + ids=[ + "all records >= state", + "one record < state", + "one record >= state", + "no state, all records returned", + ], +) +def test_parse_response(stream_state, expected_records, unsubscribes_stream): + mock_response = MagicMock(spec=requests.Response) + mock_response.json.return_value = { + "unsubscribes": [ + {"campaign_id": "campaign_1", "email_id": "email_1", "timestamp": "2022-01-02T00:00:00Z"}, + {"campaign_id": "campaign_1", "email_id": "email_2", "timestamp": "2022-01-02T00:00:00Z"}, + {"campaign_id": "campaign_1", "email_id": "email_3", "timestamp": "2022-01-01T00:00:00Z"}, + {"campaign_id": "campaign_1", "email_id": "email_4", "timestamp": "2022-01-03T00:00:00Z"}, + ] + } + stream_slice = {"campaign_id": "campaign_1"} + records = list(unsubscribes_stream.parse_response(response=mock_response, stream_slice=stream_slice, stream_state=stream_state)) + assert records == expected_records + + +@pytest.mark.parametrize( + "latest_record, expected_updated_state", + [ + # Test case 1: latest_record > and updates the state of campaign_1 + ( + { + "email_id": "email_1", + "email_address": "address1@email.io", + "reason": "None given", + "timestamp": "2022-01-05T00:00:00Z", + "campaign_id": "campaign_1", + }, + { + "campaign_1": {"timestamp": "2022-01-05T00:00:00Z"}, + "campaign_2": {"timestamp": "2022-01-02T00:00:00Z"}, + "campaign_3": {"timestamp": "2022-01-03T00:00:00Z"}, + }, + ), + # Test case 2: latest_record > and updates the state of campaign_2 + ( + { + "email_id": "email_2", + "email_address": "address2@email.io", + "reason": "Inappropriate content", + "timestamp": "2022-01-05T00:00:00Z", + "campaign_id": "campaign_2", + }, + { + "campaign_1": {"timestamp": "2022-01-01T00:00:00Z"}, + "campaign_2": {"timestamp": "2022-01-05T00:00:00Z"}, + "campaign_3": {"timestamp": "2022-01-03T00:00:00Z"}, + }, + ), + # Test case 3: latest_record < and does not update the state of campaign_3 + ( + { + "email_id": "email_3", + "email_address": "address3@email.io", + "reason": "No longer interested", + "timestamp": "2021-01-01T00:00:00Z", + "campaign_id": "campaign_3", + }, + { + "campaign_1": {"timestamp": "2022-01-01T00:00:00Z"}, + "campaign_2": {"timestamp": "2022-01-02T00:00:00Z"}, + "campaign_3": {"timestamp": "2022-01-03T00:00:00Z"}, + }, + ), + # Test case 4: latest_record sets state campaign_4 + ( + { + "email_id": "email_4", + "email_address": "address4@email.io", + "reason": "No longer interested", + "timestamp": "2022-01-04T00:00:00Z", + "campaign_id": "campaign_4", + }, + { + "campaign_1": {"timestamp": "2022-01-01T00:00:00Z"}, + "campaign_2": {"timestamp": "2022-01-02T00:00:00Z"}, + "campaign_3": {"timestamp": "2022-01-03T00:00:00Z"}, + "campaign_4": {"timestamp": "2022-01-04T00:00:00Z"}, + }, + ), + ], + ids=[ + "latest_record > and updates the state of campaign_1", + "latest_record > and updates the state of campaign_2", + "latest_record < and does not update the state of campaign_3", + "latest_record sets state of campaign_4", + ], +) +def test_unsubscribes_get_updated_state(unsubscribes_stream, mock_unsubscribes_state, latest_record, expected_updated_state): + updated_state = unsubscribes_stream.get_updated_state(mock_unsubscribes_state, latest_record) + assert updated_state == expected_updated_state + + +@pytest.mark.parametrize( + "stream,url,status_code,response_content,expected_availability,expected_reason_substring", + [ + ( + Campaigns, + "https://some_dc.api.mailchimp.com/3.0/campaigns", + 403, + b'{"object": "error", "status": 403, "code": "restricted_resource"}', + False, + "Unable to read campaigns stream", + ), + ( + EmailActivity, + "https://some_dc.api.mailchimp.com/3.0/reports/123/email-activity", + 403, + b'{"object": "error", "status": 403, "code": "restricted_resource"}', + False, + "Unable to read email_activity stream", + ), + ( + Lists, + "https://some_dc.api.mailchimp.com/3.0/lists", + 200, + b'{ "lists": [{"id": "123", "date_created": "2022-01-01T00:00:00+000"}]}', + True, + None, + ), + ( + Lists, + "https://some_dc.api.mailchimp.com/3.0/lists", + 400, + b'{ "object": "error", "status": 404, "code": "invalid_action"}', + False, + None, + ), + ], + ids=[ + "Campaigns 403 error", + "EmailActivity 403 error", + "Lists 200 success", + "Lists 400 error", + ], +) +def test_403_error_handling( + auth, requests_mock, stream, url, status_code, response_content, expected_availability, expected_reason_substring +): + """ + Test that availability strategy flags streams with 403 error as unavailable + and returns appropriate message. + """ + + requests_mock.get(url=url, status_code=status_code, content=response_content) + + stream = stream(authenticator=auth) + + if stream.__class__.__name__ == "EmailActivity": + stream.stream_slices = MagicMock(return_value=[{"campaign_id": "123"}]) + + try: + is_available, reason = stream.check_availability(logger=logging.Logger, source=MagicMock()) + + assert is_available is expected_availability + + if expected_reason_substring: + assert expected_reason_substring in reason + else: + assert reason is None + + # Handle non-403 error + except HTTPError as e: + assert e.response.status_code == status_code + + +@pytest.mark.parametrize( + "stream, stream_slice, expected_endpoint", + [ + (Automations, {}, "automations"), + (Lists, {}, "lists"), + (Campaigns, {}, "campaigns"), + (EmailActivity, {"campaign_id": "123"}, "reports/123/email-activity"), + (InterestCategories, {"parent": {"id": "123"}}, "lists/123/interest-categories"), + (Interests, {"parent": {"list_id": "123", "id": "456"}}, "lists/123/interest-categories/456/interests"), + (ListMembers, {"list_id": "123"}, "lists/123/members"), + (Reports, {}, "reports"), + (SegmentMembers, {"list_id": "123", "segment_id": "456"}, "lists/123/segments/456/members"), + (Segments, {"list_id": "123"}, "lists/123/segments"), + (Tags, {"parent": {"id": "123"}}, "lists/123/tag-search"), + (Unsubscribes, {"campaign_id": "123"}, "reports/123/unsubscribed"), + ], + ids=[ + "Automations", + "Lists", + "Campaigns", + "EmailActivity", + "InterestCategories", + "Interests", + "ListMembers", + "Reports", + "SegmentMembers", + "Segments", + "Tags", + "Unsubscribes", + ], +) +def test_path(auth, stream, stream_slice, expected_endpoint): + """ + Test the path method for each stream. + """ + + # Add parent stream where necessary + if stream is InterestCategories or stream is Tags: + stream = stream(authenticator=auth, parent=Lists(authenticator=auth)) + elif stream is Interests: + stream = stream(authenticator=auth, parent=InterestCategories(authenticator=auth, parent=Lists(authenticator=auth))) + else: + stream = stream(authenticator=auth) + + endpoint = stream.path(stream_slice=stream_slice) + + assert endpoint == expected_endpoint, f"Stream {stream}: expected path '{expected_endpoint}', got '{endpoint}'" + + +@pytest.mark.parametrize( + "start_date, state_date, expected_return_value", + [ + ( + "2021-01-01T00:00:00.000Z", + "2020-01-01T00:00:00+00:00", + "2021-01-01T00:00:00Z" + ), + ( + "2021-01-01T00:00:00.000Z", + "2023-10-05T00:00:00+00:00", + "2023-10-05T00:00:00+00:00" + ), + ( + None, + "2022-01-01T00:00:00+00:00", + "2022-01-01T00:00:00+00:00" + ), + ( + "2020-01-01T00:00:00.000Z", + None, + "2020-01-01T00:00:00Z" + ), + ( + None, + None, + None + ) + ] +) +def test_get_filter_date(auth, start_date, state_date, expected_return_value): + """ + Tests that the get_filter_date method returns the correct date string + """ + stream = Campaigns(authenticator=auth, start_date=start_date) + result = stream.get_filter_date(start_date, state_date) + assert result == expected_return_value, f"Expected: {expected_return_value}, Actual: {result}" + + +@pytest.mark.parametrize( + "stream_class, records, filter_date, expected_return_value", + [ + ( + Unsubscribes, + [ + {"campaign_id": "campaign_1", "email_id": "email_1", "timestamp": "2022-01-02T00:00:00Z"}, + {"campaign_id": "campaign_1", "email_id": "email_2", "timestamp": "2022-01-04T00:00:00Z"}, + {"campaign_id": "campaign_1", "email_id": "email_3", "timestamp": "2022-01-03T00:00:00Z"}, + {"campaign_id": "campaign_1", "email_id": "email_4", "timestamp": "2022-01-01T00:00:00Z"}, + ], + "2022-01-02T12:00:00+00:00", + [ + {"campaign_id": "campaign_1", "email_id": "email_2", "timestamp": "2022-01-04T00:00:00Z"}, + {"campaign_id": "campaign_1", "email_id": "email_3", "timestamp": "2022-01-03T00:00:00Z"}, + ], + ), + ( + SegmentMembers, + [ + {"id": 1, "segment_id": "segment_1", "last_changed": "2021-01-04T00:00:00Z"}, + {"id": 2, "segment_id": "segment_1", "last_changed": "2021-01-01T00:00:00Z"}, + {"id": 3, "segment_id": "segment_1", "last_changed": "2021-01-03T00:00:00Z"}, + {"id": 4, "segment_id": "segment_1", "last_changed": "2021-01-02T00:00:00Z"}, + ], + None, + [ + {"id": 1, "segment_id": "segment_1", "last_changed": "2021-01-04T00:00:00Z"}, + {"id": 2, "segment_id": "segment_1", "last_changed": "2021-01-01T00:00:00Z"}, + {"id": 3, "segment_id": "segment_1", "last_changed": "2021-01-03T00:00:00Z"}, + {"id": 4, "segment_id": "segment_1", "last_changed": "2021-01-02T00:00:00Z"}, + ], + ) + ], + ids=[ + "Unsubscribes: filter_date is set, records filtered", + "SegmentMembers: filter_date is None, all records returned" + ] +) +def test_filter_old_records(auth, stream_class, records, filter_date, expected_return_value): + """ + Tests the logic for filtering old records in streams that do not support query_param filtering. + """ + stream = stream_class(authenticator=auth) + filtered_records = list(stream.filter_old_records(records, filter_date)) + assert filtered_records == expected_return_value diff --git a/source-mailchimp/tests/unit_test.py b/source-mailchimp/tests/unit_test.py new file mode 100644 index 0000000000..0371987d87 --- /dev/null +++ b/source-mailchimp/tests/unit_test.py @@ -0,0 +1,13 @@ +# +# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# + + +from airbyte_cdk.logger import AirbyteLogger +from source_mailchimp import SourceMailchimp + + +def test_client_wrong_credentials(): + source = SourceMailchimp() + status, error = source.check_connection(logger=AirbyteLogger, config={"username": "Jonny", "apikey": "blah-blah"}) + assert not status diff --git a/source-mailchimp/tests/utils.py b/source-mailchimp/tests/utils.py new file mode 100644 index 0000000000..ca673999a9 --- /dev/null +++ b/source-mailchimp/tests/utils.py @@ -0,0 +1,27 @@ +# +# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# + +from typing import Any, MutableMapping + +from airbyte_cdk.models import SyncMode +from airbyte_cdk.sources.streams import Stream + + +def read_incremental(stream_instance: Stream, stream_state: MutableMapping[str, Any]): + res = [] + slices = stream_instance.stream_slices(sync_mode=SyncMode.incremental, stream_state=stream_state) + for slice in slices: + records = stream_instance.read_records(sync_mode=SyncMode.incremental, stream_slice=slice, stream_state=stream_state) + for record in records: + stream_state = stream_instance.get_updated_state(stream_state, record) + res.append(record) + return res + + +def read_full_refresh(stream_instance: Stream): + records = [] + slices = stream_instance.stream_slices(sync_mode=SyncMode.full_refresh) + for slice in slices: + records.extend(list(stream_instance.read_records(stream_slice=slice, sync_mode=SyncMode.full_refresh))) + return records