From 8a1ade3dd1c2f95a760b7168ac6c4feb5154957b Mon Sep 17 00:00:00 2001 From: Anya Agarenko Date: Mon, 30 Oct 2023 18:19:51 +0300 Subject: [PATCH] Rebuilding project structure from scratch (#1976) --- .dockerignore | 2 + .github/actions/build/action.yml | 42 + .github/workflows/ci.yml | 121 +- .github/workflows/crossplatform.yml | 80 +- .python-version | 1 - Dockerfile | 71 +- Makefile | 45 +- README.md | 24 +- dev-requirements.txt | 515 --- docker-compose.yml | 2 +- src/mypy.ini => mypy.ini | 8 +- poetry.lock | 3980 +++++++++++++++++ pyproject.toml | 318 +- renovate.json | 4 +- requirements.txt | 249 -- src/a12n/tests/conftest.py | 6 - src/amocrm/client/__init__.py | 3 - src/amocrm/dto/__init__.py | 17 - src/amocrm/models/__init__.py | 13 - src/app/admin/__init__.py | 12 - src/app/conf/boilerplate.py | 10 - src/app/conf/environ.py | 15 - src/app/conf/tags.py | 6 - src/app/fixtures/__init__.py | 21 - src/app/fixtures/send_mail.py | 6 - src/app/integrations/dashamail/__init__.py | 7 - src/app/tasks/__init__.py | 7 - src/app/urls/v2.py | 28 - src/{a12n => apps}/__init__.py | 0 .../migrations => apps/a12n}/__init__.py | 0 src/{ => apps}/a12n/api/forms.py | 2 +- src/{ => apps}/a12n/api/serializers.py | 2 +- src/{ => apps}/a12n/api/throttling.py | 2 +- src/{ => apps}/a12n/api/views.py | 16 +- src/{ => apps}/a12n/apps.py | 4 +- src/{ => apps}/a12n/jwt.py | 2 +- .../a12n/migrations/0001_initial.py | 4 +- .../0002_PasswordlessTokensUsedDate.py | 0 .../a12n/migrations}/__init__.py | 0 src/{ => apps}/a12n/models.py | 4 +- src/{ => apps}/a12n/signals/handlers.py | 0 src/{ => apps}/a12n/urls.py | 12 +- src/{ => apps}/a12n/utils.py | 2 +- .../migrations => apps/amocrm}/__init__.py | 0 src/{ => apps}/amocrm/apps.py | 2 +- src/apps/amocrm/client/__init__.py | 3 + src/{ => apps}/amocrm/client/client.py | 2 +- src/{ => apps}/amocrm/client/http.py | 6 +- src/apps/amocrm/dto/__init__.py | 17 + src/{ => apps}/amocrm/dto/catalogs.py | 4 +- src/{ => apps}/amocrm/dto/customer.py | 6 +- src/{ => apps}/amocrm/dto/groups.py | 8 +- src/{ => apps}/amocrm/dto/lead.py | 14 +- src/{ => apps}/amocrm/dto/pipelines.py | 2 +- src/{ => apps}/amocrm/dto/product.py | 8 +- src/{ => apps}/amocrm/dto/transaction.py | 6 +- src/{ => apps}/amocrm/exceptions.py | 2 +- src/{ => apps}/amocrm/ids.py | 8 +- .../amocrm/migrations/0001_AddAmoCRMUser.py | 0 .../0002_AddAmoCRMGroup_and_Course.py | 0 .../migrations/0003_Add_AmoCRMUserContact.py | 0 .../0004_Add_AmoCRM_leads_and_transactions.py | 0 .../0005_Add_lead_and_transaction_to_Order.py | 0 ...erties_from_amocrm_lead_and_transaction.py | 0 .../0007_Move_contact_id_to_AmoCRMUser.py | 0 .../0008_Delete_separate_AmoCRMUserContact.py | 0 .../amocrm/migrations}/__init__.py | 0 src/apps/amocrm/models/__init__.py | 13 + src/{ => apps}/amocrm/models/amocrm_course.py | 2 +- .../amocrm/models/amocrm_order_lead.py | 2 +- .../amocrm/models/amocrm_order_transaction.py | 2 +- .../amocrm/models/amocrm_product_group.py | 2 +- src/{ => apps}/amocrm/models/amocrm_user.py | 2 +- .../amocrm/services}/__init__.py | 0 .../amocrm/services/access_token_getter.py | 4 +- .../amocrm/services/course_pusher.py | 8 +- .../amocrm/services/group_pusher.py | 8 +- .../amocrm/services/orders/order_pusher.py | 14 +- .../amocrm/services/orders/order_returner.py | 8 +- src/{ => apps}/amocrm/services/user_pusher.py | 8 +- src/{ => apps}/amocrm/tasks.py | 18 +- .../tests/http => apps/banking}/__init__.py | 0 src/{ => apps}/banking/api/views.py | 4 +- src/{ => apps}/banking/apps.py | 2 +- src/apps/banking/atol/__init__.py | 5 + src/{ => apps}/banking/atol/auth.py | 2 +- src/{ => apps}/banking/atol/client.py | 8 +- src/{ => apps}/banking/atol/exceptions.py | 0 src/{ => apps}/banking/base.py | 6 +- .../banking/management/commands/test_atol.py | 4 +- .../banking/migrations/0001_initial.py | 0 .../banking/migrations}/__init__.py | 0 src/{ => apps}/banking/models.py | 4 +- src/{ => apps}/banking/price_calculator.py | 2 +- src/{ => apps}/banking/selector.py | 12 +- src/{ => apps}/banking/urls.py | 10 +- src/{ => apps}/banking/zero_price_bank.py | 4 +- .../services => apps/chains}/__init__.py | 0 src/apps/chains/admin/__init__.py | 7 + src/{ => apps}/chains/admin/chain.py | 10 +- src/{ => apps}/chains/admin/forms.py | 4 +- src/{ => apps}/chains/admin/message.py | 10 +- src/{ => apps}/chains/apps.py | 2 +- .../chains/migrations/0001_Initial.py | 0 .../0002_ChainsAdminImprovements.py | 0 .../migrations/0003_LimitParentChoices.py | 0 .../chains/migrations/0004_UniqueChainName.py | 0 .../migrations/0005_MessageAdminSpeedup.py | 0 src/{ => apps}/chains/migrations/0006_i18n.py | 0 .../migrations/0007_StudyConstraints.py | 0 .../migrations/0008_ChainProgressStatus.py | 0 ...teChainProgressForAlreadyPurchasedUsers.py | 0 .../migrations/0010_ChainsAdminLabelChange.py | 0 .../migrations/0011_chain_archived_field.py | 0 .../chains/migrations}/__init__.py | 0 src/apps/chains/models/__init__.py | 9 + src/{ => apps}/chains/models/chain.py | 4 +- src/{ => apps}/chains/models/message.py | 6 +- src/{ => apps}/chains/models/progress.py | 8 +- src/apps/chains/services/__init__.py | 7 + .../chains/services/chain_sender.py | 12 +- .../chains/services/message_sender.py | 12 +- .../admin/js/clickable_message_intervals.js | 0 .../static/admin/js/limit_message_choices.js | 0 src/{ => apps}/chains/tasks.py | 8 +- src/{app => apps/diplomas}/__init__.py | 0 src/{ => apps}/diplomas/admin.py | 14 +- src/{ => apps}/diplomas/api/permissions.py | 0 src/{ => apps}/diplomas/api/serializers.py | 8 +- src/{ => apps}/diplomas/api/viewsets.py | 10 +- src/{ => apps}/diplomas/apps.py | 2 +- .../diplomas/migrations/0001_initial.py | 0 .../migrations/0002_RandomDiplomaFileNames.py | 4 +- .../migrations/0003_ShortDiplomaSlug.py | 0 .../migrations/0004_DiplomaTemplates.py | 0 ..._DroppedHomeworkFlagFromDiplomaTemplate.py | 0 .../0006_DiplomaTemplateHomework.py | 0 .../diplomas}/migrations/__init__.py | 0 src/{ => apps}/diplomas/models.py | 10 +- src/apps/diplomas/services/__init__.py | 7 + .../diplomas/services/diploma_generator.py | 14 +- .../diplomas/services/diploma_regenerator.py | 16 +- src/{ => apps}/diplomas/tasks.py | 14 +- src/{ => apps}/diplomas/urls.py | 2 +- src/{banking => apps/homework}/__init__.py | 0 src/apps/homework/admin/__init__.py | 2 + src/{ => apps}/homework/admin/answer/admin.py | 10 +- .../homework/admin/answer/filters.py | 2 +- .../homework/admin/question/admin.py | 8 +- src/{ => apps}/homework/api/filtersets.py | 4 +- src/{ => apps}/homework/api/permissions.py | 2 +- src/{ => apps}/homework/api/serializers.py | 14 +- src/{ => apps}/homework/api/views.py | 12 +- src/{ => apps}/homework/api/viewsets.py | 34 +- src/{ => apps}/homework/apps.py | 4 +- .../homework/migrations/0001_initial.py | 0 .../migrations/0002_MultipleCourses.py | 0 .../homework/migrations/0003_AnswerTree.py | 0 .../migrations/0004_DefaultAnswerOrdering.py | 0 .../migrations/0005_GodAnswerUsers.py | 0 .../migrations/0006_AnswerAccessLogEntry.py | 0 .../0006_SeeAllQuestionsPermission.py | 0 .../migrations/0007_merge_20210420_0027.py | 0 .../migrations/0008_AnswersCrossCheck.py | 0 .../0009_ExcludeAnswersFromCrossCheck.py | 0 .../0010_ForogttenAnswerModified.py | 0 .../homework/migrations/0011_AnswerImage.py | 4 +- .../homework/migrations/0012_Reaction.py | 0 .../0013_DropAnswerRelationsForMypyUpgrade.py | 0 .../homework}/migrations/__init__.py | 0 src/apps/homework/models/__init__.py | 13 + src/{ => apps}/homework/models/answer.py | 14 +- .../models/answer_access_log_entry.py | 8 +- .../homework/models/answer_cross_check.py | 4 +- .../homework/models/answer_image.py | 6 +- src/{ => apps}/homework/models/question.py | 6 +- src/{ => apps}/homework/models/reaction.py | 4 +- src/apps/homework/services/__init__.py | 12 + .../services/answer_crosscheck_dispatcher.py | 8 +- .../homework/services/new_answer_notifier.py | 8 +- .../question_crosscheck_dispatcher.py | 14 +- .../homework/services/reaction_creator.py | 10 +- src/{ => apps}/homework/signals/handlers.py | 4 +- src/{ => apps}/homework/tasks.py | 8 +- src/{ => apps}/homework/urls.py | 6 +- src/{chains => apps/magnets}/__init__.py | 0 src/{ => apps}/magnets/admin.py | 6 +- src/{ => apps}/magnets/api/serializers.py | 2 +- src/{ => apps}/magnets/api/validators.py | 2 +- src/{ => apps}/magnets/api/views.py | 10 +- src/{ => apps}/magnets/apps.py | 2 +- src/{ => apps}/magnets/creator.py | 10 +- .../magnets/migrations/0001_initial.py | 0 .../magnets/migrations/0002_CampaignLog.py | 0 .../migrations/0003_CampaignSuccessMessage.py | 0 .../magnets}/migrations/__init__.py | 0 src/{ => apps}/magnets/models.py | 8 +- src/{ => apps}/magnets/urls.py | 2 +- src/{diplomas => apps/mailing}/__init__.py | 0 src/apps/mailing/admin/__init__.py | 3 + .../mailing/admin/email_configuration.py | 4 +- .../mailing/admin/personal_email_domain.py | 8 + src/{ => apps}/mailing/apps.py | 2 +- src/{ => apps}/mailing/backends.py | 0 src/{ => apps}/mailing/configuration.py | 4 +- src/{ => apps}/mailing/helpers.py | 0 .../management/commands/send_test_email.py | 2 +- .../0001_EmailLogEntryMovedToDedicatedApp.py | 4 +- .../migrations/0002_EmailConfiguration.py | 0 .../mailing/migrations/0003_CustomReplyTo.py | 0 .../migrations/0004_PersonalEmailDomain.py | 0 .../0005_MigrateIndexDefinitions.py | 0 .../mailing}/migrations/__init__.py | 0 src/apps/mailing/models/__init__.py | 10 + .../mailing/models/configuration.py | 4 +- src/{ => apps}/mailing/models/log_entry.py | 4 +- .../mailing/models/personal_email_domain.py | 4 +- src/{ => apps}/mailing/owl.py | 10 +- src/{ => apps}/mailing/tasks.py | 4 +- src/{homework => apps/notion}/__init__.py | 0 src/{ => apps}/notion/admin.py | 16 +- src/{ => apps}/notion/api/serializers.py | 2 +- src/{ => apps}/notion/api/throttling.py | 2 +- src/{ => apps}/notion/api/views.py | 12 +- src/{ => apps}/notion/apps.py | 2 +- src/{ => apps}/notion/block.py | 6 +- src/{ => apps}/notion/cache.py | 8 +- src/{ => apps}/notion/client.py | 10 +- src/{ => apps}/notion/exceptions.py | 0 src/{ => apps}/notion/helpers.py | 4 +- .../commands/update_notion_cache.py | 2 +- .../notion/migrations/0001_initial.py | 2 +- .../migrations/0002_NotionaMaterialTitle.py | 0 .../migrations/0003_HomePageMaterial.py | 0 .../migrations/0004_NotionMaterialSlug.py | 0 .../notion/migrations/0005_MaterailFiles.py | 0 .../migrations/0006_NotionCacheEntry.py | 0 .../notion}/migrations/__init__.py | 0 src/{ => apps}/notion/models.py | 10 +- src/{ => apps}/notion/page.py | 8 +- src/{ => apps}/notion/rewrite.py | 10 +- src/{ => apps}/notion/tasks.py | 8 +- src/{ => apps}/notion/types.py | 0 src/{ => apps}/notion/urls.py | 2 +- src/{magnets => apps/orders}/__init__.py | 0 src/apps/orders/admin/__init__.py | 2 + src/{ => apps}/orders/admin/orders/actions.py | 10 +- src/{ => apps}/orders/admin/orders/admin.py | 20 +- src/{ => apps}/orders/admin/orders/filters.py | 4 +- src/{ => apps}/orders/admin/orders/forms.py | 6 +- .../orders/admin/orders/throttling.py | 2 +- .../orders/admin/promocodes/actions.py | 2 +- .../orders/admin/promocodes/admin.py | 12 +- src/{ => apps}/orders/api/serializers.py | 0 src/{ => apps}/orders/api/throttling.py | 2 +- src/{ => apps}/orders/api/views.py | 4 +- src/{ => apps}/orders/apps.py | 4 +- src/{ => apps}/orders/exceptions.py | 0 src/{ => apps}/orders/fields.py | 2 +- src/{ => apps}/orders/human_readable.py | 4 +- .../orders/migrations/0001_initial.py | 8 +- src/{ => apps}/orders/migrations/0002_L18N.py | 0 .../orders/migrations/0003_OrderBundles.py | 6 +- .../orders/migrations/0004_PromoCodes.py | 0 .../0005_PromoCodesActiveByDefault.py | 0 .../migrations/0006_PromoCodeComments.py | 0 .../orders/migrations/0007_OrderPromoCodes.py | 0 .../orders/migrations/0008_PromocodesI18n.py | 0 .../orders/migrations/0009_Gifts.py | 0 .../orders/migrations/0010_OrderI18n.py | 8 +- .../0011_NotificationToGiverIsSent.py | 0 .../migrations/0012_DesiredBankString.py | 0 .../migrations/0013_PerProductPromoCodes.py | 0 .../migrations/0014_NonAttachedPromocodes.py | 0 .../orders/migrations/0015_PromoCodeValue.py | 0 .../orders/migrations/0016_UnpaidDate.py | 0 .../migrations/0017_OrderPermissions.py | 0 .../migrations/0018_StudentProxyModel.py | 0 .../orders/migrations/0019_OrderAuthor.py | 0 .../0020_OrderAuthorMigrationFix.py | 0 ...rderConstraintForProductItemsCountCheck.py | 0 .../migrations/0022_PurchaseTimeUERate.py | 0 .../orders/migrations/0023_AcquringPercent.py | 0 .../orders/migrations/0024_OrderSlugs.py | 0 .../orders/migrations/0025_BankFieldRename.py | 0 .../migrations/0026_PromocodeExpiration.py | 0 .../0027_PromocodeDestinationField.py | 0 .../0028_PromocodeExpiresFieldTranslation.py | 0 .../orders/migrations/0029_DropGiftFields.py | 0 .../0030_Add_lead_and_transaction_to_Order.py | 0 ...erties_from_amocrm_lead_and_transaction.py | 0 .../migrations/0032_order_set_bank_choices.py | 0 .../orders}/migrations/__init__.py | 0 src/apps/orders/models/__init__.py | 7 + src/{ => apps}/orders/models/order.py | 22 +- src/{ => apps}/orders/models/promocode.py | 6 +- src/apps/orders/services/__init__.py | 17 + .../orders/services/order_creator.py | 30 +- .../services/order_diploma_generator.py | 14 +- .../orders/services/order_email_changer.py | 8 +- .../orders/services/order_paid_setter.py | 12 +- .../orders/services/order_refunder.py | 26 +- .../orders/services/order_shipper.py | 8 +- .../orders/services/order_unshipper.py | 4 +- .../orders/services/purchase_creator.py | 24 +- .../orders/signals}/__init__.py | 0 src/{ => apps}/orders/signals/handlers.py | 8 +- src/{ => apps}/orders/signals/signals.py | 0 .../orders/static/admin/order_list.css | 0 src/{ => apps}/orders/tasks.py | 6 +- src/{ => apps}/orders/urls.py | 2 +- .../migrations => apps/products}/__init__.py | 0 src/apps/products/admin/__init__.py | 2 + src/{ => apps}/products/admin/course.py | 12 +- .../products/admin/courses/actions.py | 0 src/{ => apps}/products/admin/group.py | 8 +- src/{ => apps}/products/api/serializers.py | 4 +- src/{ => apps}/products/api/views.py | 22 +- src/{ => apps}/products/apps.py | 2 +- .../products/migrations/0001_initial.py | 0 .../migrations/0002_CourseGenitiveName.py | 0 .../migrations/0003_DefaultOrdering.py | 0 .../products/migrations/0004_ReceiptNames.py | 0 .../migrations/0005_ClickMeeetingRoomURL.py | 0 .../migrations/0006_ShippableFullName.py | 0 .../products/migrations/0007_L18N.py | 0 .../products/migrations/0008_Bundles.py | 0 .../migrations/0008_CustomTemplateId.py | 0 .../migrations/0009_merge_20191222_1525.py | 0 .../migrations/0010_ParentShippableModel.py | 0 .../products/migrations/0011_Price.py | 0 .../migrations/0012_ZoomusWebinarId.py | 0 .../migrations/0013_TemplateIdRename.py | 0 .../migrations/0014_CourseWelcomeLetter.py | 0 .../0015_GiftWelcomeLetterTemplateId.py | 0 .../migrations/0016_MailchimpListId.py | 0 .../migrations/0017_TinkoffCreditPromoCode.py | 0 .../products/migrations/0018_ProductGroups.py | 0 .../migrations/0019_CourseDisplayInLMS.py | 0 .../migrations/0020_InternationalNames.py | 0 .../migrations/0021_removeMailchimpListId.py | 0 .../migrations/0022_DitchClickmeetings.py | 0 .../migrations/0023_DiplomaTemplateContext.py | 0 ...024_DiplomaTemplateContextIsNotRequired.py | 0 .../migrations/0025_DisableTriggersFlag.py | 0 .../0026_CourseConfirmationTemplateId.py | 0 .../migrations/0027_CourseConfirmationURL.py | 0 .../migrations/0028_CourseCoverField.py | 4 +- .../products/migrations/0029_TagsForUser.py | 0 .../0030_SetUniqieSlugForProducts.py | 0 .../migrations/0031_DropGiftFields.py | 0 .../migrations/0032_Drop_Zoom_integration.py | 0 .../products/migrations}/__init__.py | 0 src/{ => apps}/products/models/__init__.py | 8 +- src/{ => apps}/products/models/base.py | 14 +- src/{ => apps}/products/models/bundle.py | 8 +- src/{ => apps}/products/models/course.py | 10 +- src/{ => apps}/products/models/group.py | 4 +- src/{ => apps}/products/models/record.py | 6 +- .../static/admin/css/course_action_form.css | 0 .../static/admin/js/course_action_form.js | 0 src/{ => apps}/products/tasks.py | 2 +- src/{ => apps}/products/urls.py | 4 +- .../stripebank}/__init__.py | 0 src/{ => apps}/stripebank/api/serializers.py | 4 +- src/{ => apps}/stripebank/api/views.py | 4 +- src/{ => apps}/stripebank/apps.py | 2 +- src/{ => apps}/stripebank/bank.py | 2 +- .../stripebank/migrations/0001_Initial.py | 0 .../stripebank/migrations/0002_OrderUUID.py | 0 .../stripebank/migrations}/__init__.py | 0 src/{ => apps}/stripebank/models.py | 4 +- .../migrations => apps/studying}/__init__.py | 0 src/{ => apps}/studying/api/serializers.py | 2 +- src/{ => apps}/studying/api/views.py | 10 +- src/{ => apps}/studying/apps.py | 4 +- .../studying/migrations/0001_initial.py | 0 .../0002_StudyIsHomeworkAccepted.py | 0 .../studying/migrations}/__init__.py | 0 src/{ => apps}/studying/models.py | 4 +- src/apps/studying/shipment/__init__.py | 5 + src/{ => apps}/studying/shipment/base.py | 6 +- src/{ => apps}/studying/shipment/course.py | 10 +- src/{ => apps}/studying/shipment_factory.py | 10 +- src/{ => apps}/studying/urls.py | 2 +- .../tinkoff}/__init__.py | 0 src/{ => apps}/tinkoff/api/permissions.py | 6 +- src/{ => apps}/tinkoff/api/serializers.py | 6 +- src/{ => apps}/tinkoff/api/views.py | 14 +- src/{ => apps}/tinkoff/apps.py | 2 +- src/{ => apps}/tinkoff/bank.py | 4 +- src/{ => apps}/tinkoff/credit.py | 2 +- src/{ => apps}/tinkoff/dolyame.py | 2 +- src/{ => apps}/tinkoff/exceptions.py | 0 .../management/commands/refund_dolyame.py | 4 +- .../tinkoff/migrations/0001_initial.py | 0 .../tinkoff/migrations/0002_EmptyCardID.py | 0 .../migrations/0003_CreditNotifications.py | 0 .../migrations/0004_DolyameNotifications.py | 0 .../tinkoff/migrations/0005_DolyameTypoFix.py | 0 .../migrations/0006_DolyameRefundedStatus.py | 0 .../migrations/0007_TinkoffCreditOrderSlug.py | 0 .../migrations/0008_TinkoffBankOrderSlug.py | 0 .../migrations/0009_DolyameOrderUUID.py | 0 .../tinkoff/migrations}/__init__.py | 0 src/{ => apps}/tinkoff/models.py | 4 +- src/{ => apps}/tinkoff/tasks.py | 8 +- src/{ => apps}/tinkoff/token_validator.py | 6 +- src/{products => apps/users}/__init__.py | 0 src/apps/users/admin/__init__.py | 7 + src/{ => apps}/users/admin/student.py | 10 +- src/{ => apps}/users/admin/user.py | 4 +- src/{ => apps}/users/api/serializers.py | 2 +- src/{ => apps}/users/api/views.py | 8 +- src/{ => apps}/users/apps.py | 2 +- .../users/management}/__init__.py | 0 .../users/management/commands}/__init__.py | 0 .../commands/create_dev_admin_user.py | 2 +- .../commands/update_students_tags.py | 2 +- .../users/migrations/0001_initial.py | 0 .../migrations/0002_SubscribedToNewsLetter.py | 0 .../users/migrations/0003_Django31.py | 0 .../users/migrations/0004_NamesInEnglish.py | 0 .../users/migrations/0005_UserUUID.py | 0 .../users/migrations/0006_Gender.py | 0 .../migrations/0007_StudentProxyModel.py | 0 .../migrations/0008_AddtionalProfileFields.py | 0 .../migrations/0009_add_telegram_username.py | 0 .../0010_drop_linkedin_github_constraints.py | 0 .../users/migrations/0011_TagsForUser.py | 0 .../users}/migrations/__init__.py | 0 src/{ => apps}/users/models.py | 6 +- src/apps/users/services/__init__.py | 7 + src/{ => apps}/users/services/user_creator.py | 6 +- src/{ => apps}/users/services/user_updater.py | 10 +- src/apps/users/tags/__init__.py | 11 + src/{ => apps}/users/tags/any_purchase_tag.py | 2 +- src/{ => apps}/users/tags/b2b_tag.py | 4 +- src/{ => apps}/users/tags/base.py | 4 +- src/{ => apps}/users/tags/pipeline.py | 4 +- src/{ => apps}/users/tags/purchased_tag.py | 6 +- src/{ => apps}/users/tags/started_tag.py | 6 +- src/{ => apps}/users/tasks.py | 6 +- src/{ => apps}/users/urls.py | 2 +- src/banking/atol/__init__.py | 5 - src/chains/admin/__init__.py | 7 - src/chains/models/__init__.py | 9 - src/chains/services/__init__.py | 7 - src/conftest.py | 20 - src/{app => core}/.env.ci | 0 src/{studying => core}/__init__.py | 0 src/core/admin/__init__.py | 12 + src/{app => core}/admin/filters.py | 0 src/{app => core}/admin/mixin.py | 2 +- src/{app => core}/admin/model_admin.py | 2 +- src/{app => core}/admin/widgets.py | 0 src/{app => core}/api/filters.py | 0 src/{app => core}/api/mixins.py | 0 src/{app => core}/celery.py | 8 +- src/{app => core}/conf/api.py | 8 +- src/{app => core}/conf/auth.py | 4 +- src/core/conf/boilerplate.py | 10 + src/{app => core}/conf/cache.py | 2 +- src/{app => core}/conf/db.py | 2 +- src/{app => core}/conf/debug_toolbar.py | 0 src/{app => core}/conf/email.py | 2 +- src/core/conf/environ.py | 18 + src/{app => core}/conf/features.py | 2 +- src/{app => core}/conf/healthchecks.py | 0 src/{app => core}/conf/http.py | 2 +- src/{app => core}/conf/i18n.py | 0 src/{app => core}/conf/installed_apps.py | 63 +- src/{app => core}/conf/integrations/amocrm.py | 2 +- src/{app => core}/conf/integrations/atol.py | 2 +- .../conf/integrations/banking/banking.py | 2 +- .../conf/integrations/banking/stripe.py | 2 +- .../conf/integrations/banking/tinkoff.py | 2 +- .../conf/integrations/clickmeetings.py | 2 +- .../conf/integrations/diploma_generator.py | 2 +- src/{app => core}/conf/integrations/notion.py | 2 +- src/{app => core}/conf/integrations/tg.py | 2 +- src/{app => core}/conf/markdown.py | 0 src/{app => core}/conf/media.py | 2 +- src/{app => core}/conf/middleware.py | 10 +- src/{app => core}/conf/sentry.py | 6 +- src/{app => core}/conf/static.py | 4 +- src/{app => core}/conf/storage.py | 2 +- src/core/conf/tags.py | 6 + src/{app => core}/conf/templates.py | 0 src/{app => core}/conf/timezone.py | 2 +- src/{app => core}/conf/vat.py | 2 +- src/{app => core}/conf/warnings.py | 0 src/{app => core}/current_user.py | 2 +- src/{app => core}/exceptions.py | 0 src/{app => core}/files.py | 2 +- src/{app => core}/helpers.py | 0 src/core/integrations/dashamail/__init__.py | 7 + .../integrations/dashamail/client.py | 6 +- .../integrations/dashamail/exceptions.py | 0 .../integrations/dashamail/http.py | 2 +- .../dashamail/subscription_updater.py | 6 +- src/{app => core}/integrations/s3.py | 0 src/{app => core}/integrations/tg.py | 0 .../commands/clean_antispam_logs.py | 2 +- src/{app => core}/markdown.py | 0 .../middleware/global_current_user.py | 4 +- src/{app => core}/middleware/real_ip.py | 0 ...set_user_from_non_django_authentication.py | 2 +- .../migrations/0001_CourseMailLog.py | 0 .../migrations/0002_DropTheOnetimeApp.py | 2 +- .../migrations/0003_RenameCoursesAppPt1.py | 2 +- .../0004_EmailLogEntryMovedToDedicatedApp.py | 2 +- .../migrations/0005_RemoveTriggersApp.py | 2 +- src/{studying => core}/migrations/__init__.py | 0 src/{app => core}/models.py | 0 src/{app => core}/pagination.py | 0 src/{app => core}/permissions.py | 0 src/{app => core}/pricing.py | 0 src/{app => core}/renderers.py | 0 src/{app => core}/serializers.py | 2 +- src/{app => core}/services.py | 0 src/{app => core}/settings.py | 2 +- src/{app => core}/static/admin.css | 0 src/{app => core}/static/prettyjson.css | 0 src/core/tasks/__init__.py | 7 + src/{app => core}/tasks/dashamail.py | 6 +- src/{app => core}/tasks/tg.py | 4 +- src/{app => core}/test/api_client.py | 2 +- .../test/disable_test_command_runner.py | 0 src/{app => core}/test/factory.py | 0 src/{app => core}/test/mixer.py | 0 src/{app => core}/throttling.py | 0 src/{app => core}/types.py | 0 src/{app => core}/urls/__init__.py | 4 +- src/core/urls/v2.py | 28 + src/{app => core}/validators.py | 0 src/{app => core}/views.py | 2 +- src/{app => core}/viewsets.py | 2 +- src/{app => core}/wsgi.py | 2 +- src/diplomas/services/__init__.py | 7 - src/homework/admin/__init__.py | 2 - src/homework/models/__init__.py | 13 - src/homework/services/__init__.py | 12 - src/locale/ru/LC_MESSAGES/django.po | 394 +- src/mailing/admin/__init__.py | 3 - src/mailing/admin/personal_email_domain.py | 8 - src/mailing/models/__init__.py | 10 - src/manage.py | 2 +- src/orders/admin/__init__.py | 2 - src/orders/models/__init__.py | 7 - src/orders/services/__init__.py | 17 - src/products/admin/__init__.py | 2 - src/pyproject.toml | 1 - src/pytest.ini | 34 - src/studying/shipment/__init__.py | 5 - src/users/admin/__init__.py | 7 - src/users/services/__init__.py | 7 - src/users/tags/__init__.py | 11 - {src/tinkoff => tests}/__init__.py | 0 .../migrations => tests/apps}/__init__.py | 0 {src/users => tests/apps/a12n}/__init__.py | 0 tests/apps/a12n/api/conftest.py | 6 + ...tests_obtain_jwt_via_passwordless_token.py | 0 .../a12n}/api/tests_obtain_jwt_via_user_id.py | 2 +- .../apps/a12n}/api/tests_obtain_token.py | 4 +- .../apps/a12n}/api/tests_password_change.py | 0 .../a12n}/api/tests_password_reset_confirm.py | 0 .../apps/a12n}/api/tests_refresh_token.py | 2 +- .../a12n}/api/tests_request_password_reset.py | 0 .../api/tests_request_passwordless_token.py | 4 +- .../tests_passwordless_token_absolute_url.py | 0 .../apps/amocrm}/__init__.py | 0 .../tests => tests/apps/amocrm}/conftest.py | 6 +- .../apps/amocrm}/dto/conftest.py | 18 +- .../apps/amocrm}/dto/tests_amo_groups.py | 4 +- .../apps/amocrm}/dto/tests_amo_pipelines.py | 2 +- .../apps/amocrm}/dto/tests_catalogs.py | 2 +- .../apps/amocrm}/dto/tests_customer.py | 12 +- .../apps/amocrm}/dto/tests_lead.py | 8 +- .../apps/amocrm}/dto/tests_product.py | 2 +- .../apps/amocrm}/dto/tests_transaction.py | 2 +- .../apps/amocrm/http}/__init__.py | 0 .../apps/amocrm}/http/tests_http.py | 8 +- .../apps/amocrm/ids}/__init__.py | 0 .../apps/amocrm}/ids/tests_b2c_pipeline_id.py | 12 +- .../apps/amocrm}/ids/tests_catalog_id.py | 6 +- .../amocrm}/ids/tests_contact_fields_ids.py | 6 +- .../amocrm}/ids/tests_product_fields_ids.py | 8 +- tests/apps/amocrm/services/__init__.py | 0 tests/apps/amocrm/services/order/__init__.py | 0 .../apps/amocrm}/services/order/conftest.py | 0 .../services/order/tests_order_pusher.py | 22 +- .../services/order/tests_order_returner.py | 8 +- .../amocrm}/services/tests_course_pusher.py | 8 +- .../amocrm}/services/tests_group_pusher.py | 6 +- .../amocrm}/services/tests_user_pusher.py | 8 +- .../apps/amocrm}/tests_access_token_getter.py | 2 +- .../apps/banking}/atol/conftest.py | 4 +- .../apps/banking}/atol/test_atol_auth.py | 6 +- .../apps/banking}/atol/test_atol_data.py | 0 .../banking}/atol/test_atol_notifications.py | 2 +- .../apps/banking}/tests_bank_selector.py | 10 +- .../apps/banking}/tests_price_calculator.py | 2 +- .../apps/chains}/chain_sender/conftest.py | 4 +- .../test_chain_sender_integrational.py | 8 +- .../chains}/chain_sender/test_chain_tasks.py | 2 +- .../test_sending_next_messages.py | 0 .../test_sending_root_messages.py | 0 .../tests => tests/apps/chains}/conftest.py | 0 .../apps/chains}/message_sender/conftest.py | 4 +- .../message_sender/test_sending_message.py | 2 +- .../apps/chains}/test_message_time_to_send.py | 0 .../unit/test_chain_queryset_active.py | 2 +- .../unit/test_chain_queryset_editable.py | 2 +- .../chains}/unit/test_progress_get_last.py | 2 +- .../apps/diplomas}/api/conftest.py | 2 +- .../diplomas}/api/tests_diploma_create.py | 4 +- .../diplomas}/api/tests_diploma_deletion.py | 0 .../apps/diplomas}/api/tests_diploma_list.py | 0 .../diplomas}/api/tests_diploma_retrieve.py | 2 +- .../api/tests_diploma_update_is_disabled.py | 0 .../tests => tests/apps/diplomas}/conftest.py | 6 +- .../tests_diploma_generator_functional.py | 4 +- .../tests_diploma_generator_retry.py | 2 +- .../tests_diploma_generator_unit.py | 4 +- .../test_diploma_filter_with_template.py | 4 +- .../tests_diploma_get_absolute_url.py | 0 .../diplomas}/tests_diploma_regenerator.py | 16 +- .../tests_answer_get_purchased_course.py | 0 .../homework}/answers/tests_answer_str.py | 0 ...tests_answers_allowed_for_user_queryset.py | 2 +- .../tests_answers_get_absolute_urls.py | 0 .../apps/homework}/api/conftest.py | 0 .../apps/homework}/api/tests_answer_create.py | 2 +- .../homework}/api/tests_answer_destroy.py | 2 +- .../api/tests_answer_image_upload.py | 2 +- .../apps/homework}/api/tests_answer_list.py | 0 .../api/tests_answer_retrieval_access_logs.py | 2 +- .../homework}/api/tests_answer_retrieve.py | 0 .../apps/homework}/api/tests_answer_update.py | 2 +- .../apps/homework}/api/tests_comments_list.py | 0 .../api/tests_comments_list_descendants.py | 0 .../api/tests_markdown_sanitization.py | 0 .../homework}/api/tests_question_retrieve.py | 0 .../homework}/api/tests_reaction_create.py | 2 +- .../homework}/api/tests_reaction_destroy.py | 2 +- .../tests => tests/apps/homework}/conftest.py | 0 .../apps/homework}/cross_check/conftest.py | 4 +- .../tests_crosscheck_dispatcher.py | 2 +- .../tests_crosscheck_is_checked.py | 0 ...tests_dispatch_answers_of_the_same_user.py | 2 +- .../cross_check/tests_get_answer_to_check.py | 2 +- .../cross_check/tests_get_crosscheck_count.py | 0 .../tests_question_crosscheck_dispatcher.py | 4 +- .../tests_question_crosscheck_queryset.py | 0 .../homework}/new_answer_notifier/conftest.py | 2 +- ...ts_answer_notifier_get_template_context.py | 0 .../tests_get_users_to_notify.py | 0 .../tests_new_answer_email.py | 0 .../tests_new_answer_notifier_integration.py | 2 +- .../questions/tests_question_absolute_url.py | 0 .../reactions/test_reaction_creator.py | 6 +- .../homework}/tests_crosscheck_integration.py | 4 +- .../tests => tests/apps/magnets}/conftest.py | 2 +- .../magnets}/email_lead_magnet/conftest.py | 0 .../tests_emaiL_lead_magnet_creating_api.py | 2 +- .../tests_email_lead_magnet_execution.py | 2 +- .../magnets}/tests_lead_magnet_creator.py | 8 +- .../magnets}/tests_lead_magnet_lead_count.py | 2 +- .../apps/mailing}/configuration/conftest.py | 0 .../configuration/test_get_configuration.py | 4 +- .../apps/mailing}/owl/conftest.py | 2 +- .../apps/mailing}/owl/tests_owl_antispam.py | 4 +- .../mailing}/owl/tests_owl_configuration.py | 4 +- .../apps/mailing}/owl/tests_owl_functional.py | 0 .../apps/mailing}/owl/tests_owl_unit.py | 2 +- .../apps/mailing}/owl/tests_send_mail_task.py | 6 +- .../apps/notion}/api/conftest.py | 6 +- .../apps/notion}/api/test_notion_cache_api.py | 6 +- .../notion}/api/test_notion_material_api.py | 0 .../test_notion_material_api_permissions.py | 0 .../apps/notion}/block_list/conftest.py | 2 +- .../test_get_underlying_block_ids.py | 2 +- .../tests => tests/apps/notion}/conftest.py | 12 +- .../apps/notion}/test_celery_tasks.py | 8 +- .../apps/notion}/test_fetch_blocks.py | 0 .../apps/notion}/test_fetch_page.py | 4 +- .../notion}/test_fetch_page_recursively.py | 6 +- .../apps/notion}/test_id_to_uuid.py | 2 +- .../notion}/test_material_get_absolute_url.py | 0 .../apps/notion}/test_notion_block.py | 2 +- .../apps/notion}/test_notion_cache.py | 22 +- .../apps/notion}/test_notion_rewrite_links.py | 4 +- .../apps/notion}/test_page_url_to_id.py | 2 +- .../orders}/configurable_bank/conftest.py | 24 +- .../tests_configurable_bank.py | 2 +- .../tests_zero_price_bank.py | 0 .../tests => tests/apps/orders}/conftest.py | 0 tests/apps/orders/human_readable/__init__.py | 0 .../apps/orders}/human_readable/conftest.py | 0 .../human_readable/test_get_customer.py | 2 +- .../test_get_payment_method_name.py | 6 +- .../conftest.py | 0 .../tests_order_item.py | 0 .../tests_order_item_foreignkey.py | 0 .../tests_order_set_item.py | 2 +- .../models/test_order_item_constraints.py | 4 +- .../apps/orders}/models/tests_order_refund.py | 2 +- .../orders}/order_confirmation/conftest.py | 2 +- .../tests_order_confirmation_api.py | 0 .../apps/orders}/order_creator/conftest.py | 2 +- .../order_creator/tests_order_creator.py | 2 +- ...ests_order_creator_confirmation_message.py | 2 +- .../tests_order_creator_promocodes.py | 2 +- .../tests_order_creator_update_chain.py | 10 +- .../orders}/order_email_changer/conftest.py | 8 +- .../tests_order_email_changer.py | 0 .../apps/orders}/order_queryset/conftest.py | 0 .../test_order_paid_queryset.py | 2 +- ..._order_shipped_without_payment_queryset.py | 2 +- .../apps/orders}/order_shipping/conftest.py | 10 +- .../order_shipping/tests_order_set_paid.py | 2 +- .../tests_sending_happiness_messages.py | 10 +- .../tests_shipping_without_payment.py | 0 ...ng_order_as_paid_on_dolyame_transaction.py | 2 +- ...rder_as_paid_on_stripe_bank_transaction.py | 3 +- ...der_as_paid_on_tinkoff_bank_transaction.py | 2 +- ...r_as_paid_on_tinkoff_credit_transaction.py | 2 +- .../apps/orders}/promocode/conftest.py | 0 .../promocode/tests_price_with_promocode.py | 2 +- .../promocode/tests_promocode_apply.py | 0 .../tests_promocode_compatible_with.py | 0 .../tests_promocode_get_or_nothing.py | 2 +- .../promocode/tests_promocode_order_count.py | 2 +- .../orders}/services/tests_order_refunder.py | 20 +- .../orders}/services/tests_order_unshipper.py | 8 +- ...purchasing_order_with_non_trimmed_email.py | 2 +- .../orders}/tests_order_diploma_generator.py | 12 +- .../bundles/tests_bundle_deprecated.py | 0 .../tests => tests/apps/products}/conftest.py | 2 +- .../apps/products}/course_api/conftest.py | 2 +- .../course_api/tests_purchasing_course.py | 12 +- .../tests_purchasing_course_with_promocode.py | 2 +- .../tests_purchasing_zero_priced_course.py | 2 +- .../tests_course_get_purchased_users.py | 0 .../courses/tests_course_get_template_id.py | 0 ...ourse_send_email_to_all_purchased_users.py | 0 .../products}/courses/tests_course_str.py | 0 .../records/tests_record_deprecated.py | 0 .../products}/shippable/tests_get_price.py | 0 .../apps/stripebank}/.fixtures/webhook.json | 0 .../apps/stripebank}/conftest.py | 6 +- .../apps/stripebank}/test_stripe_get_items.py | 0 .../apps/stripebank}/test_stripe_webhook.py | 2 +- .../apps/studying}/api/test_home_page_slug.py | 0 .../api/test_purchased_courses_view.py | 0 .../tests => tests/apps/studying}/conftest.py | 0 .../studying}/course_shipment/conftest.py | 2 +- .../tests_course_shipment_study_model.py | 2 +- .../tests_course_shipment_welcome_letter.py | 0 .../tests_course_template_context.py | 0 .../studying}/shipping_factory/conftest.py | 0 .../shipping_factory/tests_shippable_mixin.py | 2 +- .../tests_shipping_factory_get.py | 4 +- .../tests_shipping_factory_ship.py | 4 +- .../tests_shipping_factory_unship.py | 4 +- .../apps/tinkoff}/.fixtures/testing.pem | 0 .../apps/tinkoff}/bank_client/conftest.py | 2 +- ...ests_tinkoff_bank_success_and_fail_urls.py | 2 +- .../tests_tinkoff_get_initial_payment_url.py | 2 +- .../bank_client/tests_tinkoff_receipt.py | 0 .../bank_client/tests_tinkoff_refund.py | 2 +- .../tests_tinkoff_request_signing.py | 0 .../tests => tests/apps/tinkoff}/conftest.py | 0 .../apps/tinkoff}/credit_client/conftest.py | 2 +- .../tests_tinkoff_credit_creation.py | 2 +- .../tests_tinkoff_credit_demo_mode.py | 0 .../tinkoff}/credit_notifications/conftest.py | 2 +- .../tests_tinkoff_credit_notification.py | 2 +- ...tinkoff_credit_notification_permissions.py | 4 +- .../apps/tinkoff}/dolyame_client/conftest.py | 4 +- .../test_dolyame_common_methods.py | 0 .../dolyame_client/test_dolyame_creation.py | 0 .../dolyame_client/test_dolyame_refund.py | 2 +- .../dolyame_notifications/conftest.py | 4 +- .../test_creating_dolyame_notifications.py | 2 +- .../payment_notifications/conftest.py | 2 +- .../tests_tinkoff_payment_notification_api.py | 6 +- .../tests_tinkoff_token_validator.py | 6 +- .../apps/users}/api/tests_user_self_view.py | 8 +- .../apps/users}/tags/conftest.py | 0 .../apps/users}/tags/test_any_purchase_tag.py | 2 +- .../apps/users}/tags/test_b2b_tag.py | 3 +- .../users}/tags/test_rebuild_tags_task.py | 6 +- .../tags/test_started_and_purchased_tags.py | 2 +- .../apps/users}/test_freezegun_not_broken.py | 2 +- .../users}/test_user_diploma_languages.py | 0 .../apps/users}/tests_name_parsing.py | 2 +- .../users}/tests_user_printable_gender.py | 2 +- .../apps/users}/tests_user_printable_name.py | 0 .../apps/users}/tests_user_str.py | 0 .../apps/users}/user_creator/conftest.py | 0 .../tests_user_creator_for_existing_users.py | 2 +- .../tests_user_creator_name_and_email.py | 2 +- .../tests_user_creator_subscription.py | 4 +- tests/conftest.py | 23 + .../core}/dashamail/conftest.py | 4 +- .../dashamail/test_subscription_updater.py | 12 +- .../tests_dashamail_get_subscriber.py | 0 .../core}/dashamail/tests_dashamail_http.py | 2 +- .../dashamail/tests_dashamail_subscribe.py | 2 +- .../tests_dashamail_subscribe_task.py | 6 +- .../tests_dashamail_update_subscriber.py | 2 +- .../core}/dashamail/tests_dashamail_url.py | 0 .../core}/helpers/tests_lower_first.py | 2 +- .../pricing/tests_format_old_price_helper.py | 2 +- .../pricing/tests_format_price_helper.py | 2 +- .../core}/tests_drf_spectacular_view.py | 0 .../core}/tests_home_page_view.py | 0 .../tests => tests/core}/tests_s3_client.py | 2 +- tests/factories/__init__.py | 0 tests/factories/apps/__init__.py | 0 .../factories/apps/diplomas.py | 8 +- .../factories/apps/orders.py | 8 +- .../factories/apps/products.py | 8 +- src/app/factory.py => tests/factories/core.py | 4 +- tests/fixtures/__init__.py | 0 tests/fixtures/apps/__init__.py | 0 .../fixtures/apps/products.py | 2 +- .../fixtures/apps/users.py | 0 tests/fixtures/core/__init__.py | 21 + .../fixtures => tests/fixtures/core}/api.py | 4 +- .../core}/dasha_subscription_updater.py | 2 +- .../fixtures/core}/factory.py | 4 +- tests/fixtures/core/send_mail.py | 6 + .../fixtures/core}/timezone.py | 0 836 files changed, 6047 insertions(+), 2837 deletions(-) create mode 100644 .github/actions/build/action.yml delete mode 100644 .python-version delete mode 100644 dev-requirements.txt rename src/mypy.ini => mypy.ini (93%) create mode 100644 poetry.lock delete mode 100644 requirements.txt delete mode 100644 src/a12n/tests/conftest.py delete mode 100644 src/amocrm/client/__init__.py delete mode 100644 src/amocrm/dto/__init__.py delete mode 100644 src/amocrm/models/__init__.py delete mode 100644 src/app/admin/__init__.py delete mode 100644 src/app/conf/boilerplate.py delete mode 100644 src/app/conf/environ.py delete mode 100644 src/app/conf/tags.py delete mode 100644 src/app/fixtures/__init__.py delete mode 100644 src/app/fixtures/send_mail.py delete mode 100644 src/app/integrations/dashamail/__init__.py delete mode 100644 src/app/tasks/__init__.py delete mode 100644 src/app/urls/v2.py rename src/{a12n => apps}/__init__.py (100%) rename src/{a12n/migrations => apps/a12n}/__init__.py (100%) rename src/{ => apps}/a12n/api/forms.py (96%) rename src/{ => apps}/a12n/api/serializers.py (78%) rename src/{ => apps}/a12n/api/throttling.py (79%) rename src/{ => apps}/a12n/api/views.py (85%) rename src/{ => apps}/a12n/apps.py (56%) rename src/{ => apps}/a12n/jwt.py (91%) rename src/{ => apps}/a12n/migrations/0001_initial.py (90%) rename src/{ => apps}/a12n/migrations/0002_PasswordlessTokensUsedDate.py (100%) rename src/{amocrm => apps/a12n/migrations}/__init__.py (100%) rename src/{ => apps}/a12n/models.py (94%) rename src/{ => apps}/a12n/signals/handlers.py (100%) rename src/{ => apps}/a12n/urls.py (69%) rename src/{ => apps}/a12n/utils.py (93%) rename src/{amocrm/migrations => apps/amocrm}/__init__.py (100%) rename src/{ => apps}/amocrm/apps.py (83%) create mode 100644 src/apps/amocrm/client/__init__.py rename src/{ => apps}/amocrm/client/client.py (89%) rename src/{ => apps}/amocrm/client/http.py (94%) create mode 100644 src/apps/amocrm/dto/__init__.py rename src/{ => apps}/amocrm/dto/catalogs.py (95%) rename src/{ => apps}/amocrm/dto/customer.py (96%) rename src/{ => apps}/amocrm/dto/groups.py (87%) rename src/{ => apps}/amocrm/dto/lead.py (89%) rename src/{ => apps}/amocrm/dto/pipelines.py (96%) rename src/{ => apps}/amocrm/dto/product.py (92%) rename src/{ => apps}/amocrm/dto/transaction.py (92%) rename src/{ => apps}/amocrm/exceptions.py (89%) rename src/{ => apps}/amocrm/ids.py (92%) rename src/{ => apps}/amocrm/migrations/0001_AddAmoCRMUser.py (100%) rename src/{ => apps}/amocrm/migrations/0002_AddAmoCRMGroup_and_Course.py (100%) rename src/{ => apps}/amocrm/migrations/0003_Add_AmoCRMUserContact.py (100%) rename src/{ => apps}/amocrm/migrations/0004_Add_AmoCRM_leads_and_transactions.py (100%) rename src/{ => apps}/amocrm/migrations/0005_Add_lead_and_transaction_to_Order.py (100%) rename src/{ => apps}/amocrm/migrations/0006_Drop_o2o_properties_from_amocrm_lead_and_transaction.py (100%) rename src/{ => apps}/amocrm/migrations/0007_Move_contact_id_to_AmoCRMUser.py (100%) rename src/{ => apps}/amocrm/migrations/0008_Delete_separate_AmoCRMUserContact.py (100%) rename src/{amocrm/services => apps/amocrm/migrations}/__init__.py (100%) create mode 100644 src/apps/amocrm/models/__init__.py rename src/{ => apps}/amocrm/models/amocrm_course.py (89%) rename src/{ => apps}/amocrm/models/amocrm_order_lead.py (84%) rename src/{ => apps}/amocrm/models/amocrm_order_transaction.py (85%) rename src/{ => apps}/amocrm/models/amocrm_product_group.py (90%) rename src/{ => apps}/amocrm/models/amocrm_user.py (90%) rename src/{amocrm/tests => apps/amocrm/services}/__init__.py (100%) rename src/{ => apps}/amocrm/services/access_token_getter.py (96%) rename src/{ => apps}/amocrm/services/course_pusher.py (80%) rename src/{ => apps}/amocrm/services/group_pusher.py (84%) rename src/{ => apps}/amocrm/services/orders/order_pusher.py (90%) rename src/{ => apps}/amocrm/services/orders/order_returner.py (75%) rename src/{ => apps}/amocrm/services/user_pusher.py (80%) rename src/{ => apps}/amocrm/tasks.py (77%) rename src/{amocrm/tests/http => apps/banking}/__init__.py (100%) rename src/{ => apps}/banking/api/views.py (91%) rename src/{ => apps}/banking/apps.py (72%) create mode 100644 src/apps/banking/atol/__init__.py rename src/{ => apps}/banking/atol/auth.py (93%) rename src/{ => apps}/banking/atol/client.py (94%) rename src/{ => apps}/banking/atol/exceptions.py (100%) rename src/{ => apps}/banking/base.py (93%) rename src/{ => apps}/banking/management/commands/test_atol.py (70%) rename src/{ => apps}/banking/migrations/0001_initial.py (100%) rename src/{amocrm/tests/ids => apps/banking/migrations}/__init__.py (100%) rename src/{ => apps}/banking/models.py (88%) rename src/{ => apps}/banking/price_calculator.py (91%) rename src/{ => apps}/banking/selector.py (70%) rename src/{ => apps}/banking/urls.py (60%) rename src/{ => apps}/banking/zero_price_bank.py (94%) rename src/{amocrm/tests/services => apps/chains}/__init__.py (100%) create mode 100644 src/apps/chains/admin/__init__.py rename src/{ => apps}/chains/admin/chain.py (82%) rename src/{ => apps}/chains/admin/forms.py (94%) rename src/{ => apps}/chains/admin/message.py (84%) rename src/{ => apps}/chains/apps.py (83%) rename src/{ => apps}/chains/migrations/0001_Initial.py (100%) rename src/{ => apps}/chains/migrations/0002_ChainsAdminImprovements.py (100%) rename src/{ => apps}/chains/migrations/0003_LimitParentChoices.py (100%) rename src/{ => apps}/chains/migrations/0004_UniqueChainName.py (100%) rename src/{ => apps}/chains/migrations/0005_MessageAdminSpeedup.py (100%) rename src/{ => apps}/chains/migrations/0006_i18n.py (100%) rename src/{ => apps}/chains/migrations/0007_StudyConstraints.py (100%) rename src/{ => apps}/chains/migrations/0008_ChainProgressStatus.py (100%) rename src/{ => apps}/chains/migrations/0009_CreateChainProgressForAlreadyPurchasedUsers.py (100%) rename src/{ => apps}/chains/migrations/0010_ChainsAdminLabelChange.py (100%) rename src/{ => apps}/chains/migrations/0011_chain_archived_field.py (100%) rename src/{amocrm/tests/services/order => apps/chains/migrations}/__init__.py (100%) create mode 100644 src/apps/chains/models/__init__.py rename src/{ => apps}/chains/models/chain.py (94%) rename src/{ => apps}/chains/models/message.py (94%) rename src/{ => apps}/chains/models/progress.py (86%) create mode 100644 src/apps/chains/services/__init__.py rename src/{ => apps}/chains/services/chain_sender.py (82%) rename src/{ => apps}/chains/services/message_sender.py (82%) rename src/{ => apps}/chains/static/admin/js/clickable_message_intervals.js (100%) rename src/{ => apps}/chains/static/admin/js/limit_message_choices.js (100%) rename src/{ => apps}/chains/tasks.py (75%) rename src/{app => apps/diplomas}/__init__.py (100%) rename src/{ => apps}/diplomas/admin.py (91%) rename src/{ => apps}/diplomas/api/permissions.py (100%) rename src/{ => apps}/diplomas/api/serializers.py (91%) rename src/{ => apps}/diplomas/api/viewsets.py (83%) rename src/{ => apps}/diplomas/apps.py (82%) rename src/{ => apps}/diplomas/migrations/0001_initial.py (100%) rename src/{ => apps}/diplomas/migrations/0002_RandomDiplomaFileNames.py (76%) rename src/{ => apps}/diplomas/migrations/0003_ShortDiplomaSlug.py (100%) rename src/{ => apps}/diplomas/migrations/0004_DiplomaTemplates.py (100%) rename src/{ => apps}/diplomas/migrations/0005_DroppedHomeworkFlagFromDiplomaTemplate.py (100%) rename src/{ => apps}/diplomas/migrations/0006_DiplomaTemplateHomework.py (100%) rename src/{app => apps/diplomas}/migrations/__init__.py (100%) rename src/{ => apps}/diplomas/models.py (94%) create mode 100644 src/apps/diplomas/services/__init__.py rename src/{ => apps}/diplomas/services/diploma_generator.py (88%) rename src/{ => apps}/diplomas/services/diploma_regenerator.py (87%) rename src/{ => apps}/diplomas/tasks.py (68%) rename src/{ => apps}/diplomas/urls.py (80%) rename src/{banking => apps/homework}/__init__.py (100%) create mode 100644 src/apps/homework/admin/__init__.py rename src/{ => apps}/homework/admin/answer/admin.py (93%) rename src/{ => apps}/homework/admin/answer/filters.py (91%) rename src/{ => apps}/homework/admin/question/admin.py (86%) rename src/{ => apps}/homework/api/filtersets.py (86%) rename src/{ => apps}/homework/api/permissions.py (98%) rename src/{ => apps}/homework/api/serializers.py (91%) rename src/{ => apps}/homework/api/views.py (75%) rename src/{ => apps}/homework/api/viewsets.py (80%) rename src/{ => apps}/homework/apps.py (55%) rename src/{ => apps}/homework/migrations/0001_initial.py (100%) rename src/{ => apps}/homework/migrations/0002_MultipleCourses.py (100%) rename src/{ => apps}/homework/migrations/0003_AnswerTree.py (100%) rename src/{ => apps}/homework/migrations/0004_DefaultAnswerOrdering.py (100%) rename src/{ => apps}/homework/migrations/0005_GodAnswerUsers.py (100%) rename src/{ => apps}/homework/migrations/0006_AnswerAccessLogEntry.py (100%) rename src/{ => apps}/homework/migrations/0006_SeeAllQuestionsPermission.py (100%) rename src/{ => apps}/homework/migrations/0007_merge_20210420_0027.py (100%) rename src/{ => apps}/homework/migrations/0008_AnswersCrossCheck.py (100%) rename src/{ => apps}/homework/migrations/0009_ExcludeAnswersFromCrossCheck.py (100%) rename src/{ => apps}/homework/migrations/0010_ForogttenAnswerModified.py (100%) rename src/{ => apps}/homework/migrations/0011_AnswerImage.py (89%) rename src/{ => apps}/homework/migrations/0012_Reaction.py (100%) rename src/{ => apps}/homework/migrations/0013_DropAnswerRelationsForMypyUpgrade.py (100%) rename src/{banking => apps/homework}/migrations/__init__.py (100%) create mode 100644 src/apps/homework/models/__init__.py rename src/{ => apps}/homework/models/answer.py (94%) rename src/{ => apps}/homework/models/answer_access_log_entry.py (87%) rename src/{ => apps}/homework/models/answer_cross_check.py (89%) rename src/{ => apps}/homework/models/answer_image.py (66%) rename src/{ => apps}/homework/models/question.py (86%) rename src/{ => apps}/homework/models/reaction.py (93%) create mode 100644 src/apps/homework/services/__init__.py rename src/{ => apps}/homework/services/answer_crosscheck_dispatcher.py (93%) rename src/{ => apps}/homework/services/new_answer_notifier.py (90%) rename src/{ => apps}/homework/services/question_crosscheck_dispatcher.py (85%) rename src/{ => apps}/homework/services/reaction_creator.py (88%) rename src/{ => apps}/homework/signals/handlers.py (88%) rename src/{ => apps}/homework/tasks.py (70%) rename src/{ => apps}/homework/urls.py (80%) rename src/{chains => apps/magnets}/__init__.py (100%) rename src/{ => apps}/magnets/admin.py (88%) rename src/{ => apps}/magnets/api/serializers.py (79%) rename src/{ => apps}/magnets/api/validators.py (94%) rename src/{ => apps}/magnets/api/views.py (80%) rename src/{ => apps}/magnets/apps.py (85%) rename src/{ => apps}/magnets/creator.py (77%) rename src/{ => apps}/magnets/migrations/0001_initial.py (100%) rename src/{ => apps}/magnets/migrations/0002_CampaignLog.py (100%) rename src/{ => apps}/magnets/migrations/0003_CampaignSuccessMessage.py (100%) rename src/{chains => apps/magnets}/migrations/__init__.py (100%) rename src/{ => apps}/magnets/models.py (90%) rename src/{ => apps}/magnets/urls.py (65%) rename src/{diplomas => apps/mailing}/__init__.py (100%) create mode 100644 src/apps/mailing/admin/__init__.py rename src/{ => apps}/mailing/admin/email_configuration.py (68%) create mode 100644 src/apps/mailing/admin/personal_email_domain.py rename src/{ => apps}/mailing/apps.py (82%) rename src/{ => apps}/mailing/backends.py (100%) rename src/{ => apps}/mailing/configuration.py (89%) rename src/{ => apps}/mailing/helpers.py (100%) rename src/{ => apps}/mailing/management/commands/send_test_email.py (95%) rename src/{ => apps}/mailing/migrations/0001_EmailLogEntryMovedToDedicatedApp.py (91%) rename src/{ => apps}/mailing/migrations/0002_EmailConfiguration.py (100%) rename src/{ => apps}/mailing/migrations/0003_CustomReplyTo.py (100%) rename src/{ => apps}/mailing/migrations/0004_PersonalEmailDomain.py (100%) rename src/{ => apps}/mailing/migrations/0005_MigrateIndexDefinitions.py (100%) rename src/{diplomas => apps/mailing}/migrations/__init__.py (100%) create mode 100644 src/apps/mailing/models/__init__.py rename src/{ => apps}/mailing/models/configuration.py (94%) rename src/{ => apps}/mailing/models/log_entry.py (86%) rename src/{ => apps}/mailing/models/personal_email_domain.py (80%) rename src/{ => apps}/mailing/owl.py (92%) rename src/{ => apps}/mailing/tasks.py (88%) rename src/{homework => apps/notion}/__init__.py (100%) rename src/{ => apps}/notion/admin.py (78%) rename src/{ => apps}/notion/api/serializers.py (84%) rename src/{ => apps}/notion/api/throttling.py (79%) rename src/{ => apps}/notion/api/views.py (80%) rename src/{ => apps}/notion/apps.py (83%) rename src/{ => apps}/notion/block.py (95%) rename src/{ => apps}/notion/cache.py (92%) rename src/{ => apps}/notion/client.py (93%) rename src/{ => apps}/notion/exceptions.py (100%) rename src/{ => apps}/notion/helpers.py (87%) rename src/{ => apps}/notion/management/commands/update_notion_cache.py (93%) rename src/{ => apps}/notion/migrations/0001_initial.py (93%) rename src/{ => apps}/notion/migrations/0002_NotionaMaterialTitle.py (100%) rename src/{ => apps}/notion/migrations/0003_HomePageMaterial.py (100%) rename src/{ => apps}/notion/migrations/0004_NotionMaterialSlug.py (100%) rename src/{ => apps}/notion/migrations/0005_MaterailFiles.py (100%) rename src/{ => apps}/notion/migrations/0006_NotionCacheEntry.py (100%) rename src/{homework => apps/notion}/migrations/__init__.py (100%) rename src/{ => apps}/notion/models.py (93%) rename src/{ => apps}/notion/page.py (85%) rename src/{ => apps}/notion/rewrite.py (88%) rename src/{ => apps}/notion/tasks.py (74%) rename src/{ => apps}/notion/types.py (100%) rename src/{ => apps}/notion/urls.py (78%) rename src/{magnets => apps/orders}/__init__.py (100%) create mode 100644 src/apps/orders/admin/__init__.py rename src/{ => apps}/orders/admin/orders/actions.py (94%) rename src/{ => apps}/orders/admin/orders/admin.py (88%) rename src/{ => apps}/orders/admin/orders/filters.py (94%) rename src/{ => apps}/orders/admin/orders/forms.py (94%) rename src/{ => apps}/orders/admin/orders/throttling.py (80%) rename src/{ => apps}/orders/admin/promocodes/actions.py (92%) rename src/{ => apps}/orders/admin/promocodes/admin.py (88%) rename src/{ => apps}/orders/api/serializers.py (100%) rename src/{ => apps}/orders/api/throttling.py (83%) rename src/{ => apps}/orders/api/views.py (89%) rename src/{ => apps}/orders/apps.py (55%) rename src/{ => apps}/orders/exceptions.py (100%) rename src/{ => apps}/orders/fields.py (92%) rename src/{ => apps}/orders/human_readable.py (93%) rename src/{ => apps}/orders/migrations/0001_initial.py (79%) rename src/{ => apps}/orders/migrations/0002_L18N.py (100%) rename src/{ => apps}/orders/migrations/0003_OrderBundles.py (66%) rename src/{ => apps}/orders/migrations/0004_PromoCodes.py (100%) rename src/{ => apps}/orders/migrations/0005_PromoCodesActiveByDefault.py (100%) rename src/{ => apps}/orders/migrations/0006_PromoCodeComments.py (100%) rename src/{ => apps}/orders/migrations/0007_OrderPromoCodes.py (100%) rename src/{ => apps}/orders/migrations/0008_PromocodesI18n.py (100%) rename src/{ => apps}/orders/migrations/0009_Gifts.py (100%) rename src/{ => apps}/orders/migrations/0010_OrderI18n.py (76%) rename src/{ => apps}/orders/migrations/0011_NotificationToGiverIsSent.py (100%) rename src/{ => apps}/orders/migrations/0012_DesiredBankString.py (100%) rename src/{ => apps}/orders/migrations/0013_PerProductPromoCodes.py (100%) rename src/{ => apps}/orders/migrations/0014_NonAttachedPromocodes.py (100%) rename src/{ => apps}/orders/migrations/0015_PromoCodeValue.py (100%) rename src/{ => apps}/orders/migrations/0016_UnpaidDate.py (100%) rename src/{ => apps}/orders/migrations/0017_OrderPermissions.py (100%) rename src/{ => apps}/orders/migrations/0018_StudentProxyModel.py (100%) rename src/{ => apps}/orders/migrations/0019_OrderAuthor.py (100%) rename src/{ => apps}/orders/migrations/0020_OrderAuthorMigrationFix.py (100%) rename src/{ => apps}/orders/migrations/0021_OrderConstraintForProductItemsCountCheck.py (100%) rename src/{ => apps}/orders/migrations/0022_PurchaseTimeUERate.py (100%) rename src/{ => apps}/orders/migrations/0023_AcquringPercent.py (100%) rename src/{ => apps}/orders/migrations/0024_OrderSlugs.py (100%) rename src/{ => apps}/orders/migrations/0025_BankFieldRename.py (100%) rename src/{ => apps}/orders/migrations/0026_PromocodeExpiration.py (100%) rename src/{ => apps}/orders/migrations/0027_PromocodeDestinationField.py (100%) rename src/{ => apps}/orders/migrations/0028_PromocodeExpiresFieldTranslation.py (100%) rename src/{ => apps}/orders/migrations/0029_DropGiftFields.py (100%) rename src/{ => apps}/orders/migrations/0030_Add_lead_and_transaction_to_Order.py (100%) rename src/{ => apps}/orders/migrations/0031_Drop_o2o_properties_from_amocrm_lead_and_transaction.py (100%) rename src/{ => apps}/orders/migrations/0032_order_set_bank_choices.py (100%) rename src/{magnets => apps/orders}/migrations/__init__.py (100%) create mode 100644 src/apps/orders/models/__init__.py rename src/{ => apps}/orders/models/order.py (91%) rename src/{ => apps}/orders/models/promocode.py (96%) create mode 100644 src/apps/orders/services/__init__.py rename src/{ => apps}/orders/services/order_creator.py (86%) rename src/{ => apps}/orders/services/order_diploma_generator.py (78%) rename src/{ => apps}/orders/services/order_email_changer.py (81%) rename src/{ => apps}/orders/services/order_paid_setter.py (86%) rename src/{ => apps}/orders/services/order_refunder.py (84%) rename src/{ => apps}/orders/services/order_shipper.py (90%) rename src/{ => apps}/orders/services/order_unshipper.py (87%) rename src/{ => apps}/orders/services/purchase_creator.py (83%) rename src/{mailing => apps/orders/signals}/__init__.py (100%) rename src/{ => apps}/orders/signals/handlers.py (83%) rename src/{ => apps}/orders/signals/signals.py (100%) rename src/{ => apps}/orders/static/admin/order_list.css (100%) rename src/{ => apps}/orders/tasks.py (52%) rename src/{ => apps}/orders/urls.py (80%) rename src/{mailing/migrations => apps/products}/__init__.py (100%) create mode 100644 src/apps/products/admin/__init__.py rename src/{ => apps}/products/admin/course.py (89%) rename src/{ => apps}/products/admin/courses/actions.py (100%) rename src/{ => apps}/products/admin/group.py (77%) rename src/{ => apps}/products/api/serializers.py (90%) rename src/{ => apps}/products/api/views.py (83%) rename src/{ => apps}/products/apps.py (71%) rename src/{ => apps}/products/migrations/0001_initial.py (100%) rename src/{ => apps}/products/migrations/0002_CourseGenitiveName.py (100%) rename src/{ => apps}/products/migrations/0003_DefaultOrdering.py (100%) rename src/{ => apps}/products/migrations/0004_ReceiptNames.py (100%) rename src/{ => apps}/products/migrations/0005_ClickMeeetingRoomURL.py (100%) rename src/{ => apps}/products/migrations/0006_ShippableFullName.py (100%) rename src/{ => apps}/products/migrations/0007_L18N.py (100%) rename src/{ => apps}/products/migrations/0008_Bundles.py (100%) rename src/{ => apps}/products/migrations/0008_CustomTemplateId.py (100%) rename src/{ => apps}/products/migrations/0009_merge_20191222_1525.py (100%) rename src/{ => apps}/products/migrations/0010_ParentShippableModel.py (100%) rename src/{ => apps}/products/migrations/0011_Price.py (100%) rename src/{ => apps}/products/migrations/0012_ZoomusWebinarId.py (100%) rename src/{ => apps}/products/migrations/0013_TemplateIdRename.py (100%) rename src/{ => apps}/products/migrations/0014_CourseWelcomeLetter.py (100%) rename src/{ => apps}/products/migrations/0015_GiftWelcomeLetterTemplateId.py (100%) rename src/{ => apps}/products/migrations/0016_MailchimpListId.py (100%) rename src/{ => apps}/products/migrations/0017_TinkoffCreditPromoCode.py (100%) rename src/{ => apps}/products/migrations/0018_ProductGroups.py (100%) rename src/{ => apps}/products/migrations/0019_CourseDisplayInLMS.py (100%) rename src/{ => apps}/products/migrations/0020_InternationalNames.py (100%) rename src/{ => apps}/products/migrations/0021_removeMailchimpListId.py (100%) rename src/{ => apps}/products/migrations/0022_DitchClickmeetings.py (100%) rename src/{ => apps}/products/migrations/0023_DiplomaTemplateContext.py (100%) rename src/{ => apps}/products/migrations/0024_DiplomaTemplateContextIsNotRequired.py (100%) rename src/{ => apps}/products/migrations/0025_DisableTriggersFlag.py (100%) rename src/{ => apps}/products/migrations/0026_CourseConfirmationTemplateId.py (100%) rename src/{ => apps}/products/migrations/0027_CourseConfirmationURL.py (100%) rename src/{ => apps}/products/migrations/0028_CourseCoverField.py (77%) rename src/{ => apps}/products/migrations/0029_TagsForUser.py (100%) rename src/{ => apps}/products/migrations/0030_SetUniqieSlugForProducts.py (100%) rename src/{ => apps}/products/migrations/0031_DropGiftFields.py (100%) rename src/{ => apps}/products/migrations/0032_Drop_Zoom_integration.py (100%) rename src/{notion => apps/products/migrations}/__init__.py (100%) rename src/{ => apps}/products/models/__init__.py (50%) rename src/{ => apps}/products/models/base.py (89%) rename src/{ => apps}/products/models/bundle.py (86%) rename src/{ => apps}/products/models/course.py (94%) rename src/{ => apps}/products/models/group.py (80%) rename src/{ => apps}/products/models/record.py (89%) rename src/{ => apps}/products/static/admin/css/course_action_form.css (100%) rename src/{ => apps}/products/static/admin/js/course_action_form.js (100%) rename src/{ => apps}/products/tasks.py (85%) rename src/{ => apps}/products/urls.py (64%) rename src/{notion/migrations => apps/stripebank}/__init__.py (100%) rename src/{ => apps}/stripebank/api/serializers.py (88%) rename src/{ => apps}/stripebank/api/views.py (91%) rename src/{ => apps}/stripebank/apps.py (81%) rename src/{ => apps}/stripebank/bank.py (97%) rename src/{ => apps}/stripebank/migrations/0001_Initial.py (100%) rename src/{ => apps}/stripebank/migrations/0002_OrderUUID.py (100%) rename src/{orders => apps/stripebank/migrations}/__init__.py (100%) rename src/{ => apps}/stripebank/models.py (86%) rename src/{orders/migrations => apps/studying}/__init__.py (100%) rename src/{ => apps}/studying/api/serializers.py (88%) rename src/{ => apps}/studying/api/views.py (68%) rename src/{ => apps}/studying/apps.py (68%) rename src/{ => apps}/studying/migrations/0001_initial.py (100%) rename src/{ => apps}/studying/migrations/0002_StudyIsHomeworkAccepted.py (100%) rename src/{orders/signals => apps/studying/migrations}/__init__.py (100%) rename src/{ => apps}/studying/models.py (90%) create mode 100644 src/apps/studying/shipment/__init__.py rename src/{ => apps}/studying/shipment/base.py (82%) rename src/{ => apps}/studying/shipment/course.py (83%) rename src/{ => apps}/studying/shipment_factory.py (81%) rename src/{ => apps}/studying/urls.py (75%) rename src/{orders/tests/human_readable => apps/tinkoff}/__init__.py (100%) rename src/{ => apps}/tinkoff/api/permissions.py (81%) rename src/{ => apps}/tinkoff/api/serializers.py (94%) rename src/{ => apps}/tinkoff/api/views.py (80%) rename src/{ => apps}/tinkoff/apps.py (72%) rename src/{ => apps}/tinkoff/bank.py (97%) rename src/{ => apps}/tinkoff/credit.py (98%) rename src/{ => apps}/tinkoff/dolyame.py (98%) rename src/{ => apps}/tinkoff/exceptions.py (100%) rename src/{ => apps}/tinkoff/management/commands/refund_dolyame.py (86%) rename src/{ => apps}/tinkoff/migrations/0001_initial.py (100%) rename src/{ => apps}/tinkoff/migrations/0002_EmptyCardID.py (100%) rename src/{ => apps}/tinkoff/migrations/0003_CreditNotifications.py (100%) rename src/{ => apps}/tinkoff/migrations/0004_DolyameNotifications.py (100%) rename src/{ => apps}/tinkoff/migrations/0005_DolyameTypoFix.py (100%) rename src/{ => apps}/tinkoff/migrations/0006_DolyameRefundedStatus.py (100%) rename src/{ => apps}/tinkoff/migrations/0007_TinkoffCreditOrderSlug.py (100%) rename src/{ => apps}/tinkoff/migrations/0008_TinkoffBankOrderSlug.py (100%) rename src/{ => apps}/tinkoff/migrations/0009_DolyameOrderUUID.py (100%) rename src/{orders/tests/services => apps/tinkoff/migrations}/__init__.py (100%) rename src/{ => apps}/tinkoff/models.py (97%) rename src/{ => apps}/tinkoff/tasks.py (70%) rename src/{ => apps}/tinkoff/token_validator.py (88%) rename src/{products => apps/users}/__init__.py (100%) create mode 100644 src/apps/users/admin/__init__.py rename src/{ => apps}/users/admin/student.py (89%) rename src/{ => apps}/users/admin/user.py (75%) rename src/{ => apps}/users/api/serializers.py (94%) rename src/{ => apps}/users/api/views.py (86%) rename src/{ => apps}/users/apps.py (86%) rename src/{products/migrations => apps/users/management}/__init__.py (100%) rename src/{stripebank => apps/users/management/commands}/__init__.py (100%) rename src/{ => apps}/users/management/commands/create_dev_admin_user.py (95%) rename src/{ => apps}/users/management/commands/update_students_tags.py (92%) rename src/{ => apps}/users/migrations/0001_initial.py (100%) rename src/{ => apps}/users/migrations/0002_SubscribedToNewsLetter.py (100%) rename src/{ => apps}/users/migrations/0003_Django31.py (100%) rename src/{ => apps}/users/migrations/0004_NamesInEnglish.py (100%) rename src/{ => apps}/users/migrations/0005_UserUUID.py (100%) rename src/{ => apps}/users/migrations/0006_Gender.py (100%) rename src/{ => apps}/users/migrations/0007_StudentProxyModel.py (100%) rename src/{ => apps}/users/migrations/0008_AddtionalProfileFields.py (100%) rename src/{ => apps}/users/migrations/0009_add_telegram_username.py (100%) rename src/{ => apps}/users/migrations/0010_drop_linkedin_github_constraints.py (100%) rename src/{ => apps}/users/migrations/0011_TagsForUser.py (100%) rename src/{stripebank => apps/users}/migrations/__init__.py (100%) rename src/{ => apps}/users/models.py (97%) create mode 100644 src/apps/users/services/__init__.py rename src/{ => apps}/users/services/user_creator.py (93%) rename src/{ => apps}/users/services/user_updater.py (87%) create mode 100644 src/apps/users/tags/__init__.py rename src/{ => apps}/users/tags/any_purchase_tag.py (88%) rename src/{ => apps}/users/tags/b2b_tag.py (86%) rename src/{ => apps}/users/tags/base.py (91%) rename src/{ => apps}/users/tags/pipeline.py (85%) rename src/{ => apps}/users/tags/purchased_tag.py (87%) rename src/{ => apps}/users/tags/started_tag.py (90%) rename src/{ => apps}/users/tasks.py (76%) rename src/{ => apps}/users/urls.py (67%) delete mode 100644 src/banking/atol/__init__.py delete mode 100644 src/chains/admin/__init__.py delete mode 100644 src/chains/models/__init__.py delete mode 100644 src/chains/services/__init__.py delete mode 100644 src/conftest.py rename src/{app => core}/.env.ci (100%) rename src/{studying => core}/__init__.py (100%) create mode 100644 src/core/admin/__init__.py rename src/{app => core}/admin/filters.py (100%) rename src/{app => core}/admin/mixin.py (98%) rename src/{app => core}/admin/model_admin.py (88%) rename src/{app => core}/admin/widgets.py (100%) rename src/{app => core}/api/filters.py (100%) rename src/{app => core}/api/mixins.py (100%) rename src/{app => core}/celery.py (81%) rename src/{app => core}/conf/api.py (89%) rename src/{app => core}/conf/auth.py (94%) create mode 100644 src/core/conf/boilerplate.py rename src/{app => core}/conf/cache.py (87%) rename src/{app => core}/conf/db.py (92%) rename src/{app => core}/conf/debug_toolbar.py (100%) rename src/{app => core}/conf/email.py (96%) create mode 100644 src/core/conf/environ.py rename src/{app => core}/conf/features.py (88%) rename src/{app => core}/conf/healthchecks.py (100%) rename src/{app => core}/conf/http.py (95%) rename src/{app => core}/conf/i18n.py (100%) rename src/{app => core}/conf/installed_apps.py (58%) rename src/{app => core}/conf/integrations/amocrm.py (92%) rename src/{app => core}/conf/integrations/atol.py (90%) rename src/{app => core}/conf/integrations/banking/banking.py (78%) rename src/{app => core}/conf/integrations/banking/stripe.py (80%) rename src/{app => core}/conf/integrations/banking/tinkoff.py (94%) rename src/{app => core}/conf/integrations/clickmeetings.py (69%) rename src/{app => core}/conf/integrations/diploma_generator.py (80%) rename src/{app => core}/conf/integrations/notion.py (87%) rename src/{app => core}/conf/integrations/tg.py (80%) rename src/{app => core}/conf/markdown.py (100%) rename src/{app => core}/conf/media.py (75%) rename src/{app => core}/conf/middleware.py (70%) rename src/{app => core}/conf/sentry.py (86%) rename src/{app => core}/conf/static.py (60%) rename src/{app => core}/conf/storage.py (96%) create mode 100644 src/core/conf/tags.py rename src/{app => core}/conf/templates.py (100%) rename src/{app => core}/conf/timezone.py (70%) rename src/{app => core}/conf/vat.py (58%) rename src/{app => core}/conf/warnings.py (100%) rename src/{app => core}/current_user.py (94%) rename src/{app => core}/exceptions.py (100%) rename src/{app => core}/files.py (92%) rename src/{app => core}/helpers.py (100%) create mode 100644 src/core/integrations/dashamail/__init__.py rename src/{app => core}/integrations/dashamail/client.py (91%) rename src/{app => core}/integrations/dashamail/exceptions.py (100%) rename src/{app => core}/integrations/dashamail/http.py (95%) rename src/{app => core}/integrations/dashamail/subscription_updater.py (88%) rename src/{app => core}/integrations/s3.py (100%) rename src/{app => core}/integrations/tg.py (100%) rename src/{app => core}/management/commands/clean_antispam_logs.py (84%) rename src/{app => core}/markdown.py (100%) rename src/{app => core}/middleware/global_current_user.py (72%) rename src/{app => core}/middleware/real_ip.py (100%) rename src/{app => core}/middleware/set_user_from_non_django_authentication.py (97%) rename src/{app => core}/migrations/0001_CourseMailLog.py (100%) rename src/{app => core}/migrations/0002_DropTheOnetimeApp.py (91%) rename src/{app => core}/migrations/0003_RenameCoursesAppPt1.py (86%) rename src/{app => core}/migrations/0004_EmailLogEntryMovedToDedicatedApp.py (87%) rename src/{app => core}/migrations/0005_RemoveTriggersApp.py (88%) rename src/{studying => core}/migrations/__init__.py (100%) rename src/{app => core}/models.py (100%) rename src/{app => core}/pagination.py (100%) rename src/{app => core}/permissions.py (100%) rename src/{app => core}/pricing.py (100%) rename src/{app => core}/renderers.py (100%) rename src/{app => core}/serializers.py (94%) rename src/{app => core}/services.py (100%) rename src/{app => core}/settings.py (97%) rename src/{app => core}/static/admin.css (100%) rename src/{app => core}/static/prettyjson.css (100%) create mode 100644 src/core/tasks/__init__.py rename src/{app => core}/tasks/dashamail.py (70%) rename src/{app => core}/tasks/tg.py (65%) rename src/{app => core}/test/api_client.py (98%) rename src/{app => core}/test/disable_test_command_runner.py (100%) rename src/{app => core}/test/factory.py (100%) rename src/{app => core}/test/mixer.py (100%) rename src/{app => core}/throttling.py (100%) rename src/{app => core}/types.py (100%) rename src/{app => core}/urls/__init__.py (80%) create mode 100644 src/core/urls/v2.py rename src/{app => core}/validators.py (100%) rename src/{app => core}/views.py (93%) rename src/{app => core}/viewsets.py (99%) rename src/{app => core}/wsgi.py (83%) delete mode 100644 src/diplomas/services/__init__.py delete mode 100644 src/homework/admin/__init__.py delete mode 100644 src/homework/models/__init__.py delete mode 100644 src/homework/services/__init__.py delete mode 100644 src/mailing/admin/__init__.py delete mode 100644 src/mailing/admin/personal_email_domain.py delete mode 100644 src/mailing/models/__init__.py delete mode 100644 src/orders/admin/__init__.py delete mode 100644 src/orders/models/__init__.py delete mode 100644 src/orders/services/__init__.py delete mode 100644 src/products/admin/__init__.py delete mode 120000 src/pyproject.toml delete mode 100644 src/pytest.ini delete mode 100644 src/studying/shipment/__init__.py delete mode 100644 src/users/admin/__init__.py delete mode 100644 src/users/services/__init__.py delete mode 100644 src/users/tags/__init__.py rename {src/tinkoff => tests}/__init__.py (100%) rename {src/tinkoff/migrations => tests/apps}/__init__.py (100%) rename {src/users => tests/apps/a12n}/__init__.py (100%) create mode 100644 tests/apps/a12n/api/conftest.py rename {src/a12n/tests => tests/apps/a12n}/api/tests_obtain_jwt_via_passwordless_token.py (100%) rename {src/a12n/tests => tests/apps/a12n}/api/tests_obtain_jwt_via_user_id.py (92%) rename {src/a12n/tests => tests/apps/a12n}/api/tests_obtain_token.py (96%) rename {src/a12n/tests => tests/apps/a12n}/api/tests_password_change.py (100%) rename {src/a12n/tests => tests/apps/a12n}/api/tests_password_reset_confirm.py (100%) rename {src/a12n/tests => tests/apps/a12n}/api/tests_refresh_token.py (97%) rename {src/a12n/tests => tests/apps/a12n}/api/tests_request_password_reset.py (100%) rename {src/a12n/tests => tests/apps/a12n}/api/tests_request_passwordless_token.py (92%) rename {src/a12n/tests => tests/apps/a12n}/tests_passwordless_token_absolute_url.py (100%) rename {src/users/management => tests/apps/amocrm}/__init__.py (100%) rename {src/amocrm/tests => tests/apps/amocrm}/conftest.py (75%) rename {src/amocrm/tests => tests/apps/amocrm}/dto/conftest.py (66%) rename {src/amocrm/tests => tests/apps/amocrm}/dto/tests_amo_groups.py (96%) rename {src/amocrm/tests => tests/apps/amocrm}/dto/tests_amo_pipelines.py (99%) rename {src/amocrm/tests => tests/apps/amocrm}/dto/tests_catalogs.py (98%) rename {src/amocrm/tests => tests/apps/amocrm}/dto/tests_customer.py (89%) rename {src/amocrm/tests => tests/apps/amocrm}/dto/tests_lead.py (90%) rename {src/amocrm/tests => tests/apps/amocrm}/dto/tests_product.py (98%) rename {src/amocrm/tests => tests/apps/amocrm}/dto/tests_transaction.py (97%) rename {src/users/management/commands => tests/apps/amocrm/http}/__init__.py (100%) rename {src/amocrm/tests => tests/apps/amocrm}/http/tests_http.py (96%) rename {src/users/migrations => tests/apps/amocrm/ids}/__init__.py (100%) rename {src/amocrm/tests => tests/apps/amocrm}/ids/tests_b2c_pipeline_id.py (76%) rename {src/amocrm/tests => tests/apps/amocrm}/ids/tests_catalog_id.py (76%) rename {src/amocrm/tests => tests/apps/amocrm}/ids/tests_contact_fields_ids.py (75%) rename {src/amocrm/tests => tests/apps/amocrm}/ids/tests_product_fields_ids.py (71%) create mode 100644 tests/apps/amocrm/services/__init__.py create mode 100644 tests/apps/amocrm/services/order/__init__.py rename {src/amocrm/tests => tests/apps/amocrm}/services/order/conftest.py (100%) rename {src/amocrm/tests => tests/apps/amocrm}/services/order/tests_order_pusher.py (88%) rename {src/amocrm/tests => tests/apps/amocrm}/services/order/tests_order_returner.py (82%) rename {src/amocrm/tests => tests/apps/amocrm}/services/tests_course_pusher.py (73%) rename {src/amocrm/tests => tests/apps/amocrm}/services/tests_group_pusher.py (62%) rename {src/amocrm/tests => tests/apps/amocrm}/services/tests_user_pusher.py (66%) rename {src/amocrm/tests => tests/apps/amocrm}/tests_access_token_getter.py (96%) rename {src/banking/tests => tests/apps/banking}/atol/conftest.py (91%) rename {src/banking/tests => tests/apps/banking}/atol/test_atol_auth.py (88%) rename {src/banking/tests => tests/apps/banking}/atol/test_atol_data.py (100%) rename {src/banking/tests => tests/apps/banking}/atol/test_atol_notifications.py (93%) rename {src/banking/tests => tests/apps/banking}/tests_bank_selector.py (64%) rename {src/banking/tests => tests/apps/banking}/tests_price_calculator.py (90%) rename {src/chains/tests => tests/apps/chains}/chain_sender/conftest.py (58%) rename {src/chains/tests => tests/apps/chains}/chain_sender/test_chain_sender_integrational.py (95%) rename {src/chains/tests => tests/apps/chains}/chain_sender/test_chain_tasks.py (95%) rename {src/chains/tests => tests/apps/chains}/chain_sender/test_sending_next_messages.py (100%) rename {src/chains/tests => tests/apps/chains}/chain_sender/test_sending_root_messages.py (100%) rename {src/chains/tests => tests/apps/chains}/conftest.py (100%) rename {src/chains/tests => tests/apps/chains}/message_sender/conftest.py (63%) rename {src/chains/tests => tests/apps/chains}/message_sender/test_sending_message.py (97%) rename {src/chains/tests => tests/apps/chains}/test_message_time_to_send.py (100%) rename {src/chains/tests => tests/apps/chains}/unit/test_chain_queryset_active.py (93%) rename {src/chains/tests => tests/apps/chains}/unit/test_chain_queryset_editable.py (95%) rename {src/chains/tests => tests/apps/chains}/unit/test_progress_get_last.py (95%) rename {src/diplomas/tests => tests/apps/diplomas}/api/conftest.py (88%) rename {src/diplomas/tests => tests/apps/diplomas}/api/tests_diploma_create.py (93%) rename {src/diplomas/tests => tests/apps/diplomas}/api/tests_diploma_deletion.py (100%) rename {src/diplomas/tests => tests/apps/diplomas}/api/tests_diploma_list.py (100%) rename {src/diplomas/tests => tests/apps/diplomas}/api/tests_diploma_retrieve.py (96%) rename {src/diplomas/tests => tests/apps/diplomas}/api/tests_diploma_update_is_disabled.py (100%) rename {src/diplomas/tests => tests/apps/diplomas}/conftest.py (88%) rename {src/diplomas/tests => tests/apps/diplomas}/diploma_generator/tests_diploma_generator_functional.py (93%) rename {src/diplomas/tests => tests/apps/diplomas}/diploma_generator/tests_diploma_generator_retry.py (92%) rename {src/diplomas/tests => tests/apps/diplomas}/diploma_generator/tests_diploma_generator_unit.py (96%) rename {src/diplomas/tests => tests/apps/diplomas}/diploma_queryset/test_diploma_filter_with_template.py (92%) rename {src/diplomas/tests => tests/apps/diplomas}/tests_diploma_get_absolute_url.py (100%) rename {src/diplomas/tests => tests/apps/diplomas}/tests_diploma_regenerator.py (89%) rename {src/homework/tests => tests/apps/homework}/answers/tests_answer_get_purchased_course.py (100%) rename {src/homework/tests => tests/apps/homework}/answers/tests_answer_str.py (100%) rename {src/homework/tests => tests/apps/homework}/answers/tests_answers_allowed_for_user_queryset.py (98%) rename {src/homework/tests => tests/apps/homework}/answers/tests_answers_get_absolute_urls.py (100%) rename {src/homework/tests => tests/apps/homework}/api/conftest.py (100%) rename {src/homework/tests => tests/apps/homework}/api/tests_answer_create.py (99%) rename {src/homework/tests => tests/apps/homework}/api/tests_answer_destroy.py (97%) rename {src/homework/tests => tests/apps/homework}/api/tests_answer_image_upload.py (96%) rename {src/homework/tests => tests/apps/homework}/api/tests_answer_list.py (100%) rename {src/homework/tests => tests/apps/homework}/api/tests_answer_retrieval_access_logs.py (96%) rename {src/homework/tests => tests/apps/homework}/api/tests_answer_retrieve.py (100%) rename {src/homework/tests => tests/apps/homework}/api/tests_answer_update.py (98%) rename {src/homework/tests => tests/apps/homework}/api/tests_comments_list.py (100%) rename {src/homework/tests => tests/apps/homework}/api/tests_comments_list_descendants.py (100%) rename {src/homework/tests => tests/apps/homework}/api/tests_markdown_sanitization.py (100%) rename {src/homework/tests => tests/apps/homework}/api/tests_question_retrieve.py (100%) rename {src/homework/tests => tests/apps/homework}/api/tests_reaction_create.py (96%) rename {src/homework/tests => tests/apps/homework}/api/tests_reaction_destroy.py (92%) rename {src/homework/tests => tests/apps/homework}/conftest.py (100%) rename {src/homework/tests => tests/apps/homework}/cross_check/conftest.py (83%) rename {src/homework/tests => tests/apps/homework}/cross_check/tests_crosscheck_dispatcher.py (93%) rename {src/homework/tests => tests/apps/homework}/cross_check/tests_crosscheck_is_checked.py (100%) rename {src/homework/tests => tests/apps/homework}/cross_check/tests_dispatch_answers_of_the_same_user.py (95%) rename {src/homework/tests => tests/apps/homework}/cross_check/tests_get_answer_to_check.py (96%) rename {src/homework/tests => tests/apps/homework}/cross_check/tests_get_crosscheck_count.py (100%) rename {src/homework/tests => tests/apps/homework}/cross_check/tests_question_crosscheck_dispatcher.py (93%) rename {src/homework/tests => tests/apps/homework}/cross_check/tests_question_crosscheck_queryset.py (100%) rename {src/homework/tests => tests/apps/homework}/new_answer_notifier/conftest.py (87%) rename {src/homework/tests => tests/apps/homework}/new_answer_notifier/tests_answer_notifier_get_template_context.py (100%) rename {src/homework/tests => tests/apps/homework}/new_answer_notifier/tests_get_users_to_notify.py (100%) rename {src/homework/tests => tests/apps/homework}/new_answer_notifier/tests_new_answer_email.py (100%) rename {src/homework/tests => tests/apps/homework}/new_answer_notifier/tests_new_answer_notifier_integration.py (98%) rename {src/homework/tests => tests/apps/homework}/questions/tests_question_absolute_url.py (100%) rename {src/homework/tests => tests/apps/homework}/reactions/test_reaction_creator.py (91%) rename {src/homework/tests => tests/apps/homework}/tests_crosscheck_integration.py (95%) rename {src/magnets/tests => tests/apps/magnets}/conftest.py (84%) rename {src/magnets/tests => tests/apps/magnets}/email_lead_magnet/conftest.py (100%) rename {src/magnets/tests => tests/apps/magnets}/email_lead_magnet/tests_emaiL_lead_magnet_creating_api.py (97%) rename {src/magnets/tests => tests/apps/magnets}/email_lead_magnet/tests_email_lead_magnet_execution.py (96%) rename {src/magnets/tests => tests/apps/magnets}/tests_lead_magnet_creator.py (88%) rename {src/magnets/tests => tests/apps/magnets}/tests_lead_magnet_lead_count.py (93%) rename {src/mailing/tests => tests/apps/mailing}/configuration/conftest.py (100%) rename {src/mailing/tests => tests/apps/mailing}/configuration/test_get_configuration.py (95%) rename {src/mailing/tests => tests/apps/mailing}/owl/conftest.py (90%) rename {src/mailing/tests => tests/apps/mailing}/owl/tests_owl_antispam.py (93%) rename {src/mailing/tests => tests/apps/mailing}/owl/tests_owl_configuration.py (92%) rename {src/mailing/tests => tests/apps/mailing}/owl/tests_owl_functional.py (100%) rename {src/mailing/tests => tests/apps/mailing}/owl/tests_owl_unit.py (96%) rename {src/mailing/tests => tests/apps/mailing}/owl/tests_send_mail_task.py (77%) rename {src/notion/tests => tests/apps/notion}/api/conftest.py (79%) rename {src/notion/tests => tests/apps/notion}/api/test_notion_cache_api.py (92%) rename {src/notion/tests => tests/apps/notion}/api/test_notion_material_api.py (100%) rename {src/notion/tests => tests/apps/notion}/api/test_notion_material_api_permissions.py (100%) rename {src/notion/tests => tests/apps/notion}/block_list/conftest.py (95%) rename {src/notion/tests => tests/apps/notion}/block_list/test_get_underlying_block_ids.py (97%) rename {src/notion/tests => tests/apps/notion}/conftest.py (84%) rename {src/notion/tests => tests/apps/notion}/test_celery_tasks.py (79%) rename {src/notion/tests => tests/apps/notion}/test_fetch_blocks.py (100%) rename {src/notion/tests => tests/apps/notion}/test_fetch_page.py (96%) rename {src/notion/tests => tests/apps/notion}/test_fetch_page_recursively.py (93%) rename {src/notion/tests => tests/apps/notion}/test_id_to_uuid.py (88%) rename {src/notion/tests => tests/apps/notion}/test_material_get_absolute_url.py (100%) rename {src/notion/tests => tests/apps/notion}/test_notion_block.py (93%) rename {src/notion/tests => tests/apps/notion}/test_notion_cache.py (86%) rename {src/notion/tests => tests/apps/notion}/test_notion_rewrite_links.py (97%) rename {src/notion/tests => tests/apps/notion}/test_page_url_to_id.py (92%) rename {src/orders/tests => tests/apps/orders}/configurable_bank/conftest.py (52%) rename {src/orders/tests => tests/apps/orders}/configurable_bank/tests_configurable_bank.py (98%) rename {src/orders/tests => tests/apps/orders}/configurable_bank/tests_zero_price_bank.py (100%) rename {src/orders/tests => tests/apps/orders}/conftest.py (100%) create mode 100644 tests/apps/orders/human_readable/__init__.py rename {src/orders/tests => tests/apps/orders}/human_readable/conftest.py (100%) rename {src/orders/tests => tests/apps/orders}/human_readable/test_get_customer.py (96%) rename {src/orders/tests => tests/apps/orders}/human_readable/test_get_payment_method_name.py (93%) rename {src/orders/tests => tests/apps/orders}/models/order_content_type_replacement/conftest.py (100%) rename {src/orders/tests => tests/apps/orders}/models/order_content_type_replacement/tests_order_item.py (100%) rename {src/orders/tests => tests/apps/orders}/models/order_content_type_replacement/tests_order_item_foreignkey.py (100%) rename {src/orders/tests => tests/apps/orders}/models/order_content_type_replacement/tests_order_set_item.py (92%) rename {src/orders/tests => tests/apps/orders}/models/test_order_item_constraints.py (93%) rename {src/orders/tests => tests/apps/orders}/models/tests_order_refund.py (94%) rename {src/orders/tests => tests/apps/orders}/order_confirmation/conftest.py (84%) rename {src/orders/tests => tests/apps/orders}/order_confirmation/tests_order_confirmation_api.py (100%) rename {src/orders/tests => tests/apps/orders}/order_creator/conftest.py (76%) rename {src/orders/tests => tests/apps/orders}/order_creator/tests_order_creator.py (96%) rename {src/orders/tests => tests/apps/orders}/order_creator/tests_order_creator_confirmation_message.py (95%) rename {src/orders/tests => tests/apps/orders}/order_creator/tests_order_creator_promocodes.py (93%) rename {src/orders/tests => tests/apps/orders}/order_creator/tests_order_creator_update_chain.py (90%) rename {src/orders/tests => tests/apps/orders}/order_email_changer/conftest.py (71%) rename {src/orders/tests => tests/apps/orders}/order_email_changer/tests_order_email_changer.py (100%) rename {src/orders/tests => tests/apps/orders}/order_queryset/conftest.py (100%) rename {src/orders/tests => tests/apps/orders}/order_queryset/test_order_paid_queryset.py (94%) rename {src/orders/tests => tests/apps/orders}/order_queryset/test_order_shipped_without_payment_queryset.py (95%) rename {src/orders/tests => tests/apps/orders}/order_shipping/conftest.py (72%) rename {src/orders/tests => tests/apps/orders}/order_shipping/tests_order_set_paid.py (97%) rename {src/orders/tests => tests/apps/orders}/order_shipping/tests_sending_happiness_messages.py (88%) rename {src/orders/tests => tests/apps/orders}/order_shipping/tests_shipping_without_payment.py (100%) rename {src/orders/tests => tests/apps/orders}/pay_signals/test_setting_order_as_paid_on_dolyame_transaction.py (93%) rename {src/orders/tests => tests/apps/orders}/pay_signals/test_setting_order_as_paid_on_stripe_bank_transaction.py (93%) rename {src/orders/tests => tests/apps/orders}/pay_signals/test_setting_order_as_paid_on_tinkoff_bank_transaction.py (93%) rename {src/orders/tests => tests/apps/orders}/pay_signals/test_setting_order_as_paid_on_tinkoff_credit_transaction.py (93%) rename {src/orders/tests => tests/apps/orders}/promocode/conftest.py (100%) rename {src/orders/tests => tests/apps/orders}/promocode/tests_price_with_promocode.py (96%) rename {src/orders/tests => tests/apps/orders}/promocode/tests_promocode_apply.py (100%) rename {src/orders/tests => tests/apps/orders}/promocode/tests_promocode_compatible_with.py (100%) rename {src/orders/tests => tests/apps/orders}/promocode/tests_promocode_get_or_nothing.py (97%) rename {src/orders/tests => tests/apps/orders}/promocode/tests_promocode_order_count.py (96%) rename {src/orders/tests => tests/apps/orders}/services/tests_order_refunder.py (90%) rename {src/orders/tests => tests/apps/orders}/services/tests_order_unshipper.py (86%) rename {src/orders/tests => tests/apps/orders}/test_purchasing_order_with_non_trimmed_email.py (89%) rename {src/orders/tests => tests/apps/orders}/tests_order_diploma_generator.py (83%) rename {src/products/tests => tests/apps/products}/bundles/tests_bundle_deprecated.py (100%) rename {src/products/tests => tests/apps/products}/conftest.py (85%) rename {src/products/tests => tests/apps/products}/course_api/conftest.py (95%) rename {src/products/tests => tests/apps/products}/course_api/tests_purchasing_course.py (87%) rename {src/products/tests => tests/apps/products}/course_api/tests_purchasing_course_with_promocode.py (97%) rename {src/products/tests => tests/apps/products}/course_api/tests_purchasing_zero_priced_course.py (95%) rename {src/products/tests => tests/apps/products}/courses/tests_course_get_purchased_users.py (100%) rename {src/products/tests => tests/apps/products}/courses/tests_course_get_template_id.py (100%) rename {src/products/tests => tests/apps/products}/courses/tests_course_send_email_to_all_purchased_users.py (100%) rename {src/products/tests => tests/apps/products}/courses/tests_course_str.py (100%) rename {src/products/tests => tests/apps/products}/records/tests_record_deprecated.py (100%) rename {src/products/tests => tests/apps/products}/shippable/tests_get_price.py (100%) rename {src/stripebank/tests => tests/apps/stripebank}/.fixtures/webhook.json (100%) rename {src/stripebank/tests => tests/apps/stripebank}/conftest.py (78%) rename {src/stripebank/tests => tests/apps/stripebank}/test_stripe_get_items.py (100%) rename {src/stripebank/tests => tests/apps/stripebank}/test_stripe_webhook.py (93%) rename {src/studying/tests => tests/apps/studying}/api/test_home_page_slug.py (100%) rename {src/studying/tests => tests/apps/studying}/api/test_purchased_courses_view.py (100%) rename {src/studying/tests => tests/apps/studying}/conftest.py (100%) rename {src/studying/tests => tests/apps/studying}/course_shipment/conftest.py (90%) rename {src/studying/tests => tests/apps/studying}/course_shipment/tests_course_shipment_study_model.py (95%) rename {src/studying/tests => tests/apps/studying}/course_shipment/tests_course_shipment_welcome_letter.py (100%) rename {src/studying/tests => tests/apps/studying}/course_shipment/tests_course_template_context.py (100%) rename {src/studying/tests => tests/apps/studying}/shipping_factory/conftest.py (100%) rename {src/studying/tests => tests/apps/studying}/shipping_factory/tests_shippable_mixin.py (79%) rename {src/studying/tests => tests/apps/studying}/shipping_factory/tests_shipping_factory_get.py (76%) rename {src/studying/tests => tests/apps/studying}/shipping_factory/tests_shipping_factory_ship.py (78%) rename {src/studying/tests => tests/apps/studying}/shipping_factory/tests_shipping_factory_unship.py (81%) rename {src/tinkoff/tests => tests/apps/tinkoff}/.fixtures/testing.pem (100%) rename {src/tinkoff/tests => tests/apps/tinkoff}/bank_client/conftest.py (92%) rename {src/tinkoff/tests => tests/apps/tinkoff}/bank_client/tests_tinkoff_bank_success_and_fail_urls.py (94%) rename {src/tinkoff/tests => tests/apps/tinkoff}/bank_client/tests_tinkoff_get_initial_payment_url.py (96%) rename {src/tinkoff/tests => tests/apps/tinkoff}/bank_client/tests_tinkoff_receipt.py (100%) rename {src/tinkoff/tests => tests/apps/tinkoff}/bank_client/tests_tinkoff_refund.py (96%) rename {src/tinkoff/tests => tests/apps/tinkoff}/bank_client/tests_tinkoff_request_signing.py (100%) rename {src/tinkoff/tests => tests/apps/tinkoff}/conftest.py (100%) rename {src/tinkoff/tests => tests/apps/tinkoff}/credit_client/conftest.py (92%) rename {src/tinkoff/tests => tests/apps/tinkoff}/credit_client/tests_tinkoff_credit_creation.py (92%) rename {src/tinkoff/tests => tests/apps/tinkoff}/credit_client/tests_tinkoff_credit_demo_mode.py (100%) rename {src/tinkoff/tests => tests/apps/tinkoff}/credit_notifications/conftest.py (94%) rename {src/tinkoff/tests => tests/apps/tinkoff}/credit_notifications/tests_tinkoff_credit_notification.py (96%) rename {src/tinkoff/tests => tests/apps/tinkoff}/credit_notifications/tests_tinkoff_credit_notification_permissions.py (79%) rename {src/tinkoff/tests => tests/apps/tinkoff}/dolyame_client/conftest.py (74%) rename {src/tinkoff/tests => tests/apps/tinkoff}/dolyame_client/test_dolyame_common_methods.py (100%) rename {src/tinkoff/tests => tests/apps/tinkoff}/dolyame_client/test_dolyame_creation.py (100%) rename {src/tinkoff/tests => tests/apps/tinkoff}/dolyame_client/test_dolyame_refund.py (98%) rename {src/tinkoff/tests => tests/apps/tinkoff}/dolyame_notifications/conftest.py (92%) rename {src/tinkoff/tests => tests/apps/tinkoff}/dolyame_notifications/test_creating_dolyame_notifications.py (97%) rename {src/tinkoff/tests => tests/apps/tinkoff}/payment_notifications/conftest.py (72%) rename {src/tinkoff/tests => tests/apps/tinkoff}/payment_notifications/tests_tinkoff_payment_notification_api.py (93%) rename {src/tinkoff/tests => tests/apps/tinkoff}/payment_notifications/tests_tinkoff_token_validator.py (90%) rename {src/users/tests => tests/apps/users}/api/tests_user_self_view.py (91%) rename {src/users/tests => tests/apps/users}/tags/conftest.py (100%) rename {src/users/tests => tests/apps/users}/tags/test_any_purchase_tag.py (90%) rename {src/users/tests => tests/apps/users}/tags/test_b2b_tag.py (92%) rename {src/users/tests => tests/apps/users}/tags/test_rebuild_tags_task.py (73%) rename {src/users/tests => tests/apps/users}/tags/test_started_and_purchased_tags.py (97%) rename {src/users/tests => tests/apps/users}/test_freezegun_not_broken.py (95%) rename {src/users/tests => tests/apps/users}/test_user_diploma_languages.py (100%) rename {src/users/tests => tests/apps/users}/tests_name_parsing.py (93%) rename {src/users/tests => tests/apps/users}/tests_user_printable_gender.py (91%) rename {src/users/tests => tests/apps/users}/tests_user_printable_name.py (100%) rename {src/users/tests => tests/apps/users}/tests_user_str.py (100%) rename {src/users/tests => tests/apps/users}/user_creator/conftest.py (100%) rename {src/users/tests => tests/apps/users}/user_creator/tests_user_creator_for_existing_users.py (97%) rename {src/users/tests => tests/apps/users}/user_creator/tests_user_creator_name_and_email.py (97%) rename {src/users/tests => tests/apps/users}/user_creator/tests_user_creator_subscription.py (91%) create mode 100644 tests/conftest.py rename {src/app/tests => tests/core}/dashamail/conftest.py (87%) rename {src/app/tests => tests/core}/dashamail/test_subscription_updater.py (74%) rename {src/app/tests => tests/core}/dashamail/tests_dashamail_get_subscriber.py (100%) rename {src/app/tests => tests/core}/dashamail/tests_dashamail_http.py (95%) rename {src/app/tests => tests/core}/dashamail/tests_dashamail_subscribe.py (93%) rename {src/app/tests => tests/core}/dashamail/tests_dashamail_subscribe_task.py (52%) rename {src/app/tests => tests/core}/dashamail/tests_dashamail_update_subscriber.py (93%) rename {src/app/tests => tests/core}/dashamail/tests_dashamail_url.py (100%) rename {src/app/tests => tests/core}/helpers/tests_lower_first.py (87%) rename {src/app/tests => tests/core}/pricing/tests_format_old_price_helper.py (92%) rename {src/app/tests => tests/core}/pricing/tests_format_price_helper.py (91%) rename {src/app/tests => tests/core}/tests_drf_spectacular_view.py (100%) rename {src/app/tests => tests/core}/tests_home_page_view.py (100%) rename {src/app/tests => tests/core}/tests_s3_client.py (80%) create mode 100644 tests/factories/__init__.py create mode 100644 tests/factories/apps/__init__.py rename src/diplomas/factory.py => tests/factories/apps/diplomas.py (72%) rename src/orders/factory.py => tests/factories/apps/orders.py (78%) rename src/products/factory.py => tests/factories/apps/products.py (74%) rename src/app/factory.py => tests/factories/core.py (81%) create mode 100644 tests/fixtures/__init__.py create mode 100644 tests/fixtures/apps/__init__.py rename src/products/fixtures.py => tests/fixtures/apps/products.py (84%) rename src/users/fixtures.py => tests/fixtures/apps/users.py (100%) create mode 100644 tests/fixtures/core/__init__.py rename {src/app/fixtures => tests/fixtures/core}/api.py (85%) rename {src/app/fixtures => tests/fixtures/core}/dasha_subscription_updater.py (53%) rename {src/app/fixtures => tests/fixtures/core}/factory.py (58%) create mode 100644 tests/fixtures/core/send_mail.py rename {src/app/fixtures => tests/fixtures/core}/timezone.py (100%) diff --git a/.dockerignore b/.dockerignore index 9571f4ab990..31f3768d6e7 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,3 +2,5 @@ venv/ storage/ .vscode/ .env +.git +tests/ diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml new file mode 100644 index 00000000000..18f8a2fffe5 --- /dev/null +++ b/.github/actions/build/action.yml @@ -0,0 +1,42 @@ +name: build + +runs: + using: composite + + steps: + - name: load cached poetry installation + id: cached-poetry + uses: actions/cache@v3 + with: + path: ~/.local + key: poetry-v1-${{ hashFiles('pyproject.toml') }} + + - name: install poetry + if: steps.cached-poetry.outputs.cache-hit != 'true' + uses: snok/install-poetry@v1 + with: + version: 1.6.1 + + - name: install python + id: setup-python + uses: actions/setup-python@v4 + with: + cache: 'poetry' + python-version-file: 'pyproject.toml' + + - name: make sure poetry lockfile is up to date + run: poetry check --lock && echo Lockfile is ok, $(poetry --version) + shell: bash + + - name: save python version to the env + run: echo "python-version=${{ steps.setup-python.outputs.python-version }}" >> $GITHUB_ENV + shell: bash + + - name: install deps + if: steps.setup-python.outputs.cache-hit != 'true' + run: poetry install --no-interaction --no-root + shell: bash + + - name: restore default environment + run: cp src/core/.env.ci src/core/.env + shell: bash diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2d7c7acfdee..240bd181600 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,5 +1,6 @@ ---- name: CI + + on: push: branches: @@ -7,39 +8,28 @@ on: pull_request: jobs: - build: + lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: checkout + uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - id: setup-python - with: - python-version-file: '.python-version' + - name: build + uses: ./.github/actions/build - - uses: actions/cache@v3 - id: cache-dependencies + - name: restore mypy cache + uses: actions/cache@v3 with: - path: | - venv - key: ${{ runner.os }}-venv-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/*requirements.txt') }} - - - name: Install dependencies - if: steps.cache-dependencies.outputs.cache-hit != 'true' - run: | - python -m venv venv - . venv/bin/activate - pip install --upgrade pip pip-tools - pip-sync requirements.txt dev-requirements.txt - - - name: Run the linter - run: | - . venv/bin/activate - cp src/app/.env.ci src/app/.env - make lint + path: .mypy_cache + key: mypy-cache-${{ github.ref_name }} + restore-keys: mypy-cache-master + + - name: lint + run: make lint + test: - needs: build - runs-on: ubuntu-latest + needs: lint + runs-on: ubuntu-16x services: postgres: image: postgres:13.9-alpine @@ -60,32 +50,22 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - id: setup-python - with: - python-version-file: '.python-version' + - name: build + uses: ./.github/actions/build - - uses: actions/cache@v3 + - name: install locale stuff + uses: awalsh128/cache-apt-pkgs-action@v1 with: - path: | - venv - key: ${{ runner.os }}-venv-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/*requirements.txt') }} + packages: locales-all gettext + version: 1 - - name: Install locale stuff - run: | - sudo apt-get update - sudo apt-get --no-install-recommends install -y locales-all gettext - - - name: Run the tests + - name: test env: DATABASE_URL: postgres://postgres:secret@localhost:5432/postgres REDISCLOUD_URL: redis://localhost:6379/5 - run: | - . venv/bin/activate - cp src/app/.env.ci src/app/.env - make test + run: make test -e SIMULTANEOUS_TEST_JOBS=16 - - name: Upload code coverage to codeclimate + - name: upload code coverage to codeclimate uses: paambaati/codeclimate-action@v3.2.0 env: CC_TEST_REPORTER_ID: dd4cac59d43b52ee4c29cfed9d5162098a49ff65d9e72003abc1fa65cd608f1d @@ -97,30 +77,25 @@ jobs: needs: test runs-on: ubuntu-latest steps: - - name: Checkout + - name: checkout uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - id: setup-python - with: - python-version-file: '.python-version' + - name: build + uses: ./.github/actions/build - - name: Set up QEMU + - name: set up qemu uses: docker/setup-qemu-action@v2 - - name: Set up Docker Buildx + - name: set up buildx uses: docker/setup-buildx-action@v2 - - name: Store default envfironment file to be runnable at the developer machine - run: cp src/app/.env.ci src/app/.env - - - name: Generate image identifier + - name: generate image identifier id: image uses: ASzc/change-string-case-action@v5 with: string: ${{ github.repository_owner }} - - name: Login to GitHub Container Registry + - name: login to ghcr uses: docker/login-action@v2 if: ${{ github.ref == 'refs/heads/master' }} with: @@ -128,7 +103,7 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Build web image + - name: build web image uses: docker/build-push-action@v3 with: context: . @@ -139,12 +114,12 @@ jobs: ghcr.io/${{ steps.image.outputs.lowercase }}/monolith-web:${{ github.sha }} build-args: | - PYTHON_VERSION=${{ steps.setup-python.outputs.python-version }} + PYTHON_VERSION=${{ env.python-version }} RELEASE=${{ github.sha }} cache-from: type=gha cache-to: type=gha,mode=max - - name: Build worker image + - name: build worker image uses: docker/build-push-action@v3 with: context: . @@ -154,12 +129,12 @@ jobs: ghcr.io/${{ steps.image.outputs.lowercase }}/monolith-worker:latest ghcr.io/${{ steps.image.outputs.lowercase }}/monolith-worker:${{ github.sha }} build-args: | - PYTHON_VERSION=${{ steps.setup-python.outputs.python-version }} + PYTHON_VERSION=${{ env.python-version }} RELEASE=${{ github.sha }} cache-from: type=gha cache-to: type=gha,mode=max - - name: Build scheduler image + - name: build scheduler image uses: docker/build-push-action@v3 with: context: . @@ -169,7 +144,7 @@ jobs: ghcr.io/${{ steps.image.outputs.lowercase }}/monolith-scheduler:latest ghcr.io/${{ steps.image.outputs.lowercase }}/monolith-scheduler:${{ github.sha }} build-args: | - PYTHON_VERSION=${{ steps.setup-python.outputs.python-version }} + PYTHON_VERSION=${{ env.python-version }} RELEASE=${{ github.sha }} cache-from: type=gha cache-to: type=gha,mode=max @@ -179,10 +154,10 @@ jobs: if: github.ref == 'refs/heads/master' && github.repository_owner == 'tough-dev-school' runs-on: ubuntu-latest steps: - - name: Checkout + - name: checkout uses: actions/checkout@v3 - - name: Draft Sentry release + - name: draft sentry release uses: getsentry/action-release@v1 env: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} @@ -192,13 +167,13 @@ jobs: environment: production finalize: false - - name: Read image identifiers + - name: read image identifiers id: image uses: ASzc/change-string-case-action@v5 with: string: ${{ github.repository_owner }} - - name: Update backend image + - name: update backend image uses: appleboy/ssh-action@v0.1.7 with: host: ${{ secrets.DEPLOY_HOST }} @@ -206,7 +181,7 @@ jobs: key: ${{ secrets.DEPLOY_KEY }} script: docker service update app_backend --image ghcr.io/${{ steps.image.outputs.lowercase }}/monolith-web:${{ github.sha }} --with-registry-auth - - name: Update celery worker image + - name: update celery worker image uses: appleboy/ssh-action@v0.1.7 with: host: ${{ secrets.DEPLOY_HOST }} @@ -214,7 +189,7 @@ jobs: key: ${{ secrets.DEPLOY_KEY }} script: docker service update app_worker --image ghcr.io/${{ steps.image.outputs.lowercase }}/monolith-worker:${{ github.sha }} --with-registry-auth - - name: Update celery amocrm worker image + - name: update celery amocrm worker image uses: appleboy/ssh-action@v0.1.7 with: host: ${{ secrets.DEPLOY_HOST }} @@ -222,7 +197,7 @@ jobs: key: ${{ secrets.DEPLOY_KEY }} script: docker service update app_amocrm-worker --image ghcr.io/${{ steps.image.outputs.lowercase }}/monolith-worker:${{ github.sha }} --with-registry-auth - - name: Update celery scheduler image + - name: update celery scheduler image uses: appleboy/ssh-action@v0.1.7 with: host: ${{ secrets.DEPLOY_HOST }} @@ -231,7 +206,7 @@ jobs: script: | docker service update app_scheduler --detach --image ghcr.io/${{ steps.image.outputs.lowercase }}/monolith-scheduler:${{ github.sha }} --with-registry-auth - - name: Finalize Sentry release + - name: finalize sentry release uses: getsentry/action-release@v1 env: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} diff --git a/.github/workflows/crossplatform.yml b/.github/workflows/crossplatform.yml index 1ae6f4718d6..b99daa71456 100644 --- a/.github/workflows/crossplatform.yml +++ b/.github/workflows/crossplatform.yml @@ -1,41 +1,25 @@ ---- name: Crossplatform nightly + on: schedule: - cron: '30 4 * * *' workflow_dispatch: jobs: - build: + lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: checkout + uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - with: - python-version-file: '.python-version' + - name: build + uses: ./.github/actions/build - - uses: actions/cache@v3 - with: - path: | - venv - key: ${{ runner.os }}-venv-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/*requirements.txt') }} + - name: lint + run: make lint - - name: Install dependencies - if: steps.cache-primes.outputs.cache-hit != 'true' - run: | - python -m venv venv - . venv/bin/activate - pip install --upgrade pip pip-tools - pip-sync requirements.txt dev-requirements.txt - - - name: Run the linter - run: | - . venv/bin/activate - cp src/app/.env.ci src/app/.env - make lint test: - needs: build + needs: lint runs-on: ubuntu-latest services: postgres: @@ -55,60 +39,46 @@ jobs: - 6379:6379 steps: - - uses: actions/checkout@v3 - - - uses: actions/setup-python@v4 - with: - python-version-file: '.python-version' + - name: checkout + uses: actions/checkout@v3 - - uses: actions/cache@v3 - with: - path: | - venv - key: ${{ runner.os }}-venv-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/*requirements.txt') }} + - name: build + uses: ./.github/actions/build - - name: Install locale stuff + - name: install locale stuff run: | sudo apt-get update sudo apt-get --no-install-recommends install -y locales-all gettext - - name: Run the tests + - name: test env: DATABASE_URL: postgres://postgres:secret@localhost:5432/postgres REDISCLOUD_URL: redis://localhost:6379/5 - run: | - . venv/bin/activate - cp src/app/.env.ci src/app/.env - make test + run: make test build-docker-image: needs: test runs-on: ubuntu-latest steps: - - name: Checkout + - name: checkout uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - id: setup-python - with: - python-version-file: '.python-version' + - name: build + uses: ./.github/actions/build - - name: Set up QEMU + - name: set up qemu uses: docker/setup-qemu-action@v2 - - name: Set up Docker Buildx + - name: set up buildx uses: docker/setup-buildx-action@v2 - - name: Store default envfironment file to be runnable at the developer machine - run: cp src/app/.env.ci src/app/.env - - - name: Generate image identifier + - name: generate image identifier id: image uses: ASzc/change-string-case-action@v5 with: string: ${{ github.repository_owner }} - - name: Login to GitHub Container Registry + - name: login to ghcr uses: docker/login-action@v2 if: ${{ github.ref == 'refs/heads/master' }} with: @@ -116,7 +86,7 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Build dev image + - name: build dev image uses: docker/build-push-action@v3 with: context: . @@ -128,7 +98,7 @@ jobs: ghcr.io/${{ steps.image.outputs.lowercase }}/dev-backend:${{ github.sha }} build-args: | - PYTHON_VERSION=${{ steps.setup-python.outputs.python-version }} + PYTHON_VERSION=${{ env.python-version }} RELEASE=${{ github.sha }} cache-from: type=gha cache-to: type=gha,mode=max diff --git a/.python-version b/.python-version deleted file mode 100644 index 9ac38041885..00000000000 --- a/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.11.5 diff --git a/Dockerfile b/Dockerfile index 77bb061dd0b..b70a493e04a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,34 @@ ARG PYTHON_VERSION -FROM python:${PYTHON_VERSION}-slim-bullseye as base + +# +# Compile custom uwsgi, cuz debian's one is weird +# +FROM python:${PYTHON_VERSION}-slim-bookworm as uwsgi-compile +ENV _UWSGI_VERSION 2.0.22 +RUN apt-get update && apt-get --no-install-recommends install -y build-essential wget && rm -rf /var/lib/apt/lists/* +RUN wget -O uwsgi-${_UWSGI_VERSION}.tar.gz https://github.com/unbit/uwsgi/archive/${_UWSGI_VERSION}.tar.gz \ + && tar zxvf uwsgi-*.tar.gz \ + && UWSGI_BIN_NAME=/uwsgi make -C uwsgi-${_UWSGI_VERSION} \ + && rm -Rf uwsgi-* + + +# +# Build poetry and export compiled dependecines as plain requirements.txt +# +FROM python:${PYTHON_VERSION}-slim-bookworm as deps-compile + +WORKDIR / +COPY poetry.lock pyproject.toml / + +# Version is taken from poetry.lock, assuming it is generated with up-to-date version of poetry +RUN pip install --no-cache-dir poetry==$(cat poetry.lock |head -n1|awk -v FS='(Poetry |and)' '{print $2}') +RUN poetry export --format=requirements.txt > requirements.txt + + +# +# Base image with django dependecines +# +FROM python:${PYTHON_VERSION}-slim-bookworm as base LABEL maintainer="fedor@borshev.com" LABEL com.datadoghq.ad.logs='[{"source": "uwsgi", "service": "django"}]' @@ -8,33 +37,17 @@ ENV PYTHONUNBUFFERED 1 ENV DEBIAN_FRONTEND noninteractive ENV STATIC_ROOT /var/lib/django-static -ENV CELERY_APP=app.celery +ENV CELERY_APP=core.celery -ENV _UWSGI_VERSION 2.0.21 ENV _WAITFOR_VERSION 2.2.3 -RUN echo deb http://deb.debian.org/debian buster contrib non-free > /etc/apt/sources.list.d/debian-contrib.list \ - && apt-get update \ - && apt-get --no-install-recommends install -y gettext locales-all wget imagemagick tzdata git netcat \ - && rm -rf /var/lib/apt/lists/* - -RUN apt-get update && apt-get --no-install-recommends install -y build-essential libxml2-dev libxslt1-dev \ - && apt-get --no-install-recommends install -y libjpeg62-turbo-dev libjpeg-dev libfreetype6-dev libtiff5-dev liblcms2-dev libwebp-dev tk8.6-dev \ - && apt-get --no-install-recommends install -y libffi-dev libcgraph6 libgraphviz-dev libmagic-dev \ +RUN apt-get update \ + && apt-get --no-install-recommends install -y gettext locales-all tzdata git wait-for-it \ && rm -rf /var/lib/apt/lists/* -RUN wget -O /usr/local/bin/wait-for https://github.com/eficode/wait-for/releases/download/v${_WAITFOR_VERSION}/wait-for \ - && chmod +x /usr/local/bin/wait-for - -RUN wget -O uwsgi-${_UWSGI_VERSION}.tar.gz https://github.com/unbit/uwsgi/archive/${_UWSGI_VERSION}.tar.gz \ - && tar zxvf uwsgi-*.tar.gz \ - && UWSGI_BIN_NAME=/usr/local/bin/uwsgi make -C uwsgi-${_UWSGI_VERSION} \ - && rm -Rf uwsgi-* - +COPY --from=uwsgi-compile /uwsgi /usr/local/bin/ RUN pip install --no-cache-dir --upgrade pip - -COPY requirements.txt / - +COPY --from=deps-compile /requirements.txt / RUN pip install --no-cache-dir -r requirements.txt WORKDIR /src @@ -47,17 +60,23 @@ ENV NO_CACHE=Off USER nobody - +# +# Web worker image +# FROM base as web HEALTHCHECK CMD wget -q -O /dev/null http://localhost:8000/api/v2/healthchecks/db/ --header "Host: app.tough-dev.school" || exit 1 -CMD ./manage.py migrate && uwsgi --master --http :8000 --module app.wsgi --workers 2 --threads 2 --harakiri 25 --max-requests 1000 --log-x-forwarded-for - +CMD ./manage.py migrate && uwsgi --master --http :8000 --module core.wsgi --workers 2 --threads 2 --harakiri 25 --max-requests 1000 --log-x-forwarded-for +# +# Background processing image +# FROM base as worker HEALTHCHECK CMD celery -A ${CELERY_APP} inspect ping -d $QUEUE@$HOSTNAME CMD celery -A ${CELERY_APP} worker -Q $QUEUE -c ${CONCURENCY:-2} -n "${QUEUE}@%h" --max-tasks-per-child ${MAX_REQUESTS_PER_CHILD:-50} --time-limit ${TIME_LIMIT:-900} --soft-time-limit ${SOFT_TIME_LIMIT:-45} - +# +# Periodic scheduler image +# FROM base as scheduler ENV SCHEDULER_DB_PATH=/var/db/scheduler USER root diff --git a/Makefile b/Makefile index c402853cbd8..011d2c3043e 100644 --- a/Makefile +++ b/Makefile @@ -1,33 +1,24 @@ -install-dev-deps: dev-deps - pip-sync requirements.txt dev-requirements.txt - -install-deps: deps - pip-sync requirements.txt - -deps: - pip install --upgrade pip pip-tools - pip-compile --output-file requirements.txt --resolver=backtracking pyproject.toml - -dev-deps: deps - pip-compile --extra=dev --output-file dev-requirements.txt --resolver=backtracking pyproject.toml - -server: - cd src && ./manage.py migrate && ./manage.py runserver - -worker: - cd src && celery -A app worker -E --purge +manage = poetry run python src/manage.py +SIMULTANEOUS_TEST_JOBS=4 fmt: - cd src && autoflake --in-place --remove-all-unused-imports --recursive . - cd src && isort . - cd src && black . + poetry run autoflake --in-place --remove-all-unused-imports --recursive src + poetry run isort src + poetry run black src lint: - cd src && ./manage.py makemigrations --check --no-input --dry-run - flake8 src - cd src && mypy + $(manage) makemigrations --check --no-input --dry-run + poetry run flake8 src + poetry run mypy src + +server: + $(manage) migrate + $(manage) runserver test: - cd src && pytest -n 4 --ff -x --create-db --cov-report=xml --cov=. -m 'not single_thread' - cd src && pytest --ff -x --cov-report=xml --cov=. --cov-append -m 'single_thread' - cd src && pytest --dead-fixtures + poetry run pytest -n ${SIMULTANEOUS_TEST_JOBS} --ff -x --create-db --cov-report=xml --cov=. -m 'not single_thread' + poetry run pytest --ff -x --cov-report=xml --cov=. --cov-append -m 'single_thread' + poetry run pytest --dead-fixtures + +worker: + poetry run celery --app core --workdir src worker --events --purge diff --git a/README.md b/README.md index db9b4c0087a..29a05af604c 100644 --- a/README.md +++ b/README.md @@ -5,24 +5,22 @@ Django-based production project, integrated with Tinkoff, Dashamail, Postmark, S3 and telegram. Frontend is built on vue.js in the [separate repo](http://github.com/f213/education-frontend). ## Configuration -Configuration is stored in `src/app/.env`, for examples see `src/app/.env.ci` +Configuration is stored in `src/core/.env`, for examples see `src/core/.env.ci` ## Installing on a local machine -This project requires python 3.11. Python virtual environment should be installed and activated.\ -Deps are managed by [pip-tools](https://github.com/jazzband/pip-tools) with requirements stored in [pyproject.toml](https://github.com/jazzband/pip-tools#requirements-from-pyprojecttoml). +This project requires python 3.11. Deps are managed by [Poetry](https://python-poetry.org/). Install requirements: ```bash -pip install --upgrade pip pip-tools -make +poetry install ``` Configure postgres and redis. It's convenient to use docker and docker-compose: ```bash -docker-compose up -d +docker compose up -d ``` If you don't have access to de-anonymized db image use `postgres:13.6-alpine` in `docker-compose.yml` instead: @@ -35,19 +33,21 @@ postgres: Run the server: ```bash -cd src && cp app/.env.ci app/.env # default environment variables -./manage.py migrate -./manage.py createsuperuser -./manage.py runserver +cp src/core/.env.ci src/core/.env + +poetry run python src/manage.py migrate +poetry run python src/manage.py createsuperuser + +make server ``` Testing: ```bash # run lint -make -C .. lint +make lint # run unit tests -make -C .. test +make test ``` ## Backend Code requirements diff --git a/dev-requirements.txt b/dev-requirements.txt deleted file mode 100644 index 758c29ac2ba..00000000000 --- a/dev-requirements.txt +++ /dev/null @@ -1,515 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.11 -# by the following command: -# -# pip-compile --extra=dev --output-file=dev-requirements.txt pyproject.toml -# -amqp==5.1.1 - # via kombu -anyio==3.7.1 - # via httpcore -appnope==0.1.3 - # via ipython -asgiref==3.7.2 - # via django -astor==0.8.1 - # via flake8-simplify -astroid==2.15.8 - # via flake8-django -asttokens==2.4.0 - # via stack-data -async-timeout==4.0.3 - # via redis -attrs==23.1.0 - # via - # flake8-bugbear - # flake8-eradicate - # flake8-multiline-containers - # jsonschema - # referencing -autoflake==1.7.8 - # via education-backend (pyproject.toml) -babel==2.13.0 - # via education-backend (pyproject.toml) -backcall==0.2.0 - # via ipython -bcrypt==4.0.1 - # via education-backend (pyproject.toml) -billiard==3.6.4.0 - # via celery -black==23.9.1 - # via - # education-backend (pyproject.toml) - # flake8-black -bleach==6.1.0 - # via education-backend (pyproject.toml) -boto3==1.28.1 - # via education-backend (pyproject.toml) -boto3-stubs==1.28.1 - # via education-backend (pyproject.toml) -botocore==1.31.1 - # via - # boto3 - # s3transfer -botocore-stubs==1.29.165 - # via boto3-stubs -celery==5.2.7 - # via education-backend (pyproject.toml) -certifi==2023.7.22 - # via - # django-healthchecks - # httpcore - # httpx - # requests - # sentry-sdk -cffi==1.16.0 - # via - # cmarkgfm - # cryptography -charset-normalizer==3.3.0 - # via requests -click==8.1.7 - # via - # black - # celery - # click-didyoumean - # click-plugins - # click-repl -click-didyoumean==0.3.0 - # via celery -click-plugins==1.1.1 - # via celery -click-repl==0.3.0 - # via celery -cmarkgfm==2022.10.27 - # via education-backend (pyproject.toml) -cognitive-complexity==1.3.0 - # via flake8-cognitive-complexity -coverage[toml]==7.3.2 - # via pytest-cov -cryptography==41.0.4 - # via pyjwt -decorator==5.1.1 - # via - # ipython - # retry -dj-rest-auth==4.0.1 - # via education-backend (pyproject.toml) -django==4.2.6 - # via - # dj-rest-auth - # django-anymail - # django-axes - # django-cachalot - # django-cors-headers - # django-debug-toolbar - # django-filter - # django-healthchecks - # django-prettyjson - # django-storages - # django-stubs - # django-stubs-ext - # djangorestframework - # drf-jwt - # drf-recaptcha - # drf-spectacular - # drf-spectacular-sidecar - # education-backend (pyproject.toml) -django-anymail==10.1 - # via education-backend (pyproject.toml) -django-axes==6.1.1 - # via education-backend (pyproject.toml) -django-behaviors==0.5.1 - # via education-backend (pyproject.toml) -django-cachalot==2.6.1 - # via education-backend (pyproject.toml) -django-cors-headers==4.3.0 - # via education-backend (pyproject.toml) -django-debug-toolbar==4.2.0 - # via education-backend (pyproject.toml) -django-environ==0.11.2 - # via education-backend (pyproject.toml) -django-filter==23.3 - # via education-backend (pyproject.toml) -django-healthchecks==1.5.0 - # via education-backend (pyproject.toml) -django-ipware==5.0.1 - # via - # drf-recaptcha - # education-backend (pyproject.toml) -django-prettyjson==0.4.1 - # via education-backend (pyproject.toml) -django-split-settings==1.2.0 - # via education-backend (pyproject.toml) -django-storages==1.14.2 - # via education-backend (pyproject.toml) -django-stubs==4.2.4 - # via - # djangorestframework-stubs - # education-backend (pyproject.toml) -django-stubs-ext==4.2.2 - # via django-stubs -django-tree-queries==0.15.0 - # via education-backend (pyproject.toml) -djangorestframework==3.14.0 - # via - # dj-rest-auth - # drf-jwt - # drf-recaptcha - # drf-spectacular - # education-backend (pyproject.toml) -djangorestframework-stubs==3.14.3 - # via education-backend (pyproject.toml) -drf-jwt==1.19.2 - # via education-backend (pyproject.toml) -drf-recaptcha==3.0.0 - # via education-backend (pyproject.toml) -drf-spectacular[sidecar]==0.26.5 - # via education-backend (pyproject.toml) -drf-spectacular-sidecar==2023.10.1 - # via drf-spectacular -emoji==2.8.0 - # via education-backend (pyproject.toml) -eradicate==2.3.0 - # via flake8-eradicate -execnet==2.0.2 - # via pytest-xdist -executing==1.2.0 - # via stack-data -faker==12.0.1 - # via mixer -flake8==5.0.4 - # via - # flake8-absolute-import - # flake8-black - # flake8-bugbear - # flake8-django - # flake8-eradicate - # flake8-isort - # flake8-multiline-containers - # flake8-mutable - # flake8-pep3101 - # flake8-print - # flake8-printf-formatting - # flake8-pyproject - # flake8-pytest - # flake8-simplify - # flake8-tidy-imports - # flake8-use-fstring - # flake8-walrus -flake8-absolute-import==1.0.0.2 - # via education-backend (pyproject.toml) -flake8-black==0.3.6 - # via education-backend (pyproject.toml) -flake8-bugbear==23.3.12 - # via education-backend (pyproject.toml) -flake8-cognitive-complexity==0.1.0 - # via education-backend (pyproject.toml) -flake8-django==1.4 - # via education-backend (pyproject.toml) -flake8-eradicate==1.5.0 - # via education-backend (pyproject.toml) -flake8-fixme==1.1.1 - # via education-backend (pyproject.toml) -flake8-isort==6.1.0 - # via education-backend (pyproject.toml) -flake8-multiline-containers==0.0.19 - # via education-backend (pyproject.toml) -flake8-mutable==1.2.0 - # via education-backend (pyproject.toml) -flake8-pep3101==2.0.0 - # via education-backend (pyproject.toml) -flake8-pie==0.16.0 - # via education-backend (pyproject.toml) -flake8-plugin-utils==1.3.3 - # via flake8-pytest-style -flake8-print==5.0.0 - # via education-backend (pyproject.toml) -flake8-printf-formatting==1.1.2 - # via education-backend (pyproject.toml) -flake8-pyproject==1.2.3 - # via education-backend (pyproject.toml) -flake8-pytest==1.4 - # via education-backend (pyproject.toml) -flake8-pytest-style==1.7.2 - # via education-backend (pyproject.toml) -flake8-simplify==0.21.0 - # via education-backend (pyproject.toml) -flake8-tidy-imports==4.10.0 - # via education-backend (pyproject.toml) -flake8-todo==0.7 - # via education-backend (pyproject.toml) -flake8-use-fstring==1.4 - # via education-backend (pyproject.toml) -flake8-variables-names==0.0.6 - # via education-backend (pyproject.toml) -flake8-walrus==1.2.0 - # via education-backend (pyproject.toml) -freezegun==1.2.2 - # via - # education-backend (pyproject.toml) - # pytest-freezegun -h11==0.14.0 - # via httpcore -h2==4.1.0 - # via httpx -hpack==4.0.0 - # via h2 -httpcore==0.18.0 - # via httpx -httpx[http2]==0.25.0 - # via - # education-backend (pyproject.toml) - # respx -hyperframe==6.0.1 - # via h2 -idna==3.4 - # via - # anyio - # httpx - # requests -inflection==0.5.1 - # via drf-spectacular -iniconfig==2.0.0 - # via pytest -ipython==8.16.1 - # via education-backend (pyproject.toml) -isort==5.12.0 - # via flake8-isort -jedi==0.19.1 - # via - # education-backend (pyproject.toml) - # ipython -jmespath==1.0.1 - # via - # boto3 - # botocore -jsonschema==4.19.1 - # via drf-spectacular -jsonschema-specifications==2023.7.1 - # via jsonschema -kombu==5.3.1 - # via celery -lazy-object-proxy==1.9.0 - # via astroid -matplotlib-inline==0.1.6 - # via ipython -mccabe==0.7.0 - # via flake8 -mixer==7.2.2 - # via education-backend (pyproject.toml) -mypy==1.6.0 - # via - # django-stubs - # djangorestframework-stubs - # education-backend (pyproject.toml) -mypy-extensions==1.0.0 - # via - # black - # mypy -packaging==23.2 - # via - # black - # pytest -parso==0.8.3 - # via jedi -pathspec==0.11.2 - # via black -pexpect==4.8.0 - # via ipython -pickleshare==0.7.5 - # via ipython -pillow==10.1.0 - # via education-backend (pyproject.toml) -platformdirs==3.11.0 - # via black -pluggy==1.3.0 - # via pytest -prompt-toolkit==3.0.39 - # via - # click-repl - # ipython -psycopg2-binary==2.9.9 - # via education-backend (pyproject.toml) -ptyprocess==0.7.0 - # via pexpect -pure-eval==0.2.2 - # via stack-data -py==1.11.0 - # via retry -pycodestyle==2.9.1 - # via - # flake8 - # flake8-print - # flake8-todo -pycparser==2.21 - # via cffi -pyflakes==2.5.0 - # via - # autoflake - # flake8 -pygments==2.16.1 - # via ipython -pyjwt[crypto]==2.8.0 - # via - # drf-jwt - # education-backend (pyproject.toml) -pytest==7.4.2 - # via - # pytest-cov - # pytest-deadfixtures - # pytest-django - # pytest-env - # pytest-freezegun - # pytest-mock - # pytest-randomly - # pytest-repeat - # pytest-xdist -pytest-cov==4.1.0 - # via education-backend (pyproject.toml) -pytest-deadfixtures==2.2.1 - # via education-backend (pyproject.toml) -pytest-django==4.5.2 - # via education-backend (pyproject.toml) -pytest-env==1.0.1 - # via education-backend (pyproject.toml) -pytest-freezegun==0.4.2 - # via education-backend (pyproject.toml) -pytest-mock==3.11.1 - # via education-backend (pyproject.toml) -pytest-randomly==3.15.0 - # via education-backend (pyproject.toml) -pytest-repeat==0.9.3 - # via education-backend (pyproject.toml) -pytest-xdist==3.3.1 - # via education-backend (pyproject.toml) -python-dateutil==2.8.2 - # via - # botocore - # faker - # freezegun -pytz==2023.3.post1 - # via - # celery - # djangorestframework -pyyaml==6.0.1 - # via drf-spectacular -redis==5.0.1 - # via education-backend (pyproject.toml) -referencing==0.30.2 - # via - # jsonschema - # jsonschema-specifications -requests==2.31.0 - # via - # django-anymail - # django-healthchecks - # djangorestframework-stubs - # stripe -respx==0.20.2 - # via education-backend (pyproject.toml) -retry==0.9.2 - # via education-backend (pyproject.toml) -rpds-py==0.10.6 - # via - # jsonschema - # referencing -s3transfer==0.6.2 - # via boto3 -sentry-sdk==1.31.0 - # via education-backend (pyproject.toml) -shortuuid==1.0.11 - # via education-backend (pyproject.toml) -simplejson==3.19.2 - # via education-backend (pyproject.toml) -six==1.16.0 - # via - # asttokens - # bleach - # django-prettyjson - # python-dateutil -sniffio==1.3.0 - # via - # anyio - # httpcore - # httpx -sqlparse==0.4.4 - # via - # django - # django-debug-toolbar -stack-data==0.6.3 - # via ipython -standardjson==0.3.1 - # via django-prettyjson -stripe==6.7.0 - # via education-backend (pyproject.toml) -traitlets==5.11.2 - # via - # ipython - # matplotlib-inline -types-awscrt==0.19.3 - # via botocore-stubs -types-babel==2.11.0.15 - # via education-backend (pyproject.toml) -types-bleach==6.1.0.0 - # via education-backend (pyproject.toml) -types-freezegun==1.1.10 - # via education-backend (pyproject.toml) -types-markdown==3.5.0.0 - # via education-backend (pyproject.toml) -types-pillow==10.0.0.3 - # via education-backend (pyproject.toml) -types-pytz==2023.3.1.1 - # via - # django-stubs - # types-babel -types-pyyaml==6.0.12.12 - # via - # django-stubs - # djangorestframework-stubs -types-requests==2.31.0.6 - # via djangorestframework-stubs -types-retry==0.9.9.4 - # via education-backend (pyproject.toml) -types-s3transfer==0.7.0 - # via boto3-stubs -types-setuptools==68.2.0.0 - # via types-babel -types-simplejson==3.19.0.2 - # via education-backend (pyproject.toml) -types-stripe==3.5.2.14 - # via education-backend (pyproject.toml) -types-urllib3==1.26.25.14 - # via types-requests -typing-extensions==4.8.0 - # via - # django-stubs - # django-stubs-ext - # djangorestframework-stubs - # flake8-pie - # mypy -uritemplate==4.1.1 - # via drf-spectacular -urllib3==1.26.18 - # via - # botocore - # django-anymail - # education-backend (pyproject.toml) - # requests - # sentry-sdk -vine==5.0.0 - # via - # amqp - # celery - # kombu -wcwidth==0.2.8 - # via prompt-toolkit -webencodings==0.5.1 - # via bleach -whitenoise==6.5.0 - # via education-backend (pyproject.toml) -wrapt==1.15.0 - # via astroid - -# The following packages are considered to be unsafe in a requirements file: -# setuptools diff --git a/docker-compose.yml b/docker-compose.yml index f25072a9c0c..004f385c3eb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,7 +12,7 @@ services: notion-middleware: image: ghcr.io/tough-dev-school/notion-middleware - env_file: ".env" + env_file: "src/core/.env" ports: - 8001:8000 diff --git a/src/mypy.ini b/mypy.ini similarity index 93% rename from src/mypy.ini rename to mypy.ini index 14c5d39f801..1b516ab9c93 100644 --- a/src/mypy.ini +++ b/mypy.ini @@ -1,6 +1,6 @@ [mypy] python_version = 3.11 -files = . +mypy_path = src namespace_packages = on explicit_package_bases = on warn_no_return = off @@ -21,10 +21,10 @@ plugins = exclude = .*\/migrations\/.* [mypy.plugins.django-stubs] -django_settings_module = "app.settings" +django_settings_module = "core.settings" strict_settings = false -[mypy-app.test.*] +[mypy-core.test.*] disallow_untyped_defs = off [mypy-*.tests.*] @@ -39,7 +39,7 @@ disallow_untyped_defs = off [mypy-*.management.*] disallow_untyped_defs = off -[mypy-app.validators] +[mypy-core.validators] no_implicit_reexport = off [mypy-anymail.*] diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 00000000000..7863f4bdd29 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,3980 @@ +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. + +[[package]] +name = "amqp" +version = "5.1.1" +description = "Low-level AMQP client for Python (fork of amqplib)." +optional = false +python-versions = ">=3.6" +files = [ + {file = "amqp-5.1.1-py3-none-any.whl", hash = "sha256:6f0956d2c23d8fa6e7691934d8c3930eadb44972cbbd1a7ae3a520f735d43359"}, + {file = "amqp-5.1.1.tar.gz", hash = "sha256:2c1b13fecc0893e946c65cbd5f36427861cffa4ea2201d8f6fca22e2a373b5e2"}, +] + +[package.dependencies] +vine = ">=5.0.0" + +[[package]] +name = "anyio" +version = "4.0.0" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +optional = false +python-versions = ">=3.8" +files = [ + {file = "anyio-4.0.0-py3-none-any.whl", hash = "sha256:cfdb2b588b9fc25ede96d8db56ed50848b0b649dca3dd1df0b11f683bb9e0b5f"}, + {file = "anyio-4.0.0.tar.gz", hash = "sha256:f7ed51751b2c2add651e5747c891b47e26d2a21be5d32d9311dfe9692f3e5d7a"}, +] + +[package.dependencies] +idna = ">=2.8" +sniffio = ">=1.1" + +[package.extras] +doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (>=0.22)"] + +[[package]] +name = "appnope" +version = "0.1.3" +description = "Disable App Nap on macOS >= 10.9" +optional = false +python-versions = "*" +files = [ + {file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"}, + {file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"}, +] + +[[package]] +name = "asgiref" +version = "3.7.2" +description = "ASGI specs, helper code, and adapters" +optional = false +python-versions = ">=3.7" +files = [ + {file = "asgiref-3.7.2-py3-none-any.whl", hash = "sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e"}, + {file = "asgiref-3.7.2.tar.gz", hash = "sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed"}, +] + +[package.extras] +tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] + +[[package]] +name = "astor" +version = "0.8.1" +description = "Read/rewrite/write Python ASTs" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +files = [ + {file = "astor-0.8.1-py2.py3-none-any.whl", hash = "sha256:070a54e890cefb5b3739d19f30f5a5ec840ffc9c50ffa7d23cc9fc1a38ebbfc5"}, + {file = "astor-0.8.1.tar.gz", hash = "sha256:6a6effda93f4e1ce9f618779b2dd1d9d84f1e32812c23a29b3fff6fd7f63fa5e"}, +] + +[[package]] +name = "astroid" +version = "2.15.8" +description = "An abstract syntax tree for Python with inference support." +optional = false +python-versions = ">=3.7.2" +files = [ + {file = "astroid-2.15.8-py3-none-any.whl", hash = "sha256:1aa149fc5c6589e3d0ece885b4491acd80af4f087baafa3fb5203b113e68cd3c"}, + {file = "astroid-2.15.8.tar.gz", hash = "sha256:6c107453dffee9055899705de3c9ead36e74119cee151e5a9aaf7f0b0e020a6a"}, +] + +[package.dependencies] +lazy-object-proxy = ">=1.4.0" +wrapt = {version = ">=1.14,<2", markers = "python_version >= \"3.11\""} + +[[package]] +name = "asttokens" +version = "2.4.0" +description = "Annotate AST trees with source code positions" +optional = false +python-versions = "*" +files = [ + {file = "asttokens-2.4.0-py2.py3-none-any.whl", hash = "sha256:cf8fc9e61a86461aa9fb161a14a0841a03c405fa829ac6b202670b3495d2ce69"}, + {file = "asttokens-2.4.0.tar.gz", hash = "sha256:2e0171b991b2c959acc6c49318049236844a5da1d65ba2672c4880c1c894834e"}, +] + +[package.dependencies] +six = ">=1.12.0" + +[package.extras] +test = ["astroid", "pytest"] + +[[package]] +name = "async-timeout" +version = "4.0.3" +description = "Timeout context manager for asyncio programs" +optional = false +python-versions = ">=3.7" +files = [ + {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, + {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, +] + +[[package]] +name = "attrs" +version = "23.1.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.7" +files = [ + {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, + {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, +] + +[package.extras] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[docs,tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] + +[[package]] +name = "autoflake" +version = "2.2.1" +description = "Removes unused imports and unused variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "autoflake-2.2.1-py3-none-any.whl", hash = "sha256:265cde0a43c1f44ecfb4f30d95b0437796759d07be7706a2f70e4719234c0f79"}, + {file = "autoflake-2.2.1.tar.gz", hash = "sha256:62b7b6449a692c3c9b0c916919bbc21648da7281e8506bcf8d3f8280e431ebc1"}, +] + +[package.dependencies] +pyflakes = ">=3.0.0" + +[[package]] +name = "babel" +version = "2.13.1" +description = "Internationalization utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "Babel-2.13.1-py3-none-any.whl", hash = "sha256:7077a4984b02b6727ac10f1f7294484f737443d7e2e66c5e4380e41a3ae0b4ed"}, + {file = "Babel-2.13.1.tar.gz", hash = "sha256:33e0952d7dd6374af8dbf6768cc4ddf3ccfefc244f9986d4074704f2fbd18900"}, +] + +[package.extras] +dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] + +[[package]] +name = "backcall" +version = "0.2.0" +description = "Specifications for callback functions passed in to an API" +optional = false +python-versions = "*" +files = [ + {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, + {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, +] + +[[package]] +name = "bcrypt" +version = "4.0.1" +description = "Modern password hashing for your software and your servers" +optional = false +python-versions = ">=3.6" +files = [ + {file = "bcrypt-4.0.1-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:b1023030aec778185a6c16cf70f359cbb6e0c289fd564a7cfa29e727a1c38f8f"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:08d2947c490093a11416df18043c27abe3921558d2c03e2076ccb28a116cb6d0"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0eaa47d4661c326bfc9d08d16debbc4edf78778e6aaba29c1bc7ce67214d4410"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae88eca3024bb34bb3430f964beab71226e761f51b912de5133470b649d82344"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:a522427293d77e1c29e303fc282e2d71864579527a04ddcfda6d4f8396c6c36a"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:fbdaec13c5105f0c4e5c52614d04f0bca5f5af007910daa8b6b12095edaa67b3"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:ca3204d00d3cb2dfed07f2d74a25f12fc12f73e606fcaa6975d1f7ae69cacbb2"}, + {file = "bcrypt-4.0.1-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:089098effa1bc35dc055366740a067a2fc76987e8ec75349eb9484061c54f535"}, + {file = "bcrypt-4.0.1-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:e9a51bbfe7e9802b5f3508687758b564069ba937748ad7b9e890086290d2f79e"}, + {file = "bcrypt-4.0.1-cp36-abi3-win32.whl", hash = "sha256:2caffdae059e06ac23fce178d31b4a702f2a3264c20bfb5ff541b338194d8fab"}, + {file = "bcrypt-4.0.1-cp36-abi3-win_amd64.whl", hash = "sha256:8a68f4341daf7522fe8d73874de8906f3a339048ba406be6ddc1b3ccb16fc0d9"}, + {file = "bcrypt-4.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf4fa8b2ca74381bb5442c089350f09a3f17797829d958fad058d6e44d9eb83c"}, + {file = "bcrypt-4.0.1-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:67a97e1c405b24f19d08890e7ae0c4f7ce1e56a712a016746c8b2d7732d65d4b"}, + {file = "bcrypt-4.0.1-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b3b85202d95dd568efcb35b53936c5e3b3600c7cdcc6115ba461df3a8e89f38d"}, + {file = "bcrypt-4.0.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbb03eec97496166b704ed663a53680ab57c5084b2fc98ef23291987b525cb7d"}, + {file = "bcrypt-4.0.1-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:5ad4d32a28b80c5fa6671ccfb43676e8c1cc232887759d1cd7b6f56ea4355215"}, + {file = "bcrypt-4.0.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b57adba8a1444faf784394de3436233728a1ecaeb6e07e8c22c8848f179b893c"}, + {file = "bcrypt-4.0.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:705b2cea8a9ed3d55b4491887ceadb0106acf7c6387699fca771af56b1cdeeda"}, + {file = "bcrypt-4.0.1-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:2b3ac11cf45161628f1f3733263e63194f22664bf4d0c0f3ab34099c02134665"}, + {file = "bcrypt-4.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3100851841186c25f127731b9fa11909ab7b1df6fc4b9f8353f4f1fd952fbf71"}, + {file = "bcrypt-4.0.1.tar.gz", hash = "sha256:27d375903ac8261cfe4047f6709d16f7d18d39b1ec92aaf72af989552a650ebd"}, +] + +[package.extras] +tests = ["pytest (>=3.2.1,!=3.3.0)"] +typecheck = ["mypy"] + +[[package]] +name = "billiard" +version = "3.6.4.0" +description = "Python multiprocessing fork with improvements and bugfixes" +optional = false +python-versions = "*" +files = [ + {file = "billiard-3.6.4.0-py3-none-any.whl", hash = "sha256:87103ea78fa6ab4d5c751c4909bcff74617d985de7fa8b672cf8618afd5a875b"}, + {file = "billiard-3.6.4.0.tar.gz", hash = "sha256:299de5a8da28a783d51b197d496bef4f1595dd023a93a4f59dde1886ae905547"}, +] + +[[package]] +name = "black" +version = "23.10.1" +description = "The uncompromising code formatter." +optional = false +python-versions = ">=3.8" +files = [ + {file = "black-23.10.1-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:ec3f8e6234c4e46ff9e16d9ae96f4ef69fa328bb4ad08198c8cee45bb1f08c69"}, + {file = "black-23.10.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:1b917a2aa020ca600483a7b340c165970b26e9029067f019e3755b56e8dd5916"}, + {file = "black-23.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c74de4c77b849e6359c6f01987e94873c707098322b91490d24296f66d067dc"}, + {file = "black-23.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:7b4d10b0f016616a0d93d24a448100adf1699712fb7a4efd0e2c32bbb219b173"}, + {file = "black-23.10.1-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b15b75fc53a2fbcac8a87d3e20f69874d161beef13954747e053bca7a1ce53a0"}, + {file = "black-23.10.1-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:e293e4c2f4a992b980032bbd62df07c1bcff82d6964d6c9496f2cd726e246ace"}, + {file = "black-23.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d56124b7a61d092cb52cce34182a5280e160e6aff3137172a68c2c2c4b76bcb"}, + {file = "black-23.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:3f157a8945a7b2d424da3335f7ace89c14a3b0625e6593d21139c2d8214d55ce"}, + {file = "black-23.10.1-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:cfcce6f0a384d0da692119f2d72d79ed07c7159879d0bb1bb32d2e443382bf3a"}, + {file = "black-23.10.1-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:33d40f5b06be80c1bbce17b173cda17994fbad096ce60eb22054da021bf933d1"}, + {file = "black-23.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:840015166dbdfbc47992871325799fd2dc0dcf9395e401ada6d88fe11498abad"}, + {file = "black-23.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:037e9b4664cafda5f025a1728c50a9e9aedb99a759c89f760bd83730e76ba884"}, + {file = "black-23.10.1-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:7cb5936e686e782fddb1c73f8aa6f459e1ad38a6a7b0e54b403f1f05a1507ee9"}, + {file = "black-23.10.1-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:7670242e90dc129c539e9ca17665e39a146a761e681805c54fbd86015c7c84f7"}, + {file = "black-23.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ed45ac9a613fb52dad3b61c8dea2ec9510bf3108d4db88422bacc7d1ba1243d"}, + {file = "black-23.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:6d23d7822140e3fef190734216cefb262521789367fbdc0b3f22af6744058982"}, + {file = "black-23.10.1-py3-none-any.whl", hash = "sha256:d431e6739f727bb2e0495df64a6c7a5310758e87505f5f8cde9ff6c0f2d7e4fe"}, + {file = "black-23.10.1.tar.gz", hash = "sha256:1f8ce316753428ff68749c65a5f7844631aa18c8679dfd3ca9dc1a289979c258"}, +] + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "bleach" +version = "6.1.0" +description = "An easy safelist-based HTML-sanitizing tool." +optional = false +python-versions = ">=3.8" +files = [ + {file = "bleach-6.1.0-py3-none-any.whl", hash = "sha256:3225f354cfc436b9789c66c4ee030194bee0568fbf9cbdad3bc8b5c26c5f12b6"}, + {file = "bleach-6.1.0.tar.gz", hash = "sha256:0a31f1837963c41d46bbf1331b8778e1308ea0791db03cc4e7357b97cf42a8fe"}, +] + +[package.dependencies] +six = ">=1.9.0" +webencodings = "*" + +[package.extras] +css = ["tinycss2 (>=1.1.0,<1.3)"] + +[[package]] +name = "boto3" +version = "1.28.70" +description = "The AWS SDK for Python" +optional = false +python-versions = ">= 3.7" +files = [ + {file = "boto3-1.28.70-py3-none-any.whl", hash = "sha256:22ec3b54801c81746657827c7b1c4a3b2e4cfa7c21be3b96218d32e9390ee5eb"}, + {file = "boto3-1.28.70.tar.gz", hash = "sha256:89002e1d8411c7c54110f9f8fc4a11d57d6d7977c0cb4ba064887ca5d4c788f7"}, +] + +[package.dependencies] +botocore = ">=1.31.70,<1.32.0" +jmespath = ">=0.7.1,<2.0.0" +s3transfer = ">=0.7.0,<0.8.0" + +[package.extras] +crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] + +[[package]] +name = "boto3-stubs" +version = "1.28.70" +description = "Type annotations for boto3 1.28.70 generated with mypy-boto3-builder 7.19.0" +optional = false +python-versions = ">=3.7" +files = [ + {file = "boto3-stubs-1.28.70.tar.gz", hash = "sha256:0c67fd217c9fd0d5688504aa64c5b760bccca9886ce05d675bbc613b568cba28"}, + {file = "boto3_stubs-1.28.70-py3-none-any.whl", hash = "sha256:6d50983e2535220f3da911ac43e3fd13347d644474b3ebe694c4158c75a3df7f"}, +] + +[package.dependencies] +botocore-stubs = "*" +types-s3transfer = "*" +typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.12\""} + +[package.extras] +accessanalyzer = ["mypy-boto3-accessanalyzer (>=1.28.0,<1.29.0)"] +account = ["mypy-boto3-account (>=1.28.0,<1.29.0)"] +acm = ["mypy-boto3-acm (>=1.28.0,<1.29.0)"] +acm-pca = ["mypy-boto3-acm-pca (>=1.28.0,<1.29.0)"] +alexaforbusiness = ["mypy-boto3-alexaforbusiness (>=1.28.0,<1.29.0)"] +all = ["mypy-boto3-accessanalyzer (>=1.28.0,<1.29.0)", "mypy-boto3-account (>=1.28.0,<1.29.0)", "mypy-boto3-acm (>=1.28.0,<1.29.0)", "mypy-boto3-acm-pca (>=1.28.0,<1.29.0)", "mypy-boto3-alexaforbusiness (>=1.28.0,<1.29.0)", "mypy-boto3-amp (>=1.28.0,<1.29.0)", "mypy-boto3-amplify (>=1.28.0,<1.29.0)", "mypy-boto3-amplifybackend (>=1.28.0,<1.29.0)", "mypy-boto3-amplifyuibuilder (>=1.28.0,<1.29.0)", "mypy-boto3-apigateway (>=1.28.0,<1.29.0)", "mypy-boto3-apigatewaymanagementapi (>=1.28.0,<1.29.0)", "mypy-boto3-apigatewayv2 (>=1.28.0,<1.29.0)", "mypy-boto3-appconfig (>=1.28.0,<1.29.0)", "mypy-boto3-appconfigdata (>=1.28.0,<1.29.0)", "mypy-boto3-appfabric (>=1.28.0,<1.29.0)", "mypy-boto3-appflow (>=1.28.0,<1.29.0)", "mypy-boto3-appintegrations (>=1.28.0,<1.29.0)", "mypy-boto3-application-autoscaling (>=1.28.0,<1.29.0)", "mypy-boto3-application-insights (>=1.28.0,<1.29.0)", "mypy-boto3-applicationcostprofiler (>=1.28.0,<1.29.0)", "mypy-boto3-appmesh (>=1.28.0,<1.29.0)", "mypy-boto3-apprunner (>=1.28.0,<1.29.0)", "mypy-boto3-appstream (>=1.28.0,<1.29.0)", "mypy-boto3-appsync (>=1.28.0,<1.29.0)", "mypy-boto3-arc-zonal-shift (>=1.28.0,<1.29.0)", "mypy-boto3-athena (>=1.28.0,<1.29.0)", "mypy-boto3-auditmanager (>=1.28.0,<1.29.0)", "mypy-boto3-autoscaling (>=1.28.0,<1.29.0)", "mypy-boto3-autoscaling-plans (>=1.28.0,<1.29.0)", "mypy-boto3-backup (>=1.28.0,<1.29.0)", "mypy-boto3-backup-gateway (>=1.28.0,<1.29.0)", "mypy-boto3-backupstorage (>=1.28.0,<1.29.0)", "mypy-boto3-batch (>=1.28.0,<1.29.0)", "mypy-boto3-bedrock (>=1.28.0,<1.29.0)", "mypy-boto3-bedrock-runtime (>=1.28.0,<1.29.0)", "mypy-boto3-billingconductor (>=1.28.0,<1.29.0)", "mypy-boto3-braket (>=1.28.0,<1.29.0)", "mypy-boto3-budgets (>=1.28.0,<1.29.0)", "mypy-boto3-ce (>=1.28.0,<1.29.0)", "mypy-boto3-chime (>=1.28.0,<1.29.0)", "mypy-boto3-chime-sdk-identity (>=1.28.0,<1.29.0)", "mypy-boto3-chime-sdk-media-pipelines (>=1.28.0,<1.29.0)", "mypy-boto3-chime-sdk-meetings (>=1.28.0,<1.29.0)", "mypy-boto3-chime-sdk-messaging (>=1.28.0,<1.29.0)", "mypy-boto3-chime-sdk-voice (>=1.28.0,<1.29.0)", "mypy-boto3-cleanrooms (>=1.28.0,<1.29.0)", "mypy-boto3-cloud9 (>=1.28.0,<1.29.0)", "mypy-boto3-cloudcontrol (>=1.28.0,<1.29.0)", "mypy-boto3-clouddirectory (>=1.28.0,<1.29.0)", "mypy-boto3-cloudformation (>=1.28.0,<1.29.0)", "mypy-boto3-cloudfront (>=1.28.0,<1.29.0)", "mypy-boto3-cloudhsm (>=1.28.0,<1.29.0)", "mypy-boto3-cloudhsmv2 (>=1.28.0,<1.29.0)", "mypy-boto3-cloudsearch (>=1.28.0,<1.29.0)", "mypy-boto3-cloudsearchdomain (>=1.28.0,<1.29.0)", "mypy-boto3-cloudtrail (>=1.28.0,<1.29.0)", "mypy-boto3-cloudtrail-data (>=1.28.0,<1.29.0)", "mypy-boto3-cloudwatch (>=1.28.0,<1.29.0)", "mypy-boto3-codeartifact (>=1.28.0,<1.29.0)", "mypy-boto3-codebuild (>=1.28.0,<1.29.0)", "mypy-boto3-codecatalyst (>=1.28.0,<1.29.0)", "mypy-boto3-codecommit (>=1.28.0,<1.29.0)", "mypy-boto3-codedeploy (>=1.28.0,<1.29.0)", "mypy-boto3-codeguru-reviewer (>=1.28.0,<1.29.0)", "mypy-boto3-codeguru-security (>=1.28.0,<1.29.0)", "mypy-boto3-codeguruprofiler (>=1.28.0,<1.29.0)", "mypy-boto3-codepipeline (>=1.28.0,<1.29.0)", "mypy-boto3-codestar (>=1.28.0,<1.29.0)", "mypy-boto3-codestar-connections (>=1.28.0,<1.29.0)", "mypy-boto3-codestar-notifications (>=1.28.0,<1.29.0)", "mypy-boto3-cognito-identity (>=1.28.0,<1.29.0)", "mypy-boto3-cognito-idp (>=1.28.0,<1.29.0)", "mypy-boto3-cognito-sync (>=1.28.0,<1.29.0)", "mypy-boto3-comprehend (>=1.28.0,<1.29.0)", "mypy-boto3-comprehendmedical (>=1.28.0,<1.29.0)", "mypy-boto3-compute-optimizer (>=1.28.0,<1.29.0)", "mypy-boto3-config (>=1.28.0,<1.29.0)", "mypy-boto3-connect (>=1.28.0,<1.29.0)", "mypy-boto3-connect-contact-lens (>=1.28.0,<1.29.0)", "mypy-boto3-connectcampaigns (>=1.28.0,<1.29.0)", "mypy-boto3-connectcases (>=1.28.0,<1.29.0)", "mypy-boto3-connectparticipant (>=1.28.0,<1.29.0)", "mypy-boto3-controltower (>=1.28.0,<1.29.0)", "mypy-boto3-cur (>=1.28.0,<1.29.0)", "mypy-boto3-customer-profiles (>=1.28.0,<1.29.0)", "mypy-boto3-databrew (>=1.28.0,<1.29.0)", "mypy-boto3-dataexchange (>=1.28.0,<1.29.0)", "mypy-boto3-datapipeline (>=1.28.0,<1.29.0)", "mypy-boto3-datasync (>=1.28.0,<1.29.0)", "mypy-boto3-datazone (>=1.28.0,<1.29.0)", "mypy-boto3-dax (>=1.28.0,<1.29.0)", "mypy-boto3-detective (>=1.28.0,<1.29.0)", "mypy-boto3-devicefarm (>=1.28.0,<1.29.0)", "mypy-boto3-devops-guru (>=1.28.0,<1.29.0)", "mypy-boto3-directconnect (>=1.28.0,<1.29.0)", "mypy-boto3-discovery (>=1.28.0,<1.29.0)", "mypy-boto3-dlm (>=1.28.0,<1.29.0)", "mypy-boto3-dms (>=1.28.0,<1.29.0)", "mypy-boto3-docdb (>=1.28.0,<1.29.0)", "mypy-boto3-docdb-elastic (>=1.28.0,<1.29.0)", "mypy-boto3-drs (>=1.28.0,<1.29.0)", "mypy-boto3-ds (>=1.28.0,<1.29.0)", "mypy-boto3-dynamodb (>=1.28.0,<1.29.0)", "mypy-boto3-dynamodbstreams (>=1.28.0,<1.29.0)", "mypy-boto3-ebs (>=1.28.0,<1.29.0)", "mypy-boto3-ec2 (>=1.28.0,<1.29.0)", "mypy-boto3-ec2-instance-connect (>=1.28.0,<1.29.0)", "mypy-boto3-ecr (>=1.28.0,<1.29.0)", "mypy-boto3-ecr-public (>=1.28.0,<1.29.0)", "mypy-boto3-ecs (>=1.28.0,<1.29.0)", "mypy-boto3-efs (>=1.28.0,<1.29.0)", "mypy-boto3-eks (>=1.28.0,<1.29.0)", "mypy-boto3-elastic-inference (>=1.28.0,<1.29.0)", "mypy-boto3-elasticache (>=1.28.0,<1.29.0)", "mypy-boto3-elasticbeanstalk (>=1.28.0,<1.29.0)", "mypy-boto3-elastictranscoder (>=1.28.0,<1.29.0)", "mypy-boto3-elb (>=1.28.0,<1.29.0)", "mypy-boto3-elbv2 (>=1.28.0,<1.29.0)", "mypy-boto3-emr (>=1.28.0,<1.29.0)", "mypy-boto3-emr-containers (>=1.28.0,<1.29.0)", "mypy-boto3-emr-serverless (>=1.28.0,<1.29.0)", "mypy-boto3-entityresolution (>=1.28.0,<1.29.0)", "mypy-boto3-es (>=1.28.0,<1.29.0)", "mypy-boto3-events (>=1.28.0,<1.29.0)", "mypy-boto3-evidently (>=1.28.0,<1.29.0)", "mypy-boto3-finspace (>=1.28.0,<1.29.0)", "mypy-boto3-finspace-data (>=1.28.0,<1.29.0)", "mypy-boto3-firehose (>=1.28.0,<1.29.0)", "mypy-boto3-fis (>=1.28.0,<1.29.0)", "mypy-boto3-fms (>=1.28.0,<1.29.0)", "mypy-boto3-forecast (>=1.28.0,<1.29.0)", "mypy-boto3-forecastquery (>=1.28.0,<1.29.0)", "mypy-boto3-frauddetector (>=1.28.0,<1.29.0)", "mypy-boto3-fsx (>=1.28.0,<1.29.0)", "mypy-boto3-gamelift (>=1.28.0,<1.29.0)", "mypy-boto3-glacier (>=1.28.0,<1.29.0)", "mypy-boto3-globalaccelerator (>=1.28.0,<1.29.0)", "mypy-boto3-glue (>=1.28.0,<1.29.0)", "mypy-boto3-grafana (>=1.28.0,<1.29.0)", "mypy-boto3-greengrass (>=1.28.0,<1.29.0)", "mypy-boto3-greengrassv2 (>=1.28.0,<1.29.0)", "mypy-boto3-groundstation (>=1.28.0,<1.29.0)", "mypy-boto3-guardduty (>=1.28.0,<1.29.0)", "mypy-boto3-health (>=1.28.0,<1.29.0)", "mypy-boto3-healthlake (>=1.28.0,<1.29.0)", "mypy-boto3-honeycode (>=1.28.0,<1.29.0)", "mypy-boto3-iam (>=1.28.0,<1.29.0)", "mypy-boto3-identitystore (>=1.28.0,<1.29.0)", "mypy-boto3-imagebuilder (>=1.28.0,<1.29.0)", "mypy-boto3-importexport (>=1.28.0,<1.29.0)", "mypy-boto3-inspector (>=1.28.0,<1.29.0)", "mypy-boto3-inspector2 (>=1.28.0,<1.29.0)", "mypy-boto3-internetmonitor (>=1.28.0,<1.29.0)", "mypy-boto3-iot (>=1.28.0,<1.29.0)", "mypy-boto3-iot-data (>=1.28.0,<1.29.0)", "mypy-boto3-iot-jobs-data (>=1.28.0,<1.29.0)", "mypy-boto3-iot-roborunner (>=1.28.0,<1.29.0)", "mypy-boto3-iot1click-devices (>=1.28.0,<1.29.0)", "mypy-boto3-iot1click-projects (>=1.28.0,<1.29.0)", "mypy-boto3-iotanalytics (>=1.28.0,<1.29.0)", "mypy-boto3-iotdeviceadvisor (>=1.28.0,<1.29.0)", "mypy-boto3-iotevents (>=1.28.0,<1.29.0)", "mypy-boto3-iotevents-data (>=1.28.0,<1.29.0)", "mypy-boto3-iotfleethub (>=1.28.0,<1.29.0)", "mypy-boto3-iotfleetwise (>=1.28.0,<1.29.0)", "mypy-boto3-iotsecuretunneling (>=1.28.0,<1.29.0)", "mypy-boto3-iotsitewise (>=1.28.0,<1.29.0)", "mypy-boto3-iotthingsgraph (>=1.28.0,<1.29.0)", "mypy-boto3-iottwinmaker (>=1.28.0,<1.29.0)", "mypy-boto3-iotwireless (>=1.28.0,<1.29.0)", "mypy-boto3-ivs (>=1.28.0,<1.29.0)", "mypy-boto3-ivs-realtime (>=1.28.0,<1.29.0)", "mypy-boto3-ivschat (>=1.28.0,<1.29.0)", "mypy-boto3-kafka (>=1.28.0,<1.29.0)", "mypy-boto3-kafkaconnect (>=1.28.0,<1.29.0)", "mypy-boto3-kendra (>=1.28.0,<1.29.0)", "mypy-boto3-kendra-ranking (>=1.28.0,<1.29.0)", "mypy-boto3-keyspaces (>=1.28.0,<1.29.0)", "mypy-boto3-kinesis (>=1.28.0,<1.29.0)", "mypy-boto3-kinesis-video-archived-media (>=1.28.0,<1.29.0)", "mypy-boto3-kinesis-video-media (>=1.28.0,<1.29.0)", "mypy-boto3-kinesis-video-signaling (>=1.28.0,<1.29.0)", "mypy-boto3-kinesis-video-webrtc-storage (>=1.28.0,<1.29.0)", "mypy-boto3-kinesisanalytics (>=1.28.0,<1.29.0)", "mypy-boto3-kinesisanalyticsv2 (>=1.28.0,<1.29.0)", "mypy-boto3-kinesisvideo (>=1.28.0,<1.29.0)", "mypy-boto3-kms (>=1.28.0,<1.29.0)", "mypy-boto3-lakeformation (>=1.28.0,<1.29.0)", "mypy-boto3-lambda (>=1.28.0,<1.29.0)", "mypy-boto3-lex-models (>=1.28.0,<1.29.0)", "mypy-boto3-lex-runtime (>=1.28.0,<1.29.0)", "mypy-boto3-lexv2-models (>=1.28.0,<1.29.0)", "mypy-boto3-lexv2-runtime (>=1.28.0,<1.29.0)", "mypy-boto3-license-manager (>=1.28.0,<1.29.0)", "mypy-boto3-license-manager-linux-subscriptions (>=1.28.0,<1.29.0)", "mypy-boto3-license-manager-user-subscriptions (>=1.28.0,<1.29.0)", "mypy-boto3-lightsail (>=1.28.0,<1.29.0)", "mypy-boto3-location (>=1.28.0,<1.29.0)", "mypy-boto3-logs (>=1.28.0,<1.29.0)", "mypy-boto3-lookoutequipment (>=1.28.0,<1.29.0)", "mypy-boto3-lookoutmetrics (>=1.28.0,<1.29.0)", "mypy-boto3-lookoutvision (>=1.28.0,<1.29.0)", "mypy-boto3-m2 (>=1.28.0,<1.29.0)", "mypy-boto3-machinelearning (>=1.28.0,<1.29.0)", "mypy-boto3-macie (>=1.28.0,<1.29.0)", "mypy-boto3-macie2 (>=1.28.0,<1.29.0)", "mypy-boto3-managedblockchain (>=1.28.0,<1.29.0)", "mypy-boto3-managedblockchain-query (>=1.28.0,<1.29.0)", "mypy-boto3-marketplace-catalog (>=1.28.0,<1.29.0)", "mypy-boto3-marketplace-entitlement (>=1.28.0,<1.29.0)", "mypy-boto3-marketplacecommerceanalytics (>=1.28.0,<1.29.0)", "mypy-boto3-mediaconnect (>=1.28.0,<1.29.0)", "mypy-boto3-mediaconvert (>=1.28.0,<1.29.0)", "mypy-boto3-medialive (>=1.28.0,<1.29.0)", "mypy-boto3-mediapackage (>=1.28.0,<1.29.0)", "mypy-boto3-mediapackage-vod (>=1.28.0,<1.29.0)", "mypy-boto3-mediapackagev2 (>=1.28.0,<1.29.0)", "mypy-boto3-mediastore (>=1.28.0,<1.29.0)", "mypy-boto3-mediastore-data (>=1.28.0,<1.29.0)", "mypy-boto3-mediatailor (>=1.28.0,<1.29.0)", "mypy-boto3-medical-imaging (>=1.28.0,<1.29.0)", "mypy-boto3-memorydb (>=1.28.0,<1.29.0)", "mypy-boto3-meteringmarketplace (>=1.28.0,<1.29.0)", "mypy-boto3-mgh (>=1.28.0,<1.29.0)", "mypy-boto3-mgn (>=1.28.0,<1.29.0)", "mypy-boto3-migration-hub-refactor-spaces (>=1.28.0,<1.29.0)", "mypy-boto3-migrationhub-config (>=1.28.0,<1.29.0)", "mypy-boto3-migrationhuborchestrator (>=1.28.0,<1.29.0)", "mypy-boto3-migrationhubstrategy (>=1.28.0,<1.29.0)", "mypy-boto3-mobile (>=1.28.0,<1.29.0)", "mypy-boto3-mq (>=1.28.0,<1.29.0)", "mypy-boto3-mturk (>=1.28.0,<1.29.0)", "mypy-boto3-mwaa (>=1.28.0,<1.29.0)", "mypy-boto3-neptune (>=1.28.0,<1.29.0)", "mypy-boto3-neptunedata (>=1.28.0,<1.29.0)", "mypy-boto3-network-firewall (>=1.28.0,<1.29.0)", "mypy-boto3-networkmanager (>=1.28.0,<1.29.0)", "mypy-boto3-nimble (>=1.28.0,<1.29.0)", "mypy-boto3-oam (>=1.28.0,<1.29.0)", "mypy-boto3-omics (>=1.28.0,<1.29.0)", "mypy-boto3-opensearch (>=1.28.0,<1.29.0)", "mypy-boto3-opensearchserverless (>=1.28.0,<1.29.0)", "mypy-boto3-opsworks (>=1.28.0,<1.29.0)", "mypy-boto3-opsworkscm (>=1.28.0,<1.29.0)", "mypy-boto3-organizations (>=1.28.0,<1.29.0)", "mypy-boto3-osis (>=1.28.0,<1.29.0)", "mypy-boto3-outposts (>=1.28.0,<1.29.0)", "mypy-boto3-panorama (>=1.28.0,<1.29.0)", "mypy-boto3-payment-cryptography (>=1.28.0,<1.29.0)", "mypy-boto3-payment-cryptography-data (>=1.28.0,<1.29.0)", "mypy-boto3-pca-connector-ad (>=1.28.0,<1.29.0)", "mypy-boto3-personalize (>=1.28.0,<1.29.0)", "mypy-boto3-personalize-events (>=1.28.0,<1.29.0)", "mypy-boto3-personalize-runtime (>=1.28.0,<1.29.0)", "mypy-boto3-pi (>=1.28.0,<1.29.0)", "mypy-boto3-pinpoint (>=1.28.0,<1.29.0)", "mypy-boto3-pinpoint-email (>=1.28.0,<1.29.0)", "mypy-boto3-pinpoint-sms-voice (>=1.28.0,<1.29.0)", "mypy-boto3-pinpoint-sms-voice-v2 (>=1.28.0,<1.29.0)", "mypy-boto3-pipes (>=1.28.0,<1.29.0)", "mypy-boto3-polly (>=1.28.0,<1.29.0)", "mypy-boto3-pricing (>=1.28.0,<1.29.0)", "mypy-boto3-privatenetworks (>=1.28.0,<1.29.0)", "mypy-boto3-proton (>=1.28.0,<1.29.0)", "mypy-boto3-qldb (>=1.28.0,<1.29.0)", "mypy-boto3-qldb-session (>=1.28.0,<1.29.0)", "mypy-boto3-quicksight (>=1.28.0,<1.29.0)", "mypy-boto3-ram (>=1.28.0,<1.29.0)", "mypy-boto3-rbin (>=1.28.0,<1.29.0)", "mypy-boto3-rds (>=1.28.0,<1.29.0)", "mypy-boto3-rds-data (>=1.28.0,<1.29.0)", "mypy-boto3-redshift (>=1.28.0,<1.29.0)", "mypy-boto3-redshift-data (>=1.28.0,<1.29.0)", "mypy-boto3-redshift-serverless (>=1.28.0,<1.29.0)", "mypy-boto3-rekognition (>=1.28.0,<1.29.0)", "mypy-boto3-resiliencehub (>=1.28.0,<1.29.0)", "mypy-boto3-resource-explorer-2 (>=1.28.0,<1.29.0)", "mypy-boto3-resource-groups (>=1.28.0,<1.29.0)", "mypy-boto3-resourcegroupstaggingapi (>=1.28.0,<1.29.0)", "mypy-boto3-robomaker (>=1.28.0,<1.29.0)", "mypy-boto3-rolesanywhere (>=1.28.0,<1.29.0)", "mypy-boto3-route53 (>=1.28.0,<1.29.0)", "mypy-boto3-route53-recovery-cluster (>=1.28.0,<1.29.0)", "mypy-boto3-route53-recovery-control-config (>=1.28.0,<1.29.0)", "mypy-boto3-route53-recovery-readiness (>=1.28.0,<1.29.0)", "mypy-boto3-route53domains (>=1.28.0,<1.29.0)", "mypy-boto3-route53resolver (>=1.28.0,<1.29.0)", "mypy-boto3-rum (>=1.28.0,<1.29.0)", "mypy-boto3-s3 (>=1.28.0,<1.29.0)", "mypy-boto3-s3control (>=1.28.0,<1.29.0)", "mypy-boto3-s3outposts (>=1.28.0,<1.29.0)", "mypy-boto3-sagemaker (>=1.28.0,<1.29.0)", "mypy-boto3-sagemaker-a2i-runtime (>=1.28.0,<1.29.0)", "mypy-boto3-sagemaker-edge (>=1.28.0,<1.29.0)", "mypy-boto3-sagemaker-featurestore-runtime (>=1.28.0,<1.29.0)", "mypy-boto3-sagemaker-geospatial (>=1.28.0,<1.29.0)", "mypy-boto3-sagemaker-metrics (>=1.28.0,<1.29.0)", "mypy-boto3-sagemaker-runtime (>=1.28.0,<1.29.0)", "mypy-boto3-savingsplans (>=1.28.0,<1.29.0)", "mypy-boto3-scheduler (>=1.28.0,<1.29.0)", "mypy-boto3-schemas (>=1.28.0,<1.29.0)", "mypy-boto3-sdb (>=1.28.0,<1.29.0)", "mypy-boto3-secretsmanager (>=1.28.0,<1.29.0)", "mypy-boto3-securityhub (>=1.28.0,<1.29.0)", "mypy-boto3-securitylake (>=1.28.0,<1.29.0)", "mypy-boto3-serverlessrepo (>=1.28.0,<1.29.0)", "mypy-boto3-service-quotas (>=1.28.0,<1.29.0)", "mypy-boto3-servicecatalog (>=1.28.0,<1.29.0)", "mypy-boto3-servicecatalog-appregistry (>=1.28.0,<1.29.0)", "mypy-boto3-servicediscovery (>=1.28.0,<1.29.0)", "mypy-boto3-ses (>=1.28.0,<1.29.0)", "mypy-boto3-sesv2 (>=1.28.0,<1.29.0)", "mypy-boto3-shield (>=1.28.0,<1.29.0)", "mypy-boto3-signer (>=1.28.0,<1.29.0)", "mypy-boto3-simspaceweaver (>=1.28.0,<1.29.0)", "mypy-boto3-sms (>=1.28.0,<1.29.0)", "mypy-boto3-sms-voice (>=1.28.0,<1.29.0)", "mypy-boto3-snow-device-management (>=1.28.0,<1.29.0)", "mypy-boto3-snowball (>=1.28.0,<1.29.0)", "mypy-boto3-sns (>=1.28.0,<1.29.0)", "mypy-boto3-sqs (>=1.28.0,<1.29.0)", "mypy-boto3-ssm (>=1.28.0,<1.29.0)", "mypy-boto3-ssm-contacts (>=1.28.0,<1.29.0)", "mypy-boto3-ssm-incidents (>=1.28.0,<1.29.0)", "mypy-boto3-ssm-sap (>=1.28.0,<1.29.0)", "mypy-boto3-sso (>=1.28.0,<1.29.0)", "mypy-boto3-sso-admin (>=1.28.0,<1.29.0)", "mypy-boto3-sso-oidc (>=1.28.0,<1.29.0)", "mypy-boto3-stepfunctions (>=1.28.0,<1.29.0)", "mypy-boto3-storagegateway (>=1.28.0,<1.29.0)", "mypy-boto3-sts (>=1.28.0,<1.29.0)", "mypy-boto3-support (>=1.28.0,<1.29.0)", "mypy-boto3-support-app (>=1.28.0,<1.29.0)", "mypy-boto3-swf (>=1.28.0,<1.29.0)", "mypy-boto3-synthetics (>=1.28.0,<1.29.0)", "mypy-boto3-textract (>=1.28.0,<1.29.0)", "mypy-boto3-timestream-query (>=1.28.0,<1.29.0)", "mypy-boto3-timestream-write (>=1.28.0,<1.29.0)", "mypy-boto3-tnb (>=1.28.0,<1.29.0)", "mypy-boto3-transcribe (>=1.28.0,<1.29.0)", "mypy-boto3-transfer (>=1.28.0,<1.29.0)", "mypy-boto3-translate (>=1.28.0,<1.29.0)", "mypy-boto3-verifiedpermissions (>=1.28.0,<1.29.0)", "mypy-boto3-voice-id (>=1.28.0,<1.29.0)", "mypy-boto3-vpc-lattice (>=1.28.0,<1.29.0)", "mypy-boto3-waf (>=1.28.0,<1.29.0)", "mypy-boto3-waf-regional (>=1.28.0,<1.29.0)", "mypy-boto3-wafv2 (>=1.28.0,<1.29.0)", "mypy-boto3-wellarchitected (>=1.28.0,<1.29.0)", "mypy-boto3-wisdom (>=1.28.0,<1.29.0)", "mypy-boto3-workdocs (>=1.28.0,<1.29.0)", "mypy-boto3-worklink (>=1.28.0,<1.29.0)", "mypy-boto3-workmail (>=1.28.0,<1.29.0)", "mypy-boto3-workmailmessageflow (>=1.28.0,<1.29.0)", "mypy-boto3-workspaces (>=1.28.0,<1.29.0)", "mypy-boto3-workspaces-web (>=1.28.0,<1.29.0)", "mypy-boto3-xray (>=1.28.0,<1.29.0)"] +amp = ["mypy-boto3-amp (>=1.28.0,<1.29.0)"] +amplify = ["mypy-boto3-amplify (>=1.28.0,<1.29.0)"] +amplifybackend = ["mypy-boto3-amplifybackend (>=1.28.0,<1.29.0)"] +amplifyuibuilder = ["mypy-boto3-amplifyuibuilder (>=1.28.0,<1.29.0)"] +apigateway = ["mypy-boto3-apigateway (>=1.28.0,<1.29.0)"] +apigatewaymanagementapi = ["mypy-boto3-apigatewaymanagementapi (>=1.28.0,<1.29.0)"] +apigatewayv2 = ["mypy-boto3-apigatewayv2 (>=1.28.0,<1.29.0)"] +appconfig = ["mypy-boto3-appconfig (>=1.28.0,<1.29.0)"] +appconfigdata = ["mypy-boto3-appconfigdata (>=1.28.0,<1.29.0)"] +appfabric = ["mypy-boto3-appfabric (>=1.28.0,<1.29.0)"] +appflow = ["mypy-boto3-appflow (>=1.28.0,<1.29.0)"] +appintegrations = ["mypy-boto3-appintegrations (>=1.28.0,<1.29.0)"] +application-autoscaling = ["mypy-boto3-application-autoscaling (>=1.28.0,<1.29.0)"] +application-insights = ["mypy-boto3-application-insights (>=1.28.0,<1.29.0)"] +applicationcostprofiler = ["mypy-boto3-applicationcostprofiler (>=1.28.0,<1.29.0)"] +appmesh = ["mypy-boto3-appmesh (>=1.28.0,<1.29.0)"] +apprunner = ["mypy-boto3-apprunner (>=1.28.0,<1.29.0)"] +appstream = ["mypy-boto3-appstream (>=1.28.0,<1.29.0)"] +appsync = ["mypy-boto3-appsync (>=1.28.0,<1.29.0)"] +arc-zonal-shift = ["mypy-boto3-arc-zonal-shift (>=1.28.0,<1.29.0)"] +athena = ["mypy-boto3-athena (>=1.28.0,<1.29.0)"] +auditmanager = ["mypy-boto3-auditmanager (>=1.28.0,<1.29.0)"] +autoscaling = ["mypy-boto3-autoscaling (>=1.28.0,<1.29.0)"] +autoscaling-plans = ["mypy-boto3-autoscaling-plans (>=1.28.0,<1.29.0)"] +backup = ["mypy-boto3-backup (>=1.28.0,<1.29.0)"] +backup-gateway = ["mypy-boto3-backup-gateway (>=1.28.0,<1.29.0)"] +backupstorage = ["mypy-boto3-backupstorage (>=1.28.0,<1.29.0)"] +batch = ["mypy-boto3-batch (>=1.28.0,<1.29.0)"] +bedrock = ["mypy-boto3-bedrock (>=1.28.0,<1.29.0)"] +bedrock-runtime = ["mypy-boto3-bedrock-runtime (>=1.28.0,<1.29.0)"] +billingconductor = ["mypy-boto3-billingconductor (>=1.28.0,<1.29.0)"] +boto3 = ["boto3 (==1.28.70)", "botocore (==1.31.70)"] +braket = ["mypy-boto3-braket (>=1.28.0,<1.29.0)"] +budgets = ["mypy-boto3-budgets (>=1.28.0,<1.29.0)"] +ce = ["mypy-boto3-ce (>=1.28.0,<1.29.0)"] +chime = ["mypy-boto3-chime (>=1.28.0,<1.29.0)"] +chime-sdk-identity = ["mypy-boto3-chime-sdk-identity (>=1.28.0,<1.29.0)"] +chime-sdk-media-pipelines = ["mypy-boto3-chime-sdk-media-pipelines (>=1.28.0,<1.29.0)"] +chime-sdk-meetings = ["mypy-boto3-chime-sdk-meetings (>=1.28.0,<1.29.0)"] +chime-sdk-messaging = ["mypy-boto3-chime-sdk-messaging (>=1.28.0,<1.29.0)"] +chime-sdk-voice = ["mypy-boto3-chime-sdk-voice (>=1.28.0,<1.29.0)"] +cleanrooms = ["mypy-boto3-cleanrooms (>=1.28.0,<1.29.0)"] +cloud9 = ["mypy-boto3-cloud9 (>=1.28.0,<1.29.0)"] +cloudcontrol = ["mypy-boto3-cloudcontrol (>=1.28.0,<1.29.0)"] +clouddirectory = ["mypy-boto3-clouddirectory (>=1.28.0,<1.29.0)"] +cloudformation = ["mypy-boto3-cloudformation (>=1.28.0,<1.29.0)"] +cloudfront = ["mypy-boto3-cloudfront (>=1.28.0,<1.29.0)"] +cloudhsm = ["mypy-boto3-cloudhsm (>=1.28.0,<1.29.0)"] +cloudhsmv2 = ["mypy-boto3-cloudhsmv2 (>=1.28.0,<1.29.0)"] +cloudsearch = ["mypy-boto3-cloudsearch (>=1.28.0,<1.29.0)"] +cloudsearchdomain = ["mypy-boto3-cloudsearchdomain (>=1.28.0,<1.29.0)"] +cloudtrail = ["mypy-boto3-cloudtrail (>=1.28.0,<1.29.0)"] +cloudtrail-data = ["mypy-boto3-cloudtrail-data (>=1.28.0,<1.29.0)"] +cloudwatch = ["mypy-boto3-cloudwatch (>=1.28.0,<1.29.0)"] +codeartifact = ["mypy-boto3-codeartifact (>=1.28.0,<1.29.0)"] +codebuild = ["mypy-boto3-codebuild (>=1.28.0,<1.29.0)"] +codecatalyst = ["mypy-boto3-codecatalyst (>=1.28.0,<1.29.0)"] +codecommit = ["mypy-boto3-codecommit (>=1.28.0,<1.29.0)"] +codedeploy = ["mypy-boto3-codedeploy (>=1.28.0,<1.29.0)"] +codeguru-reviewer = ["mypy-boto3-codeguru-reviewer (>=1.28.0,<1.29.0)"] +codeguru-security = ["mypy-boto3-codeguru-security (>=1.28.0,<1.29.0)"] +codeguruprofiler = ["mypy-boto3-codeguruprofiler (>=1.28.0,<1.29.0)"] +codepipeline = ["mypy-boto3-codepipeline (>=1.28.0,<1.29.0)"] +codestar = ["mypy-boto3-codestar (>=1.28.0,<1.29.0)"] +codestar-connections = ["mypy-boto3-codestar-connections (>=1.28.0,<1.29.0)"] +codestar-notifications = ["mypy-boto3-codestar-notifications (>=1.28.0,<1.29.0)"] +cognito-identity = ["mypy-boto3-cognito-identity (>=1.28.0,<1.29.0)"] +cognito-idp = ["mypy-boto3-cognito-idp (>=1.28.0,<1.29.0)"] +cognito-sync = ["mypy-boto3-cognito-sync (>=1.28.0,<1.29.0)"] +comprehend = ["mypy-boto3-comprehend (>=1.28.0,<1.29.0)"] +comprehendmedical = ["mypy-boto3-comprehendmedical (>=1.28.0,<1.29.0)"] +compute-optimizer = ["mypy-boto3-compute-optimizer (>=1.28.0,<1.29.0)"] +config = ["mypy-boto3-config (>=1.28.0,<1.29.0)"] +connect = ["mypy-boto3-connect (>=1.28.0,<1.29.0)"] +connect-contact-lens = ["mypy-boto3-connect-contact-lens (>=1.28.0,<1.29.0)"] +connectcampaigns = ["mypy-boto3-connectcampaigns (>=1.28.0,<1.29.0)"] +connectcases = ["mypy-boto3-connectcases (>=1.28.0,<1.29.0)"] +connectparticipant = ["mypy-boto3-connectparticipant (>=1.28.0,<1.29.0)"] +controltower = ["mypy-boto3-controltower (>=1.28.0,<1.29.0)"] +cur = ["mypy-boto3-cur (>=1.28.0,<1.29.0)"] +customer-profiles = ["mypy-boto3-customer-profiles (>=1.28.0,<1.29.0)"] +databrew = ["mypy-boto3-databrew (>=1.28.0,<1.29.0)"] +dataexchange = ["mypy-boto3-dataexchange (>=1.28.0,<1.29.0)"] +datapipeline = ["mypy-boto3-datapipeline (>=1.28.0,<1.29.0)"] +datasync = ["mypy-boto3-datasync (>=1.28.0,<1.29.0)"] +datazone = ["mypy-boto3-datazone (>=1.28.0,<1.29.0)"] +dax = ["mypy-boto3-dax (>=1.28.0,<1.29.0)"] +detective = ["mypy-boto3-detective (>=1.28.0,<1.29.0)"] +devicefarm = ["mypy-boto3-devicefarm (>=1.28.0,<1.29.0)"] +devops-guru = ["mypy-boto3-devops-guru (>=1.28.0,<1.29.0)"] +directconnect = ["mypy-boto3-directconnect (>=1.28.0,<1.29.0)"] +discovery = ["mypy-boto3-discovery (>=1.28.0,<1.29.0)"] +dlm = ["mypy-boto3-dlm (>=1.28.0,<1.29.0)"] +dms = ["mypy-boto3-dms (>=1.28.0,<1.29.0)"] +docdb = ["mypy-boto3-docdb (>=1.28.0,<1.29.0)"] +docdb-elastic = ["mypy-boto3-docdb-elastic (>=1.28.0,<1.29.0)"] +drs = ["mypy-boto3-drs (>=1.28.0,<1.29.0)"] +ds = ["mypy-boto3-ds (>=1.28.0,<1.29.0)"] +dynamodb = ["mypy-boto3-dynamodb (>=1.28.0,<1.29.0)"] +dynamodbstreams = ["mypy-boto3-dynamodbstreams (>=1.28.0,<1.29.0)"] +ebs = ["mypy-boto3-ebs (>=1.28.0,<1.29.0)"] +ec2 = ["mypy-boto3-ec2 (>=1.28.0,<1.29.0)"] +ec2-instance-connect = ["mypy-boto3-ec2-instance-connect (>=1.28.0,<1.29.0)"] +ecr = ["mypy-boto3-ecr (>=1.28.0,<1.29.0)"] +ecr-public = ["mypy-boto3-ecr-public (>=1.28.0,<1.29.0)"] +ecs = ["mypy-boto3-ecs (>=1.28.0,<1.29.0)"] +efs = ["mypy-boto3-efs (>=1.28.0,<1.29.0)"] +eks = ["mypy-boto3-eks (>=1.28.0,<1.29.0)"] +elastic-inference = ["mypy-boto3-elastic-inference (>=1.28.0,<1.29.0)"] +elasticache = ["mypy-boto3-elasticache (>=1.28.0,<1.29.0)"] +elasticbeanstalk = ["mypy-boto3-elasticbeanstalk (>=1.28.0,<1.29.0)"] +elastictranscoder = ["mypy-boto3-elastictranscoder (>=1.28.0,<1.29.0)"] +elb = ["mypy-boto3-elb (>=1.28.0,<1.29.0)"] +elbv2 = ["mypy-boto3-elbv2 (>=1.28.0,<1.29.0)"] +emr = ["mypy-boto3-emr (>=1.28.0,<1.29.0)"] +emr-containers = ["mypy-boto3-emr-containers (>=1.28.0,<1.29.0)"] +emr-serverless = ["mypy-boto3-emr-serverless (>=1.28.0,<1.29.0)"] +entityresolution = ["mypy-boto3-entityresolution (>=1.28.0,<1.29.0)"] +es = ["mypy-boto3-es (>=1.28.0,<1.29.0)"] +essential = ["mypy-boto3-cloudformation (>=1.28.0,<1.29.0)", "mypy-boto3-dynamodb (>=1.28.0,<1.29.0)", "mypy-boto3-ec2 (>=1.28.0,<1.29.0)", "mypy-boto3-lambda (>=1.28.0,<1.29.0)", "mypy-boto3-rds (>=1.28.0,<1.29.0)", "mypy-boto3-s3 (>=1.28.0,<1.29.0)", "mypy-boto3-sqs (>=1.28.0,<1.29.0)"] +events = ["mypy-boto3-events (>=1.28.0,<1.29.0)"] +evidently = ["mypy-boto3-evidently (>=1.28.0,<1.29.0)"] +finspace = ["mypy-boto3-finspace (>=1.28.0,<1.29.0)"] +finspace-data = ["mypy-boto3-finspace-data (>=1.28.0,<1.29.0)"] +firehose = ["mypy-boto3-firehose (>=1.28.0,<1.29.0)"] +fis = ["mypy-boto3-fis (>=1.28.0,<1.29.0)"] +fms = ["mypy-boto3-fms (>=1.28.0,<1.29.0)"] +forecast = ["mypy-boto3-forecast (>=1.28.0,<1.29.0)"] +forecastquery = ["mypy-boto3-forecastquery (>=1.28.0,<1.29.0)"] +frauddetector = ["mypy-boto3-frauddetector (>=1.28.0,<1.29.0)"] +fsx = ["mypy-boto3-fsx (>=1.28.0,<1.29.0)"] +gamelift = ["mypy-boto3-gamelift (>=1.28.0,<1.29.0)"] +glacier = ["mypy-boto3-glacier (>=1.28.0,<1.29.0)"] +globalaccelerator = ["mypy-boto3-globalaccelerator (>=1.28.0,<1.29.0)"] +glue = ["mypy-boto3-glue (>=1.28.0,<1.29.0)"] +grafana = ["mypy-boto3-grafana (>=1.28.0,<1.29.0)"] +greengrass = ["mypy-boto3-greengrass (>=1.28.0,<1.29.0)"] +greengrassv2 = ["mypy-boto3-greengrassv2 (>=1.28.0,<1.29.0)"] +groundstation = ["mypy-boto3-groundstation (>=1.28.0,<1.29.0)"] +guardduty = ["mypy-boto3-guardduty (>=1.28.0,<1.29.0)"] +health = ["mypy-boto3-health (>=1.28.0,<1.29.0)"] +healthlake = ["mypy-boto3-healthlake (>=1.28.0,<1.29.0)"] +honeycode = ["mypy-boto3-honeycode (>=1.28.0,<1.29.0)"] +iam = ["mypy-boto3-iam (>=1.28.0,<1.29.0)"] +identitystore = ["mypy-boto3-identitystore (>=1.28.0,<1.29.0)"] +imagebuilder = ["mypy-boto3-imagebuilder (>=1.28.0,<1.29.0)"] +importexport = ["mypy-boto3-importexport (>=1.28.0,<1.29.0)"] +inspector = ["mypy-boto3-inspector (>=1.28.0,<1.29.0)"] +inspector2 = ["mypy-boto3-inspector2 (>=1.28.0,<1.29.0)"] +internetmonitor = ["mypy-boto3-internetmonitor (>=1.28.0,<1.29.0)"] +iot = ["mypy-boto3-iot (>=1.28.0,<1.29.0)"] +iot-data = ["mypy-boto3-iot-data (>=1.28.0,<1.29.0)"] +iot-jobs-data = ["mypy-boto3-iot-jobs-data (>=1.28.0,<1.29.0)"] +iot-roborunner = ["mypy-boto3-iot-roborunner (>=1.28.0,<1.29.0)"] +iot1click-devices = ["mypy-boto3-iot1click-devices (>=1.28.0,<1.29.0)"] +iot1click-projects = ["mypy-boto3-iot1click-projects (>=1.28.0,<1.29.0)"] +iotanalytics = ["mypy-boto3-iotanalytics (>=1.28.0,<1.29.0)"] +iotdeviceadvisor = ["mypy-boto3-iotdeviceadvisor (>=1.28.0,<1.29.0)"] +iotevents = ["mypy-boto3-iotevents (>=1.28.0,<1.29.0)"] +iotevents-data = ["mypy-boto3-iotevents-data (>=1.28.0,<1.29.0)"] +iotfleethub = ["mypy-boto3-iotfleethub (>=1.28.0,<1.29.0)"] +iotfleetwise = ["mypy-boto3-iotfleetwise (>=1.28.0,<1.29.0)"] +iotsecuretunneling = ["mypy-boto3-iotsecuretunneling (>=1.28.0,<1.29.0)"] +iotsitewise = ["mypy-boto3-iotsitewise (>=1.28.0,<1.29.0)"] +iotthingsgraph = ["mypy-boto3-iotthingsgraph (>=1.28.0,<1.29.0)"] +iottwinmaker = ["mypy-boto3-iottwinmaker (>=1.28.0,<1.29.0)"] +iotwireless = ["mypy-boto3-iotwireless (>=1.28.0,<1.29.0)"] +ivs = ["mypy-boto3-ivs (>=1.28.0,<1.29.0)"] +ivs-realtime = ["mypy-boto3-ivs-realtime (>=1.28.0,<1.29.0)"] +ivschat = ["mypy-boto3-ivschat (>=1.28.0,<1.29.0)"] +kafka = ["mypy-boto3-kafka (>=1.28.0,<1.29.0)"] +kafkaconnect = ["mypy-boto3-kafkaconnect (>=1.28.0,<1.29.0)"] +kendra = ["mypy-boto3-kendra (>=1.28.0,<1.29.0)"] +kendra-ranking = ["mypy-boto3-kendra-ranking (>=1.28.0,<1.29.0)"] +keyspaces = ["mypy-boto3-keyspaces (>=1.28.0,<1.29.0)"] +kinesis = ["mypy-boto3-kinesis (>=1.28.0,<1.29.0)"] +kinesis-video-archived-media = ["mypy-boto3-kinesis-video-archived-media (>=1.28.0,<1.29.0)"] +kinesis-video-media = ["mypy-boto3-kinesis-video-media (>=1.28.0,<1.29.0)"] +kinesis-video-signaling = ["mypy-boto3-kinesis-video-signaling (>=1.28.0,<1.29.0)"] +kinesis-video-webrtc-storage = ["mypy-boto3-kinesis-video-webrtc-storage (>=1.28.0,<1.29.0)"] +kinesisanalytics = ["mypy-boto3-kinesisanalytics (>=1.28.0,<1.29.0)"] +kinesisanalyticsv2 = ["mypy-boto3-kinesisanalyticsv2 (>=1.28.0,<1.29.0)"] +kinesisvideo = ["mypy-boto3-kinesisvideo (>=1.28.0,<1.29.0)"] +kms = ["mypy-boto3-kms (>=1.28.0,<1.29.0)"] +lakeformation = ["mypy-boto3-lakeformation (>=1.28.0,<1.29.0)"] +lambda = ["mypy-boto3-lambda (>=1.28.0,<1.29.0)"] +lex-models = ["mypy-boto3-lex-models (>=1.28.0,<1.29.0)"] +lex-runtime = ["mypy-boto3-lex-runtime (>=1.28.0,<1.29.0)"] +lexv2-models = ["mypy-boto3-lexv2-models (>=1.28.0,<1.29.0)"] +lexv2-runtime = ["mypy-boto3-lexv2-runtime (>=1.28.0,<1.29.0)"] +license-manager = ["mypy-boto3-license-manager (>=1.28.0,<1.29.0)"] +license-manager-linux-subscriptions = ["mypy-boto3-license-manager-linux-subscriptions (>=1.28.0,<1.29.0)"] +license-manager-user-subscriptions = ["mypy-boto3-license-manager-user-subscriptions (>=1.28.0,<1.29.0)"] +lightsail = ["mypy-boto3-lightsail (>=1.28.0,<1.29.0)"] +location = ["mypy-boto3-location (>=1.28.0,<1.29.0)"] +logs = ["mypy-boto3-logs (>=1.28.0,<1.29.0)"] +lookoutequipment = ["mypy-boto3-lookoutequipment (>=1.28.0,<1.29.0)"] +lookoutmetrics = ["mypy-boto3-lookoutmetrics (>=1.28.0,<1.29.0)"] +lookoutvision = ["mypy-boto3-lookoutvision (>=1.28.0,<1.29.0)"] +m2 = ["mypy-boto3-m2 (>=1.28.0,<1.29.0)"] +machinelearning = ["mypy-boto3-machinelearning (>=1.28.0,<1.29.0)"] +macie = ["mypy-boto3-macie (>=1.28.0,<1.29.0)"] +macie2 = ["mypy-boto3-macie2 (>=1.28.0,<1.29.0)"] +managedblockchain = ["mypy-boto3-managedblockchain (>=1.28.0,<1.29.0)"] +managedblockchain-query = ["mypy-boto3-managedblockchain-query (>=1.28.0,<1.29.0)"] +marketplace-catalog = ["mypy-boto3-marketplace-catalog (>=1.28.0,<1.29.0)"] +marketplace-entitlement = ["mypy-boto3-marketplace-entitlement (>=1.28.0,<1.29.0)"] +marketplacecommerceanalytics = ["mypy-boto3-marketplacecommerceanalytics (>=1.28.0,<1.29.0)"] +mediaconnect = ["mypy-boto3-mediaconnect (>=1.28.0,<1.29.0)"] +mediaconvert = ["mypy-boto3-mediaconvert (>=1.28.0,<1.29.0)"] +medialive = ["mypy-boto3-medialive (>=1.28.0,<1.29.0)"] +mediapackage = ["mypy-boto3-mediapackage (>=1.28.0,<1.29.0)"] +mediapackage-vod = ["mypy-boto3-mediapackage-vod (>=1.28.0,<1.29.0)"] +mediapackagev2 = ["mypy-boto3-mediapackagev2 (>=1.28.0,<1.29.0)"] +mediastore = ["mypy-boto3-mediastore (>=1.28.0,<1.29.0)"] +mediastore-data = ["mypy-boto3-mediastore-data (>=1.28.0,<1.29.0)"] +mediatailor = ["mypy-boto3-mediatailor (>=1.28.0,<1.29.0)"] +medical-imaging = ["mypy-boto3-medical-imaging (>=1.28.0,<1.29.0)"] +memorydb = ["mypy-boto3-memorydb (>=1.28.0,<1.29.0)"] +meteringmarketplace = ["mypy-boto3-meteringmarketplace (>=1.28.0,<1.29.0)"] +mgh = ["mypy-boto3-mgh (>=1.28.0,<1.29.0)"] +mgn = ["mypy-boto3-mgn (>=1.28.0,<1.29.0)"] +migration-hub-refactor-spaces = ["mypy-boto3-migration-hub-refactor-spaces (>=1.28.0,<1.29.0)"] +migrationhub-config = ["mypy-boto3-migrationhub-config (>=1.28.0,<1.29.0)"] +migrationhuborchestrator = ["mypy-boto3-migrationhuborchestrator (>=1.28.0,<1.29.0)"] +migrationhubstrategy = ["mypy-boto3-migrationhubstrategy (>=1.28.0,<1.29.0)"] +mobile = ["mypy-boto3-mobile (>=1.28.0,<1.29.0)"] +mq = ["mypy-boto3-mq (>=1.28.0,<1.29.0)"] +mturk = ["mypy-boto3-mturk (>=1.28.0,<1.29.0)"] +mwaa = ["mypy-boto3-mwaa (>=1.28.0,<1.29.0)"] +neptune = ["mypy-boto3-neptune (>=1.28.0,<1.29.0)"] +neptunedata = ["mypy-boto3-neptunedata (>=1.28.0,<1.29.0)"] +network-firewall = ["mypy-boto3-network-firewall (>=1.28.0,<1.29.0)"] +networkmanager = ["mypy-boto3-networkmanager (>=1.28.0,<1.29.0)"] +nimble = ["mypy-boto3-nimble (>=1.28.0,<1.29.0)"] +oam = ["mypy-boto3-oam (>=1.28.0,<1.29.0)"] +omics = ["mypy-boto3-omics (>=1.28.0,<1.29.0)"] +opensearch = ["mypy-boto3-opensearch (>=1.28.0,<1.29.0)"] +opensearchserverless = ["mypy-boto3-opensearchserverless (>=1.28.0,<1.29.0)"] +opsworks = ["mypy-boto3-opsworks (>=1.28.0,<1.29.0)"] +opsworkscm = ["mypy-boto3-opsworkscm (>=1.28.0,<1.29.0)"] +organizations = ["mypy-boto3-organizations (>=1.28.0,<1.29.0)"] +osis = ["mypy-boto3-osis (>=1.28.0,<1.29.0)"] +outposts = ["mypy-boto3-outposts (>=1.28.0,<1.29.0)"] +panorama = ["mypy-boto3-panorama (>=1.28.0,<1.29.0)"] +payment-cryptography = ["mypy-boto3-payment-cryptography (>=1.28.0,<1.29.0)"] +payment-cryptography-data = ["mypy-boto3-payment-cryptography-data (>=1.28.0,<1.29.0)"] +pca-connector-ad = ["mypy-boto3-pca-connector-ad (>=1.28.0,<1.29.0)"] +personalize = ["mypy-boto3-personalize (>=1.28.0,<1.29.0)"] +personalize-events = ["mypy-boto3-personalize-events (>=1.28.0,<1.29.0)"] +personalize-runtime = ["mypy-boto3-personalize-runtime (>=1.28.0,<1.29.0)"] +pi = ["mypy-boto3-pi (>=1.28.0,<1.29.0)"] +pinpoint = ["mypy-boto3-pinpoint (>=1.28.0,<1.29.0)"] +pinpoint-email = ["mypy-boto3-pinpoint-email (>=1.28.0,<1.29.0)"] +pinpoint-sms-voice = ["mypy-boto3-pinpoint-sms-voice (>=1.28.0,<1.29.0)"] +pinpoint-sms-voice-v2 = ["mypy-boto3-pinpoint-sms-voice-v2 (>=1.28.0,<1.29.0)"] +pipes = ["mypy-boto3-pipes (>=1.28.0,<1.29.0)"] +polly = ["mypy-boto3-polly (>=1.28.0,<1.29.0)"] +pricing = ["mypy-boto3-pricing (>=1.28.0,<1.29.0)"] +privatenetworks = ["mypy-boto3-privatenetworks (>=1.28.0,<1.29.0)"] +proton = ["mypy-boto3-proton (>=1.28.0,<1.29.0)"] +qldb = ["mypy-boto3-qldb (>=1.28.0,<1.29.0)"] +qldb-session = ["mypy-boto3-qldb-session (>=1.28.0,<1.29.0)"] +quicksight = ["mypy-boto3-quicksight (>=1.28.0,<1.29.0)"] +ram = ["mypy-boto3-ram (>=1.28.0,<1.29.0)"] +rbin = ["mypy-boto3-rbin (>=1.28.0,<1.29.0)"] +rds = ["mypy-boto3-rds (>=1.28.0,<1.29.0)"] +rds-data = ["mypy-boto3-rds-data (>=1.28.0,<1.29.0)"] +redshift = ["mypy-boto3-redshift (>=1.28.0,<1.29.0)"] +redshift-data = ["mypy-boto3-redshift-data (>=1.28.0,<1.29.0)"] +redshift-serverless = ["mypy-boto3-redshift-serverless (>=1.28.0,<1.29.0)"] +rekognition = ["mypy-boto3-rekognition (>=1.28.0,<1.29.0)"] +resiliencehub = ["mypy-boto3-resiliencehub (>=1.28.0,<1.29.0)"] +resource-explorer-2 = ["mypy-boto3-resource-explorer-2 (>=1.28.0,<1.29.0)"] +resource-groups = ["mypy-boto3-resource-groups (>=1.28.0,<1.29.0)"] +resourcegroupstaggingapi = ["mypy-boto3-resourcegroupstaggingapi (>=1.28.0,<1.29.0)"] +robomaker = ["mypy-boto3-robomaker (>=1.28.0,<1.29.0)"] +rolesanywhere = ["mypy-boto3-rolesanywhere (>=1.28.0,<1.29.0)"] +route53 = ["mypy-boto3-route53 (>=1.28.0,<1.29.0)"] +route53-recovery-cluster = ["mypy-boto3-route53-recovery-cluster (>=1.28.0,<1.29.0)"] +route53-recovery-control-config = ["mypy-boto3-route53-recovery-control-config (>=1.28.0,<1.29.0)"] +route53-recovery-readiness = ["mypy-boto3-route53-recovery-readiness (>=1.28.0,<1.29.0)"] +route53domains = ["mypy-boto3-route53domains (>=1.28.0,<1.29.0)"] +route53resolver = ["mypy-boto3-route53resolver (>=1.28.0,<1.29.0)"] +rum = ["mypy-boto3-rum (>=1.28.0,<1.29.0)"] +s3 = ["mypy-boto3-s3 (>=1.28.0,<1.29.0)"] +s3control = ["mypy-boto3-s3control (>=1.28.0,<1.29.0)"] +s3outposts = ["mypy-boto3-s3outposts (>=1.28.0,<1.29.0)"] +sagemaker = ["mypy-boto3-sagemaker (>=1.28.0,<1.29.0)"] +sagemaker-a2i-runtime = ["mypy-boto3-sagemaker-a2i-runtime (>=1.28.0,<1.29.0)"] +sagemaker-edge = ["mypy-boto3-sagemaker-edge (>=1.28.0,<1.29.0)"] +sagemaker-featurestore-runtime = ["mypy-boto3-sagemaker-featurestore-runtime (>=1.28.0,<1.29.0)"] +sagemaker-geospatial = ["mypy-boto3-sagemaker-geospatial (>=1.28.0,<1.29.0)"] +sagemaker-metrics = ["mypy-boto3-sagemaker-metrics (>=1.28.0,<1.29.0)"] +sagemaker-runtime = ["mypy-boto3-sagemaker-runtime (>=1.28.0,<1.29.0)"] +savingsplans = ["mypy-boto3-savingsplans (>=1.28.0,<1.29.0)"] +scheduler = ["mypy-boto3-scheduler (>=1.28.0,<1.29.0)"] +schemas = ["mypy-boto3-schemas (>=1.28.0,<1.29.0)"] +sdb = ["mypy-boto3-sdb (>=1.28.0,<1.29.0)"] +secretsmanager = ["mypy-boto3-secretsmanager (>=1.28.0,<1.29.0)"] +securityhub = ["mypy-boto3-securityhub (>=1.28.0,<1.29.0)"] +securitylake = ["mypy-boto3-securitylake (>=1.28.0,<1.29.0)"] +serverlessrepo = ["mypy-boto3-serverlessrepo (>=1.28.0,<1.29.0)"] +service-quotas = ["mypy-boto3-service-quotas (>=1.28.0,<1.29.0)"] +servicecatalog = ["mypy-boto3-servicecatalog (>=1.28.0,<1.29.0)"] +servicecatalog-appregistry = ["mypy-boto3-servicecatalog-appregistry (>=1.28.0,<1.29.0)"] +servicediscovery = ["mypy-boto3-servicediscovery (>=1.28.0,<1.29.0)"] +ses = ["mypy-boto3-ses (>=1.28.0,<1.29.0)"] +sesv2 = ["mypy-boto3-sesv2 (>=1.28.0,<1.29.0)"] +shield = ["mypy-boto3-shield (>=1.28.0,<1.29.0)"] +signer = ["mypy-boto3-signer (>=1.28.0,<1.29.0)"] +simspaceweaver = ["mypy-boto3-simspaceweaver (>=1.28.0,<1.29.0)"] +sms = ["mypy-boto3-sms (>=1.28.0,<1.29.0)"] +sms-voice = ["mypy-boto3-sms-voice (>=1.28.0,<1.29.0)"] +snow-device-management = ["mypy-boto3-snow-device-management (>=1.28.0,<1.29.0)"] +snowball = ["mypy-boto3-snowball (>=1.28.0,<1.29.0)"] +sns = ["mypy-boto3-sns (>=1.28.0,<1.29.0)"] +sqs = ["mypy-boto3-sqs (>=1.28.0,<1.29.0)"] +ssm = ["mypy-boto3-ssm (>=1.28.0,<1.29.0)"] +ssm-contacts = ["mypy-boto3-ssm-contacts (>=1.28.0,<1.29.0)"] +ssm-incidents = ["mypy-boto3-ssm-incidents (>=1.28.0,<1.29.0)"] +ssm-sap = ["mypy-boto3-ssm-sap (>=1.28.0,<1.29.0)"] +sso = ["mypy-boto3-sso (>=1.28.0,<1.29.0)"] +sso-admin = ["mypy-boto3-sso-admin (>=1.28.0,<1.29.0)"] +sso-oidc = ["mypy-boto3-sso-oidc (>=1.28.0,<1.29.0)"] +stepfunctions = ["mypy-boto3-stepfunctions (>=1.28.0,<1.29.0)"] +storagegateway = ["mypy-boto3-storagegateway (>=1.28.0,<1.29.0)"] +sts = ["mypy-boto3-sts (>=1.28.0,<1.29.0)"] +support = ["mypy-boto3-support (>=1.28.0,<1.29.0)"] +support-app = ["mypy-boto3-support-app (>=1.28.0,<1.29.0)"] +swf = ["mypy-boto3-swf (>=1.28.0,<1.29.0)"] +synthetics = ["mypy-boto3-synthetics (>=1.28.0,<1.29.0)"] +textract = ["mypy-boto3-textract (>=1.28.0,<1.29.0)"] +timestream-query = ["mypy-boto3-timestream-query (>=1.28.0,<1.29.0)"] +timestream-write = ["mypy-boto3-timestream-write (>=1.28.0,<1.29.0)"] +tnb = ["mypy-boto3-tnb (>=1.28.0,<1.29.0)"] +transcribe = ["mypy-boto3-transcribe (>=1.28.0,<1.29.0)"] +transfer = ["mypy-boto3-transfer (>=1.28.0,<1.29.0)"] +translate = ["mypy-boto3-translate (>=1.28.0,<1.29.0)"] +verifiedpermissions = ["mypy-boto3-verifiedpermissions (>=1.28.0,<1.29.0)"] +voice-id = ["mypy-boto3-voice-id (>=1.28.0,<1.29.0)"] +vpc-lattice = ["mypy-boto3-vpc-lattice (>=1.28.0,<1.29.0)"] +waf = ["mypy-boto3-waf (>=1.28.0,<1.29.0)"] +waf-regional = ["mypy-boto3-waf-regional (>=1.28.0,<1.29.0)"] +wafv2 = ["mypy-boto3-wafv2 (>=1.28.0,<1.29.0)"] +wellarchitected = ["mypy-boto3-wellarchitected (>=1.28.0,<1.29.0)"] +wisdom = ["mypy-boto3-wisdom (>=1.28.0,<1.29.0)"] +workdocs = ["mypy-boto3-workdocs (>=1.28.0,<1.29.0)"] +worklink = ["mypy-boto3-worklink (>=1.28.0,<1.29.0)"] +workmail = ["mypy-boto3-workmail (>=1.28.0,<1.29.0)"] +workmailmessageflow = ["mypy-boto3-workmailmessageflow (>=1.28.0,<1.29.0)"] +workspaces = ["mypy-boto3-workspaces (>=1.28.0,<1.29.0)"] +workspaces-web = ["mypy-boto3-workspaces-web (>=1.28.0,<1.29.0)"] +xray = ["mypy-boto3-xray (>=1.28.0,<1.29.0)"] + +[[package]] +name = "botocore" +version = "1.31.70" +description = "Low-level, data-driven core of boto 3." +optional = false +python-versions = ">= 3.7" +files = [ + {file = "botocore-1.31.70-py3-none-any.whl", hash = "sha256:049bbf526c95b6169f59617a5ff1b0061cb7a0e44992b8c27c6955832b383988"}, + {file = "botocore-1.31.70.tar.gz", hash = "sha256:5f49def4ec2e4216dd0195d23d9811027d02ee6c8a37b031e2b2fe38e8c77ddc"}, +] + +[package.dependencies] +jmespath = ">=0.7.1,<2.0.0" +python-dateutil = ">=2.1,<3.0.0" +urllib3 = {version = ">=1.25.4,<2.1", markers = "python_version >= \"3.10\""} + +[package.extras] +crt = ["awscrt (==0.16.26)"] + +[[package]] +name = "botocore-stubs" +version = "1.31.70" +description = "Type annotations and code completion for botocore" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "botocore_stubs-1.31.70-py3-none-any.whl", hash = "sha256:205b952cef00bfdf5e2b1a7fb7ef40c7008729af7934663703ef006f9a420a29"}, + {file = "botocore_stubs-1.31.70.tar.gz", hash = "sha256:5a7f77649bf54d326461cb380b935338ed41370b0330a7495b3a82f6277369be"}, +] + +[package.dependencies] +types-awscrt = "*" + +[[package]] +name = "celery" +version = "5.2.7" +description = "Distributed Task Queue." +optional = false +python-versions = ">=3.7" +files = [ + {file = "celery-5.2.7-py3-none-any.whl", hash = "sha256:138420c020cd58d6707e6257b6beda91fd39af7afde5d36c6334d175302c0e14"}, + {file = "celery-5.2.7.tar.gz", hash = "sha256:fafbd82934d30f8a004f81e8f7a062e31413a23d444be8ee3326553915958c6d"}, +] + +[package.dependencies] +billiard = ">=3.6.4.0,<4.0" +click = ">=8.0.3,<9.0" +click-didyoumean = ">=0.0.3" +click-plugins = ">=1.1.1" +click-repl = ">=0.2.0" +kombu = ">=5.2.3,<6.0" +pytz = ">=2021.3" +vine = ">=5.0.0,<6.0" + +[package.extras] +arangodb = ["pyArango (>=1.3.2)"] +auth = ["cryptography"] +azureblockblob = ["azure-storage-blob (==12.9.0)"] +brotli = ["brotli (>=1.0.0)", "brotlipy (>=0.7.0)"] +cassandra = ["cassandra-driver (<3.21.0)"] +consul = ["python-consul2"] +cosmosdbsql = ["pydocumentdb (==2.3.2)"] +couchbase = ["couchbase (>=3.0.0)"] +couchdb = ["pycouchdb"] +django = ["Django (>=1.11)"] +dynamodb = ["boto3 (>=1.9.178)"] +elasticsearch = ["elasticsearch"] +eventlet = ["eventlet (>=0.32.0)"] +gevent = ["gevent (>=1.5.0)"] +librabbitmq = ["librabbitmq (>=1.5.0)"] +memcache = ["pylibmc"] +mongodb = ["pymongo[srv] (>=3.11.1)"] +msgpack = ["msgpack"] +pymemcache = ["python-memcached"] +pyro = ["pyro4"] +pytest = ["pytest-celery"] +redis = ["redis (>=3.4.1,!=4.0.0,!=4.0.1)"] +s3 = ["boto3 (>=1.9.125)"] +slmq = ["softlayer-messaging (>=1.0.3)"] +solar = ["ephem"] +sqlalchemy = ["sqlalchemy"] +sqs = ["kombu[sqs]"] +tblib = ["tblib (>=1.3.0)", "tblib (>=1.5.0)"] +yaml = ["PyYAML (>=3.10)"] +zookeeper = ["kazoo (>=1.3.1)"] +zstd = ["zstandard"] + +[[package]] +name = "certifi" +version = "2023.7.22" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, + {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, +] + +[[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.1" +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.1.tar.gz", hash = "sha256:d9137a876020661972ca6eec0766d81aef8a5627df628b664b234b73396e727e"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8aee051c89e13565c6bd366813c386939f8e928af93c29fda4af86d25b73d8f8"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:352a88c3df0d1fa886562384b86f9a9e27563d4704ee0e9d56ec6fcd270ea690"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:223b4d54561c01048f657fa6ce41461d5ad8ff128b9678cfe8b2ecd951e3f8a2"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f861d94c2a450b974b86093c6c027888627b8082f1299dfd5a4bae8e2292821"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1171ef1fc5ab4693c5d151ae0fdad7f7349920eabbaca6271f95969fa0756c2d"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28f512b9a33235545fbbdac6a330a510b63be278a50071a336afc1b78781b147"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0e842112fe3f1a4ffcf64b06dc4c61a88441c2f02f373367f7b4c1aa9be2ad5"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f9bc2ce123637a60ebe819f9fccc614da1bcc05798bbbaf2dd4ec91f3e08846"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f194cce575e59ffe442c10a360182a986535fd90b57f7debfaa5c845c409ecc3"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9a74041ba0bfa9bc9b9bb2cd3238a6ab3b7618e759b41bd15b5f6ad958d17605"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b578cbe580e3b41ad17b1c428f382c814b32a6ce90f2d8e39e2e635d49e498d1"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6db3cfb9b4fcecb4390db154e75b49578c87a3b9979b40cdf90d7e4b945656e1"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:debb633f3f7856f95ad957d9b9c781f8e2c6303ef21724ec94bea2ce2fcbd056"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-win32.whl", hash = "sha256:87071618d3d8ec8b186d53cb6e66955ef2a0e4fa63ccd3709c0c90ac5a43520f"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:e372d7dfd154009142631de2d316adad3cc1c36c32a38b16a4751ba78da2a397"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae4070f741f8d809075ef697877fd350ecf0b7c5837ed68738607ee0a2c572cf"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:58e875eb7016fd014c0eea46c6fa92b87b62c0cb31b9feae25cbbe62c919f54d"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dbd95e300367aa0827496fe75a1766d198d34385a58f97683fe6e07f89ca3e3c"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de0b4caa1c8a21394e8ce971997614a17648f94e1cd0640fbd6b4d14cab13a72"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:985c7965f62f6f32bf432e2681173db41336a9c2611693247069288bcb0c7f8b"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a15c1fe6d26e83fd2e5972425a772cca158eae58b05d4a25a4e474c221053e2d"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae55d592b02c4349525b6ed8f74c692509e5adffa842e582c0f861751701a673"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be4d9c2770044a59715eb57c1144dedea7c5d5ae80c68fb9959515037cde2008"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:851cf693fb3aaef71031237cd68699dded198657ec1e76a76eb8be58c03a5d1f"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:31bbaba7218904d2eabecf4feec0d07469284e952a27400f23b6628439439fa7"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:871d045d6ccc181fd863a3cd66ee8e395523ebfbc57f85f91f035f50cee8e3d4"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:501adc5eb6cd5f40a6f77fbd90e5ab915c8fd6e8c614af2db5561e16c600d6f3"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f5fb672c396d826ca16a022ac04c9dce74e00a1c344f6ad1a0fdc1ba1f332213"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-win32.whl", hash = "sha256:bb06098d019766ca16fc915ecaa455c1f1cd594204e7f840cd6258237b5079a8"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:8af5a8917b8af42295e86b64903156b4f110a30dca5f3b5aedea123fbd638bff"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7ae8e5142dcc7a49168f4055255dbcced01dc1714a90a21f87448dc8d90617d1"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5b70bab78accbc672f50e878a5b73ca692f45f5b5e25c8066d748c09405e6a55"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ceca5876032362ae73b83347be8b5dbd2d1faf3358deb38c9c88776779b2e2f"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34d95638ff3613849f473afc33f65c401a89f3b9528d0d213c7037c398a51296"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9edbe6a5bf8b56a4a84533ba2b2f489d0046e755c29616ef8830f9e7d9cf5728"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6a02a3c7950cafaadcd46a226ad9e12fc9744652cc69f9e5534f98b47f3bbcf"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10b8dd31e10f32410751b3430996f9807fc4d1587ca69772e2aa940a82ab571a"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edc0202099ea1d82844316604e17d2b175044f9bcb6b398aab781eba957224bd"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b891a2f68e09c5ef989007fac11476ed33c5c9994449a4e2c3386529d703dc8b"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:71ef3b9be10070360f289aea4838c784f8b851be3ba58cf796262b57775c2f14"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:55602981b2dbf8184c098bc10287e8c245e351cd4fdcad050bd7199d5a8bf514"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:46fb9970aa5eeca547d7aa0de5d4b124a288b42eaefac677bde805013c95725c"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:520b7a142d2524f999447b3a0cf95115df81c4f33003c51a6ab637cbda9d0bf4"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-win32.whl", hash = "sha256:8ec8ef42c6cd5856a7613dcd1eaf21e5573b2185263d87d27c8edcae33b62a61"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:baec8148d6b8bd5cee1ae138ba658c71f5b03e0d69d5907703e3e1df96db5e41"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63a6f59e2d01310f754c270e4a257426fe5a591dc487f1983b3bbe793cf6bac6"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d6bfc32a68bc0933819cfdfe45f9abc3cae3877e1d90aac7259d57e6e0f85b1"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4f3100d86dcd03c03f7e9c3fdb23d92e32abbca07e7c13ebd7ddfbcb06f5991f"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39b70a6f88eebe239fa775190796d55a33cfb6d36b9ffdd37843f7c4c1b5dc67"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e12f8ee80aa35e746230a2af83e81bd6b52daa92a8afaef4fea4a2ce9b9f4fa"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b6cefa579e1237ce198619b76eaa148b71894fb0d6bcf9024460f9bf30fd228"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:61f1e3fb621f5420523abb71f5771a204b33c21d31e7d9d86881b2cffe92c47c"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4f6e2a839f83a6a76854d12dbebde50e4b1afa63e27761549d006fa53e9aa80e"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:1ec937546cad86d0dce5396748bf392bb7b62a9eeb8c66efac60e947697f0e58"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:82ca51ff0fc5b641a2d4e1cc8c5ff108699b7a56d7f3ad6f6da9dbb6f0145b48"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:633968254f8d421e70f91c6ebe71ed0ab140220469cf87a9857e21c16687c034"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-win32.whl", hash = "sha256:c0c72d34e7de5604df0fde3644cc079feee5e55464967d10b24b1de268deceb9"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:63accd11149c0f9a99e3bc095bbdb5a464862d77a7e309ad5938fbc8721235ae"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5a3580a4fdc4ac05f9e53c57f965e3594b2f99796231380adb2baaab96e22761"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2465aa50c9299d615d757c1c888bc6fef384b7c4aec81c05a0172b4400f98557"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cb7cd68814308aade9d0c93c5bd2ade9f9441666f8ba5aa9c2d4b389cb5e2a45"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91e43805ccafa0a91831f9cd5443aa34528c0c3f2cc48c4cb3d9a7721053874b"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:854cc74367180beb327ab9d00f964f6d91da06450b0855cbbb09187bcdb02de5"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c15070ebf11b8b7fd1bfff7217e9324963c82dbdf6182ff7050519e350e7ad9f"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c4c99f98fc3a1835af8179dcc9013f93594d0670e2fa80c83aa36346ee763d2"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3fb765362688821404ad6cf86772fc54993ec11577cd5a92ac44b4c2ba52155b"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dced27917823df984fe0c80a5c4ad75cf58df0fbfae890bc08004cd3888922a2"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a66bcdf19c1a523e41b8e9d53d0cedbfbac2e93c649a2e9502cb26c014d0980c"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ecd26be9f112c4f96718290c10f4caea6cc798459a3a76636b817a0ed7874e42"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3f70fd716855cd3b855316b226a1ac8bdb3caf4f7ea96edcccc6f484217c9597"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:17a866d61259c7de1bdadef418a37755050ddb4b922df8b356503234fff7932c"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-win32.whl", hash = "sha256:548eefad783ed787b38cb6f9a574bd8664468cc76d1538215d510a3cd41406cb"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:45f053a0ece92c734d874861ffe6e3cc92150e32136dd59ab1fb070575189c97"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bc791ec3fd0c4309a753f95bb6c749ef0d8ea3aea91f07ee1cf06b7b02118f2f"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0c8c61fb505c7dad1d251c284e712d4e0372cef3b067f7ddf82a7fa82e1e9a93"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2c092be3885a1b7899cd85ce24acedc1034199d6fca1483fa2c3a35c86e43041"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2000c54c395d9e5e44c99dc7c20a64dc371f777faf8bae4919ad3e99ce5253e"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4cb50a0335382aac15c31b61d8531bc9bb657cfd848b1d7158009472189f3d62"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c30187840d36d0ba2893bc3271a36a517a717f9fd383a98e2697ee890a37c273"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe81b35c33772e56f4b6cf62cf4aedc1762ef7162a31e6ac7fe5e40d0149eb67"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0bf89afcbcf4d1bb2652f6580e5e55a840fdf87384f6063c4a4f0c95e378656"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:06cf46bdff72f58645434d467bf5228080801298fbba19fe268a01b4534467f5"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3c66df3f41abee950d6638adc7eac4730a306b022570f71dd0bd6ba53503ab57"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd805513198304026bd379d1d516afbf6c3c13f4382134a2c526b8b854da1c2e"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:9505dc359edb6a330efcd2be825fdb73ee3e628d9010597aa1aee5aa63442e97"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:31445f38053476a0c4e6d12b047b08ced81e2c7c712e5a1ad97bc913256f91b2"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-win32.whl", hash = "sha256:bd28b31730f0e982ace8663d108e01199098432a30a4c410d06fe08fdb9e93f4"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:555fe186da0068d3354cdf4bbcbc609b0ecae4d04c921cc13e209eece7720727"}, + {file = "charset_normalizer-3.3.1-py3-none-any.whl", hash = "sha256:800561453acdecedaac137bf09cd719c7a440b6800ec182f077bb8e7025fb708"}, +] + +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "click-didyoumean" +version = "0.3.0" +description = "Enables git-like *did-you-mean* feature in click" +optional = false +python-versions = ">=3.6.2,<4.0.0" +files = [ + {file = "click-didyoumean-0.3.0.tar.gz", hash = "sha256:f184f0d851d96b6d29297354ed981b7dd71df7ff500d82fa6d11f0856bee8035"}, + {file = "click_didyoumean-0.3.0-py3-none-any.whl", hash = "sha256:a0713dc7a1de3f06bc0df5a9567ad19ead2d3d5689b434768a6145bff77c0667"}, +] + +[package.dependencies] +click = ">=7" + +[[package]] +name = "click-plugins" +version = "1.1.1" +description = "An extension module for click to enable registering CLI commands via setuptools entry-points." +optional = false +python-versions = "*" +files = [ + {file = "click-plugins-1.1.1.tar.gz", hash = "sha256:46ab999744a9d831159c3411bb0c79346d94a444df9a3a3742e9ed63645f264b"}, + {file = "click_plugins-1.1.1-py2.py3-none-any.whl", hash = "sha256:5d262006d3222f5057fd81e1623d4443e41dcda5dc815c06b442aa3c02889fc8"}, +] + +[package.dependencies] +click = ">=4.0" + +[package.extras] +dev = ["coveralls", "pytest (>=3.6)", "pytest-cov", "wheel"] + +[[package]] +name = "click-repl" +version = "0.3.0" +description = "REPL plugin for Click" +optional = false +python-versions = ">=3.6" +files = [ + {file = "click-repl-0.3.0.tar.gz", hash = "sha256:17849c23dba3d667247dc4defe1757fff98694e90fe37474f3feebb69ced26a9"}, + {file = "click_repl-0.3.0-py3-none-any.whl", hash = "sha256:fb7e06deb8da8de86180a33a9da97ac316751c094c6899382da7feeeeb51b812"}, +] + +[package.dependencies] +click = ">=7.0" +prompt-toolkit = ">=3.0.36" + +[package.extras] +testing = ["pytest (>=7.2.1)", "pytest-cov (>=4.0.0)", "tox (>=4.4.3)"] + +[[package]] +name = "cmarkgfm" +version = "2022.10.27" +description = "Minimal bindings to GitHub's fork of cmark" +optional = false +python-versions = "*" +files = [ + {file = "cmarkgfm-2022.10.27-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a6a3970cf1c8ba4465d5046dd6a6d7f6024e67d6eec812a4701a21c5161a2fbd"}, + {file = "cmarkgfm-2022.10.27-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4325b75a3b5b802d5edcc2378aa6405a1e5df0aeeec583d1b05d73b0562fa7d0"}, + {file = "cmarkgfm-2022.10.27-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:216a540e85258839cffa7274731a87d91b3e17c9079b3b02467c312e784b5281"}, + {file = "cmarkgfm-2022.10.27-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0756ea0f6b55eff2617ea0518d6730e37d6077c10baaabbe8b46210ff5a250ef"}, + {file = "cmarkgfm-2022.10.27-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a91279ab8e2869c19120595e41ebd81a6f5034c1e6b1cfc5e81cd80d40bf3eb"}, + {file = "cmarkgfm-2022.10.27-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:69a769feb1b2d16982fe952afd44e124a4d306a44cdfd6857e74b8eb5d47d765"}, + {file = "cmarkgfm-2022.10.27-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:21557c06a411b1d754eed7f6fc9a8ff41f8a4a004b32c8bd2cec2ab3f3cb4d3c"}, + {file = "cmarkgfm-2022.10.27-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8e9f038a4f0e54c135e468994f1ea97141b086d1f1bd8f498c12f3d559017e8e"}, + {file = "cmarkgfm-2022.10.27-cp310-cp310-win32.whl", hash = "sha256:5fc7178a6afd69a5dfc197558791cecedead9fc77e95ec63c201e8219ce33000"}, + {file = "cmarkgfm-2022.10.27-cp310-cp310-win_amd64.whl", hash = "sha256:f17677e66f95f25999c959c3f5361c05e739ad4f6b70ab9fdd24b1734c3ab029"}, + {file = "cmarkgfm-2022.10.27-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:670b414274edf3ecc0a950a80580e1de553c599a30658827a5d7f7bccbde5843"}, + {file = "cmarkgfm-2022.10.27-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8830dfb61251f2b677dea7ffc531c3f6037f7e9a66a14ad24bdaf3cefe2dc8c4"}, + {file = "cmarkgfm-2022.10.27-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8daf62cddc81b31a8f3c9093936c4cb75b25a8024c09f276cb027f1647e3326"}, + {file = "cmarkgfm-2022.10.27-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210c0f0dbc1aadab30bc75c48b14b645414733a668df52b43058028e43a046e8"}, + {file = "cmarkgfm-2022.10.27-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd6315e1036d31884bff25719636e3499a7f4593b0f7b47dc742678328f2f26f"}, + {file = "cmarkgfm-2022.10.27-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b0b13eac6194d59f9d3ab44af7076221510e788572f34e25104ad47b33d960e1"}, + {file = "cmarkgfm-2022.10.27-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:76beb5b50b32d7bafec2154608a037601a2186d15df95cec6ab4cc937afca365"}, + {file = "cmarkgfm-2022.10.27-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d3fd62dd65c3a64ced175a1447ea41b01a7ac1c0df1c8358323267c9326b7745"}, + {file = "cmarkgfm-2022.10.27-cp311-cp311-win32.whl", hash = "sha256:1790164f84e6b037d0b39df11f757e021a9f9c313681297a051d50bc7b5249fc"}, + {file = "cmarkgfm-2022.10.27-cp311-cp311-win_amd64.whl", hash = "sha256:799cf03a82a7849d975a3b955798d5e439a08fb678b657c5078115dc61314674"}, + {file = "cmarkgfm-2022.10.27-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:ca0e03a590c6f62738d208f8689da08eae9d3bcc2f4dd97e38df45d8dbc333ab"}, + {file = "cmarkgfm-2022.10.27-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2d3bdb7e525abd03366a57eabd03e0c3f3f36bbf8af2267200605b7b712763b"}, + {file = "cmarkgfm-2022.10.27-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47e267ce890b579585a32f77d347d61de2390b517cfc52bb4ca67c5c4b4c055a"}, + {file = "cmarkgfm-2022.10.27-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f938c503fce528d9cb715314134f8900cf09ddbd7e2bea88cf54a4bad58d0d5b"}, + {file = "cmarkgfm-2022.10.27-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:c82af8cdb76a71459662e447f9b1545ae6146cb9287df978705a298f87a76a90"}, + {file = "cmarkgfm-2022.10.27-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:89dcd4fea4ae44f1a0697cf805b6931a126b2b3ea23ed1ccdad7e020425224a9"}, + {file = "cmarkgfm-2022.10.27-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:ddc2bbb5572722758787066f5f841745c58452e28c59ce7c13b7228be1cb48f3"}, + {file = "cmarkgfm-2022.10.27-cp36-cp36m-win32.whl", hash = "sha256:ccfc25b5abfe1398426f099d840b5fa7dec118b44f06833e2ba8b67c6ffc12d9"}, + {file = "cmarkgfm-2022.10.27-cp36-cp36m-win_amd64.whl", hash = "sha256:fbec94c3e91b5e03d90a2cc2e865179e5bc58673e92b03ba64b520a97a0e9219"}, + {file = "cmarkgfm-2022.10.27-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0023de4b19bb557b143bed274f76cb36551f7f1d1cdffd29b6cde646b85d9ffb"}, + {file = "cmarkgfm-2022.10.27-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6672784820981d315b695bb7ce08d40886502368e133b453d675ff6f2fffae49"}, + {file = "cmarkgfm-2022.10.27-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07a06d424ccef98528cba1158946f92117e07579f1dc9942ed4fd70f81693b9f"}, + {file = "cmarkgfm-2022.10.27-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a6e597bdf595f81dc214e821b579b8d665116c55ed5288b599ae941e446098"}, + {file = "cmarkgfm-2022.10.27-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:071f5f0dac9475bab6a065878f248a69be52a7736b6c661e06ca7199f25fe097"}, + {file = "cmarkgfm-2022.10.27-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:0176d51fb57162c642b1d2c70048950a5ae119af81e77565a0383b992b1f86d6"}, + {file = "cmarkgfm-2022.10.27-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8744be702511464d04c34000005009607471f1afe65d6037777747d6b4607e5f"}, + {file = "cmarkgfm-2022.10.27-cp37-cp37m-win32.whl", hash = "sha256:483e48613f5c7b3350cdabfd0f69aaa086513542d0de533f39e5669bf4df5de4"}, + {file = "cmarkgfm-2022.10.27-cp37-cp37m-win_amd64.whl", hash = "sha256:123ad8d50fbedacd036760ba46e36170bad9dd2c1e83655d8622b7803169bb49"}, + {file = "cmarkgfm-2022.10.27-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ea7d6cb95e2d74049cf08fde4ca6cbf030b9bf9ef75009847bbefb35094bb4c2"}, + {file = "cmarkgfm-2022.10.27-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:98c0527153daf16589ef095aa72f06a4bdb9213433ff47811fbc4172c91d865b"}, + {file = "cmarkgfm-2022.10.27-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cfe84b8912b355b8036c093ecdd6abbe6df075176879a49867dd72b9e53449f3"}, + {file = "cmarkgfm-2022.10.27-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20e897160be161161a565df94ce502714a1aa63af3ad682e6d1f1c7e6656fdbb"}, + {file = "cmarkgfm-2022.10.27-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5bad39b832f734f588aea00868e53ba1aaf058d569e40e5c9016702edebf88e8"}, + {file = "cmarkgfm-2022.10.27-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:80cf50b52bc0a47c032706de27b9526b6035c73b57ce06662021144cba4b6c5e"}, + {file = "cmarkgfm-2022.10.27-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:90ae1b4b2c6b92f8f5b1e5416a2f5b1bba7a5f9aea29b0de79767ed80655527a"}, + {file = "cmarkgfm-2022.10.27-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ea8a84d3702ccc32f8dfd0917dfb95f3d1843a0b6f85131c5cbfd1480d1d31ee"}, + {file = "cmarkgfm-2022.10.27-cp38-cp38-win32.whl", hash = "sha256:c66077349e7f7d954aa37d770310de5a8214ac9dca9756440f99e008a0e693de"}, + {file = "cmarkgfm-2022.10.27-cp38-cp38-win_amd64.whl", hash = "sha256:cc70b89309404dd84a524d439aa2b2e54872e0f623f9523bd77e66526251954f"}, + {file = "cmarkgfm-2022.10.27-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5a39333e1fdcd0116c24adc33423999913865bd3cc83fc44b2218aac7fbe5637"}, + {file = "cmarkgfm-2022.10.27-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5342c6d12e343cc66b4b8dcd09fc0c1977cb32fd1d57c15bd756876606591ee9"}, + {file = "cmarkgfm-2022.10.27-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c804446b941dc08dcc3d2def3913cfc4bae954b80babfaa2a502e8ebdea29185"}, + {file = "cmarkgfm-2022.10.27-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c04921575e412a6459d645a45ca987061b17d89310c92aedf108f97f2b8b7b91"}, + {file = "cmarkgfm-2022.10.27-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1013ce61db1dd3febcaca1ee42cad9eb823852bb76cbae61c1488734ce51f2b7"}, + {file = "cmarkgfm-2022.10.27-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:db3449fdb87752be5ad0698d6f2ca030af320cdf71ebc9a1ebae1b9c1d3661c8"}, + {file = "cmarkgfm-2022.10.27-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:325c03644da5ab81a7071aae6fbafa3beb22413f7fd7440baf6d510cfcf7be21"}, + {file = "cmarkgfm-2022.10.27-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:27149c63b1190ee6e7dd4b32d0a2c313bc1856bcdde7a42a0a5b6ae42d97ed94"}, + {file = "cmarkgfm-2022.10.27-cp39-cp39-win32.whl", hash = "sha256:e65e492407d7cb3b695f3f715a1cbe6f97db69eb14011b8f156fc10c758b55c7"}, + {file = "cmarkgfm-2022.10.27-cp39-cp39-win_amd64.whl", hash = "sha256:3f510fafa9d904336eecc3aa41536fd287c2d32baa21b14d48950ced802ca531"}, + {file = "cmarkgfm-2022.10.27.tar.gz", hash = "sha256:93d9ac7716ea901ca0bfd18ae3b68f1f6bf51de0830c3f233ef734fcd52a0799"}, +] + +[package.dependencies] +cffi = ">=1.15.0" + +[[package]] +name = "cognitive-complexity" +version = "1.3.0" +description = "Library to calculate Python functions cognitive complexity via code" +optional = false +python-versions = ">=3.6" +files = [ + {file = "cognitive_complexity-1.3.0.tar.gz", hash = "sha256:a0cfbd47dee0b19f4056f892389f501694b205c3af69fb703cc744541e03dde5"}, +] + +[package.dependencies] +setuptools = "*" + +[[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 = "coverage" +version = "7.3.2" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "coverage-7.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d872145f3a3231a5f20fd48500274d7df222e291d90baa2026cc5152b7ce86bf"}, + {file = "coverage-7.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:310b3bb9c91ea66d59c53fa4989f57d2436e08f18fb2f421a1b0b6b8cc7fffda"}, + {file = "coverage-7.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f47d39359e2c3779c5331fc740cf4bce6d9d680a7b4b4ead97056a0ae07cb49a"}, + {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa72dbaf2c2068404b9870d93436e6d23addd8bbe9295f49cbca83f6e278179c"}, + {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:beaa5c1b4777f03fc63dfd2a6bd820f73f036bfb10e925fce067b00a340d0f3f"}, + {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:dbc1b46b92186cc8074fee9d9fbb97a9dd06c6cbbef391c2f59d80eabdf0faa6"}, + {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:315a989e861031334d7bee1f9113c8770472db2ac484e5b8c3173428360a9148"}, + {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d1bc430677773397f64a5c88cb522ea43175ff16f8bfcc89d467d974cb2274f9"}, + {file = "coverage-7.3.2-cp310-cp310-win32.whl", hash = "sha256:a889ae02f43aa45032afe364c8ae84ad3c54828c2faa44f3bfcafecb5c96b02f"}, + {file = "coverage-7.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:c0ba320de3fb8c6ec16e0be17ee1d3d69adcda99406c43c0409cb5c41788a611"}, + {file = "coverage-7.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ac8c802fa29843a72d32ec56d0ca792ad15a302b28ca6203389afe21f8fa062c"}, + {file = "coverage-7.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:89a937174104339e3a3ffcf9f446c00e3a806c28b1841c63edb2b369310fd074"}, + {file = "coverage-7.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e267e9e2b574a176ddb983399dec325a80dbe161f1a32715c780b5d14b5f583a"}, + {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2443cbda35df0d35dcfb9bf8f3c02c57c1d6111169e3c85fc1fcc05e0c9f39a3"}, + {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4175e10cc8dda0265653e8714b3174430b07c1dca8957f4966cbd6c2b1b8065a"}, + {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf38419fb1a347aaf63481c00f0bdc86889d9fbf3f25109cf96c26b403fda1"}, + {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5c913b556a116b8d5f6ef834038ba983834d887d82187c8f73dec21049abd65c"}, + {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1981f785239e4e39e6444c63a98da3a1db8e971cb9ceb50a945ba6296b43f312"}, + {file = "coverage-7.3.2-cp311-cp311-win32.whl", hash = "sha256:43668cabd5ca8258f5954f27a3aaf78757e6acf13c17604d89648ecc0cc66640"}, + {file = "coverage-7.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10c39c0452bf6e694511c901426d6b5ac005acc0f78ff265dbe36bf81f808a2"}, + {file = "coverage-7.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4cbae1051ab791debecc4a5dcc4a1ff45fc27b91b9aee165c8a27514dd160836"}, + {file = "coverage-7.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12d15ab5833a997716d76f2ac1e4b4d536814fc213c85ca72756c19e5a6b3d63"}, + {file = "coverage-7.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c7bba973ebee5e56fe9251300c00f1579652587a9f4a5ed8404b15a0471f216"}, + {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe494faa90ce6381770746077243231e0b83ff3f17069d748f645617cefe19d4"}, + {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6e9589bd04d0461a417562649522575d8752904d35c12907d8c9dfeba588faf"}, + {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d51ac2a26f71da1b57f2dc81d0e108b6ab177e7d30e774db90675467c847bbdf"}, + {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:99b89d9f76070237975b315b3d5f4d6956ae354a4c92ac2388a5695516e47c84"}, + {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fa28e909776dc69efb6ed975a63691bc8172b64ff357e663a1bb06ff3c9b589a"}, + {file = "coverage-7.3.2-cp312-cp312-win32.whl", hash = "sha256:289fe43bf45a575e3ab10b26d7b6f2ddb9ee2dba447499f5401cfb5ecb8196bb"}, + {file = "coverage-7.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7dbc3ed60e8659bc59b6b304b43ff9c3ed858da2839c78b804973f613d3e92ed"}, + {file = "coverage-7.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f94b734214ea6a36fe16e96a70d941af80ff3bfd716c141300d95ebc85339738"}, + {file = "coverage-7.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:af3d828d2c1cbae52d34bdbb22fcd94d1ce715d95f1a012354a75e5913f1bda2"}, + {file = "coverage-7.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:630b13e3036e13c7adc480ca42fa7afc2a5d938081d28e20903cf7fd687872e2"}, + {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9eacf273e885b02a0273bb3a2170f30e2d53a6d53b72dbe02d6701b5296101c"}, + {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8f17966e861ff97305e0801134e69db33b143bbfb36436efb9cfff6ec7b2fd9"}, + {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b4275802d16882cf9c8b3d057a0839acb07ee9379fa2749eca54efbce1535b82"}, + {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:72c0cfa5250f483181e677ebc97133ea1ab3eb68645e494775deb6a7f6f83901"}, + {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cb536f0dcd14149425996821a168f6e269d7dcd2c273a8bff8201e79f5104e76"}, + {file = "coverage-7.3.2-cp38-cp38-win32.whl", hash = "sha256:307adb8bd3abe389a471e649038a71b4eb13bfd6b7dd9a129fa856f5c695cf92"}, + {file = "coverage-7.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:88ed2c30a49ea81ea3b7f172e0269c182a44c236eb394718f976239892c0a27a"}, + {file = "coverage-7.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b631c92dfe601adf8f5ebc7fc13ced6bb6e9609b19d9a8cd59fa47c4186ad1ce"}, + {file = "coverage-7.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d3d9df4051c4a7d13036524b66ecf7a7537d14c18a384043f30a303b146164e9"}, + {file = "coverage-7.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f7363d3b6a1119ef05015959ca24a9afc0ea8a02c687fe7e2d557705375c01f"}, + {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f11cc3c967a09d3695d2a6f03fb3e6236622b93be7a4b5dc09166a861be6d25"}, + {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:149de1d2401ae4655c436a3dced6dd153f4c3309f599c3d4bd97ab172eaf02d9"}, + {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3a4006916aa6fee7cd38db3bfc95aa9c54ebb4ffbfc47c677c8bba949ceba0a6"}, + {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9028a3871280110d6e1aa2df1afd5ef003bab5fb1ef421d6dc748ae1c8ef2ebc"}, + {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9f805d62aec8eb92bab5b61c0f07329275b6f41c97d80e847b03eb894f38d083"}, + {file = "coverage-7.3.2-cp39-cp39-win32.whl", hash = "sha256:d1c88ec1a7ff4ebca0219f5b1ef863451d828cccf889c173e1253aa84b1e07ce"}, + {file = "coverage-7.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b4767da59464bb593c07afceaddea61b154136300881844768037fd5e859353f"}, + {file = "coverage-7.3.2-pp38.pp39.pp310-none-any.whl", hash = "sha256:ae97af89f0fbf373400970c0a21eef5aa941ffeed90aee43650b81f7d7f47637"}, + {file = "coverage-7.3.2.tar.gz", hash = "sha256:be32ad29341b0170e795ca590e1c07e81fc061cb5b10c74ce7203491484404ef"}, +] + +[package.extras] +toml = ["tomli"] + +[[package]] +name = "cryptography" +version = "41.0.5" +description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." +optional = false +python-versions = ">=3.7" +files = [ + {file = "cryptography-41.0.5-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:da6a0ff8f1016ccc7477e6339e1d50ce5f59b88905585f77193ebd5068f1e797"}, + {file = "cryptography-41.0.5-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:b948e09fe5fb18517d99994184854ebd50b57248736fd4c720ad540560174ec5"}, + {file = "cryptography-41.0.5-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d38e6031e113b7421db1de0c1b1f7739564a88f1684c6b89234fbf6c11b75147"}, + {file = "cryptography-41.0.5-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e270c04f4d9b5671ebcc792b3ba5d4488bf7c42c3c241a3748e2599776f29696"}, + {file = "cryptography-41.0.5-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ec3b055ff8f1dce8e6ef28f626e0972981475173d7973d63f271b29c8a2897da"}, + {file = "cryptography-41.0.5-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:7d208c21e47940369accfc9e85f0de7693d9a5d843c2509b3846b2db170dfd20"}, + {file = "cryptography-41.0.5-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:8254962e6ba1f4d2090c44daf50a547cd5f0bf446dc658a8e5f8156cae0d8548"}, + {file = "cryptography-41.0.5-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:a48e74dad1fb349f3dc1d449ed88e0017d792997a7ad2ec9587ed17405667e6d"}, + {file = "cryptography-41.0.5-cp37-abi3-win32.whl", hash = "sha256:d3977f0e276f6f5bf245c403156673db103283266601405376f075c849a0b936"}, + {file = "cryptography-41.0.5-cp37-abi3-win_amd64.whl", hash = "sha256:73801ac9736741f220e20435f84ecec75ed70eda90f781a148f1bad546963d81"}, + {file = "cryptography-41.0.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3be3ca726e1572517d2bef99a818378bbcf7d7799d5372a46c79c29eb8d166c1"}, + {file = "cryptography-41.0.5-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:e886098619d3815e0ad5790c973afeee2c0e6e04b4da90b88e6bd06e2a0b1b72"}, + {file = "cryptography-41.0.5-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:573eb7128cbca75f9157dcde974781209463ce56b5804983e11a1c462f0f4e88"}, + {file = "cryptography-41.0.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0c327cac00f082013c7c9fb6c46b7cc9fa3c288ca702c74773968173bda421bf"}, + {file = "cryptography-41.0.5-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:227ec057cd32a41c6651701abc0328135e472ed450f47c2766f23267b792a88e"}, + {file = "cryptography-41.0.5-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:22892cc830d8b2c89ea60148227631bb96a7da0c1b722f2aac8824b1b7c0b6b8"}, + {file = "cryptography-41.0.5-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:5a70187954ba7292c7876734183e810b728b4f3965fbe571421cb2434d279179"}, + {file = "cryptography-41.0.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:88417bff20162f635f24f849ab182b092697922088b477a7abd6664ddd82291d"}, + {file = "cryptography-41.0.5-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c707f7afd813478e2019ae32a7c49cd932dd60ab2d2a93e796f68236b7e1fbf1"}, + {file = "cryptography-41.0.5-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:580afc7b7216deeb87a098ef0674d6ee34ab55993140838b14c9b83312b37b86"}, + {file = "cryptography-41.0.5-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fba1e91467c65fe64a82c689dc6cf58151158993b13eb7a7f3f4b7f395636723"}, + {file = "cryptography-41.0.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0d2a6a598847c46e3e321a7aef8af1436f11c27f1254933746304ff014664d84"}, + {file = "cryptography-41.0.5.tar.gz", hash = "sha256:392cb88b597247177172e02da6b7a63deeff1937fa6fec3bbf902ebd75d97ec7"}, +] + +[package.dependencies] +cffi = ">=1.12" + +[package.extras] +docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] +docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"] +nox = ["nox"] +pep8test = ["black", "check-sdist", "mypy", "ruff"] +sdist = ["build"] +ssh = ["bcrypt (>=3.1.5)"] +test = ["pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] +test-randomorder = ["pytest-randomly"] + +[[package]] +name = "decorator" +version = "5.1.1" +description = "Decorators for Humans" +optional = false +python-versions = ">=3.5" +files = [ + {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, + {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, +] + +[[package]] +name = "dj-rest-auth" +version = "5.0.1" +description = "Authentication and Registration in Django Rest Framework" +optional = false +python-versions = ">=3.6" +files = [ + {file = "dj-rest-auth-5.0.1.tar.gz", hash = "sha256:2f574edd7bcc9a421e6e1d9d47f7b1eb56b71eb797927be135c995ea546dd9b5"}, +] + +[package.dependencies] +Django = ">=3.2" +djangorestframework = ">=3.13.0" + +[package.extras] +with-social = ["django-allauth (>=0.55.0,<0.56.0)"] + +[[package]] +name = "django" +version = "4.2.6" +description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design." +optional = false +python-versions = ">=3.8" +files = [ + {file = "Django-4.2.6-py3-none-any.whl", hash = "sha256:a64d2487cdb00ad7461434320ccc38e60af9c404773a2f95ab0093b4453a3215"}, + {file = "Django-4.2.6.tar.gz", hash = "sha256:08f41f468b63335aea0d904c5729e0250300f6a1907bf293a65499496cdbc68f"}, +] + +[package.dependencies] +asgiref = ">=3.6.0,<4" +sqlparse = ">=0.3.1" +tzdata = {version = "*", markers = "sys_platform == \"win32\""} + +[package.extras] +argon2 = ["argon2-cffi (>=19.1.0)"] +bcrypt = ["bcrypt"] + +[[package]] +name = "django-anymail" +version = "10.1" +description = "Django email backends and webhooks for Amazon SES, Brevo (Sendinblue), MailerSend, Mailgun, Mailjet, Mandrill, Postal, Postmark, SendGrid, and SparkPost" +optional = false +python-versions = ">=3.7" +files = [ + {file = "django_anymail-10.1-py3-none-any.whl", hash = "sha256:e0a65c1e235dcb863dab67a3e193e899a48503b650df483d7b73f73983fd874b"}, + {file = "django_anymail-10.1.tar.gz", hash = "sha256:5c4f26bd0f5507324ed1da31e430bca3293bb2c16f386e813484f2ea2df83d06"}, +] + +[package.dependencies] +django = ">=2.0" +requests = ">=2.4.3" +urllib3 = ">=1.25.0" + +[package.extras] +amazon-ses = ["boto3"] +postal = ["cryptography"] + +[[package]] +name = "django-axes" +version = "6.1.1" +description = "Keep track of failed login attempts in Django-powered sites." +optional = false +python-versions = ">=3.7" +files = [ + {file = "django-axes-6.1.1.tar.gz", hash = "sha256:cd1bc4f7becc8e9243eb4090dffa258d7d7125ca0ce3153b6ffc920bccbf2c3f"}, + {file = "django_axes-6.1.1-py3-none-any.whl", hash = "sha256:29c48ff5f09046afd5e9a16e96d3bbb79f6c11c59f0a7bbd732559e60d0aa9fa"}, +] + +[package.dependencies] +django = ">=3.2" +setuptools = "*" + +[package.extras] +ipware = ["django-ipware (>=3)"] + +[[package]] +name = "django-behaviors" +version = "0.5.1" +description = "Common behaviors for Django Models, e.g. Timestamps, Publishing, Authoring/Editing and more." +optional = false +python-versions = "*" +files = [ + {file = "django-behaviors-0.5.1.tar.gz", hash = "sha256:75e6828573c25ffa71c8ce6c568d294fc659b3b6d572507b012ce70fbb27aaff"}, + {file = "django_behaviors-0.5.1-py2.py3-none-any.whl", hash = "sha256:1ac2ec9c9e919ca4b962f9dee861a53f5af27749c8d13a21077b5a61fb879501"}, +] + +[[package]] +name = "django-cachalot" +version = "2.6.1" +description = "Caches your Django ORM queries and automatically invalidates them." +optional = false +python-versions = "*" +files = [ + {file = "django-cachalot-2.6.1.tar.gz", hash = "sha256:6772d2d2cc2efa8b6484b242567a5a01847f8e1e8c8ef59a7b9a367b2edfa929"}, + {file = "django_cachalot-2.6.1-py3-none-any.whl", hash = "sha256:442ad5321e646ce33ec7825c289476373b8926d23b4c1b8b9659879306e44748"}, +] + +[package.dependencies] +Django = ">=3.2,<4.3" + +[[package]] +name = "django-cors-headers" +version = "4.3.0" +description = "django-cors-headers is a Django application for handling the server headers required for Cross-Origin Resource Sharing (CORS)." +optional = false +python-versions = ">=3.8" +files = [ + {file = "django_cors_headers-4.3.0-py3-none-any.whl", hash = "sha256:bd36c7aea0d070e462f3383f0dc9ef717e5fdc2b10a99c98c285f16da84ffba2"}, + {file = "django_cors_headers-4.3.0.tar.gz", hash = "sha256:25aabc94d4837678c1edf442c7f68a5f5fd151f6767b0e0b01c61a2179d02711"}, +] + +[package.dependencies] +Django = ">=3.2" + +[[package]] +name = "django-debug-toolbar" +version = "4.2.0" +description = "A configurable set of panels that display various debug information about the current request/response." +optional = false +python-versions = ">=3.8" +files = [ + {file = "django_debug_toolbar-4.2.0-py3-none-any.whl", hash = "sha256:af99128c06e8e794479e65ab62cc6c7d1e74e1c19beb44dcbf9bad7a9c017327"}, + {file = "django_debug_toolbar-4.2.0.tar.gz", hash = "sha256:bc7fdaafafcdedefcc67a4a5ad9dac96efd6e41db15bc74d402a54a2ba4854dc"}, +] + +[package.dependencies] +django = ">=3.2.4" +sqlparse = ">=0.2" + +[[package]] +name = "django-environ" +version = "0.11.2" +description = "A package that allows you to utilize 12factor inspired environment variables to configure your Django application." +optional = false +python-versions = ">=3.6,<4" +files = [ + {file = "django-environ-0.11.2.tar.gz", hash = "sha256:f32a87aa0899894c27d4e1776fa6b477e8164ed7f6b3e410a62a6d72caaf64be"}, + {file = "django_environ-0.11.2-py2.py3-none-any.whl", hash = "sha256:0ff95ab4344bfeff693836aa978e6840abef2e2f1145adff7735892711590c05"}, +] + +[package.extras] +develop = ["coverage[toml] (>=5.0a4)", "furo (>=2021.8.17b43,<2021.9.dev0)", "pytest (>=4.6.11)", "sphinx (>=3.5.0)", "sphinx-notfound-page"] +docs = ["furo (>=2021.8.17b43,<2021.9.dev0)", "sphinx (>=3.5.0)", "sphinx-notfound-page"] +testing = ["coverage[toml] (>=5.0a4)", "pytest (>=4.6.11)"] + +[[package]] +name = "django-filter" +version = "23.3" +description = "Django-filter is a reusable Django application for allowing users to filter querysets dynamically." +optional = false +python-versions = ">=3.7" +files = [ + {file = "django-filter-23.3.tar.gz", hash = "sha256:015fe155582e1805b40629344e4a6cf3cc40450827d294d040b4b8c1749a9fa6"}, + {file = "django_filter-23.3-py3-none-any.whl", hash = "sha256:65bc5d1d8f4fff3aaf74cb5da537b6620e9214fb4b3180f6c560776b1b6dccd0"}, +] + +[package.dependencies] +Django = ">=3.2" + +[[package]] +name = "django-healthchecks" +version = "1.5.0" +description = "Simple Django app/framework to publish health checks" +optional = false +python-versions = "*" +files = [ + {file = "django-healthchecks-1.5.0.tar.gz", hash = "sha256:0f167deaa30bde59552796799abf2a97a118bc190e8601eef713379703cf9f64"}, + {file = "django_healthchecks-1.5.0-py2.py3-none-any.whl", hash = "sha256:25eb021a4a94240b28d996e82775ad6c3b392a2b262360b965a24b88fcfad78d"}, +] + +[package.dependencies] +certifi = ">=2020.6.20" +Django = ">=3.2" +requests = ">=2.24.0" + +[package.extras] +docs = ["sphinx (>=1.4.0)"] +test = ["coverage[toml] (==5.2)", "flake8 (==3.8.3)", "flake8-blind-except (==0.1.1)", "flake8-debugger (==3.2.1)", "freezegun (==0.3.15)", "isort (==5.0.6)", "pytest (==6.2.5)", "pytest-django (==3.9.0)", "requests-mock (==1.8.0)"] + +[[package]] +name = "django-ipware" +version = "5.0.1" +description = "A Django application to retrieve user's IP address" +optional = false +python-versions = ">=3.8" +files = [ + {file = "django-ipware-5.0.1.tar.gz", hash = "sha256:176fddb27d8d0f96fe3872fe03a781ea96638553e05842d89c12a3dd9bedf5f5"}, + {file = "django_ipware-5.0.1-py2.py3-none-any.whl", hash = "sha256:1d34382cb95e0fd0273321a51c39429c5b435c01754c02218658acf151ce9107"}, +] + +[[package]] +name = "django-prettyjson" +version = "0.4.1" +description = "Enables pretty JSON viewer in Django forms, admin, or templates" +optional = false +python-versions = "*" +files = [ + {file = "django-prettyjson-0.4.1.tar.gz", hash = "sha256:b758a5f3c073db93e17485b4eb9cb19e9838f6e5d6cb91096d795e015e28d3bd"}, + {file = "django_prettyjson-0.4.1-py2.py3-none-any.whl", hash = "sha256:f9f4d73899947f17a67f61b57216612373195937fa936ba9335549fe878b3355"}, +] + +[package.dependencies] +django = ">=1.8" +six = ">=1.10.0" +standardjson = ">=0.3.1" + +[[package]] +name = "django-split-settings" +version = "1.2.0" +description = "Organize Django settings into multiple files and directories. Easily override and modify settings. Use wildcards and optional settings files." +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "django-split-settings-1.2.0.tar.gz", hash = "sha256:31415a618256b54c5cee8662cbaa72a890683b8b7465d64ba88fdd3affdd6c60"}, + {file = "django_split_settings-1.2.0-py3-none-any.whl", hash = "sha256:4b3be146776d49c61bd9dcf89fad40edb1544f13ab27a87a0b1aecf5a0d636f4"}, +] + +[[package]] +name = "django-storages" +version = "1.14.2" +description = "Support for many storage backends in Django" +optional = false +python-versions = ">=3.7" +files = [ + {file = "django-storages-1.14.2.tar.gz", hash = "sha256:51b36af28cc5813b98d5f3dfe7459af638d84428c8df4a03990c7d74d1bea4e5"}, + {file = "django_storages-1.14.2-py3-none-any.whl", hash = "sha256:1db759346b52ada6c2efd9f23d8241ecf518813eb31db9e2589207174f58f6ad"}, +] + +[package.dependencies] +Django = ">=3.2" + +[package.extras] +azure = ["azure-core (>=1.13)", "azure-storage-blob (>=12)"] +boto3 = ["boto3 (>=1.4.4)"] +dropbox = ["dropbox (>=7.2.1)"] +google = ["google-cloud-storage (>=1.27)"] +libcloud = ["apache-libcloud"] +s3 = ["boto3 (>=1.4.4)"] +sftp = ["paramiko (>=1.15)"] + +[[package]] +name = "django-stubs" +version = "4.2.6" +description = "Mypy stubs for Django" +optional = false +python-versions = ">=3.8" +files = [ + {file = "django-stubs-4.2.6.tar.gz", hash = "sha256:e60b43de662a199db4b15c803c06669e0ac5035614af291cbd3b91591f7dcc94"}, + {file = "django_stubs-4.2.6-py3-none-any.whl", hash = "sha256:2fcd257884a68dfa02de41ee5410ec805264d9b07d9b5b119e4dea82c7b8345e"}, +] + +[package.dependencies] +django = "*" +django-stubs-ext = ">=4.2.5" +types-pytz = "*" +types-PyYAML = "*" +typing-extensions = "*" + +[package.extras] +compatible-mypy = ["mypy (>=1.6.0,<1.7.0)"] + +[[package]] +name = "django-stubs-ext" +version = "4.2.5" +description = "Monkey-patching and extensions for django-stubs" +optional = false +python-versions = ">=3.8" +files = [ + {file = "django-stubs-ext-4.2.5.tar.gz", hash = "sha256:8c4d1fb5f68419b3b2474c659681a189803e27d6a5e5abf5aa0da57601b58633"}, + {file = "django_stubs_ext-4.2.5-py3-none-any.whl", hash = "sha256:921cd7ae4614e74c234bc0fe86ee75537d163addfe1fc6f134bf03e29d86c01e"}, +] + +[package.dependencies] +django = "*" +typing-extensions = "*" + +[[package]] +name = "django-tree-queries" +version = "0.15.0" +description = "Tree queries with explicit opt-in, without configurability" +optional = false +python-versions = ">=3.6" +files = [ + {file = "django_tree_queries-0.15.0-py3-none-any.whl", hash = "sha256:cf11340de59d3122919fde46e99966bad40ff942df768d683383b111554134a1"}, + {file = "django_tree_queries-0.15.0.tar.gz", hash = "sha256:0e994c2a4601c021a115a397ec8d0ff7d5e614fae95947f72126e6a419c60f08"}, +] + +[package.extras] +tests = ["coverage"] + +[[package]] +name = "djangorestframework" +version = "3.14.0" +description = "Web APIs for Django, made easy." +optional = false +python-versions = ">=3.6" +files = [ + {file = "djangorestframework-3.14.0-py3-none-any.whl", hash = "sha256:eb63f58c9f218e1a7d064d17a70751f528ed4e1d35547fdade9aaf4cd103fd08"}, + {file = "djangorestframework-3.14.0.tar.gz", hash = "sha256:579a333e6256b09489cbe0a067e66abe55c6595d8926be6b99423786334350c8"}, +] + +[package.dependencies] +django = ">=3.0" +pytz = "*" + +[[package]] +name = "djangorestframework-stubs" +version = "3.14.4" +description = "PEP-484 stubs for django-rest-framework" +optional = false +python-versions = ">=3.8" +files = [ + {file = "djangorestframework-stubs-3.14.4.tar.gz", hash = "sha256:8ee8719bfeb647b92cc200e15b3cc9813d2e4468c8190777a55a121542a4b2d4"}, + {file = "djangorestframework_stubs-3.14.4-py3-none-any.whl", hash = "sha256:5be8275dd05d6629b3d1688929586ef7b6bc66b4f3f728b5e0389305f07c7a7f"}, +] + +[package.dependencies] +django-stubs = ">=4.2.5" +mypy = ">=0.991" +requests = ">=2.0.0" +types-PyYAML = ">=5.4.3" +types-requests = ">=0.1.12" +typing-extensions = ">=3.10.0" + +[package.extras] +compatible-mypy = ["mypy (>=1.6.0,<1.7.0)"] +coreapi = ["coreapi (>=2.0.0)"] +markdown = ["types-Markdown (>=0.1.5)"] + +[[package]] +name = "drf-jwt" +version = "1.19.2" +description = "JSON Web Token based authentication for Django REST framework" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +files = [ + {file = "drf-jwt-1.19.2.tar.gz", hash = "sha256:660bc66f992065cef59832adcbbdf871847e9738671c19e5121971e773768235"}, + {file = "drf_jwt-1.19.2-py2.py3-none-any.whl", hash = "sha256:63c3d4ed61a1013958cd63416e2d5c84467d8ae3e6e1be44b1fb58743dbd1582"}, +] + +[package.dependencies] +Django = ">=1.11" +djangorestframework = ">=3.7" +PyJWT = {version = ">=1.5.2,<3.0.0", extras = ["crypto"]} + +[package.extras] +dev = ["tox"] +docs = ["mkdocs (==0.13.2)"] +lint = ["black", "flake8", "isort"] +test = ["mock", "pytest (>=3.0)", "pytest-cov", "pytest-django", "pytest-runner", "six"] + +[[package]] +name = "drf-recaptcha" +version = "3.0.0" +description = "Django rest framework recaptcha field serializer." +optional = false +python-versions = ">=3.7" +files = [ + {file = "drf-recaptcha-3.0.0.tar.gz", hash = "sha256:30ede1831737bcbdc60a67b41d83fa290bea15f6bf39a6470e9d68057abccd76"}, + {file = "drf_recaptcha-3.0.0-py3-none-any.whl", hash = "sha256:351d8b1a203841aac540636a1a2d60e1bb5cf62a6e019c873e82b959bc6941fa"}, +] + +[package.dependencies] +django = ">=3.2" +django-ipware = ">=2.1" +djangorestframework = ">=3.11" + +[[package]] +name = "drf-spectacular" +version = "0.26.5" +description = "Sane and flexible OpenAPI 3 schema generation for Django REST framework" +optional = false +python-versions = ">=3.6" +files = [ + {file = "drf-spectacular-0.26.5.tar.gz", hash = "sha256:aee55330a774ba8a9cbdb125714d1c9ee05a8aafd3ce3be8bfd26527649aeb44"}, + {file = "drf_spectacular-0.26.5-py3-none-any.whl", hash = "sha256:c0002a820b11771fdbf37853deb371947caf0159d1afeeffe7598e964bc1db94"}, +] + +[package.dependencies] +Django = ">=2.2" +djangorestframework = ">=3.10.3" +drf-spectacular-sidecar = {version = "*", optional = true, markers = "extra == \"sidecar\""} +inflection = ">=0.3.1" +jsonschema = ">=2.6.0" +PyYAML = ">=5.1" +uritemplate = ">=2.0.0" + +[package.extras] +offline = ["drf-spectacular-sidecar"] +sidecar = ["drf-spectacular-sidecar"] + +[[package]] +name = "drf-spectacular-sidecar" +version = "2023.10.1" +description = "Serve self-contained distribution builds of Swagger UI and Redoc with Django" +optional = false +python-versions = ">=3.6" +files = [ + {file = "drf-spectacular-sidecar-2023.10.1.tar.gz", hash = "sha256:546a83c173589715e530fad211af60cbcda2db54eb9e0935d44251639332af6d"}, + {file = "drf_spectacular_sidecar-2023.10.1-py3-none-any.whl", hash = "sha256:3d042a6772512f4d238f0385d3430acf5f669f595fd0be2641fe6bbfb4c7b376"}, +] + +[package.dependencies] +Django = ">=2.2" + +[[package]] +name = "emoji" +version = "2.8.0" +description = "Emoji for Python" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "emoji-2.8.0-py2.py3-none-any.whl", hash = "sha256:a8468fd836b7ecb6d1eac054c9a591701ce0ccd6c6f7779ad71b66f76664df90"}, + {file = "emoji-2.8.0.tar.gz", hash = "sha256:8d8b5dec3c507444b58890e598fc895fcec022b3f5acb49497c6ccc5208b8b00"}, +] + +[package.extras] +dev = ["coverage", "coveralls", "pytest"] + +[[package]] +name = "eradicate" +version = "2.3.0" +description = "Removes commented-out code." +optional = false +python-versions = "*" +files = [ + {file = "eradicate-2.3.0-py3-none-any.whl", hash = "sha256:2b29b3dd27171f209e4ddd8204b70c02f0682ae95eecb353f10e8d72b149c63e"}, + {file = "eradicate-2.3.0.tar.gz", hash = "sha256:06df115be3b87d0fc1c483db22a2ebb12bcf40585722810d809cc770f5031c37"}, +] + +[[package]] +name = "execnet" +version = "2.0.2" +description = "execnet: rapid multi-Python deployment" +optional = false +python-versions = ">=3.7" +files = [ + {file = "execnet-2.0.2-py3-none-any.whl", hash = "sha256:88256416ae766bc9e8895c76a87928c0012183da3cc4fc18016e6f050e025f41"}, + {file = "execnet-2.0.2.tar.gz", hash = "sha256:cc59bc4423742fd71ad227122eb0dd44db51efb3dc4095b45ac9a08c770096af"}, +] + +[package.extras] +testing = ["hatch", "pre-commit", "pytest", "tox"] + +[[package]] +name = "executing" +version = "2.0.0" +description = "Get the currently executing AST node of a frame, and other information" +optional = false +python-versions = "*" +files = [ + {file = "executing-2.0.0-py2.py3-none-any.whl", hash = "sha256:06df6183df67389625f4e763921c6cf978944721abf3e714000200aab95b0657"}, + {file = "executing-2.0.0.tar.gz", hash = "sha256:0ff053696fdeef426cda5bd18eacd94f82c91f49823a2e9090124212ceea9b08"}, +] + +[package.extras] +tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] + +[[package]] +name = "faker" +version = "12.0.1" +description = "Faker is a Python package that generates fake data for you." +optional = false +python-versions = ">=3.6" +files = [ + {file = "Faker-12.0.1-py3-none-any.whl", hash = "sha256:1dc2811f20e163892fefe7006f2ce00778f8099a40aee265bfa60a13400de63d"}, + {file = "Faker-12.0.1.tar.gz", hash = "sha256:aa7103805ae793277abbb85da9f6f05e76a1a295a9384a8e17c2fba2b3a690cb"}, +] + +[package.dependencies] +python-dateutil = ">=2.4" + +[[package]] +name = "flake8" +version = "6.1.0" +description = "the modular source code checker: pep8 pyflakes and co" +optional = false +python-versions = ">=3.8.1" +files = [ + {file = "flake8-6.1.0-py2.py3-none-any.whl", hash = "sha256:ffdfce58ea94c6580c77888a86506937f9a1a227dfcd15f245d694ae20a6b6e5"}, + {file = "flake8-6.1.0.tar.gz", hash = "sha256:d5b3857f07c030bdb5bf41c7f53799571d75c4491748a3adcd47de929e34cd23"}, +] + +[package.dependencies] +mccabe = ">=0.7.0,<0.8.0" +pycodestyle = ">=2.11.0,<2.12.0" +pyflakes = ">=3.1.0,<3.2.0" + +[[package]] +name = "flake8-absolute-import" +version = "1.0.0.2" +description = "flake8 plugin to require absolute imports" +optional = false +python-versions = ">=3.6" +files = [ + {file = "flake8-absolute-import-1.0.0.2.tar.gz", hash = "sha256:fcb734ac5a9639fa4ffbc6242ae9d6e9d8063f9cd078d6d218597ee883a99d48"}, + {file = "flake8_absolute_import-1.0.0.2-py3-none-any.whl", hash = "sha256:b72142db999ec5e0ac4f4ac57fb8776a2959d07346c4d3742c446f206d45fcef"}, +] + +[package.dependencies] +flake8 = ">=5.0" + +[[package]] +name = "flake8-black" +version = "0.3.6" +description = "flake8 plugin to call black as a code style validator" +optional = false +python-versions = ">=3.7" +files = [ + {file = "flake8-black-0.3.6.tar.gz", hash = "sha256:0dfbca3274777792a5bcb2af887a4cad72c72d0e86c94e08e3a3de151bb41c34"}, + {file = "flake8_black-0.3.6-py3-none-any.whl", hash = "sha256:fe8ea2eca98d8a504f22040d9117347f6b367458366952862ac3586e7d4eeaca"}, +] + +[package.dependencies] +black = ">=22.1.0" +flake8 = ">=3" + +[package.extras] +develop = ["build", "twine"] + +[[package]] +name = "flake8-bugbear" +version = "23.9.16" +description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." +optional = false +python-versions = ">=3.8.1" +files = [ + {file = "flake8-bugbear-23.9.16.tar.gz", hash = "sha256:90cf04b19ca02a682feb5aac67cae8de742af70538590509941ab10ae8351f71"}, + {file = "flake8_bugbear-23.9.16-py3-none-any.whl", hash = "sha256:b182cf96ea8f7a8595b2f87321d7d9b28728f4d9c3318012d896543d19742cb5"}, +] + +[package.dependencies] +attrs = ">=19.2.0" +flake8 = ">=6.0.0" + +[package.extras] +dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "pytest", "tox"] + +[[package]] +name = "flake8-cognitive-complexity" +version = "0.1.0" +description = "An extension for flake8 that validates cognitive functions complexity" +optional = false +python-versions = ">=3.6" +files = [ + {file = "flake8_cognitive_complexity-0.1.0.tar.gz", hash = "sha256:f202df054e4f6ff182b659c261922b9c684628a47beb19cb0973c50d6a7831c1"}, +] + +[package.dependencies] +cognitive_complexity = "*" +setuptools = "*" + +[[package]] +name = "flake8-django" +version = "1.4" +description = "Plugin to catch bad style specific to Django Projects." +optional = false +python-versions = ">=3.7.2,<4.0.0" +files = [ + {file = "flake8_django-1.4.tar.gz", hash = "sha256:4debba883084191568e3187416d1d6bdd4abd826da988f197a3c36572e9f30de"}, +] + +[package.dependencies] +astroid = ">=2.15.2,<3.0.0" +flake8 = ">=3.8.4,<7" + +[[package]] +name = "flake8-eradicate" +version = "1.5.0" +description = "Flake8 plugin to find commented out code" +optional = false +python-versions = ">=3.8,<4.0" +files = [ + {file = "flake8_eradicate-1.5.0-py3-none-any.whl", hash = "sha256:18acc922ad7de623f5247c7d5595da068525ec5437dd53b22ec2259b96ce9d22"}, + {file = "flake8_eradicate-1.5.0.tar.gz", hash = "sha256:aee636cb9ecb5594a7cd92d67ad73eb69909e5cc7bd81710cf9d00970f3983a6"}, +] + +[package.dependencies] +attrs = "*" +eradicate = ">=2.0,<3.0" +flake8 = ">5" + +[[package]] +name = "flake8-fixme" +version = "1.1.1" +description = "Check for FIXME, TODO and other temporary developer notes. Plugin for flake8." +optional = false +python-versions = "*" +files = [ + {file = "flake8-fixme-1.1.1.tar.gz", hash = "sha256:50cade07d27a4c30d4f12351478df87339e67640c83041b664724bda6d16f33a"}, + {file = "flake8_fixme-1.1.1-py2.py3-none-any.whl", hash = "sha256:226a6f2ef916730899f29ac140bed5d4a17e5aba79f00a0e3ae1eff1997cb1ac"}, +] + +[[package]] +name = "flake8-isort" +version = "6.1.0" +description = "flake8 plugin that integrates isort ." +optional = false +python-versions = ">=3.8" +files = [ + {file = "flake8-isort-6.1.0.tar.gz", hash = "sha256:d4639343bac540194c59fb1618ac2c285b3e27609f353bef6f50904d40c1643e"}, +] + +[package.dependencies] +flake8 = "*" +isort = ">=5.0.0,<6" + +[package.extras] +test = ["pytest"] + +[[package]] +name = "flake8-multiline-containers" +version = "0.0.19" +description = "Ensure a consistent format for multiline containers." +optional = false +python-versions = "*" +files = [ + {file = "flake8-multiline-containers-0.0.19.tar.gz", hash = "sha256:7c47527f1a2b0a991b876e58a2758e0ecc6b2d10a5fd4ee7740d042722f2f281"}, + {file = "flake8_multiline_containers-0.0.19-py3-none-any.whl", hash = "sha256:1b684da84b401f42f1ad36f0f90e24b7f49b2691458cb582911fb99d871bb0b2"}, +] + +[package.dependencies] +attrs = ">=19.3.0" +flake8 = ">=3.7.9" + +[[package]] +name = "flake8-mutable" +version = "1.2.0" +description = "mutable defaults flake8 extension" +optional = false +python-versions = "*" +files = [ + {file = "flake8-mutable-1.2.0.tar.gz", hash = "sha256:ee9b77111b867d845177bbc289d87d541445ffcc6029a0c5c65865b42b18c6a6"}, + {file = "flake8_mutable-1.2.0-py2-none-any.whl", hash = "sha256:38fd9dadcbcda6550a916197bc40ed76908119dabb37fbcca30873666c31d2d5"}, +] + +[package.dependencies] +flake8 = "*" + +[[package]] +name = "flake8-pep3101" +version = "2.0.0" +description = "Checks for old string formatting." +optional = false +python-versions = "*" +files = [ + {file = "flake8-pep3101-2.0.0.tar.gz", hash = "sha256:ae2ee1758734a473ca971b4bf9ff09c961b6099916db91fdb6b9718328dfcacb"}, + {file = "flake8_pep3101-2.0.0-py3-none-any.whl", hash = "sha256:1d818e1f53c6d26e875714f2f041ec15fbb23c17e2268dbbb024e9c3383541cd"}, +] + +[package.dependencies] +flake8 = "*" + +[package.extras] +test = ["pytest"] + +[[package]] +name = "flake8-pie" +version = "0.16.0" +description = "A flake8 extension that implements misc. lints" +optional = false +python-versions = ">=3.7" +files = [ + {file = "flake8-pie-0.16.0.tar.gz", hash = "sha256:b8dcb7b92706fa33d05d92a4b3e49b7a9fd3f0041849166275b646ba50e515ba"}, + {file = "flake8_pie-0.16.0-py3-none-any.whl", hash = "sha256:24cd7849b0eee22e2328b9e9d2a1dea40013b0a3106864bbadd06a4b05dbb71f"}, +] + +[package.dependencies] +typing_extensions = "*" + +[[package]] +name = "flake8-plugin-utils" +version = "1.3.3" +description = "The package provides base classes and utils for flake8 plugin writing" +optional = false +python-versions = ">=3.6,<4.0" +files = [ + {file = "flake8-plugin-utils-1.3.3.tar.gz", hash = "sha256:39f6f338d038b301c6fd344b06f2e81e382b68fa03c0560dff0d9b1791a11a2c"}, + {file = "flake8_plugin_utils-1.3.3-py3-none-any.whl", hash = "sha256:e4848c57d9d50f19100c2d75fa794b72df068666a9041b4b0409be923356a3ed"}, +] + +[[package]] +name = "flake8-print" +version = "5.0.0" +description = "print statement checker plugin for flake8" +optional = false +python-versions = ">=3.7" +files = [ + {file = "flake8-print-5.0.0.tar.gz", hash = "sha256:76915a2a389cc1c0879636c219eb909c38501d3a43cc8dae542081c9ba48bdf9"}, + {file = "flake8_print-5.0.0-py3-none-any.whl", hash = "sha256:84a1a6ea10d7056b804221ac5e62b1cee1aefc897ce16f2e5c42d3046068f5d8"}, +] + +[package.dependencies] +flake8 = ">=3.0" +pycodestyle = "*" + +[[package]] +name = "flake8-printf-formatting" +version = "1.1.2" +description = "flake8 plugin which forbids printf-style string formatting" +optional = false +python-versions = ">=3.6" +files = [ + {file = "flake8-printf-formatting-1.1.2.tar.gz", hash = "sha256:0f9e1308ac290356e4b271d4f26adfc3f9165680a7b6c221503b0f3e155a2784"}, + {file = "flake8_printf_formatting-1.1.2-py2.py3-none-any.whl", hash = "sha256:d908ffabdf08581043a50572744fd60563d82386630b0335445894120089d2df"}, +] + +[package.dependencies] +flake8 = "*" + +[[package]] +name = "flake8-pyproject" +version = "1.2.3" +description = "Flake8 plug-in loading the configuration from pyproject.toml" +optional = false +python-versions = ">= 3.6" +files = [ + {file = "flake8_pyproject-1.2.3-py3-none-any.whl", hash = "sha256:6249fe53545205af5e76837644dc80b4c10037e73a0e5db87ff562d75fb5bd4a"}, +] + +[package.dependencies] +Flake8 = ">=5" + +[package.extras] +dev = ["pyTest", "pyTest-cov"] + +[[package]] +name = "flake8-pytest" +version = "1.4" +description = "pytest assert checker plugin for flake8" +optional = false +python-versions = "*" +files = [ + {file = "flake8-pytest-1.4.tar.gz", hash = "sha256:19f543b2d1cc89d61b76f19d0a9e58e9a110a035175f701b3425c363a7732c56"}, + {file = "flake8_pytest-1.4-py2.py3-none-any.whl", hash = "sha256:97328f258ffad9fe18babb3b0714a16b121505ad3ac87d4e33020874555d0784"}, +] + +[package.dependencies] +flake8 = "*" + +[[package]] +name = "flake8-pytest-style" +version = "1.7.2" +description = "A flake8 plugin checking common style issues or inconsistencies with pytest-based tests." +optional = false +python-versions = ">=3.7.2,<4.0.0" +files = [ + {file = "flake8_pytest_style-1.7.2-py3-none-any.whl", hash = "sha256:f5d2aa3219163a052dd92226589d45fab8ea027a3269922f0c4029f548ea5cd1"}, + {file = "flake8_pytest_style-1.7.2.tar.gz", hash = "sha256:b924197c99b951315949920b0e5547f34900b1844348432e67a44ab191582109"}, +] + +[package.dependencies] +flake8-plugin-utils = ">=1.3.2,<2.0.0" + +[[package]] +name = "flake8-simplify" +version = "0.20.0" +description = "flake8 plugin which checks for code that can be simplified" +optional = false +python-versions = ">=3.6.1" +files = [ + {file = "flake8_simplify-0.20.0-py3-none-any.whl", hash = "sha256:599a47824726c93fadcf0274e569daed45052e38cd906360d9080eaa3bd76d61"}, + {file = "flake8_simplify-0.20.0.tar.gz", hash = "sha256:7b8796bbea8aed45f56621c389d0556cc86f0afa5d992581139451240a8fbeca"}, +] + +[package.dependencies] +astor = ">=0.1" +flake8 = ">=3.7" + +[[package]] +name = "flake8-tidy-imports" +version = "4.10.0" +description = "A flake8 plugin that helps you write tidier imports." +optional = false +python-versions = ">=3.8" +files = [ + {file = "flake8_tidy_imports-4.10.0-py3-none-any.whl", hash = "sha256:b0387fb2ea200441bd142309e716fb7b8f4b0937bdf5f8b7c0c118a5f5e2b8ed"}, + {file = "flake8_tidy_imports-4.10.0.tar.gz", hash = "sha256:bd6cf86465402d2b86903009b748d85a628e599e17b76e810c9857e3a2815173"}, +] + +[package.dependencies] +flake8 = ">=3.8.0" + +[[package]] +name = "flake8-todo" +version = "0.7" +description = "TODO notes checker, plugin for flake8" +optional = false +python-versions = "*" +files = [ + {file = "flake8-todo-0.7.tar.gz", hash = "sha256:6e4c5491ff838c06fe5a771b0e95ee15fc005ca57196011011280fc834a85915"}, +] + +[package.dependencies] +pycodestyle = ">=2.0.0,<3.0.0" + +[[package]] +name = "flake8-use-fstring" +version = "1.4" +description = "Flake8 plugin for string formatting style." +optional = false +python-versions = ">=3.6" +files = [ + {file = "flake8-use-fstring-1.4.tar.gz", hash = "sha256:6550bf722585eb97dffa8343b0f1c372101f5c4ab5b07ebf0edd1c79880cdd39"}, +] + +[package.dependencies] +flake8 = ">=3" + +[package.extras] +ci = ["coverage (==4.*)", "coveralls", "flake8-builtins", "flake8-commas", "flake8-fixme", "flake8-print", "flake8-quotes", "flake8-todo", "pytest (>=4)", "pytest-cov (>=2)"] +dev = ["coverage (==4.*)", "flake8-builtins", "flake8-commas", "flake8-fixme", "flake8-print", "flake8-quotes", "flake8-todo", "pytest (>=4)", "pytest-cov (>=2)"] +test = ["coverage (==4.*)", "flake8-builtins", "flake8-commas", "flake8-fixme", "flake8-print", "flake8-quotes", "flake8-todo", "pytest (>=4)", "pytest-cov (>=2)"] + +[[package]] +name = "flake8-variables-names" +version = "0.0.6" +description = "A flake8 extension that helps to make more readable variables names" +optional = false +python-versions = ">=3.7" +files = [ + {file = "flake8_variables_names-0.0.6-py3-none-any.whl", hash = "sha256:4aff935d54b3f7afcd026b4dae55029877bd05a7c507b294b45bc7bf577d7b47"}, + {file = "flake8_variables_names-0.0.6.tar.gz", hash = "sha256:292c50e4813d632aa3adcd02c185e7bb583f5fc8ebe02e70f13c958bfe46ad91"}, +] + +[[package]] +name = "flake8-walrus" +version = "1.2.0" +description = "flake8 plugin which forbids assignment expressions (the walrus operator)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "flake8_walrus-1.2.0-py2.py3-none-any.whl", hash = "sha256:a9f72722188b95a393f8727a0eaeb8f31d9796eeb5a4328c9c4499ccd57e589d"}, + {file = "flake8_walrus-1.2.0.tar.gz", hash = "sha256:5dff966f0cc67abae104349812cd255ef3b5e09a7f768eac39b5a4a39f4d1e73"}, +] + +[package.dependencies] +flake8 = ">=5.0" + +[[package]] +name = "freezegun" +version = "1.2.2" +description = "Let your Python tests travel through time" +optional = false +python-versions = ">=3.6" +files = [ + {file = "freezegun-1.2.2-py3-none-any.whl", hash = "sha256:ea1b963b993cb9ea195adbd893a48d573fda951b0da64f60883d7e988b606c9f"}, + {file = "freezegun-1.2.2.tar.gz", hash = "sha256:cd22d1ba06941384410cd967d8a99d5ae2442f57dfafeff2fda5de8dc5c05446"}, +] + +[package.dependencies] +python-dateutil = ">=2.7" + +[[package]] +name = "h11" +version = "0.14.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.7" +files = [ + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, +] + +[[package]] +name = "h2" +version = "4.1.0" +description = "HTTP/2 State-Machine based protocol implementation" +optional = false +python-versions = ">=3.6.1" +files = [ + {file = "h2-4.1.0-py3-none-any.whl", hash = "sha256:03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d"}, + {file = "h2-4.1.0.tar.gz", hash = "sha256:a83aca08fbe7aacb79fec788c9c0bac936343560ed9ec18b82a13a12c28d2abb"}, +] + +[package.dependencies] +hpack = ">=4.0,<5" +hyperframe = ">=6.0,<7" + +[[package]] +name = "hpack" +version = "4.0.0" +description = "Pure-Python HPACK header compression" +optional = false +python-versions = ">=3.6.1" +files = [ + {file = "hpack-4.0.0-py3-none-any.whl", hash = "sha256:84a076fad3dc9a9f8063ccb8041ef100867b1878b25ef0ee63847a5d53818a6c"}, + {file = "hpack-4.0.0.tar.gz", hash = "sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095"}, +] + +[[package]] +name = "httpcore" +version = "0.18.0" +description = "A minimal low-level HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpcore-0.18.0-py3-none-any.whl", hash = "sha256:adc5398ee0a476567bf87467063ee63584a8bce86078bf748e48754f60202ced"}, + {file = "httpcore-0.18.0.tar.gz", hash = "sha256:13b5e5cd1dca1a6636a6aaea212b19f4f85cd88c366a2b82304181b769aab3c9"}, +] + +[package.dependencies] +anyio = ">=3.0,<5.0" +certifi = "*" +h11 = ">=0.13,<0.15" +sniffio = "==1.*" + +[package.extras] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] + +[[package]] +name = "httpx" +version = "0.25.0" +description = "The next generation HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpx-0.25.0-py3-none-any.whl", hash = "sha256:181ea7f8ba3a82578be86ef4171554dd45fec26a02556a744db029a0a27b7100"}, + {file = "httpx-0.25.0.tar.gz", hash = "sha256:47ecda285389cb32bb2691cc6e069e3ab0205956f681c5b2ad2325719751d875"}, +] + +[package.dependencies] +certifi = "*" +h2 = {version = ">=3,<5", optional = true, markers = "extra == \"http2\""} +httpcore = ">=0.18.0,<0.19.0" +idna = "*" +sniffio = "*" + +[package.extras] +brotli = ["brotli", "brotlicffi"] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] + +[[package]] +name = "hyperframe" +version = "6.0.1" +description = "HTTP/2 framing layer for Python" +optional = false +python-versions = ">=3.6.1" +files = [ + {file = "hyperframe-6.0.1-py3-none-any.whl", hash = "sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15"}, + {file = "hyperframe-6.0.1.tar.gz", hash = "sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"}, +] + +[[package]] +name = "idna" +version = "3.4" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] + +[[package]] +name = "inflection" +version = "0.5.1" +description = "A port of Ruby on Rails inflector to Python" +optional = false +python-versions = ">=3.5" +files = [ + {file = "inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"}, + {file = "inflection-0.5.1.tar.gz", hash = "sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417"}, +] + +[[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 = "ipython" +version = "8.16.1" +description = "IPython: Productive Interactive Computing" +optional = false +python-versions = ">=3.9" +files = [ + {file = "ipython-8.16.1-py3-none-any.whl", hash = "sha256:0852469d4d579d9cd613c220af7bf0c9cc251813e12be647cb9d463939db9b1e"}, + {file = "ipython-8.16.1.tar.gz", hash = "sha256:ad52f58fca8f9f848e256c629eff888efc0528c12fe0f8ec14f33205f23ef938"}, +] + +[package.dependencies] +appnope = {version = "*", markers = "sys_platform == \"darwin\""} +backcall = "*" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +decorator = "*" +jedi = ">=0.16" +matplotlib-inline = "*" +pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} +pickleshare = "*" +prompt-toolkit = ">=3.0.30,<3.0.37 || >3.0.37,<3.1.0" +pygments = ">=2.4.0" +stack-data = "*" +traitlets = ">=5" + +[package.extras] +all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.21)", "pandas", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] +black = ["black"] +doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] +kernel = ["ipykernel"] +nbconvert = ["nbconvert"] +nbformat = ["nbformat"] +notebook = ["ipywidgets", "notebook"] +parallel = ["ipyparallel"] +qtconsole = ["qtconsole"] +test = ["pytest (<7.1)", "pytest-asyncio", "testpath"] +test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pandas", "pytest (<7.1)", "pytest-asyncio", "testpath", "trio"] + +[[package]] +name = "isort" +version = "5.12.0" +description = "A Python utility / library to sort Python imports." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, + {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, +] + +[package.extras] +colors = ["colorama (>=0.4.3)"] +pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] +plugins = ["setuptools"] +requirements-deprecated-finder = ["pip-api", "pipreqs"] + +[[package]] +name = "jedi" +version = "0.19.1" +description = "An autocompletion tool for Python that can be used for text editors." +optional = false +python-versions = ">=3.6" +files = [ + {file = "jedi-0.19.1-py2.py3-none-any.whl", hash = "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0"}, + {file = "jedi-0.19.1.tar.gz", hash = "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd"}, +] + +[package.dependencies] +parso = ">=0.8.3,<0.9.0" + +[package.extras] +docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"] +qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] +testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] + +[[package]] +name = "jmespath" +version = "1.0.1" +description = "JSON Matching Expressions" +optional = false +python-versions = ">=3.7" +files = [ + {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, + {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, +] + +[[package]] +name = "jsonschema" +version = "4.19.1" +description = "An implementation of JSON Schema validation for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema-4.19.1-py3-none-any.whl", hash = "sha256:cd5f1f9ed9444e554b38ba003af06c0a8c2868131e56bfbef0550fb450c0330e"}, + {file = "jsonschema-4.19.1.tar.gz", hash = "sha256:ec84cc37cfa703ef7cd4928db24f9cb31428a5d0fa77747b8b51a847458e0bbf"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +jsonschema-specifications = ">=2023.03.6" +referencing = ">=0.28.4" +rpds-py = ">=0.7.1" + +[package.extras] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] + +[[package]] +name = "jsonschema-specifications" +version = "2023.7.1" +description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema_specifications-2023.7.1-py3-none-any.whl", hash = "sha256:05adf340b659828a004220a9613be00fa3f223f2b82002e273dee62fd50524b1"}, + {file = "jsonschema_specifications-2023.7.1.tar.gz", hash = "sha256:c91a50404e88a1f6ba40636778e2ee08f6e24c5613fe4c53ac24578a5a7f72bb"}, +] + +[package.dependencies] +referencing = ">=0.28.0" + +[[package]] +name = "kombu" +version = "5.3.2" +description = "Messaging library for Python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "kombu-5.3.2-py3-none-any.whl", hash = "sha256:b753c9cfc9b1e976e637a7cbc1a65d446a22e45546cd996ea28f932082b7dc9e"}, + {file = "kombu-5.3.2.tar.gz", hash = "sha256:0ba213f630a2cb2772728aef56ac6883dc3a2f13435e10048f6e97d48506dbbd"}, +] + +[package.dependencies] +amqp = ">=5.1.1,<6.0.0" +vine = "*" + +[package.extras] +azureservicebus = ["azure-servicebus (>=7.10.0)"] +azurestoragequeues = ["azure-identity (>=1.12.0)", "azure-storage-queue (>=12.6.0)"] +confluentkafka = ["confluent-kafka (==2.1.1)"] +consul = ["python-consul2"] +librabbitmq = ["librabbitmq (>=2.0.0)"] +mongodb = ["pymongo (>=4.1.1)"] +msgpack = ["msgpack"] +pyro = ["pyro4"] +qpid = ["qpid-python (>=0.26)", "qpid-tools (>=0.26)"] +redis = ["redis (>=4.5.2)"] +slmq = ["softlayer-messaging (>=1.0.3)"] +sqlalchemy = ["sqlalchemy (>=1.4.48,<2.1)"] +sqs = ["boto3 (>=1.26.143)", "pycurl (>=7.43.0.5)", "urllib3 (>=1.26.16)"] +yaml = ["PyYAML (>=3.10)"] +zookeeper = ["kazoo (>=2.8.0)"] + +[[package]] +name = "lazy-object-proxy" +version = "1.9.0" +description = "A fast and thorough lazy object proxy." +optional = false +python-versions = ">=3.7" +files = [ + {file = "lazy-object-proxy-1.9.0.tar.gz", hash = "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-win32.whl", hash = "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455"}, + {file = "lazy_object_proxy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-win32.whl", hash = "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586"}, + {file = "lazy_object_proxy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win32.whl", hash = "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734"}, + {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-win32.whl", hash = "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82"}, + {file = "lazy_object_proxy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-win32.whl", hash = "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821"}, + {file = "lazy_object_proxy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f"}, +] + +[[package]] +name = "matplotlib-inline" +version = "0.1.6" +description = "Inline Matplotlib backend for Jupyter" +optional = false +python-versions = ">=3.5" +files = [ + {file = "matplotlib-inline-0.1.6.tar.gz", hash = "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304"}, + {file = "matplotlib_inline-0.1.6-py3-none-any.whl", hash = "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311"}, +] + +[package.dependencies] +traitlets = "*" + +[[package]] +name = "mccabe" +version = "0.7.0" +description = "McCabe checker, plugin for flake8" +optional = false +python-versions = ">=3.6" +files = [ + {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, + {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, +] + +[[package]] +name = "mixer" +version = "7.2.2" +description = "Mixer -- Is a fixtures replacement. Supported Django ORM, SqlAlchemy ORM, Mongoengine ODM and custom python objects." +optional = false +python-versions = ">=3.7" +files = [ + {file = "mixer-7.2.2-py3-none-any.whl", hash = "sha256:8089b8e2d00288c77e622936198f5dd03c8ac1603a1530a4f870dc213363b2ae"}, + {file = "mixer-7.2.2.tar.gz", hash = "sha256:9b3f1a261b56d8f2394f39955f83adbc7ff3ab4bb1065ebfec19a10d3e8501e0"}, +] + +[package.dependencies] +Faker = ">=5.4.0,<12.1" + +[package.extras] +tests = ["Django (>=3.0)", "Flask (>=1.0)", "Marshmallow (>=3.9)", "SQLAlchemy (>=1.1.4)", "flask-sqlalchemy (>=2.1)", "mongoengine (>=0.10.1)", "peewee (>=3.7.0)", "pony (>=0.7)", "psycopg2-binary (>=2.8.4)", "pytest"] + +[[package]] +name = "mypy" +version = "1.6.1" +description = "Optional static typing for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy-1.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e5012e5cc2ac628177eaac0e83d622b2dd499e28253d4107a08ecc59ede3fc2c"}, + {file = "mypy-1.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d8fbb68711905f8912e5af474ca8b78d077447d8f3918997fecbf26943ff3cbb"}, + {file = "mypy-1.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21a1ad938fee7d2d96ca666c77b7c494c3c5bd88dff792220e1afbebb2925b5e"}, + {file = "mypy-1.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b96ae2c1279d1065413965c607712006205a9ac541895004a1e0d4f281f2ff9f"}, + {file = "mypy-1.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:40b1844d2e8b232ed92e50a4bd11c48d2daa351f9deee6c194b83bf03e418b0c"}, + {file = "mypy-1.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:81af8adaa5e3099469e7623436881eff6b3b06db5ef75e6f5b6d4871263547e5"}, + {file = "mypy-1.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8c223fa57cb154c7eab5156856c231c3f5eace1e0bed9b32a24696b7ba3c3245"}, + {file = "mypy-1.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8032e00ce71c3ceb93eeba63963b864bf635a18f6c0c12da6c13c450eedb183"}, + {file = "mypy-1.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4c46b51de523817a0045b150ed11b56f9fff55f12b9edd0f3ed35b15a2809de0"}, + {file = "mypy-1.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:19f905bcfd9e167159b3d63ecd8cb5e696151c3e59a1742e79bc3bcb540c42c7"}, + {file = "mypy-1.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:82e469518d3e9a321912955cc702d418773a2fd1e91c651280a1bda10622f02f"}, + {file = "mypy-1.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d4473c22cc296425bbbce7e9429588e76e05bc7342da359d6520b6427bf76660"}, + {file = "mypy-1.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59a0d7d24dfb26729e0a068639a6ce3500e31d6655df8557156c51c1cb874ce7"}, + {file = "mypy-1.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cfd13d47b29ed3bbaafaff7d8b21e90d827631afda134836962011acb5904b71"}, + {file = "mypy-1.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:eb4f18589d196a4cbe5290b435d135dee96567e07c2b2d43b5c4621b6501531a"}, + {file = "mypy-1.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:41697773aa0bf53ff917aa077e2cde7aa50254f28750f9b88884acea38a16169"}, + {file = "mypy-1.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7274b0c57737bd3476d2229c6389b2ec9eefeb090bbaf77777e9d6b1b5a9d143"}, + {file = "mypy-1.6.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbaf4662e498c8c2e352da5f5bca5ab29d378895fa2d980630656178bd607c46"}, + {file = "mypy-1.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bb8ccb4724f7d8601938571bf3f24da0da791fe2db7be3d9e79849cb64e0ae85"}, + {file = "mypy-1.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:68351911e85145f582b5aa6cd9ad666c8958bcae897a1bfda8f4940472463c45"}, + {file = "mypy-1.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:49ae115da099dcc0922a7a895c1eec82c1518109ea5c162ed50e3b3594c71208"}, + {file = "mypy-1.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8b27958f8c76bed8edaa63da0739d76e4e9ad4ed325c814f9b3851425582a3cd"}, + {file = "mypy-1.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:925cd6a3b7b55dfba252b7c4561892311c5358c6b5a601847015a1ad4eb7d332"}, + {file = "mypy-1.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8f57e6b6927a49550da3d122f0cb983d400f843a8a82e65b3b380d3d7259468f"}, + {file = "mypy-1.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:a43ef1c8ddfdb9575691720b6352761f3f53d85f1b57d7745701041053deff30"}, + {file = "mypy-1.6.1-py3-none-any.whl", hash = "sha256:4cbe68ef919c28ea561165206a2dcb68591c50f3bcf777932323bc208d949cf1"}, + {file = "mypy-1.6.1.tar.gz", hash = "sha256:4d01c00d09a0be62a4ca3f933e315455bde83f37f892ba4b08ce92f3cf44bcc1"}, +] + +[package.dependencies] +mypy-extensions = ">=1.0.0" +typing-extensions = ">=4.1.0" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +install-types = ["pip"] +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 = "packaging" +version = "23.2" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, +] + +[[package]] +name = "parso" +version = "0.8.3" +description = "A Python Parser" +optional = false +python-versions = ">=3.6" +files = [ + {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"}, + {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"}, +] + +[package.extras] +qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] +testing = ["docopt", "pytest (<6.0.0)"] + +[[package]] +name = "pathspec" +version = "0.11.2" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, + {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, +] + +[[package]] +name = "pexpect" +version = "4.8.0" +description = "Pexpect allows easy control of interactive console applications." +optional = false +python-versions = "*" +files = [ + {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, + {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, +] + +[package.dependencies] +ptyprocess = ">=0.5" + +[[package]] +name = "pickleshare" +version = "0.7.5" +description = "Tiny 'shelve'-like database with concurrency support" +optional = false +python-versions = "*" +files = [ + {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, + {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, +] + +[[package]] +name = "pillow" +version = "10.1.0" +description = "Python Imaging Library (Fork)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "Pillow-10.1.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1ab05f3db77e98f93964697c8efc49c7954b08dd61cff526b7f2531a22410106"}, + {file = "Pillow-10.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6932a7652464746fcb484f7fc3618e6503d2066d853f68a4bd97193a3996e273"}, + {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5f63b5a68daedc54c7c3464508d8c12075e56dcfbd42f8c1bf40169061ae666"}, + {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0949b55eb607898e28eaccb525ab104b2d86542a85c74baf3a6dc24002edec2"}, + {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:ae88931f93214777c7a3aa0a8f92a683f83ecde27f65a45f95f22d289a69e593"}, + {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b0eb01ca85b2361b09480784a7931fc648ed8b7836f01fb9241141b968feb1db"}, + {file = "Pillow-10.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d27b5997bdd2eb9fb199982bb7eb6164db0426904020dc38c10203187ae2ff2f"}, + {file = "Pillow-10.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7df5608bc38bd37ef585ae9c38c9cd46d7c81498f086915b0f97255ea60c2818"}, + {file = "Pillow-10.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:41f67248d92a5e0a2076d3517d8d4b1e41a97e2df10eb8f93106c89107f38b57"}, + {file = "Pillow-10.1.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1fb29c07478e6c06a46b867e43b0bcdb241b44cc52be9bc25ce5944eed4648e7"}, + {file = "Pillow-10.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2cdc65a46e74514ce742c2013cd4a2d12e8553e3a2563c64879f7c7e4d28bce7"}, + {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50d08cd0a2ecd2a8657bd3d82c71efd5a58edb04d9308185d66c3a5a5bed9610"}, + {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:062a1610e3bc258bff2328ec43f34244fcec972ee0717200cb1425214fe5b839"}, + {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:61f1a9d247317fa08a308daaa8ee7b3f760ab1809ca2da14ecc88ae4257d6172"}, + {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a646e48de237d860c36e0db37ecaecaa3619e6f3e9d5319e527ccbc8151df061"}, + {file = "Pillow-10.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:47e5bf85b80abc03be7455c95b6d6e4896a62f6541c1f2ce77a7d2bb832af262"}, + {file = "Pillow-10.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a92386125e9ee90381c3369f57a2a50fa9e6aa8b1cf1d9c4b200d41a7dd8e992"}, + {file = "Pillow-10.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:0f7c276c05a9767e877a0b4c5050c8bee6a6d960d7f0c11ebda6b99746068c2a"}, + {file = "Pillow-10.1.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:a89b8312d51715b510a4fe9fc13686283f376cfd5abca8cd1c65e4c76e21081b"}, + {file = "Pillow-10.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:00f438bb841382b15d7deb9a05cc946ee0f2c352653c7aa659e75e592f6fa17d"}, + {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d929a19f5469b3f4df33a3df2983db070ebb2088a1e145e18facbc28cae5b27"}, + {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a92109192b360634a4489c0c756364c0c3a2992906752165ecb50544c251312"}, + {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:0248f86b3ea061e67817c47ecbe82c23f9dd5d5226200eb9090b3873d3ca32de"}, + {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9882a7451c680c12f232a422730f986a1fcd808da0fd428f08b671237237d651"}, + {file = "Pillow-10.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1c3ac5423c8c1da5928aa12c6e258921956757d976405e9467c5f39d1d577a4b"}, + {file = "Pillow-10.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:806abdd8249ba3953c33742506fe414880bad78ac25cc9a9b1c6ae97bedd573f"}, + {file = "Pillow-10.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:eaed6977fa73408b7b8a24e8b14e59e1668cfc0f4c40193ea7ced8e210adf996"}, + {file = "Pillow-10.1.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:fe1e26e1ffc38be097f0ba1d0d07fcade2bcfd1d023cda5b29935ae8052bd793"}, + {file = "Pillow-10.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7a7e3daa202beb61821c06d2517428e8e7c1aab08943e92ec9e5755c2fc9ba5e"}, + {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24fadc71218ad2b8ffe437b54876c9382b4a29e030a05a9879f615091f42ffc2"}, + {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa1d323703cfdac2036af05191b969b910d8f115cf53093125e4058f62012c9a"}, + {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:912e3812a1dbbc834da2b32299b124b5ddcb664ed354916fd1ed6f193f0e2d01"}, + {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:7dbaa3c7de82ef37e7708521be41db5565004258ca76945ad74a8e998c30af8d"}, + {file = "Pillow-10.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9d7bc666bd8c5a4225e7ac71f2f9d12466ec555e89092728ea0f5c0c2422ea80"}, + {file = "Pillow-10.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:baada14941c83079bf84c037e2d8b7506ce201e92e3d2fa0d1303507a8538212"}, + {file = "Pillow-10.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:2ef6721c97894a7aa77723740a09547197533146fba8355e86d6d9a4a1056b14"}, + {file = "Pillow-10.1.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0a026c188be3b443916179f5d04548092e253beb0c3e2ee0a4e2cdad72f66099"}, + {file = "Pillow-10.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:04f6f6149f266a100374ca3cc368b67fb27c4af9f1cc8cb6306d849dcdf12616"}, + {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb40c011447712d2e19cc261c82655f75f32cb724788df315ed992a4d65696bb"}, + {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a8413794b4ad9719346cd9306118450b7b00d9a15846451549314a58ac42219"}, + {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:c9aeea7b63edb7884b031a35305629a7593272b54f429a9869a4f63a1bf04c34"}, + {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b4005fee46ed9be0b8fb42be0c20e79411533d1fd58edabebc0dd24626882cfd"}, + {file = "Pillow-10.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4d0152565c6aa6ebbfb1e5d8624140a440f2b99bf7afaafbdbf6430426497f28"}, + {file = "Pillow-10.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d921bc90b1defa55c9917ca6b6b71430e4286fc9e44c55ead78ca1a9f9eba5f2"}, + {file = "Pillow-10.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:cfe96560c6ce2f4c07d6647af2d0f3c54cc33289894ebd88cfbb3bcd5391e256"}, + {file = "Pillow-10.1.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:937bdc5a7f5343d1c97dc98149a0be7eb9704e937fe3dc7140e229ae4fc572a7"}, + {file = "Pillow-10.1.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1c25762197144e211efb5f4e8ad656f36c8d214d390585d1d21281f46d556ba"}, + {file = "Pillow-10.1.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:afc8eef765d948543a4775f00b7b8c079b3321d6b675dde0d02afa2ee23000b4"}, + {file = "Pillow-10.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:883f216eac8712b83a63f41b76ddfb7b2afab1b74abbb413c5df6680f071a6b9"}, + {file = "Pillow-10.1.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b920e4d028f6442bea9a75b7491c063f0b9a3972520731ed26c83e254302eb1e"}, + {file = "Pillow-10.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c41d960babf951e01a49c9746f92c5a7e0d939d1652d7ba30f6b3090f27e412"}, + {file = "Pillow-10.1.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1fafabe50a6977ac70dfe829b2d5735fd54e190ab55259ec8aea4aaea412fa0b"}, + {file = "Pillow-10.1.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:3b834f4b16173e5b92ab6566f0473bfb09f939ba14b23b8da1f54fa63e4b623f"}, + {file = "Pillow-10.1.0.tar.gz", hash = "sha256:e6bf8de6c36ed96c86ea3b6e1d5273c53f46ef518a062464cd7ef5dd2cf92e38"}, +] + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] +tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "platformdirs" +version = "3.11.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +optional = false +python-versions = ">=3.7" +files = [ + {file = "platformdirs-3.11.0-py3-none-any.whl", hash = "sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e"}, + {file = "platformdirs-3.11.0.tar.gz", hash = "sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3"}, +] + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] + +[[package]] +name = "pluggy" +version = "1.3.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"}, + {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "prompt-toolkit" +version = "3.0.39" +description = "Library for building powerful interactive command lines in Python" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "prompt_toolkit-3.0.39-py3-none-any.whl", hash = "sha256:9dffbe1d8acf91e3de75f3b544e4842382fc06c6babe903ac9acb74dc6e08d88"}, + {file = "prompt_toolkit-3.0.39.tar.gz", hash = "sha256:04505ade687dc26dc4284b1ad19a83be2f2afe83e7a828ace0c72f3a1df72aac"}, +] + +[package.dependencies] +wcwidth = "*" + +[[package]] +name = "psycopg2-binary" +version = "2.9.9" +description = "psycopg2 - Python-PostgreSQL Database Adapter" +optional = false +python-versions = ">=3.7" +files = [ + {file = "psycopg2-binary-2.9.9.tar.gz", hash = "sha256:7f01846810177d829c7692f1f5ada8096762d9172af1b1a28d4ab5b77c923c1c"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c2470da5418b76232f02a2fcd2229537bb2d5a7096674ce61859c3229f2eb202"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c6af2a6d4b7ee9615cbb162b0738f6e1fd1f5c3eda7e5da17861eacf4c717ea7"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:75723c3c0fbbf34350b46a3199eb50638ab22a0228f93fb472ef4d9becc2382b"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83791a65b51ad6ee6cf0845634859d69a038ea9b03d7b26e703f94c7e93dbcf9"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0ef4854e82c09e84cc63084a9e4ccd6d9b154f1dbdd283efb92ecd0b5e2b8c84"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed1184ab8f113e8d660ce49a56390ca181f2981066acc27cf637d5c1e10ce46e"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d2997c458c690ec2bc6b0b7ecbafd02b029b7b4283078d3b32a852a7ce3ddd98"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:b58b4710c7f4161b5e9dcbe73bb7c62d65670a87df7bcce9e1faaad43e715245"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:0c009475ee389757e6e34611d75f6e4f05f0cf5ebb76c6037508318e1a1e0d7e"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8dbf6d1bc73f1d04ec1734bae3b4fb0ee3cb2a493d35ede9badbeb901fb40f6f"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-win32.whl", hash = "sha256:3f78fd71c4f43a13d342be74ebbc0666fe1f555b8837eb113cb7416856c79682"}, + {file = "psycopg2_binary-2.9.9-cp310-cp310-win_amd64.whl", hash = "sha256:876801744b0dee379e4e3c38b76fc89f88834bb15bf92ee07d94acd06ec890a0"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ee825e70b1a209475622f7f7b776785bd68f34af6e7a46e2e42f27b659b5bc26"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1ea665f8ce695bcc37a90ee52de7a7980be5161375d42a0b6c6abedbf0d81f0f"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:143072318f793f53819048fdfe30c321890af0c3ec7cb1dfc9cc87aa88241de2"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c332c8d69fb64979ebf76613c66b985414927a40f8defa16cf1bc028b7b0a7b0"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7fc5a5acafb7d6ccca13bfa8c90f8c51f13d8fb87d95656d3950f0158d3ce53"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:977646e05232579d2e7b9c59e21dbe5261f403a88417f6a6512e70d3f8a046be"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b6356793b84728d9d50ead16ab43c187673831e9d4019013f1402c41b1db9b27"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bc7bb56d04601d443f24094e9e31ae6deec9ccb23581f75343feebaf30423359"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:77853062a2c45be16fd6b8d6de2a99278ee1d985a7bd8b103e97e41c034006d2"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:78151aa3ec21dccd5cdef6c74c3e73386dcdfaf19bced944169697d7ac7482fc"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-win32.whl", hash = "sha256:dc4926288b2a3e9fd7b50dc6a1909a13bbdadfc67d93f3374d984e56f885579d"}, + {file = "psycopg2_binary-2.9.9-cp311-cp311-win_amd64.whl", hash = "sha256:b76bedd166805480ab069612119ea636f5ab8f8771e640ae103e05a4aae3e417"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8532fd6e6e2dc57bcb3bc90b079c60de896d2128c5d9d6f24a63875a95a088cf"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f8544b092a29a6ddd72f3556a9fcf249ec412e10ad28be6a0c0d948924f2212"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2d423c8d8a3c82d08fe8af900ad5b613ce3632a1249fd6a223941d0735fce493"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e5afae772c00980525f6d6ecf7cbca55676296b580c0e6abb407f15f3706996"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e6f98446430fdf41bd36d4faa6cb409f5140c1c2cf58ce0bbdaf16af7d3f119"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c77e3d1862452565875eb31bdb45ac62502feabbd53429fdc39a1cc341d681ba"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:cb16c65dcb648d0a43a2521f2f0a2300f40639f6f8c1ecbc662141e4e3e1ee07"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:911dda9c487075abd54e644ccdf5e5c16773470a6a5d3826fda76699410066fb"}, + {file = "psycopg2_binary-2.9.9-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:57fede879f08d23c85140a360c6a77709113efd1c993923c59fde17aa27599fe"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2293b001e319ab0d869d660a704942c9e2cce19745262a8aba2115ef41a0a42a"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03ef7df18daf2c4c07e2695e8cfd5ee7f748a1d54d802330985a78d2a5a6dca9"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a602ea5aff39bb9fac6308e9c9d82b9a35c2bf288e184a816002c9fae930b77"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8359bf4791968c5a78c56103702000105501adb557f3cf772b2c207284273984"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:275ff571376626195ab95a746e6a04c7df8ea34638b99fc11160de91f2fef503"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:f9b5571d33660d5009a8b3c25dc1db560206e2d2f89d3df1cb32d72c0d117d52"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:420f9bbf47a02616e8554e825208cb947969451978dceb77f95ad09c37791dae"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:4154ad09dac630a0f13f37b583eae260c6aa885d67dfbccb5b02c33f31a6d420"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a148c5d507bb9b4f2030a2025c545fccb0e1ef317393eaba42e7eabd28eb6041"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-win32.whl", hash = "sha256:68fc1f1ba168724771e38bee37d940d2865cb0f562380a1fb1ffb428b75cb692"}, + {file = "psycopg2_binary-2.9.9-cp37-cp37m-win_amd64.whl", hash = "sha256:281309265596e388ef483250db3640e5f414168c5a67e9c665cafce9492eda2f"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:60989127da422b74a04345096c10d416c2b41bd7bf2a380eb541059e4e999980"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:246b123cc54bb5361588acc54218c8c9fb73068bf227a4a531d8ed56fa3ca7d6"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34eccd14566f8fe14b2b95bb13b11572f7c7d5c36da61caf414d23b91fcc5d94"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18d0ef97766055fec15b5de2c06dd8e7654705ce3e5e5eed3b6651a1d2a9a152"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d3f82c171b4ccd83bbaf35aa05e44e690113bd4f3b7b6cc54d2219b132f3ae55"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ead20f7913a9c1e894aebe47cccf9dc834e1618b7aa96155d2091a626e59c972"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ca49a8119c6cbd77375ae303b0cfd8c11f011abbbd64601167ecca18a87e7cdd"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:323ba25b92454adb36fa425dc5cf6f8f19f78948cbad2e7bc6cdf7b0d7982e59"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:1236ed0952fbd919c100bc839eaa4a39ebc397ed1c08a97fc45fee2a595aa1b3"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:729177eaf0aefca0994ce4cffe96ad3c75e377c7b6f4efa59ebf003b6d398716"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-win32.whl", hash = "sha256:804d99b24ad523a1fe18cc707bf741670332f7c7412e9d49cb5eab67e886b9b5"}, + {file = "psycopg2_binary-2.9.9-cp38-cp38-win_amd64.whl", hash = "sha256:a6cdcc3ede532f4a4b96000b6362099591ab4a3e913d70bcbac2b56c872446f7"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:72dffbd8b4194858d0941062a9766f8297e8868e1dd07a7b36212aaa90f49472"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:30dcc86377618a4c8f3b72418df92e77be4254d8f89f14b8e8f57d6d43603c0f"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:31a34c508c003a4347d389a9e6fcc2307cc2150eb516462a7a17512130de109e"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:15208be1c50b99203fe88d15695f22a5bed95ab3f84354c494bcb1d08557df67"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1873aade94b74715be2246321c8650cabf5a0d098a95bab81145ffffa4c13876"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a58c98a7e9c021f357348867f537017057c2ed7f77337fd914d0bedb35dace7"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4686818798f9194d03c9129a4d9a702d9e113a89cb03bffe08c6cf799e053291"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ebdc36bea43063116f0486869652cb2ed7032dbc59fbcb4445c4862b5c1ecf7f"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:ca08decd2697fdea0aea364b370b1249d47336aec935f87b8bbfd7da5b2ee9c1"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ac05fb791acf5e1a3e39402641827780fe44d27e72567a000412c648a85ba860"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-win32.whl", hash = "sha256:9dba73be7305b399924709b91682299794887cbbd88e38226ed9f6712eabee90"}, + {file = "psycopg2_binary-2.9.9-cp39-cp39-win_amd64.whl", hash = "sha256:f7ae5d65ccfbebdfa761585228eb4d0df3a8b15cfb53bd953e713e09fbb12957"}, +] + +[[package]] +name = "ptyprocess" +version = "0.7.0" +description = "Run a subprocess in a pseudo terminal" +optional = false +python-versions = "*" +files = [ + {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, + {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, +] + +[[package]] +name = "pure-eval" +version = "0.2.2" +description = "Safely evaluate AST nodes without side effects" +optional = false +python-versions = "*" +files = [ + {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, + {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"}, +] + +[package.extras] +tests = ["pytest"] + +[[package]] +name = "py" +version = "1.11.0" +description = "library with cross-python path, ini-parsing, io, code, log facilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, +] + +[[package]] +name = "pycodestyle" +version = "2.11.1" +description = "Python style guide checker" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pycodestyle-2.11.1-py2.py3-none-any.whl", hash = "sha256:44fe31000b2d866f2e41841b18528a505fbd7fef9017b04eff4e2648a0fadc67"}, + {file = "pycodestyle-2.11.1.tar.gz", hash = "sha256:41ba0e7afc9752dfb53ced5489e89f8186be00e599e712660695b7a75ff2663f"}, +] + +[[package]] +name = "pycparser" +version = "2.21" +description = "C parser in Python" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, + {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, +] + +[[package]] +name = "pyflakes" +version = "3.1.0" +description = "passive checker of Python programs" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyflakes-3.1.0-py2.py3-none-any.whl", hash = "sha256:4132f6d49cb4dae6819e5379898f2b8cce3c5f23994194c24b77d5da2e36f774"}, + {file = "pyflakes-3.1.0.tar.gz", hash = "sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc"}, +] + +[[package]] +name = "pygments" +version = "2.16.1" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"}, + {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"}, +] + +[package.extras] +plugins = ["importlib-metadata"] + +[[package]] +name = "pyjwt" +version = "2.8.0" +description = "JSON Web Token implementation in Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "PyJWT-2.8.0-py3-none-any.whl", hash = "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320"}, + {file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"}, +] + +[package.dependencies] +cryptography = {version = ">=3.4.0", optional = true, markers = "extra == \"crypto\""} + +[package.extras] +crypto = ["cryptography (>=3.4.0)"] +dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] +docs = ["sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] +tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] + +[[package]] +name = "pytest" +version = "7.4.3" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-7.4.3-py3-none-any.whl", hash = "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac"}, + {file = "pytest-7.4.3.tar.gz", hash = "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5"}, +] + +[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-cov" +version = "4.1.0" +description = "Pytest plugin for measuring coverage." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, + {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, +] + +[package.dependencies] +coverage = {version = ">=5.2.1", extras = ["toml"]} +pytest = ">=4.6" + +[package.extras] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] + +[[package]] +name = "pytest-deadfixtures" +version = "2.2.1" +description = "A simple plugin to list unused fixtures in pytest" +optional = false +python-versions = "*" +files = [ + {file = "pytest-deadfixtures-2.2.1.tar.gz", hash = "sha256:ca15938a4e8330993ccec9c6c847383d88b3cd574729530647dc6b492daa9c1e"}, + {file = "pytest_deadfixtures-2.2.1-py2.py3-none-any.whl", hash = "sha256:db71533f2d9456227084e00a1231e732973e299ccb7c37ab92e95032ab6c083e"}, +] + +[package.dependencies] +pytest = ">=3.0.0" + +[[package]] +name = "pytest-django" +version = "4.5.2" +description = "A Django plugin for pytest." +optional = false +python-versions = ">=3.5" +files = [ + {file = "pytest-django-4.5.2.tar.gz", hash = "sha256:d9076f759bb7c36939dbdd5ae6633c18edfc2902d1a69fdbefd2426b970ce6c2"}, + {file = "pytest_django-4.5.2-py3-none-any.whl", hash = "sha256:c60834861933773109334fe5a53e83d1ef4828f2203a1d6a0fa9972f4f75ab3e"}, +] + +[package.dependencies] +pytest = ">=5.4.0" + +[package.extras] +docs = ["sphinx", "sphinx-rtd-theme"] +testing = ["Django", "django-configurations (>=2.0)"] + +[[package]] +name = "pytest-env" +version = "1.1.0" +description = "pytest plugin that allows you to add environment variables." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest_env-1.1.0-py3-none-any.whl", hash = "sha256:86f2dbc05a78cfbb42a4be19e04fd7b4ef364127d0118af2f59b4dcccfd773bf"}, + {file = "pytest_env-1.1.0.tar.gz", hash = "sha256:33a630a3db07068528c16f061350664d0146519824bd8c87b4cb120fff202ad9"}, +] + +[package.dependencies] +pytest = ">=7.4.2" + +[package.extras] +test = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "pytest-mock (>=3.12)"] + +[[package]] +name = "pytest-freezegun" +version = "0.4.2" +description = "Wrap tests with fixtures in freeze_time" +optional = false +python-versions = "*" +files = [ + {file = "pytest-freezegun-0.4.2.zip", hash = "sha256:19c82d5633751bf3ec92caa481fb5cffaac1787bd485f0df6436fd6242176949"}, + {file = "pytest_freezegun-0.4.2-py2.py3-none-any.whl", hash = "sha256:5318a6bfb8ba4b709c8471c94d0033113877b3ee02da5bfcd917c1889cde99a7"}, +] + +[package.dependencies] +freezegun = ">0.3" +pytest = ">=3.0.0" + +[[package]] +name = "pytest-mock" +version = "3.12.0" +description = "Thin-wrapper around the mock package for easier use with pytest" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest-mock-3.12.0.tar.gz", hash = "sha256:31a40f038c22cad32287bb43932054451ff5583ff094bca6f675df2f8bc1a6e9"}, + {file = "pytest_mock-3.12.0-py3-none-any.whl", hash = "sha256:0972719a7263072da3a21c7f4773069bcc7486027d7e8e1f81d98a47e701bc4f"}, +] + +[package.dependencies] +pytest = ">=5.0" + +[package.extras] +dev = ["pre-commit", "pytest-asyncio", "tox"] + +[[package]] +name = "pytest-randomly" +version = "3.15.0" +description = "Pytest plugin to randomly order tests and control random.seed." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest_randomly-3.15.0-py3-none-any.whl", hash = "sha256:0516f4344b29f4e9cdae8bce31c4aeebf59d0b9ef05927c33354ff3859eeeca6"}, + {file = "pytest_randomly-3.15.0.tar.gz", hash = "sha256:b908529648667ba5e54723088edd6f82252f540cc340d748d1fa985539687047"}, +] + +[package.dependencies] +pytest = "*" + +[[package]] +name = "pytest-repeat" +version = "0.9.3" +description = "pytest plugin for repeating tests" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest_repeat-0.9.3-py3-none-any.whl", hash = "sha256:26ab2df18226af9d5ce441c858f273121e92ff55f5bb311d25755b8d7abdd8ed"}, + {file = "pytest_repeat-0.9.3.tar.gz", hash = "sha256:ffd3836dfcd67bb270bec648b330e20be37d2966448c4148c4092d1e8aba8185"}, +] + +[package.dependencies] +pytest = "*" + +[[package]] +name = "pytest-xdist" +version = "3.3.1" +description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-xdist-3.3.1.tar.gz", hash = "sha256:d5ee0520eb1b7bcca50a60a518ab7a7707992812c578198f8b44fdfac78e8c93"}, + {file = "pytest_xdist-3.3.1-py3-none-any.whl", hash = "sha256:ff9daa7793569e6a68544850fd3927cd257cc03a7ef76c95e86915355e82b5f2"}, +] + +[package.dependencies] +execnet = ">=1.1" +pytest = ">=6.2.0" + +[package.extras] +psutil = ["psutil (>=3.0)"] +setproctitle = ["setproctitle"] +testing = ["filelock"] + +[[package]] +name = "python-dateutil" +version = "2.8.2" +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.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "pytoolconfig" +version = "1.2.6" +description = "Python tool configuration" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytoolconfig-1.2.6-py3-none-any.whl", hash = "sha256:e8b2e538f11dbabc4617884d45401e0105e2d7db920cb8ae6baa94d66126a8e3"}, + {file = "pytoolconfig-1.2.6.tar.gz", hash = "sha256:f2d00ea4f8cbdffd3006780ba51016618c835b338f634e3f7f8b2715b1710889"}, +] + +[package.dependencies] +packaging = ">=22.0" +platformdirs = {version = ">=1.4.4", optional = true, markers = "extra == \"global\""} + +[package.extras] +doc = ["sphinx (>=4.5.0)", "tabulate (>=0.8.9)"] +gendocs = ["pytoolconfig[doc]", "sphinx (>=4.5.0)", "sphinx-autodoc-typehints (>=1.18.1)", "sphinx-rtd-theme (>=1.0.0)"] +global = ["platformdirs (>=1.4.4)"] +validation = ["pydantic (>=1.7.4)"] + +[[package]] +name = "pytz" +version = "2023.3.post1" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +files = [ + {file = "pytz-2023.3.post1-py2.py3-none-any.whl", hash = "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7"}, + {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"}, +] + +[[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_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 = "redis" +version = "5.0.1" +description = "Python client for Redis database and key-value store" +optional = false +python-versions = ">=3.7" +files = [ + {file = "redis-5.0.1-py3-none-any.whl", hash = "sha256:ed4802971884ae19d640775ba3b03aa2e7bd5e8fb8dfaed2decce4d0fc48391f"}, + {file = "redis-5.0.1.tar.gz", hash = "sha256:0dab495cd5753069d3bc650a0dde8a8f9edde16fc5691b689a566eda58100d0f"}, +] + +[package.dependencies] +async-timeout = {version = ">=4.0.2", markers = "python_full_version <= \"3.11.2\""} + +[package.extras] +hiredis = ["hiredis (>=1.0.0)"] +ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"] + +[[package]] +name = "referencing" +version = "0.30.2" +description = "JSON Referencing + Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "referencing-0.30.2-py3-none-any.whl", hash = "sha256:449b6669b6121a9e96a7f9e410b245d471e8d48964c67113ce9afe50c8dd7bdf"}, + {file = "referencing-0.30.2.tar.gz", hash = "sha256:794ad8003c65938edcdbc027f1933215e0d0ccc0291e3ce20a4d87432b59efc0"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +rpds-py = ">=0.7.0" + +[[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-mock" +version = "1.11.0" +description = "Mock out responses from the requests package" +optional = false +python-versions = "*" +files = [ + {file = "requests-mock-1.11.0.tar.gz", hash = "sha256:ef10b572b489a5f28e09b708697208c4a3b2b89ef80a9f01584340ea357ec3c4"}, + {file = "requests_mock-1.11.0-py2.py3-none-any.whl", hash = "sha256:f7fae383f228633f6bececebdab236c478ace2284d6292c6e7e2867b9ab74d15"}, +] + +[package.dependencies] +requests = ">=2.3,<3" +six = "*" + +[package.extras] +fixture = ["fixtures"] +test = ["fixtures", "mock", "purl", "pytest", "requests-futures", "sphinx", "testtools"] + +[[package]] +name = "respx" +version = "0.20.2" +description = "A utility for mocking out the Python HTTPX and HTTP Core libraries." +optional = false +python-versions = ">=3.7" +files = [ + {file = "respx-0.20.2-py2.py3-none-any.whl", hash = "sha256:ab8e1cf6da28a5b2dd883ea617f8130f77f676736e6e9e4a25817ad116a172c9"}, + {file = "respx-0.20.2.tar.gz", hash = "sha256:07cf4108b1c88b82010f67d3c831dae33a375c7b436e54d87737c7f9f99be643"}, +] + +[package.dependencies] +httpx = ">=0.21.0" + +[[package]] +name = "retry" +version = "0.9.2" +description = "Easy to use retry decorator." +optional = false +python-versions = "*" +files = [ + {file = "retry-0.9.2-py2.py3-none-any.whl", hash = "sha256:ccddf89761fa2c726ab29391837d4327f819ea14d244c232a1d24c67a2f98606"}, + {file = "retry-0.9.2.tar.gz", hash = "sha256:f8bfa8b99b69c4506d6f5bd3b0aabf77f98cdb17f3c9fc3f5ca820033336fba4"}, +] + +[package.dependencies] +decorator = ">=3.4.2" +py = ">=1.4.26,<2.0.0" + +[[package]] +name = "rope" +version = "1.10.0" +description = "a python refactoring library..." +optional = false +python-versions = ">=3.8" +files = [ + {file = "rope-1.10.0-py3-none-any.whl", hash = "sha256:4e9f06d7296708a8a6518590c49352c99394053d91fde5b1d74c9ffc85c76d5b"}, + {file = "rope-1.10.0.tar.gz", hash = "sha256:14bfcc7dfea69fa32c53db0667e86e321ef059de555c7f8101a0cb91c8d85a55"}, +] + +[package.dependencies] +pytoolconfig = {version = ">=1.2.2", extras = ["global"]} + +[package.extras] +dev = ["build (>=0.7.0)", "pre-commit (>=2.20.0)", "pytest (>=7.0.1)", "pytest-timeout (>=2.1.0)"] +doc = ["pytoolconfig[doc]", "sphinx (>=4.5.0)", "sphinx-autodoc-typehints (>=1.18.1)", "sphinx-rtd-theme (>=1.0.0)"] +release = ["pip-tools (>=6.12.1)", "toml (>=0.10.2)", "twine (>=4.0.2)"] + +[[package]] +name = "rpds-py" +version = "0.10.6" +description = "Python bindings to Rust's persistent data structures (rpds)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "rpds_py-0.10.6-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:6bdc11f9623870d75692cc33c59804b5a18d7b8a4b79ef0b00b773a27397d1f6"}, + {file = "rpds_py-0.10.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:26857f0f44f0e791f4a266595a7a09d21f6b589580ee0585f330aaccccb836e3"}, + {file = "rpds_py-0.10.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7f5e15c953ace2e8dde9824bdab4bec50adb91a5663df08d7d994240ae6fa31"}, + {file = "rpds_py-0.10.6-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:61fa268da6e2e1cd350739bb61011121fa550aa2545762e3dc02ea177ee4de35"}, + {file = "rpds_py-0.10.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c48f3fbc3e92c7dd6681a258d22f23adc2eb183c8cb1557d2fcc5a024e80b094"}, + {file = "rpds_py-0.10.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0503c5b681566e8b722fe8c4c47cce5c7a51f6935d5c7012c4aefe952a35eed"}, + {file = "rpds_py-0.10.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:734c41f9f57cc28658d98270d3436dba65bed0cfc730d115b290e970150c540d"}, + {file = "rpds_py-0.10.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a5d7ed104d158c0042a6a73799cf0eb576dfd5fc1ace9c47996e52320c37cb7c"}, + {file = "rpds_py-0.10.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e3df0bc35e746cce42579826b89579d13fd27c3d5319a6afca9893a9b784ff1b"}, + {file = "rpds_py-0.10.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:73e0a78a9b843b8c2128028864901f55190401ba38aae685350cf69b98d9f7c9"}, + {file = "rpds_py-0.10.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5ed505ec6305abd2c2c9586a7b04fbd4baf42d4d684a9c12ec6110deefe2a063"}, + {file = "rpds_py-0.10.6-cp310-none-win32.whl", hash = "sha256:d97dd44683802000277bbf142fd9f6b271746b4846d0acaf0cefa6b2eaf2a7ad"}, + {file = "rpds_py-0.10.6-cp310-none-win_amd64.whl", hash = "sha256:b455492cab07107bfe8711e20cd920cc96003e0da3c1f91297235b1603d2aca7"}, + {file = "rpds_py-0.10.6-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:e8cdd52744f680346ff8c1ecdad5f4d11117e1724d4f4e1874f3a67598821069"}, + {file = "rpds_py-0.10.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:66414dafe4326bca200e165c2e789976cab2587ec71beb80f59f4796b786a238"}, + {file = "rpds_py-0.10.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc435d059f926fdc5b05822b1be4ff2a3a040f3ae0a7bbbe672babb468944722"}, + {file = "rpds_py-0.10.6-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8e7f2219cb72474571974d29a191714d822e58be1eb171f229732bc6fdedf0ac"}, + {file = "rpds_py-0.10.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3953c6926a63f8ea5514644b7afb42659b505ece4183fdaaa8f61d978754349e"}, + {file = "rpds_py-0.10.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2bb2e4826be25e72013916eecd3d30f66fd076110de09f0e750163b416500721"}, + {file = "rpds_py-0.10.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bf347b495b197992efc81a7408e9a83b931b2f056728529956a4d0858608b80"}, + {file = "rpds_py-0.10.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:102eac53bb0bf0f9a275b438e6cf6904904908562a1463a6fc3323cf47d7a532"}, + {file = "rpds_py-0.10.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:40f93086eef235623aa14dbddef1b9fb4b22b99454cb39a8d2e04c994fb9868c"}, + {file = "rpds_py-0.10.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e22260a4741a0e7a206e175232867b48a16e0401ef5bce3c67ca5b9705879066"}, + {file = "rpds_py-0.10.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f4e56860a5af16a0fcfa070a0a20c42fbb2012eed1eb5ceeddcc7f8079214281"}, + {file = "rpds_py-0.10.6-cp311-none-win32.whl", hash = "sha256:0774a46b38e70fdde0c6ded8d6d73115a7c39d7839a164cc833f170bbf539116"}, + {file = "rpds_py-0.10.6-cp311-none-win_amd64.whl", hash = "sha256:4a5ee600477b918ab345209eddafde9f91c0acd931f3776369585a1c55b04c57"}, + {file = "rpds_py-0.10.6-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:5ee97c683eaface61d38ec9a489e353d36444cdebb128a27fe486a291647aff6"}, + {file = "rpds_py-0.10.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0713631d6e2d6c316c2f7b9320a34f44abb644fc487b77161d1724d883662e31"}, + {file = "rpds_py-0.10.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5a53f5998b4bbff1cb2e967e66ab2addc67326a274567697379dd1e326bded7"}, + {file = "rpds_py-0.10.6-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6a555ae3d2e61118a9d3e549737bb4a56ff0cec88a22bd1dfcad5b4e04759175"}, + {file = "rpds_py-0.10.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:945eb4b6bb8144909b203a88a35e0a03d22b57aefb06c9b26c6e16d72e5eb0f0"}, + {file = "rpds_py-0.10.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:52c215eb46307c25f9fd2771cac8135d14b11a92ae48d17968eda5aa9aaf5071"}, + {file = "rpds_py-0.10.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1b3cd23d905589cb205710b3988fc8f46d4a198cf12862887b09d7aaa6bf9b9"}, + {file = "rpds_py-0.10.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64ccc28683666672d7c166ed465c09cee36e306c156e787acef3c0c62f90da5a"}, + {file = "rpds_py-0.10.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:516a611a2de12fbea70c78271e558f725c660ce38e0006f75139ba337d56b1f6"}, + {file = "rpds_py-0.10.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9ff93d3aedef11f9c4540cf347f8bb135dd9323a2fc705633d83210d464c579d"}, + {file = "rpds_py-0.10.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d858532212f0650be12b6042ff4378dc2efbb7792a286bee4489eaa7ba010586"}, + {file = "rpds_py-0.10.6-cp312-none-win32.whl", hash = "sha256:3c4eff26eddac49d52697a98ea01b0246e44ca82ab09354e94aae8823e8bda02"}, + {file = "rpds_py-0.10.6-cp312-none-win_amd64.whl", hash = "sha256:150eec465dbc9cbca943c8e557a21afdcf9bab8aaabf386c44b794c2f94143d2"}, + {file = "rpds_py-0.10.6-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:cf693eb4a08eccc1a1b636e4392322582db2a47470d52e824b25eca7a3977b53"}, + {file = "rpds_py-0.10.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4134aa2342f9b2ab6c33d5c172e40f9ef802c61bb9ca30d21782f6e035ed0043"}, + {file = "rpds_py-0.10.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e782379c2028a3611285a795b89b99a52722946d19fc06f002f8b53e3ea26ea9"}, + {file = "rpds_py-0.10.6-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f6da6d842195fddc1cd34c3da8a40f6e99e4a113918faa5e60bf132f917c247"}, + {file = "rpds_py-0.10.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b4a9fe992887ac68256c930a2011255bae0bf5ec837475bc6f7edd7c8dfa254e"}, + {file = "rpds_py-0.10.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b788276a3c114e9f51e257f2a6f544c32c02dab4aa7a5816b96444e3f9ffc336"}, + {file = "rpds_py-0.10.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:caa1afc70a02645809c744eefb7d6ee8fef7e2fad170ffdeacca267fd2674f13"}, + {file = "rpds_py-0.10.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bddd4f91eede9ca5275e70479ed3656e76c8cdaaa1b354e544cbcf94c6fc8ac4"}, + {file = "rpds_py-0.10.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:775049dfa63fb58293990fc59473e659fcafd953bba1d00fc5f0631a8fd61977"}, + {file = "rpds_py-0.10.6-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:c6c45a2d2b68c51fe3d9352733fe048291e483376c94f7723458cfd7b473136b"}, + {file = "rpds_py-0.10.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0699ab6b8c98df998c3eacf51a3b25864ca93dab157abe358af46dc95ecd9801"}, + {file = "rpds_py-0.10.6-cp38-none-win32.whl", hash = "sha256:ebdab79f42c5961682654b851f3f0fc68e6cc7cd8727c2ac4ffff955154123c1"}, + {file = "rpds_py-0.10.6-cp38-none-win_amd64.whl", hash = "sha256:24656dc36f866c33856baa3ab309da0b6a60f37d25d14be916bd3e79d9f3afcf"}, + {file = "rpds_py-0.10.6-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:0898173249141ee99ffcd45e3829abe7bcee47d941af7434ccbf97717df020e5"}, + {file = "rpds_py-0.10.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9e9184fa6c52a74a5521e3e87badbf9692549c0fcced47443585876fcc47e469"}, + {file = "rpds_py-0.10.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5752b761902cd15073a527b51de76bbae63d938dc7c5c4ad1e7d8df10e765138"}, + {file = "rpds_py-0.10.6-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:99a57006b4ec39dbfb3ed67e5b27192792ffb0553206a107e4aadb39c5004cd5"}, + {file = "rpds_py-0.10.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09586f51a215d17efdb3a5f090d7cbf1633b7f3708f60a044757a5d48a83b393"}, + {file = "rpds_py-0.10.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e225a6a14ecf44499aadea165299092ab0cba918bb9ccd9304eab1138844490b"}, + {file = "rpds_py-0.10.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2039f8d545f20c4e52713eea51a275e62153ee96c8035a32b2abb772b6fc9e5"}, + {file = "rpds_py-0.10.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:34ad87a831940521d462ac11f1774edf867c34172010f5390b2f06b85dcc6014"}, + {file = "rpds_py-0.10.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dcdc88b6b01015da066da3fb76545e8bb9a6880a5ebf89e0f0b2e3ca557b3ab7"}, + {file = "rpds_py-0.10.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:25860ed5c4e7f5e10c496ea78af46ae8d8468e0be745bd233bab9ca99bfd2647"}, + {file = "rpds_py-0.10.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7854a207ef77319ec457c1eb79c361b48807d252d94348305db4f4b62f40f7f3"}, + {file = "rpds_py-0.10.6-cp39-none-win32.whl", hash = "sha256:e6fcc026a3f27c1282c7ed24b7fcac82cdd70a0e84cc848c0841a3ab1e3dea2d"}, + {file = "rpds_py-0.10.6-cp39-none-win_amd64.whl", hash = "sha256:e98c4c07ee4c4b3acf787e91b27688409d918212dfd34c872201273fdd5a0e18"}, + {file = "rpds_py-0.10.6-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:68fe9199184c18d997d2e4293b34327c0009a78599ce703e15cd9a0f47349bba"}, + {file = "rpds_py-0.10.6-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:3339eca941568ed52d9ad0f1b8eb9fe0958fa245381747cecf2e9a78a5539c42"}, + {file = "rpds_py-0.10.6-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a360cfd0881d36c6dc271992ce1eda65dba5e9368575663de993eeb4523d895f"}, + {file = "rpds_py-0.10.6-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:031f76fc87644a234883b51145e43985aa2d0c19b063e91d44379cd2786144f8"}, + {file = "rpds_py-0.10.6-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f36a9d751f86455dc5278517e8b65580eeee37d61606183897f122c9e51cef3"}, + {file = "rpds_py-0.10.6-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:052a832078943d2b2627aea0d19381f607fe331cc0eb5df01991268253af8417"}, + {file = "rpds_py-0.10.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:023574366002bf1bd751ebaf3e580aef4a468b3d3c216d2f3f7e16fdabd885ed"}, + {file = "rpds_py-0.10.6-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:defa2c0c68734f4a82028c26bcc85e6b92cced99866af118cd6a89b734ad8e0d"}, + {file = "rpds_py-0.10.6-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:879fb24304ead6b62dbe5034e7b644b71def53c70e19363f3c3be2705c17a3b4"}, + {file = "rpds_py-0.10.6-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:53c43e10d398e365da2d4cc0bcaf0854b79b4c50ee9689652cdc72948e86f487"}, + {file = "rpds_py-0.10.6-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:3777cc9dea0e6c464e4b24760664bd8831738cc582c1d8aacf1c3f546bef3f65"}, + {file = "rpds_py-0.10.6-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:40578a6469e5d1df71b006936ce95804edb5df47b520c69cf5af264d462f2cbb"}, + {file = "rpds_py-0.10.6-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:cf71343646756a072b85f228d35b1d7407da1669a3de3cf47f8bbafe0c8183a4"}, + {file = "rpds_py-0.10.6-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10f32b53f424fc75ff7b713b2edb286fdbfc94bf16317890260a81c2c00385dc"}, + {file = "rpds_py-0.10.6-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:81de24a1c51cfb32e1fbf018ab0bdbc79c04c035986526f76c33e3f9e0f3356c"}, + {file = "rpds_py-0.10.6-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac17044876e64a8ea20ab132080ddc73b895b4abe9976e263b0e30ee5be7b9c2"}, + {file = "rpds_py-0.10.6-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5e8a78bd4879bff82daef48c14d5d4057f6856149094848c3ed0ecaf49f5aec2"}, + {file = "rpds_py-0.10.6-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78ca33811e1d95cac8c2e49cb86c0fb71f4d8409d8cbea0cb495b6dbddb30a55"}, + {file = "rpds_py-0.10.6-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c63c3ef43f0b3fb00571cff6c3967cc261c0ebd14a0a134a12e83bdb8f49f21f"}, + {file = "rpds_py-0.10.6-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:7fde6d0e00b2fd0dbbb40c0eeec463ef147819f23725eda58105ba9ca48744f4"}, + {file = "rpds_py-0.10.6-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:79edd779cfc46b2e15b0830eecd8b4b93f1a96649bcb502453df471a54ce7977"}, + {file = "rpds_py-0.10.6-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:9164ec8010327ab9af931d7ccd12ab8d8b5dc2f4c6a16cbdd9d087861eaaefa1"}, + {file = "rpds_py-0.10.6-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d29ddefeab1791e3c751e0189d5f4b3dbc0bbe033b06e9c333dca1f99e1d523e"}, + {file = "rpds_py-0.10.6-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:30adb75ecd7c2a52f5e76af50644b3e0b5ba036321c390b8e7ec1bb2a16dd43c"}, + {file = "rpds_py-0.10.6-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd609fafdcdde6e67a139898196698af37438b035b25ad63704fd9097d9a3482"}, + {file = "rpds_py-0.10.6-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6eef672de005736a6efd565577101277db6057f65640a813de6c2707dc69f396"}, + {file = "rpds_py-0.10.6-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cf4393c7b41abbf07c88eb83e8af5013606b1cdb7f6bc96b1b3536b53a574b8"}, + {file = "rpds_py-0.10.6-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ad857f42831e5b8d41a32437f88d86ead6c191455a3499c4b6d15e007936d4cf"}, + {file = "rpds_py-0.10.6-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d7360573f1e046cb3b0dceeb8864025aa78d98be4bb69f067ec1c40a9e2d9df"}, + {file = "rpds_py-0.10.6-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d08f63561c8a695afec4975fae445245386d645e3e446e6f260e81663bfd2e38"}, + {file = "rpds_py-0.10.6-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:f0f17f2ce0f3529177a5fff5525204fad7b43dd437d017dd0317f2746773443d"}, + {file = "rpds_py-0.10.6-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:442626328600bde1d09dc3bb00434f5374948838ce75c41a52152615689f9403"}, + {file = "rpds_py-0.10.6-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:e9616f5bd2595f7f4a04b67039d890348ab826e943a9bfdbe4938d0eba606971"}, + {file = "rpds_py-0.10.6.tar.gz", hash = "sha256:4ce5a708d65a8dbf3748d2474b580d606b1b9f91b5c6ab2a316e0b0cf7a4ba50"}, +] + +[[package]] +name = "s3transfer" +version = "0.7.0" +description = "An Amazon S3 Transfer Manager" +optional = false +python-versions = ">= 3.7" +files = [ + {file = "s3transfer-0.7.0-py3-none-any.whl", hash = "sha256:10d6923c6359175f264811ef4bf6161a3156ce8e350e705396a7557d6293c33a"}, + {file = "s3transfer-0.7.0.tar.gz", hash = "sha256:fd3889a66f5fe17299fe75b82eae6cf722554edca744ca5d5fe308b104883d2e"}, +] + +[package.dependencies] +botocore = ">=1.12.36,<2.0a.0" + +[package.extras] +crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"] + +[[package]] +name = "sentry-sdk" +version = "1.32.0" +description = "Python client for Sentry (https://sentry.io)" +optional = false +python-versions = "*" +files = [ + {file = "sentry-sdk-1.32.0.tar.gz", hash = "sha256:935e8fbd7787a3702457393b74b13d89a5afb67185bc0af85c00cb27cbd42e7c"}, + {file = "sentry_sdk-1.32.0-py2.py3-none-any.whl", hash = "sha256:eeb0b3550536f3bbc05bb1c7e0feb3a78d74acb43b607159a606ed2ec0a33a4d"}, +] + +[package.dependencies] +certifi = "*" +urllib3 = {version = ">=1.26.11", markers = "python_version >= \"3.6\""} + +[package.extras] +aiohttp = ["aiohttp (>=3.5)"] +arq = ["arq (>=0.23)"] +asyncpg = ["asyncpg (>=0.23)"] +beam = ["apache-beam (>=2.12)"] +bottle = ["bottle (>=0.12.13)"] +celery = ["celery (>=3)"] +chalice = ["chalice (>=1.16.0)"] +clickhouse-driver = ["clickhouse-driver (>=0.2.0)"] +django = ["django (>=1.8)"] +falcon = ["falcon (>=1.4)"] +fastapi = ["fastapi (>=0.79.0)"] +flask = ["blinker (>=1.1)", "flask (>=0.11)", "markupsafe"] +grpcio = ["grpcio (>=1.21.1)"] +httpx = ["httpx (>=0.16.0)"] +huey = ["huey (>=2)"] +loguru = ["loguru (>=0.5)"] +opentelemetry = ["opentelemetry-distro (>=0.35b0)"] +opentelemetry-experimental = ["opentelemetry-distro (>=0.40b0,<1.0)", "opentelemetry-instrumentation-aiohttp-client (>=0.40b0,<1.0)", "opentelemetry-instrumentation-django (>=0.40b0,<1.0)", "opentelemetry-instrumentation-fastapi (>=0.40b0,<1.0)", "opentelemetry-instrumentation-flask (>=0.40b0,<1.0)", "opentelemetry-instrumentation-requests (>=0.40b0,<1.0)", "opentelemetry-instrumentation-sqlite3 (>=0.40b0,<1.0)", "opentelemetry-instrumentation-urllib (>=0.40b0,<1.0)"] +pure-eval = ["asttokens", "executing", "pure-eval"] +pymongo = ["pymongo (>=3.1)"] +pyspark = ["pyspark (>=2.4.4)"] +quart = ["blinker (>=1.1)", "quart (>=0.16.1)"] +rq = ["rq (>=0.6)"] +sanic = ["sanic (>=0.8)"] +sqlalchemy = ["sqlalchemy (>=1.2)"] +starlette = ["starlette (>=0.19.1)"] +starlite = ["starlite (>=1.48)"] +tornado = ["tornado (>=5)"] + +[[package]] +name = "setuptools" +version = "68.2.2" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-68.2.2-py3-none-any.whl", hash = "sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a"}, + {file = "setuptools-68.2.2.tar.gz", hash = "sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87"}, +] + +[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-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "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.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + +[[package]] +name = "shortuuid" +version = "1.0.11" +description = "A generator library for concise, unambiguous and URL-safe UUIDs." +optional = false +python-versions = ">=3.5" +files = [ + {file = "shortuuid-1.0.11-py3-none-any.whl", hash = "sha256:27ea8f28b1bd0bf8f15057a3ece57275d2059d2b0bb02854f02189962c13b6aa"}, + {file = "shortuuid-1.0.11.tar.gz", hash = "sha256:fc75f2615914815a8e4cb1501b3a513745cb66ef0fd5fc6fb9f8c3fa3481f789"}, +] + +[[package]] +name = "simplejson" +version = "3.19.2" +description = "Simple, fast, extensible JSON encoder/decoder for Python" +optional = false +python-versions = ">=2.5, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "simplejson-3.19.2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3471e95110dcaf901db16063b2e40fb394f8a9e99b3fe9ee3acc6f6ef72183a2"}, + {file = "simplejson-3.19.2-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:3194cd0d2c959062b94094c0a9f8780ffd38417a5322450a0db0ca1a23e7fbd2"}, + {file = "simplejson-3.19.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:8a390e56a7963e3946ff2049ee1eb218380e87c8a0e7608f7f8790ba19390867"}, + {file = "simplejson-3.19.2-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:1537b3dd62d8aae644f3518c407aa8469e3fd0f179cdf86c5992792713ed717a"}, + {file = "simplejson-3.19.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:a8617625369d2d03766413bff9e64310feafc9fc4f0ad2b902136f1a5cd8c6b0"}, + {file = "simplejson-3.19.2-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:2c433a412e96afb9a3ce36fa96c8e61a757af53e9c9192c97392f72871e18e69"}, + {file = "simplejson-3.19.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:f1c70249b15e4ce1a7d5340c97670a95f305ca79f376887759b43bb33288c973"}, + {file = "simplejson-3.19.2-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:287e39ba24e141b046812c880f4619d0ca9e617235d74abc27267194fc0c7835"}, + {file = "simplejson-3.19.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:6f0a0b41dd05eefab547576bed0cf066595f3b20b083956b1405a6f17d1be6ad"}, + {file = "simplejson-3.19.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2f98d918f7f3aaf4b91f2b08c0c92b1774aea113334f7cde4fe40e777114dbe6"}, + {file = "simplejson-3.19.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7d74beca677623481810c7052926365d5f07393c72cbf62d6cce29991b676402"}, + {file = "simplejson-3.19.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7f2398361508c560d0bf1773af19e9fe644e218f2a814a02210ac2c97ad70db0"}, + {file = "simplejson-3.19.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ad331349b0b9ca6da86064a3599c425c7a21cd41616e175ddba0866da32df48"}, + {file = "simplejson-3.19.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:332c848f02d71a649272b3f1feccacb7e4f7e6de4a2e6dc70a32645326f3d428"}, + {file = "simplejson-3.19.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:25785d038281cd106c0d91a68b9930049b6464288cea59ba95b35ee37c2d23a5"}, + {file = "simplejson-3.19.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18955c1da6fc39d957adfa346f75226246b6569e096ac9e40f67d102278c3bcb"}, + {file = "simplejson-3.19.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:11cc3afd8160d44582543838b7e4f9aa5e97865322844b75d51bf4e0e413bb3e"}, + {file = "simplejson-3.19.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:b01fda3e95d07a6148702a641e5e293b6da7863f8bc9b967f62db9461330562c"}, + {file = "simplejson-3.19.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:778331444917108fa8441f59af45886270d33ce8a23bfc4f9b192c0b2ecef1b3"}, + {file = "simplejson-3.19.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9eb117db8d7ed733a7317c4215c35993b815bf6aeab67523f1f11e108c040672"}, + {file = "simplejson-3.19.2-cp310-cp310-win32.whl", hash = "sha256:39b6d79f5cbfa3eb63a869639cfacf7c41d753c64f7801efc72692c1b2637ac7"}, + {file = "simplejson-3.19.2-cp310-cp310-win_amd64.whl", hash = "sha256:5675e9d8eeef0aa06093c1ff898413ade042d73dc920a03e8cea2fb68f62445a"}, + {file = "simplejson-3.19.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ed628c1431100b0b65387419551e822987396bee3c088a15d68446d92f554e0c"}, + {file = "simplejson-3.19.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:adcb3332979cbc941b8fff07181f06d2b608625edc0a4d8bc3ffc0be414ad0c4"}, + {file = "simplejson-3.19.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:08889f2f597ae965284d7b52a5c3928653a9406d88c93e3161180f0abc2433ba"}, + {file = "simplejson-3.19.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef7938a78447174e2616be223f496ddccdbf7854f7bf2ce716dbccd958cc7d13"}, + {file = "simplejson-3.19.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a970a2e6d5281d56cacf3dc82081c95c1f4da5a559e52469287457811db6a79b"}, + {file = "simplejson-3.19.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:554313db34d63eac3b3f42986aa9efddd1a481169c12b7be1e7512edebff8eaf"}, + {file = "simplejson-3.19.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d36081c0b1c12ea0ed62c202046dca11438bee48dd5240b7c8de8da62c620e9"}, + {file = "simplejson-3.19.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a3cd18e03b0ee54ea4319cdcce48357719ea487b53f92a469ba8ca8e39df285e"}, + {file = "simplejson-3.19.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:66e5dc13bfb17cd6ee764fc96ccafd6e405daa846a42baab81f4c60e15650414"}, + {file = "simplejson-3.19.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:972a7833d4a1fcf7a711c939e315721a88b988553fc770a5b6a5a64bd6ebeba3"}, + {file = "simplejson-3.19.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3e74355cb47e0cd399ead3477e29e2f50e1540952c22fb3504dda0184fc9819f"}, + {file = "simplejson-3.19.2-cp311-cp311-win32.whl", hash = "sha256:1dd4f692304854352c3e396e9b5f0a9c9e666868dd0bdc784e2ac4c93092d87b"}, + {file = "simplejson-3.19.2-cp311-cp311-win_amd64.whl", hash = "sha256:9300aee2a8b5992d0f4293d88deb59c218989833e3396c824b69ba330d04a589"}, + {file = "simplejson-3.19.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b8d940fd28eb34a7084877747a60873956893e377f15a32ad445fe66c972c3b8"}, + {file = "simplejson-3.19.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4969d974d9db826a2c07671273e6b27bc48e940738d768fa8f33b577f0978378"}, + {file = "simplejson-3.19.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c594642d6b13d225e10df5c16ee15b3398e21a35ecd6aee824f107a625690374"}, + {file = "simplejson-3.19.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2f5a398b5e77bb01b23d92872255e1bcb3c0c719a3be40b8df146570fe7781a"}, + {file = "simplejson-3.19.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:176a1b524a3bd3314ed47029a86d02d5a95cc0bee15bd3063a1e1ec62b947de6"}, + {file = "simplejson-3.19.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3c7363a8cb8c5238878ec96c5eb0fc5ca2cb11fc0c7d2379863d342c6ee367a"}, + {file = "simplejson-3.19.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:346820ae96aa90c7d52653539a57766f10f33dd4be609206c001432b59ddf89f"}, + {file = "simplejson-3.19.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de9a2792612ec6def556d1dc621fd6b2073aff015d64fba9f3e53349ad292734"}, + {file = "simplejson-3.19.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1c768e7584c45094dca4b334af361e43b0aaa4844c04945ac7d43379eeda9bc2"}, + {file = "simplejson-3.19.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:9652e59c022e62a5b58a6f9948b104e5bb96d3b06940c6482588176f40f4914b"}, + {file = "simplejson-3.19.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9c1a4393242e321e344213a90a1e3bf35d2f624aa8b8f6174d43e3c6b0e8f6eb"}, + {file = "simplejson-3.19.2-cp312-cp312-win32.whl", hash = "sha256:7cb98be113911cb0ad09e5523d0e2a926c09a465c9abb0784c9269efe4f95917"}, + {file = "simplejson-3.19.2-cp312-cp312-win_amd64.whl", hash = "sha256:6779105d2fcb7fcf794a6a2a233787f6bbd4731227333a072d8513b252ed374f"}, + {file = "simplejson-3.19.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:061e81ea2d62671fa9dea2c2bfbc1eec2617ae7651e366c7b4a2baf0a8c72cae"}, + {file = "simplejson-3.19.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4280e460e51f86ad76dc456acdbfa9513bdf329556ffc8c49e0200878ca57816"}, + {file = "simplejson-3.19.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11c39fbc4280d7420684494373b7c5904fa72a2b48ef543a56c2d412999c9e5d"}, + {file = "simplejson-3.19.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bccb3e88ec26ffa90f72229f983d3a5d1155e41a1171190fa723d4135523585b"}, + {file = "simplejson-3.19.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bb5b50dc6dd671eb46a605a3e2eb98deb4a9af787a08fcdddabe5d824bb9664"}, + {file = "simplejson-3.19.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:d94245caa3c61f760c4ce4953cfa76e7739b6f2cbfc94cc46fff6c050c2390c5"}, + {file = "simplejson-3.19.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:d0e5ffc763678d48ecc8da836f2ae2dd1b6eb2d27a48671066f91694e575173c"}, + {file = "simplejson-3.19.2-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:d222a9ed082cd9f38b58923775152003765016342a12f08f8c123bf893461f28"}, + {file = "simplejson-3.19.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8434dcdd347459f9fd9c526117c01fe7ca7b016b6008dddc3c13471098f4f0dc"}, + {file = "simplejson-3.19.2-cp36-cp36m-win32.whl", hash = "sha256:c9ac1c2678abf9270e7228133e5b77c6c3c930ad33a3c1dfbdd76ff2c33b7b50"}, + {file = "simplejson-3.19.2-cp36-cp36m-win_amd64.whl", hash = "sha256:92c4a4a2b1f4846cd4364855cbac83efc48ff5a7d7c06ba014c792dd96483f6f"}, + {file = "simplejson-3.19.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0d551dc931638e2102b8549836a1632e6e7cf620af3d093a7456aa642bff601d"}, + {file = "simplejson-3.19.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:73a8a4653f2e809049999d63530180d7b5a344b23a793502413ad1ecea9a0290"}, + {file = "simplejson-3.19.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:40847f617287a38623507d08cbcb75d51cf9d4f9551dd6321df40215128325a3"}, + {file = "simplejson-3.19.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be893258d5b68dd3a8cba8deb35dc6411db844a9d35268a8d3793b9d9a256f80"}, + {file = "simplejson-3.19.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9eb3cff1b7d71aa50c89a0536f469cb8d6dcdd585d8f14fb8500d822f3bdee4"}, + {file = "simplejson-3.19.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d0f402e787e6e7ee7876c8b05e2fe6464820d9f35ba3f172e95b5f8b699f6c7f"}, + {file = "simplejson-3.19.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:fbbcc6b0639aa09b9649f36f1bcb347b19403fe44109948392fbb5ea69e48c3e"}, + {file = "simplejson-3.19.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:2fc697be37585eded0c8581c4788fcfac0e3f84ca635b73a5bf360e28c8ea1a2"}, + {file = "simplejson-3.19.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0b0a3eb6dd39cce23801a50c01a0976971498da49bc8a0590ce311492b82c44b"}, + {file = "simplejson-3.19.2-cp37-cp37m-win32.whl", hash = "sha256:49f9da0d6cd17b600a178439d7d2d57c5ef01f816b1e0e875e8e8b3b42db2693"}, + {file = "simplejson-3.19.2-cp37-cp37m-win_amd64.whl", hash = "sha256:c87c22bd6a987aca976e3d3e23806d17f65426191db36d40da4ae16a6a494cbc"}, + {file = "simplejson-3.19.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9e4c166f743bb42c5fcc60760fb1c3623e8fda94f6619534217b083e08644b46"}, + {file = "simplejson-3.19.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0a48679310e1dd5c9f03481799311a65d343748fe86850b7fb41df4e2c00c087"}, + {file = "simplejson-3.19.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c0521e0f07cb56415fdb3aae0bbd8701eb31a9dfef47bb57206075a0584ab2a2"}, + {file = "simplejson-3.19.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d2d5119b1d7a1ed286b8af37357116072fc96700bce3bec5bb81b2e7057ab41"}, + {file = "simplejson-3.19.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2c1467d939932901a97ba4f979e8f2642415fcf02ea12f53a4e3206c9c03bc17"}, + {file = "simplejson-3.19.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49aaf4546f6023c44d7e7136be84a03a4237f0b2b5fb2b17c3e3770a758fc1a0"}, + {file = "simplejson-3.19.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60848ab779195b72382841fc3fa4f71698a98d9589b0a081a9399904487b5832"}, + {file = "simplejson-3.19.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0436a70d8eb42bea4fe1a1c32d371d9bb3b62c637969cb33970ad624d5a3336a"}, + {file = "simplejson-3.19.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:49e0e3faf3070abdf71a5c80a97c1afc059b4f45a5aa62de0c2ca0444b51669b"}, + {file = "simplejson-3.19.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ff836cd4041e16003549449cc0a5e372f6b6f871eb89007ab0ee18fb2800fded"}, + {file = "simplejson-3.19.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3848427b65e31bea2c11f521b6fc7a3145d6e501a1038529da2391aff5970f2f"}, + {file = "simplejson-3.19.2-cp38-cp38-win32.whl", hash = "sha256:3f39bb1f6e620f3e158c8b2eaf1b3e3e54408baca96a02fe891794705e788637"}, + {file = "simplejson-3.19.2-cp38-cp38-win_amd64.whl", hash = "sha256:0405984f3ec1d3f8777c4adc33eac7ab7a3e629f3b1c05fdded63acc7cf01137"}, + {file = "simplejson-3.19.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:445a96543948c011a3a47c8e0f9d61e9785df2544ea5be5ab3bc2be4bd8a2565"}, + {file = "simplejson-3.19.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4a8c3cc4f9dfc33220246760358c8265dad6e1104f25f0077bbca692d616d358"}, + {file = "simplejson-3.19.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:af9c7e6669c4d0ad7362f79cb2ab6784d71147503e62b57e3d95c4a0f222c01c"}, + {file = "simplejson-3.19.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:064300a4ea17d1cd9ea1706aa0590dcb3be81112aac30233823ee494f02cb78a"}, + {file = "simplejson-3.19.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9453419ea2ab9b21d925d0fd7e3a132a178a191881fab4169b6f96e118cc25bb"}, + {file = "simplejson-3.19.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e038c615b3906df4c3be8db16b3e24821d26c55177638ea47b3f8f73615111c"}, + {file = "simplejson-3.19.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16ca9c90da4b1f50f089e14485db8c20cbfff2d55424062791a7392b5a9b3ff9"}, + {file = "simplejson-3.19.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1018bd0d70ce85f165185d2227c71e3b1e446186f9fa9f971b69eee223e1e3cd"}, + {file = "simplejson-3.19.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e8dd53a8706b15bc0e34f00e6150fbefb35d2fd9235d095b4f83b3c5ed4fa11d"}, + {file = "simplejson-3.19.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:2d022b14d7758bfb98405672953fe5c202ea8a9ccf9f6713c5bd0718eba286fd"}, + {file = "simplejson-3.19.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:febffa5b1eda6622d44b245b0685aff6fb555ce0ed734e2d7b1c3acd018a2cff"}, + {file = "simplejson-3.19.2-cp39-cp39-win32.whl", hash = "sha256:4edcd0bf70087b244ba77038db23cd98a1ace2f91b4a3ecef22036314d77ac23"}, + {file = "simplejson-3.19.2-cp39-cp39-win_amd64.whl", hash = "sha256:aad7405c033d32c751d98d3a65801e2797ae77fac284a539f6c3a3e13005edc4"}, + {file = "simplejson-3.19.2-py3-none-any.whl", hash = "sha256:bcedf4cae0d47839fee7de344f96b5694ca53c786f28b5f773d4f0b265a159eb"}, + {file = "simplejson-3.19.2.tar.gz", hash = "sha256:9eb442a2442ce417801c912df68e1f6ccfcd41577ae7274953ab3ad24ef7d82c"}, +] + +[[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 = "sniffio" +version = "1.3.0" +description = "Sniff out which async library your code is running under" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, + {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, +] + +[[package]] +name = "sqlparse" +version = "0.4.4" +description = "A non-validating SQL parser." +optional = false +python-versions = ">=3.5" +files = [ + {file = "sqlparse-0.4.4-py3-none-any.whl", hash = "sha256:5430a4fe2ac7d0f93e66f1efc6e1338a41884b7ddf2a350cedd20ccc4d9d28f3"}, + {file = "sqlparse-0.4.4.tar.gz", hash = "sha256:d446183e84b8349fa3061f0fe7f06ca94ba65b426946ffebe6e3e8295332420c"}, +] + +[package.extras] +dev = ["build", "flake8"] +doc = ["sphinx"] +test = ["pytest", "pytest-cov"] + +[[package]] +name = "stack-data" +version = "0.6.3" +description = "Extract data from python stack frames and tracebacks for informative displays" +optional = false +python-versions = "*" +files = [ + {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"}, + {file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"}, +] + +[package.dependencies] +asttokens = ">=2.1.0" +executing = ">=1.2.0" +pure-eval = "*" + +[package.extras] +tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] + +[[package]] +name = "standardjson" +version = "0.3.1" +description = "JSON encoder that aims to be fully compliant with specifications ECMA-262 and ECMA-404." +optional = false +python-versions = "*" +files = [ + {file = "standardjson-0.3.1-py2.py3-none-any.whl", hash = "sha256:69e79b090d3f7dd887ae4a9db226ea79cd3fd3d7cfa8491d23ec6b06126e24b0"}, + {file = "standardjson-0.3.1.tar.gz", hash = "sha256:71b7b0a649d5e3bd343a02737e752c054c218242dcaa739abab98086e537fbab"}, +] + +[[package]] +name = "stripe" +version = "6.7.0" +description = "Python bindings for the Stripe API" +optional = false +python-versions = ">=3.6" +files = [ + {file = "stripe-6.7.0-py2.py3-none-any.whl", hash = "sha256:a453d6daa633f656297a9323c736fdcb53164418d643fdc30499a6d32ad7933c"}, + {file = "stripe-6.7.0.tar.gz", hash = "sha256:2794ccc4b4c97070d1cab4385e1d2aad65937b4437b75cc1faf7d67dda8199f4"}, +] + +[package.dependencies] +requests = {version = ">=2.20", markers = "python_version >= \"3.0\""} +typing-extensions = {version = ">=4.0.0", markers = "python_version >= \"3.7\""} + +[[package]] +name = "traitlets" +version = "5.12.0" +description = "Traitlets Python configuration system" +optional = false +python-versions = ">=3.8" +files = [ + {file = "traitlets-5.12.0-py3-none-any.whl", hash = "sha256:81539f07f7aebcde2e4b5ab76727f53eabf18ad155c6ed7979a681411602fa47"}, + {file = "traitlets-5.12.0.tar.gz", hash = "sha256:833273bf645d8ce31dcb613c56999e2e055b1ffe6d09168a164bcd91c36d5d35"}, +] + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] +test = ["argcomplete (>=3.0.3)", "mypy (>=1.6.0)", "pre-commit", "pytest (>=7.0,<7.5)", "pytest-mock", "pytest-mypy-testing"] + +[[package]] +name = "types-awscrt" +version = "0.19.3" +description = "Type annotations and code completion for awscrt" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "types_awscrt-0.19.3-py3-none-any.whl", hash = "sha256:7b55f5a12ccd4407bc8f1e35c69bb40c931f8513ce1ad81a4527fce3989003fd"}, + {file = "types_awscrt-0.19.3.tar.gz", hash = "sha256:9a21caac4287c113dd52665707785c45bb1d3242b7a2b8aeb57c49e9e749a330"}, +] + +[[package]] +name = "types-babel" +version = "2.11.0.15" +description = "Typing stubs for babel" +optional = false +python-versions = "*" +files = [ + {file = "types-babel-2.11.0.15.tar.gz", hash = "sha256:282c184c8c9d81e8269212c1b8fa0d39ee88fb8bc43be47980412781c9c85f7e"}, + {file = "types_babel-2.11.0.15-py3-none-any.whl", hash = "sha256:d0579f2e8adeaef3fbe2eb63e5a2ecf01767fc018e5f3f36a3c9d8b723bd62c7"}, +] + +[package.dependencies] +types-pytz = "*" +types-setuptools = "*" + +[[package]] +name = "types-bleach" +version = "6.1.0.0" +description = "Typing stubs for bleach" +optional = false +python-versions = ">=3.7" +files = [ + {file = "types-bleach-6.1.0.0.tar.gz", hash = "sha256:3cf0e55d4618890a00af1151f878b2e2a7a96433850b74e12bede7663d774532"}, + {file = "types_bleach-6.1.0.0-py3-none-any.whl", hash = "sha256:f0bc75d0f6475036ac69afebf37c41d116dfba78dae55db80437caf0fcd35c28"}, +] + +[[package]] +name = "types-freezegun" +version = "1.1.10" +description = "Typing stubs for freezegun" +optional = false +python-versions = "*" +files = [ + {file = "types-freezegun-1.1.10.tar.gz", hash = "sha256:cb3a2d2eee950eacbaac0673ab50499823365ceb8c655babb1544a41446409ec"}, + {file = "types_freezegun-1.1.10-py3-none-any.whl", hash = "sha256:fadebe72213e0674036153366205038e1f95c8ca96deb4ef9b71ddc15413543e"}, +] + +[[package]] +name = "types-markdown" +version = "3.5.0.0" +description = "Typing stubs for Markdown" +optional = false +python-versions = ">=3.7" +files = [ + {file = "types-Markdown-3.5.0.0.tar.gz", hash = "sha256:8c2f5526bba29feee24040d4694ced554d09ae46d1f1523b2b739558beabae42"}, + {file = "types_Markdown-3.5.0.0-py3-none-any.whl", hash = "sha256:f1ff987576f347ec83aca0c2ced45e64e1deb771e0a6189744480013ccb59c96"}, +] + +[[package]] +name = "types-pillow" +version = "10.1.0.0" +description = "Typing stubs for Pillow" +optional = false +python-versions = ">=3.7" +files = [ + {file = "types-Pillow-10.1.0.0.tar.gz", hash = "sha256:0f5e7cf010ed226800cb5821e87781e5d0e81257d948a9459baa74a8c8b7d822"}, + {file = "types_Pillow-10.1.0.0-py3-none-any.whl", hash = "sha256:f97f596b6a39ddfd26da3eb67421062193e10732d2310f33898d36f9694331b5"}, +] + +[[package]] +name = "types-pytz" +version = "2023.3.1.1" +description = "Typing stubs for pytz" +optional = false +python-versions = "*" +files = [ + {file = "types-pytz-2023.3.1.1.tar.gz", hash = "sha256:cc23d0192cd49c8f6bba44ee0c81e4586a8f30204970fc0894d209a6b08dab9a"}, + {file = "types_pytz-2023.3.1.1-py3-none-any.whl", hash = "sha256:1999a123a3dc0e39a2ef6d19f3f8584211de9e6a77fe7a0259f04a524e90a5cf"}, +] + +[[package]] +name = "types-pyyaml" +version = "6.0.12.12" +description = "Typing stubs for PyYAML" +optional = false +python-versions = "*" +files = [ + {file = "types-PyYAML-6.0.12.12.tar.gz", hash = "sha256:334373d392fde0fdf95af5c3f1661885fa10c52167b14593eb856289e1855062"}, + {file = "types_PyYAML-6.0.12.12-py3-none-any.whl", hash = "sha256:c05bc6c158facb0676674b7f11fe3960db4f389718e19e62bd2b84d6205cfd24"}, +] + +[[package]] +name = "types-requests" +version = "2.31.0.10" +description = "Typing stubs for requests" +optional = false +python-versions = ">=3.7" +files = [ + {file = "types-requests-2.31.0.10.tar.gz", hash = "sha256:dc5852a76f1eaf60eafa81a2e50aefa3d1f015c34cf0cba130930866b1b22a92"}, + {file = "types_requests-2.31.0.10-py3-none-any.whl", hash = "sha256:b32b9a86beffa876c0c3ac99a4cd3b8b51e973fb8e3bd4e0a6bb32c7efad80fc"}, +] + +[package.dependencies] +urllib3 = ">=2" + +[[package]] +name = "types-retry" +version = "0.9.9.4" +description = "Typing stubs for retry" +optional = false +python-versions = "*" +files = [ + {file = "types-retry-0.9.9.4.tar.gz", hash = "sha256:e4731dc684b56b875d9746459ad665d3bc281a56b530acdf1c97730167799941"}, + {file = "types_retry-0.9.9.4-py3-none-any.whl", hash = "sha256:f29760a9fe8b1fefe253e5fe6be7e4c0eba243932c600e0eccffb42a21d17765"}, +] + +[[package]] +name = "types-s3transfer" +version = "0.7.0" +description = "Type annotations and code completion for s3transfer" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "types_s3transfer-0.7.0-py3-none-any.whl", hash = "sha256:ae9ed9273465d9f43da8b96307383da410c6b59c3b2464c88d20b578768e97c6"}, + {file = "types_s3transfer-0.7.0.tar.gz", hash = "sha256:aca0f2486d0a3a5037cd5b8f3e20a4522a29579a8dd183281ff0aa1c4e2c8aa7"}, +] + +[[package]] +name = "types-setuptools" +version = "68.2.0.0" +description = "Typing stubs for setuptools" +optional = false +python-versions = "*" +files = [ + {file = "types-setuptools-68.2.0.0.tar.gz", hash = "sha256:a4216f1e2ef29d089877b3af3ab2acf489eb869ccaf905125c69d2dc3932fd85"}, + {file = "types_setuptools-68.2.0.0-py3-none-any.whl", hash = "sha256:77edcc843e53f8fc83bb1a840684841f3dc804ec94562623bfa2ea70d5a2ba1b"}, +] + +[[package]] +name = "types-simplejson" +version = "3.19.0.2" +description = "Typing stubs for simplejson" +optional = false +python-versions = "*" +files = [ + {file = "types-simplejson-3.19.0.2.tar.gz", hash = "sha256:ebc81f886f89d99d6b80c726518aa2228bc77c26438f18fd81455e4f79f8ee1b"}, + {file = "types_simplejson-3.19.0.2-py3-none-any.whl", hash = "sha256:8ba093dc7884f59b3e62aed217144085e675a269debc32678fd80e0b43b2b86f"}, +] + +[[package]] +name = "types-stripe" +version = "3.5.2.14" +description = "Typing stubs for stripe" +optional = false +python-versions = "*" +files = [ + {file = "types-stripe-3.5.2.14.tar.gz", hash = "sha256:bcc020aa5ba9acd796b9f2ac21f044c8e377ce2c0f570057f0f64c4b4637bbe7"}, + {file = "types_stripe-3.5.2.14-py3-none-any.whl", hash = "sha256:f5f1249f72a35ada1db95523edc7e8f7b543dc8434b2ff23eaa9ec2e251c2e59"}, +] + +[[package]] +name = "typing-extensions" +version = "4.8.0" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, + {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, +] + +[[package]] +name = "tzdata" +version = "2023.3" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +files = [ + {file = "tzdata-2023.3-py2.py3-none-any.whl", hash = "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"}, + {file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"}, +] + +[[package]] +name = "uritemplate" +version = "4.1.1" +description = "Implementation of RFC 6570 URI Templates" +optional = false +python-versions = ">=3.6" +files = [ + {file = "uritemplate-4.1.1-py2.py3-none-any.whl", hash = "sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e"}, + {file = "uritemplate-4.1.1.tar.gz", hash = "sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0"}, +] + +[[package]] +name = "urllib3" +version = "2.0.7" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.7" +files = [ + {file = "urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"}, + {file = "urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "vine" +version = "5.0.0" +description = "Promises, promises, promises." +optional = false +python-versions = ">=3.6" +files = [ + {file = "vine-5.0.0-py2.py3-none-any.whl", hash = "sha256:4c9dceab6f76ed92105027c49c823800dd33cacce13bdedc5b914e3514b7fb30"}, + {file = "vine-5.0.0.tar.gz", hash = "sha256:7d3b1624a953da82ef63462013bbd271d3eb75751489f9807598e8f340bd637e"}, +] + +[[package]] +name = "wcwidth" +version = "0.2.8" +description = "Measures the displayed width of unicode strings in a terminal" +optional = false +python-versions = "*" +files = [ + {file = "wcwidth-0.2.8-py2.py3-none-any.whl", hash = "sha256:77f719e01648ed600dfa5402c347481c0992263b81a027344f3e1ba25493a704"}, + {file = "wcwidth-0.2.8.tar.gz", hash = "sha256:8705c569999ffbb4f6a87c6d1b80f324bd6db952f5eb0b95bc07517f4c1813d4"}, +] + +[[package]] +name = "webencodings" +version = "0.5.1" +description = "Character encoding aliases for legacy web content" +optional = false +python-versions = "*" +files = [ + {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, + {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, +] + +[[package]] +name = "whitenoise" +version = "6.6.0" +description = "Radically simplified static file serving for WSGI applications" +optional = false +python-versions = ">=3.8" +files = [ + {file = "whitenoise-6.6.0-py3-none-any.whl", hash = "sha256:b1f9db9bf67dc183484d760b99f4080185633136a273a03f6436034a41064146"}, + {file = "whitenoise-6.6.0.tar.gz", hash = "sha256:8998f7370973447fac1e8ef6e8ded2c5209a7b1f67c1012866dbcd09681c3251"}, +] + +[package.extras] +brotli = ["Brotli"] + +[[package]] +name = "wrapt" +version = "1.15.0" +description = "Module for decorators, wrappers and monkey patching." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +files = [ + {file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a"}, + {file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"}, + {file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"}, + {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"}, + {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7"}, + {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0"}, + {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec"}, + {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90"}, + {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975"}, + {file = "wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1"}, + {file = "wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e"}, + {file = "wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7"}, + {file = "wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72"}, + {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb"}, + {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e"}, + {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c"}, + {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3"}, + {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92"}, + {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"}, + {file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"}, + {file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248"}, + {file = "wrapt-1.15.0-cp35-cp35m-win32.whl", hash = "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559"}, + {file = "wrapt-1.15.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"}, + {file = "wrapt-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba"}, + {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752"}, + {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364"}, + {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475"}, + {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8"}, + {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418"}, + {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2"}, + {file = "wrapt-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1"}, + {file = "wrapt-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420"}, + {file = "wrapt-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317"}, + {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e"}, + {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e"}, + {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0"}, + {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019"}, + {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034"}, + {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653"}, + {file = "wrapt-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0"}, + {file = "wrapt-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e"}, + {file = "wrapt-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145"}, + {file = "wrapt-1.15.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f"}, + {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd"}, + {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b"}, + {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f"}, + {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6"}, + {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094"}, + {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7"}, + {file = "wrapt-1.15.0-cp38-cp38-win32.whl", hash = "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b"}, + {file = "wrapt-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1"}, + {file = "wrapt-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86"}, + {file = "wrapt-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c"}, + {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d"}, + {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc"}, + {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29"}, + {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a"}, + {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8"}, + {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9"}, + {file = "wrapt-1.15.0-cp39-cp39-win32.whl", hash = "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff"}, + {file = "wrapt-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6"}, + {file = "wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640"}, + {file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "~3.11" +content-hash = "1c442030061150fdf8877225ebc3c57c9b8c87bd55af7d5c0d2a240afe04fd08" diff --git a/pyproject.toml b/pyproject.toml index 852e1c7e518..60c557c6966 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,141 +1,118 @@ -[project] +[tool.poetry] name = "education-backend" -version = "2022.10.31" -requires-python = ">=3.10" -dependencies = [ - "Django", - "django-behaviors", - "django-cors-headers", - "django-environ", - "django-ipware", - "django-split-settings", - "django-tree-queries", - "django-cachalot", - "django-prettyjson", - "whitenoise", - "psycopg2-binary", - "shortuuid", - "retry", - "bcrypt", - "simplejson", - "Pillow", - - "djangorestframework", - "django-storages", - "drf-recaptcha", - "drf-spectacular[sidecar]", - "drf-jwt", - "django-filter", - "django-anymail", - "django-axes", - "django-debug-toolbar", - "dj-rest-auth", - - "django-healthchecks", - - "cmarkgfm", - "bleach", - - "sentry-sdk", - - "babel", - "boto3", - "PyJWT", - "urllib3", - - "celery", - "redis", - - "httpx[http2]", - "stripe", - - "emoji", -] - - -[project.optional-dependencies] -dev = [ - "ipython", - - "pytest-django", - "pytest-cov", - "pytest-deadfixtures", - "pytest-env", - "pytest-freezegun", - "pytest-mock", - "pytest-randomly", - "pytest-repeat", - "pytest-xdist", - "respx", - - "freezegun", - "mixer", - - "black", - - "jedi", - "autoflake", - "flake8-absolute-import", - "flake8-black", - "flake8-bugbear", - "flake8-cognitive-complexity", - "flake8-django", - "flake8-eradicate", - "flake8-fixme", - "flake8-isort>=4.0.0", - "flake8-multiline-containers", - "flake8-mutable", - "flake8-pie", - "flake8-pep3101", - "flake8-print", - "flake8-printf-formatting", - "flake8-pytest", - "flake8-pytest-style", - "flake8-simplify", - "flake8-tidy-imports", - "flake8-todo", - "flake8-variables-names", - "flake8-walrus", - "flake8-use-fstring", - "flake8-pyproject", - - "mypy", - "boto3-stubs", - "django-stubs", - "djangorestframework-stubs", - "types-babel", - "types-bleach", - "types-freezegun", - "types-Markdown", - "types-retry", - "types-Pillow", - "types-simplejson", - "types-stripe", -] +version = "2023.10.20" +description = "" +authors = ["Fedor Borshev "] +readme = "README.md" + +[tool.poetry.dependencies] +python = "~3.11" +babel = "^2.12.1" +bcrypt = "^4.0.1" +bleach = "^6.0.0" +boto3 = "^1.28.48" +celery = "5.2.7" +cmarkgfm = "^2022.10.27" +django = "^4.2.5" +djangorestframework = "^3.14.0" +django-anymail = "^10.1" +django-axes = "^6.1.1" +django-behaviors = "^0.5.1" +django-cachalot = "^2.6.1" +django-cors-headers = "^4.2.0" +django-debug-toolbar = "^4.2.0" +django-environ = "^0.11.2" +django-filter = "^23.2" +django-healthchecks = "^1.5.0" +django-ipware = "^5.0.0" +django-prettyjson = "^0.4.1" +django-split-settings = "^1.2.0" +django-storages = "^1.14" +django-tree-queries = "^0.15.0" +dj-rest-auth = "^5.0.0" +drf-jwt = "^1.19.2" +drf-recaptcha = "^3.0.0" +drf-spectacular = {extras = ["sidecar"], version = "^0.26.4"} +emoji = "^2.8.0" +httpx = {extras = ["http2"], version = "^0.25.0"} +psycopg2-binary = "^2.9.7" +redis = "^5.0.0" +retry = "^0.9.2" +sentry-sdk = "^1.31.0" +shortuuid = "^1.0.11" +simplejson = "^3.19.1" +stripe = "^6.5.0" +whitenoise = "^6.5.0" +pillow = "^10.1.0" + +[tool.poetry.group.dev.dependencies] +autoflake = "^2.2.1" +black = "^23.9.1" + +flake8-absolute-import = "^1.0.0.1" +flake8-black = "^0.3.6" +flake8-bugbear = "^23.7.10" +flake8-cognitive-complexity = "^0.1.0" +flake8-django = "^1.4" +flake8-eradicate = "^1.5.0" +flake8-fixme = "^1.1.1" +flake8-isort = "^6.0.0" +flake8-multiline-containers = "^0.0.19" +flake8-mutable = "^1.2.0" +flake8-pep3101 = "^2.0.0" +flake8-pie = "^0.16.0" +flake8-print = "^5.0.0" +flake8-printf-formatting = "^1.1.2" +flake8-pyproject = "^1.2.3" +flake8-pytest = "^1.4" +flake8-pytest-style = "^1.7.2" +flake8-simplify = "^0.20.0" +flake8-tidy-imports = "^4.10.0" +flake8-todo = "^0.7" +flake8-use-fstring = "^1.4" +flake8-variables-names = "^0.0.6" +flake8-walrus = "^1.2.0" + +freezegun = "^1.2.2" +ipython = "^8.15.0" +jedi = "^0.19.0" +mixer = "^7.2.2" +mypy = "^1.6.1" +pytest-django = "^4.5.2" +pytest-cov = "^4.1.0" +pytest-deadfixtures = "^2.2.1" +pytest-env = "^1.0.1" +pytest-freezegun = "^0.4.2" +pytest-mock = "^3.11.1" +pytest-randomly = "^3.15.0" +pytest-repeat = "^0.9.1" +pytest-xdist = "^3.3.1" +requests-mock = "^1.11.0" +respx = "^0.20.2" + +boto3-stubs = "^1.28.48" +djangorestframework-stubs = "^3.14.4" +django-stubs = "^4.2.6" +types-babel = "^2.11.0.15" +types-bleach = "^6.0.0.4" +types-freezegun = "^1.1.10" +types-markdown = "^3.4.2.10" +types-pillow = "^10.0.0.3" +types-requests = "^2.31.0.2" +types-retry = "^0.9.9.4" +types-simplejson = "^3.19.0.2" +types-stripe = "^3.5.2.14" +rope = "^1.10.0" +[tool.black] +exclude = """ +/( + | migrations +)/ +""" +line_length = 160 [tool.flake8] -max-line-length = 160 -line-quotes = "\"" -ignore = [ - "B010", # Do not call setattr(x, 'attr', val), instead use normal property access: x.attr = val - "DJ01", # Avoid using null=True on string-based fields such as CharField and TextField - "DJ07", # Allow __all__ in fields for ModelForm - "DJ12", # Field ordering - "E501", # Line too long - "E265", # Block comments should have one space before the pound sign (#) and the comment itself - "F811", # Redefinition of unused name from line n - "FS003", # f-string missing prefix - "PIE783", # Warn about Celery task definitions that don't have explicit names - "PIE785", # Celery tasks can bunch up if they don't have expirations - "PIE801", # Return boolean expressions directly instead of returning True and False - "PT001", # Use @pytest.fixture() over @pytest.fixture - "SIM102", # Use a single if-statement instead of nested if-statements - "SIM113", # Use enumerate instead of manually incrementing a counter - "VNE003", # Variable names that shadow builtins are not allowed - "W503", # https://www.flake8rules.com/rules/W503.html - "E203", # whitespace before ':', disabled for black purposes https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#slices -] banned-modules = """ typing.Optional = Please use "x | None" typing.Union = Please use "x | y" @@ -143,28 +120,71 @@ banned-modules = """ typing.Dict = Please use "dict" instead of "Dict" """ exclude = [ - "static", - "migrations", "frontend", + "migrations", + "static", ".git", "__pycache__", ] - +ignore = [ + "DJ01", # avoid using null=True on string-based fields such CharField + "DJ07", # do not use __all__ with ModelForm, use fields instead + "DJ08", # model does not define __str__ method + "E501", # line too long ({} > {} characters) + "PIE783", # celery tasks should have explicit names + "PIE785", # celery tasks should have expirations + "PIE801", # prefer-simple-return: Return boolean expressions directly instead of returning `True` and `False` + "PT001", # use @pytest.fixture() over @pytest.fixture + "SIM102", # use a single if-statement instead of nested if-statements + "SIM113", # use enumerate for `{}` + "VNE003", # variable names that shadow builtins are not allowed + "W503", # line break before binary operator +] +line-quotes = "\"" [tool.isort] -profile = "google" -line_length = 160 -multi_line_output = 3 -use_parentheses = true extra_standard_library = ["pytest"] known_django = ["django", "restframework"] +line_length = 160 +multi_line_output = 3 +profile = "google" sections = ["FUTURE", "STDLIB", "THIRDPARTY", "DJANGO", "FIRSTPARTY", "LOCALFOLDER"] +use_parentheses = true - -[tool.black] - exclude = ''' - /( - | migrations - )/ - ''' - line_length = 160 +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" + +[tool.pytest.ini_options] +addopts = "--reuse-db" +DJANGO_SETTINGS_MODULE = "core.settings" +env = [ + "ATOL_WEBHOOK_SALT = SECRET-SALT", + "AWS_ACCESS_KEY_ID = zeroc00l94", + "AWS_S3_ENDPOINT_URL = https://fra1.digitaloceanspaces.com", + "AWS_S3_REGION_NAME = Ukraine", + "AWS_SECRET_ACCESS_KEY = h4xx0r", + "AWS_STORAGE_BUCKET_NAME = pwned_data", + "CELERY_ALWAYS_EAGER = on", + "CI = 1", + "DEFAULT_FILE_STORAGE = django.core.files.storage.FileSystemStorage", + "DISABLE_HOMEWORK_PERMISSIONS_CHECKING = on", + "DISABLE_NEW_ANSWER_NOTIFICATIONS = on", + "DISABLE_THROTTLING = on", + "RECAPTCHA_ENABLED = off", +] +filterwarnings = [ + "error", + "ignore:'cgi' is deprecated", + "ignore:distutils Version classes are deprecated. Use packaging.version instead.:DeprecationWarning:pytest_freezegun:17", + "ignore:pkg_resources is deprecated as an API", + "ignore:SelectableGroups dict interface is deprecated", + "ignore:unclosed file:ResourceWarning", +] +markers = [ + "freeze_time: freezing time marker (pytest-freezegun does not register it)", + "single_thread: marked tests should be ran only in single thread", + "slow: tests with inentional slow run", +] +python_files = "test*.py" +pythonpath = ". src" diff --git a/renovate.json b/renovate.json index c40f51edcda..9233d5d32d9 100644 --- a/renovate.json +++ b/renovate.json @@ -2,8 +2,8 @@ "extends": [ "config:base" ], - "enabledManagers": ["pip_requirements"], - "ignoreDeps": ["boto3", "boto3-stubs", "botocore", "botocore-stubs"], + "enabledManagers": ["poetry"], + "ignoreDeps": ["boto3", "boto3-stubs", "botocore", "botocore-stubs", "s3transfer"], "packageRules": [ { "matchUpdateTypes": ["minor", "patch", "pin", "digest"], diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 4307a5e19e2..00000000000 --- a/requirements.txt +++ /dev/null @@ -1,249 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.11 -# by the following command: -# -# pip-compile --output-file=requirements.txt pyproject.toml -# -amqp==5.1.1 - # via kombu -anyio==3.7.1 - # via httpcore -asgiref==3.7.2 - # via django -async-timeout==4.0.3 - # via redis -attrs==23.1.0 - # via - # jsonschema - # referencing -babel==2.13.0 - # via education-backend (pyproject.toml) -bcrypt==4.0.1 - # via education-backend (pyproject.toml) -billiard==3.6.4.0 - # via celery -bleach==6.1.0 - # via education-backend (pyproject.toml) -boto3==1.28.1 - # via education-backend (pyproject.toml) -botocore==1.31.1 - # via - # boto3 - # s3transfer -celery==5.2.7 - # via education-backend (pyproject.toml) -certifi==2023.7.22 - # via - # django-healthchecks - # httpcore - # httpx - # requests - # sentry-sdk -cffi==1.16.0 - # via - # cmarkgfm - # cryptography -charset-normalizer==3.3.0 - # via requests -click==8.1.7 - # via - # celery - # click-didyoumean - # click-plugins - # click-repl -click-didyoumean==0.3.0 - # via celery -click-plugins==1.1.1 - # via celery -click-repl==0.3.0 - # via celery -cmarkgfm==2022.10.27 - # via education-backend (pyproject.toml) -cryptography==41.0.4 - # via pyjwt -decorator==5.1.1 - # via retry -dj-rest-auth==4.0.1 - # via education-backend (pyproject.toml) -django==4.2.6 - # via - # dj-rest-auth - # django-anymail - # django-axes - # django-cachalot - # django-cors-headers - # django-debug-toolbar - # django-filter - # django-healthchecks - # django-prettyjson - # django-storages - # djangorestframework - # drf-jwt - # drf-recaptcha - # drf-spectacular - # drf-spectacular-sidecar - # education-backend (pyproject.toml) -django-anymail==10.1 - # via education-backend (pyproject.toml) -django-axes==6.1.1 - # via education-backend (pyproject.toml) -django-behaviors==0.5.1 - # via education-backend (pyproject.toml) -django-cachalot==2.6.1 - # via education-backend (pyproject.toml) -django-cors-headers==4.3.0 - # via education-backend (pyproject.toml) -django-debug-toolbar==4.2.0 - # via education-backend (pyproject.toml) -django-environ==0.11.2 - # via education-backend (pyproject.toml) -django-filter==23.3 - # via education-backend (pyproject.toml) -django-healthchecks==1.5.0 - # via education-backend (pyproject.toml) -django-ipware==5.0.1 - # via - # drf-recaptcha - # education-backend (pyproject.toml) -django-prettyjson==0.4.1 - # via education-backend (pyproject.toml) -django-split-settings==1.2.0 - # via education-backend (pyproject.toml) -django-storages==1.14.2 - # via education-backend (pyproject.toml) -django-tree-queries==0.15.0 - # via education-backend (pyproject.toml) -djangorestframework==3.14.0 - # via - # dj-rest-auth - # drf-jwt - # drf-recaptcha - # drf-spectacular - # education-backend (pyproject.toml) -drf-jwt==1.19.2 - # via education-backend (pyproject.toml) -drf-recaptcha==3.0.0 - # via education-backend (pyproject.toml) -drf-spectacular[sidecar]==0.26.5 - # via education-backend (pyproject.toml) -drf-spectacular-sidecar==2023.10.1 - # via drf-spectacular -emoji==2.8.0 - # via education-backend (pyproject.toml) -h11==0.14.0 - # via httpcore -h2==4.1.0 - # via httpx -hpack==4.0.0 - # via h2 -httpcore==0.18.0 - # via httpx -httpx[http2]==0.25.0 - # via education-backend (pyproject.toml) -hyperframe==6.0.1 - # via h2 -idna==3.4 - # via - # anyio - # httpx - # requests -inflection==0.5.1 - # via drf-spectacular -jmespath==1.0.1 - # via - # boto3 - # botocore -jsonschema==4.19.1 - # via drf-spectacular -jsonschema-specifications==2023.7.1 - # via jsonschema -kombu==5.3.1 - # via celery -pillow==10.1.0 - # via education-backend (pyproject.toml) -prompt-toolkit==3.0.39 - # via click-repl -psycopg2-binary==2.9.9 - # via education-backend (pyproject.toml) -py==1.11.0 - # via retry -pycparser==2.21 - # via cffi -pyjwt[crypto]==2.8.0 - # via - # drf-jwt - # education-backend (pyproject.toml) -python-dateutil==2.8.2 - # via botocore -pytz==2023.3.post1 - # via - # celery - # djangorestframework -pyyaml==6.0.1 - # via drf-spectacular -redis==5.0.1 - # via education-backend (pyproject.toml) -referencing==0.30.2 - # via - # jsonschema - # jsonschema-specifications -requests==2.31.0 - # via - # django-anymail - # django-healthchecks - # stripe -retry==0.9.2 - # via education-backend (pyproject.toml) -rpds-py==0.10.6 - # via - # jsonschema - # referencing -s3transfer==0.6.2 - # via boto3 -sentry-sdk==1.31.0 - # via education-backend (pyproject.toml) -shortuuid==1.0.11 - # via education-backend (pyproject.toml) -simplejson==3.19.2 - # via education-backend (pyproject.toml) -six==1.16.0 - # via - # bleach - # django-prettyjson - # python-dateutil -sniffio==1.3.0 - # via - # anyio - # httpcore - # httpx -sqlparse==0.4.4 - # via - # django - # django-debug-toolbar -standardjson==0.3.1 - # via django-prettyjson -stripe==6.7.0 - # via education-backend (pyproject.toml) -uritemplate==4.1.1 - # via drf-spectacular -urllib3==1.26.18 - # via - # botocore - # django-anymail - # education-backend (pyproject.toml) - # requests - # sentry-sdk -vine==5.0.0 - # via - # amqp - # celery - # kombu -wcwidth==0.2.8 - # via prompt-toolkit -webencodings==0.5.1 - # via bleach -whitenoise==6.5.0 - # via education-backend (pyproject.toml) - -# The following packages are considered to be unsafe in a requirements file: -# setuptools diff --git a/src/a12n/tests/conftest.py b/src/a12n/tests/conftest.py deleted file mode 100644 index 572e9854537..00000000000 --- a/src/a12n/tests/conftest.py +++ /dev/null @@ -1,6 +0,0 @@ -import pytest - - -@pytest.fixture(autouse=True) -def subscribe(mocker): - return mocker.patch("app.tasks.update_dashamail_subscription.delay") diff --git a/src/amocrm/client/__init__.py b/src/amocrm/client/__init__.py deleted file mode 100644 index a5b97fde744..00000000000 --- a/src/amocrm/client/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -__all__ = ["AmoCRMClient"] - -from amocrm.client.client import AmoCRMClient diff --git a/src/amocrm/dto/__init__.py b/src/amocrm/dto/__init__.py deleted file mode 100644 index aa3cb1f5fb3..00000000000 --- a/src/amocrm/dto/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -from amocrm.dto.catalogs import AmoCRMCatalogs -from amocrm.dto.customer import AmoCRMCustomer -from amocrm.dto.groups import AmoCRMGroups -from amocrm.dto.lead import AmoCRMLead -from amocrm.dto.pipelines import AmoCRMPipelines -from amocrm.dto.product import AmoCRMProduct -from amocrm.dto.transaction import AmoCRMTransaction - -__all__ = [ - "AmoCRMCustomer", - "AmoCRMProduct", - "AmoCRMGroups", - "AmoCRMLead", - "AmoCRMTransaction", - "AmoCRMPipelines", - "AmoCRMCatalogs", -] diff --git a/src/amocrm/models/__init__.py b/src/amocrm/models/__init__.py deleted file mode 100644 index cf50c78185b..00000000000 --- a/src/amocrm/models/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -__all__ = [ - "AmoCRMUser", - "AmoCRMCourse", - "AmoCRMOrderLead", - "AmoCRMOrderTransaction", - "AmoCRMProductGroup", -] - -from amocrm.models.amocrm_course import AmoCRMCourse -from amocrm.models.amocrm_order_lead import AmoCRMOrderLead -from amocrm.models.amocrm_order_transaction import AmoCRMOrderTransaction -from amocrm.models.amocrm_product_group import AmoCRMProductGroup -from amocrm.models.amocrm_user import AmoCRMUser diff --git a/src/app/admin/__init__.py b/src/app/admin/__init__.py deleted file mode 100644 index 47d8bcc0660..00000000000 --- a/src/app/admin/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from django.contrib import admin - -from app.admin.model_admin import ModelAdmin -from app.admin.model_admin import StackedInline -from app.admin.model_admin import TabularInline - -__all__ = [ - "admin", - "ModelAdmin", - "StackedInline", - "TabularInline", -] diff --git a/src/app/conf/boilerplate.py b/src/app/conf/boilerplate.py deleted file mode 100644 index 7e88e28c6fc..00000000000 --- a/src/app/conf/boilerplate.py +++ /dev/null @@ -1,10 +0,0 @@ -import os.path - -BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - -ROOT_URLCONF = "app.urls" - -# Disable built-in ./manage.py test command in favor of pytest -TEST_RUNNER = "app.test.disable_test_command_runner.DisableTestCommandRunner" - -WSGI_APPLICATION = "app.wsgi.application" diff --git a/src/app/conf/environ.py b/src/app/conf/environ.py deleted file mode 100644 index d6064799c91..00000000000 --- a/src/app/conf/environ.py +++ /dev/null @@ -1,15 +0,0 @@ -"""Read .env file""" -import os.path - -import environ # type: ignore - -env = environ.Env( - DEBUG=(bool, False), - CI=(bool, False), -) -if os.path.exists("app/.env"): - environ.Env.read_env("app/.env") # reading .env file - -__all__ = [ - "env", -] diff --git a/src/app/conf/tags.py b/src/app/conf/tags.py deleted file mode 100644 index 96476ef3be8..00000000000 --- a/src/app/conf/tags.py +++ /dev/null @@ -1,6 +0,0 @@ -TAG_PIPELINE = [ - "users.tags.AnyPurchaseTag", - "users.tags.StartedTag", - "users.tags.PurchasedTag", - "users.tags.B2BTag", -] diff --git a/src/app/fixtures/__init__.py b/src/app/fixtures/__init__.py deleted file mode 100644 index ced021bc145..00000000000 --- a/src/app/fixtures/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -from app.fixtures.api import anon -from app.fixtures.api import api -from app.fixtures.api import as_ -from app.fixtures.api import as_user -from app.fixtures.dasha_subscription_updater import _mock_subscription_updater -from app.fixtures.factory import factory -from app.fixtures.factory import mixer -from app.fixtures.send_mail import send_mail -from app.fixtures.timezone import kamchatka_timezone - -__all__ = [ - "anon", - "api", - "as_", - "as_user", - "factory", - "mixer", - "send_mail", - "kamchatka_timezone", - "_mock_subscription_updater", -] diff --git a/src/app/fixtures/send_mail.py b/src/app/fixtures/send_mail.py deleted file mode 100644 index 86725d062cd..00000000000 --- a/src/app/fixtures/send_mail.py +++ /dev/null @@ -1,6 +0,0 @@ -import pytest - - -@pytest.fixture -def send_mail(mocker): - return mocker.patch("mailing.tasks.send_mail.delay") diff --git a/src/app/integrations/dashamail/__init__.py b/src/app/integrations/dashamail/__init__.py deleted file mode 100644 index 2f5b8d11afd..00000000000 --- a/src/app/integrations/dashamail/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from app.integrations.dashamail.client import AppDashamail -from app.integrations.dashamail.exceptions import DashamailException - -__all__ = [ - "AppDashamail", - "DashamailException", -] diff --git a/src/app/tasks/__init__.py b/src/app/tasks/__init__.py deleted file mode 100644 index f9031b67ea5..00000000000 --- a/src/app/tasks/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from app.tasks.dashamail import update_dashamail_subscription -from app.tasks.tg import send_telegram_message - -__all__ = [ - "send_telegram_message", - "update_dashamail_subscription", -] diff --git a/src/app/urls/v2.py b/src/app/urls/v2.py deleted file mode 100644 index 2d856beaaba..00000000000 --- a/src/app/urls/v2.py +++ /dev/null @@ -1,28 +0,0 @@ -from drf_spectacular.views import SpectacularAPIView -from drf_spectacular.views import SpectacularSwaggerView - -from django.urls import include -from django.urls import path - -urlpatterns = [ - path("auth/", include("a12n.urls")), - path("banking/", include("banking.urls")), - path("diplomas/", include("diplomas.urls")), - path("homework/", include("homework.urls")), - path("leads/", include("magnets.urls")), - path("users/", include("users.urls")), - path("notion/", include("notion.urls")), - path("studies/", include("studying.urls")), - path("orders/", include("orders.urls")), - path("", include("products.urls")), - path("healthchecks/", include("django_healthchecks.urls")), - path( - "docs/schema/", - SpectacularAPIView.as_view(api_version="v2"), - name="schema", - ), - path( - "docs/swagger/", - SpectacularSwaggerView.as_view(url_name="schema"), - ), -] diff --git a/src/a12n/__init__.py b/src/apps/__init__.py similarity index 100% rename from src/a12n/__init__.py rename to src/apps/__init__.py diff --git a/src/a12n/migrations/__init__.py b/src/apps/a12n/__init__.py similarity index 100% rename from src/a12n/migrations/__init__.py rename to src/apps/a12n/__init__.py diff --git a/src/a12n/api/forms.py b/src/apps/a12n/api/forms.py similarity index 96% rename from src/a12n/api/forms.py rename to src/apps/a12n/api/forms.py index 0afa12d89b4..6cb0c71a3a0 100644 --- a/src/a12n/api/forms.py +++ b/src/apps/a12n/api/forms.py @@ -4,7 +4,7 @@ from django.conf import settings from django.contrib.auth.forms import PasswordResetForm as DjangoPasswordResetForm -from mailing.tasks import send_mail +from apps.mailing.tasks import send_mail class EspTemplatePasswordResetForm(DjangoPasswordResetForm): diff --git a/src/a12n/api/serializers.py b/src/apps/a12n/api/serializers.py similarity index 78% rename from src/a12n/api/serializers.py rename to src/apps/a12n/api/serializers.py index 8e934c7a896..7a20bf83044 100644 --- a/src/a12n/api/serializers.py +++ b/src/apps/a12n/api/serializers.py @@ -1,6 +1,6 @@ from dj_rest_auth.serializers import PasswordResetSerializer as DjRestAuthPasswordResetSerializer -from a12n.api.forms import EspTemplatePasswordResetForm +from apps.a12n.api.forms import EspTemplatePasswordResetForm class PasswordResetSerializer(DjRestAuthPasswordResetSerializer): diff --git a/src/a12n/api/throttling.py b/src/apps/a12n/api/throttling.py similarity index 79% rename from src/a12n/api/throttling.py rename to src/apps/a12n/api/throttling.py index 73230c58976..7105b1e2420 100644 --- a/src/a12n/api/throttling.py +++ b/src/apps/a12n/api/throttling.py @@ -1,6 +1,6 @@ from rest_framework.throttling import AnonRateThrottle -from app.throttling import ConfigurableThrottlingMixin +from core.throttling import ConfigurableThrottlingMixin class AuthAnonRateThrottle(ConfigurableThrottlingMixin, AnonRateThrottle): # type: ignore diff --git a/src/a12n/api/views.py b/src/apps/a12n/api/views.py similarity index 85% rename from src/a12n/api/views.py rename to src/apps/a12n/api/views.py index 8f63e701372..0bc6b574310 100644 --- a/src/a12n/api/views.py +++ b/src/apps/a12n/api/views.py @@ -7,14 +7,14 @@ from django.conf import settings from django.shortcuts import get_object_or_404 -from a12n.api.serializers import PasswordResetSerializer -from a12n.api.throttling import AuthAnonRateThrottle -from a12n.models import PasswordlessAuthToken -from a12n.utils import get_jwt -from app.permissions import SuperUserOnly -from app.views import AnonymousAPIView -from mailing.tasks import send_mail -from users.models import User +from apps.a12n.api.serializers import PasswordResetSerializer +from apps.a12n.api.throttling import AuthAnonRateThrottle +from apps.a12n.models import PasswordlessAuthToken +from apps.a12n.utils import get_jwt +from apps.mailing.tasks import send_mail +from apps.users.models import User +from core.permissions import SuperUserOnly +from core.views import AnonymousAPIView class ObtainJSONWebTokenView(jwt.ObtainJSONWebTokenView): diff --git a/src/a12n/apps.py b/src/apps/a12n/apps.py similarity index 56% rename from src/a12n/apps.py rename to src/apps/a12n/apps.py index 2d443b2cfb6..0f38441f9d1 100644 --- a/src/a12n/apps.py +++ b/src/apps/a12n/apps.py @@ -2,7 +2,7 @@ class A12NConfig(AppConfig): - name = "a12n" + name = "apps.a12n" def ready(self) -> None: - import a12n.signals.handlers # noqa + import apps.a12n.signals.handlers # noqa diff --git a/src/a12n/jwt.py b/src/apps/a12n/jwt.py similarity index 91% rename from src/a12n/jwt.py rename to src/apps/a12n/jwt.py index fa1c508eec8..4d36ed1c208 100644 --- a/src/a12n/jwt.py +++ b/src/apps/a12n/jwt.py @@ -1,7 +1,7 @@ import jwt from rest_framework_jwt.utils import jwt_create_payload -from users.models import User +from apps.users.models import User def payload_handler(user: User) -> dict: diff --git a/src/a12n/migrations/0001_initial.py b/src/apps/a12n/migrations/0001_initial.py similarity index 90% rename from src/a12n/migrations/0001_initial.py rename to src/apps/a12n/migrations/0001_initial.py index d18c5b413be..6f2587a9bba 100644 --- a/src/a12n/migrations/0001_initial.py +++ b/src/apps/a12n/migrations/0001_initial.py @@ -7,7 +7,7 @@ from django.db import models import django.db.models.deletion -import a12n.models +import apps.a12n.models class Migration(migrations.Migration): @@ -26,7 +26,7 @@ class Migration(migrations.Migration): ('created', models.DateTimeField(auto_now_add=True, db_index=True)), ('modified', models.DateTimeField(blank=True, db_index=True, null=True)), ('token', models.UUIDField(db_index=True, default=uuid.uuid4, unique=True)), - ('expires', models.DateTimeField(default=a12n.models.default_expiration)), + ('expires', models.DateTimeField(default=apps.a12n.models.default_expiration)), ('used', models.BooleanField(default=False)), ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], diff --git a/src/a12n/migrations/0002_PasswordlessTokensUsedDate.py b/src/apps/a12n/migrations/0002_PasswordlessTokensUsedDate.py similarity index 100% rename from src/a12n/migrations/0002_PasswordlessTokensUsedDate.py rename to src/apps/a12n/migrations/0002_PasswordlessTokensUsedDate.py diff --git a/src/amocrm/__init__.py b/src/apps/a12n/migrations/__init__.py similarity index 100% rename from src/amocrm/__init__.py rename to src/apps/a12n/migrations/__init__.py diff --git a/src/a12n/models.py b/src/apps/a12n/models.py similarity index 94% rename from src/a12n/models.py rename to src/apps/a12n/models.py index c825c60a0ab..718af3bdf11 100644 --- a/src/a12n/models.py +++ b/src/apps/a12n/models.py @@ -6,8 +6,8 @@ from django.conf import settings from django.utils import timezone -from app.models import models -from app.models import TimestampedModel +from core.models import models +from core.models import TimestampedModel def default_expiration() -> datetime: diff --git a/src/a12n/signals/handlers.py b/src/apps/a12n/signals/handlers.py similarity index 100% rename from src/a12n/signals/handlers.py rename to src/apps/a12n/signals/handlers.py diff --git a/src/a12n/urls.py b/src/apps/a12n/urls.py similarity index 69% rename from src/a12n/urls.py rename to src/apps/a12n/urls.py index 20156379121..f5a0625eaf7 100644 --- a/src/a12n/urls.py +++ b/src/apps/a12n/urls.py @@ -3,12 +3,12 @@ from django.urls import path -from a12n.api.views import ObtainJSONWebTokenViaPasswordlessToken -from a12n.api.views import ObtainJSONWebTokenViaUserId -from a12n.api.views import ObtainJSONWebTokenView -from a12n.api.views import RefreshJSONWebTokenView -from a12n.api.views import RequestPasswordLessToken -from a12n.api.views import RequestPasswordResetView +from apps.a12n.api.views import ObtainJSONWebTokenViaPasswordlessToken +from apps.a12n.api.views import ObtainJSONWebTokenViaUserId +from apps.a12n.api.views import ObtainJSONWebTokenView +from apps.a12n.api.views import RefreshJSONWebTokenView +from apps.a12n.api.views import RequestPasswordLessToken +from apps.a12n.api.views import RequestPasswordResetView urlpatterns = [ path("token/", ObtainJSONWebTokenView.as_view()), diff --git a/src/a12n/utils.py b/src/apps/a12n/utils.py similarity index 93% rename from src/a12n/utils.py rename to src/apps/a12n/utils.py index 939d742b7e2..f005cf6ca1c 100644 --- a/src/a12n/utils.py +++ b/src/apps/a12n/utils.py @@ -1,7 +1,7 @@ import jwt from rest_framework_jwt.settings import api_settings -from users.models import User +from apps.users.models import User def get_jwt(user: User) -> str: diff --git a/src/amocrm/migrations/__init__.py b/src/apps/amocrm/__init__.py similarity index 100% rename from src/amocrm/migrations/__init__.py rename to src/apps/amocrm/__init__.py diff --git a/src/amocrm/apps.py b/src/apps/amocrm/apps.py similarity index 83% rename from src/amocrm/apps.py rename to src/apps/amocrm/apps.py index 01277811c98..cd2c65da753 100644 --- a/src/amocrm/apps.py +++ b/src/apps/amocrm/apps.py @@ -3,4 +3,4 @@ class AmocrmConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" - name = "amocrm" + name = "apps.amocrm" diff --git a/src/apps/amocrm/client/__init__.py b/src/apps/amocrm/client/__init__.py new file mode 100644 index 00000000000..4441973401c --- /dev/null +++ b/src/apps/amocrm/client/__init__.py @@ -0,0 +1,3 @@ +__all__ = ["AmoCRMClient"] + +from apps.amocrm.client.client import AmoCRMClient diff --git a/src/amocrm/client/client.py b/src/apps/amocrm/client/client.py similarity index 89% rename from src/amocrm/client/client.py rename to src/apps/amocrm/client/client.py index ee1b8bb86f7..288be9593da 100644 --- a/src/amocrm/client/client.py +++ b/src/apps/amocrm/client/client.py @@ -1,4 +1,4 @@ -from amocrm.client import http +from apps.amocrm.client import http class AmoCRMClient: diff --git a/src/amocrm/client/http.py b/src/apps/amocrm/client/http.py similarity index 94% rename from src/amocrm/client/http.py rename to src/apps/amocrm/client/http.py index 3889a8a0bf1..e653d3c6d1c 100644 --- a/src/amocrm/client/http.py +++ b/src/apps/amocrm/client/http.py @@ -8,8 +8,8 @@ from django.conf import settings from django.core.cache import cache -from amocrm.exceptions import AmoCRMException -from amocrm.services.access_token_getter import AmoCRMTokenGetter +from apps.amocrm.exceptions import AmoCRMException +from apps.amocrm.services.access_token_getter import AmoCRMTokenGetter class AmoCRMClientException(AmoCRMException): @@ -53,7 +53,7 @@ def get_validated_response(response: Response, url: str, expected_status_codes: expected_status_codes = expected_status_codes or [200] if response.status_code not in expected_status_codes: - raise AmoCRMClientException(f"Non-ok HTTP response from amocrm: {response.status_code}\nResponse data: {response_json}") + raise AmoCRMClientException(f"Non-ok HTTP response from apps.amocrm: {response.status_code}\nResponse data: {response_json}") errors = response_json.get("_embedded", {}).get("errors") if isinstance(response_json, dict) else None if errors: diff --git a/src/apps/amocrm/dto/__init__.py b/src/apps/amocrm/dto/__init__.py new file mode 100644 index 00000000000..09ac9dba8b0 --- /dev/null +++ b/src/apps/amocrm/dto/__init__.py @@ -0,0 +1,17 @@ +from apps.amocrm.dto.catalogs import AmoCRMCatalogs +from apps.amocrm.dto.customer import AmoCRMCustomer +from apps.amocrm.dto.groups import AmoCRMGroups +from apps.amocrm.dto.lead import AmoCRMLead +from apps.amocrm.dto.pipelines import AmoCRMPipelines +from apps.amocrm.dto.product import AmoCRMProduct +from apps.amocrm.dto.transaction import AmoCRMTransaction + +__all__ = [ + "AmoCRMCustomer", + "AmoCRMProduct", + "AmoCRMGroups", + "AmoCRMLead", + "AmoCRMTransaction", + "AmoCRMPipelines", + "AmoCRMCatalogs", +] diff --git a/src/amocrm/dto/catalogs.py b/src/apps/amocrm/dto/catalogs.py similarity index 95% rename from src/amocrm/dto/catalogs.py rename to src/apps/amocrm/dto/catalogs.py index aeae9018bed..c0165613af2 100644 --- a/src/amocrm/dto/catalogs.py +++ b/src/apps/amocrm/dto/catalogs.py @@ -1,6 +1,6 @@ from typing import TypedDict -from amocrm.client import http +from apps.amocrm.client import http class CatalogField(TypedDict): @@ -18,7 +18,7 @@ class AmoCRMCatalogs: # NOQA: PIE798 @classmethod def get(cls) -> list[Catalog]: """ - Returns all catalogs from amocrm + Returns all catalogs from apps.amocrm https://www.amocrm.ru/developers/content/crm_platform/catalogs-api#lists-list """ response = http.get(url="/api/v4/catalogs", params={"limit": 250}, cached=True) diff --git a/src/amocrm/dto/customer.py b/src/apps/amocrm/dto/customer.py similarity index 96% rename from src/amocrm/dto/customer.py rename to src/apps/amocrm/dto/customer.py index 5bb78ad1767..b0141c379c8 100644 --- a/src/amocrm/dto/customer.py +++ b/src/apps/amocrm/dto/customer.py @@ -1,7 +1,7 @@ from dataclasses import dataclass -from amocrm.client import http -from users.models import User +from apps.amocrm.client import http +from apps.users.models import User @dataclass @@ -97,7 +97,7 @@ def _get_user_as_customer(self) -> dict: } def _get_user_as_contact(self) -> dict: - from amocrm.ids import contact_field_id + from apps.amocrm.ids import contact_field_id return { "name": str(self.user), diff --git a/src/amocrm/dto/groups.py b/src/apps/amocrm/dto/groups.py similarity index 87% rename from src/amocrm/dto/groups.py rename to src/apps/amocrm/dto/groups.py index 305d3941398..0041d216b67 100644 --- a/src/amocrm/dto/groups.py +++ b/src/apps/amocrm/dto/groups.py @@ -1,8 +1,8 @@ from dataclasses import dataclass from typing import Iterable -from amocrm.client import http -from products.models import Group +from apps.amocrm.client import http +from apps.products.models import Group @dataclass @@ -19,8 +19,8 @@ def push(self) -> list[tuple[str, int]]: Updates product catalog field returns list of pairs like [(group_slug, amocrm_id), ...] """ - from amocrm.ids import product_field_id - from amocrm.ids import products_catalog_id + from apps.amocrm.ids import product_field_id + from apps.amocrm.ids import products_catalog_id groups_as_product_fields = [self._get_group_as_product_field(group=group) for group in self.groups] response = http.patch( diff --git a/src/amocrm/dto/lead.py b/src/apps/amocrm/dto/lead.py similarity index 89% rename from src/amocrm/dto/lead.py rename to src/apps/amocrm/dto/lead.py index 48b47ebf947..6ec72aeabe8 100644 --- a/src/amocrm/dto/lead.py +++ b/src/apps/amocrm/dto/lead.py @@ -1,11 +1,11 @@ from dataclasses import dataclass from typing import TYPE_CHECKING -from amocrm.client import http -from orders.models import Order +from apps.amocrm.client import http +from apps.orders.models import Order if TYPE_CHECKING: - from amocrm.ids import STATUSES_NAMES + from apps.amocrm.ids import STATUSES_NAMES @dataclass @@ -25,7 +25,7 @@ def update(self, status: "STATUSES_NAMES | None" = None) -> None: https://www.amocrm.ru/developers/content/crm_platform/leads-api#leads-edit """ - from amocrm.ids import b2c_pipeline_status_id + from apps.amocrm.ids import b2c_pipeline_status_id data = self._get_order_as_lead() data.update({"id": self.order.amocrm_lead.amocrm_id}) # type: ignore @@ -42,7 +42,7 @@ def _create_lead(self) -> int: Create lead and returns amocrm_id https://www.amocrm.ru/developers/content/crm_platform/leads-api#leads-complex-add """ - from amocrm.ids import b2c_pipeline_status_id + from apps.amocrm.ids import b2c_pipeline_status_id data = self._get_order_as_lead() data.update( @@ -74,7 +74,7 @@ def _link_course_to_lead(self, lead_id: int, course_id: int) -> None: Link given customer to given contact https://www.amocrm.ru/developers/content/crm_platform/entity-links-api#links-link """ - from amocrm.ids import products_catalog_id + from apps.amocrm.ids import products_catalog_id http.post( url=f"/api/v4/leads/{lead_id}/link", @@ -91,7 +91,7 @@ def _link_course_to_lead(self, lead_id: int, course_id: int) -> None: ) def _get_order_as_lead(self) -> dict: - from amocrm.ids import b2c_pipeline_id + from apps.amocrm.ids import b2c_pipeline_id return { "pipeline_id": b2c_pipeline_id(), diff --git a/src/amocrm/dto/pipelines.py b/src/apps/amocrm/dto/pipelines.py similarity index 96% rename from src/amocrm/dto/pipelines.py rename to src/apps/amocrm/dto/pipelines.py index fa264c729d3..45b6e81a013 100644 --- a/src/amocrm/dto/pipelines.py +++ b/src/apps/amocrm/dto/pipelines.py @@ -1,6 +1,6 @@ from typing import TypedDict -from amocrm.client import http +from apps.amocrm.client import http class PipelineStatus(TypedDict): diff --git a/src/amocrm/dto/product.py b/src/apps/amocrm/dto/product.py similarity index 92% rename from src/amocrm/dto/product.py rename to src/apps/amocrm/dto/product.py index 89c89356d8e..e4f8790f1b2 100644 --- a/src/amocrm/dto/product.py +++ b/src/apps/amocrm/dto/product.py @@ -1,8 +1,8 @@ from dataclasses import dataclass from typing import Annotated, NotRequired, TypedDict -from amocrm.client import http -from products.models import Course +from apps.amocrm.client import http +from apps.products.models import Course class ProductFieldValue(TypedDict): @@ -44,7 +44,7 @@ def update(self) -> None: ) def _get_course_as_product(self) -> Product: - from amocrm.ids import product_field_id + from apps.amocrm.ids import product_field_id price = ProductField( field_id=product_field_id(field_code="PRICE"), @@ -74,6 +74,6 @@ def _get_course_as_product(self) -> Product: @staticmethod def _get_catalog_id() -> int: - from amocrm.ids import products_catalog_id + from apps.amocrm.ids import products_catalog_id return products_catalog_id() diff --git a/src/amocrm/dto/transaction.py b/src/apps/amocrm/dto/transaction.py similarity index 92% rename from src/amocrm/dto/transaction.py rename to src/apps/amocrm/dto/transaction.py index bde536e698e..0a3786cf66c 100644 --- a/src/amocrm/dto/transaction.py +++ b/src/apps/amocrm/dto/transaction.py @@ -1,7 +1,7 @@ from dataclasses import dataclass -from amocrm.client import http -from orders.models import Order +from apps.amocrm.client import http +from apps.orders.models import Order @dataclass @@ -13,7 +13,7 @@ def create(self) -> int: Create transaction for given order https://www.amocrm.ru/support/customers/create_purchase """ - from amocrm.ids import products_catalog_id + from apps.amocrm.ids import products_catalog_id response = http.post( url=f"/api/v4/customers/{self.order.user.amocrm_user.customer_id}/transactions", diff --git a/src/amocrm/exceptions.py b/src/apps/amocrm/exceptions.py similarity index 89% rename from src/amocrm/exceptions.py rename to src/apps/amocrm/exceptions.py index 87fb0e3d38f..0cb8c47bfea 100644 --- a/src/amocrm/exceptions.py +++ b/src/apps/amocrm/exceptions.py @@ -1,4 +1,4 @@ -from app.exceptions import AppServiceException +from core.exceptions import AppServiceException class AmoCRMException(Exception): diff --git a/src/amocrm/ids.py b/src/apps/amocrm/ids.py similarity index 92% rename from src/amocrm/ids.py rename to src/apps/amocrm/ids.py index 7ab613cf0c9..0345f10ec55 100644 --- a/src/amocrm/ids.py +++ b/src/apps/amocrm/ids.py @@ -2,10 +2,10 @@ from django.conf import settings -from amocrm.dto import AmoCRMCatalogs -from amocrm.dto import AmoCRMPipelines -from amocrm.dto.pipelines import Pipeline -from amocrm.exceptions import AmoCRMCacheException +from apps.amocrm.dto import AmoCRMCatalogs +from apps.amocrm.dto import AmoCRMPipelines +from apps.amocrm.dto.pipelines import Pipeline +from apps.amocrm.exceptions import AmoCRMCacheException STATUSES_NAMES = Literal["unsorted", "first_contact", "purchased", "closed"] STATUSES_NAMES_TRANSLATE = { diff --git a/src/amocrm/migrations/0001_AddAmoCRMUser.py b/src/apps/amocrm/migrations/0001_AddAmoCRMUser.py similarity index 100% rename from src/amocrm/migrations/0001_AddAmoCRMUser.py rename to src/apps/amocrm/migrations/0001_AddAmoCRMUser.py diff --git a/src/amocrm/migrations/0002_AddAmoCRMGroup_and_Course.py b/src/apps/amocrm/migrations/0002_AddAmoCRMGroup_and_Course.py similarity index 100% rename from src/amocrm/migrations/0002_AddAmoCRMGroup_and_Course.py rename to src/apps/amocrm/migrations/0002_AddAmoCRMGroup_and_Course.py diff --git a/src/amocrm/migrations/0003_Add_AmoCRMUserContact.py b/src/apps/amocrm/migrations/0003_Add_AmoCRMUserContact.py similarity index 100% rename from src/amocrm/migrations/0003_Add_AmoCRMUserContact.py rename to src/apps/amocrm/migrations/0003_Add_AmoCRMUserContact.py diff --git a/src/amocrm/migrations/0004_Add_AmoCRM_leads_and_transactions.py b/src/apps/amocrm/migrations/0004_Add_AmoCRM_leads_and_transactions.py similarity index 100% rename from src/amocrm/migrations/0004_Add_AmoCRM_leads_and_transactions.py rename to src/apps/amocrm/migrations/0004_Add_AmoCRM_leads_and_transactions.py diff --git a/src/amocrm/migrations/0005_Add_lead_and_transaction_to_Order.py b/src/apps/amocrm/migrations/0005_Add_lead_and_transaction_to_Order.py similarity index 100% rename from src/amocrm/migrations/0005_Add_lead_and_transaction_to_Order.py rename to src/apps/amocrm/migrations/0005_Add_lead_and_transaction_to_Order.py diff --git a/src/amocrm/migrations/0006_Drop_o2o_properties_from_amocrm_lead_and_transaction.py b/src/apps/amocrm/migrations/0006_Drop_o2o_properties_from_amocrm_lead_and_transaction.py similarity index 100% rename from src/amocrm/migrations/0006_Drop_o2o_properties_from_amocrm_lead_and_transaction.py rename to src/apps/amocrm/migrations/0006_Drop_o2o_properties_from_amocrm_lead_and_transaction.py diff --git a/src/amocrm/migrations/0007_Move_contact_id_to_AmoCRMUser.py b/src/apps/amocrm/migrations/0007_Move_contact_id_to_AmoCRMUser.py similarity index 100% rename from src/amocrm/migrations/0007_Move_contact_id_to_AmoCRMUser.py rename to src/apps/amocrm/migrations/0007_Move_contact_id_to_AmoCRMUser.py diff --git a/src/amocrm/migrations/0008_Delete_separate_AmoCRMUserContact.py b/src/apps/amocrm/migrations/0008_Delete_separate_AmoCRMUserContact.py similarity index 100% rename from src/amocrm/migrations/0008_Delete_separate_AmoCRMUserContact.py rename to src/apps/amocrm/migrations/0008_Delete_separate_AmoCRMUserContact.py diff --git a/src/amocrm/services/__init__.py b/src/apps/amocrm/migrations/__init__.py similarity index 100% rename from src/amocrm/services/__init__.py rename to src/apps/amocrm/migrations/__init__.py diff --git a/src/apps/amocrm/models/__init__.py b/src/apps/amocrm/models/__init__.py new file mode 100644 index 00000000000..42880483771 --- /dev/null +++ b/src/apps/amocrm/models/__init__.py @@ -0,0 +1,13 @@ +__all__ = [ + "AmoCRMUser", + "AmoCRMCourse", + "AmoCRMOrderLead", + "AmoCRMOrderTransaction", + "AmoCRMProductGroup", +] + +from apps.amocrm.models.amocrm_course import AmoCRMCourse +from apps.amocrm.models.amocrm_order_lead import AmoCRMOrderLead +from apps.amocrm.models.amocrm_order_transaction import AmoCRMOrderTransaction +from apps.amocrm.models.amocrm_product_group import AmoCRMProductGroup +from apps.amocrm.models.amocrm_user import AmoCRMUser diff --git a/src/amocrm/models/amocrm_course.py b/src/apps/amocrm/models/amocrm_course.py similarity index 89% rename from src/amocrm/models/amocrm_course.py rename to src/apps/amocrm/models/amocrm_course.py index a11e11a1566..13897af16b2 100644 --- a/src/amocrm/models/amocrm_course.py +++ b/src/apps/amocrm/models/amocrm_course.py @@ -1,6 +1,6 @@ from django.db import models -from app.models import TimestampedModel +from core.models import TimestampedModel class AmoCRMCourse(TimestampedModel): diff --git a/src/amocrm/models/amocrm_order_lead.py b/src/apps/amocrm/models/amocrm_order_lead.py similarity index 84% rename from src/amocrm/models/amocrm_order_lead.py rename to src/apps/amocrm/models/amocrm_order_lead.py index 4d62601f5c8..bb00fdf2184 100644 --- a/src/amocrm/models/amocrm_order_lead.py +++ b/src/apps/amocrm/models/amocrm_order_lead.py @@ -1,6 +1,6 @@ from django.db import models -from app.models import TimestampedModel +from core.models import TimestampedModel class AmoCRMOrderLead(TimestampedModel): diff --git a/src/amocrm/models/amocrm_order_transaction.py b/src/apps/amocrm/models/amocrm_order_transaction.py similarity index 85% rename from src/amocrm/models/amocrm_order_transaction.py rename to src/apps/amocrm/models/amocrm_order_transaction.py index 4bf894439c9..6ff2f2f96ed 100644 --- a/src/amocrm/models/amocrm_order_transaction.py +++ b/src/apps/amocrm/models/amocrm_order_transaction.py @@ -1,6 +1,6 @@ from django.db import models -from app.models import TimestampedModel +from core.models import TimestampedModel class AmoCRMOrderTransaction(TimestampedModel): diff --git a/src/amocrm/models/amocrm_product_group.py b/src/apps/amocrm/models/amocrm_product_group.py similarity index 90% rename from src/amocrm/models/amocrm_product_group.py rename to src/apps/amocrm/models/amocrm_product_group.py index 26fe322af4a..8542c61f520 100644 --- a/src/amocrm/models/amocrm_product_group.py +++ b/src/apps/amocrm/models/amocrm_product_group.py @@ -1,6 +1,6 @@ from django.db import models -from app.models import TimestampedModel +from core.models import TimestampedModel class AmoCRMProductGroup(TimestampedModel): diff --git a/src/amocrm/models/amocrm_user.py b/src/apps/amocrm/models/amocrm_user.py similarity index 90% rename from src/amocrm/models/amocrm_user.py rename to src/apps/amocrm/models/amocrm_user.py index bc9aab52d5d..64549ae42e5 100644 --- a/src/amocrm/models/amocrm_user.py +++ b/src/apps/amocrm/models/amocrm_user.py @@ -1,6 +1,6 @@ from django.db import models -from app.models import TimestampedModel +from core.models import TimestampedModel class AmoCRMUser(TimestampedModel): diff --git a/src/amocrm/tests/__init__.py b/src/apps/amocrm/services/__init__.py similarity index 100% rename from src/amocrm/tests/__init__.py rename to src/apps/amocrm/services/__init__.py diff --git a/src/amocrm/services/access_token_getter.py b/src/apps/amocrm/services/access_token_getter.py similarity index 96% rename from src/amocrm/services/access_token_getter.py rename to src/apps/amocrm/services/access_token_getter.py index ee3363045c5..afaa9464002 100644 --- a/src/amocrm/services/access_token_getter.py +++ b/src/apps/amocrm/services/access_token_getter.py @@ -6,8 +6,8 @@ from django.conf import settings from django.core.cache import cache -from amocrm.exceptions import AmoCRMServiceException -from app.services import BaseService +from apps.amocrm.exceptions import AmoCRMServiceException +from core.services import BaseService class AmoCRMTokenGetterException(AmoCRMServiceException): diff --git a/src/amocrm/services/course_pusher.py b/src/apps/amocrm/services/course_pusher.py similarity index 80% rename from src/amocrm/services/course_pusher.py rename to src/apps/amocrm/services/course_pusher.py index 50c3421eb5c..c363934e3ea 100644 --- a/src/amocrm/services/course_pusher.py +++ b/src/apps/amocrm/services/course_pusher.py @@ -1,9 +1,9 @@ from dataclasses import dataclass -from amocrm.dto import AmoCRMProduct -from amocrm.models import AmoCRMCourse -from app.services import BaseService -from products.models import Course +from apps.amocrm.dto import AmoCRMProduct +from apps.amocrm.models import AmoCRMCourse +from apps.products.models import Course +from core.services import BaseService @dataclass diff --git a/src/amocrm/services/group_pusher.py b/src/apps/amocrm/services/group_pusher.py similarity index 84% rename from src/amocrm/services/group_pusher.py rename to src/apps/amocrm/services/group_pusher.py index e016a75ff9d..2c9eee70b32 100644 --- a/src/amocrm/services/group_pusher.py +++ b/src/apps/amocrm/services/group_pusher.py @@ -1,7 +1,7 @@ -from amocrm.dto import AmoCRMGroups -from amocrm.models import AmoCRMProductGroup -from app.services import BaseService -from products.models import Group +from apps.amocrm.dto import AmoCRMGroups +from apps.amocrm.models import AmoCRMProductGroup +from apps.products.models import Group +from core.services import BaseService class AmoCRMGroupsPusher(BaseService): diff --git a/src/amocrm/services/orders/order_pusher.py b/src/apps/amocrm/services/orders/order_pusher.py similarity index 90% rename from src/amocrm/services/orders/order_pusher.py rename to src/apps/amocrm/services/orders/order_pusher.py index ff8f6a30ba1..1d879aa80d2 100644 --- a/src/amocrm/services/orders/order_pusher.py +++ b/src/apps/amocrm/services/orders/order_pusher.py @@ -1,12 +1,12 @@ from dataclasses import dataclass -from amocrm.dto import AmoCRMLead -from amocrm.dto import AmoCRMTransaction -from amocrm.exceptions import AmoCRMServiceException -from amocrm.models import AmoCRMOrderLead -from amocrm.models import AmoCRMOrderTransaction -from app.services import BaseService -from orders.models import Order +from apps.amocrm.dto import AmoCRMLead +from apps.amocrm.dto import AmoCRMTransaction +from apps.amocrm.exceptions import AmoCRMServiceException +from apps.amocrm.models import AmoCRMOrderLead +from apps.amocrm.models import AmoCRMOrderTransaction +from apps.orders.models import Order +from core.services import BaseService class AmoCRMOrderPusherException(AmoCRMServiceException): diff --git a/src/amocrm/services/orders/order_returner.py b/src/apps/amocrm/services/orders/order_returner.py similarity index 75% rename from src/amocrm/services/orders/order_returner.py rename to src/apps/amocrm/services/orders/order_returner.py index 52e5c21e8b3..ca01103c9a3 100644 --- a/src/amocrm/services/orders/order_returner.py +++ b/src/apps/amocrm/services/orders/order_returner.py @@ -1,9 +1,9 @@ from dataclasses import dataclass -from amocrm.dto import AmoCRMLead -from amocrm.dto import AmoCRMTransaction -from app.services import BaseService -from orders.models import Order +from apps.amocrm.dto import AmoCRMLead +from apps.amocrm.dto import AmoCRMTransaction +from apps.orders.models import Order +from core.services import BaseService @dataclass diff --git a/src/amocrm/services/user_pusher.py b/src/apps/amocrm/services/user_pusher.py similarity index 80% rename from src/amocrm/services/user_pusher.py rename to src/apps/amocrm/services/user_pusher.py index fa4ffca3d63..f19330cdfb6 100644 --- a/src/amocrm/services/user_pusher.py +++ b/src/apps/amocrm/services/user_pusher.py @@ -1,9 +1,9 @@ from dataclasses import dataclass -from amocrm.dto import AmoCRMCustomer -from amocrm.models import AmoCRMUser -from app.services import BaseService -from users.models import User +from apps.amocrm.dto import AmoCRMCustomer +from apps.amocrm.models import AmoCRMUser +from apps.users.models import User +from core.services import BaseService @dataclass diff --git a/src/amocrm/tasks.py b/src/apps/amocrm/tasks.py similarity index 77% rename from src/amocrm/tasks.py rename to src/apps/amocrm/tasks.py index 7446bfcd91d..b98854b49af 100644 --- a/src/amocrm/tasks.py +++ b/src/apps/amocrm/tasks.py @@ -4,15 +4,15 @@ from django.apps import apps from django.conf import settings -from amocrm.client import AmoCRMClient -from amocrm.client.http import AmoCRMClientException -from amocrm.services.access_token_getter import AmoCRMTokenGetterException -from amocrm.services.course_pusher import AmoCRMCoursePusher -from amocrm.services.group_pusher import AmoCRMGroupsPusher -from amocrm.services.orders.order_pusher import AmoCRMOrderPusher -from amocrm.services.orders.order_returner import AmoCRMOrderReturner -from amocrm.services.user_pusher import AmoCRMUserPusher -from app.celery import celery +from apps.amocrm.client import AmoCRMClient +from apps.amocrm.client.http import AmoCRMClientException +from apps.amocrm.services.access_token_getter import AmoCRMTokenGetterException +from apps.amocrm.services.course_pusher import AmoCRMCoursePusher +from apps.amocrm.services.group_pusher import AmoCRMGroupsPusher +from apps.amocrm.services.orders.order_pusher import AmoCRMOrderPusher +from apps.amocrm.services.orders.order_returner import AmoCRMOrderReturner +from apps.amocrm.services.user_pusher import AmoCRMUserPusher +from core.celery import celery __all__ = [ "amocrm_enabled", diff --git a/src/amocrm/tests/http/__init__.py b/src/apps/banking/__init__.py similarity index 100% rename from src/amocrm/tests/http/__init__.py rename to src/apps/banking/__init__.py diff --git a/src/banking/api/views.py b/src/apps/banking/api/views.py similarity index 91% rename from src/banking/api/views.py rename to src/apps/banking/api/views.py index a8d25ee3417..ac7ed4dac10 100644 --- a/src/banking/api/views.py +++ b/src/apps/banking/api/views.py @@ -6,8 +6,8 @@ from django.http import HttpResponse -from banking.models import Receipt -from orders.models import Order +from apps.banking.models import Receipt +from apps.orders.models import Order class AtolWebhookView(APIView): diff --git a/src/banking/apps.py b/src/apps/banking/apps.py similarity index 72% rename from src/banking/apps.py rename to src/apps/banking/apps.py index cae8102bc57..e9daa700ef8 100644 --- a/src/banking/apps.py +++ b/src/apps/banking/apps.py @@ -2,4 +2,4 @@ class BankingConfig(AppConfig): - name = "banking" + name = "apps.banking" diff --git a/src/apps/banking/atol/__init__.py b/src/apps/banking/atol/__init__.py new file mode 100644 index 00000000000..de0b6836393 --- /dev/null +++ b/src/apps/banking/atol/__init__.py @@ -0,0 +1,5 @@ +from apps.banking.atol.client import AtolClient + +__all__ = [ + "AtolClient", +] diff --git a/src/banking/atol/auth.py b/src/apps/banking/atol/auth.py similarity index 93% rename from src/banking/atol/auth.py rename to src/apps/banking/atol/auth.py index 0d52dd465b4..c0fe3e412de 100644 --- a/src/banking/atol/auth.py +++ b/src/apps/banking/atol/auth.py @@ -5,7 +5,7 @@ from django.conf import settings from django.core.cache import cache -from banking.atol.exceptions import AtolAuthError +from apps.banking.atol.exceptions import AtolAuthError def get_atol_token() -> str: diff --git a/src/banking/atol/client.py b/src/apps/banking/atol/client.py similarity index 94% rename from src/banking/atol/client.py rename to src/apps/banking/atol/client.py index 84c30394115..be932d60941 100644 --- a/src/banking/atol/client.py +++ b/src/apps/banking/atol/client.py @@ -5,10 +5,10 @@ from django.conf import settings -from app.services import BaseService -from banking.atol import exceptions -from banking.atol.auth import get_atol_token -from orders.models import Order +from apps.banking.atol import exceptions +from apps.banking.atol.auth import get_atol_token +from apps.orders.models import Order +from core.services import BaseService BASE_URL = "https://online.atol.ru/possystem/v4/" diff --git a/src/banking/atol/exceptions.py b/src/apps/banking/atol/exceptions.py similarity index 100% rename from src/banking/atol/exceptions.py rename to src/apps/banking/atol/exceptions.py diff --git a/src/banking/base.py b/src/apps/banking/base.py similarity index 93% rename from src/banking/base.py rename to src/apps/banking/base.py index d9cbdbd5392..8ae1b82acf9 100644 --- a/src/banking/base.py +++ b/src/apps/banking/base.py @@ -11,8 +11,8 @@ if TYPE_CHECKING: from django_stubs_ext import StrPromise - from orders.models import Order - from users.models import User + from apps.orders.models import Order + from apps.users.models import User class Bank(metaclass=ABCMeta): @@ -57,7 +57,7 @@ def fail_url(self) -> str: @property def price(self) -> int | str: - from banking import price_calculator + from apps.banking import price_calculator price = price_calculator.to_bank(bank=self.__class__, price=self.order.price) return int(price * 100) diff --git a/src/banking/management/commands/test_atol.py b/src/apps/banking/management/commands/test_atol.py similarity index 70% rename from src/banking/management/commands/test_atol.py rename to src/apps/banking/management/commands/test_atol.py index 03f58bbc32b..527f9f2682a 100644 --- a/src/banking/management/commands/test_atol.py +++ b/src/apps/banking/management/commands/test_atol.py @@ -1,7 +1,7 @@ from django.core.management.base import BaseCommand -from banking.atol.client import AtolClient -from orders.models import Order +from apps.banking.atol.client import AtolClient +from apps.orders.models import Order class Command(BaseCommand): diff --git a/src/banking/migrations/0001_initial.py b/src/apps/banking/migrations/0001_initial.py similarity index 100% rename from src/banking/migrations/0001_initial.py rename to src/apps/banking/migrations/0001_initial.py diff --git a/src/amocrm/tests/ids/__init__.py b/src/apps/banking/migrations/__init__.py similarity index 100% rename from src/amocrm/tests/ids/__init__.py rename to src/apps/banking/migrations/__init__.py diff --git a/src/banking/models.py b/src/apps/banking/models.py similarity index 88% rename from src/banking/models.py rename to src/apps/banking/models.py index 02b9d45daaf..4941ac8f0e9 100644 --- a/src/banking/models.py +++ b/src/apps/banking/models.py @@ -1,8 +1,8 @@ from django.db.models import TextChoices from django.utils.translation import gettext_lazy as _ -from app.models import models -from app.models import TimestampedModel +from core.models import models +from core.models import TimestampedModel class Receipt(TimestampedModel): diff --git a/src/banking/price_calculator.py b/src/apps/banking/price_calculator.py similarity index 91% rename from src/banking/price_calculator.py rename to src/apps/banking/price_calculator.py index 3ae7a011bca..f9508fdc67e 100644 --- a/src/banking/price_calculator.py +++ b/src/apps/banking/price_calculator.py @@ -1,7 +1,7 @@ from decimal import Decimal from typing import Type -from banking.base import Bank +from apps.banking.base import Bank def to_bank(bank: Type[Bank], price: Decimal) -> Decimal: diff --git a/src/banking/selector.py b/src/apps/banking/selector.py similarity index 70% rename from src/banking/selector.py rename to src/apps/banking/selector.py index 2197efe0b8b..600242651d3 100644 --- a/src/banking/selector.py +++ b/src/apps/banking/selector.py @@ -1,11 +1,11 @@ from typing import Type -from banking.base import Bank -from banking.zero_price_bank import ZeroPriceBank -from stripebank.bank import StripeBank -from tinkoff.bank import TinkoffBank -from tinkoff.credit import TinkoffCredit -from tinkoff.dolyame import Dolyame +from apps.banking.base import Bank +from apps.banking.zero_price_bank import ZeroPriceBank +from apps.stripebank.bank import StripeBank +from apps.tinkoff.bank import TinkoffBank +from apps.tinkoff.credit import TinkoffCredit +from apps.tinkoff.dolyame import Dolyame BANKS: dict[str, Type[Bank]] = { "tinkoff_bank": TinkoffBank, diff --git a/src/banking/urls.py b/src/apps/banking/urls.py similarity index 60% rename from src/banking/urls.py rename to src/apps/banking/urls.py index 89179d5669c..e726c32f5b8 100644 --- a/src/banking/urls.py +++ b/src/apps/banking/urls.py @@ -1,11 +1,11 @@ from django.conf import settings from django.urls import path -from banking.api.views import AtolWebhookView -from stripebank.api.views import StripeWebhookView -from tinkoff.api.views import DolyameNotificationsView -from tinkoff.api.views import TinkoffCreditNotificationsView -from tinkoff.api.views import TinkoffPaymentNotificationsView +from apps.banking.api.views import AtolWebhookView +from apps.stripebank.api.views import StripeWebhookView +from apps.tinkoff.api.views import DolyameNotificationsView +from apps.tinkoff.api.views import TinkoffCreditNotificationsView +from apps.tinkoff.api.views import TinkoffPaymentNotificationsView urlpatterns = [ path("tinkoff-notifications/", TinkoffPaymentNotificationsView.as_view()), diff --git a/src/banking/zero_price_bank.py b/src/apps/banking/zero_price_bank.py similarity index 94% rename from src/banking/zero_price_bank.py rename to src/apps/banking/zero_price_bank.py index d6c918cdf3c..43507729646 100644 --- a/src/banking/zero_price_bank.py +++ b/src/apps/banking/zero_price_bank.py @@ -5,10 +5,10 @@ from django.utils.translation import gettext_lazy as _ -from banking.base import Bank +from apps.banking.base import Bank if TYPE_CHECKING: - from orders.models import Order + from apps.orders.models import Order class ZeroPriceBank(Bank): diff --git a/src/amocrm/tests/services/__init__.py b/src/apps/chains/__init__.py similarity index 100% rename from src/amocrm/tests/services/__init__.py rename to src/apps/chains/__init__.py diff --git a/src/apps/chains/admin/__init__.py b/src/apps/chains/admin/__init__.py new file mode 100644 index 00000000000..47adeb934ce --- /dev/null +++ b/src/apps/chains/admin/__init__.py @@ -0,0 +1,7 @@ +from apps.chains.admin.chain import ChainAdmin +from apps.chains.admin.message import MessageAdmin + +__all__ = [ + "ChainAdmin", + "MessageAdmin", +] diff --git a/src/chains/admin/chain.py b/src/apps/chains/admin/chain.py similarity index 82% rename from src/chains/admin/chain.py rename to src/apps/chains/admin/chain.py index 28c16562607..d2d3f22a444 100644 --- a/src/chains/admin/chain.py +++ b/src/apps/chains/admin/chain.py @@ -3,11 +3,11 @@ from django.db.models import QuerySet from django.utils.translation import gettext_lazy as _ -from app.admin import admin -from app.admin import ModelAdmin -from app.admin.filters import DefaultFalseBooleanFilter -from chains.models import Chain -from chains.models.chain import ChainQuerySet +from apps.chains.models import Chain +from apps.chains.models.chain import ChainQuerySet +from core.admin import admin +from core.admin import ModelAdmin +from core.admin.filters import DefaultFalseBooleanFilter class ChainArchivedFilter(DefaultFalseBooleanFilter): diff --git a/src/chains/admin/forms.py b/src/apps/chains/admin/forms.py similarity index 94% rename from src/chains/admin/forms.py rename to src/apps/chains/admin/forms.py index ffbdee9b9e5..d667919071d 100644 --- a/src/chains/admin/forms.py +++ b/src/apps/chains/admin/forms.py @@ -1,8 +1,8 @@ from django import forms from django.utils.translation import gettext_lazy as _ -from chains.models import Chain -from chains.models import Message +from apps.chains.models import Chain +from apps.chains.models import Message class ChainChoiceField(forms.ModelChoiceField): diff --git a/src/chains/admin/message.py b/src/apps/chains/admin/message.py similarity index 84% rename from src/chains/admin/message.py rename to src/apps/chains/admin/message.py index 38d55122dd3..19b495a0352 100644 --- a/src/chains/admin/message.py +++ b/src/apps/chains/admin/message.py @@ -3,11 +3,11 @@ from django.http.request import HttpRequest from django.utils.translation import gettext_lazy as _ -from app.admin import admin -from app.admin import ModelAdmin -from chains.admin.forms import MessageAddForm -from chains.admin.forms import MessageEditForm -from chains.models import Message +from apps.chains.admin.forms import MessageAddForm +from apps.chains.admin.forms import MessageEditForm +from apps.chains.models import Message +from core.admin import admin +from core.admin import ModelAdmin @admin.register(Message) diff --git a/src/chains/apps.py b/src/apps/chains/apps.py similarity index 83% rename from src/chains/apps.py rename to src/apps/chains/apps.py index e01f14fa9c8..41477ae5929 100644 --- a/src/chains/apps.py +++ b/src/apps/chains/apps.py @@ -3,4 +3,4 @@ class ChainsConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" - name = "chains" + name = "apps.chains" diff --git a/src/chains/migrations/0001_Initial.py b/src/apps/chains/migrations/0001_Initial.py similarity index 100% rename from src/chains/migrations/0001_Initial.py rename to src/apps/chains/migrations/0001_Initial.py diff --git a/src/chains/migrations/0002_ChainsAdminImprovements.py b/src/apps/chains/migrations/0002_ChainsAdminImprovements.py similarity index 100% rename from src/chains/migrations/0002_ChainsAdminImprovements.py rename to src/apps/chains/migrations/0002_ChainsAdminImprovements.py diff --git a/src/chains/migrations/0003_LimitParentChoices.py b/src/apps/chains/migrations/0003_LimitParentChoices.py similarity index 100% rename from src/chains/migrations/0003_LimitParentChoices.py rename to src/apps/chains/migrations/0003_LimitParentChoices.py diff --git a/src/chains/migrations/0004_UniqueChainName.py b/src/apps/chains/migrations/0004_UniqueChainName.py similarity index 100% rename from src/chains/migrations/0004_UniqueChainName.py rename to src/apps/chains/migrations/0004_UniqueChainName.py diff --git a/src/chains/migrations/0005_MessageAdminSpeedup.py b/src/apps/chains/migrations/0005_MessageAdminSpeedup.py similarity index 100% rename from src/chains/migrations/0005_MessageAdminSpeedup.py rename to src/apps/chains/migrations/0005_MessageAdminSpeedup.py diff --git a/src/chains/migrations/0006_i18n.py b/src/apps/chains/migrations/0006_i18n.py similarity index 100% rename from src/chains/migrations/0006_i18n.py rename to src/apps/chains/migrations/0006_i18n.py diff --git a/src/chains/migrations/0007_StudyConstraints.py b/src/apps/chains/migrations/0007_StudyConstraints.py similarity index 100% rename from src/chains/migrations/0007_StudyConstraints.py rename to src/apps/chains/migrations/0007_StudyConstraints.py diff --git a/src/chains/migrations/0008_ChainProgressStatus.py b/src/apps/chains/migrations/0008_ChainProgressStatus.py similarity index 100% rename from src/chains/migrations/0008_ChainProgressStatus.py rename to src/apps/chains/migrations/0008_ChainProgressStatus.py diff --git a/src/chains/migrations/0009_CreateChainProgressForAlreadyPurchasedUsers.py b/src/apps/chains/migrations/0009_CreateChainProgressForAlreadyPurchasedUsers.py similarity index 100% rename from src/chains/migrations/0009_CreateChainProgressForAlreadyPurchasedUsers.py rename to src/apps/chains/migrations/0009_CreateChainProgressForAlreadyPurchasedUsers.py diff --git a/src/chains/migrations/0010_ChainsAdminLabelChange.py b/src/apps/chains/migrations/0010_ChainsAdminLabelChange.py similarity index 100% rename from src/chains/migrations/0010_ChainsAdminLabelChange.py rename to src/apps/chains/migrations/0010_ChainsAdminLabelChange.py diff --git a/src/chains/migrations/0011_chain_archived_field.py b/src/apps/chains/migrations/0011_chain_archived_field.py similarity index 100% rename from src/chains/migrations/0011_chain_archived_field.py rename to src/apps/chains/migrations/0011_chain_archived_field.py diff --git a/src/amocrm/tests/services/order/__init__.py b/src/apps/chains/migrations/__init__.py similarity index 100% rename from src/amocrm/tests/services/order/__init__.py rename to src/apps/chains/migrations/__init__.py diff --git a/src/apps/chains/models/__init__.py b/src/apps/chains/models/__init__.py new file mode 100644 index 00000000000..aa975c231a4 --- /dev/null +++ b/src/apps/chains/models/__init__.py @@ -0,0 +1,9 @@ +from apps.chains.models.chain import Chain +from apps.chains.models.message import Message +from apps.chains.models.progress import Progress + +__all__ = [ + "Chain", + "Message", + "Progress", +] diff --git a/src/chains/models/chain.py b/src/apps/chains/models/chain.py similarity index 94% rename from src/chains/models/chain.py rename to src/apps/chains/models/chain.py index 69590b6bf06..0a2f6000ce2 100644 --- a/src/chains/models/chain.py +++ b/src/apps/chains/models/chain.py @@ -1,8 +1,8 @@ from django.db.models import QuerySet from django.utils.translation import gettext_lazy as _ -from app.models import models -from app.models import TimestampedModel +from core.models import models +from core.models import TimestampedModel class ChainQuerySet(QuerySet): diff --git a/src/chains/models/message.py b/src/apps/chains/models/message.py similarity index 94% rename from src/chains/models/message.py rename to src/apps/chains/models/message.py index 7d0366b217c..3dcfffbde37 100644 --- a/src/chains/models/message.py +++ b/src/apps/chains/models/message.py @@ -5,9 +5,9 @@ from django.utils import timezone from django.utils.translation import gettext_lazy as _ -from app.models import models -from app.models import TimestampedModel -from studying.models import Study +from apps.studying.models import Study +from core.models import models +from core.models import TimestampedModel class MessageQuerySet(QuerySet): diff --git a/src/chains/models/progress.py b/src/apps/chains/models/progress.py similarity index 86% rename from src/chains/models/progress.py rename to src/apps/chains/models/progress.py index 09b10c6cb61..cc3a134f169 100644 --- a/src/chains/models/progress.py +++ b/src/apps/chains/models/progress.py @@ -1,11 +1,11 @@ from typing import Optional, TYPE_CHECKING # NOQA: I251 -from app.models import models -from app.models import TimestampedModel -from studying.models import Study +from apps.studying.models import Study +from core.models import models +from core.models import TimestampedModel if TYPE_CHECKING: - from chains.models.chain import Chain + from apps.chains.models.chain import Chain class ProgressQuerySet(models.QuerySet): diff --git a/src/apps/chains/services/__init__.py b/src/apps/chains/services/__init__.py new file mode 100644 index 00000000000..11317760427 --- /dev/null +++ b/src/apps/chains/services/__init__.py @@ -0,0 +1,7 @@ +from apps.chains.services.chain_sender import ChainSender +from apps.chains.services.message_sender import MessageSender + +__all__ = [ + "ChainSender", + "MessageSender", +] diff --git a/src/chains/services/chain_sender.py b/src/apps/chains/services/chain_sender.py similarity index 82% rename from src/chains/services/chain_sender.py rename to src/apps/chains/services/chain_sender.py index 2b7d62a8fc6..6d83ca52b2a 100644 --- a/src/chains/services/chain_sender.py +++ b/src/apps/chains/services/chain_sender.py @@ -1,10 +1,10 @@ from dataclasses import dataclass -from app.services import BaseService -from chains.models import Chain -from chains.models import Message -from chains.models import Progress -from studying.models import Study +from apps.chains.models import Chain +from apps.chains.models import Message +from apps.chains.models import Progress +from apps.studying.models import Study +from core.services import BaseService @dataclass @@ -37,6 +37,6 @@ def send_root_messages(self, study: Study) -> None: @staticmethod def send(message: Message, study: Study) -> None: - from chains.services.message_sender import MessageSender + from apps.chains.services.message_sender import MessageSender MessageSender(message=message, study=study)() diff --git a/src/chains/services/message_sender.py b/src/apps/chains/services/message_sender.py similarity index 82% rename from src/chains/services/message_sender.py rename to src/apps/chains/services/message_sender.py index 85c3e138657..e143e3201f4 100644 --- a/src/chains/services/message_sender.py +++ b/src/apps/chains/services/message_sender.py @@ -1,12 +1,12 @@ from dataclasses import dataclass from functools import partial -from app.services import BaseService -from chains import tasks -from chains.models import Message -from chains.models import Progress -from mailing.tasks import send_mail -from studying.models import Study +from apps.chains import tasks +from apps.chains.models import Message +from apps.chains.models import Progress +from apps.mailing.tasks import send_mail +from apps.studying.models import Study +from core.services import BaseService @dataclass diff --git a/src/chains/static/admin/js/clickable_message_intervals.js b/src/apps/chains/static/admin/js/clickable_message_intervals.js similarity index 100% rename from src/chains/static/admin/js/clickable_message_intervals.js rename to src/apps/chains/static/admin/js/clickable_message_intervals.js diff --git a/src/chains/static/admin/js/limit_message_choices.js b/src/apps/chains/static/admin/js/limit_message_choices.js similarity index 100% rename from src/chains/static/admin/js/limit_message_choices.js rename to src/apps/chains/static/admin/js/limit_message_choices.js diff --git a/src/chains/tasks.py b/src/apps/chains/tasks.py similarity index 75% rename from src/chains/tasks.py rename to src/apps/chains/tasks.py index 3d2cfb2a3fd..e5cced88ace 100644 --- a/src/chains/tasks.py +++ b/src/apps/chains/tasks.py @@ -1,7 +1,7 @@ -from app.celery import celery -from chains.models import Chain -from chains.models import Progress -from chains.services import ChainSender +from apps.chains.models import Chain +from apps.chains.models import Progress +from apps.chains.services import ChainSender +from core.celery import celery @celery.task diff --git a/src/app/__init__.py b/src/apps/diplomas/__init__.py similarity index 100% rename from src/app/__init__.py rename to src/apps/diplomas/__init__.py diff --git a/src/diplomas/admin.py b/src/apps/diplomas/admin.py similarity index 91% rename from src/diplomas/admin.py rename to src/apps/diplomas/admin.py index 1f02859d97c..ce4e168dce3 100644 --- a/src/diplomas/admin.py +++ b/src/apps/diplomas/admin.py @@ -6,13 +6,13 @@ from django.db.models import QuerySet from django.utils.translation import gettext_lazy as _ -from app.admin import admin -from app.admin import ModelAdmin -from diplomas.models import Diploma -from diplomas.models import DiplomaTemplate -from orders import tasks -from products.models import Course -from users.models import User +from apps.diplomas.models import Diploma +from apps.diplomas.models import DiplomaTemplate +from apps.orders import tasks +from apps.products.models import Course +from apps.users.models import User +from core.admin import admin +from core.admin import ModelAdmin @admin.register(Diploma) diff --git a/src/diplomas/api/permissions.py b/src/apps/diplomas/api/permissions.py similarity index 100% rename from src/diplomas/api/permissions.py rename to src/apps/diplomas/api/permissions.py diff --git a/src/diplomas/api/serializers.py b/src/apps/diplomas/api/serializers.py similarity index 91% rename from src/diplomas/api/serializers.py rename to src/apps/diplomas/api/serializers.py index 635316ffb80..f2993f201d3 100644 --- a/src/diplomas/api/serializers.py +++ b/src/apps/diplomas/api/serializers.py @@ -1,10 +1,10 @@ from rest_framework import serializers from rest_framework.exceptions import ValidationError -from diplomas.models import Diploma -from products.api.serializers import CourseSimpleSerializer -from studying.models import Study -from users.api.serializers import UserSafeSerializer +from apps.diplomas.models import Diploma +from apps.products.api.serializers import CourseSimpleSerializer +from apps.studying.models import Study +from apps.users.api.serializers import UserSafeSerializer class DiplomaSerializer(serializers.ModelSerializer): diff --git a/src/diplomas/api/viewsets.py b/src/apps/diplomas/api/viewsets.py similarity index 83% rename from src/diplomas/api/viewsets.py rename to src/apps/diplomas/api/viewsets.py index ac16c232d14..aa8d99caa93 100644 --- a/src/diplomas/api/viewsets.py +++ b/src/apps/diplomas/api/viewsets.py @@ -5,11 +5,11 @@ from django.db.models import QuerySet -from app.api.mixins import DisablePaginationWithQueryParamMixin -from app.viewsets import AppViewSet -from diplomas.api import serializers -from diplomas.api.permissions import DiplomaPermission -from diplomas.models import Diploma +from apps.diplomas.api import serializers +from apps.diplomas.api.permissions import DiplomaPermission +from apps.diplomas.models import Diploma +from core.api.mixins import DisablePaginationWithQueryParamMixin +from core.viewsets import AppViewSet class DiplomaViewSet(DisablePaginationWithQueryParamMixin, AppViewSet): diff --git a/src/diplomas/apps.py b/src/apps/diplomas/apps.py similarity index 82% rename from src/diplomas/apps.py rename to src/apps/diplomas/apps.py index c4c017bc70c..8494b86b1b8 100644 --- a/src/diplomas/apps.py +++ b/src/apps/diplomas/apps.py @@ -3,4 +3,4 @@ class DiplomasConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" - name = "diplomas" + name = "apps.diplomas" diff --git a/src/diplomas/migrations/0001_initial.py b/src/apps/diplomas/migrations/0001_initial.py similarity index 100% rename from src/diplomas/migrations/0001_initial.py rename to src/apps/diplomas/migrations/0001_initial.py diff --git a/src/diplomas/migrations/0002_RandomDiplomaFileNames.py b/src/apps/diplomas/migrations/0002_RandomDiplomaFileNames.py similarity index 76% rename from src/diplomas/migrations/0002_RandomDiplomaFileNames.py rename to src/apps/diplomas/migrations/0002_RandomDiplomaFileNames.py index e68c6a25af3..5a1e94d2e52 100644 --- a/src/diplomas/migrations/0002_RandomDiplomaFileNames.py +++ b/src/apps/diplomas/migrations/0002_RandomDiplomaFileNames.py @@ -3,7 +3,7 @@ from django.db import migrations from django.db import models -import app.files +import core.files class Migration(migrations.Migration): @@ -16,6 +16,6 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='diploma', name='image', - field=models.ImageField(upload_to=app.files.RandomFileName('diplomas')), + field=models.ImageField(upload_to=core.files.RandomFileName('diplomas')), ), ] diff --git a/src/diplomas/migrations/0003_ShortDiplomaSlug.py b/src/apps/diplomas/migrations/0003_ShortDiplomaSlug.py similarity index 100% rename from src/diplomas/migrations/0003_ShortDiplomaSlug.py rename to src/apps/diplomas/migrations/0003_ShortDiplomaSlug.py diff --git a/src/diplomas/migrations/0004_DiplomaTemplates.py b/src/apps/diplomas/migrations/0004_DiplomaTemplates.py similarity index 100% rename from src/diplomas/migrations/0004_DiplomaTemplates.py rename to src/apps/diplomas/migrations/0004_DiplomaTemplates.py diff --git a/src/diplomas/migrations/0005_DroppedHomeworkFlagFromDiplomaTemplate.py b/src/apps/diplomas/migrations/0005_DroppedHomeworkFlagFromDiplomaTemplate.py similarity index 100% rename from src/diplomas/migrations/0005_DroppedHomeworkFlagFromDiplomaTemplate.py rename to src/apps/diplomas/migrations/0005_DroppedHomeworkFlagFromDiplomaTemplate.py diff --git a/src/diplomas/migrations/0006_DiplomaTemplateHomework.py b/src/apps/diplomas/migrations/0006_DiplomaTemplateHomework.py similarity index 100% rename from src/diplomas/migrations/0006_DiplomaTemplateHomework.py rename to src/apps/diplomas/migrations/0006_DiplomaTemplateHomework.py diff --git a/src/app/migrations/__init__.py b/src/apps/diplomas/migrations/__init__.py similarity index 100% rename from src/app/migrations/__init__.py rename to src/apps/diplomas/migrations/__init__.py diff --git a/src/diplomas/models.py b/src/apps/diplomas/models.py similarity index 94% rename from src/diplomas/models.py rename to src/apps/diplomas/models.py index 02bc3916115..8b2831a82a3 100644 --- a/src/diplomas/models.py +++ b/src/apps/diplomas/models.py @@ -9,13 +9,13 @@ from django.db.models import OuterRef from django.utils.translation import gettext_lazy as _ -from app.files import RandomFileName -from app.models import models -from app.models import TimestampedModel -from mailing.tasks import send_mail +from apps.mailing.tasks import send_mail +from core.files import RandomFileName +from core.models import models +from core.models import TimestampedModel if TYPE_CHECKING: - from users.models import User + from apps.users.models import User class Languages(models.TextChoices): diff --git a/src/apps/diplomas/services/__init__.py b/src/apps/diplomas/services/__init__.py new file mode 100644 index 00000000000..d5c5ababcd8 --- /dev/null +++ b/src/apps/diplomas/services/__init__.py @@ -0,0 +1,7 @@ +from apps.diplomas.services.diploma_generator import DiplomaGenerator +from apps.diplomas.services.diploma_regenerator import DiplomaRegenerator + +__all__ = [ + "DiplomaGenerator", + "DiplomaRegenerator", +] diff --git a/src/diplomas/services/diploma_generator.py b/src/apps/diplomas/services/diploma_generator.py similarity index 88% rename from src/diplomas/services/diploma_generator.py rename to src/apps/diplomas/services/diploma_generator.py index 4dc245974f3..a426e5997f7 100644 --- a/src/diplomas/services/diploma_generator.py +++ b/src/apps/diplomas/services/diploma_generator.py @@ -7,13 +7,13 @@ from django.conf import settings from django.core.files.base import ContentFile -from app.services import BaseService -from app.types import Language -from diplomas.models import Diploma -from diplomas.models import DiplomaTemplate -from products.models import Course -from studying.models import Study -from users.models import User +from apps.diplomas.models import Diploma +from apps.diplomas.models import DiplomaTemplate +from apps.products.models import Course +from apps.studying.models import Study +from apps.users.models import User +from core.services import BaseService +from core.types import Language class WrongDiplomaServiceResponse(httpx.HTTPError): diff --git a/src/diplomas/services/diploma_regenerator.py b/src/apps/diplomas/services/diploma_regenerator.py similarity index 87% rename from src/diplomas/services/diploma_regenerator.py rename to src/apps/diplomas/services/diploma_regenerator.py index 1b94b490a6e..77b6852f8c7 100644 --- a/src/diplomas/services/diploma_regenerator.py +++ b/src/apps/diplomas/services/diploma_regenerator.py @@ -3,14 +3,14 @@ from django.db.models import QuerySet -from app.services import BaseService -from app.types import Language -from diplomas.models import Diploma -from diplomas.models import DiplomaTemplate -from diplomas.services.diploma_generator import DiplomaGenerator -from mailing.tasks import send_mail -from studying.models import Study -from users.models import User +from apps.diplomas.models import Diploma +from apps.diplomas.models import DiplomaTemplate +from apps.diplomas.services.diploma_generator import DiplomaGenerator +from apps.mailing.tasks import send_mail +from apps.studying.models import Study +from apps.users.models import User +from core.services import BaseService +from core.types import Language @dataclass diff --git a/src/diplomas/tasks.py b/src/apps/diplomas/tasks.py similarity index 68% rename from src/diplomas/tasks.py rename to src/apps/diplomas/tasks.py index 3ff2d923772..b9396f4b6ae 100644 --- a/src/diplomas/tasks.py +++ b/src/apps/diplomas/tasks.py @@ -1,12 +1,12 @@ import httpx -from app.celery import celery -from app.types import Language -from diplomas.services import DiplomaGenerator -from diplomas.services import DiplomaRegenerator -from diplomas.services.diploma_generator import WrongDiplomaServiceResponse -from products.models import Course -from users.models import User +from apps.diplomas.services import DiplomaGenerator +from apps.diplomas.services import DiplomaRegenerator +from apps.diplomas.services.diploma_generator import WrongDiplomaServiceResponse +from apps.products.models import Course +from apps.users.models import User +from core.celery import celery +from core.types import Language @celery.task( diff --git a/src/diplomas/urls.py b/src/apps/diplomas/urls.py similarity index 80% rename from src/diplomas/urls.py rename to src/apps/diplomas/urls.py index 1337f078913..00c5ad3f10a 100644 --- a/src/diplomas/urls.py +++ b/src/apps/diplomas/urls.py @@ -3,7 +3,7 @@ from django.urls import include from django.urls import path -from diplomas.api.viewsets import DiplomaViewSet +from apps.diplomas.api.viewsets import DiplomaViewSet router = SimpleRouter() diff --git a/src/banking/__init__.py b/src/apps/homework/__init__.py similarity index 100% rename from src/banking/__init__.py rename to src/apps/homework/__init__.py diff --git a/src/apps/homework/admin/__init__.py b/src/apps/homework/admin/__init__.py new file mode 100644 index 00000000000..79a3c7a285f --- /dev/null +++ b/src/apps/homework/admin/__init__.py @@ -0,0 +1,2 @@ +import apps.homework.admin.answer.admin # noqa +import apps.homework.admin.question.admin # noqa diff --git a/src/homework/admin/answer/admin.py b/src/apps/homework/admin/answer/admin.py similarity index 93% rename from src/homework/admin/answer/admin.py rename to src/apps/homework/admin/answer/admin.py index 3bdd7d333e5..509965d1465 100644 --- a/src/homework/admin/answer/admin.py +++ b/src/apps/homework/admin/answer/admin.py @@ -5,11 +5,11 @@ from django.utils.safestring import mark_safe from django.utils.translation import gettext_lazy as _ -from app.admin import admin -from app.admin import ModelAdmin -from homework.admin.answer.filters import IsRootFilter -from homework.models import Answer -from homework.models import AnswerCrossCheck +from apps.homework.admin.answer.filters import IsRootFilter +from apps.homework.models import Answer +from apps.homework.models import AnswerCrossCheck +from core.admin import admin +from core.admin import ModelAdmin @admin.register(Answer) diff --git a/src/homework/admin/answer/filters.py b/src/apps/homework/admin/answer/filters.py similarity index 91% rename from src/homework/admin/answer/filters.py rename to src/apps/homework/admin/answer/filters.py index 6869d466026..55f8dc7a5fa 100644 --- a/src/homework/admin/answer/filters.py +++ b/src/apps/homework/admin/answer/filters.py @@ -3,7 +3,7 @@ from django.db.models import QuerySet from django.utils.translation import gettext_lazy as _ -from app.admin.filters import BooleanFilter +from core.admin.filters import BooleanFilter class IsRootFilter(BooleanFilter): diff --git a/src/homework/admin/question/admin.py b/src/apps/homework/admin/question/admin.py similarity index 86% rename from src/homework/admin/question/admin.py rename to src/apps/homework/admin/question/admin.py index d0017d6119d..74260581533 100644 --- a/src/homework/admin/question/admin.py +++ b/src/apps/homework/admin/question/admin.py @@ -3,10 +3,10 @@ from django.db.models import QuerySet from django.utils.translation import gettext_lazy as _ -from app.admin import admin -from app.admin import ModelAdmin -from homework import tasks -from homework.models import Question +from apps.homework import tasks +from apps.homework.models import Question +from core.admin import admin +from core.admin import ModelAdmin @admin.register(Question) diff --git a/src/homework/api/filtersets.py b/src/apps/homework/api/filtersets.py similarity index 86% rename from src/homework/api/filtersets.py rename to src/apps/homework/api/filtersets.py index 71457ef6a67..4fae2a898f4 100644 --- a/src/homework/api/filtersets.py +++ b/src/apps/homework/api/filtersets.py @@ -1,7 +1,7 @@ from django_filters import rest_framework as filters -from app.api.filters import UUIDInFilter -from homework.models import Answer +from apps.homework.models import Answer +from core.api.filters import UUIDInFilter class AnswerFilterSet(filters.FilterSet): diff --git a/src/homework/api/permissions.py b/src/apps/homework/api/permissions.py similarity index 98% rename from src/homework/api/permissions.py rename to src/apps/homework/api/permissions.py index 30fd42392ff..3bea017906c 100644 --- a/src/homework/api/permissions.py +++ b/src/apps/homework/api/permissions.py @@ -8,7 +8,7 @@ from django.conf import settings from django.utils import timezone -from homework.models import Question +from apps.homework.models import Question def get_all_purcased_user_ids(question: Question) -> frozenset[int]: diff --git a/src/homework/api/serializers.py b/src/apps/homework/api/serializers.py similarity index 91% rename from src/homework/api/serializers.py rename to src/apps/homework/api/serializers.py index 9acf61593b6..113ae7fcbb0 100644 --- a/src/homework/api/serializers.py +++ b/src/apps/homework/api/serializers.py @@ -2,13 +2,13 @@ from rest_framework import serializers -from app.serializers import MarkdownField -from app.serializers import SoftField -from homework.models import Answer -from homework.models import AnswerImage -from homework.models import Question -from homework.models.reaction import Reaction -from users.api.serializers import UserSafeSerializer +from apps.homework.models import Answer +from apps.homework.models import AnswerImage +from apps.homework.models import Question +from apps.homework.models.reaction import Reaction +from apps.users.api.serializers import UserSafeSerializer +from core.serializers import MarkdownField +from core.serializers import SoftField class ReactionDetailedSerializer(serializers.ModelSerializer): diff --git a/src/homework/api/views.py b/src/apps/homework/api/views.py similarity index 75% rename from src/homework/api/views.py rename to src/apps/homework/api/views.py index e5e28412889..1f30c4f0c8a 100644 --- a/src/homework/api/views.py +++ b/src/apps/homework/api/views.py @@ -3,12 +3,12 @@ from django.db.models import QuerySet -from homework.api import serializers -from homework.api.filtersets import AnswerCommentFilterSet -from homework.api.permissions import ShouldHavePurchasedCoursePermission -from homework.models import Answer -from homework.models import AnswerImage -from homework.models import Question +from apps.homework.api import serializers +from apps.homework.api.filtersets import AnswerCommentFilterSet +from apps.homework.api.permissions import ShouldHavePurchasedCoursePermission +from apps.homework.models import Answer +from apps.homework.models import AnswerImage +from apps.homework.models import Question class QuestionView(generics.RetrieveAPIView): diff --git a/src/homework/api/viewsets.py b/src/apps/homework/api/viewsets.py similarity index 80% rename from src/homework/api/viewsets.py rename to src/apps/homework/api/viewsets.py index ac60bee34f7..9ba1721a6d2 100644 --- a/src/homework/api/viewsets.py +++ b/src/apps/homework/api/viewsets.py @@ -10,23 +10,23 @@ from django.db.models import QuerySet from django.utils.functional import cached_property -from app.api.mixins import DisablePaginationWithQueryParamMixin -from app.viewsets import AppViewSet -from app.viewsets import CreateDeleteAppViewSet -from homework.api.filtersets import AnswerFilterSet -from homework.api.permissions import MayChangeAnswerOnlyForLimitedTime -from homework.api.permissions import MayChangeAnswerOnlyWithoutDescendants -from homework.api.permissions import ShouldBeAuthorOrReadOnly -from homework.api.permissions import ShouldHavePurchasedQuestionCoursePermission -from homework.api.serializers import AnswerCreateSerializer -from homework.api.serializers import AnswerDetailedSerializer -from homework.api.serializers import ReactionCreateSerializer -from homework.api.serializers import ReactionDetailedSerializer -from homework.models import Answer -from homework.models import AnswerAccessLogEntry -from homework.models.answer import AnswerQuerySet -from homework.models.reaction import Reaction -from homework.services import ReactionCreator +from apps.homework.api.filtersets import AnswerFilterSet +from apps.homework.api.permissions import MayChangeAnswerOnlyForLimitedTime +from apps.homework.api.permissions import MayChangeAnswerOnlyWithoutDescendants +from apps.homework.api.permissions import ShouldBeAuthorOrReadOnly +from apps.homework.api.permissions import ShouldHavePurchasedQuestionCoursePermission +from apps.homework.api.serializers import AnswerCreateSerializer +from apps.homework.api.serializers import AnswerDetailedSerializer +from apps.homework.api.serializers import ReactionCreateSerializer +from apps.homework.api.serializers import ReactionDetailedSerializer +from apps.homework.models import Answer +from apps.homework.models import AnswerAccessLogEntry +from apps.homework.models.answer import AnswerQuerySet +from apps.homework.models.reaction import Reaction +from apps.homework.services import ReactionCreator +from core.api.mixins import DisablePaginationWithQueryParamMixin +from core.viewsets import AppViewSet +from core.viewsets import CreateDeleteAppViewSet class AnswerViewSet(DisablePaginationWithQueryParamMixin, AppViewSet): diff --git a/src/homework/apps.py b/src/apps/homework/apps.py similarity index 55% rename from src/homework/apps.py rename to src/apps/homework/apps.py index 5c9418625c5..3ac6a26673f 100644 --- a/src/homework/apps.py +++ b/src/apps/homework/apps.py @@ -2,7 +2,7 @@ class HomeworkConfig(AppConfig): - name = "homework" + name = "apps.homework" def ready(self) -> None: - import homework.signals.handlers # noqa + import apps.homework.signals.handlers # noqa diff --git a/src/homework/migrations/0001_initial.py b/src/apps/homework/migrations/0001_initial.py similarity index 100% rename from src/homework/migrations/0001_initial.py rename to src/apps/homework/migrations/0001_initial.py diff --git a/src/homework/migrations/0002_MultipleCourses.py b/src/apps/homework/migrations/0002_MultipleCourses.py similarity index 100% rename from src/homework/migrations/0002_MultipleCourses.py rename to src/apps/homework/migrations/0002_MultipleCourses.py diff --git a/src/homework/migrations/0003_AnswerTree.py b/src/apps/homework/migrations/0003_AnswerTree.py similarity index 100% rename from src/homework/migrations/0003_AnswerTree.py rename to src/apps/homework/migrations/0003_AnswerTree.py diff --git a/src/homework/migrations/0004_DefaultAnswerOrdering.py b/src/apps/homework/migrations/0004_DefaultAnswerOrdering.py similarity index 100% rename from src/homework/migrations/0004_DefaultAnswerOrdering.py rename to src/apps/homework/migrations/0004_DefaultAnswerOrdering.py diff --git a/src/homework/migrations/0005_GodAnswerUsers.py b/src/apps/homework/migrations/0005_GodAnswerUsers.py similarity index 100% rename from src/homework/migrations/0005_GodAnswerUsers.py rename to src/apps/homework/migrations/0005_GodAnswerUsers.py diff --git a/src/homework/migrations/0006_AnswerAccessLogEntry.py b/src/apps/homework/migrations/0006_AnswerAccessLogEntry.py similarity index 100% rename from src/homework/migrations/0006_AnswerAccessLogEntry.py rename to src/apps/homework/migrations/0006_AnswerAccessLogEntry.py diff --git a/src/homework/migrations/0006_SeeAllQuestionsPermission.py b/src/apps/homework/migrations/0006_SeeAllQuestionsPermission.py similarity index 100% rename from src/homework/migrations/0006_SeeAllQuestionsPermission.py rename to src/apps/homework/migrations/0006_SeeAllQuestionsPermission.py diff --git a/src/homework/migrations/0007_merge_20210420_0027.py b/src/apps/homework/migrations/0007_merge_20210420_0027.py similarity index 100% rename from src/homework/migrations/0007_merge_20210420_0027.py rename to src/apps/homework/migrations/0007_merge_20210420_0027.py diff --git a/src/homework/migrations/0008_AnswersCrossCheck.py b/src/apps/homework/migrations/0008_AnswersCrossCheck.py similarity index 100% rename from src/homework/migrations/0008_AnswersCrossCheck.py rename to src/apps/homework/migrations/0008_AnswersCrossCheck.py diff --git a/src/homework/migrations/0009_ExcludeAnswersFromCrossCheck.py b/src/apps/homework/migrations/0009_ExcludeAnswersFromCrossCheck.py similarity index 100% rename from src/homework/migrations/0009_ExcludeAnswersFromCrossCheck.py rename to src/apps/homework/migrations/0009_ExcludeAnswersFromCrossCheck.py diff --git a/src/homework/migrations/0010_ForogttenAnswerModified.py b/src/apps/homework/migrations/0010_ForogttenAnswerModified.py similarity index 100% rename from src/homework/migrations/0010_ForogttenAnswerModified.py rename to src/apps/homework/migrations/0010_ForogttenAnswerModified.py diff --git a/src/homework/migrations/0011_AnswerImage.py b/src/apps/homework/migrations/0011_AnswerImage.py similarity index 89% rename from src/homework/migrations/0011_AnswerImage.py rename to src/apps/homework/migrations/0011_AnswerImage.py index 16eaef9ebb8..1b8ad087344 100644 --- a/src/homework/migrations/0011_AnswerImage.py +++ b/src/apps/homework/migrations/0011_AnswerImage.py @@ -5,7 +5,7 @@ from django.db import models import django.db.models.deletion -import app.files +import core.files class Migration(migrations.Migration): @@ -22,7 +22,7 @@ class Migration(migrations.Migration): ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), ("created", models.DateTimeField(auto_now_add=True, db_index=True)), ("modified", models.DateTimeField(blank=True, db_index=True, null=True)), - ("image", models.ImageField(upload_to=app.files.RandomFileName("homework/answers"))), + ("image", models.ImageField(upload_to=core.files.RandomFileName("homework/answers"))), ("author", models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), ], options={ diff --git a/src/homework/migrations/0012_Reaction.py b/src/apps/homework/migrations/0012_Reaction.py similarity index 100% rename from src/homework/migrations/0012_Reaction.py rename to src/apps/homework/migrations/0012_Reaction.py diff --git a/src/homework/migrations/0013_DropAnswerRelationsForMypyUpgrade.py b/src/apps/homework/migrations/0013_DropAnswerRelationsForMypyUpgrade.py similarity index 100% rename from src/homework/migrations/0013_DropAnswerRelationsForMypyUpgrade.py rename to src/apps/homework/migrations/0013_DropAnswerRelationsForMypyUpgrade.py diff --git a/src/banking/migrations/__init__.py b/src/apps/homework/migrations/__init__.py similarity index 100% rename from src/banking/migrations/__init__.py rename to src/apps/homework/migrations/__init__.py diff --git a/src/apps/homework/models/__init__.py b/src/apps/homework/models/__init__.py new file mode 100644 index 00000000000..99ebbbb4e82 --- /dev/null +++ b/src/apps/homework/models/__init__.py @@ -0,0 +1,13 @@ +from apps.homework.models.answer import Answer +from apps.homework.models.answer_access_log_entry import AnswerAccessLogEntry +from apps.homework.models.answer_cross_check import AnswerCrossCheck +from apps.homework.models.answer_image import AnswerImage +from apps.homework.models.question import Question + +__all__ = [ + "Answer", + "AnswerAccessLogEntry", + "AnswerCrossCheck", + "AnswerImage", + "Question", +] diff --git a/src/homework/models/answer.py b/src/apps/homework/models/answer.py similarity index 94% rename from src/homework/models/answer.py rename to src/apps/homework/models/answer.py index 07c61b43ee8..15bd091bf23 100644 --- a/src/homework/models/answer.py +++ b/src/apps/homework/models/answer.py @@ -13,13 +13,13 @@ from django.db.models.query_utils import FilteredRelation from django.utils.translation import gettext_lazy as _ -from app.markdown import markdownify -from app.markdown import remove_html -from app.models import models -from homework.models.reaction import Reaction -from orders.models import Order -from products.models import Course -from users.models import User +from apps.homework.models.reaction import Reaction +from apps.orders.models import Order +from apps.products.models import Course +from apps.users.models import User +from core.markdown import markdownify +from core.markdown import remove_html +from core.models import models class AnswerQuerySet(TreeQuerySet): diff --git a/src/homework/models/answer_access_log_entry.py b/src/apps/homework/models/answer_access_log_entry.py similarity index 87% rename from src/homework/models/answer_access_log_entry.py rename to src/apps/homework/models/answer_access_log_entry.py index 5eac54e996c..70240a373ec 100644 --- a/src/homework/models/answer_access_log_entry.py +++ b/src/apps/homework/models/answer_access_log_entry.py @@ -5,12 +5,12 @@ from django.db.models import QuerySet from django.db.models import UniqueConstraint -from app.models import models -from app.models import TimestampedModel +from core.models import models +from core.models import TimestampedModel if TYPE_CHECKING: - from homework.models import Answer - from users.models import User + from apps.homework.models import Answer + from apps.users.models import User class AnswerAccessLogEntryQuerySet(QuerySet): diff --git a/src/homework/models/answer_cross_check.py b/src/apps/homework/models/answer_cross_check.py similarity index 89% rename from src/homework/models/answer_cross_check.py rename to src/apps/homework/models/answer_cross_check.py index 2547f4c92f5..4fbad49135a 100644 --- a/src/homework/models/answer_cross_check.py +++ b/src/apps/homework/models/answer_cross_check.py @@ -1,8 +1,8 @@ from django.db.models import Index from django.db.models import UniqueConstraint -from app.models import models -from app.models import TimestampedModel +from core.models import models +from core.models import TimestampedModel class AnswerCrossCheck(TimestampedModel): diff --git a/src/homework/models/answer_image.py b/src/apps/homework/models/answer_image.py similarity index 66% rename from src/homework/models/answer_image.py rename to src/apps/homework/models/answer_image.py index 42de5aa2f84..83faadeeffd 100644 --- a/src/homework/models/answer_image.py +++ b/src/apps/homework/models/answer_image.py @@ -1,6 +1,6 @@ -from app.files import RandomFileName -from app.models import models -from app.models import TimestampedModel +from core.files import RandomFileName +from core.models import models +from core.models import TimestampedModel class AnswerImage(TimestampedModel): diff --git a/src/homework/models/question.py b/src/apps/homework/models/question.py similarity index 86% rename from src/homework/models/question.py rename to src/apps/homework/models/question.py index 21b6e3ea5d3..8e15a6d4986 100644 --- a/src/homework/models/question.py +++ b/src/apps/homework/models/question.py @@ -5,8 +5,8 @@ from django.conf import settings from django.utils.translation import gettext_lazy as _ -from app.models import models -from app.models import TimestampedModel +from core.models import models +from core.models import TimestampedModel class Question(TimestampedModel): @@ -27,7 +27,7 @@ def get_absolute_url(self) -> str: return urljoin(settings.FRONTEND_URL, f"homework/question-admin/{self.slug}/") def dispatch_crosscheck(self, **kwargs: dict[str, Any]) -> int: - from homework.services import QuestionCrossCheckDispatcher + from apps.homework.services import QuestionCrossCheckDispatcher dispatcher = QuestionCrossCheckDispatcher(question=self, **kwargs) # type: ignore diff --git a/src/homework/models/reaction.py b/src/apps/homework/models/reaction.py similarity index 93% rename from src/homework/models/reaction.py rename to src/apps/homework/models/reaction.py index 165f1c4eeeb..fdf2f2e7bf3 100644 --- a/src/homework/models/reaction.py +++ b/src/apps/homework/models/reaction.py @@ -3,8 +3,8 @@ from django.db.models import QuerySet from django.utils.translation import gettext_lazy as _ -from app.models import models -from app.models import TimestampedModel +from core.models import models +from core.models import TimestampedModel class ReactionQuerySet(QuerySet): diff --git a/src/apps/homework/services/__init__.py b/src/apps/homework/services/__init__.py new file mode 100644 index 00000000000..93114c5c958 --- /dev/null +++ b/src/apps/homework/services/__init__.py @@ -0,0 +1,12 @@ +from apps.homework.services.answer_crosscheck_dispatcher import AnswerCrossCheckDispatcher +from apps.homework.services.new_answer_notifier import NewAnswerNotifier +from apps.homework.services.question_crosscheck_dispatcher import QuestionCrossCheckDispatcher + +__all__ = [ + "AnswerCrossCheckDispatcher", + "NewAnswerNotifier", + "QuestionCrossCheckDispatcher", + "ReactionCreator", +] + +from apps.homework.services.reaction_creator import ReactionCreator diff --git a/src/homework/services/answer_crosscheck_dispatcher.py b/src/apps/homework/services/answer_crosscheck_dispatcher.py similarity index 93% rename from src/homework/services/answer_crosscheck_dispatcher.py rename to src/apps/homework/services/answer_crosscheck_dispatcher.py index 9b2625b92f0..544fd3fb36e 100644 --- a/src/homework/services/answer_crosscheck_dispatcher.py +++ b/src/apps/homework/services/answer_crosscheck_dispatcher.py @@ -5,10 +5,10 @@ from django.db.models import Q from django.db.models import QuerySet -from app.services import BaseService -from homework.models import Answer -from homework.models import AnswerCrossCheck -from users.models import User +from apps.homework.models import Answer +from apps.homework.models import AnswerCrossCheck +from apps.users.models import User +from core.services import BaseService @dataclass diff --git a/src/homework/services/new_answer_notifier.py b/src/apps/homework/services/new_answer_notifier.py similarity index 90% rename from src/homework/services/new_answer_notifier.py rename to src/apps/homework/services/new_answer_notifier.py index 93d85e40c6a..74ea7356109 100644 --- a/src/homework/services/new_answer_notifier.py +++ b/src/apps/homework/services/new_answer_notifier.py @@ -2,10 +2,10 @@ from django.db.models import QuerySet -from app.services import BaseService -from homework.models import Answer -from mailing.tasks import send_mail -from users.models import User +from apps.homework.models import Answer +from apps.mailing.tasks import send_mail +from apps.users.models import User +from core.services import BaseService @dataclass diff --git a/src/homework/services/question_crosscheck_dispatcher.py b/src/apps/homework/services/question_crosscheck_dispatcher.py similarity index 85% rename from src/homework/services/question_crosscheck_dispatcher.py rename to src/apps/homework/services/question_crosscheck_dispatcher.py index a8a7057938e..c30eb45e7ce 100644 --- a/src/homework/services/question_crosscheck_dispatcher.py +++ b/src/apps/homework/services/question_crosscheck_dispatcher.py @@ -2,13 +2,13 @@ from django.db.models import QuerySet -from app.services import BaseService -from homework.models import Answer -from homework.models import AnswerCrossCheck -from homework.models import Question -from homework.services.answer_crosscheck_dispatcher import AnswerCrossCheckDispatcher -from mailing.tasks import send_mail -from users.models import User +from apps.homework.models import Answer +from apps.homework.models import AnswerCrossCheck +from apps.homework.models import Question +from apps.homework.services.answer_crosscheck_dispatcher import AnswerCrossCheckDispatcher +from apps.mailing.tasks import send_mail +from apps.users.models import User +from core.services import BaseService @dataclass diff --git a/src/homework/services/reaction_creator.py b/src/apps/homework/services/reaction_creator.py similarity index 88% rename from src/homework/services/reaction_creator.py rename to src/apps/homework/services/reaction_creator.py index ee1efec8b28..40b7e02f75f 100644 --- a/src/homework/services/reaction_creator.py +++ b/src/apps/homework/services/reaction_creator.py @@ -8,11 +8,11 @@ from django.db import IntegrityError from django.utils.translation import gettext_lazy as _ -from app.exceptions import AppServiceException -from app.services import BaseService -from homework.models import Answer -from homework.models.reaction import Reaction -from users.models import User +from apps.homework.models import Answer +from apps.homework.models.reaction import Reaction +from apps.users.models import User +from core.exceptions import AppServiceException +from core.services import BaseService class ReactionCreatorException(AppServiceException): diff --git a/src/homework/signals/handlers.py b/src/apps/homework/signals/handlers.py similarity index 88% rename from src/homework/signals/handlers.py rename to src/apps/homework/signals/handlers.py index 3ffeddcfeba..42c400a78db 100644 --- a/src/homework/signals/handlers.py +++ b/src/apps/homework/signals/handlers.py @@ -5,8 +5,8 @@ from django.db.models.signals import post_save from django.dispatch import receiver -from homework import tasks -from homework.models import Answer +from apps.homework import tasks +from apps.homework.models import Answer @receiver(post_save, sender=Answer) diff --git a/src/homework/tasks.py b/src/apps/homework/tasks.py similarity index 70% rename from src/homework/tasks.py rename to src/apps/homework/tasks.py index 4748c5d2d0f..097623ff941 100644 --- a/src/homework/tasks.py +++ b/src/apps/homework/tasks.py @@ -1,9 +1,9 @@ from typing import Any -from app.celery import celery -from homework.models import Answer -from homework.models import Question -from homework.services import NewAnswerNotifier +from apps.homework.models import Answer +from apps.homework.models import Question +from apps.homework.services import NewAnswerNotifier +from core.celery import celery @celery.task diff --git a/src/homework/urls.py b/src/apps/homework/urls.py similarity index 80% rename from src/homework/urls.py rename to src/apps/homework/urls.py index 9802c5a1b9c..8ec2832817a 100644 --- a/src/homework/urls.py +++ b/src/apps/homework/urls.py @@ -3,9 +3,9 @@ from django.urls import include from django.urls import path -from homework.api import views -from homework.api.viewsets import AnswerViewSet -from homework.api.viewsets import ReactionViewSet +from apps.homework.api import views +from apps.homework.api.viewsets import AnswerViewSet +from apps.homework.api.viewsets import ReactionViewSet router = SimpleRouter() router.register("answers", AnswerViewSet) diff --git a/src/chains/__init__.py b/src/apps/magnets/__init__.py similarity index 100% rename from src/chains/__init__.py rename to src/apps/magnets/__init__.py diff --git a/src/magnets/admin.py b/src/apps/magnets/admin.py similarity index 88% rename from src/magnets/admin.py rename to src/apps/magnets/admin.py index b0b9cd76ae8..3dad2d8c77c 100644 --- a/src/magnets/admin.py +++ b/src/apps/magnets/admin.py @@ -3,9 +3,9 @@ from django.db.models import QuerySet from django.utils.translation import gettext_lazy as _ -from app.admin import admin -from app.admin import ModelAdmin -from magnets.models import EmailLeadMagnetCampaign +from apps.magnets.models import EmailLeadMagnetCampaign +from core.admin import admin +from core.admin import ModelAdmin @admin.register(EmailLeadMagnetCampaign) diff --git a/src/magnets/api/serializers.py b/src/apps/magnets/api/serializers.py similarity index 79% rename from src/magnets/api/serializers.py rename to src/apps/magnets/api/serializers.py index 6dceb313f4f..10576905b5f 100644 --- a/src/magnets/api/serializers.py +++ b/src/apps/magnets/api/serializers.py @@ -1,6 +1,6 @@ from rest_framework import serializers -from magnets.models import EmailLeadMagnetCampaign +from apps.magnets.models import EmailLeadMagnetCampaign class EmailLeadMagnetCampaignStubSerializer(serializers.ModelSerializer): diff --git a/src/magnets/api/validators.py b/src/apps/magnets/api/validators.py similarity index 94% rename from src/magnets/api/validators.py rename to src/apps/magnets/api/validators.py index 99db4f28d96..831f0509b14 100644 --- a/src/magnets/api/validators.py +++ b/src/apps/magnets/api/validators.py @@ -1,6 +1,6 @@ from drf_recaptcha.fields import ReCaptchaV3Field -from app import validators +from core import validators class LeadValidator(validators.Validator): diff --git a/src/magnets/api/views.py b/src/apps/magnets/api/views.py similarity index 80% rename from src/magnets/api/views.py rename to src/apps/magnets/api/views.py index e0ebdded404..770883cd407 100644 --- a/src/magnets/api/views.py +++ b/src/apps/magnets/api/views.py @@ -3,11 +3,11 @@ from django.shortcuts import get_object_or_404 -from app.views import AnonymousAPIView -from app.viewsets import ValidationMixin -from magnets.api.validators import LeadValidator -from magnets.creator import LeadCreator -from magnets.models import EmailLeadMagnetCampaign +from apps.magnets.api.validators import LeadValidator +from apps.magnets.creator import LeadCreator +from apps.magnets.models import EmailLeadMagnetCampaign +from core.views import AnonymousAPIView +from core.viewsets import ValidationMixin class EmailLeadMagnetCampaignView(AnonymousAPIView, ValidationMixin): diff --git a/src/magnets/apps.py b/src/apps/magnets/apps.py similarity index 85% rename from src/magnets/apps.py rename to src/apps/magnets/apps.py index ae49586041f..8849570dc6a 100644 --- a/src/magnets/apps.py +++ b/src/apps/magnets/apps.py @@ -3,6 +3,6 @@ class MagnetsConfig(AppConfig): - name = "magnets" + name = "apps.magnets" verbose_name = _("Magnets") diff --git a/src/magnets/creator.py b/src/apps/magnets/creator.py similarity index 77% rename from src/magnets/creator.py rename to src/apps/magnets/creator.py index cbec4126bf4..76e8f754e3a 100644 --- a/src/magnets/creator.py +++ b/src/apps/magnets/creator.py @@ -1,10 +1,10 @@ from dataclasses import dataclass -from app.services import BaseService -from magnets.models import EmailLeadMagnetCampaign -from magnets.models import LeadCampaignLogEntry -from users.models import User -from users.services import UserCreator +from apps.magnets.models import EmailLeadMagnetCampaign +from apps.magnets.models import LeadCampaignLogEntry +from apps.users.models import User +from apps.users.services import UserCreator +from core.services import BaseService @dataclass diff --git a/src/magnets/migrations/0001_initial.py b/src/apps/magnets/migrations/0001_initial.py similarity index 100% rename from src/magnets/migrations/0001_initial.py rename to src/apps/magnets/migrations/0001_initial.py diff --git a/src/magnets/migrations/0002_CampaignLog.py b/src/apps/magnets/migrations/0002_CampaignLog.py similarity index 100% rename from src/magnets/migrations/0002_CampaignLog.py rename to src/apps/magnets/migrations/0002_CampaignLog.py diff --git a/src/magnets/migrations/0003_CampaignSuccessMessage.py b/src/apps/magnets/migrations/0003_CampaignSuccessMessage.py similarity index 100% rename from src/magnets/migrations/0003_CampaignSuccessMessage.py rename to src/apps/magnets/migrations/0003_CampaignSuccessMessage.py diff --git a/src/chains/migrations/__init__.py b/src/apps/magnets/migrations/__init__.py similarity index 100% rename from src/chains/migrations/__init__.py rename to src/apps/magnets/migrations/__init__.py diff --git a/src/magnets/models.py b/src/apps/magnets/models.py similarity index 90% rename from src/magnets/models.py rename to src/apps/magnets/models.py index 6e1e89f830a..a30f05d293e 100644 --- a/src/magnets/models.py +++ b/src/apps/magnets/models.py @@ -1,10 +1,10 @@ from django.db.models import Count from django.utils.translation import gettext_lazy as _ -from app.models import models -from app.models import TimestampedModel -from mailing.tasks import send_mail -from users.models import User +from apps.mailing.tasks import send_mail +from apps.users.models import User +from core.models import models +from core.models import TimestampedModel class EmailLeadCampaignQuerySet(models.QuerySet): diff --git a/src/magnets/urls.py b/src/apps/magnets/urls.py similarity index 65% rename from src/magnets/urls.py rename to src/apps/magnets/urls.py index cb577e89609..149ad1973f6 100644 --- a/src/magnets/urls.py +++ b/src/apps/magnets/urls.py @@ -1,6 +1,6 @@ from django.urls import path -from magnets.api.views import EmailLeadMagnetCampaignView +from apps.magnets.api.views import EmailLeadMagnetCampaignView urlpatterns = [ path("email//", EmailLeadMagnetCampaignView.as_view()), diff --git a/src/diplomas/__init__.py b/src/apps/mailing/__init__.py similarity index 100% rename from src/diplomas/__init__.py rename to src/apps/mailing/__init__.py diff --git a/src/apps/mailing/admin/__init__.py b/src/apps/mailing/admin/__init__.py new file mode 100644 index 00000000000..de370bbff1b --- /dev/null +++ b/src/apps/mailing/admin/__init__.py @@ -0,0 +1,3 @@ +__all__ = ["PersonalEmailDomainAdmin"] + +from apps.mailing.admin.personal_email_domain import PersonalEmailDomainAdmin diff --git a/src/mailing/admin/email_configuration.py b/src/apps/mailing/admin/email_configuration.py similarity index 68% rename from src/mailing/admin/email_configuration.py rename to src/apps/mailing/admin/email_configuration.py index 62e9ea810e3..15e7c56cf69 100644 --- a/src/mailing/admin/email_configuration.py +++ b/src/apps/mailing/admin/email_configuration.py @@ -1,5 +1,5 @@ -from app.admin import StackedInline -from mailing.models import EmailConfiguration +from apps.mailing.models import EmailConfiguration +from core.admin import StackedInline class EmailConfigurationAdmin(StackedInline): diff --git a/src/apps/mailing/admin/personal_email_domain.py b/src/apps/mailing/admin/personal_email_domain.py new file mode 100644 index 00000000000..d0f5b861006 --- /dev/null +++ b/src/apps/mailing/admin/personal_email_domain.py @@ -0,0 +1,8 @@ +from apps.mailing.models import PersonalEmailDomain +from core.admin import admin +from core.admin import ModelAdmin + + +@admin.register(PersonalEmailDomain) +class PersonalEmailDomainAdmin(ModelAdmin): + list_display = ("name",) diff --git a/src/mailing/apps.py b/src/apps/mailing/apps.py similarity index 82% rename from src/mailing/apps.py rename to src/apps/mailing/apps.py index 9f00622044f..13033e602e2 100644 --- a/src/mailing/apps.py +++ b/src/apps/mailing/apps.py @@ -3,4 +3,4 @@ class MailingConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" - name = "mailing" + name = "apps.mailing" diff --git a/src/mailing/backends.py b/src/apps/mailing/backends.py similarity index 100% rename from src/mailing/backends.py rename to src/apps/mailing/backends.py diff --git a/src/mailing/configuration.py b/src/apps/mailing/configuration.py similarity index 89% rename from src/mailing/configuration.py rename to src/apps/mailing/configuration.py index 4f469816ac8..1cd65ad0b27 100644 --- a/src/mailing/configuration.py +++ b/src/apps/mailing/configuration.py @@ -3,8 +3,8 @@ from django.apps import apps if TYPE_CHECKING: - from mailing.models import EmailConfiguration - from products.models import Course + from apps.mailing.models import EmailConfiguration + from apps.products.models import Course def get_configuration(*, recipient: str) -> Optional["EmailConfiguration"]: diff --git a/src/mailing/helpers.py b/src/apps/mailing/helpers.py similarity index 100% rename from src/mailing/helpers.py rename to src/apps/mailing/helpers.py diff --git a/src/mailing/management/commands/send_test_email.py b/src/apps/mailing/management/commands/send_test_email.py similarity index 95% rename from src/mailing/management/commands/send_test_email.py rename to src/apps/mailing/management/commands/send_test_email.py index 81f58426c58..6ccbe3fef0f 100644 --- a/src/mailing/management/commands/send_test_email.py +++ b/src/apps/mailing/management/commands/send_test_email.py @@ -1,6 +1,6 @@ from django.core.management.base import BaseCommand -from mailing import tasks +from apps.mailing import tasks class Command(BaseCommand): diff --git a/src/mailing/migrations/0001_EmailLogEntryMovedToDedicatedApp.py b/src/apps/mailing/migrations/0001_EmailLogEntryMovedToDedicatedApp.py similarity index 91% rename from src/mailing/migrations/0001_EmailLogEntryMovedToDedicatedApp.py rename to src/apps/mailing/migrations/0001_EmailLogEntryMovedToDedicatedApp.py index 1caed95e80d..e8944780204 100644 --- a/src/mailing/migrations/0001_EmailLogEntryMovedToDedicatedApp.py +++ b/src/apps/mailing/migrations/0001_EmailLogEntryMovedToDedicatedApp.py @@ -11,7 +11,7 @@ def migrate_from_previous_table(apps, schema_editor): """ EmailLogEntry = apps.get_model('mailing.EmailLogEntry') - previous_entries = apps.get_model('app.EmailLogEntry').objects.values( + previous_entries = apps.get_model('core.EmailLogEntry').objects.values( 'modified', 'email', 'template_id', @@ -25,7 +25,7 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('app', '0003_RenameCoursesAppPt1'), + ('core', '0003_RenameCoursesAppPt1'), ] operations = [ diff --git a/src/mailing/migrations/0002_EmailConfiguration.py b/src/apps/mailing/migrations/0002_EmailConfiguration.py similarity index 100% rename from src/mailing/migrations/0002_EmailConfiguration.py rename to src/apps/mailing/migrations/0002_EmailConfiguration.py diff --git a/src/mailing/migrations/0003_CustomReplyTo.py b/src/apps/mailing/migrations/0003_CustomReplyTo.py similarity index 100% rename from src/mailing/migrations/0003_CustomReplyTo.py rename to src/apps/mailing/migrations/0003_CustomReplyTo.py diff --git a/src/mailing/migrations/0004_PersonalEmailDomain.py b/src/apps/mailing/migrations/0004_PersonalEmailDomain.py similarity index 100% rename from src/mailing/migrations/0004_PersonalEmailDomain.py rename to src/apps/mailing/migrations/0004_PersonalEmailDomain.py diff --git a/src/mailing/migrations/0005_MigrateIndexDefinitions.py b/src/apps/mailing/migrations/0005_MigrateIndexDefinitions.py similarity index 100% rename from src/mailing/migrations/0005_MigrateIndexDefinitions.py rename to src/apps/mailing/migrations/0005_MigrateIndexDefinitions.py diff --git a/src/diplomas/migrations/__init__.py b/src/apps/mailing/migrations/__init__.py similarity index 100% rename from src/diplomas/migrations/__init__.py rename to src/apps/mailing/migrations/__init__.py diff --git a/src/apps/mailing/models/__init__.py b/src/apps/mailing/models/__init__.py new file mode 100644 index 00000000000..1dd0487d1cc --- /dev/null +++ b/src/apps/mailing/models/__init__.py @@ -0,0 +1,10 @@ +from apps.mailing.models.configuration import EmailConfiguration +from apps.mailing.models.log_entry import EmailLogEntry + +__all__ = [ + "EmailConfiguration", + "EmailLogEntry", + "PersonalEmailDomain", +] + +from apps.mailing.models.personal_email_domain import PersonalEmailDomain diff --git a/src/mailing/models/configuration.py b/src/apps/mailing/models/configuration.py similarity index 94% rename from src/mailing/models/configuration.py rename to src/apps/mailing/models/configuration.py index 9ac566f133c..edda437100b 100644 --- a/src/mailing/models/configuration.py +++ b/src/apps/mailing/models/configuration.py @@ -1,7 +1,7 @@ from django.utils.translation import gettext_lazy as _ -from app.models import models -from app.models import TimestampedModel +from core.models import models +from core.models import TimestampedModel class EmailConfiguration(TimestampedModel): diff --git a/src/mailing/models/log_entry.py b/src/apps/mailing/models/log_entry.py similarity index 86% rename from src/mailing/models/log_entry.py rename to src/apps/mailing/models/log_entry.py index 5bd4c405b4b..0d74fe24636 100644 --- a/src/mailing/models/log_entry.py +++ b/src/apps/mailing/models/log_entry.py @@ -1,8 +1,8 @@ from django.db.models import Index from django.db.models import UniqueConstraint -from app.models import models -from app.models import TimestampedModel +from core.models import models +from core.models import TimestampedModel class EmailLogEntry(TimestampedModel): diff --git a/src/mailing/models/personal_email_domain.py b/src/apps/mailing/models/personal_email_domain.py similarity index 80% rename from src/mailing/models/personal_email_domain.py rename to src/apps/mailing/models/personal_email_domain.py index da554287081..23aeb9403fe 100644 --- a/src/mailing/models/personal_email_domain.py +++ b/src/apps/mailing/models/personal_email_domain.py @@ -1,7 +1,7 @@ from django.utils.translation import gettext_lazy as _ -from app.models import models -from app.models import TimestampedModel +from core.models import models +from core.models import TimestampedModel class PersonalEmailDomain(TimestampedModel): diff --git a/src/mailing/owl.py b/src/apps/mailing/owl.py similarity index 92% rename from src/mailing/owl.py rename to src/apps/mailing/owl.py index bea593fd43b..62e84af304d 100644 --- a/src/mailing/owl.py +++ b/src/apps/mailing/owl.py @@ -7,11 +7,11 @@ from django.core.mail.backends.base import BaseEmailBackend from django.utils.functional import cached_property -from app.services import BaseService -from mailing import helpers -from mailing.configuration import get_configuration -from mailing.models import EmailConfiguration -from mailing.models import EmailLogEntry +from apps.mailing import helpers +from apps.mailing.configuration import get_configuration +from apps.mailing.models import EmailConfiguration +from apps.mailing.models import EmailLogEntry +from core.services import BaseService @dataclass diff --git a/src/mailing/tasks.py b/src/apps/mailing/tasks.py similarity index 88% rename from src/mailing/tasks.py rename to src/apps/mailing/tasks.py index 21f3b91ed8c..a535abd119b 100644 --- a/src/mailing/tasks.py +++ b/src/apps/mailing/tasks.py @@ -1,7 +1,7 @@ from anymail.exceptions import AnymailRequestsAPIError -from app.celery import celery -from mailing.owl import Owl +from apps.mailing.owl import Owl +from core.celery import celery @celery.task( diff --git a/src/homework/__init__.py b/src/apps/notion/__init__.py similarity index 100% rename from src/homework/__init__.py rename to src/apps/notion/__init__.py diff --git a/src/notion/admin.py b/src/apps/notion/admin.py similarity index 78% rename from src/notion/admin.py rename to src/apps/notion/admin.py index 5de7ad6c261..c2d1a550d24 100644 --- a/src/notion/admin.py +++ b/src/apps/notion/admin.py @@ -2,13 +2,13 @@ from django import forms -from app.admin import admin -from app.admin import ModelAdmin -from notion import helpers -from notion.client import NotionClient -from notion.exceptions import NotionError -from notion.models import Material -from notion.models import MaterialFile +from apps.notion import helpers +from apps.notion.client import NotionClient +from apps.notion.exceptions import NotionError +from apps.notion.models import Material +from apps.notion.models import MaterialFile +from core.admin import admin +from core.admin import ModelAdmin class NotionMaterialForm(forms.ModelForm): @@ -20,7 +20,7 @@ def clean_page_id(self) -> str: return helpers.page_url_to_id(self.cleaned_data["page_id"]) def clean_title(self) -> str: - """Fetch page title from notion""" + """Fetch page title from apps.notion""" if len(self.cleaned_data["title"]) == 0 and "https://" in self.data["page_id"]: notion = NotionClient() try: diff --git a/src/notion/api/serializers.py b/src/apps/notion/api/serializers.py similarity index 84% rename from src/notion/api/serializers.py rename to src/apps/notion/api/serializers.py index b346018b8a2..2cdbfddb653 100644 --- a/src/notion/api/serializers.py +++ b/src/apps/notion/api/serializers.py @@ -1,6 +1,6 @@ from rest_framework import serializers -from notion.page import NotionPage +from apps.notion.page import NotionPage class NotionPageSerializer(serializers.Serializer): diff --git a/src/notion/api/throttling.py b/src/apps/notion/api/throttling.py similarity index 79% rename from src/notion/api/throttling.py rename to src/apps/notion/api/throttling.py index 5d7b58acd0e..3c6cdbc73fd 100644 --- a/src/notion/api/throttling.py +++ b/src/apps/notion/api/throttling.py @@ -1,6 +1,6 @@ from rest_framework.throttling import UserRateThrottle -from app.throttling import ConfigurableThrottlingMixin +from core.throttling import ConfigurableThrottlingMixin class NotionThrottle(ConfigurableThrottlingMixin, UserRateThrottle): # type: ignore diff --git a/src/notion/api/views.py b/src/apps/notion/api/views.py similarity index 80% rename from src/notion/api/views.py rename to src/apps/notion/api/views.py index a596eeff515..b18ac544e84 100644 --- a/src/notion/api/views.py +++ b/src/apps/notion/api/views.py @@ -6,12 +6,12 @@ from django.db.models import QuerySet -from app.views import AuthenticatedAPIView -from notion.api.serializers import NotionPageSerializer -from notion.api.throttling import NotionThrottle -from notion.cache import get_cached_page -from notion.helpers import uuid_to_id -from notion.models import Material +from apps.notion.api.serializers import NotionPageSerializer +from apps.notion.api.throttling import NotionThrottle +from apps.notion.cache import get_cached_page +from apps.notion.helpers import uuid_to_id +from apps.notion.models import Material +from core.views import AuthenticatedAPIView class NotionMaterialView(AuthenticatedAPIView): diff --git a/src/notion/apps.py b/src/apps/notion/apps.py similarity index 83% rename from src/notion/apps.py rename to src/apps/notion/apps.py index 50904a16318..94427638c67 100644 --- a/src/notion/apps.py +++ b/src/apps/notion/apps.py @@ -3,4 +3,4 @@ class NotionConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" - name = "notion" + name = "apps.notion" diff --git a/src/notion/block.py b/src/apps/notion/block.py similarity index 95% rename from src/notion/block.py rename to src/apps/notion/block.py index df415dfc1a3..86a9a90fe65 100644 --- a/src/notion/block.py +++ b/src/apps/notion/block.py @@ -3,9 +3,9 @@ from dataclasses import dataclass from typing import Generator -from notion.rewrite import rewrite -from notion.types import BlockData -from notion.types import BlockId +from apps.notion.rewrite import rewrite +from apps.notion.types import BlockData +from apps.notion.types import BlockId @dataclass diff --git a/src/notion/cache.py b/src/apps/notion/cache.py similarity index 92% rename from src/notion/cache.py rename to src/apps/notion/cache.py index 1bf007b293a..3121c21b81d 100644 --- a/src/notion/cache.py +++ b/src/apps/notion/cache.py @@ -5,10 +5,10 @@ from django.conf import settings from django.utils import timezone -from app.current_user import get_current_user -from notion.client import NotionClient -from notion.models import NotionCacheEntry -from notion.page import NotionPage +from apps.notion.client import NotionClient +from apps.notion.models import NotionCacheEntry +from apps.notion.page import NotionPage +from core.current_user import get_current_user TIMEOUT = 60 * 60 * 24 * 365 * 5 # 5 years diff --git a/src/notion/client.py b/src/apps/notion/client.py similarity index 93% rename from src/notion/client.py rename to src/apps/notion/client.py index c6d46fb41e3..328d6bfb0b9 100644 --- a/src/notion/client.py +++ b/src/apps/notion/client.py @@ -5,11 +5,11 @@ from django.conf import settings -from notion.block import NotionBlockList -from notion.exceptions import HTTPError -from notion.helpers import id_to_uuid -from notion.page import NotionPage -from notion.types import BlockId +from apps.notion.block import NotionBlockList +from apps.notion.exceptions import HTTPError +from apps.notion.helpers import id_to_uuid +from apps.notion.page import NotionPage +from apps.notion.types import BlockId class NotionClient: diff --git a/src/notion/exceptions.py b/src/apps/notion/exceptions.py similarity index 100% rename from src/notion/exceptions.py rename to src/apps/notion/exceptions.py diff --git a/src/notion/helpers.py b/src/apps/notion/helpers.py similarity index 87% rename from src/notion/helpers.py rename to src/apps/notion/helpers.py index 2349b9bfdd5..e3c7f73c492 100644 --- a/src/notion/helpers.py +++ b/src/apps/notion/helpers.py @@ -1,11 +1,11 @@ from os.path import basename from urllib.parse import urlparse -from notion.types import BlockId +from apps.notion.types import BlockId def page_url_to_id(page_url: str) -> BlockId: - """Get page id from notion.so URL""" + """Get page id from apps.notion.so URL""" url_path = urlparse(page_url).path if url_path.endswith("/"): diff --git a/src/notion/management/commands/update_notion_cache.py b/src/apps/notion/management/commands/update_notion_cache.py similarity index 93% rename from src/notion/management/commands/update_notion_cache.py rename to src/apps/notion/management/commands/update_notion_cache.py index 87718b8418a..fc034611a36 100644 --- a/src/notion/management/commands/update_notion_cache.py +++ b/src/apps/notion/management/commands/update_notion_cache.py @@ -2,7 +2,7 @@ from django.core.management.base import BaseCommand -from notion import tasks +from apps.notion import tasks class Command(BaseCommand): diff --git a/src/notion/migrations/0001_initial.py b/src/apps/notion/migrations/0001_initial.py similarity index 93% rename from src/notion/migrations/0001_initial.py rename to src/apps/notion/migrations/0001_initial.py index 1e593a91390..a2afbc07664 100644 --- a/src/notion/migrations/0001_initial.py +++ b/src/apps/notion/migrations/0001_initial.py @@ -20,7 +20,7 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created', models.DateTimeField(auto_now_add=True, db_index=True)), ('modified', models.DateTimeField(blank=True, db_index=True, null=True)), - ('page_id', models.CharField(db_index=True, help_text='Paste it from notion address bar', max_length=64, verbose_name='Notion page id')), + ('page_id', models.CharField(db_index=True, help_text='Paste it from apps.notion address bar', max_length=64, verbose_name='Notion page id')), ('active', models.BooleanField(default=True, verbose_name='Active')), ('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='products.course')), ], diff --git a/src/notion/migrations/0002_NotionaMaterialTitle.py b/src/apps/notion/migrations/0002_NotionaMaterialTitle.py similarity index 100% rename from src/notion/migrations/0002_NotionaMaterialTitle.py rename to src/apps/notion/migrations/0002_NotionaMaterialTitle.py diff --git a/src/notion/migrations/0003_HomePageMaterial.py b/src/apps/notion/migrations/0003_HomePageMaterial.py similarity index 100% rename from src/notion/migrations/0003_HomePageMaterial.py rename to src/apps/notion/migrations/0003_HomePageMaterial.py diff --git a/src/notion/migrations/0004_NotionMaterialSlug.py b/src/apps/notion/migrations/0004_NotionMaterialSlug.py similarity index 100% rename from src/notion/migrations/0004_NotionMaterialSlug.py rename to src/apps/notion/migrations/0004_NotionMaterialSlug.py diff --git a/src/notion/migrations/0005_MaterailFiles.py b/src/apps/notion/migrations/0005_MaterailFiles.py similarity index 100% rename from src/notion/migrations/0005_MaterailFiles.py rename to src/apps/notion/migrations/0005_MaterailFiles.py diff --git a/src/notion/migrations/0006_NotionCacheEntry.py b/src/apps/notion/migrations/0006_NotionCacheEntry.py similarity index 100% rename from src/notion/migrations/0006_NotionCacheEntry.py rename to src/apps/notion/migrations/0006_NotionCacheEntry.py diff --git a/src/homework/migrations/__init__.py b/src/apps/notion/migrations/__init__.py similarity index 100% rename from src/homework/migrations/__init__.py rename to src/apps/notion/migrations/__init__.py diff --git a/src/notion/models.py b/src/apps/notion/models.py similarity index 93% rename from src/notion/models.py rename to src/apps/notion/models.py index d9034a92e6b..510f015473c 100644 --- a/src/notion/models.py +++ b/src/apps/notion/models.py @@ -12,10 +12,10 @@ from django.utils import timezone from django.utils.translation import gettext_lazy as _ -from app.models import models -from app.models import TimestampedModel -from notion.helpers import uuid_to_id -from users.models import User +from apps.notion.helpers import uuid_to_id +from apps.users.models import User +from core.models import models +from core.models import TimestampedModel class MaterialQuerySet(QuerySet): @@ -48,7 +48,7 @@ class Material(TimestampedModel): title = models.CharField(_("Page title"), max_length=128, blank=True, help_text=_("Will be fetched automatically if empty")) course = models.ForeignKey("products.Course", on_delete=models.CASCADE) - page_id = models.CharField(_("Notion page id"), max_length=64, db_index=True, help_text=_("Paste it from notion address bar")) + page_id = models.CharField(_("Notion page id"), max_length=64, db_index=True, help_text=_("Paste it from apps.notion address bar")) active = models.BooleanField(_("Active"), default=True) is_home_page = models.BooleanField(_("Is home page of the course"), default=False) diff --git a/src/notion/page.py b/src/apps/notion/page.py similarity index 85% rename from src/notion/page.py rename to src/apps/notion/page.py index bec15881d14..7447e1dca56 100644 --- a/src/notion/page.py +++ b/src/apps/notion/page.py @@ -1,10 +1,10 @@ import contextlib from dataclasses import dataclass -from notion.block import NotionBlock -from notion.block import NotionBlockList -from notion.exceptions import NotionResponseError -from notion.exceptions import NotSharedForWeb +from apps.notion.block import NotionBlock +from apps.notion.block import NotionBlockList +from apps.notion.exceptions import NotionResponseError +from apps.notion.exceptions import NotSharedForWeb @dataclass diff --git a/src/notion/rewrite.py b/src/apps/notion/rewrite.py similarity index 88% rename from src/notion/rewrite.py rename to src/apps/notion/rewrite.py index a7c88194011..a318f5fe699 100644 --- a/src/notion/rewrite.py +++ b/src/apps/notion/rewrite.py @@ -2,11 +2,11 @@ from functools import lru_cache from typing import Mapping -from notion.helpers import uuid_to_id -from notion.models import Material -from notion.types import BlockData -from notion.types import BlockId -from notion.types import TextProperty +from apps.notion.helpers import uuid_to_id +from apps.notion.models import Material +from apps.notion.types import BlockData +from apps.notion.types import BlockId +from apps.notion.types import TextProperty @lru_cache diff --git a/src/notion/tasks.py b/src/apps/notion/tasks.py similarity index 74% rename from src/notion/tasks.py rename to src/apps/notion/tasks.py index 92fc37690b8..f15ba4f2075 100644 --- a/src/notion/tasks.py +++ b/src/apps/notion/tasks.py @@ -1,7 +1,7 @@ -from app.celery import celery -from notion.cache import cache -from notion.client import NotionClient -from notion.models import Material +from apps.notion.cache import cache +from apps.notion.client import NotionClient +from apps.notion.models import Material +from core.celery import celery @celery.task(rate_limit="6/m", acks_late=True) diff --git a/src/notion/types.py b/src/apps/notion/types.py similarity index 100% rename from src/notion/types.py rename to src/apps/notion/types.py diff --git a/src/notion/urls.py b/src/apps/notion/urls.py similarity index 78% rename from src/notion/urls.py rename to src/apps/notion/urls.py index a94703bddc6..b8d371bc8f5 100644 --- a/src/notion/urls.py +++ b/src/apps/notion/urls.py @@ -1,6 +1,6 @@ from django.urls import path -from notion.api import views +from apps.notion.api import views urlpatterns = [ path("materials//", views.NotionMaterialView.as_view()), diff --git a/src/magnets/__init__.py b/src/apps/orders/__init__.py similarity index 100% rename from src/magnets/__init__.py rename to src/apps/orders/__init__.py diff --git a/src/apps/orders/admin/__init__.py b/src/apps/orders/admin/__init__.py new file mode 100644 index 00000000000..c304479859a --- /dev/null +++ b/src/apps/orders/admin/__init__.py @@ -0,0 +1,2 @@ +import apps.orders.admin.orders.admin # noqa +import apps.orders.admin.promocodes.admin # noqa diff --git a/src/orders/admin/orders/actions.py b/src/apps/orders/admin/orders/actions.py similarity index 94% rename from src/orders/admin/orders/actions.py rename to src/apps/orders/admin/orders/actions.py index 15559d810c3..992d2f5da34 100644 --- a/src/orders/admin/orders/actions.py +++ b/src/apps/orders/admin/orders/actions.py @@ -7,11 +7,11 @@ from django.http.request import HttpRequest from django.utils.translation import gettext as _ -from app.admin import admin -from orders import tasks -from orders.admin.orders.throttling import OrderRefundActionThrottle -from orders.models import Order -from studying.models import Study +from apps.orders import tasks +from apps.orders.admin.orders.throttling import OrderRefundActionThrottle +from apps.orders.models import Order +from apps.studying.models import Study +from core.admin import admin def format_orders_for_message(orders: list[Order]) -> str: diff --git a/src/orders/admin/orders/admin.py b/src/apps/orders/admin/orders/admin.py similarity index 88% rename from src/orders/admin/orders/admin.py rename to src/apps/orders/admin/orders/admin.py index 4d054af6308..b91c8f04a99 100644 --- a/src/orders/admin/orders/admin.py +++ b/src/apps/orders/admin/orders/admin.py @@ -5,16 +5,16 @@ from django.utils.safestring import mark_safe from django.utils.translation import gettext as _ -from app.admin import admin -from app.admin import ModelAdmin -from app.pricing import format_price -from orders import human_readable -from orders.admin.orders import actions -from orders.admin.orders.filters import OrderStatusFilter -from orders.admin.orders.forms import OrderAddForm -from orders.admin.orders.forms import OrderChangeForm -from orders.models import Order -from users.models import Student +from apps.orders import human_readable +from apps.orders.admin.orders import actions +from apps.orders.admin.orders.filters import OrderStatusFilter +from apps.orders.admin.orders.forms import OrderAddForm +from apps.orders.admin.orders.forms import OrderChangeForm +from apps.orders.models import Order +from apps.users.models import Student +from core.admin import admin +from core.admin import ModelAdmin +from core.pricing import format_price @admin.register(Order) diff --git a/src/orders/admin/orders/filters.py b/src/apps/orders/admin/orders/filters.py similarity index 94% rename from src/orders/admin/orders/filters.py rename to src/apps/orders/admin/orders/filters.py index be53e393a98..fbeebd599f6 100644 --- a/src/orders/admin/orders/filters.py +++ b/src/apps/orders/admin/orders/filters.py @@ -5,8 +5,8 @@ from django.utils.translation import gettext_lazy as _ from django.utils.translation import pgettext_lazy -from app.admin import admin -from orders.models import Order +from apps.orders.models import Order +from core.admin import admin class OrderStatusFilter(admin.SimpleListFilter): diff --git a/src/orders/admin/orders/forms.py b/src/apps/orders/admin/orders/forms.py similarity index 94% rename from src/orders/admin/orders/forms.py rename to src/apps/orders/admin/orders/forms.py index 5aacdbf7db2..5eacf13fe66 100644 --- a/src/orders/admin/orders/forms.py +++ b/src/apps/orders/admin/orders/forms.py @@ -3,9 +3,9 @@ from django import forms from django.utils.translation import gettext_lazy as _ -from orders.models import Order -from orders.services import OrderCreator -from orders.services import OrderEmailChanger +from apps.orders.models import Order +from apps.orders.services import OrderCreator +from apps.orders.services import OrderEmailChanger class OrderChangeForm(forms.ModelForm): diff --git a/src/orders/admin/orders/throttling.py b/src/apps/orders/admin/orders/throttling.py similarity index 80% rename from src/orders/admin/orders/throttling.py rename to src/apps/orders/admin/orders/throttling.py index c4d126acdcd..9fd84acec29 100644 --- a/src/orders/admin/orders/throttling.py +++ b/src/apps/orders/admin/orders/throttling.py @@ -1,6 +1,6 @@ from rest_framework.throttling import UserRateThrottle -from app.throttling import ConfigurableThrottlingMixin +from core.throttling import ConfigurableThrottlingMixin class OrderRefundActionThrottle(ConfigurableThrottlingMixin, UserRateThrottle): # type: ignore diff --git a/src/orders/admin/promocodes/actions.py b/src/apps/orders/admin/promocodes/actions.py similarity index 92% rename from src/orders/admin/promocodes/actions.py rename to src/apps/orders/admin/promocodes/actions.py index 4b58b8214fd..0955b558c6f 100644 --- a/src/orders/admin/promocodes/actions.py +++ b/src/apps/orders/admin/promocodes/actions.py @@ -4,7 +4,7 @@ from django.http.request import HttpRequest from django.utils.translation import gettext_lazy as _ -from app.admin import admin +from core.admin import admin @admin.action(description=_("Deactivate selected promo codes")) diff --git a/src/orders/admin/promocodes/admin.py b/src/apps/orders/admin/promocodes/admin.py similarity index 88% rename from src/orders/admin/promocodes/admin.py rename to src/apps/orders/admin/promocodes/admin.py index 6fa58489ab8..7583e28ad45 100644 --- a/src/orders/admin/promocodes/admin.py +++ b/src/apps/orders/admin/promocodes/admin.py @@ -4,12 +4,12 @@ from django.utils import timezone from django.utils.translation import gettext as _ -from app.admin import admin -from app.admin import ModelAdmin -from app.admin.filters import DefaultTrueBooleanFilter -from orders.admin.promocodes import actions -from orders.models import PromoCode -from orders.models.promocode import PromoCodeQuerySet +from apps.orders.admin.promocodes import actions +from apps.orders.models import PromoCode +from apps.orders.models.promocode import PromoCodeQuerySet +from core.admin import admin +from core.admin import ModelAdmin +from core.admin.filters import DefaultTrueBooleanFilter class PromodeActiveFilter(DefaultTrueBooleanFilter): diff --git a/src/orders/api/serializers.py b/src/apps/orders/api/serializers.py similarity index 100% rename from src/orders/api/serializers.py rename to src/apps/orders/api/serializers.py diff --git a/src/orders/api/throttling.py b/src/apps/orders/api/throttling.py similarity index 83% rename from src/orders/api/throttling.py rename to src/apps/orders/api/throttling.py index 69df5b96517..0eda3c43159 100644 --- a/src/orders/api/throttling.py +++ b/src/apps/orders/api/throttling.py @@ -1,6 +1,6 @@ from rest_framework.throttling import AnonRateThrottle -from app.throttling import ConfigurableThrottlingMixin +from core.throttling import ConfigurableThrottlingMixin class PromocodeThrottle(ConfigurableThrottlingMixin, AnonRateThrottle): # type: ignore diff --git a/src/orders/api/views.py b/src/apps/orders/api/views.py similarity index 89% rename from src/orders/api/views.py rename to src/apps/orders/api/views.py index 901629bb657..948b75ba574 100644 --- a/src/orders/api/views.py +++ b/src/apps/orders/api/views.py @@ -6,8 +6,8 @@ from django.http import HttpResponseRedirect -from app.throttling import PublicIDThrottle -from orders.models import Order +from apps.orders.models import Order +from core.throttling import PublicIDThrottle class OrderConfirmationView(RetrieveAPIView): diff --git a/src/orders/apps.py b/src/apps/orders/apps.py similarity index 55% rename from src/orders/apps.py rename to src/apps/orders/apps.py index 26cfbaabdb0..51ff3988881 100644 --- a/src/orders/apps.py +++ b/src/apps/orders/apps.py @@ -2,7 +2,7 @@ class OrdersConfig(AppConfig): - name = "orders" + name = "apps.orders" def ready(self) -> None: - import orders.signals.handlers # noqa + import apps.orders.signals.handlers # noqa diff --git a/src/orders/exceptions.py b/src/apps/orders/exceptions.py similarity index 100% rename from src/orders/exceptions.py rename to src/apps/orders/exceptions.py diff --git a/src/orders/fields.py b/src/apps/orders/fields.py similarity index 92% rename from src/orders/fields.py rename to src/apps/orders/fields.py index 3f6a5d48444..55bc62341c7 100644 --- a/src/orders/fields.py +++ b/src/apps/orders/fields.py @@ -1,6 +1,6 @@ from typing import Any -from app.models import models +from core.models import models class ItemField(models.ForeignKey): diff --git a/src/orders/human_readable.py b/src/apps/orders/human_readable.py similarity index 93% rename from src/orders/human_readable.py rename to src/apps/orders/human_readable.py index 3ab9a9de0ac..5be03daccb0 100644 --- a/src/orders/human_readable.py +++ b/src/apps/orders/human_readable.py @@ -1,8 +1,8 @@ from django.utils.html import format_html from django.utils.translation import gettext as _ -from banking.selector import get_bank -from orders.models import Order +from apps.banking.selector import get_bank +from apps.orders.models import Order def get_order_payment_method_name(order: Order) -> str: diff --git a/src/orders/migrations/0001_initial.py b/src/apps/orders/migrations/0001_initial.py similarity index 79% rename from src/orders/migrations/0001_initial.py rename to src/apps/orders/migrations/0001_initial.py index a3ec711efd6..9080fbd7b4f 100644 --- a/src/orders/migrations/0001_initial.py +++ b/src/apps/orders/migrations/0001_initial.py @@ -5,8 +5,8 @@ from django.db import models import django.db.models.deletion -import orders.fields -import orders.models +import apps.orders.fields +import apps.orders.models class Migration(migrations.Migration): @@ -28,8 +28,8 @@ class Migration(migrations.Migration): ('price', models.DecimalField(decimal_places=2, max_digits=9)), ('paid', models.DateTimeField('Date when order got paid', null=True, blank=True, help_text='If set during creation, order automaticaly gets shipped')), ('shipped', models.DateTimeField('Date when order was shipped', null=True, blank=True)), - ('course', orders.fields.ItemField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='products.Course')), - ('record', orders.fields.ItemField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='products.Record')), + ('course', apps.orders.fields.ItemField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='products.Course')), + ('record', apps.orders.fields.ItemField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='products.Record')), ('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), ], options={ diff --git a/src/orders/migrations/0002_L18N.py b/src/apps/orders/migrations/0002_L18N.py similarity index 100% rename from src/orders/migrations/0002_L18N.py rename to src/apps/orders/migrations/0002_L18N.py diff --git a/src/orders/migrations/0003_OrderBundles.py b/src/apps/orders/migrations/0003_OrderBundles.py similarity index 66% rename from src/orders/migrations/0003_OrderBundles.py rename to src/apps/orders/migrations/0003_OrderBundles.py index 6138d2df2b0..ae5849dcf3b 100644 --- a/src/orders/migrations/0003_OrderBundles.py +++ b/src/apps/orders/migrations/0003_OrderBundles.py @@ -3,8 +3,8 @@ from django.db import migrations import django.db.models.deletion -import orders.fields -import orders.models +import apps.orders.fields +import apps.orders.models class Migration(migrations.Migration): @@ -18,6 +18,6 @@ class Migration(migrations.Migration): migrations.AddField( model_name='order', name='bundle', - field=orders.fields.ItemField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='products.Bundle'), + field=apps.orders.fields.ItemField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='products.Bundle'), ), ] diff --git a/src/orders/migrations/0004_PromoCodes.py b/src/apps/orders/migrations/0004_PromoCodes.py similarity index 100% rename from src/orders/migrations/0004_PromoCodes.py rename to src/apps/orders/migrations/0004_PromoCodes.py diff --git a/src/orders/migrations/0005_PromoCodesActiveByDefault.py b/src/apps/orders/migrations/0005_PromoCodesActiveByDefault.py similarity index 100% rename from src/orders/migrations/0005_PromoCodesActiveByDefault.py rename to src/apps/orders/migrations/0005_PromoCodesActiveByDefault.py diff --git a/src/orders/migrations/0006_PromoCodeComments.py b/src/apps/orders/migrations/0006_PromoCodeComments.py similarity index 100% rename from src/orders/migrations/0006_PromoCodeComments.py rename to src/apps/orders/migrations/0006_PromoCodeComments.py diff --git a/src/orders/migrations/0007_OrderPromoCodes.py b/src/apps/orders/migrations/0007_OrderPromoCodes.py similarity index 100% rename from src/orders/migrations/0007_OrderPromoCodes.py rename to src/apps/orders/migrations/0007_OrderPromoCodes.py diff --git a/src/orders/migrations/0008_PromocodesI18n.py b/src/apps/orders/migrations/0008_PromocodesI18n.py similarity index 100% rename from src/orders/migrations/0008_PromocodesI18n.py rename to src/apps/orders/migrations/0008_PromocodesI18n.py diff --git a/src/orders/migrations/0009_Gifts.py b/src/apps/orders/migrations/0009_Gifts.py similarity index 100% rename from src/orders/migrations/0009_Gifts.py rename to src/apps/orders/migrations/0009_Gifts.py diff --git a/src/orders/migrations/0010_OrderI18n.py b/src/apps/orders/migrations/0010_OrderI18n.py similarity index 76% rename from src/orders/migrations/0010_OrderI18n.py rename to src/apps/orders/migrations/0010_OrderI18n.py index 13418abfec4..93e7d5987ff 100644 --- a/src/orders/migrations/0010_OrderI18n.py +++ b/src/apps/orders/migrations/0010_OrderI18n.py @@ -5,7 +5,7 @@ from django.db import models import django.db.models.deletion -import orders.fields +import apps.orders.fields class Migration(migrations.Migration): @@ -20,12 +20,12 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='order', name='bundle', - field=orders.fields.ItemField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='products.bundle', verbose_name='Bundle'), + field=apps.orders.fields.ItemField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='products.bundle', verbose_name='Bundle'), ), migrations.AlterField( model_name='order', name='course', - field=orders.fields.ItemField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='products.course', verbose_name='Course'), + field=apps.orders.fields.ItemField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='products.course', verbose_name='Course'), ), migrations.AlterField( model_name='order', @@ -45,7 +45,7 @@ class Migration(migrations.Migration): migrations.AlterField( model_name='order', name='record', - field=orders.fields.ItemField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='products.record', verbose_name='Record'), + field=apps.orders.fields.ItemField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='products.record', verbose_name='Record'), ), migrations.AlterField( model_name='order', diff --git a/src/orders/migrations/0011_NotificationToGiverIsSent.py b/src/apps/orders/migrations/0011_NotificationToGiverIsSent.py similarity index 100% rename from src/orders/migrations/0011_NotificationToGiverIsSent.py rename to src/apps/orders/migrations/0011_NotificationToGiverIsSent.py diff --git a/src/orders/migrations/0012_DesiredBankString.py b/src/apps/orders/migrations/0012_DesiredBankString.py similarity index 100% rename from src/orders/migrations/0012_DesiredBankString.py rename to src/apps/orders/migrations/0012_DesiredBankString.py diff --git a/src/orders/migrations/0013_PerProductPromoCodes.py b/src/apps/orders/migrations/0013_PerProductPromoCodes.py similarity index 100% rename from src/orders/migrations/0013_PerProductPromoCodes.py rename to src/apps/orders/migrations/0013_PerProductPromoCodes.py diff --git a/src/orders/migrations/0014_NonAttachedPromocodes.py b/src/apps/orders/migrations/0014_NonAttachedPromocodes.py similarity index 100% rename from src/orders/migrations/0014_NonAttachedPromocodes.py rename to src/apps/orders/migrations/0014_NonAttachedPromocodes.py diff --git a/src/orders/migrations/0015_PromoCodeValue.py b/src/apps/orders/migrations/0015_PromoCodeValue.py similarity index 100% rename from src/orders/migrations/0015_PromoCodeValue.py rename to src/apps/orders/migrations/0015_PromoCodeValue.py diff --git a/src/orders/migrations/0016_UnpaidDate.py b/src/apps/orders/migrations/0016_UnpaidDate.py similarity index 100% rename from src/orders/migrations/0016_UnpaidDate.py rename to src/apps/orders/migrations/0016_UnpaidDate.py diff --git a/src/orders/migrations/0017_OrderPermissions.py b/src/apps/orders/migrations/0017_OrderPermissions.py similarity index 100% rename from src/orders/migrations/0017_OrderPermissions.py rename to src/apps/orders/migrations/0017_OrderPermissions.py diff --git a/src/orders/migrations/0018_StudentProxyModel.py b/src/apps/orders/migrations/0018_StudentProxyModel.py similarity index 100% rename from src/orders/migrations/0018_StudentProxyModel.py rename to src/apps/orders/migrations/0018_StudentProxyModel.py diff --git a/src/orders/migrations/0019_OrderAuthor.py b/src/apps/orders/migrations/0019_OrderAuthor.py similarity index 100% rename from src/orders/migrations/0019_OrderAuthor.py rename to src/apps/orders/migrations/0019_OrderAuthor.py diff --git a/src/orders/migrations/0020_OrderAuthorMigrationFix.py b/src/apps/orders/migrations/0020_OrderAuthorMigrationFix.py similarity index 100% rename from src/orders/migrations/0020_OrderAuthorMigrationFix.py rename to src/apps/orders/migrations/0020_OrderAuthorMigrationFix.py diff --git a/src/orders/migrations/0021_OrderConstraintForProductItemsCountCheck.py b/src/apps/orders/migrations/0021_OrderConstraintForProductItemsCountCheck.py similarity index 100% rename from src/orders/migrations/0021_OrderConstraintForProductItemsCountCheck.py rename to src/apps/orders/migrations/0021_OrderConstraintForProductItemsCountCheck.py diff --git a/src/orders/migrations/0022_PurchaseTimeUERate.py b/src/apps/orders/migrations/0022_PurchaseTimeUERate.py similarity index 100% rename from src/orders/migrations/0022_PurchaseTimeUERate.py rename to src/apps/orders/migrations/0022_PurchaseTimeUERate.py diff --git a/src/orders/migrations/0023_AcquringPercent.py b/src/apps/orders/migrations/0023_AcquringPercent.py similarity index 100% rename from src/orders/migrations/0023_AcquringPercent.py rename to src/apps/orders/migrations/0023_AcquringPercent.py diff --git a/src/orders/migrations/0024_OrderSlugs.py b/src/apps/orders/migrations/0024_OrderSlugs.py similarity index 100% rename from src/orders/migrations/0024_OrderSlugs.py rename to src/apps/orders/migrations/0024_OrderSlugs.py diff --git a/src/orders/migrations/0025_BankFieldRename.py b/src/apps/orders/migrations/0025_BankFieldRename.py similarity index 100% rename from src/orders/migrations/0025_BankFieldRename.py rename to src/apps/orders/migrations/0025_BankFieldRename.py diff --git a/src/orders/migrations/0026_PromocodeExpiration.py b/src/apps/orders/migrations/0026_PromocodeExpiration.py similarity index 100% rename from src/orders/migrations/0026_PromocodeExpiration.py rename to src/apps/orders/migrations/0026_PromocodeExpiration.py diff --git a/src/orders/migrations/0027_PromocodeDestinationField.py b/src/apps/orders/migrations/0027_PromocodeDestinationField.py similarity index 100% rename from src/orders/migrations/0027_PromocodeDestinationField.py rename to src/apps/orders/migrations/0027_PromocodeDestinationField.py diff --git a/src/orders/migrations/0028_PromocodeExpiresFieldTranslation.py b/src/apps/orders/migrations/0028_PromocodeExpiresFieldTranslation.py similarity index 100% rename from src/orders/migrations/0028_PromocodeExpiresFieldTranslation.py rename to src/apps/orders/migrations/0028_PromocodeExpiresFieldTranslation.py diff --git a/src/orders/migrations/0029_DropGiftFields.py b/src/apps/orders/migrations/0029_DropGiftFields.py similarity index 100% rename from src/orders/migrations/0029_DropGiftFields.py rename to src/apps/orders/migrations/0029_DropGiftFields.py diff --git a/src/orders/migrations/0030_Add_lead_and_transaction_to_Order.py b/src/apps/orders/migrations/0030_Add_lead_and_transaction_to_Order.py similarity index 100% rename from src/orders/migrations/0030_Add_lead_and_transaction_to_Order.py rename to src/apps/orders/migrations/0030_Add_lead_and_transaction_to_Order.py diff --git a/src/orders/migrations/0031_Drop_o2o_properties_from_amocrm_lead_and_transaction.py b/src/apps/orders/migrations/0031_Drop_o2o_properties_from_amocrm_lead_and_transaction.py similarity index 100% rename from src/orders/migrations/0031_Drop_o2o_properties_from_amocrm_lead_and_transaction.py rename to src/apps/orders/migrations/0031_Drop_o2o_properties_from_amocrm_lead_and_transaction.py diff --git a/src/orders/migrations/0032_order_set_bank_choices.py b/src/apps/orders/migrations/0032_order_set_bank_choices.py similarity index 100% rename from src/orders/migrations/0032_order_set_bank_choices.py rename to src/apps/orders/migrations/0032_order_set_bank_choices.py diff --git a/src/magnets/migrations/__init__.py b/src/apps/orders/migrations/__init__.py similarity index 100% rename from src/magnets/migrations/__init__.py rename to src/apps/orders/migrations/__init__.py diff --git a/src/apps/orders/models/__init__.py b/src/apps/orders/models/__init__.py new file mode 100644 index 00000000000..c054d533322 --- /dev/null +++ b/src/apps/orders/models/__init__.py @@ -0,0 +1,7 @@ +from apps.orders.models.order import Order +from apps.orders.models.promocode import PromoCode + +__all__ = [ + "Order", + "PromoCode", +] diff --git a/src/orders/models/order.py b/src/apps/orders/models/order.py similarity index 91% rename from src/orders/models/order.py rename to src/apps/orders/models/order.py index a050069b89b..862ba69e90b 100644 --- a/src/orders/models/order.py +++ b/src/apps/orders/models/order.py @@ -7,13 +7,13 @@ from django.utils.translation import gettext_lazy as _ from django.utils.translation import pgettext_lazy -from app.models import models -from app.models import only_one_or_zero_is_set -from app.models import TimestampedModel -from banking.selector import BANK_CHOICES -from orders.exceptions import UnknownItemException -from orders.fields import ItemField -from products.models import Product +from apps.banking.selector import BANK_CHOICES +from apps.orders.exceptions import UnknownItemException +from apps.orders.fields import ItemField +from apps.products.models import Product +from core.models import models +from core.models import only_one_or_zero_is_set +from core.models import TimestampedModel class OrderQuerySet(QuerySet): @@ -128,17 +128,17 @@ def set_item(self, item: Product) -> None: raise UnknownItemException(f"There is no foreignKey for {item.__class__}") def set_paid(self, silent: bool | None = False) -> None: - from orders.services import OrderPaidSetter + from apps.orders.services import OrderPaidSetter OrderPaidSetter(self, silent=silent)() def refund(self) -> None: - from orders.services import OrderRefunder + from apps.orders.services import OrderRefunder OrderRefunder(self)() def ship(self, silent: bool | None = False) -> None: - from orders.services import OrderShipper + from apps.orders.services import OrderShipper OrderShipper(self, silent=silent)() @@ -150,6 +150,6 @@ def ship_without_payment(self) -> bool: return False def unship(self) -> None: - from orders.services import OrderUnshipper + from apps.orders.services import OrderUnshipper OrderUnshipper(self)() diff --git a/src/orders/models/promocode.py b/src/apps/orders/models/promocode.py similarity index 96% rename from src/orders/models/promocode.py rename to src/apps/orders/models/promocode.py index ef53643217f..a9cf0ff1b87 100644 --- a/src/orders/models/promocode.py +++ b/src/apps/orders/models/promocode.py @@ -12,9 +12,9 @@ from django.utils import timezone from django.utils.translation import gettext_lazy as _ -from app.models import models -from app.models import TimestampedModel -from products.models import Course +from apps.products.models import Course +from core.models import models +from core.models import TimestampedModel class PromoCodeQuerySet(QuerySet): diff --git a/src/apps/orders/services/__init__.py b/src/apps/orders/services/__init__.py new file mode 100644 index 00000000000..8429d4d3c2d --- /dev/null +++ b/src/apps/orders/services/__init__.py @@ -0,0 +1,17 @@ +from apps.orders.services.order_creator import OrderCreator +from apps.orders.services.order_diploma_generator import OrderDiplomaGenerator +from apps.orders.services.order_email_changer import OrderEmailChanger +from apps.orders.services.order_paid_setter import OrderPaidSetter +from apps.orders.services.order_refunder import OrderRefunder +from apps.orders.services.order_shipper import OrderShipper +from apps.orders.services.order_unshipper import OrderUnshipper + +__all__ = [ + "OrderCreator", + "OrderDiplomaGenerator", + "OrderEmailChanger", + "OrderPaidSetter", + "OrderShipper", + "OrderUnshipper", + "OrderRefunder", +] diff --git a/src/orders/services/order_creator.py b/src/apps/orders/services/order_creator.py similarity index 86% rename from src/orders/services/order_creator.py rename to src/apps/orders/services/order_creator.py index 958cd2eb766..ff58a7039cb 100644 --- a/src/orders/services/order_creator.py +++ b/src/apps/orders/services/order_creator.py @@ -13,21 +13,21 @@ from django.utils.timezone import is_naive from django.utils.timezone import make_aware -from amocrm.tasks import amocrm_enabled -from amocrm.tasks import push_order -from amocrm.tasks import push_user -from app.current_user import get_current_user -from app.exceptions import AppServiceException -from app.helpers import lower_first -from app.services import BaseService -from banking.base import Bank -from banking.selector import get_bank -from mailing.tasks import send_mail -from orders.models import Order -from orders.models import PromoCode -from products.models.base import Shippable -from users.models import User -from users.tasks import rebuild_tags +from apps.amocrm.tasks import amocrm_enabled +from apps.amocrm.tasks import push_order +from apps.amocrm.tasks import push_user +from apps.banking.base import Bank +from apps.banking.selector import get_bank +from apps.mailing.tasks import send_mail +from apps.orders.models import Order +from apps.orders.models import PromoCode +from apps.products.models.base import Shippable +from apps.users.models import User +from apps.users.tasks import rebuild_tags +from core.current_user import get_current_user +from core.exceptions import AppServiceException +from core.helpers import lower_first +from core.services import BaseService class OrderCreatorException(AppServiceException): diff --git a/src/orders/services/order_diploma_generator.py b/src/apps/orders/services/order_diploma_generator.py similarity index 78% rename from src/orders/services/order_diploma_generator.py rename to src/apps/orders/services/order_diploma_generator.py index 8e4ada8978b..49c3ee264a1 100644 --- a/src/orders/services/order_diploma_generator.py +++ b/src/apps/orders/services/order_diploma_generator.py @@ -2,13 +2,13 @@ from django.utils.functional import cached_property -from app.services import BaseService -from diplomas.models import DiplomaTemplate -from diplomas.tasks import generate_diploma -from orders.models import Order -from products.models import Course -from studying.models import Study -from users.models import User +from apps.diplomas.models import DiplomaTemplate +from apps.diplomas.tasks import generate_diploma +from apps.orders.models import Order +from apps.products.models import Course +from apps.studying.models import Study +from apps.users.models import User +from core.services import BaseService @dataclass diff --git a/src/orders/services/order_email_changer.py b/src/apps/orders/services/order_email_changer.py similarity index 81% rename from src/orders/services/order_email_changer.py rename to src/apps/orders/services/order_email_changer.py index 4a677eb5c41..170b72baaac 100644 --- a/src/orders/services/order_email_changer.py +++ b/src/apps/orders/services/order_email_changer.py @@ -2,10 +2,10 @@ from django.utils.functional import cached_property -from app.services import BaseService -from orders.models import Order -from users.models import User -from users.services import UserCreator +from apps.orders.models import Order +from apps.users.models import User +from apps.users.services import UserCreator +from core.services import BaseService @dataclass diff --git a/src/orders/services/order_paid_setter.py b/src/apps/orders/services/order_paid_setter.py similarity index 86% rename from src/orders/services/order_paid_setter.py rename to src/apps/orders/services/order_paid_setter.py index caa62efd010..b7ef7e1f5ca 100644 --- a/src/orders/services/order_paid_setter.py +++ b/src/apps/orders/services/order_paid_setter.py @@ -4,12 +4,12 @@ from django.utils import timezone -from amocrm.tasks import amocrm_enabled -from amocrm.tasks import push_order -from amocrm.tasks import push_user -from app.services import BaseService -from orders.models import Order -from users.tasks import rebuild_tags +from apps.amocrm.tasks import amocrm_enabled +from apps.amocrm.tasks import push_order +from apps.amocrm.tasks import push_user +from apps.orders.models import Order +from apps.users.tasks import rebuild_tags +from core.services import BaseService @dataclass diff --git a/src/orders/services/order_refunder.py b/src/apps/orders/services/order_refunder.py similarity index 84% rename from src/orders/services/order_refunder.py rename to src/apps/orders/services/order_refunder.py index c445a67a7a4..7a5ae7998e3 100644 --- a/src/orders/services/order_refunder.py +++ b/src/apps/orders/services/order_refunder.py @@ -8,19 +8,19 @@ from django.utils import timezone from django.utils.functional import cached_property -from amocrm.tasks import amocrm_enabled -from amocrm.tasks import push_user -from amocrm.tasks import return_order -from app.current_user import get_current_user -from app.pricing import format_price -from app.services import BaseService -from banking.base import Bank -from banking.selector import get_bank -from mailing import tasks as mailing_tasks -from orders import human_readable -from orders.models import Order -from orders.services.order_unshipper import OrderUnshipper -from users.tasks import rebuild_tags +from apps.amocrm.tasks import amocrm_enabled +from apps.amocrm.tasks import push_user +from apps.amocrm.tasks import return_order +from apps.banking.base import Bank +from apps.banking.selector import get_bank +from apps.mailing import tasks as mailing_tasks +from apps.orders import human_readable +from apps.orders.models import Order +from apps.orders.services.order_unshipper import OrderUnshipper +from apps.users.tasks import rebuild_tags +from core.current_user import get_current_user +from core.pricing import format_price +from core.services import BaseService class OrderRefunderException(Exception): diff --git a/src/orders/services/order_shipper.py b/src/apps/orders/services/order_shipper.py similarity index 90% rename from src/orders/services/order_shipper.py rename to src/apps/orders/services/order_shipper.py index 9face7039d9..94b971cc9a3 100644 --- a/src/orders/services/order_shipper.py +++ b/src/apps/orders/services/order_shipper.py @@ -3,10 +3,10 @@ from django.conf import settings from django.utils import timezone -from app.services import BaseService -from app.tasks import send_telegram_message -from orders import human_readable -from orders.models import Order +from apps.orders import human_readable +from apps.orders.models import Order +from core.services import BaseService +from core.tasks import send_telegram_message @dataclass diff --git a/src/orders/services/order_unshipper.py b/src/apps/orders/services/order_unshipper.py similarity index 87% rename from src/orders/services/order_unshipper.py rename to src/apps/orders/services/order_unshipper.py index 8d23f934400..e4bcad97c53 100644 --- a/src/orders/services/order_unshipper.py +++ b/src/apps/orders/services/order_unshipper.py @@ -1,7 +1,7 @@ from dataclasses import dataclass -from app.services import BaseService -from orders.models import Order +from apps.orders.models import Order +from core.services import BaseService @dataclass diff --git a/src/orders/services/purchase_creator.py b/src/apps/orders/services/purchase_creator.py similarity index 83% rename from src/orders/services/purchase_creator.py rename to src/apps/orders/services/purchase_creator.py index 8f3cc485786..172384a9f29 100644 --- a/src/orders/services/purchase_creator.py +++ b/src/apps/orders/services/purchase_creator.py @@ -2,18 +2,18 @@ from celery import chain -from amocrm.tasks import amocrm_enabled -from amocrm.tasks import push_order -from amocrm.tasks import push_user -from app.services import BaseService -from banking.selector import get_bank -from banking.zero_price_bank import ZeroPriceBank -from orders.models import Order -from orders.services import OrderCreator -from products.models import Product -from users.models import User -from users.services import UserCreator -from users.tasks import rebuild_tags +from apps.amocrm.tasks import amocrm_enabled +from apps.amocrm.tasks import push_order +from apps.amocrm.tasks import push_user +from apps.banking.selector import get_bank +from apps.banking.zero_price_bank import ZeroPriceBank +from apps.orders.models import Order +from apps.orders.services import OrderCreator +from apps.products.models import Product +from apps.users.models import User +from apps.users.services import UserCreator +from apps.users.tasks import rebuild_tags +from core.services import BaseService @dataclass diff --git a/src/mailing/__init__.py b/src/apps/orders/signals/__init__.py similarity index 100% rename from src/mailing/__init__.py rename to src/apps/orders/signals/__init__.py diff --git a/src/orders/signals/handlers.py b/src/apps/orders/signals/handlers.py similarity index 83% rename from src/orders/signals/handlers.py rename to src/apps/orders/signals/handlers.py index 58b3361683d..ca4a590b3ca 100644 --- a/src/orders/signals/handlers.py +++ b/src/apps/orders/signals/handlers.py @@ -3,10 +3,10 @@ from django.db.models.signals import post_save from django.dispatch import receiver -from stripebank.models import StripeNotification -from tinkoff.models import CreditNotification as TinkoffCreditNotification -from tinkoff.models import DolyameNotification -from tinkoff.models import PaymentNotification as TinkoffPaymentNotification +from apps.stripebank.models import StripeNotification +from apps.tinkoff.models import CreditNotification as TinkoffCreditNotification +from apps.tinkoff.models import DolyameNotification +from apps.tinkoff.models import PaymentNotification as TinkoffPaymentNotification @receiver(post_save, sender=TinkoffPaymentNotification) diff --git a/src/orders/signals/signals.py b/src/apps/orders/signals/signals.py similarity index 100% rename from src/orders/signals/signals.py rename to src/apps/orders/signals/signals.py diff --git a/src/orders/static/admin/order_list.css b/src/apps/orders/static/admin/order_list.css similarity index 100% rename from src/orders/static/admin/order_list.css rename to src/apps/orders/static/admin/order_list.css diff --git a/src/orders/tasks.py b/src/apps/orders/tasks.py similarity index 52% rename from src/orders/tasks.py rename to src/apps/orders/tasks.py index b456630d205..347c7617dbd 100644 --- a/src/orders/tasks.py +++ b/src/apps/orders/tasks.py @@ -1,10 +1,10 @@ -from app.celery import celery -from orders.models import Order +from apps.orders.models import Order +from core.celery import celery @celery.task def generate_diploma(order_id: int) -> None: - from orders.services import OrderDiplomaGenerator + from apps.orders.services import OrderDiplomaGenerator order = Order.objects.get(pk=order_id) diff --git a/src/orders/urls.py b/src/apps/orders/urls.py similarity index 80% rename from src/orders/urls.py rename to src/apps/orders/urls.py index e738f8abb2e..122fec34d6e 100644 --- a/src/orders/urls.py +++ b/src/apps/orders/urls.py @@ -1,6 +1,6 @@ from django.urls import path -from orders.api import views +from apps.orders.api import views urlpatterns = [ path("/confirm/", views.OrderConfirmationView.as_view(), name="confirm-order"), diff --git a/src/mailing/migrations/__init__.py b/src/apps/products/__init__.py similarity index 100% rename from src/mailing/migrations/__init__.py rename to src/apps/products/__init__.py diff --git a/src/apps/products/admin/__init__.py b/src/apps/products/admin/__init__.py new file mode 100644 index 00000000000..a8e9332540e --- /dev/null +++ b/src/apps/products/admin/__init__.py @@ -0,0 +1,2 @@ +import apps.products.admin.course # noqa +import apps.products.admin.group # noqa diff --git a/src/products/admin/course.py b/src/apps/products/admin/course.py similarity index 89% rename from src/products/admin/course.py rename to src/apps/products/admin/course.py index 505d36a61ae..5d5cf9f499d 100644 --- a/src/products/admin/course.py +++ b/src/apps/products/admin/course.py @@ -3,12 +3,12 @@ from django.http import HttpRequest from django.utils.translation import gettext as _ -from amocrm import tasks -from app.admin import admin -from app.admin import ModelAdmin -from mailing.admin.email_configuration import EmailConfigurationAdmin -from products.admin.courses import actions -from products.models import Course +from apps.amocrm import tasks +from apps.mailing.admin.email_configuration import EmailConfigurationAdmin +from apps.products.admin.courses import actions +from apps.products.models import Course +from core.admin import admin +from core.admin import ModelAdmin @admin.register(Course) diff --git a/src/products/admin/courses/actions.py b/src/apps/products/admin/courses/actions.py similarity index 100% rename from src/products/admin/courses/actions.py rename to src/apps/products/admin/courses/actions.py diff --git a/src/products/admin/group.py b/src/apps/products/admin/group.py similarity index 77% rename from src/products/admin/group.py rename to src/apps/products/admin/group.py index 878ed2640c3..370a2519699 100644 --- a/src/products/admin/group.py +++ b/src/apps/products/admin/group.py @@ -2,10 +2,10 @@ from django.http import HttpRequest -from amocrm import tasks -from app.admin import admin -from app.admin import ModelAdmin -from products.models import Group +from apps.amocrm import tasks +from apps.products.models import Group +from core.admin import admin +from core.admin import ModelAdmin @admin.register(Group) diff --git a/src/products/api/serializers.py b/src/apps/products/api/serializers.py similarity index 90% rename from src/products/api/serializers.py rename to src/apps/products/api/serializers.py index b42cd3dbb3a..b36fdb5a459 100644 --- a/src/products/api/serializers.py +++ b/src/apps/products/api/serializers.py @@ -1,7 +1,7 @@ from rest_framework import serializers -from banking.selector import BANK_CHOICES -from products.models import Course +from apps.banking.selector import BANK_CHOICES +from apps.products.models import Course class CourseSimpleSerializer(serializers.ModelSerializer): diff --git a/src/products/api/views.py b/src/apps/products/api/views.py similarity index 83% rename from src/products/api/views.py rename to src/apps/products/api/views.py index bb8f17ed480..35c57c14788 100644 --- a/src/products/api/views.py +++ b/src/apps/products/api/views.py @@ -9,17 +9,17 @@ from django.http import HttpResponseRedirect -from app.pricing import format_price -from banking import price_calculator -from banking.selector import BANK_KEYS -from banking.selector import get_bank -from orders.api.serializers import PromocodeSerializer -from orders.api.throttling import PromocodeThrottle -from orders.api.throttling import PurchaseThrottle -from orders.models import PromoCode -from orders.services.purchase_creator import PurchaseCreator -from products.api.serializers import PurchaseSerializer -from products.models import Course +from apps.banking import price_calculator +from apps.banking.selector import BANK_KEYS +from apps.banking.selector import get_bank +from apps.orders.api.serializers import PromocodeSerializer +from apps.orders.api.throttling import PromocodeThrottle +from apps.orders.api.throttling import PurchaseThrottle +from apps.orders.models import PromoCode +from apps.orders.services.purchase_creator import PurchaseCreator +from apps.products.api.serializers import PurchaseSerializer +from apps.products.models import Course +from core.pricing import format_price if TYPE_CHECKING: from rest_framework.request import Request diff --git a/src/products/apps.py b/src/apps/products/apps.py similarity index 71% rename from src/products/apps.py rename to src/apps/products/apps.py index 4b1b6ac8b23..16b5f388a5d 100644 --- a/src/products/apps.py +++ b/src/apps/products/apps.py @@ -2,4 +2,4 @@ class ProductsConfig(AppConfig): - name = "products" + name = "apps.products" diff --git a/src/products/migrations/0001_initial.py b/src/apps/products/migrations/0001_initial.py similarity index 100% rename from src/products/migrations/0001_initial.py rename to src/apps/products/migrations/0001_initial.py diff --git a/src/products/migrations/0002_CourseGenitiveName.py b/src/apps/products/migrations/0002_CourseGenitiveName.py similarity index 100% rename from src/products/migrations/0002_CourseGenitiveName.py rename to src/apps/products/migrations/0002_CourseGenitiveName.py diff --git a/src/products/migrations/0003_DefaultOrdering.py b/src/apps/products/migrations/0003_DefaultOrdering.py similarity index 100% rename from src/products/migrations/0003_DefaultOrdering.py rename to src/apps/products/migrations/0003_DefaultOrdering.py diff --git a/src/products/migrations/0004_ReceiptNames.py b/src/apps/products/migrations/0004_ReceiptNames.py similarity index 100% rename from src/products/migrations/0004_ReceiptNames.py rename to src/apps/products/migrations/0004_ReceiptNames.py diff --git a/src/products/migrations/0005_ClickMeeetingRoomURL.py b/src/apps/products/migrations/0005_ClickMeeetingRoomURL.py similarity index 100% rename from src/products/migrations/0005_ClickMeeetingRoomURL.py rename to src/apps/products/migrations/0005_ClickMeeetingRoomURL.py diff --git a/src/products/migrations/0006_ShippableFullName.py b/src/apps/products/migrations/0006_ShippableFullName.py similarity index 100% rename from src/products/migrations/0006_ShippableFullName.py rename to src/apps/products/migrations/0006_ShippableFullName.py diff --git a/src/products/migrations/0007_L18N.py b/src/apps/products/migrations/0007_L18N.py similarity index 100% rename from src/products/migrations/0007_L18N.py rename to src/apps/products/migrations/0007_L18N.py diff --git a/src/products/migrations/0008_Bundles.py b/src/apps/products/migrations/0008_Bundles.py similarity index 100% rename from src/products/migrations/0008_Bundles.py rename to src/apps/products/migrations/0008_Bundles.py diff --git a/src/products/migrations/0008_CustomTemplateId.py b/src/apps/products/migrations/0008_CustomTemplateId.py similarity index 100% rename from src/products/migrations/0008_CustomTemplateId.py rename to src/apps/products/migrations/0008_CustomTemplateId.py diff --git a/src/products/migrations/0009_merge_20191222_1525.py b/src/apps/products/migrations/0009_merge_20191222_1525.py similarity index 100% rename from src/products/migrations/0009_merge_20191222_1525.py rename to src/apps/products/migrations/0009_merge_20191222_1525.py diff --git a/src/products/migrations/0010_ParentShippableModel.py b/src/apps/products/migrations/0010_ParentShippableModel.py similarity index 100% rename from src/products/migrations/0010_ParentShippableModel.py rename to src/apps/products/migrations/0010_ParentShippableModel.py diff --git a/src/products/migrations/0011_Price.py b/src/apps/products/migrations/0011_Price.py similarity index 100% rename from src/products/migrations/0011_Price.py rename to src/apps/products/migrations/0011_Price.py diff --git a/src/products/migrations/0012_ZoomusWebinarId.py b/src/apps/products/migrations/0012_ZoomusWebinarId.py similarity index 100% rename from src/products/migrations/0012_ZoomusWebinarId.py rename to src/apps/products/migrations/0012_ZoomusWebinarId.py diff --git a/src/products/migrations/0013_TemplateIdRename.py b/src/apps/products/migrations/0013_TemplateIdRename.py similarity index 100% rename from src/products/migrations/0013_TemplateIdRename.py rename to src/apps/products/migrations/0013_TemplateIdRename.py diff --git a/src/products/migrations/0014_CourseWelcomeLetter.py b/src/apps/products/migrations/0014_CourseWelcomeLetter.py similarity index 100% rename from src/products/migrations/0014_CourseWelcomeLetter.py rename to src/apps/products/migrations/0014_CourseWelcomeLetter.py diff --git a/src/products/migrations/0015_GiftWelcomeLetterTemplateId.py b/src/apps/products/migrations/0015_GiftWelcomeLetterTemplateId.py similarity index 100% rename from src/products/migrations/0015_GiftWelcomeLetterTemplateId.py rename to src/apps/products/migrations/0015_GiftWelcomeLetterTemplateId.py diff --git a/src/products/migrations/0016_MailchimpListId.py b/src/apps/products/migrations/0016_MailchimpListId.py similarity index 100% rename from src/products/migrations/0016_MailchimpListId.py rename to src/apps/products/migrations/0016_MailchimpListId.py diff --git a/src/products/migrations/0017_TinkoffCreditPromoCode.py b/src/apps/products/migrations/0017_TinkoffCreditPromoCode.py similarity index 100% rename from src/products/migrations/0017_TinkoffCreditPromoCode.py rename to src/apps/products/migrations/0017_TinkoffCreditPromoCode.py diff --git a/src/products/migrations/0018_ProductGroups.py b/src/apps/products/migrations/0018_ProductGroups.py similarity index 100% rename from src/products/migrations/0018_ProductGroups.py rename to src/apps/products/migrations/0018_ProductGroups.py diff --git a/src/products/migrations/0019_CourseDisplayInLMS.py b/src/apps/products/migrations/0019_CourseDisplayInLMS.py similarity index 100% rename from src/products/migrations/0019_CourseDisplayInLMS.py rename to src/apps/products/migrations/0019_CourseDisplayInLMS.py diff --git a/src/products/migrations/0020_InternationalNames.py b/src/apps/products/migrations/0020_InternationalNames.py similarity index 100% rename from src/products/migrations/0020_InternationalNames.py rename to src/apps/products/migrations/0020_InternationalNames.py diff --git a/src/products/migrations/0021_removeMailchimpListId.py b/src/apps/products/migrations/0021_removeMailchimpListId.py similarity index 100% rename from src/products/migrations/0021_removeMailchimpListId.py rename to src/apps/products/migrations/0021_removeMailchimpListId.py diff --git a/src/products/migrations/0022_DitchClickmeetings.py b/src/apps/products/migrations/0022_DitchClickmeetings.py similarity index 100% rename from src/products/migrations/0022_DitchClickmeetings.py rename to src/apps/products/migrations/0022_DitchClickmeetings.py diff --git a/src/products/migrations/0023_DiplomaTemplateContext.py b/src/apps/products/migrations/0023_DiplomaTemplateContext.py similarity index 100% rename from src/products/migrations/0023_DiplomaTemplateContext.py rename to src/apps/products/migrations/0023_DiplomaTemplateContext.py diff --git a/src/products/migrations/0024_DiplomaTemplateContextIsNotRequired.py b/src/apps/products/migrations/0024_DiplomaTemplateContextIsNotRequired.py similarity index 100% rename from src/products/migrations/0024_DiplomaTemplateContextIsNotRequired.py rename to src/apps/products/migrations/0024_DiplomaTemplateContextIsNotRequired.py diff --git a/src/products/migrations/0025_DisableTriggersFlag.py b/src/apps/products/migrations/0025_DisableTriggersFlag.py similarity index 100% rename from src/products/migrations/0025_DisableTriggersFlag.py rename to src/apps/products/migrations/0025_DisableTriggersFlag.py diff --git a/src/products/migrations/0026_CourseConfirmationTemplateId.py b/src/apps/products/migrations/0026_CourseConfirmationTemplateId.py similarity index 100% rename from src/products/migrations/0026_CourseConfirmationTemplateId.py rename to src/apps/products/migrations/0026_CourseConfirmationTemplateId.py diff --git a/src/products/migrations/0027_CourseConfirmationURL.py b/src/apps/products/migrations/0027_CourseConfirmationURL.py similarity index 100% rename from src/products/migrations/0027_CourseConfirmationURL.py rename to src/apps/products/migrations/0027_CourseConfirmationURL.py diff --git a/src/products/migrations/0028_CourseCoverField.py b/src/apps/products/migrations/0028_CourseCoverField.py similarity index 77% rename from src/products/migrations/0028_CourseCoverField.py rename to src/apps/products/migrations/0028_CourseCoverField.py index 7d798cabb7d..144e14385a2 100644 --- a/src/products/migrations/0028_CourseCoverField.py +++ b/src/apps/products/migrations/0028_CourseCoverField.py @@ -3,7 +3,7 @@ from django.db import migrations from django.db import models -import app.files +import core.files class Migration(migrations.Migration): @@ -16,6 +16,6 @@ class Migration(migrations.Migration): migrations.AddField( model_name='course', name='cover', - field=models.ImageField(blank=True, help_text='The cover image of course', upload_to=app.files.RandomFileName('courses/covers'), verbose_name='Cover image'), + field=models.ImageField(blank=True, help_text='The cover image of course', upload_to=core.files.RandomFileName('courses/covers'), verbose_name='Cover image'), ), ] diff --git a/src/products/migrations/0029_TagsForUser.py b/src/apps/products/migrations/0029_TagsForUser.py similarity index 100% rename from src/products/migrations/0029_TagsForUser.py rename to src/apps/products/migrations/0029_TagsForUser.py diff --git a/src/products/migrations/0030_SetUniqieSlugForProducts.py b/src/apps/products/migrations/0030_SetUniqieSlugForProducts.py similarity index 100% rename from src/products/migrations/0030_SetUniqieSlugForProducts.py rename to src/apps/products/migrations/0030_SetUniqieSlugForProducts.py diff --git a/src/products/migrations/0031_DropGiftFields.py b/src/apps/products/migrations/0031_DropGiftFields.py similarity index 100% rename from src/products/migrations/0031_DropGiftFields.py rename to src/apps/products/migrations/0031_DropGiftFields.py diff --git a/src/products/migrations/0032_Drop_Zoom_integration.py b/src/apps/products/migrations/0032_Drop_Zoom_integration.py similarity index 100% rename from src/products/migrations/0032_Drop_Zoom_integration.py rename to src/apps/products/migrations/0032_Drop_Zoom_integration.py diff --git a/src/notion/__init__.py b/src/apps/products/migrations/__init__.py similarity index 100% rename from src/notion/__init__.py rename to src/apps/products/migrations/__init__.py diff --git a/src/products/models/__init__.py b/src/apps/products/models/__init__.py similarity index 50% rename from src/products/models/__init__.py rename to src/apps/products/models/__init__.py index a3511b9b591..9579d73381d 100644 --- a/src/products/models/__init__.py +++ b/src/apps/products/models/__init__.py @@ -1,9 +1,9 @@ from typing import Type # NOQA: I251 -from products.models.bundle import Bundle -from products.models.course import Course -from products.models.group import Group -from products.models.record import Record +from apps.products.models.bundle import Bundle +from apps.products.models.course import Course +from apps.products.models.group import Group +from apps.products.models.record import Record Product = Course ProductType = Type[Course] diff --git a/src/products/models/base.py b/src/apps/products/models/base.py similarity index 89% rename from src/products/models/base.py rename to src/apps/products/models/base.py index 67b1eae0075..633451c9963 100644 --- a/src/products/models/base.py +++ b/src/apps/products/models/base.py @@ -4,15 +4,15 @@ from django.apps import apps from django.utils.translation import gettext_lazy as _ -from app.models import models -from app.models import TimestampedModel -from app.pricing import format_old_price -from app.pricing import format_price -from studying import shipment_factory as ShipmentFactory -from users.models import User +from apps.studying import shipment_factory as ShipmentFactory +from apps.users.models import User +from core.models import models +from core.models import TimestampedModel +from core.pricing import format_old_price +from core.pricing import format_price if TYPE_CHECKING: - from orders.models import Order + from apps.orders.models import Order class Shippable(TimestampedModel): diff --git a/src/products/models/bundle.py b/src/apps/products/models/bundle.py similarity index 86% rename from src/products/models/bundle.py rename to src/apps/products/models/bundle.py index 93c47ed527d..b825fcc1d1a 100644 --- a/src/products/models/bundle.py +++ b/src/apps/products/models/bundle.py @@ -2,12 +2,12 @@ from django.utils.translation import gettext_lazy as _ -from app.models import models -from products.models.base import Shippable +from apps.products.models.base import Shippable +from core.models import models if TYPE_CHECKING: - from orders.models import Order - from users.models import User + from apps.orders.models import Order + from apps.users.models import User class Bundle(Shippable): diff --git a/src/products/models/course.py b/src/apps/products/models/course.py similarity index 94% rename from src/products/models/course.py rename to src/apps/products/models/course.py index e5909c889d5..3f0cfef3d43 100644 --- a/src/products/models/course.py +++ b/src/apps/products/models/course.py @@ -5,11 +5,11 @@ from django.db.models import Subquery from django.utils.translation import gettext_lazy as _ -from app.files import RandomFileName -from app.models import models -from mailing.tasks import send_mail -from products.models.base import Shippable -from users.models import User +from apps.mailing.tasks import send_mail +from apps.products.models.base import Shippable +from apps.users.models import User +from core.files import RandomFileName +from core.models import models class CourseQuerySet(QuerySet): diff --git a/src/products/models/group.py b/src/apps/products/models/group.py similarity index 80% rename from src/products/models/group.py rename to src/apps/products/models/group.py index a352a86a6d8..830887f3f85 100644 --- a/src/products/models/group.py +++ b/src/apps/products/models/group.py @@ -1,7 +1,7 @@ from django.utils.translation import gettext_lazy as _ -from app.models import models -from app.models import TimestampedModel +from core.models import models +from core.models import TimestampedModel class Group(TimestampedModel): diff --git a/src/products/models/record.py b/src/apps/products/models/record.py similarity index 89% rename from src/products/models/record.py rename to src/apps/products/models/record.py index 5e8a2d0660f..71a27be3a2d 100644 --- a/src/products/models/record.py +++ b/src/apps/products/models/record.py @@ -2,9 +2,9 @@ from django.utils.translation import gettext_lazy as _ -from app.integrations.s3 import AppS3 -from app.models import models -from products.models.base import Shippable +from apps.products.models.base import Shippable +from core.integrations.s3 import AppS3 +from core.models import models class Record(Shippable): diff --git a/src/products/static/admin/css/course_action_form.css b/src/apps/products/static/admin/css/course_action_form.css similarity index 100% rename from src/products/static/admin/css/course_action_form.css rename to src/apps/products/static/admin/css/course_action_form.css diff --git a/src/products/static/admin/js/course_action_form.js b/src/apps/products/static/admin/js/course_action_form.js similarity index 100% rename from src/products/static/admin/js/course_action_form.js rename to src/apps/products/static/admin/js/course_action_form.js diff --git a/src/products/tasks.py b/src/apps/products/tasks.py similarity index 85% rename from src/products/tasks.py rename to src/apps/products/tasks.py index 3c9a8f99d91..65ff793108d 100644 --- a/src/products/tasks.py +++ b/src/apps/products/tasks.py @@ -1,6 +1,6 @@ from django.apps import apps -from app.celery import celery +from core.celery import celery @celery.task diff --git a/src/products/urls.py b/src/apps/products/urls.py similarity index 64% rename from src/products/urls.py rename to src/apps/products/urls.py index d72591a2b35..ec1163b3bf6 100644 --- a/src/products/urls.py +++ b/src/apps/products/urls.py @@ -1,7 +1,7 @@ from django.urls import path -from products.api.views import PromocodeView -from products.api.views import PurchaseView +from apps.products.api.views import PromocodeView +from apps.products.api.views import PurchaseView urlpatterns = [ path("courses//promocode/", PromocodeView.as_view()), diff --git a/src/notion/migrations/__init__.py b/src/apps/stripebank/__init__.py similarity index 100% rename from src/notion/migrations/__init__.py rename to src/apps/stripebank/__init__.py diff --git a/src/stripebank/api/serializers.py b/src/apps/stripebank/api/serializers.py similarity index 88% rename from src/stripebank/api/serializers.py rename to src/apps/stripebank/api/serializers.py index a6942a27c31..00697e33b84 100644 --- a/src/stripebank/api/serializers.py +++ b/src/apps/stripebank/api/serializers.py @@ -2,8 +2,8 @@ from rest_framework import serializers -from stripebank.bank import StripeBank -from stripebank.models import StripeNotification +from apps.stripebank.bank import StripeBank +from apps.stripebank.models import StripeNotification class StripeNotificationSerializer(serializers.ModelSerializer): diff --git a/src/stripebank/api/views.py b/src/apps/stripebank/api/views.py similarity index 91% rename from src/stripebank/api/views.py rename to src/apps/stripebank/api/views.py index bb1efa2ea37..6b5a8d2af80 100644 --- a/src/stripebank/api/views.py +++ b/src/apps/stripebank/api/views.py @@ -8,8 +8,8 @@ from django.conf import settings -from orders.models import Order -from stripebank.api.serializers import StripeNotificationSerializer +from apps.orders.models import Order +from apps.stripebank.api.serializers import StripeNotificationSerializer class StripeWebhookView(APIView): diff --git a/src/stripebank/apps.py b/src/apps/stripebank/apps.py similarity index 81% rename from src/stripebank/apps.py rename to src/apps/stripebank/apps.py index e37a4a77726..511e86d973d 100644 --- a/src/stripebank/apps.py +++ b/src/apps/stripebank/apps.py @@ -3,4 +3,4 @@ class StripebankConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" - name = "stripebank" + name = "apps.stripebank" diff --git a/src/stripebank/bank.py b/src/apps/stripebank/bank.py similarity index 97% rename from src/stripebank/bank.py rename to src/apps/stripebank/bank.py index 55ff028b317..3aa264b5ebf 100644 --- a/src/stripebank/bank.py +++ b/src/apps/stripebank/bank.py @@ -6,7 +6,7 @@ from django.conf import settings from django.utils.translation import gettext_lazy as _ -from banking.base import Bank +from apps.banking.base import Bank class StripeBank(Bank): diff --git a/src/stripebank/migrations/0001_Initial.py b/src/apps/stripebank/migrations/0001_Initial.py similarity index 100% rename from src/stripebank/migrations/0001_Initial.py rename to src/apps/stripebank/migrations/0001_Initial.py diff --git a/src/stripebank/migrations/0002_OrderUUID.py b/src/apps/stripebank/migrations/0002_OrderUUID.py similarity index 100% rename from src/stripebank/migrations/0002_OrderUUID.py rename to src/apps/stripebank/migrations/0002_OrderUUID.py diff --git a/src/orders/__init__.py b/src/apps/stripebank/migrations/__init__.py similarity index 100% rename from src/orders/__init__.py rename to src/apps/stripebank/migrations/__init__.py diff --git a/src/stripebank/models.py b/src/apps/stripebank/models.py similarity index 86% rename from src/stripebank/models.py rename to src/apps/stripebank/models.py index 234f2df90c3..78aa13e5aaa 100644 --- a/src/stripebank/models.py +++ b/src/apps/stripebank/models.py @@ -1,5 +1,5 @@ -from app.models import models -from app.models import TimestampedModel +from core.models import models +from core.models import TimestampedModel class StripeNotification(TimestampedModel): diff --git a/src/orders/migrations/__init__.py b/src/apps/studying/__init__.py similarity index 100% rename from src/orders/migrations/__init__.py rename to src/apps/studying/__init__.py diff --git a/src/studying/api/serializers.py b/src/apps/studying/api/serializers.py similarity index 88% rename from src/studying/api/serializers.py rename to src/apps/studying/api/serializers.py index c54aad0ba57..5d43e19286e 100644 --- a/src/studying/api/serializers.py +++ b/src/apps/studying/api/serializers.py @@ -1,6 +1,6 @@ from rest_framework import serializers -from products.models import Course +from apps.products.models import Course class CourseSerializer(serializers.ModelSerializer): diff --git a/src/studying/api/views.py b/src/apps/studying/api/views.py similarity index 68% rename from src/studying/api/views.py rename to src/apps/studying/api/views.py index 228c038c146..2e2fc536120 100644 --- a/src/studying/api/views.py +++ b/src/apps/studying/api/views.py @@ -3,11 +3,11 @@ from django.db.models import QuerySet -from app.api.mixins import DisablePaginationWithQueryParamMixin -from app.views import AuthenticatedRequest -from products.models import Course -from studying.api.serializers import CourseSerializer -from studying.models import Study +from apps.products.models import Course +from apps.studying.api.serializers import CourseSerializer +from apps.studying.models import Study +from core.api.mixins import DisablePaginationWithQueryParamMixin +from core.views import AuthenticatedRequest class PurchasedCoursesView(DisablePaginationWithQueryParamMixin, ListAPIView): diff --git a/src/studying/apps.py b/src/apps/studying/apps.py similarity index 68% rename from src/studying/apps.py rename to src/apps/studying/apps.py index 145caf7af12..84a2e564835 100644 --- a/src/studying/apps.py +++ b/src/apps/studying/apps.py @@ -2,8 +2,8 @@ class StudyingConfig(AppConfig): - name = "studying" + name = "apps.studying" def ready(self) -> None: """Register all shipping algorithms for the factory""" - import studying.shipment # noqa + import apps.studying.shipment # noqa diff --git a/src/studying/migrations/0001_initial.py b/src/apps/studying/migrations/0001_initial.py similarity index 100% rename from src/studying/migrations/0001_initial.py rename to src/apps/studying/migrations/0001_initial.py diff --git a/src/studying/migrations/0002_StudyIsHomeworkAccepted.py b/src/apps/studying/migrations/0002_StudyIsHomeworkAccepted.py similarity index 100% rename from src/studying/migrations/0002_StudyIsHomeworkAccepted.py rename to src/apps/studying/migrations/0002_StudyIsHomeworkAccepted.py diff --git a/src/orders/signals/__init__.py b/src/apps/studying/migrations/__init__.py similarity index 100% rename from src/orders/signals/__init__.py rename to src/apps/studying/migrations/__init__.py diff --git a/src/studying/models.py b/src/apps/studying/models.py similarity index 90% rename from src/studying/models.py rename to src/apps/studying/models.py index 1639dd2fec7..26c76f89df4 100644 --- a/src/studying/models.py +++ b/src/apps/studying/models.py @@ -1,8 +1,8 @@ from django.db.models import Index from django.db.models import UniqueConstraint -from app.models import models -from app.models import TimestampedModel +from core.models import models +from core.models import TimestampedModel class Study(TimestampedModel): diff --git a/src/apps/studying/shipment/__init__.py b/src/apps/studying/shipment/__init__.py new file mode 100644 index 00000000000..bdaa25e63dc --- /dev/null +++ b/src/apps/studying/shipment/__init__.py @@ -0,0 +1,5 @@ +from apps.studying.shipment.course import CourseShipment + +__all__ = [ + "CourseShipment", +] diff --git a/src/studying/shipment/base.py b/src/apps/studying/shipment/base.py similarity index 82% rename from src/studying/shipment/base.py rename to src/apps/studying/shipment/base.py index be23042589f..f30b2a99aa9 100644 --- a/src/studying/shipment/base.py +++ b/src/apps/studying/shipment/base.py @@ -3,9 +3,9 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from orders.models import Order - from products.models import Course - from users.models import User + from apps.orders.models import Order + from apps.products.models import Course + from apps.users.models import User class BaseShipment(metaclass=ABCMeta): diff --git a/src/studying/shipment/course.py b/src/apps/studying/shipment/course.py similarity index 83% rename from src/studying/shipment/course.py rename to src/apps/studying/shipment/course.py index 05653a5b25a..1ef35a72e86 100644 --- a/src/studying/shipment/course.py +++ b/src/apps/studying/shipment/course.py @@ -1,8 +1,8 @@ -from mailing.tasks import send_mail -from products.models import Course -from studying import shipment_factory as factory -from studying.models import Study -from studying.shipment.base import BaseShipment +from apps.mailing.tasks import send_mail +from apps.products.models import Course +from apps.studying import shipment_factory as factory +from apps.studying.models import Study +from apps.studying.shipment.base import BaseShipment @factory.register(Course) diff --git a/src/studying/shipment_factory.py b/src/apps/studying/shipment_factory.py similarity index 81% rename from src/studying/shipment_factory.py rename to src/apps/studying/shipment_factory.py index ccea7eb4311..957b842c578 100644 --- a/src/studying/shipment_factory.py +++ b/src/apps/studying/shipment_factory.py @@ -1,11 +1,11 @@ from typing import Callable, Type, TYPE_CHECKING if TYPE_CHECKING: - from orders.models import Order - from products.models import Product - from products.models import ProductType - from studying.shipment.base import BaseShipment - from users.models import User + from apps.orders.models import Order + from apps.products.models import Product + from apps.products.models import ProductType + from apps.studying.shipment.base import BaseShipment + from apps.users.models import User _registry: dict["ProductType", Type["BaseShipment"]] = {} diff --git a/src/studying/urls.py b/src/apps/studying/urls.py similarity index 75% rename from src/studying/urls.py rename to src/apps/studying/urls.py index e2fc3cfc4d9..55abc1985c1 100644 --- a/src/studying/urls.py +++ b/src/apps/studying/urls.py @@ -1,6 +1,6 @@ from django.urls import path -from studying.api import views +from apps.studying.api import views urlpatterns = [ path("purchased/", views.PurchasedCoursesView.as_view()), diff --git a/src/orders/tests/human_readable/__init__.py b/src/apps/tinkoff/__init__.py similarity index 100% rename from src/orders/tests/human_readable/__init__.py rename to src/apps/tinkoff/__init__.py diff --git a/src/tinkoff/api/permissions.py b/src/apps/tinkoff/api/permissions.py similarity index 81% rename from src/tinkoff/api/permissions.py rename to src/apps/tinkoff/api/permissions.py index 78bd09f4cdd..4daa3c49b8c 100644 --- a/src/tinkoff/api/permissions.py +++ b/src/apps/tinkoff/api/permissions.py @@ -8,11 +8,11 @@ class TinkoffCreditNetmaskPermission(permissions.BasePermission): - """The only way to validate webhooks from tinkoff credit is IP addess, + """The only way to validate webhooks from apps.tinkoff credit is IP addess, proof: https://forma.tinkoff.ru/docs/credit/help/http/ """ - message = "Tinkoff Credit requests are allowed only from tinkoff network" + message = "Tinkoff Credit requests are allowed only from apps.tinkoff network" def has_permission(self, request: Request, view: APIView, *args: Any, **kwargs: dict[str, Any]) -> bool: sender_ip = IPv4Address(request.META["REMOTE_ADDR"]) @@ -25,7 +25,7 @@ class DolyameNetmaskPermission(permissions.BasePermission): proof: https://dolyame.ru/develop/help/webhooks/ """ - message = "Dolyament requests are allowed only from tinkoff network" + message = "Dolyament requests are allowed only from apps.tinkoff network" def has_permission(self, request: Request, view: APIView, *args: Any, **kwargs: dict[str, Any]) -> bool: sender_ip = IPv4Address(request.META["REMOTE_ADDR"]) diff --git a/src/tinkoff/api/serializers.py b/src/apps/tinkoff/api/serializers.py similarity index 94% rename from src/tinkoff/api/serializers.py rename to src/apps/tinkoff/api/serializers.py index 5270c17f92f..cf27f4de119 100644 --- a/src/tinkoff/api/serializers.py +++ b/src/apps/tinkoff/api/serializers.py @@ -1,9 +1,9 @@ from _decimal import Decimal from rest_framework import serializers -from tinkoff.models import CreditNotification -from tinkoff.models import DolyameNotification -from tinkoff.models import PaymentNotification +from apps.tinkoff.models import CreditNotification +from apps.tinkoff.models import DolyameNotification +from apps.tinkoff.models import PaymentNotification class PaymentNotificationSerializer(serializers.ModelSerializer): diff --git a/src/tinkoff/api/views.py b/src/apps/tinkoff/api/views.py similarity index 80% rename from src/tinkoff/api/views.py rename to src/apps/tinkoff/api/views.py index 43b937ca9a2..405d3b5e992 100644 --- a/src/tinkoff/api/views.py +++ b/src/apps/tinkoff/api/views.py @@ -6,13 +6,13 @@ from django.http import HttpResponse -from orders.models import Order -from tinkoff.api.permissions import DolyameNetmaskPermission -from tinkoff.api.permissions import TinkoffCreditNetmaskPermission -from tinkoff.api.serializers import CreditNotificationSerializer -from tinkoff.api.serializers import DolyameNotificationSerializer -from tinkoff.api.serializers import PaymentNotificationSerializer -from tinkoff.token_validator import TinkoffNotificationsTokenValidator +from apps.orders.models import Order +from apps.tinkoff.api.permissions import DolyameNetmaskPermission +from apps.tinkoff.api.permissions import TinkoffCreditNetmaskPermission +from apps.tinkoff.api.serializers import CreditNotificationSerializer +from apps.tinkoff.api.serializers import DolyameNotificationSerializer +from apps.tinkoff.api.serializers import PaymentNotificationSerializer +from apps.tinkoff.token_validator import TinkoffNotificationsTokenValidator class TinkoffPaymentNotificationsView(APIView): diff --git a/src/tinkoff/apps.py b/src/apps/tinkoff/apps.py similarity index 72% rename from src/tinkoff/apps.py rename to src/apps/tinkoff/apps.py index 1d75f6f24db..3c77c756e19 100644 --- a/src/tinkoff/apps.py +++ b/src/apps/tinkoff/apps.py @@ -2,4 +2,4 @@ class TinkoffConfig(AppConfig): - name = "tinkoff" + name = "apps.tinkoff" diff --git a/src/tinkoff/bank.py b/src/apps/tinkoff/bank.py similarity index 97% rename from src/tinkoff/bank.py rename to src/apps/tinkoff/bank.py index 1b9200a69c0..acfc4284788 100644 --- a/src/tinkoff/bank.py +++ b/src/apps/tinkoff/bank.py @@ -9,8 +9,8 @@ from django.conf import settings from django.utils.translation import gettext_lazy as _ -from banking.base import Bank -from tinkoff.exceptions import TinkoffRequestException +from apps.banking.base import Bank +from apps.tinkoff.exceptions import TinkoffRequestException class TinkoffBank(Bank): diff --git a/src/tinkoff/credit.py b/src/apps/tinkoff/credit.py similarity index 98% rename from src/tinkoff/credit.py rename to src/apps/tinkoff/credit.py index cb7d118bdac..9db2491b4d9 100644 --- a/src/tinkoff/credit.py +++ b/src/apps/tinkoff/credit.py @@ -3,7 +3,7 @@ from django.conf import settings from django.utils.translation import gettext_lazy as _ -from banking.base import Bank +from apps.banking.base import Bank class TinkoffCreditRequestException(Exception): diff --git a/src/tinkoff/dolyame.py b/src/apps/tinkoff/dolyame.py similarity index 98% rename from src/tinkoff/dolyame.py rename to src/apps/tinkoff/dolyame.py index c66b01b07bd..4e25840b556 100644 --- a/src/tinkoff/dolyame.py +++ b/src/apps/tinkoff/dolyame.py @@ -6,7 +6,7 @@ from django.conf import settings from django.utils.translation import gettext_lazy as _ -from banking.base import Bank +from apps.banking.base import Bank class DolyameRequestException(Exception): diff --git a/src/tinkoff/exceptions.py b/src/apps/tinkoff/exceptions.py similarity index 100% rename from src/tinkoff/exceptions.py rename to src/apps/tinkoff/exceptions.py diff --git a/src/tinkoff/management/commands/refund_dolyame.py b/src/apps/tinkoff/management/commands/refund_dolyame.py similarity index 86% rename from src/tinkoff/management/commands/refund_dolyame.py rename to src/apps/tinkoff/management/commands/refund_dolyame.py index affc8cafa73..afd8abbd41a 100644 --- a/src/tinkoff/management/commands/refund_dolyame.py +++ b/src/apps/tinkoff/management/commands/refund_dolyame.py @@ -1,7 +1,7 @@ from django.core.management.base import BaseCommand -from orders.models import Order -from tinkoff.dolyame import Dolyame +from apps.orders.models import Order +from apps.tinkoff.dolyame import Dolyame class Command(BaseCommand): diff --git a/src/tinkoff/migrations/0001_initial.py b/src/apps/tinkoff/migrations/0001_initial.py similarity index 100% rename from src/tinkoff/migrations/0001_initial.py rename to src/apps/tinkoff/migrations/0001_initial.py diff --git a/src/tinkoff/migrations/0002_EmptyCardID.py b/src/apps/tinkoff/migrations/0002_EmptyCardID.py similarity index 100% rename from src/tinkoff/migrations/0002_EmptyCardID.py rename to src/apps/tinkoff/migrations/0002_EmptyCardID.py diff --git a/src/tinkoff/migrations/0003_CreditNotifications.py b/src/apps/tinkoff/migrations/0003_CreditNotifications.py similarity index 100% rename from src/tinkoff/migrations/0003_CreditNotifications.py rename to src/apps/tinkoff/migrations/0003_CreditNotifications.py diff --git a/src/tinkoff/migrations/0004_DolyameNotifications.py b/src/apps/tinkoff/migrations/0004_DolyameNotifications.py similarity index 100% rename from src/tinkoff/migrations/0004_DolyameNotifications.py rename to src/apps/tinkoff/migrations/0004_DolyameNotifications.py diff --git a/src/tinkoff/migrations/0005_DolyameTypoFix.py b/src/apps/tinkoff/migrations/0005_DolyameTypoFix.py similarity index 100% rename from src/tinkoff/migrations/0005_DolyameTypoFix.py rename to src/apps/tinkoff/migrations/0005_DolyameTypoFix.py diff --git a/src/tinkoff/migrations/0006_DolyameRefundedStatus.py b/src/apps/tinkoff/migrations/0006_DolyameRefundedStatus.py similarity index 100% rename from src/tinkoff/migrations/0006_DolyameRefundedStatus.py rename to src/apps/tinkoff/migrations/0006_DolyameRefundedStatus.py diff --git a/src/tinkoff/migrations/0007_TinkoffCreditOrderSlug.py b/src/apps/tinkoff/migrations/0007_TinkoffCreditOrderSlug.py similarity index 100% rename from src/tinkoff/migrations/0007_TinkoffCreditOrderSlug.py rename to src/apps/tinkoff/migrations/0007_TinkoffCreditOrderSlug.py diff --git a/src/tinkoff/migrations/0008_TinkoffBankOrderSlug.py b/src/apps/tinkoff/migrations/0008_TinkoffBankOrderSlug.py similarity index 100% rename from src/tinkoff/migrations/0008_TinkoffBankOrderSlug.py rename to src/apps/tinkoff/migrations/0008_TinkoffBankOrderSlug.py diff --git a/src/tinkoff/migrations/0009_DolyameOrderUUID.py b/src/apps/tinkoff/migrations/0009_DolyameOrderUUID.py similarity index 100% rename from src/tinkoff/migrations/0009_DolyameOrderUUID.py rename to src/apps/tinkoff/migrations/0009_DolyameOrderUUID.py diff --git a/src/orders/tests/services/__init__.py b/src/apps/tinkoff/migrations/__init__.py similarity index 100% rename from src/orders/tests/services/__init__.py rename to src/apps/tinkoff/migrations/__init__.py diff --git a/src/tinkoff/models.py b/src/apps/tinkoff/models.py similarity index 97% rename from src/tinkoff/models.py rename to src/apps/tinkoff/models.py index f82ca4cadad..e15fb40f7e2 100644 --- a/src/tinkoff/models.py +++ b/src/apps/tinkoff/models.py @@ -1,7 +1,7 @@ from django.utils.translation import gettext_lazy as _ -from app.models import models -from app.models import TimestampedModel +from core.models import models +from core.models import TimestampedModel class PaymentNotification(TimestampedModel): diff --git a/src/tinkoff/tasks.py b/src/apps/tinkoff/tasks.py similarity index 70% rename from src/tinkoff/tasks.py rename to src/apps/tinkoff/tasks.py index cd7655b5383..29f61a70f27 100644 --- a/src/tinkoff/tasks.py +++ b/src/apps/tinkoff/tasks.py @@ -1,9 +1,9 @@ import httpx -from app.celery import celery -from orders.models import Order -from tinkoff.dolyame import Dolyame -from tinkoff.dolyame import DolyameRequestException +from apps.orders.models import Order +from apps.tinkoff.dolyame import Dolyame +from apps.tinkoff.dolyame import DolyameRequestException +from core.celery import celery @celery.task( diff --git a/src/tinkoff/token_validator.py b/src/apps/tinkoff/token_validator.py similarity index 88% rename from src/tinkoff/token_validator.py rename to src/apps/tinkoff/token_validator.py index d8c33931050..3a7029b887a 100644 --- a/src/tinkoff/token_validator.py +++ b/src/apps/tinkoff/token_validator.py @@ -4,9 +4,9 @@ from django.conf import settings -from app.services import BaseService -from tinkoff.exceptions import TinkoffPaymentNotificationInvalidToken -from tinkoff.exceptions import TinkoffPaymentNotificationNoTokenPassed +from apps.tinkoff.exceptions import TinkoffPaymentNotificationInvalidToken +from apps.tinkoff.exceptions import TinkoffPaymentNotificationNoTokenPassed +from core.services import BaseService PAYLOAD_KEYS_EXCLUDED_FROM_SIGNATURE_VALIDATION = [ "Token", diff --git a/src/products/__init__.py b/src/apps/users/__init__.py similarity index 100% rename from src/products/__init__.py rename to src/apps/users/__init__.py diff --git a/src/apps/users/admin/__init__.py b/src/apps/users/admin/__init__.py new file mode 100644 index 00000000000..53d5e517df7 --- /dev/null +++ b/src/apps/users/admin/__init__.py @@ -0,0 +1,7 @@ +from apps.users.admin.student import StudentAdmin +from apps.users.admin.user import UserAdmin + +__all__ = [ + "StudentAdmin", + "UserAdmin", +] diff --git a/src/users/admin/student.py b/src/apps/users/admin/student.py similarity index 89% rename from src/users/admin/student.py rename to src/apps/users/admin/student.py index 34edf9c7366..112c21426fe 100644 --- a/src/users/admin/student.py +++ b/src/apps/users/admin/student.py @@ -3,11 +3,11 @@ from django import forms from django.utils.translation import gettext_lazy as _ -from app.admin import admin -from app.admin import ModelAdmin -from users.models import Student -from users.models import User -from users.services import UserCreator +from apps.users.models import Student +from apps.users.models import User +from apps.users.services import UserCreator +from core.admin import admin +from core.admin import ModelAdmin class PasswordLessUserCreationForm(forms.ModelForm): diff --git a/src/users/admin/user.py b/src/apps/users/admin/user.py similarity index 75% rename from src/users/admin/user.py rename to src/apps/users/admin/user.py index 19f18a472bc..c7e445376ac 100644 --- a/src/users/admin/user.py +++ b/src/apps/users/admin/user.py @@ -1,7 +1,7 @@ from django.contrib.auth.admin import UserAdmin as StockUserAdmin -from app.admin import admin -from users.models import User +from apps.users.models import User +from core.admin import admin @admin.register(User) diff --git a/src/users/api/serializers.py b/src/apps/users/api/serializers.py similarity index 94% rename from src/users/api/serializers.py rename to src/apps/users/api/serializers.py index 34f0b5154d7..76826eee1f3 100644 --- a/src/users/api/serializers.py +++ b/src/apps/users/api/serializers.py @@ -1,6 +1,6 @@ from rest_framework import serializers -from users.models import User +from apps.users.models import User class UserSerializer(serializers.ModelSerializer): diff --git a/src/users/api/views.py b/src/apps/users/api/views.py similarity index 86% rename from src/users/api/views.py rename to src/apps/users/api/views.py index b7e5ac71c57..9572cb20d82 100644 --- a/src/users/api/views.py +++ b/src/apps/users/api/views.py @@ -8,10 +8,10 @@ from django.core.exceptions import ImproperlyConfigured from django.db.models import QuerySet -from app.current_user import get_current_user -from users.api.serializers import UserSerializer -from users.models import User -from users.services import UserUpdater +from apps.users.api.serializers import UserSerializer +from apps.users.models import User +from apps.users.services import UserUpdater +from core.current_user import get_current_user class SelfView(GenericAPIView): diff --git a/src/users/apps.py b/src/apps/users/apps.py similarity index 86% rename from src/users/apps.py rename to src/apps/users/apps.py index 3421fc9fb9a..f55262b974e 100644 --- a/src/users/apps.py +++ b/src/apps/users/apps.py @@ -3,5 +3,5 @@ class UsersConfig(AppConfig): - name = "users" + name = "apps.users" verbose_name = _("Users") diff --git a/src/products/migrations/__init__.py b/src/apps/users/management/__init__.py similarity index 100% rename from src/products/migrations/__init__.py rename to src/apps/users/management/__init__.py diff --git a/src/stripebank/__init__.py b/src/apps/users/management/commands/__init__.py similarity index 100% rename from src/stripebank/__init__.py rename to src/apps/users/management/commands/__init__.py diff --git a/src/users/management/commands/create_dev_admin_user.py b/src/apps/users/management/commands/create_dev_admin_user.py similarity index 95% rename from src/users/management/commands/create_dev_admin_user.py rename to src/apps/users/management/commands/create_dev_admin_user.py index 2b6371750a3..69ac4bc88fa 100644 --- a/src/users/management/commands/create_dev_admin_user.py +++ b/src/apps/users/management/commands/create_dev_admin_user.py @@ -1,6 +1,6 @@ from django.core.management import BaseCommand -from users.models import User +from apps.users.models import User class Command(BaseCommand): diff --git a/src/users/management/commands/update_students_tags.py b/src/apps/users/management/commands/update_students_tags.py similarity index 92% rename from src/users/management/commands/update_students_tags.py rename to src/apps/users/management/commands/update_students_tags.py index 9d42f382447..ad0b3fdc9f5 100644 --- a/src/users/management/commands/update_students_tags.py +++ b/src/apps/users/management/commands/update_students_tags.py @@ -2,7 +2,7 @@ from django.apps import apps from django.core.management.base import BaseCommand -from users.tasks import rebuild_tags +from apps.users.tasks import rebuild_tags class Command(BaseCommand): diff --git a/src/users/migrations/0001_initial.py b/src/apps/users/migrations/0001_initial.py similarity index 100% rename from src/users/migrations/0001_initial.py rename to src/apps/users/migrations/0001_initial.py diff --git a/src/users/migrations/0002_SubscribedToNewsLetter.py b/src/apps/users/migrations/0002_SubscribedToNewsLetter.py similarity index 100% rename from src/users/migrations/0002_SubscribedToNewsLetter.py rename to src/apps/users/migrations/0002_SubscribedToNewsLetter.py diff --git a/src/users/migrations/0003_Django31.py b/src/apps/users/migrations/0003_Django31.py similarity index 100% rename from src/users/migrations/0003_Django31.py rename to src/apps/users/migrations/0003_Django31.py diff --git a/src/users/migrations/0004_NamesInEnglish.py b/src/apps/users/migrations/0004_NamesInEnglish.py similarity index 100% rename from src/users/migrations/0004_NamesInEnglish.py rename to src/apps/users/migrations/0004_NamesInEnglish.py diff --git a/src/users/migrations/0005_UserUUID.py b/src/apps/users/migrations/0005_UserUUID.py similarity index 100% rename from src/users/migrations/0005_UserUUID.py rename to src/apps/users/migrations/0005_UserUUID.py diff --git a/src/users/migrations/0006_Gender.py b/src/apps/users/migrations/0006_Gender.py similarity index 100% rename from src/users/migrations/0006_Gender.py rename to src/apps/users/migrations/0006_Gender.py diff --git a/src/users/migrations/0007_StudentProxyModel.py b/src/apps/users/migrations/0007_StudentProxyModel.py similarity index 100% rename from src/users/migrations/0007_StudentProxyModel.py rename to src/apps/users/migrations/0007_StudentProxyModel.py diff --git a/src/users/migrations/0008_AddtionalProfileFields.py b/src/apps/users/migrations/0008_AddtionalProfileFields.py similarity index 100% rename from src/users/migrations/0008_AddtionalProfileFields.py rename to src/apps/users/migrations/0008_AddtionalProfileFields.py diff --git a/src/users/migrations/0009_add_telegram_username.py b/src/apps/users/migrations/0009_add_telegram_username.py similarity index 100% rename from src/users/migrations/0009_add_telegram_username.py rename to src/apps/users/migrations/0009_add_telegram_username.py diff --git a/src/users/migrations/0010_drop_linkedin_github_constraints.py b/src/apps/users/migrations/0010_drop_linkedin_github_constraints.py similarity index 100% rename from src/users/migrations/0010_drop_linkedin_github_constraints.py rename to src/apps/users/migrations/0010_drop_linkedin_github_constraints.py diff --git a/src/users/migrations/0011_TagsForUser.py b/src/apps/users/migrations/0011_TagsForUser.py similarity index 100% rename from src/users/migrations/0011_TagsForUser.py rename to src/apps/users/migrations/0011_TagsForUser.py diff --git a/src/stripebank/migrations/__init__.py b/src/apps/users/migrations/__init__.py similarity index 100% rename from src/stripebank/migrations/__init__.py rename to src/apps/users/migrations/__init__.py diff --git a/src/users/models.py b/src/apps/users/models.py similarity index 97% rename from src/users/models.py rename to src/apps/users/models.py index 8e1f744d298..809a652c335 100644 --- a/src/users/models.py +++ b/src/apps/users/models.py @@ -11,9 +11,9 @@ from django.utils.functional import cached_property from django.utils.translation import gettext_lazy as _ -from app.models import models -from app.types import Language -from diplomas.models import Languages +from apps.diplomas.models import Languages +from core.models import models +from core.types import Language class User(AbstractUser): diff --git a/src/apps/users/services/__init__.py b/src/apps/users/services/__init__.py new file mode 100644 index 00000000000..38791c01380 --- /dev/null +++ b/src/apps/users/services/__init__.py @@ -0,0 +1,7 @@ +from apps.users.services.user_creator import UserCreator +from apps.users.services.user_updater import UserUpdater + +__all__ = [ + "UserCreator", + "UserUpdater", +] diff --git a/src/users/services/user_creator.py b/src/apps/users/services/user_creator.py similarity index 93% rename from src/users/services/user_creator.py rename to src/apps/users/services/user_creator.py index 4a1d20c6327..6b2bba06064 100644 --- a/src/users/services/user_creator.py +++ b/src/apps/users/services/user_creator.py @@ -5,9 +5,9 @@ from django.utils.functional import cached_property -from app.services import BaseService -from users.models import User -from users.tasks import rebuild_tags +from apps.users.models import User +from apps.users.tasks import rebuild_tags +from core.services import BaseService class UserCreateSerializer(serializers.ModelSerializer): diff --git a/src/users/services/user_updater.py b/src/apps/users/services/user_updater.py similarity index 87% rename from src/users/services/user_updater.py rename to src/apps/users/services/user_updater.py index 898a9cbccb5..6c82ce917d9 100644 --- a/src/users/services/user_updater.py +++ b/src/apps/users/services/user_updater.py @@ -2,11 +2,11 @@ from rest_framework import serializers -from amocrm.tasks import amocrm_enabled -from amocrm.tasks import push_user -from app.services import BaseService -from diplomas.tasks import regenerate_diplomas -from users.models import User +from apps.amocrm.tasks import amocrm_enabled +from apps.amocrm.tasks import push_user +from apps.diplomas.tasks import regenerate_diplomas +from apps.users.models import User +from core.services import BaseService class UserUpdateSerializer(serializers.ModelSerializer): diff --git a/src/apps/users/tags/__init__.py b/src/apps/users/tags/__init__.py new file mode 100644 index 00000000000..ce9145d0b68 --- /dev/null +++ b/src/apps/users/tags/__init__.py @@ -0,0 +1,11 @@ +__all__ = [ + "AnyPurchaseTag", + "StartedTag", + "PurchasedTag", + "B2BTag", +] + +from apps.users.tags.any_purchase_tag import AnyPurchaseTag +from apps.users.tags.b2b_tag import B2BTag +from apps.users.tags.purchased_tag import PurchasedTag +from apps.users.tags.started_tag import StartedTag diff --git a/src/users/tags/any_purchase_tag.py b/src/apps/users/tags/any_purchase_tag.py similarity index 88% rename from src/users/tags/any_purchase_tag.py rename to src/apps/users/tags/any_purchase_tag.py index f4d835a6d0c..ca2a342cef4 100644 --- a/src/users/tags/any_purchase_tag.py +++ b/src/apps/users/tags/any_purchase_tag.py @@ -1,6 +1,6 @@ from typing import final -from users.tags.base import TagMechanism +from apps.users.tags.base import TagMechanism @final diff --git a/src/users/tags/b2b_tag.py b/src/apps/users/tags/b2b_tag.py similarity index 86% rename from src/users/tags/b2b_tag.py rename to src/apps/users/tags/b2b_tag.py index 1bbd88e1959..637add9a87a 100644 --- a/src/users/tags/b2b_tag.py +++ b/src/apps/users/tags/b2b_tag.py @@ -3,8 +3,8 @@ from django.core.exceptions import ValidationError from django.core.validators import validate_email -from mailing.models import PersonalEmailDomain -from users.tags.base import TagMechanism +from apps.mailing.models import PersonalEmailDomain +from apps.users.tags.base import TagMechanism @final diff --git a/src/users/tags/base.py b/src/apps/users/tags/base.py similarity index 91% rename from src/users/tags/base.py rename to src/apps/users/tags/base.py index 8180f1c0d6b..a1ffe4f12cc 100644 --- a/src/users/tags/base.py +++ b/src/apps/users/tags/base.py @@ -5,10 +5,10 @@ from django.db.models import QuerySet -from orders.models import Order +from apps.orders.models import Order if TYPE_CHECKING: - from users.models import Student + from apps.users.models import Student @dataclass diff --git a/src/users/tags/pipeline.py b/src/apps/users/tags/pipeline.py similarity index 85% rename from src/users/tags/pipeline.py rename to src/apps/users/tags/pipeline.py index 462d9079aaa..0ce2f7edf82 100644 --- a/src/users/tags/pipeline.py +++ b/src/apps/users/tags/pipeline.py @@ -4,8 +4,8 @@ from django.utils.module_loading import import_string if TYPE_CHECKING: - from users.models import Student - from users.tags.base import TagMechanism + from apps.users.models import Student + from apps.users.tags.base import TagMechanism def generate_tags(student: "Student") -> None: diff --git a/src/users/tags/purchased_tag.py b/src/apps/users/tags/purchased_tag.py similarity index 87% rename from src/users/tags/purchased_tag.py rename to src/apps/users/tags/purchased_tag.py index 32fb206fe59..aa407de7449 100644 --- a/src/users/tags/purchased_tag.py +++ b/src/apps/users/tags/purchased_tag.py @@ -2,11 +2,11 @@ from django.db.models import QuerySet -from products.models import Course -from users.tags.base import TagMechanism +from apps.products.models import Course +from apps.users.tags.base import TagMechanism if TYPE_CHECKING: - from users.models import Student + from apps.users.models import Student @final diff --git a/src/users/tags/started_tag.py b/src/apps/users/tags/started_tag.py similarity index 90% rename from src/users/tags/started_tag.py rename to src/apps/users/tags/started_tag.py index 665e2414a73..d79a166945f 100644 --- a/src/users/tags/started_tag.py +++ b/src/apps/users/tags/started_tag.py @@ -2,11 +2,11 @@ from django.db.models import QuerySet -from products.models import Course -from users.tags.base import TagMechanism +from apps.products.models import Course +from apps.users.tags.base import TagMechanism if TYPE_CHECKING: - from users.models import Student + from apps.users.models import Student @final diff --git a/src/users/tasks.py b/src/apps/users/tasks.py similarity index 76% rename from src/users/tasks.py rename to src/apps/users/tasks.py index 5d57583dbc0..cabb7b09091 100644 --- a/src/users/tasks.py +++ b/src/apps/users/tasks.py @@ -2,9 +2,9 @@ from django.apps import apps -from app.celery import celery -from app.tasks import update_dashamail_subscription -from users.tags.pipeline import generate_tags +from apps.users.tags.pipeline import generate_tags +from core.celery import celery +from core.tasks import update_dashamail_subscription @celery.task(name="users.rebuild_tags") diff --git a/src/users/urls.py b/src/apps/users/urls.py similarity index 67% rename from src/users/urls.py rename to src/apps/users/urls.py index 92f421efcec..334458c3d20 100644 --- a/src/users/urls.py +++ b/src/apps/users/urls.py @@ -1,6 +1,6 @@ from django.urls import path -from users.api.views import SelfView +from apps.users.api.views import SelfView urlpatterns = [ path("me/", SelfView.as_view()), diff --git a/src/banking/atol/__init__.py b/src/banking/atol/__init__.py deleted file mode 100644 index 3e18905163b..00000000000 --- a/src/banking/atol/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from banking.atol.client import AtolClient - -__all__ = [ - "AtolClient", -] diff --git a/src/chains/admin/__init__.py b/src/chains/admin/__init__.py deleted file mode 100644 index 78929a1f192..00000000000 --- a/src/chains/admin/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from chains.admin.chain import ChainAdmin -from chains.admin.message import MessageAdmin - -__all__ = [ - "ChainAdmin", - "MessageAdmin", -] diff --git a/src/chains/models/__init__.py b/src/chains/models/__init__.py deleted file mode 100644 index 34c634245a4..00000000000 --- a/src/chains/models/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -from chains.models.chain import Chain -from chains.models.message import Message -from chains.models.progress import Progress - -__all__ = [ - "Chain", - "Message", - "Progress", -] diff --git a/src/chains/services/__init__.py b/src/chains/services/__init__.py deleted file mode 100644 index 1465384da6c..00000000000 --- a/src/chains/services/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from chains.services.chain_sender import ChainSender -from chains.services.message_sender import MessageSender - -__all__ = [ - "ChainSender", - "MessageSender", -] diff --git a/src/conftest.py b/src/conftest.py deleted file mode 100644 index 85866b814be..00000000000 --- a/src/conftest.py +++ /dev/null @@ -1,20 +0,0 @@ -import pytest - -from django.core.cache import cache - -pytest_plugins = [ - "app.factory", - "app.fixtures", - "users.fixtures", - "orders.factory", - "diplomas.factory", - "products.factory", - "products.fixtures", -] - - -@pytest.fixture(autouse=True) -def _cache(request): - """Clear django cache after each test run.""" - yield - cache.clear() diff --git a/src/app/.env.ci b/src/core/.env.ci similarity index 100% rename from src/app/.env.ci rename to src/core/.env.ci diff --git a/src/studying/__init__.py b/src/core/__init__.py similarity index 100% rename from src/studying/__init__.py rename to src/core/__init__.py diff --git a/src/core/admin/__init__.py b/src/core/admin/__init__.py new file mode 100644 index 00000000000..6f372cc305b --- /dev/null +++ b/src/core/admin/__init__.py @@ -0,0 +1,12 @@ +from django.contrib import admin + +from core.admin.model_admin import ModelAdmin +from core.admin.model_admin import StackedInline +from core.admin.model_admin import TabularInline + +__all__ = [ + "admin", + "ModelAdmin", + "StackedInline", + "TabularInline", +] diff --git a/src/app/admin/filters.py b/src/core/admin/filters.py similarity index 100% rename from src/app/admin/filters.py rename to src/core/admin/filters.py diff --git a/src/app/admin/mixin.py b/src/core/admin/mixin.py similarity index 98% rename from src/app/admin/mixin.py rename to src/core/admin/mixin.py index 8b12c15c15c..44dd43d923a 100644 --- a/src/app/admin/mixin.py +++ b/src/core/admin/mixin.py @@ -13,7 +13,7 @@ from django.utils import timezone from django.utils.html import format_html -from app.admin.widgets import AppNumberInput +from core.admin.widgets import AppNumberInput class DjangoModelAdminProtocol(Protocol): diff --git a/src/app/admin/model_admin.py b/src/core/admin/model_admin.py similarity index 88% rename from src/app/admin/model_admin.py rename to src/core/admin/model_admin.py index 56e5f0c9b51..18e163457be 100644 --- a/src/app/admin/model_admin.py +++ b/src/core/admin/model_admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -from app.admin.mixin import AppAdminMixin +from core.admin.mixin import AppAdminMixin class ModelAdmin(AppAdminMixin, admin.ModelAdmin): # type: ignore diff --git a/src/app/admin/widgets.py b/src/core/admin/widgets.py similarity index 100% rename from src/app/admin/widgets.py rename to src/core/admin/widgets.py diff --git a/src/app/api/filters.py b/src/core/api/filters.py similarity index 100% rename from src/app/api/filters.py rename to src/core/api/filters.py diff --git a/src/app/api/mixins.py b/src/core/api/mixins.py similarity index 100% rename from src/app/api/mixins.py rename to src/core/api/mixins.py diff --git a/src/app/celery.py b/src/core/celery.py similarity index 81% rename from src/app/celery.py rename to src/core/celery.py index e3695450359..735ecddfadb 100644 --- a/src/app/celery.py +++ b/src/core/celery.py @@ -5,13 +5,13 @@ from django.conf import settings -from app.conf.environ import env +from core.conf.environ import env __all__ = [ "celery", ] -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app.settings") +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "core.settings") celery = Celery("app") @@ -22,12 +22,12 @@ task_ignore_result=True, task_store_errors_even_if_ignored=True, task_acks_late=True, - task_routes={"amocrm.tasks.*": {"queue": "amocrm"}}, + task_routes={"apps.amocrm.tasks.*": {"queue": "amocrm"}}, timezone=env("TIME_ZONE", cast=str, default="Europe/Moscow"), enable_utc=False, beat_schedule={ "send_active_chains": { - "task": "chains.tasks.send_active_chains", + "task": "apps.chains.tasks.send_active_chains", "schedule": crontab(hour="*", minute="*/5"), }, "amocrm_push_all_products_and_product_groups": { diff --git a/src/app/conf/api.py b/src/core/conf/api.py similarity index 89% rename from src/app/conf/api.py rename to src/core/conf/api.py index c866f75b235..69b1aad2b81 100644 --- a/src/app/conf/api.py +++ b/src/core/conf/api.py @@ -1,4 +1,4 @@ -from app.conf.environ import env +from core.conf.environ import env DISABLE_THROTTLING = env("DISABLE_THROTTLING", cast=bool, default=env("DEBUG")) @@ -12,11 +12,11 @@ "rest_framework_jwt.authentication.JSONWebTokenAuthentication", ], "DEFAULT_RENDERER_CLASSES": [ - "app.renderers.AppJSONRenderer", + "core.renderers.AppJSONRenderer", ], "DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.URLPathVersioning", - "DEFAULT_PAGINATION_CLASS": "app.pagination.AppPagination", - "EXCEPTION_HANDLER": "app.exceptions.app_service_exception_handler", + "DEFAULT_PAGINATION_CLASS": "core.pagination.AppPagination", + "EXCEPTION_HANDLER": "core.exceptions.app_service_exception_handler", "PAGE_SIZE": 20, "DEFAULT_THROTTLE_RATES": { "anon-auth": "10/min", diff --git a/src/app/conf/auth.py b/src/core/conf/auth.py similarity index 94% rename from src/app/conf/auth.py rename to src/core/conf/auth.py index 0792b2deb9b..9986ae78153 100644 --- a/src/app/conf/auth.py +++ b/src/core/conf/auth.py @@ -1,7 +1,7 @@ from datetime import timedelta from os import path -from app.conf.environ import env +from core.conf.environ import env AUTH_USER_MODEL = "users.User" @@ -52,7 +52,7 @@ "JWT_ALGORITHM": "RS256", "JWT_PRIVATE_KEY": keys["private"], "JWT_PUBLIC_KEY": keys["public"], - "JWT_PAYLOAD_HANDLER": "a12n.jwt.payload_handler", + "JWT_PAYLOAD_HANDLER": "apps.a12n.jwt.payload_handler", } DANGEROUSLY_MAKE_ONE_TIME_PASSWORDLESS_TOKEN_MULTI_PASS = env("DANGEROUSLY_MAKE_ONE_TIME_PASSWORDLESS_TOKEN_MULTI_PASS", cast=bool, default=False) diff --git a/src/core/conf/boilerplate.py b/src/core/conf/boilerplate.py new file mode 100644 index 00000000000..f293b221504 --- /dev/null +++ b/src/core/conf/boilerplate.py @@ -0,0 +1,10 @@ +from pathlib import Path + +BASE_DIR = Path(__file__).resolve().parent.parent + +ROOT_URLCONF = "core.urls" + +# Disable built-in ./manage.py test command in favor of pytest +TEST_RUNNER = "core.test.disable_test_command_runner.DisableTestCommandRunner" + +WSGI_APPLICATION = "core.wsgi.application" diff --git a/src/app/conf/cache.py b/src/core/conf/cache.py similarity index 87% rename from src/app/conf/cache.py rename to src/core/conf/cache.py index c2da0ff604a..709ba575b9b 100644 --- a/src/app/conf/cache.py +++ b/src/core/conf/cache.py @@ -1,4 +1,4 @@ -from app.conf.environ import env +from core.conf.environ import env if env("NO_CACHE", cast=bool, default=False): CACHES = { diff --git a/src/app/conf/db.py b/src/core/conf/db.py similarity index 92% rename from src/app/conf/db.py rename to src/core/conf/db.py index aec5a168506..f36bf96e0d0 100644 --- a/src/app/conf/db.py +++ b/src/core/conf/db.py @@ -1,4 +1,4 @@ -from app.conf.environ import env +from core.conf.environ import env # Database # https://docs.djangoproject.com/en/2.2/ref/settings/#databases diff --git a/src/app/conf/debug_toolbar.py b/src/core/conf/debug_toolbar.py similarity index 100% rename from src/app/conf/debug_toolbar.py rename to src/core/conf/debug_toolbar.py diff --git a/src/app/conf/email.py b/src/core/conf/email.py similarity index 96% rename from src/app/conf/email.py rename to src/core/conf/email.py index a564a757a28..07ba3e08c4d 100644 --- a/src/app/conf/email.py +++ b/src/core/conf/email.py @@ -1,4 +1,4 @@ -from app.conf.environ import env +from core.conf.environ import env EMAIL_ENABLED = env("EMAIL_ENABLED", cast=bool, default=False) diff --git a/src/core/conf/environ.py b/src/core/conf/environ.py new file mode 100644 index 00000000000..a5557bf564e --- /dev/null +++ b/src/core/conf/environ.py @@ -0,0 +1,18 @@ +import environ # type: ignore[import-untyped] + +from core.conf.boilerplate import BASE_DIR + +env = environ.Env( + DEBUG=(bool, False), + CI=(bool, False), +) + +envpath = BASE_DIR / ".env" + +if envpath.exists(): + env.read_env(envpath) + + +__all__ = [ + "env", +] diff --git a/src/app/conf/features.py b/src/core/conf/features.py similarity index 88% rename from src/app/conf/features.py rename to src/core/conf/features.py index ac90ff579f2..ce977636fed 100644 --- a/src/app/conf/features.py +++ b/src/core/conf/features.py @@ -1,4 +1,4 @@ -from app.conf.environ import env +from core.conf.environ import env DEBUG = env("DEBUG", cast=bool, default=False) diff --git a/src/app/conf/healthchecks.py b/src/core/conf/healthchecks.py similarity index 100% rename from src/app/conf/healthchecks.py rename to src/core/conf/healthchecks.py diff --git a/src/app/conf/http.py b/src/core/conf/http.py similarity index 95% rename from src/app/conf/http.py rename to src/core/conf/http.py index 14aaeaac1de..c6c4ba302ee 100644 --- a/src/app/conf/http.py +++ b/src/core/conf/http.py @@ -1,4 +1,4 @@ -from app.conf.environ import env +from core.conf.environ import env ABSOLUTE_HOST = env("ABSOLUTE_HOST", cast=str, default="https://app.tough-dev.school") ALLOWED_HOSTS = ["*"] diff --git a/src/app/conf/i18n.py b/src/core/conf/i18n.py similarity index 100% rename from src/app/conf/i18n.py rename to src/core/conf/i18n.py diff --git a/src/app/conf/installed_apps.py b/src/core/conf/installed_apps.py similarity index 58% rename from src/app/conf/installed_apps.py rename to src/core/conf/installed_apps.py index 0b58053f546..f03f5d7b072 100644 --- a/src/app/conf/installed_apps.py +++ b/src/core/conf/installed_apps.py @@ -1,36 +1,41 @@ +# fmt: off INSTALLED_APPS = [ - "a12n", - "app", - "amocrm", - "banking", - "diplomas", - "homework", - "magnets", - "notion", - "orders", - "products", - "studying", - "tinkoff", - "stripebank", - "users", - "chains", - "mailing", - "corsheaders", - "anymail", - "drf_spectacular", - "drf_spectacular_sidecar", - "rest_framework", - "rest_framework.authtoken", - "drf_recaptcha", - "django_filters", - "prettyjson", - "dj_rest_auth", - "axes", - "debug_toolbar", "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", - "django.contrib.sessions", "django.contrib.messages", + "django.contrib.sessions", "django.contrib.staticfiles", + + "anymail", + "axes", + "corsheaders", + "debug_toolbar", + "dj_rest_auth", + "django_filters", + "drf_recaptcha", + "drf_spectacular", + "drf_spectacular_sidecar", + "prettyjson", + "rest_framework", + "rest_framework.authtoken", + + "apps.a12n", + "apps.amocrm", + "apps.banking", + "apps.chains", + "apps.diplomas", + "apps.homework", + "apps.magnets", + "apps.mailing", + "apps.notion", + "apps.orders", + "apps.products", + "apps.stripebank", + "apps.studying", + "apps.tinkoff", + "apps.users", + + "core", ] +# fmt: on diff --git a/src/app/conf/integrations/amocrm.py b/src/core/conf/integrations/amocrm.py similarity index 92% rename from src/app/conf/integrations/amocrm.py rename to src/core/conf/integrations/amocrm.py index f964949dbe7..cbd015806f1 100644 --- a/src/app/conf/integrations/amocrm.py +++ b/src/core/conf/integrations/amocrm.py @@ -1,4 +1,4 @@ -from app.conf.environ import env +from core.conf.environ import env AMOCRM_BASE_URL = env("AMOCRM_BASE_URL", cast=str, default="") AMOCRM_REDIRECT_URL = env("AMOCRM_REDIRECT_URL", cast=str, default="") diff --git a/src/app/conf/integrations/atol.py b/src/core/conf/integrations/atol.py similarity index 90% rename from src/app/conf/integrations/atol.py rename to src/core/conf/integrations/atol.py index aae262c6c5c..83ed8a89d6e 100644 --- a/src/app/conf/integrations/atol.py +++ b/src/core/conf/integrations/atol.py @@ -1,4 +1,4 @@ -from app.conf.environ import env +from core.conf.environ import env ATOL_LOGIN = env("ATOL_LOGIN", cast=str, default="") ATOL_PASSWORD = env("ATOL_PASSWORD", cast=str, default="") diff --git a/src/app/conf/integrations/banking/banking.py b/src/core/conf/integrations/banking/banking.py similarity index 78% rename from src/app/conf/integrations/banking/banking.py rename to src/core/conf/integrations/banking/banking.py index 91f8fddc389..7b536b938d2 100644 --- a/src/app/conf/integrations/banking/banking.py +++ b/src/core/conf/integrations/banking/banking.py @@ -1,3 +1,3 @@ -from app.conf.environ import env +from core.conf.environ import env BANKS_REFUNDS_ENABLED = env("BANKS_REFUNDS_ENABLED", cast=bool, default=not env("DEBUG")) # by default the opposite to DEBUG diff --git a/src/app/conf/integrations/banking/stripe.py b/src/core/conf/integrations/banking/stripe.py similarity index 80% rename from src/app/conf/integrations/banking/stripe.py rename to src/core/conf/integrations/banking/stripe.py index fd78d4295f8..4305760f79b 100644 --- a/src/app/conf/integrations/banking/stripe.py +++ b/src/core/conf/integrations/banking/stripe.py @@ -1,4 +1,4 @@ -from app.conf.environ import env +from core.conf.environ import env STRIPE_API_KEY = env("STRIPE_API_KEY", cast=str, default="") STRIPE_WEBHOOK_SECRET = env("STRIPE_WEBHOOK_SECRET", cast=str, default="") diff --git a/src/app/conf/integrations/banking/tinkoff.py b/src/core/conf/integrations/banking/tinkoff.py similarity index 94% rename from src/app/conf/integrations/banking/tinkoff.py rename to src/core/conf/integrations/banking/tinkoff.py index 84ec85bbf8a..38e742cac05 100644 --- a/src/app/conf/integrations/banking/tinkoff.py +++ b/src/core/conf/integrations/banking/tinkoff.py @@ -1,4 +1,4 @@ -from app.conf.environ import env +from core.conf.environ import env TINKOFF_TERMINAL_KEY = env("TINKOFF_TERMINAL_KEY", default=None) TINKOFF_TERMINAL_PASSWORD = env("TINKOFF_TERMINAL_PASSWORD", default=None) diff --git a/src/app/conf/integrations/clickmeetings.py b/src/core/conf/integrations/clickmeetings.py similarity index 69% rename from src/app/conf/integrations/clickmeetings.py rename to src/core/conf/integrations/clickmeetings.py index 0c21824abf3..5e0de6fe77d 100644 --- a/src/app/conf/integrations/clickmeetings.py +++ b/src/core/conf/integrations/clickmeetings.py @@ -1,3 +1,3 @@ -from app.conf.environ import env +from core.conf.environ import env CLICKMEETING_API_KEY = env("CLICKMEETING_API_KEY", default=None, cast=str) diff --git a/src/app/conf/integrations/diploma_generator.py b/src/core/conf/integrations/diploma_generator.py similarity index 80% rename from src/app/conf/integrations/diploma_generator.py rename to src/core/conf/integrations/diploma_generator.py index 60729bb546d..085ddae7932 100644 --- a/src/app/conf/integrations/diploma_generator.py +++ b/src/core/conf/integrations/diploma_generator.py @@ -1,4 +1,4 @@ -from app.conf.environ import env +from core.conf.environ import env DIPLOMA_GENERATOR_HOST = env("DIPLOMA_GENERATOR_HOST", default="") DIPLOMA_GENERATOR_TOKEN = env("DIPLOMA_GENERATOR_TOKEN", default="") diff --git a/src/app/conf/integrations/notion.py b/src/core/conf/integrations/notion.py similarity index 87% rename from src/app/conf/integrations/notion.py rename to src/core/conf/integrations/notion.py index a8f2bd744eb..854421fbc8f 100644 --- a/src/app/conf/integrations/notion.py +++ b/src/core/conf/integrations/notion.py @@ -1,4 +1,4 @@ -from app.conf.environ import env +from core.conf.environ import env NOTION_MIDDLEWARE_URL = env("NOTION_MIDDLEWARE_URL", cast=str, default="") NOTION_MIDDLEWARE_TIMEOUT = env("NOTION_MIDDLEWARE_TIMEOUT", cast=int, default=15) diff --git a/src/app/conf/integrations/tg.py b/src/core/conf/integrations/tg.py similarity index 80% rename from src/app/conf/integrations/tg.py rename to src/core/conf/integrations/tg.py index f2d22b124a6..80db5c2ff71 100644 --- a/src/app/conf/integrations/tg.py +++ b/src/core/conf/integrations/tg.py @@ -1,4 +1,4 @@ -from app.conf.environ import env +from core.conf.environ import env BOT_TOKEN = env("BOT_TOKEN", cast=str, default=None) HAPPINESS_MESSAGES_CHAT_ID = env("HAPPINESS_MESSAGES_CHAT_ID", cast=str, default=None) diff --git a/src/app/conf/markdown.py b/src/core/conf/markdown.py similarity index 100% rename from src/app/conf/markdown.py rename to src/core/conf/markdown.py diff --git a/src/app/conf/media.py b/src/core/conf/media.py similarity index 75% rename from src/app/conf/media.py rename to src/core/conf/media.py index 4a3a5ff06c1..8e4da0bb9fa 100644 --- a/src/app/conf/media.py +++ b/src/core/conf/media.py @@ -1,4 +1,4 @@ -from app.conf.environ import env +from core.conf.environ import env MEDIA_URL = env("MEDIA_URL", default="/media/") MEDIA_ROOT = env("MEDIA_ROOT", cast=str, default="media") diff --git a/src/app/conf/middleware.py b/src/core/conf/middleware.py similarity index 70% rename from src/app/conf/middleware.py rename to src/core/conf/middleware.py index 7a0bbd64a78..4d85a38c43b 100644 --- a/src/app/conf/middleware.py +++ b/src/core/conf/middleware.py @@ -1,4 +1,4 @@ -from app.conf.environ import env +from core.conf.environ import env MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", @@ -11,10 +11,10 @@ "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", "debug_toolbar.middleware.DebugToolbarMiddleware", - "app.middleware.real_ip.real_ip_middleware", - "app.middleware.set_user_from_non_django_authentication.JWTAuthMiddleware", - "app.middleware.set_user_from_non_django_authentication.TokenAuthMiddleware", - "app.middleware.global_current_user.set_global_user", + "core.middleware.real_ip.real_ip_middleware", + "core.middleware.set_user_from_non_django_authentication.JWTAuthMiddleware", + "core.middleware.set_user_from_non_django_authentication.TokenAuthMiddleware", + "core.middleware.global_current_user.set_global_user", "axes.middleware.AxesMiddleware", ] diff --git a/src/app/conf/sentry.py b/src/core/conf/sentry.py similarity index 86% rename from src/app/conf/sentry.py rename to src/core/conf/sentry.py index fc1692d6b4c..8365080c35d 100644 --- a/src/app/conf/sentry.py +++ b/src/core/conf/sentry.py @@ -1,4 +1,4 @@ -from app.conf.environ import env +from core.conf.environ import env SENTRY_DSN = env("SENTRY_DSN", cast=str, default="") @@ -12,8 +12,8 @@ def strip_transactions(event, hint): # type: ignore if event["transaction"] in ( "/api/v2/healthchecks/{service}/", - "chains.tasks.send_chain_messages", - "chains.tasks.send_active_chains", + "apps.chains.tasks.send_chain_messages", + "apps.chains.tasks.send_active_chains", "/admin/jsi18n/", ): return None diff --git a/src/app/conf/static.py b/src/core/conf/static.py similarity index 60% rename from src/app/conf/static.py rename to src/core/conf/static.py index bd0c5f2b9ec..a3b9333c775 100644 --- a/src/app/conf/static.py +++ b/src/core/conf/static.py @@ -1,7 +1,7 @@ import os.path -from app.conf.boilerplate import BASE_DIR -from app.conf.environ import env +from core.conf.boilerplate import BASE_DIR +from core.conf.environ import env STATIC_URL = env("STATIC_URL", default="/static/") STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles") diff --git a/src/app/conf/storage.py b/src/core/conf/storage.py similarity index 96% rename from src/app/conf/storage.py rename to src/core/conf/storage.py index 903f20e9c49..23da2b6c3b6 100644 --- a/src/app/conf/storage.py +++ b/src/core/conf/storage.py @@ -1,4 +1,4 @@ -from app.conf.environ import env +from core.conf.environ import env # https://docs.djangoproject.com/en/4.2/ref/settings/#storages STORAGES = { diff --git a/src/core/conf/tags.py b/src/core/conf/tags.py new file mode 100644 index 00000000000..dc3ae7f0133 --- /dev/null +++ b/src/core/conf/tags.py @@ -0,0 +1,6 @@ +TAG_PIPELINE = [ + "apps.users.tags.AnyPurchaseTag", + "apps.users.tags.StartedTag", + "apps.users.tags.PurchasedTag", + "apps.users.tags.B2BTag", +] diff --git a/src/app/conf/templates.py b/src/core/conf/templates.py similarity index 100% rename from src/app/conf/templates.py rename to src/core/conf/templates.py diff --git a/src/app/conf/timezone.py b/src/core/conf/timezone.py similarity index 70% rename from src/app/conf/timezone.py rename to src/core/conf/timezone.py index e68f9c50614..22ee207bed7 100644 --- a/src/app/conf/timezone.py +++ b/src/core/conf/timezone.py @@ -1,4 +1,4 @@ -from app.conf.environ import env +from core.conf.environ import env USE_TZ = True diff --git a/src/app/conf/vat.py b/src/core/conf/vat.py similarity index 58% rename from src/app/conf/vat.py rename to src/core/conf/vat.py index f0bd92e490b..c6110dc708f 100644 --- a/src/app/conf/vat.py +++ b/src/core/conf/vat.py @@ -1,3 +1,3 @@ -from app.conf.environ import env +from core.conf.environ import env VAT_ID = env("VAT_ID", cast=str, default=None) diff --git a/src/app/conf/warnings.py b/src/core/conf/warnings.py similarity index 100% rename from src/app/conf/warnings.py rename to src/core/conf/warnings.py diff --git a/src/app/current_user.py b/src/core/current_user.py similarity index 94% rename from src/app/current_user.py rename to src/core/current_user.py index 33217614130..1e870463c7e 100644 --- a/src/app/current_user.py +++ b/src/core/current_user.py @@ -1,7 +1,7 @@ from threading import current_thread from threading import local -from users.models import User +from apps.users.models import User _thread_locals = local() diff --git a/src/app/exceptions.py b/src/core/exceptions.py similarity index 100% rename from src/app/exceptions.py rename to src/core/exceptions.py diff --git a/src/app/files.py b/src/core/files.py similarity index 92% rename from src/app/files.py rename to src/core/files.py index e152253548e..7bfc2fc6fb2 100644 --- a/src/app/files.py +++ b/src/core/files.py @@ -11,7 +11,7 @@ class RandomFileName: Usage: - from app.files import RandomFileName + from core.files import RandomFileName class MyModel(models.Model): image = models.ImageField(upload_to=RandomFileName('images/folder') diff --git a/src/app/helpers.py b/src/core/helpers.py similarity index 100% rename from src/app/helpers.py rename to src/core/helpers.py diff --git a/src/core/integrations/dashamail/__init__.py b/src/core/integrations/dashamail/__init__.py new file mode 100644 index 00000000000..78a428d6a1e --- /dev/null +++ b/src/core/integrations/dashamail/__init__.py @@ -0,0 +1,7 @@ +from core.integrations.dashamail.client import AppDashamail +from core.integrations.dashamail.exceptions import DashamailException + +__all__ = [ + "AppDashamail", + "DashamailException", +] diff --git a/src/app/integrations/dashamail/client.py b/src/core/integrations/dashamail/client.py similarity index 91% rename from src/app/integrations/dashamail/client.py rename to src/core/integrations/dashamail/client.py index 6a2ed67b0bf..b9029a50462 100644 --- a/src/app/integrations/dashamail/client.py +++ b/src/core/integrations/dashamail/client.py @@ -1,8 +1,8 @@ from django.conf import settings -from app.integrations.dashamail.exceptions import DashamailSubscriptionFailed -from app.integrations.dashamail.exceptions import DashamailUpdateFailed -from app.integrations.dashamail.http import DashamailHTTP +from core.integrations.dashamail.exceptions import DashamailSubscriptionFailed +from core.integrations.dashamail.exceptions import DashamailUpdateFailed +from core.integrations.dashamail.http import DashamailHTTP class AppDashamail: diff --git a/src/app/integrations/dashamail/exceptions.py b/src/core/integrations/dashamail/exceptions.py similarity index 100% rename from src/app/integrations/dashamail/exceptions.py rename to src/core/integrations/dashamail/exceptions.py diff --git a/src/app/integrations/dashamail/http.py b/src/core/integrations/dashamail/http.py similarity index 95% rename from src/app/integrations/dashamail/http.py rename to src/core/integrations/dashamail/http.py index 2b4063c22fe..2bcde832fa3 100644 --- a/src/app/integrations/dashamail/http.py +++ b/src/core/integrations/dashamail/http.py @@ -4,7 +4,7 @@ from django.conf import settings -from app.integrations.dashamail import exceptions +from core.integrations.dashamail import exceptions class DashamailHTTP: diff --git a/src/app/integrations/dashamail/subscription_updater.py b/src/core/integrations/dashamail/subscription_updater.py similarity index 88% rename from src/app/integrations/dashamail/subscription_updater.py rename to src/core/integrations/dashamail/subscription_updater.py index 28c736d2b92..6d61ee56d05 100644 --- a/src/app/integrations/dashamail/subscription_updater.py +++ b/src/core/integrations/dashamail/subscription_updater.py @@ -1,11 +1,11 @@ from dataclasses import dataclass from typing import final, TYPE_CHECKING -from app.integrations.dashamail import AppDashamail -from app.services import BaseService +from core.integrations.dashamail import AppDashamail +from core.services import BaseService if TYPE_CHECKING: - from users.models import User + from apps.users.models import User @final diff --git a/src/app/integrations/s3.py b/src/core/integrations/s3.py similarity index 100% rename from src/app/integrations/s3.py rename to src/core/integrations/s3.py diff --git a/src/app/integrations/tg.py b/src/core/integrations/tg.py similarity index 100% rename from src/app/integrations/tg.py rename to src/core/integrations/tg.py diff --git a/src/app/management/commands/clean_antispam_logs.py b/src/core/management/commands/clean_antispam_logs.py similarity index 84% rename from src/app/management/commands/clean_antispam_logs.py rename to src/core/management/commands/clean_antispam_logs.py index bba42a9e2a6..155c44fde01 100644 --- a/src/app/management/commands/clean_antispam_logs.py +++ b/src/core/management/commands/clean_antispam_logs.py @@ -6,7 +6,7 @@ class Command(BaseCommand): help = "Clean antispam logs for outgoing email and marketing triggers" def handle(self, *args, **kwargs): - app_wide = apps.get_model("app.EmailLogEntry").objects.all().delete()[0] + app_wide = apps.get_model("core.EmailLogEntry").objects.all().delete()[0] marketing = apps.get_model("triggers.TriggerLogEntry").objects.all().delete()[0] self.stdout.write(self.style.SUCCESS(f"Removed {app_wide} email log entries and {marketing} marketing trigger log entries.")) diff --git a/src/app/markdown.py b/src/core/markdown.py similarity index 100% rename from src/app/markdown.py rename to src/core/markdown.py diff --git a/src/app/middleware/global_current_user.py b/src/core/middleware/global_current_user.py similarity index 72% rename from src/app/middleware/global_current_user.py rename to src/core/middleware/global_current_user.py index f5f42229845..f5065615f7d 100644 --- a/src/app/middleware/global_current_user.py +++ b/src/core/middleware/global_current_user.py @@ -1,5 +1,5 @@ -from app.current_user import set_current_user -from app.current_user import unset_current_user +from core.current_user import set_current_user +from core.current_user import unset_current_user def set_global_user(get_response): # type: ignore diff --git a/src/app/middleware/real_ip.py b/src/core/middleware/real_ip.py similarity index 100% rename from src/app/middleware/real_ip.py rename to src/core/middleware/real_ip.py diff --git a/src/app/middleware/set_user_from_non_django_authentication.py b/src/core/middleware/set_user_from_non_django_authentication.py similarity index 97% rename from src/app/middleware/set_user_from_non_django_authentication.py rename to src/core/middleware/set_user_from_non_django_authentication.py index b14963ccada..d2af9acb0af 100644 --- a/src/app/middleware/set_user_from_non_django_authentication.py +++ b/src/core/middleware/set_user_from_non_django_authentication.py @@ -9,7 +9,7 @@ from django.contrib.auth.middleware import get_user from django.utils.functional import SimpleLazyObject -from users.models import User +from apps.users.models import User class UserMiddleware: diff --git a/src/app/migrations/0001_CourseMailLog.py b/src/core/migrations/0001_CourseMailLog.py similarity index 100% rename from src/app/migrations/0001_CourseMailLog.py rename to src/core/migrations/0001_CourseMailLog.py diff --git a/src/app/migrations/0002_DropTheOnetimeApp.py b/src/core/migrations/0002_DropTheOnetimeApp.py similarity index 91% rename from src/app/migrations/0002_DropTheOnetimeApp.py rename to src/core/migrations/0002_DropTheOnetimeApp.py index 5d6159d4c9c..d2c4a858a8d 100644 --- a/src/app/migrations/0002_DropTheOnetimeApp.py +++ b/src/core/migrations/0002_DropTheOnetimeApp.py @@ -10,7 +10,7 @@ def drop_old_contenttypes(apps, schema_editor): class Migration(migrations.Migration): dependencies = [ - ('app', '0001_CourseMailLog'), + ('core', '0001_CourseMailLog'), ] operations = [ diff --git a/src/app/migrations/0003_RenameCoursesAppPt1.py b/src/core/migrations/0003_RenameCoursesAppPt1.py similarity index 86% rename from src/app/migrations/0003_RenameCoursesAppPt1.py rename to src/core/migrations/0003_RenameCoursesAppPt1.py index 8583f67d6fa..4e41155e719 100644 --- a/src/app/migrations/0003_RenameCoursesAppPt1.py +++ b/src/core/migrations/0003_RenameCoursesAppPt1.py @@ -6,7 +6,7 @@ class Migration(migrations.Migration): dependencies = [ - ('app', '0002_DropTheOnetimeApp'), + ('core', '0002_DropTheOnetimeApp'), ] operations = [ diff --git a/src/app/migrations/0004_EmailLogEntryMovedToDedicatedApp.py b/src/core/migrations/0004_EmailLogEntryMovedToDedicatedApp.py similarity index 87% rename from src/app/migrations/0004_EmailLogEntryMovedToDedicatedApp.py rename to src/core/migrations/0004_EmailLogEntryMovedToDedicatedApp.py index 46e2de5499e..182e8ea9a4b 100644 --- a/src/app/migrations/0004_EmailLogEntryMovedToDedicatedApp.py +++ b/src/core/migrations/0004_EmailLogEntryMovedToDedicatedApp.py @@ -6,7 +6,7 @@ class Migration(migrations.Migration): dependencies = [ - ('app', '0003_RenameCoursesAppPt1'), + ('core', '0003_RenameCoursesAppPt1'), ('mailing', '0001_EmailLogEntryMovedToDedicatedApp'), ] diff --git a/src/app/migrations/0005_RemoveTriggersApp.py b/src/core/migrations/0005_RemoveTriggersApp.py similarity index 88% rename from src/app/migrations/0005_RemoveTriggersApp.py rename to src/core/migrations/0005_RemoveTriggersApp.py index 9816077b34f..9144c35cf95 100644 --- a/src/app/migrations/0005_RemoveTriggersApp.py +++ b/src/core/migrations/0005_RemoveTriggersApp.py @@ -10,7 +10,7 @@ def remove_contenttypes(apps, schema_editor): class Migration(migrations.Migration): dependencies = [ - ("app", "0004_EmailLogEntryMovedToDedicatedApp"), + ("core", "0004_EmailLogEntryMovedToDedicatedApp"), ] operations = [ diff --git a/src/studying/migrations/__init__.py b/src/core/migrations/__init__.py similarity index 100% rename from src/studying/migrations/__init__.py rename to src/core/migrations/__init__.py diff --git a/src/app/models.py b/src/core/models.py similarity index 100% rename from src/app/models.py rename to src/core/models.py diff --git a/src/app/pagination.py b/src/core/pagination.py similarity index 100% rename from src/app/pagination.py rename to src/core/pagination.py diff --git a/src/app/permissions.py b/src/core/permissions.py similarity index 100% rename from src/app/permissions.py rename to src/core/permissions.py diff --git a/src/app/pricing.py b/src/core/pricing.py similarity index 100% rename from src/app/pricing.py rename to src/core/pricing.py diff --git a/src/app/renderers.py b/src/core/renderers.py similarity index 100% rename from src/app/renderers.py rename to src/core/renderers.py diff --git a/src/app/serializers.py b/src/core/serializers.py similarity index 94% rename from src/app/serializers.py rename to src/core/serializers.py index 06c7f63e10a..d1470f8fe75 100644 --- a/src/app/serializers.py +++ b/src/core/serializers.py @@ -2,7 +2,7 @@ from rest_framework import serializers -from app.markdown import markdownify +from core.markdown import markdownify class MarkdownField(serializers.ReadOnlyField): diff --git a/src/app/services.py b/src/core/services.py similarity index 100% rename from src/app/services.py rename to src/core/services.py diff --git a/src/app/settings.py b/src/core/settings.py similarity index 97% rename from src/app/settings.py rename to src/core/settings.py index 36b922a3b7b..bb39ebc779a 100644 --- a/src/app/settings.py +++ b/src/core/settings.py @@ -1,6 +1,6 @@ from split_settings.tools import include -from app.conf.environ import env +from core.conf.environ import env # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/ diff --git a/src/app/static/admin.css b/src/core/static/admin.css similarity index 100% rename from src/app/static/admin.css rename to src/core/static/admin.css diff --git a/src/app/static/prettyjson.css b/src/core/static/prettyjson.css similarity index 100% rename from src/app/static/prettyjson.css rename to src/core/static/prettyjson.css diff --git a/src/core/tasks/__init__.py b/src/core/tasks/__init__.py new file mode 100644 index 00000000000..c22c6a137c3 --- /dev/null +++ b/src/core/tasks/__init__.py @@ -0,0 +1,7 @@ +from core.tasks.dashamail import update_dashamail_subscription +from core.tasks.tg import send_telegram_message + +__all__ = [ + "send_telegram_message", + "update_dashamail_subscription", +] diff --git a/src/app/tasks/dashamail.py b/src/core/tasks/dashamail.py similarity index 70% rename from src/app/tasks/dashamail.py rename to src/core/tasks/dashamail.py index bd05f7a5483..caf517adbdf 100644 --- a/src/app/tasks/dashamail.py +++ b/src/core/tasks/dashamail.py @@ -2,9 +2,9 @@ from django.apps import apps -from app.celery import celery -from app.integrations.dashamail import DashamailException -from app.integrations.dashamail.subscription_updater import SubscriptionUpdater +from core.celery import celery +from core.integrations.dashamail import DashamailException +from core.integrations.dashamail.subscription_updater import SubscriptionUpdater @celery.task( diff --git a/src/app/tasks/tg.py b/src/core/tasks/tg.py similarity index 65% rename from src/app/tasks/tg.py rename to src/core/tasks/tg.py index 1ecf7b6221f..7441edc9c8b 100644 --- a/src/app/tasks/tg.py +++ b/src/core/tasks/tg.py @@ -1,5 +1,5 @@ -from app.celery import celery -from app.integrations import tg +from core.celery import celery +from core.integrations import tg @celery.task diff --git a/src/app/test/api_client.py b/src/core/test/api_client.py similarity index 98% rename from src/app/test/api_client.py rename to src/core/test/api_client.py index 960523c0440..274ba07739d 100644 --- a/src/app/test/api_client.py +++ b/src/core/test/api_client.py @@ -6,7 +6,7 @@ from rest_framework.authtoken.models import Token from rest_framework.test import APIClient -from users.models import User +from apps.users.models import User class DRFClient(APIClient): diff --git a/src/app/test/disable_test_command_runner.py b/src/core/test/disable_test_command_runner.py similarity index 100% rename from src/app/test/disable_test_command_runner.py rename to src/core/test/disable_test_command_runner.py diff --git a/src/app/test/factory.py b/src/core/test/factory.py similarity index 100% rename from src/app/test/factory.py rename to src/core/test/factory.py diff --git a/src/app/test/mixer.py b/src/core/test/mixer.py similarity index 100% rename from src/app/test/mixer.py rename to src/core/test/mixer.py diff --git a/src/app/throttling.py b/src/core/throttling.py similarity index 100% rename from src/app/throttling.py rename to src/core/throttling.py diff --git a/src/app/types.py b/src/core/types.py similarity index 100% rename from src/app/types.py rename to src/core/types.py diff --git a/src/app/urls/__init__.py b/src/core/urls/__init__.py similarity index 80% rename from src/app/urls/__init__.py rename to src/core/urls/__init__.py index 540f591630f..b5850883653 100644 --- a/src/app/urls/__init__.py +++ b/src/core/urls/__init__.py @@ -4,10 +4,10 @@ from django.contrib import admin from django.urls import path -from app.views import HomePageView +from core.views import HomePageView api = [ - path("v2/", include("app.urls.v2")), + path("v2/", include("core.urls.v2")), ] urlpatterns = [ diff --git a/src/core/urls/v2.py b/src/core/urls/v2.py new file mode 100644 index 00000000000..b9969c5ee6a --- /dev/null +++ b/src/core/urls/v2.py @@ -0,0 +1,28 @@ +from drf_spectacular.views import SpectacularAPIView +from drf_spectacular.views import SpectacularSwaggerView + +from django.urls import include +from django.urls import path + +urlpatterns = [ + path("auth/", include("apps.a12n.urls")), + path("banking/", include("apps.banking.urls")), + path("diplomas/", include("apps.diplomas.urls")), + path("homework/", include("apps.homework.urls")), + path("leads/", include("apps.magnets.urls")), + path("notion/", include("apps.notion.urls")), + path("orders/", include("apps.orders.urls")), + path("studies/", include("apps.studying.urls")), + path("users/", include("apps.users.urls")), + path("", include("apps.products.urls")), + path("healthchecks/", include("django_healthchecks.urls")), + path( + "docs/schema/", + SpectacularAPIView.as_view(api_version="v2"), + name="schema", + ), + path( + "docs/swagger/", + SpectacularSwaggerView.as_view(url_name="schema"), + ), +] diff --git a/src/app/validators.py b/src/core/validators.py similarity index 100% rename from src/app/validators.py rename to src/core/validators.py diff --git a/src/app/views.py b/src/core/views.py similarity index 93% rename from src/app/views.py rename to src/core/views.py index 51b2656ba2e..1dd235a6efe 100644 --- a/src/app/views.py +++ b/src/core/views.py @@ -4,7 +4,7 @@ from django.views.generic import RedirectView -from users.models import User +from apps.users.models import User class AuthenticatedRequest(Request): diff --git a/src/app/viewsets.py b/src/core/viewsets.py similarity index 99% rename from src/app/viewsets.py rename to src/core/viewsets.py index e6c1a0310d5..6e74539ccd3 100644 --- a/src/app/viewsets.py +++ b/src/core/viewsets.py @@ -11,7 +11,7 @@ from django.core.exceptions import ImproperlyConfigured -from app.validators import Validator +from core.validators import Validator __all__ = [ "AppViewSet", diff --git a/src/app/wsgi.py b/src/core/wsgi.py similarity index 83% rename from src/app/wsgi.py rename to src/core/wsgi.py index 347ac44a161..9f1fab67745 100644 --- a/src/app/wsgi.py +++ b/src/core/wsgi.py @@ -11,6 +11,6 @@ from django.core.wsgi import get_wsgi_application -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app.settings") +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "core.settings") application = get_wsgi_application() diff --git a/src/diplomas/services/__init__.py b/src/diplomas/services/__init__.py deleted file mode 100644 index 86cf062e713..00000000000 --- a/src/diplomas/services/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from diplomas.services.diploma_generator import DiplomaGenerator -from diplomas.services.diploma_regenerator import DiplomaRegenerator - -__all__ = [ - "DiplomaGenerator", - "DiplomaRegenerator", -] diff --git a/src/homework/admin/__init__.py b/src/homework/admin/__init__.py deleted file mode 100644 index 6f231ca1524..00000000000 --- a/src/homework/admin/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -import homework.admin.answer.admin # noqa -import homework.admin.question.admin # noqa diff --git a/src/homework/models/__init__.py b/src/homework/models/__init__.py deleted file mode 100644 index f97bfefe75f..00000000000 --- a/src/homework/models/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -from homework.models.answer import Answer -from homework.models.answer_access_log_entry import AnswerAccessLogEntry -from homework.models.answer_cross_check import AnswerCrossCheck -from homework.models.answer_image import AnswerImage -from homework.models.question import Question - -__all__ = [ - "Answer", - "AnswerAccessLogEntry", - "AnswerCrossCheck", - "AnswerImage", - "Question", -] diff --git a/src/homework/services/__init__.py b/src/homework/services/__init__.py deleted file mode 100644 index 0128d0cfcd6..00000000000 --- a/src/homework/services/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from homework.services.answer_crosscheck_dispatcher import AnswerCrossCheckDispatcher -from homework.services.new_answer_notifier import NewAnswerNotifier -from homework.services.question_crosscheck_dispatcher import QuestionCrossCheckDispatcher - -__all__ = [ - "AnswerCrossCheckDispatcher", - "NewAnswerNotifier", - "QuestionCrossCheckDispatcher", - "ReactionCreator", -] - -from homework.services.reaction_creator import ReactionCreator diff --git a/src/locale/ru/LC_MESSAGES/django.po b/src/locale/ru/LC_MESSAGES/django.po index 1fcd36f06dc..17359358899 100644 --- a/src/locale/ru/LC_MESSAGES/django.po +++ b/src/locale/ru/LC_MESSAGES/django.po @@ -19,228 +19,228 @@ msgstr "" "n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || " "(n%100>=11 && n%100<=14)? 2 : 3);\n" -#: a12n/signals/handlers.py:12 +#: core/a12n/signals/handlers.py:12 msgid "Too many failed login attempts" msgstr "" -#: app/admin/filters.py:25 +#: core/admin/filters.py:25 msgid "Yes" msgstr "Да" -#: app/admin/filters.py:26 +#: core/admin/filters.py:26 msgid "No" msgstr "Нет" -#: banking/base.py:23 +#: apps/banking/base.py:23 msgid "—" msgstr "" -#: banking/models.py:10 +#: apps/banking/models.py:10 msgid "Atol" msgstr "Атол" -#: banking/models.py:19 +#: apps/banking/models.py:19 msgid "Receipt" msgstr "Чек" -#: banking/models.py:20 +#: apps/banking/models.py:20 msgid "Receipts" msgstr "Чеки" -#: banking/zero_price_bank.py:20 +#: apps/banking/zero_price_bank.py:20 msgid "Zero Price" msgstr "Бесплатно" -#: chains/admin/chain.py:14 +#: apps/chains/admin/chain.py:14 msgid "Archived" msgstr "Заархивирована" -#: chains/admin/forms.py:17 chains/models/message.py:40 +#: apps/chains/admin/forms.py:17 apps/chains/models/message.py:40 msgid "Parent" msgstr "Родитель" -#: chains/admin/forms.py:21 chains/models/message.py:34 +#: apps/chains/admin/forms.py:21 apps/chains/models/message.py:34 msgid "Chain" msgstr "Цепочка" -#: chains/admin/forms.py:22 +#: apps/chains/admin/forms.py:22 msgid "" "Only the chains that are neither archived nor active for sending are listed" msgstr "В списке только не запущенные и не заархивированные цепочки" -#: chains/admin/message.py:50 chains/models/chain.py:34 diplomas/admin.py:58 -#: homework/admin/answer/admin.py:59 homework/admin/answer/admin.py:104 -#: orders/models/order.py:61 products/models/course.py:76 +#: apps/chains/admin/message.py:50 apps/chains/models/chain.py:34 apps/diplomas/admin.py:58 +#: apps/homework/admin/answer/admin.py:59 apps/homework/admin/answer/admin.py:104 +#: apps/orders/models/order.py:61 apps/products/models/course.py:76 msgid "Course" msgstr "Курс" -#: chains/models/chain.py:33 chains/models/message.py:33 -#: homework/models/question.py:15 magnets/models.py:21 -#: products/admin/course.py:18 +#: apps/chains/models/chain.py:33 apps/chains/models/message.py:33 +#: apps/homework/models/question.py:15 apps/magnets/models.py:21 +#: apps/products/admin/course.py:18 msgid "Name" msgstr "Название" -#: chains/models/chain.py:36 +#: apps/chains/models/chain.py:36 msgid "Sending is active" msgstr "Запущена" -#: chains/models/chain.py:37 +#: apps/chains/models/chain.py:37 msgid "The chain is archived" msgstr "Заархивирована" -#: chains/models/chain.py:40 +#: apps/chains/models/chain.py:40 msgid "Email chain" msgstr "Цепочка" -#: chains/models/chain.py:41 +#: apps/chains/models/chain.py:41 msgid "Email chains" msgstr "Цепочки" -#: chains/models/message.py:35 +#: apps/chains/models/message.py:35 msgid "Template id" msgstr "ID шаблона в постмарке" -#: chains/models/message.py:44 +#: apps/chains/models/message.py:44 msgid "Messages without parent will be sent upon start" msgstr "Если не поставить — сообщение уйдёт сразу при запуске цепочки" -#: chains/models/message.py:47 +#: apps/chains/models/message.py:47 msgid "Delay (minutes)" msgstr "Задержка (мин.)" -#: chains/models/message.py:47 +#: apps/chains/models/message.py:47 msgid "1440 for day, 10080 for week" msgstr "День — 1440, Неделя — 10080" -#: chains/models/message.py:50 +#: apps/chains/models/message.py:50 msgid "Email chain message" msgstr "Письмо" -#: chains/models/message.py:51 +#: apps/chains/models/message.py:51 msgid "Email chain messages" msgstr "Письма" -#: diplomas/admin.py:54 users/models.py:101 +#: apps/diplomas/admin.py:54 apps/users/models.py:101 msgid "Student" msgstr "Студент" -#: diplomas/admin.py:62 homework/models/question.py:20 +#: apps/diplomas/admin.py:62 apps/homework/models/question.py:20 msgid "Homework" msgstr "Домашка" -#: diplomas/admin.py:66 orders/admin/orders/admin.py:103 +#: apps/diplomas/admin.py:66 apps/orders/admin/orders/admin.py:103 msgid "Date" msgstr "Дата" -#: diplomas/admin.py:70 +#: apps/diplomas/admin.py:70 msgid "Send diploma to student" msgstr "Отправить студенту" -#: diplomas/admin.py:77 +#: apps/diplomas/admin.py:77 msgid "Regenerate diploma" msgstr "Перегенерировать" -#: diplomas/models.py:22 +#: apps/diplomas/models.py:22 msgid "Russian" msgstr "Русский" -#: diplomas/models.py:23 +#: apps/diplomas/models.py:23 msgid "English" msgstr "Английский" -#: diplomas/models.py:67 +#: apps/diplomas/models.py:67 msgid "May access diplomas of all students" msgstr "Видит все дипломы" -#: diplomas/models.py:70 +#: apps/diplomas/models.py:70 msgid "Diploma" msgstr "Диплом" -#: diplomas/models.py:71 +#: apps/diplomas/models.py:71 msgid "Diplomas" msgstr "Дипломы" -#: diplomas/models.py:96 +#: apps/diplomas/models.py:96 msgid "Check out https://is.gd/eutOYr for available templates" msgstr "Шаблоны искать в https://is.gd/eutOYr" -#: diplomas/models.py:98 +#: apps/diplomas/models.py:98 msgid "This template is for students that have completed the homework" msgstr "Для тех, кто сдал домашку" -#: diplomas/models.py:101 +#: apps/diplomas/models.py:101 msgid "Diploma template" msgstr "Шаблон диплома" -#: diplomas/models.py:102 +#: apps/diplomas/models.py:102 msgid "Diploma templates" msgstr "Шаблоны дипломов" -#: homework/admin/answer/admin.py:67 +#: apps/homework/admin/answer/admin.py:67 msgid "Crosschecking people" msgstr "Учеников проверяет" -#: homework/admin/answer/admin.py:72 homework/admin/answer/admin.py:116 +#: apps/homework/admin/answer/admin.py:72 apps/homework/admin/answer/admin.py:116 msgid "Author" msgstr "Автор" -#: homework/admin/answer/admin.py:112 +#: apps/homework/admin/answer/admin.py:112 msgid "Question" msgstr "Вопрос" -#: homework/admin/answer/admin.py:120 +#: apps/homework/admin/answer/admin.py:120 msgid "View" msgstr "" -#: homework/admin/answer/admin.py:125 +#: apps/homework/admin/answer/admin.py:125 msgid "Is checked" msgstr "" -#: homework/admin/answer/filters.py:10 +#: apps/homework/admin/answer/filters.py:10 msgid "Is root answer" msgstr "Первый ответ" -#: homework/admin/question/admin.py:31 +#: apps/homework/admin/question/admin.py:31 msgid "Dispatch crosscheck" msgstr "Запустить p2p-проверку домашки" -#: homework/models/answer.py:87 +#: apps/homework/models/answer.py:87 msgid "Exclude from cross-checking" msgstr "Исключить из p2p-проверки" -#: homework/models/answer.py:92 +#: apps/homework/models/answer.py:92 msgid "Homework answer" msgstr "Ответ на домашку" -#: homework/models/answer.py:93 +#: apps/homework/models/answer.py:93 msgid "Homework answers" msgstr "Ответы на домашку" -#: homework/models/answer.py:96 +#: apps/homework/models/answer.py:96 msgid "May see answers from every user" msgstr "Видит все ответы на домашку" -#: homework/models/question.py:21 +#: apps/homework/models/question.py:21 msgid "Homeworks" msgstr "Домашки" -#: homework/models/question.py:23 +#: apps/homework/models/question.py:23 msgid "May see questions for all homeworks" msgstr "Видит все вопросы домашки" -#: homework/models/reaction.py:27 +#: apps/homework/models/reaction.py:27 msgid "Reaction" msgstr "Реакция" -#: homework/models/reaction.py:28 +#: apps/homework/models/reaction.py:28 msgid "Reactions" msgstr "Реакции" -#: homework/services/reaction_creator.py:51 +#: apps/homework/services/reaction_creator.py:51 msgid "Invalid emoji symbol" msgstr "Неверный символ emoji" -#: homework/services/reaction_creator.py:56 +#: apps/homework/services/reaction_creator.py:56 #, python-brace-format msgid "" "Only {Reaction.MAX_REACTIONS_FROM_ONE_AUTHOR} reactions per answer are " @@ -249,568 +249,568 @@ msgstr "" "Только {Reaction.MAX_REACTIONS_FROM_ONE_AUTHOR} реакций на ответ разрешено " "для одного пользователя." -#: magnets/admin.py:33 +#: apps/magnets/admin.py:33 msgid "Lead count" msgstr "Количество лидов" -#: magnets/apps.py:8 +#: apps/magnets/apps.py:8 msgid "Magnets" msgstr "Лид-магниты" -#: magnets/models.py:24 +#: apps/magnets/models.py:24 msgid "Letter template id" msgstr "ID почтового шаблона" -#: magnets/models.py:24 +#: apps/magnets/models.py:24 msgid "Will be sent upon amocrm_lead registration" msgstr "Автоматически уходит юзеру, когда он зарегился" -#: magnets/models.py:26 +#: apps/magnets/models.py:26 msgid "Success Message" msgstr "Сообщение об успехе" -#: magnets/models.py:26 +#: apps/magnets/models.py:26 msgid "Will be shown under tilda form" msgstr "Покажется под формой в тильде" -#: magnets/models.py:29 +#: apps/magnets/models.py:29 msgid "Email Lead Magnet Campaign" msgstr "Почтовая кампания" -#: magnets/models.py:30 +#: apps/magnets/models.py:30 msgid "Email Lead Magnet Campaigns" msgstr "Почтовые кампании" -#: mailing/models/configuration.py:11 +#: apps/mailing/models/configuration.py:11 msgid "Unset" msgstr "Дефолтный" -#: mailing/models/configuration.py:12 +#: apps/mailing/models/configuration.py:12 msgid "Postmark" msgstr "" -#: mailing/models/configuration.py:16 +#: apps/mailing/models/configuration.py:16 msgid "Email sender" msgstr "Отправитель" -#: mailing/models/configuration.py:16 +#: apps/mailing/models/configuration.py:16 msgid "E.g. Fedor Borshev <fedor@borshev.com>. MUST configure postmark!" msgstr "" -#: mailing/models/configuration.py:17 +#: apps/mailing/models/configuration.py:17 msgid "Reply-to header" msgstr "Reply-to" -#: mailing/models/configuration.py:17 +#: apps/mailing/models/configuration.py:17 msgid "E.g. Fedor Borshev <fedor@borshev.com>" msgstr "" -#: mailing/models/configuration.py:22 +#: apps/mailing/models/configuration.py:22 msgid "Email configuration" msgstr "Способ отсылки" -#: mailing/models/configuration.py:23 +#: apps/mailing/models/configuration.py:23 msgid "Email configurations" msgstr "Способы отсылки" -#: mailing/models/personal_email_domain.py:11 +#: apps/mailing/models/personal_email_domain.py:11 msgid "Personal email domain" msgstr "Домен личного email" -#: mailing/models/personal_email_domain.py:12 +#: apps/mailing/models/personal_email_domain.py:12 msgid "Personal email domains" msgstr "Домены личных email" -#: notion/models.py:49 +#: apps/notion/models.py:49 msgid "Page title" msgstr "Заголовок страницы" -#: notion/models.py:49 +#: apps/notion/models.py:49 msgid "Will be fetched automatically if empty" msgstr "Если не указать — попробуем скачать из ноушена" -#: notion/models.py:51 +#: apps/notion/models.py:51 msgid "Notion page id" msgstr "ID страницы в ноушене" -#: notion/models.py:51 +#: apps/notion/models.py:51 msgid "Paste it from notion address bar" msgstr "Скопируйте адрес из строки браузера" -#: notion/models.py:52 orders/admin/promocodes/admin.py:16 -#: orders/admin/promocodes/admin.py:73 orders/models/promocode.py:54 +#: apps/notion/models.py:52 apps/orders/admin/promocodes/admin.py:16 +#: apps/orders/admin/promocodes/admin.py:73 apps/orders/models/promocode.py:54 msgid "Active" msgstr "Включено" -#: notion/models.py:53 +#: apps/notion/models.py:53 msgid "Is home page of the course" msgstr "Главная страница курса" -#: notion/models.py:56 +#: apps/notion/models.py:56 msgid "Notion material" msgstr "Материал" -#: notion/models.py:57 +#: apps/notion/models.py:57 msgid "Notion materials" msgstr "Материалы" -#: notion/models.py:62 +#: apps/notion/models.py:62 msgid "May access materials from every course" msgstr "Видит страницы ноушена от всех курсов" -#: notion/models.py:77 +#: apps/notion/models.py:77 msgid "Material file" msgstr "Файл" -#: notion/models.py:78 +#: apps/notion/models.py:78 msgid "Material files" msgstr "Файлы" -#: orders/admin/orders/actions.py:21 +#: apps/orders/admin/orders/actions.py:21 msgid "Set paid" msgstr "Пометить оплаченным" -#: orders/admin/orders/actions.py:29 +#: apps/orders/admin/orders/actions.py:29 msgid "Refund" msgstr "Вернуть" -#: orders/admin/orders/actions.py:45 +#: apps/orders/admin/orders/actions.py:45 #, python-brace-format msgid "Orders {refunded_orders_as_message} refunded." msgstr "Заказы {refunded_orders_as_message} возвращены." -#: orders/admin/orders/actions.py:51 +#: apps/orders/admin/orders/actions.py:51 #, python-brace-format msgid "Orders {non_refunded_orders_as_message} have not been refunded. Up to 5 " "refunds per day are allowed. Please come back tomorrow." msgstr "Заказы {non_refunded_orders_as_message} не были возвращены. " "Разрешено до 5 возвратов в день, попробуйте снова завтра." -#: orders/admin/orders/actions.py:56 +#: apps/orders/admin/orders/actions.py:56 msgid "Ship without payments" msgstr "Допустить до уроков без оплаты" -#: orders/admin/orders/actions.py:67 +#: apps/orders/admin/orders/actions.py:67 msgid "Ship again if paid" msgstr "Ещё раз выполнить (если заказ не оплачен — не выполнится)" -#: orders/admin/orders/actions.py:80 products/admin/courses/actions.py:40 +#: apps/orders/admin/orders/actions.py:80 apps/products/admin/courses/actions.py:40 msgid "Generate diplomas" msgstr "Сгенерировать дипломы" -#: orders/admin/orders/actions.py:90 +#: apps/orders/admin/orders/actions.py:90 msgid "Accept homework" msgstr "Засчитать домашку" -#: orders/admin/orders/actions.py:99 +#: apps/orders/admin/orders/actions.py:99 msgid "Disaccept homework" msgstr "Не засчитать домашку" -#: orders/admin/orders/admin.py:73 orders/admin/orders/admin.py:111 +#: apps/orders/admin/orders/admin.py:73 apps/orders/admin/orders/admin.py:111 msgid "Item" msgstr "Товар" -#: orders/admin/orders/admin.py:99 orders/models/order.py:45 -#: products/admin/course.py:35 +#: apps/orders/admin/orders/admin.py:99 apps/orders/models/order.py:45 +#: apps/products/admin/course.py:35 msgid "Price" msgstr "Цена" -#: orders/admin/orders/admin.py:107 orders/models/order.py:44 +#: apps/orders/admin/orders/admin.py:107 apps/orders/models/order.py:44 msgid "User" msgstr "Юзер" -#: orders/admin/orders/admin.py:115 +#: apps/orders/admin/orders/admin.py:115 msgid "Payment" msgstr "Оплата" -#: orders/admin/orders/admin.py:119 +#: apps/orders/admin/orders/admin.py:119 msgid "Login as customer" msgstr "Зайти от имени студента" -#: orders/admin/orders/filters.py:13 +#: apps/orders/admin/orders/filters.py:13 msgctxt "orders" msgid "status" msgstr "Статус" -#: orders/admin/orders/filters.py:18 +#: apps/orders/admin/orders/filters.py:18 msgid "Not paid" msgstr "Не оплачен" -#: orders/admin/orders/filters.py:19 +#: apps/orders/admin/orders/filters.py:19 msgid "Paid" msgstr "Оплачен" -#: orders/admin/orders/filters.py:20 orders/human_readable.py:19 +#: apps/orders/admin/orders/filters.py:20 apps/orders/human_readable.py:19 msgid "Shipped without payment" msgstr "Ждем денег" -#: orders/admin/orders/forms.py:12 +#: apps/orders/admin/orders/forms.py:12 msgid "If changed user, receives welcome letter one more time" msgstr "Если поменять, студент получит ещё одно письмо «спасибо за покупку»" -#: orders/admin/promocodes/actions.py:10 +#: apps/orders/admin/promocodes/actions.py:10 msgid "Deactivate selected promo codes" msgstr "Деактивировать выбранные промо-коды" -#: orders/admin/promocodes/admin.py:56 +#: apps/orders/admin/promocodes/admin.py:56 msgid "Order count" msgstr "Заказов" -#: orders/admin/promocodes/admin.py:63 +#: apps/orders/admin/promocodes/admin.py:63 msgid "Discount" msgstr "Скидка" -#: orders/human_readable.py:14 +#: apps/orders/human_readable.py:14 msgid "B2B" msgstr "" -#: orders/human_readable.py:16 +#: apps/orders/human_readable.py:16 msgid "Is paid" msgstr "Оплачен" -#: orders/models/order.py:43 +#: apps/orders/models/order.py:43 msgid "Order author" msgstr "Продавец" -#: orders/models/order.py:46 orders/models/promocode.py:50 -#: orders/models/promocode.py:60 +#: apps/orders/models/order.py:46 apps/orders/models/promocode.py:50 +#: apps/orders/models/promocode.py:60 msgid "Promo Code" msgstr "Промо-код" -#: orders/models/order.py:49 +#: apps/orders/models/order.py:49 msgid "Date when order got paid" msgstr "Когда оплачен" -#: orders/models/order.py:52 +#: apps/orders/models/order.py:52 msgid "If set during creation, order automaticaly gets shipped" msgstr "" "Чтобы отметить заказ оплаченым, воспользуйтесь массовой операцией из списка " "заказво" -#: orders/models/order.py:54 +#: apps/orders/models/order.py:54 msgid "Date when order got unpaid" msgstr "Когда вернули деньги" -#: orders/models/order.py:55 +#: apps/orders/models/order.py:55 msgid "Date when order was shipped" msgstr "Дата выполнения" -#: orders/models/order.py:57 +#: apps/orders/models/order.py:57 msgid "User-requested bank string" msgstr "Банк" -#: orders/models/order.py:58 +#: apps/orders/models/order.py:58 msgid "Purchase-time UE rate" msgstr "Курс у.е. на момент покупки" -#: orders/models/order.py:62 products/models/record.py:18 +#: apps/orders/models/order.py:62 apps/products/models/record.py:18 msgid "Record" msgstr "Запись" -#: orders/models/order.py:63 products/models/bundle.py:19 +#: apps/orders/models/order.py:63 apps/products/models/bundle.py:19 msgid "Bundle" msgstr "Набор" -#: orders/models/order.py:70 +#: apps/orders/models/order.py:70 msgctxt "orders" msgid "Order" msgstr "Заказ" -#: orders/models/order.py:71 +#: apps/orders/models/order.py:71 msgctxt "orders" msgid "Orders" msgstr "Заказы" -#: orders/models/order.py:74 +#: apps/orders/models/order.py:74 msgid "May mark orders as paid" msgstr "Отмечать заказы оплаченными" -#: orders/models/order.py:75 +#: apps/orders/models/order.py:75 msgid "May mark orders as unpaid" msgstr "Возвращать заказы" -#: orders/models/promocode.py:51 +#: apps/orders/models/promocode.py:51 msgid "Discount percent" msgstr "Процент скидки" -#: orders/models/promocode.py:52 +#: apps/orders/models/promocode.py:52 msgid "Discount amount" msgstr "Скидка в деньгах" -#: orders/models/promocode.py:52 +#: apps/orders/models/promocode.py:52 msgid "Takes precedence over percent" msgstr "Если задать — процент не будет работать" -#: orders/models/promocode.py:53 +#: apps/orders/models/promocode.py:53 msgid "Expiration date" msgstr "Дата окончания" -#: orders/models/promocode.py:55 +#: apps/orders/models/promocode.py:55 msgid "Destination" msgstr "Куда пойдет" -#: orders/models/promocode.py:57 +#: apps/orders/models/promocode.py:57 msgid "Can not be used for courses not checked here" msgstr "" "Если тут выбрать хоть что-нибудь, то промо-код будет действовать только для " "этого курса" -#: orders/models/promocode.py:61 +#: apps/orders/models/promocode.py:61 msgid "Promo Codes" msgstr "Промо-коды" -#: orders/models/promocode.py:68 +#: apps/orders/models/promocode.py:68 msgid "Percent or value must be set" msgstr "Нужно задать или процент скидки или сумму в деньгах" -#: products/admin/course.py:44 +#: apps/products/admin/course.py:44 msgid "Email messages" msgstr "Письма" -#: products/admin/course.py:53 +#: apps/products/admin/course.py:53 msgid "Order confirmation" msgstr "Подтверждение покупки (для бесплатных курсов)" -#: products/admin/courses/actions.py:15 +#: apps/products/admin/courses/actions.py:15 msgid "Email template id" msgstr "ID шаблона в постмарке" -#: products/admin/courses/actions.py:26 +#: apps/products/admin/courses/actions.py:26 msgid "Send email to all purchased_users" msgstr "Отправить письмо всем купившим" -#: products/models/base.py:23 +#: apps/products/models/base.py:23 msgid "Name for receipts" msgstr "Для чеков" -#: products/models/base.py:26 +#: apps/products/models/base.py:26 msgid "Full name for letters" msgstr "Для писем" -#: products/models/base.py:30 +#: apps/products/models/base.py:30 msgid "Name used for international purchases" msgstr "Название для международных покупок" -#: products/models/base.py:38 +#: apps/products/models/base.py:38 msgid "Fixed promo code for tinkoff credit" msgstr "Промо-код на рассрочку в Тинькофф" -#: products/models/base.py:38 +#: apps/products/models/base.py:38 msgid "Used in tinkoff credit only" msgstr "" "Пересылается в тинькофф, если покупатель оформляет рассрочку на курс. Если " "не заполнять — покупатель переплатит за кредит. Можно взять в админке " "Тинькофф" -#: products/models/base.py:41 products/models/group.py:12 +#: apps/products/models/base.py:41 apps/products/models/group.py:12 msgid "Analytical group" msgstr "Группа товаров (аналитика)" -#: products/models/bundle.py:20 +#: apps/products/models/bundle.py:20 msgid "Bundles" msgstr "Наборы" -#: products/models/course.py:47 +#: apps/products/models/course.py:47 msgid "Genitive name" msgstr "В родительном падеже" -#: products/models/course.py:50 +#: apps/products/models/course.py:50 msgid "Welcome letter template id" msgstr "ID шаблона приветственного письма" -#: products/models/course.py:50 +#: apps/products/models/course.py:50 msgid "Will be sent upon purchase if set" msgstr "Если задать — письмо будет уходить вместе с каждой покупкой" -#: products/models/course.py:52 +#: apps/products/models/course.py:52 msgid "Display in LMS" msgstr "Показывать в LMS" -#: products/models/course.py:52 +#: apps/products/models/course.py:52 msgid "If disabled will not be shown in LMS" msgstr "Если снять галочку, студенты не будут видеть курс в LMS" -#: products/models/course.py:56 +#: apps/products/models/course.py:56 msgid "Disable all triggers" msgstr "Отключить триггерные письма" -#: products/models/course.py:59 +#: apps/products/models/course.py:59 msgid "Confirmation template id" msgstr "ID шаблона для письма-подтверждения" -#: products/models/course.py:63 +#: apps/products/models/course.py:63 msgid "If set user sill receive this message upon creating zero-priced order" msgstr "Уходит пользователю, если он берёт бесплатный курс" -#: products/models/course.py:65 +#: apps/products/models/course.py:65 msgid "Confirmation success URL" msgstr "Ссылка после успешного подтверждения" -#: products/models/course.py:68 +#: apps/products/models/course.py:68 msgid "Cover image" msgstr "" -#: products/models/course.py:71 +#: apps/products/models/course.py:71 #, fuzzy #| msgid "Is home page of the course" msgid "The cover image of course" msgstr "Главная страница курса" -#: products/models/course.py:77 +#: apps/products/models/course.py:77 msgid "Courses" msgstr "Курсы" -#: products/models/course.py:86 +#: apps/products/models/course.py:86 msgid "Both confirmation_template_id and confirmation_success_url must be set" msgstr "" "У курсов с подтверждением обязательно нужно устанавливать оба поля: и " "почтовый шаблон и ссылку для упешного подтверждения " -#: products/models/course.py:89 +#: apps/products/models/course.py:89 msgid "Courses with confirmation should have zero price" msgstr "" "Курсы с подтверждением могут быть только бесплатными. Если пользователь " "платит деньги — это уже достаточное подтверждение" -#: products/models/group.py:13 +#: apps/products/models/group.py:13 msgid "Analytical groups" msgstr "Группы товаров (аналитика)" -#: products/models/record.py:14 +#: apps/products/models/record.py:14 msgid "Postmark template_id" msgstr "ID шаблона в постмарке" -#: products/models/record.py:14 +#: apps/products/models/record.py:14 msgid "Leave it blank for the default template" msgstr "Если оставить пустым — будет дефолтным" -#: products/models/record.py:19 +#: apps/products/models/record.py:19 msgid "Records" msgstr "Записи" -#: stripebank/bank.py:17 +#: apps/stripebank/bank.py:17 msgid "Stripe" msgstr "Страйп" -#: tinkoff/bank.py:18 +#: apps/tinkoff/bank.py:18 msgid "Tinkoff" msgstr "Тинькофф" -#: tinkoff/credit.py:14 +#: apps/tinkoff/credit.py:14 msgid "Tinkoff Credit" msgstr "Т.Кредит" -#: tinkoff/dolyame.py:24 +#: apps/tinkoff/dolyame.py:24 msgid "Dolyame" msgstr "Долями" -#: tinkoff/models.py:11 +#: apps/tinkoff/models.py:11 msgid "Authorized" msgstr "" -#: tinkoff/models.py:12 +#: apps/tinkoff/models.py:12 msgid "Confirmed" msgstr "" -#: tinkoff/models.py:13 +#: apps/tinkoff/models.py:13 msgid "Reversed" msgstr "" -#: tinkoff/models.py:14 tinkoff/models.py:65 +#: apps/tinkoff/models.py:14 apps/tinkoff/models.py:65 msgid "Refunded" msgstr "" -#: tinkoff/models.py:15 +#: apps/tinkoff/models.py:15 msgid "Partial refunded" msgstr "" -#: tinkoff/models.py:16 tinkoff/models.py:39 tinkoff/models.py:64 +#: apps/tinkoff/models.py:16 apps/tinkoff/models.py:39 apps/tinkoff/models.py:64 msgid "Rejected" msgstr "" -#: tinkoff/models.py:38 tinkoff/models.py:63 +#: apps/tinkoff/models.py:38 apps/tinkoff/models.py:63 msgid "Approved" msgstr "" -#: tinkoff/models.py:40 tinkoff/models.py:66 +#: apps/tinkoff/models.py:40 apps/tinkoff/models.py:66 msgid "Canceled" msgstr "" -#: tinkoff/models.py:41 +#: apps/tinkoff/models.py:41 msgid "Signed" msgstr "" -#: tinkoff/models.py:67 +#: apps/tinkoff/models.py:67 #, fuzzy #| msgid "Comment" msgid "Committed" msgstr "Комментарий" -#: tinkoff/models.py:68 +#: apps/tinkoff/models.py:68 msgid "Waiting for commit" msgstr "" -#: tinkoff/models.py:69 +#: apps/tinkoff/models.py:69 msgid "Completed" msgstr "" -#: users/admin/student.py:14 +#: apps/users/admin/student.py:14 msgid "Email" msgstr "" -#: users/admin/student.py:15 +#: apps/users/admin/student.py:15 msgid "first name" msgstr "Имя" -#: users/admin/student.py:16 +#: apps/users/admin/student.py:16 msgid "last name" msgstr "Фамилия" -#: users/admin/student.py:49 +#: apps/users/admin/student.py:49 msgid "Personal info" msgstr "Персональные данные" -#: users/admin/student.py:50 +#: apps/users/admin/student.py:50 msgid "Name in english" msgstr "Имя на английском" -#: users/apps.py:7 +#: apps/users/apps.py:7 msgid "Users" msgstr "Юзеры" -#: users/models.py:21 +#: apps/users/models.py:21 msgid "Male" msgstr "Мужчина" -#: users/models.py:22 +#: apps/users/models.py:22 msgid "Female" msgstr "Женщина" -#: users/models.py:24 +#: apps/users/models.py:24 msgid "Subscribed to newsletter" msgstr "Подписан на новости" -#: users/models.py:25 +#: apps/users/models.py:25 msgid "first name in english" msgstr "Имя на английском" -#: users/models.py:26 +#: apps/users/models.py:26 msgid "last name in english" msgstr "Фамилия на английском" -#: users/models.py:29 +#: apps/users/models.py:29 msgid "Gender" msgstr "Пол" -#: users/models.py:40 +#: apps/users/models.py:40 msgid "user" msgstr "пользователь" -#: users/models.py:41 +#: apps/users/models.py:41 msgid "users" msgstr "пользователи" -#: users/models.py:102 +#: apps/users/models.py:102 msgid "Students" msgstr "Студенты" diff --git a/src/mailing/admin/__init__.py b/src/mailing/admin/__init__.py deleted file mode 100644 index 1aef106226c..00000000000 --- a/src/mailing/admin/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -__all__ = ["PersonalEmailDomainAdmin"] - -from mailing.admin.personal_email_domain import PersonalEmailDomainAdmin diff --git a/src/mailing/admin/personal_email_domain.py b/src/mailing/admin/personal_email_domain.py deleted file mode 100644 index 9794f10c480..00000000000 --- a/src/mailing/admin/personal_email_domain.py +++ /dev/null @@ -1,8 +0,0 @@ -from app.admin import admin -from app.admin import ModelAdmin -from mailing.models import PersonalEmailDomain - - -@admin.register(PersonalEmailDomain) -class PersonalEmailDomainAdmin(ModelAdmin): - list_display = ("name",) diff --git a/src/mailing/models/__init__.py b/src/mailing/models/__init__.py deleted file mode 100644 index 2047e0f37ec..00000000000 --- a/src/mailing/models/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -from mailing.models.configuration import EmailConfiguration -from mailing.models.log_entry import EmailLogEntry - -__all__ = [ - "EmailConfiguration", - "EmailLogEntry", - "PersonalEmailDomain", -] - -from mailing.models.personal_email_domain import PersonalEmailDomain diff --git a/src/manage.py b/src/manage.py index 2a7940c75df..e67c1b14369 100755 --- a/src/manage.py +++ b/src/manage.py @@ -5,7 +5,7 @@ def main() -> None: - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app.settings") + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "core.settings") try: from django.core.management import execute_from_command_line except ImportError as exc: diff --git a/src/orders/admin/__init__.py b/src/orders/admin/__init__.py deleted file mode 100644 index 7aeaab83c8b..00000000000 --- a/src/orders/admin/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -import orders.admin.orders.admin # noqa -import orders.admin.promocodes.admin # noqa diff --git a/src/orders/models/__init__.py b/src/orders/models/__init__.py deleted file mode 100644 index 4249429d897..00000000000 --- a/src/orders/models/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from orders.models.order import Order -from orders.models.promocode import PromoCode - -__all__ = [ - "Order", - "PromoCode", -] diff --git a/src/orders/services/__init__.py b/src/orders/services/__init__.py deleted file mode 100644 index 91b63289cc6..00000000000 --- a/src/orders/services/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -from orders.services.order_creator import OrderCreator -from orders.services.order_diploma_generator import OrderDiplomaGenerator -from orders.services.order_email_changer import OrderEmailChanger -from orders.services.order_paid_setter import OrderPaidSetter -from orders.services.order_refunder import OrderRefunder -from orders.services.order_shipper import OrderShipper -from orders.services.order_unshipper import OrderUnshipper - -__all__ = [ - "OrderCreator", - "OrderDiplomaGenerator", - "OrderEmailChanger", - "OrderPaidSetter", - "OrderShipper", - "OrderUnshipper", - "OrderRefunder", -] diff --git a/src/products/admin/__init__.py b/src/products/admin/__init__.py deleted file mode 100644 index 333d1c03bac..00000000000 --- a/src/products/admin/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -import products.admin.course # noqa -import products.admin.group # noqa diff --git a/src/pyproject.toml b/src/pyproject.toml deleted file mode 120000 index 1e11d782571..00000000000 --- a/src/pyproject.toml +++ /dev/null @@ -1 +0,0 @@ -../pyproject.toml \ No newline at end of file diff --git a/src/pytest.ini b/src/pytest.ini deleted file mode 100644 index 58783108a2c..00000000000 --- a/src/pytest.ini +++ /dev/null @@ -1,34 +0,0 @@ -[pytest] -DJANGO_SETTINGS_MODULE = app.settings -python_files = test*.py -addopts = --reuse-db -markers = - freeze_time: freezing time marker (pytest-freezegun does not register it) - single_thread: marked tests should be ran only in single thread - slow: tests with inentional slow run - - -; explicitly specifying warnings to ignored -; treating all other as errors -filterwarnings = - error - ignore:unclosed file:ResourceWarning - ignore:'cgi' is deprecated - ignore:pkg_resources is deprecated as an API - ignore:SelectableGroups dict interface is deprecated - ignore:distutils Version classes are deprecated. Use packaging.version instead.:DeprecationWarning:pytest_freezegun:17 - -env = - CI=1 - CELERY_ALWAYS_EAGER=True - AWS_ACCESS_KEY_ID=zeroc00l94 - AWS_SECRET_ACCESS_KEY=h4xx0r - AWS_STORAGE_BUCKET_NAME=pwned_data - AWS_S3_REGION_NAME=Ukraine - AWS_S3_ENDPOINT_URL=https://fra1.digitaloceanspaces.com - RECAPTCHA_ENABLED=Off - DISABLE_THROTTLING=On - DEFAULT_FILE_STORAGE=django.core.files.storage.FileSystemStorage - DISABLE_HOMEWORK_PERMISSIONS_CHECKING=On - DISABLE_NEW_ANSWER_NOTIFICATIONS=On - ATOL_WEBHOOK_SALT=SECRET-SALT diff --git a/src/studying/shipment/__init__.py b/src/studying/shipment/__init__.py deleted file mode 100644 index a707b4ef616..00000000000 --- a/src/studying/shipment/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from studying.shipment.course import CourseShipment - -__all__ = [ - "CourseShipment", -] diff --git a/src/users/admin/__init__.py b/src/users/admin/__init__.py deleted file mode 100644 index 5c28e84f107..00000000000 --- a/src/users/admin/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from users.admin.student import StudentAdmin -from users.admin.user import UserAdmin - -__all__ = [ - "StudentAdmin", - "UserAdmin", -] diff --git a/src/users/services/__init__.py b/src/users/services/__init__.py deleted file mode 100644 index 8b824766d26..00000000000 --- a/src/users/services/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from users.services.user_creator import UserCreator -from users.services.user_updater import UserUpdater - -__all__ = [ - "UserCreator", - "UserUpdater", -] diff --git a/src/users/tags/__init__.py b/src/users/tags/__init__.py deleted file mode 100644 index 855941eaee2..00000000000 --- a/src/users/tags/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -__all__ = [ - "AnyPurchaseTag", - "StartedTag", - "PurchasedTag", - "B2BTag", -] - -from users.tags.any_purchase_tag import AnyPurchaseTag -from users.tags.b2b_tag import B2BTag -from users.tags.purchased_tag import PurchasedTag -from users.tags.started_tag import StartedTag diff --git a/src/tinkoff/__init__.py b/tests/__init__.py similarity index 100% rename from src/tinkoff/__init__.py rename to tests/__init__.py diff --git a/src/tinkoff/migrations/__init__.py b/tests/apps/__init__.py similarity index 100% rename from src/tinkoff/migrations/__init__.py rename to tests/apps/__init__.py diff --git a/src/users/__init__.py b/tests/apps/a12n/__init__.py similarity index 100% rename from src/users/__init__.py rename to tests/apps/a12n/__init__.py diff --git a/tests/apps/a12n/api/conftest.py b/tests/apps/a12n/api/conftest.py new file mode 100644 index 00000000000..d44d9a38253 --- /dev/null +++ b/tests/apps/a12n/api/conftest.py @@ -0,0 +1,6 @@ +import pytest + + +@pytest.fixture(autouse=True) +def subscribe(mocker): + return mocker.patch("core.tasks.update_dashamail_subscription.delay") diff --git a/src/a12n/tests/api/tests_obtain_jwt_via_passwordless_token.py b/tests/apps/a12n/api/tests_obtain_jwt_via_passwordless_token.py similarity index 100% rename from src/a12n/tests/api/tests_obtain_jwt_via_passwordless_token.py rename to tests/apps/a12n/api/tests_obtain_jwt_via_passwordless_token.py diff --git a/src/a12n/tests/api/tests_obtain_jwt_via_user_id.py b/tests/apps/a12n/api/tests_obtain_jwt_via_user_id.py similarity index 92% rename from src/a12n/tests/api/tests_obtain_jwt_via_user_id.py rename to tests/apps/a12n/api/tests_obtain_jwt_via_user_id.py index 2f11ff20ed0..a0cc0db55a4 100644 --- a/src/a12n/tests/api/tests_obtain_jwt_via_user_id.py +++ b/tests/apps/a12n/api/tests_obtain_jwt_via_user_id.py @@ -1,6 +1,6 @@ import pytest -from a12n.utils import decode_jwt_without_validation +from apps.a12n.utils import decode_jwt_without_validation pytestmark = [pytest.mark.django_db] diff --git a/src/a12n/tests/api/tests_obtain_token.py b/tests/apps/a12n/api/tests_obtain_token.py similarity index 96% rename from src/a12n/tests/api/tests_obtain_token.py rename to tests/apps/a12n/api/tests_obtain_token.py index 019f87b8d30..8b64e952970 100644 --- a/src/a12n/tests/api/tests_obtain_token.py +++ b/tests/apps/a12n/api/tests_obtain_token.py @@ -1,7 +1,7 @@ import pytest -from a12n.jwt import decode_jwt_without_validation -from users.services import UserCreator +from apps.a12n.jwt import decode_jwt_without_validation +from apps.users.services import UserCreator pytestmark = pytest.mark.django_db diff --git a/src/a12n/tests/api/tests_password_change.py b/tests/apps/a12n/api/tests_password_change.py similarity index 100% rename from src/a12n/tests/api/tests_password_change.py rename to tests/apps/a12n/api/tests_password_change.py diff --git a/src/a12n/tests/api/tests_password_reset_confirm.py b/tests/apps/a12n/api/tests_password_reset_confirm.py similarity index 100% rename from src/a12n/tests/api/tests_password_reset_confirm.py rename to tests/apps/a12n/api/tests_password_reset_confirm.py diff --git a/src/a12n/tests/api/tests_refresh_token.py b/tests/apps/a12n/api/tests_refresh_token.py similarity index 97% rename from src/a12n/tests/api/tests_refresh_token.py rename to tests/apps/a12n/api/tests_refresh_token.py index 9278235e4c5..0015be86e62 100644 --- a/src/a12n/tests/api/tests_refresh_token.py +++ b/tests/apps/a12n/api/tests_refresh_token.py @@ -2,7 +2,7 @@ from freezegun import freeze_time -from a12n.utils import get_jwt +from apps.a12n.utils import get_jwt pytestmark = [ pytest.mark.django_db, diff --git a/src/a12n/tests/api/tests_request_password_reset.py b/tests/apps/a12n/api/tests_request_password_reset.py similarity index 100% rename from src/a12n/tests/api/tests_request_password_reset.py rename to tests/apps/a12n/api/tests_request_password_reset.py diff --git a/src/a12n/tests/api/tests_request_passwordless_token.py b/tests/apps/a12n/api/tests_request_passwordless_token.py similarity index 92% rename from src/a12n/tests/api/tests_request_passwordless_token.py rename to tests/apps/a12n/api/tests_request_passwordless_token.py index 8089aed9219..cf2ca0f8621 100644 --- a/src/a12n/tests/api/tests_request_passwordless_token.py +++ b/tests/apps/a12n/api/tests_request_passwordless_token.py @@ -3,7 +3,7 @@ from datetime import timezone import pytest -from a12n.models import PasswordlessAuthToken +from apps.a12n.models import PasswordlessAuthToken pytestmark = [ pytest.mark.django_db, @@ -18,7 +18,7 @@ def user(mixer): @pytest.fixture(autouse=True) def _freeze_frontend_url(mocker): - mocker.patch("a12n.models.PasswordlessAuthToken.get_absolute_url", return_value="https://frontend/auth/__TOKEN__") + mocker.patch("apps.a12n.models.PasswordlessAuthToken.get_absolute_url", return_value="https://frontend/auth/__TOKEN__") def test_token_is_created(anon, user): diff --git a/src/a12n/tests/tests_passwordless_token_absolute_url.py b/tests/apps/a12n/tests_passwordless_token_absolute_url.py similarity index 100% rename from src/a12n/tests/tests_passwordless_token_absolute_url.py rename to tests/apps/a12n/tests_passwordless_token_absolute_url.py diff --git a/src/users/management/__init__.py b/tests/apps/amocrm/__init__.py similarity index 100% rename from src/users/management/__init__.py rename to tests/apps/amocrm/__init__.py diff --git a/src/amocrm/tests/conftest.py b/tests/apps/amocrm/conftest.py similarity index 75% rename from src/amocrm/tests/conftest.py rename to tests/apps/amocrm/conftest.py index 19a3a4d8666..29300ee38ef 100644 --- a/src/amocrm/tests/conftest.py +++ b/tests/apps/amocrm/conftest.py @@ -22,9 +22,9 @@ def amocrm_course(mixer, course): @pytest.fixture(autouse=True) def _mock_tasks_with_paid_setter(mocker): - mocker.patch("orders.services.order_paid_setter.OrderPaidSetter.after_shipment", return_value=None) - mocker.patch("orders.services.order_refunder.OrderRefunder.update_integrations", return_value=None) - mocker.patch("studying.shipment_factory.unship", return_value=None) + mocker.patch("apps.orders.services.order_paid_setter.OrderPaidSetter.after_shipment", return_value=None) + mocker.patch("apps.orders.services.order_refunder.OrderRefunder.update_integrations", return_value=None) + mocker.patch("apps.studying.shipment_factory.unship", return_value=None) @pytest.fixture diff --git a/src/amocrm/tests/dto/conftest.py b/tests/apps/amocrm/dto/conftest.py similarity index 66% rename from src/amocrm/tests/dto/conftest.py rename to tests/apps/amocrm/dto/conftest.py index 85b00f8d2ba..ec8138c82f1 100644 --- a/src/amocrm/tests/dto/conftest.py +++ b/tests/apps/amocrm/dto/conftest.py @@ -8,11 +8,11 @@ @pytest.fixture(autouse=True) def _mock_cached_fields_id(mocker): - mocker.patch("amocrm.ids.contact_field_id", return_value=2235143) - mocker.patch("amocrm.ids.product_field_id", return_value=800) - mocker.patch("amocrm.ids.products_catalog_id", return_value=900) - mocker.patch("amocrm.ids.b2c_pipeline_id", return_value=555) - mocker.patch("amocrm.ids.b2c_pipeline_status_id", return_value=333) + mocker.patch("apps.amocrm.ids.contact_field_id", return_value=2235143) + mocker.patch("apps.amocrm.ids.product_field_id", return_value=800) + mocker.patch("apps.amocrm.ids.products_catalog_id", return_value=900) + mocker.patch("apps.amocrm.ids.b2c_pipeline_id", return_value=555) + mocker.patch("apps.amocrm.ids.b2c_pipeline_status_id", return_value=333) @pytest.fixture @@ -53,19 +53,19 @@ def order(amocrm_user, course, factory): @pytest.fixture def post(mocker): - return mocker.patch("amocrm.client.http.post") + return mocker.patch("apps.amocrm.client.http.post") @pytest.fixture def patch(mocker): - return mocker.patch("amocrm.client.http.patch") + return mocker.patch("apps.amocrm.client.http.patch") @pytest.fixture def delete(mocker): - return mocker.patch("amocrm.client.http.delete") + return mocker.patch("apps.amocrm.client.http.delete") @pytest.fixture def get(mocker): - return mocker.patch("amocrm.client.http.get") + return mocker.patch("apps.amocrm.client.http.get") diff --git a/src/amocrm/tests/dto/tests_amo_groups.py b/tests/apps/amocrm/dto/tests_amo_groups.py similarity index 96% rename from src/amocrm/tests/dto/tests_amo_groups.py rename to tests/apps/amocrm/dto/tests_amo_groups.py index d3f756c08b6..bcdc5b53d38 100644 --- a/src/amocrm/tests/dto/tests_amo_groups.py +++ b/tests/apps/amocrm/dto/tests_amo_groups.py @@ -1,7 +1,7 @@ import pytest -from amocrm.dto import AmoCRMGroups -from products.models import Group +from apps.amocrm.dto import AmoCRMGroups +from apps.products.models import Group pytestmark = [ pytest.mark.django_db, diff --git a/src/amocrm/tests/dto/tests_amo_pipelines.py b/tests/apps/amocrm/dto/tests_amo_pipelines.py similarity index 99% rename from src/amocrm/tests/dto/tests_amo_pipelines.py rename to tests/apps/amocrm/dto/tests_amo_pipelines.py index 72a5553e6ed..30477ea56f3 100644 --- a/src/amocrm/tests/dto/tests_amo_pipelines.py +++ b/tests/apps/amocrm/dto/tests_amo_pipelines.py @@ -1,6 +1,6 @@ import pytest -from amocrm.dto.pipelines import AmoCRMPipelines +from apps.amocrm.dto.pipelines import AmoCRMPipelines pytestmark = [ pytest.mark.django_db, diff --git a/src/amocrm/tests/dto/tests_catalogs.py b/tests/apps/amocrm/dto/tests_catalogs.py similarity index 98% rename from src/amocrm/tests/dto/tests_catalogs.py rename to tests/apps/amocrm/dto/tests_catalogs.py index 2d2399d4708..971699a2e0d 100644 --- a/src/amocrm/tests/dto/tests_catalogs.py +++ b/tests/apps/amocrm/dto/tests_catalogs.py @@ -1,6 +1,6 @@ import pytest -from amocrm.dto.catalogs import AmoCRMCatalogs +from apps.amocrm.dto.catalogs import AmoCRMCatalogs pytestmark = [ pytest.mark.django_db, diff --git a/src/amocrm/tests/dto/tests_customer.py b/tests/apps/amocrm/dto/tests_customer.py similarity index 89% rename from src/amocrm/tests/dto/tests_customer.py rename to tests/apps/amocrm/dto/tests_customer.py index cf869a43503..bc256fb2145 100644 --- a/src/amocrm/tests/dto/tests_customer.py +++ b/tests/apps/amocrm/dto/tests_customer.py @@ -1,6 +1,6 @@ import pytest -from amocrm.dto import AmoCRMCustomer +from apps.amocrm.dto import AmoCRMCustomer pytestmark = [ pytest.mark.django_db, @@ -50,19 +50,19 @@ def _successful_create_contact_response(post): @pytest.fixture def _mock_create_calls(mocker): - mocker.patch("amocrm.dto.customer.AmoCRMCustomer._create_customer", return_value=11111) - mocker.patch("amocrm.dto.customer.AmoCRMCustomer._create_contact", return_value=22222) - mocker.patch("amocrm.dto.customer.AmoCRMCustomer._link_customer_to_contact", return_value=None) + mocker.patch("apps.amocrm.dto.customer.AmoCRMCustomer._create_customer", return_value=11111) + mocker.patch("apps.amocrm.dto.customer.AmoCRMCustomer._create_contact", return_value=22222) + mocker.patch("apps.amocrm.dto.customer.AmoCRMCustomer._link_customer_to_contact", return_value=None) @pytest.fixture def mock_update_customer(mocker): - return mocker.patch("amocrm.dto.customer.AmoCRMCustomer._update_customer") + return mocker.patch("apps.amocrm.dto.customer.AmoCRMCustomer._update_customer") @pytest.fixture def mock_update_contact(mocker): - return mocker.patch("amocrm.dto.customer.AmoCRMCustomer._update_contact") + return mocker.patch("apps.amocrm.dto.customer.AmoCRMCustomer._update_contact") @pytest.mark.usefixtures("_mock_create_calls") diff --git a/src/amocrm/tests/dto/tests_lead.py b/tests/apps/amocrm/dto/tests_lead.py similarity index 90% rename from src/amocrm/tests/dto/tests_lead.py rename to tests/apps/amocrm/dto/tests_lead.py index 84a693b2c4f..63b8291012a 100644 --- a/src/amocrm/tests/dto/tests_lead.py +++ b/tests/apps/amocrm/dto/tests_lead.py @@ -1,6 +1,6 @@ import pytest -from amocrm.dto import AmoCRMLead +from apps.amocrm.dto import AmoCRMLead pytestmark = [ pytest.mark.django_db, @@ -22,17 +22,17 @@ def _successful_create_lead_response(post): @pytest.fixture def mock_create_lead(mocker): - return mocker.patch("amocrm.dto.lead.AmoCRMLead._create_lead", return_value=11111) + return mocker.patch("apps.amocrm.dto.lead.AmoCRMLead._create_lead", return_value=11111) @pytest.fixture def mock_link_course_to_lead(mocker): - return mocker.patch("amocrm.dto.lead.AmoCRMLead._link_course_to_lead") + return mocker.patch("apps.amocrm.dto.lead.AmoCRMLead._link_course_to_lead") @pytest.fixture def mock_update_price(mocker): - return mocker.patch("amocrm.dto.lead.AmoCRMLead._set_price_from_order") + return mocker.patch("apps.amocrm.dto.lead.AmoCRMLead._set_price_from_order") @pytest.mark.usefixtures("mock_create_lead", "mock_link_course_to_lead", "mock_update_price") diff --git a/src/amocrm/tests/dto/tests_product.py b/tests/apps/amocrm/dto/tests_product.py similarity index 98% rename from src/amocrm/tests/dto/tests_product.py rename to tests/apps/amocrm/dto/tests_product.py index 6fa7f6fb9cb..82f02b4281d 100644 --- a/src/amocrm/tests/dto/tests_product.py +++ b/tests/apps/amocrm/dto/tests_product.py @@ -1,6 +1,6 @@ import pytest -from amocrm.dto import AmoCRMProduct +from apps.amocrm.dto import AmoCRMProduct pytestmark = [ pytest.mark.django_db, diff --git a/src/amocrm/tests/dto/tests_transaction.py b/tests/apps/amocrm/dto/tests_transaction.py similarity index 97% rename from src/amocrm/tests/dto/tests_transaction.py rename to tests/apps/amocrm/dto/tests_transaction.py index df6814d396e..c1f74355eae 100644 --- a/src/amocrm/tests/dto/tests_transaction.py +++ b/tests/apps/amocrm/dto/tests_transaction.py @@ -1,6 +1,6 @@ import pytest -from amocrm.dto import AmoCRMTransaction +from apps.amocrm.dto import AmoCRMTransaction pytestmark = [ pytest.mark.django_db, diff --git a/src/users/management/commands/__init__.py b/tests/apps/amocrm/http/__init__.py similarity index 100% rename from src/users/management/commands/__init__.py rename to tests/apps/amocrm/http/__init__.py diff --git a/src/amocrm/tests/http/tests_http.py b/tests/apps/amocrm/http/tests_http.py similarity index 96% rename from src/amocrm/tests/http/tests_http.py rename to tests/apps/amocrm/http/tests_http.py index dfe014717c4..7836f8e709e 100644 --- a/src/amocrm/tests/http/tests_http.py +++ b/tests/apps/amocrm/http/tests_http.py @@ -2,8 +2,8 @@ from django.core.cache import cache -from amocrm.client import http -from amocrm.client.http import AmoCRMClientException +from apps.amocrm.client import http +from apps.amocrm.client.http import AmoCRMClientException pytestmark = [ pytest.mark.single_thread, @@ -140,7 +140,7 @@ def test_request_fail(respx_mock, method): getattr(respx_mock, method)(url="https://test.amocrm.ru/api/v4/companies").respond(status_code=210) request = getattr(http, method) - with pytest.raises(AmoCRMClientException, match="Non-ok HTTP response from amocrm: 210"): + with pytest.raises(AmoCRMClientException, match="Non-ok HTTP response from apps.amocrm: 210"): request("api/v4/companies", {}) @@ -149,7 +149,7 @@ def test_request_fail_with_body(respx_mock, method): getattr(respx_mock, method)(url="https://test.amocrm.ru/api/v4/companies").respond(status_code=210, json={"info": "damn we lost"}) request = getattr(http, method) - with pytest.raises(AmoCRMClientException, match="Non-ok HTTP response from amocrm: 210\nResponse data: {'info': 'damn we lost'}"): + with pytest.raises(AmoCRMClientException, match="Non-ok HTTP response from apps.amocrm: 210\nResponse data: {'info': 'damn we lost'}"): request("api/v4/companies", {}) diff --git a/src/users/migrations/__init__.py b/tests/apps/amocrm/ids/__init__.py similarity index 100% rename from src/users/migrations/__init__.py rename to tests/apps/amocrm/ids/__init__.py diff --git a/src/amocrm/tests/ids/tests_b2c_pipeline_id.py b/tests/apps/amocrm/ids/tests_b2c_pipeline_id.py similarity index 76% rename from src/amocrm/tests/ids/tests_b2c_pipeline_id.py rename to tests/apps/amocrm/ids/tests_b2c_pipeline_id.py index 944cba32cf8..12768113661 100644 --- a/src/amocrm/tests/ids/tests_b2c_pipeline_id.py +++ b/tests/apps/amocrm/ids/tests_b2c_pipeline_id.py @@ -1,10 +1,10 @@ import pytest -from amocrm.dto.pipelines import Pipeline -from amocrm.dto.pipelines import PipelineStatus -from amocrm.exceptions import AmoCRMCacheException -from amocrm.ids import b2c_pipeline_id -from amocrm.ids import b2c_pipeline_status_id +from apps.amocrm.dto.pipelines import Pipeline +from apps.amocrm.dto.pipelines import PipelineStatus +from apps.amocrm.exceptions import AmoCRMCacheException +from apps.amocrm.ids import b2c_pipeline_id +from apps.amocrm.ids import b2c_pipeline_status_id @pytest.fixture @@ -24,7 +24,7 @@ def pipelines(b2c_pipeline): @pytest.fixture(autouse=True) def mock_get_pipelines(mocker, pipelines): - return mocker.patch("amocrm.dto.pipelines.AmoCRMPipelines.get", return_value=pipelines) + return mocker.patch("apps.amocrm.dto.pipelines.AmoCRMPipelines.get", return_value=pipelines) def test_return_pipeline_id(b2c_pipeline): diff --git a/src/amocrm/tests/ids/tests_catalog_id.py b/tests/apps/amocrm/ids/tests_catalog_id.py similarity index 76% rename from src/amocrm/tests/ids/tests_catalog_id.py rename to tests/apps/amocrm/ids/tests_catalog_id.py index fd1a86828c9..bfbb2033f32 100644 --- a/src/amocrm/tests/ids/tests_catalog_id.py +++ b/tests/apps/amocrm/ids/tests_catalog_id.py @@ -1,7 +1,7 @@ import pytest -from amocrm.exceptions import AmoCRMCacheException -from amocrm.ids import products_catalog_id +from apps.amocrm.exceptions import AmoCRMCacheException +from apps.amocrm.ids import products_catalog_id @pytest.fixture @@ -16,7 +16,7 @@ def catalogs(products_catalog): @pytest.fixture(autouse=True) def mock_get_catalogs(mocker, catalogs): - return mocker.patch("amocrm.dto.catalogs.AmoCRMCatalogs.get", return_value=catalogs) + return mocker.patch("apps.amocrm.dto.catalogs.AmoCRMCatalogs.get", return_value=catalogs) def test_return_catalog_id(products_catalog): diff --git a/src/amocrm/tests/ids/tests_contact_fields_ids.py b/tests/apps/amocrm/ids/tests_contact_fields_ids.py similarity index 75% rename from src/amocrm/tests/ids/tests_contact_fields_ids.py rename to tests/apps/amocrm/ids/tests_contact_fields_ids.py index 9c6a12a7392..2d87701c1df 100644 --- a/src/amocrm/tests/ids/tests_contact_fields_ids.py +++ b/tests/apps/amocrm/ids/tests_contact_fields_ids.py @@ -1,7 +1,7 @@ import pytest -from amocrm.exceptions import AmoCRMCacheException -from amocrm.ids import contact_field_id +from apps.amocrm.exceptions import AmoCRMCacheException +from apps.amocrm.ids import contact_field_id @pytest.fixture @@ -19,7 +19,7 @@ def fields(email_field): @pytest.fixture(autouse=True) def mock_get_contact_fields(mocker, fields): - return mocker.patch("amocrm.dto.catalogs.AmoCRMCatalogs.get_contacts_fields", return_value=fields) + return mocker.patch("apps.amocrm.dto.catalogs.AmoCRMCatalogs.get_contacts_fields", return_value=fields) def test_return_field_id(email_field): diff --git a/src/amocrm/tests/ids/tests_product_fields_ids.py b/tests/apps/amocrm/ids/tests_product_fields_ids.py similarity index 71% rename from src/amocrm/tests/ids/tests_product_fields_ids.py rename to tests/apps/amocrm/ids/tests_product_fields_ids.py index c6667b9620b..c892b30de6d 100644 --- a/src/amocrm/tests/ids/tests_product_fields_ids.py +++ b/tests/apps/amocrm/ids/tests_product_fields_ids.py @@ -1,12 +1,12 @@ import pytest -from amocrm.exceptions import AmoCRMCacheException -from amocrm.ids import product_field_id +from apps.amocrm.exceptions import AmoCRMCacheException +from apps.amocrm.ids import product_field_id @pytest.fixture(autouse=True) def mock_get_catalog_id(mocker): - return mocker.patch("amocrm.ids.products_catalog_id", return_value=123) + return mocker.patch("apps.amocrm.ids.products_catalog_id", return_value=123) @pytest.fixture @@ -21,7 +21,7 @@ def fields(group_field): @pytest.fixture(autouse=True) def mock_get_catalog_fields(mocker, fields): - return mocker.patch("amocrm.dto.catalogs.AmoCRMCatalogs.get_fields", return_value=fields) + return mocker.patch("apps.amocrm.dto.catalogs.AmoCRMCatalogs.get_fields", return_value=fields) def test_return_id_if_in_cache(group_field): diff --git a/tests/apps/amocrm/services/__init__.py b/tests/apps/amocrm/services/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/apps/amocrm/services/order/__init__.py b/tests/apps/amocrm/services/order/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/amocrm/tests/services/order/conftest.py b/tests/apps/amocrm/services/order/conftest.py similarity index 100% rename from src/amocrm/tests/services/order/conftest.py rename to tests/apps/amocrm/services/order/conftest.py diff --git a/src/amocrm/tests/services/order/tests_order_pusher.py b/tests/apps/amocrm/services/order/tests_order_pusher.py similarity index 88% rename from src/amocrm/tests/services/order/tests_order_pusher.py rename to tests/apps/amocrm/services/order/tests_order_pusher.py index 7bedf75f576..e07e8af8c5b 100644 --- a/src/amocrm/tests/services/order/tests_order_pusher.py +++ b/tests/apps/amocrm/services/order/tests_order_pusher.py @@ -2,10 +2,10 @@ from _decimal import Decimal -from amocrm.models import AmoCRMOrderLead -from amocrm.models import AmoCRMOrderTransaction -from amocrm.services.orders.order_pusher import AmoCRMOrderPusher -from amocrm.services.orders.order_pusher import AmoCRMOrderPusherException +from apps.amocrm.models import AmoCRMOrderLead +from apps.amocrm.models import AmoCRMOrderTransaction +from apps.amocrm.services.orders.order_pusher import AmoCRMOrderPusher +from apps.amocrm.services.orders.order_pusher import AmoCRMOrderPusherException pytestmark = [ pytest.mark.django_db, @@ -14,29 +14,29 @@ @pytest.fixture def mock_create_transaction(mocker): - mocker.patch("amocrm.dto.transaction.AmoCRMTransaction.create", return_value=22222) - return mocker.patch("amocrm.dto.transaction.AmoCRMTransaction.__init__", return_value=None) + mocker.patch("apps.amocrm.dto.transaction.AmoCRMTransaction.create", return_value=22222) + return mocker.patch("apps.amocrm.dto.transaction.AmoCRMTransaction.__init__", return_value=None) @pytest.fixture def mock_create_lead(mocker): - mocker.patch("amocrm.dto.lead.AmoCRMLead.create", return_value=11111) - return mocker.patch("amocrm.dto.lead.AmoCRMLead.__init__", return_value=None) + mocker.patch("apps.amocrm.dto.lead.AmoCRMLead.create", return_value=11111) + return mocker.patch("apps.amocrm.dto.lead.AmoCRMLead.__init__", return_value=None) @pytest.fixture def mock_update_lead(mocker): - return mocker.patch("amocrm.dto.lead.AmoCRMLead.update") + return mocker.patch("apps.amocrm.dto.lead.AmoCRMLead.update") @pytest.fixture def mock_push_lead(mocker): - return mocker.patch("amocrm.services.orders.order_pusher.AmoCRMOrderPusher.push_lead") + return mocker.patch("apps.amocrm.services.orders.order_pusher.AmoCRMOrderPusher.push_lead") @pytest.fixture def mock_push_order(mocker): - return mocker.patch("amocrm.services.orders.order_pusher.AmoCRMOrderPusher.push_order") + return mocker.patch("apps.amocrm.services.orders.order_pusher.AmoCRMOrderPusher.push_order") @pytest.fixture diff --git a/src/amocrm/tests/services/order/tests_order_returner.py b/tests/apps/amocrm/services/order/tests_order_returner.py similarity index 82% rename from src/amocrm/tests/services/order/tests_order_returner.py rename to tests/apps/amocrm/services/order/tests_order_returner.py index 25c266f9b9f..da17b15a68f 100644 --- a/src/amocrm/tests/services/order/tests_order_returner.py +++ b/tests/apps/amocrm/services/order/tests_order_returner.py @@ -1,7 +1,7 @@ import pytest -from amocrm.models import AmoCRMOrderTransaction -from amocrm.services.orders.order_returner import AmoCRMOrderReturner +from apps.amocrm.models import AmoCRMOrderTransaction +from apps.amocrm.services.orders.order_returner import AmoCRMOrderReturner pytestmark = [ pytest.mark.django_db, @@ -10,12 +10,12 @@ @pytest.fixture def mock_update_lead(mocker): - return mocker.patch("amocrm.dto.lead.AmoCRMLead.update") + return mocker.patch("apps.amocrm.dto.lead.AmoCRMLead.update") @pytest.fixture def mock_delete_transaction(mocker): - return mocker.patch("amocrm.dto.transaction.AmoCRMTransaction.delete") + return mocker.patch("apps.amocrm.dto.transaction.AmoCRMTransaction.delete") @pytest.fixture diff --git a/src/amocrm/tests/services/tests_course_pusher.py b/tests/apps/amocrm/services/tests_course_pusher.py similarity index 73% rename from src/amocrm/tests/services/tests_course_pusher.py rename to tests/apps/amocrm/services/tests_course_pusher.py index b0eebf5893f..e95c210beba 100644 --- a/src/amocrm/tests/services/tests_course_pusher.py +++ b/tests/apps/amocrm/services/tests_course_pusher.py @@ -1,7 +1,7 @@ import pytest -from amocrm.models import AmoCRMCourse -from amocrm.services.course_pusher import AmoCRMCoursePusher +from apps.amocrm.models import AmoCRMCourse +from apps.amocrm.services.course_pusher import AmoCRMCoursePusher pytestmark = [ pytest.mark.django_db, @@ -10,12 +10,12 @@ @pytest.fixture def mock_create(mocker): - return mocker.patch("amocrm.dto.product.AmoCRMProduct.create", return_value=555) + return mocker.patch("apps.amocrm.dto.product.AmoCRMProduct.create", return_value=555) @pytest.fixture def mock_update(mocker): - return mocker.patch("amocrm.dto.product.AmoCRMProduct.update") + return mocker.patch("apps.amocrm.dto.product.AmoCRMProduct.update") def test_call_create_if_amocrm_course_not_exist(course, mock_create): diff --git a/src/amocrm/tests/services/tests_group_pusher.py b/tests/apps/amocrm/services/tests_group_pusher.py similarity index 62% rename from src/amocrm/tests/services/tests_group_pusher.py rename to tests/apps/amocrm/services/tests_group_pusher.py index 28f9bd2c29b..582f8f62c64 100644 --- a/src/amocrm/tests/services/tests_group_pusher.py +++ b/tests/apps/amocrm/services/tests_group_pusher.py @@ -1,7 +1,7 @@ import pytest -from amocrm.services.group_pusher import AmoCRMGroupsPusher -from products.models import Group +from apps.amocrm.services.group_pusher import AmoCRMGroupsPusher +from apps.products.models import Group pytestmark = [ pytest.mark.django_db, @@ -10,7 +10,7 @@ @pytest.fixture(autouse=True) def mock_group_push(mocker): - return mocker.patch("amocrm.dto.groups.AmoCRMGroups.push", return_value=[("popug", 444), ("hehe", 333)]) + return mocker.patch("apps.amocrm.dto.groups.AmoCRMGroups.push", return_value=[("popug", 444), ("hehe", 333)]) @pytest.mark.usefixtures("_amocrm_groups") diff --git a/src/amocrm/tests/services/tests_user_pusher.py b/tests/apps/amocrm/services/tests_user_pusher.py similarity index 66% rename from src/amocrm/tests/services/tests_user_pusher.py rename to tests/apps/amocrm/services/tests_user_pusher.py index a0aec85b543..4dae275ed4b 100644 --- a/src/amocrm/tests/services/tests_user_pusher.py +++ b/tests/apps/amocrm/services/tests_user_pusher.py @@ -1,7 +1,7 @@ import pytest -from amocrm.models import AmoCRMUser -from amocrm.services.user_pusher import AmoCRMUserPusher +from apps.amocrm.models import AmoCRMUser +from apps.amocrm.services.user_pusher import AmoCRMUserPusher pytestmark = [ pytest.mark.django_db, @@ -10,12 +10,12 @@ @pytest.fixture def _mock_create(mocker): - mocker.patch("amocrm.dto.customer.AmoCRMCustomer.create", return_value=(4444, 5555)) + mocker.patch("apps.amocrm.dto.customer.AmoCRMCustomer.create", return_value=(4444, 5555)) @pytest.fixture def mock_update(mocker): - return mocker.patch("amocrm.dto.customer.AmoCRMCustomer.update") + return mocker.patch("apps.amocrm.dto.customer.AmoCRMCustomer.update") @pytest.mark.usefixtures("_mock_create") diff --git a/src/amocrm/tests/tests_access_token_getter.py b/tests/apps/amocrm/tests_access_token_getter.py similarity index 96% rename from src/amocrm/tests/tests_access_token_getter.py rename to tests/apps/amocrm/tests_access_token_getter.py index cc3335e4338..6998cc977d9 100644 --- a/src/amocrm/tests/tests_access_token_getter.py +++ b/tests/apps/amocrm/tests_access_token_getter.py @@ -2,7 +2,7 @@ from django.core.cache import cache -from amocrm.services.access_token_getter import AmoCRMTokenGetter +from apps.amocrm.services.access_token_getter import AmoCRMTokenGetter pytestmark = [ pytest.mark.django_db, diff --git a/src/banking/tests/atol/conftest.py b/tests/apps/banking/atol/conftest.py similarity index 91% rename from src/banking/tests/atol/conftest.py rename to tests/apps/banking/atol/conftest.py index 33bb08e9a0d..a0a8852a91a 100644 --- a/src/banking/tests/atol/conftest.py +++ b/tests/apps/banking/atol/conftest.py @@ -1,6 +1,6 @@ import pytest -from banking.atol.client import AtolClient +from apps.banking.atol.client import AtolClient pytestmark = [ pytest.mark.django_db, @@ -30,7 +30,7 @@ def atol(order): @pytest.fixture def post(mocker): - return mocker.patch("banking.atol.client.AtolClient.post") + return mocker.patch("apps.banking.atol.client.AtolClient.post") @pytest.fixture diff --git a/src/banking/tests/atol/test_atol_auth.py b/tests/apps/banking/atol/test_atol_auth.py similarity index 88% rename from src/banking/tests/atol/test_atol_auth.py rename to tests/apps/banking/atol/test_atol_auth.py index 17e818e07ec..5b71a248804 100644 --- a/src/banking/tests/atol/test_atol_auth.py +++ b/tests/apps/banking/atol/test_atol_auth.py @@ -2,8 +2,8 @@ from respx import MockRouter -from banking.atol import auth -from banking.atol import exceptions +from apps.banking.atol import auth +from apps.banking.atol import exceptions pytestmark = [ pytest.mark.django_db, @@ -13,7 +13,7 @@ @pytest.fixture def fetch(mocker): - return mocker.patch("banking.atol.auth.fetch", return_value="secret") + return mocker.patch("apps.banking.atol.auth.fetch", return_value="secret") def test_ok(respx_mock: MockRouter): diff --git a/src/banking/tests/atol/test_atol_data.py b/tests/apps/banking/atol/test_atol_data.py similarity index 100% rename from src/banking/tests/atol/test_atol_data.py rename to tests/apps/banking/atol/test_atol_data.py diff --git a/src/banking/tests/atol/test_atol_notifications.py b/tests/apps/banking/atol/test_atol_notifications.py similarity index 93% rename from src/banking/tests/atol/test_atol_notifications.py rename to tests/apps/banking/atol/test_atol_notifications.py index 206d8f0a623..46f4c500d7e 100644 --- a/src/banking/tests/atol/test_atol_notifications.py +++ b/tests/apps/banking/atol/test_atol_notifications.py @@ -1,6 +1,6 @@ import pytest -from banking.models import Receipt +from apps.banking.models import Receipt pytestmark = [ pytest.mark.django_db, diff --git a/src/banking/tests/tests_bank_selector.py b/tests/apps/banking/tests_bank_selector.py similarity index 64% rename from src/banking/tests/tests_bank_selector.py rename to tests/apps/banking/tests_bank_selector.py index 12c8355df54..d349be8a02c 100644 --- a/src/banking/tests/tests_bank_selector.py +++ b/tests/apps/banking/tests_bank_selector.py @@ -1,10 +1,10 @@ import pytest -from banking.selector import get_bank -from banking.zero_price_bank import ZeroPriceBank -from stripebank.bank import StripeBank -from tinkoff.bank import TinkoffBank -from tinkoff.credit import TinkoffCredit +from apps.banking.selector import get_bank +from apps.banking.zero_price_bank import ZeroPriceBank +from apps.stripebank.bank import StripeBank +from apps.tinkoff.bank import TinkoffBank +from apps.tinkoff.credit import TinkoffCredit @pytest.mark.parametrize( diff --git a/src/banking/tests/tests_price_calculator.py b/tests/apps/banking/tests_price_calculator.py similarity index 90% rename from src/banking/tests/tests_price_calculator.py rename to tests/apps/banking/tests_price_calculator.py index 5e31eee1ad0..68b1c4ca34e 100644 --- a/src/banking/tests/tests_price_calculator.py +++ b/tests/apps/banking/tests_price_calculator.py @@ -1,7 +1,7 @@ from decimal import Decimal import pytest -from banking import price_calculator +from apps.banking import price_calculator @pytest.mark.parametrize( diff --git a/src/chains/tests/chain_sender/conftest.py b/tests/apps/chains/chain_sender/conftest.py similarity index 58% rename from src/chains/tests/chain_sender/conftest.py rename to tests/apps/chains/chain_sender/conftest.py index d2ce958e44a..233b7043ab6 100644 --- a/src/chains/tests/chain_sender/conftest.py +++ b/tests/apps/chains/chain_sender/conftest.py @@ -1,6 +1,6 @@ import pytest -from chains.services import ChainSender +from apps.chains.services import ChainSender pytestmark = [pytest.mark.django_db] @@ -12,4 +12,4 @@ def chain_sender(chain): @pytest.fixture def send_message(mocker): - return mocker.patch("chains.services.chain_sender.ChainSender.send") + return mocker.patch("apps.chains.services.chain_sender.ChainSender.send") diff --git a/src/chains/tests/chain_sender/test_chain_sender_integrational.py b/tests/apps/chains/chain_sender/test_chain_sender_integrational.py similarity index 95% rename from src/chains/tests/chain_sender/test_chain_sender_integrational.py rename to tests/apps/chains/chain_sender/test_chain_sender_integrational.py index f46716dc5a8..301251005f9 100644 --- a/src/chains/tests/chain_sender/test_chain_sender_integrational.py +++ b/tests/apps/chains/chain_sender/test_chain_sender_integrational.py @@ -1,8 +1,8 @@ import pytest -from chains import tasks -from chains.models import Message -from users.models import User +from apps.chains import tasks +from apps.chains.models import Message +from apps.users.models import User pytestmark = [ pytest.mark.django_db(transaction=True), @@ -12,7 +12,7 @@ @pytest.fixture def owl(mocker): - return mocker.patch("mailing.tasks.Owl") + return mocker.patch("apps.mailing.tasks.Owl") @pytest.fixture diff --git a/src/chains/tests/chain_sender/test_chain_tasks.py b/tests/apps/chains/chain_sender/test_chain_tasks.py similarity index 95% rename from src/chains/tests/chain_sender/test_chain_tasks.py rename to tests/apps/chains/chain_sender/test_chain_tasks.py index b7bbd15691c..ccdfd239469 100644 --- a/src/chains/tests/chain_sender/test_chain_tasks.py +++ b/tests/apps/chains/chain_sender/test_chain_tasks.py @@ -1,6 +1,6 @@ import pytest -from chains import tasks +from apps.chains import tasks pytestmark = [ pytest.mark.django_db, diff --git a/src/chains/tests/chain_sender/test_sending_next_messages.py b/tests/apps/chains/chain_sender/test_sending_next_messages.py similarity index 100% rename from src/chains/tests/chain_sender/test_sending_next_messages.py rename to tests/apps/chains/chain_sender/test_sending_next_messages.py diff --git a/src/chains/tests/chain_sender/test_sending_root_messages.py b/tests/apps/chains/chain_sender/test_sending_root_messages.py similarity index 100% rename from src/chains/tests/chain_sender/test_sending_root_messages.py rename to tests/apps/chains/chain_sender/test_sending_root_messages.py diff --git a/src/chains/tests/conftest.py b/tests/apps/chains/conftest.py similarity index 100% rename from src/chains/tests/conftest.py rename to tests/apps/chains/conftest.py diff --git a/src/chains/tests/message_sender/conftest.py b/tests/apps/chains/message_sender/conftest.py similarity index 63% rename from src/chains/tests/message_sender/conftest.py rename to tests/apps/chains/message_sender/conftest.py index d3b57b9329a..53896946b75 100644 --- a/src/chains/tests/message_sender/conftest.py +++ b/tests/apps/chains/message_sender/conftest.py @@ -1,6 +1,6 @@ import pytest -from chains.services import MessageSender +from apps.chains.services import MessageSender pytestmark = [pytest.mark.django_db] @@ -12,4 +12,4 @@ def message_sender(): @pytest.fixture(autouse=True) def owl(mocker): - return mocker.patch("mailing.tasks.Owl") + return mocker.patch("apps.mailing.tasks.Owl") diff --git a/src/chains/tests/message_sender/test_sending_message.py b/tests/apps/chains/message_sender/test_sending_message.py similarity index 97% rename from src/chains/tests/message_sender/test_sending_message.py rename to tests/apps/chains/message_sender/test_sending_message.py index 289d4ba412a..5f521f85530 100644 --- a/src/chains/tests/message_sender/test_sending_message.py +++ b/tests/apps/chains/message_sender/test_sending_message.py @@ -2,7 +2,7 @@ from anymail.exceptions import AnymailRecipientsRefused -from chains.models import Progress +from apps.chains.models import Progress pytestmark = [ pytest.mark.django_db, diff --git a/src/chains/tests/test_message_time_to_send.py b/tests/apps/chains/test_message_time_to_send.py similarity index 100% rename from src/chains/tests/test_message_time_to_send.py rename to tests/apps/chains/test_message_time_to_send.py diff --git a/src/chains/tests/unit/test_chain_queryset_active.py b/tests/apps/chains/unit/test_chain_queryset_active.py similarity index 93% rename from src/chains/tests/unit/test_chain_queryset_active.py rename to tests/apps/chains/unit/test_chain_queryset_active.py index b0e772d5048..4e2a13c8fdc 100644 --- a/src/chains/tests/unit/test_chain_queryset_active.py +++ b/tests/apps/chains/unit/test_chain_queryset_active.py @@ -1,6 +1,6 @@ import pytest -from chains.models import Chain +from apps.chains.models import Chain pytestmark = [ pytest.mark.django_db, diff --git a/src/chains/tests/unit/test_chain_queryset_editable.py b/tests/apps/chains/unit/test_chain_queryset_editable.py similarity index 95% rename from src/chains/tests/unit/test_chain_queryset_editable.py rename to tests/apps/chains/unit/test_chain_queryset_editable.py index 4c9a4e77122..4c9e10fd5d0 100644 --- a/src/chains/tests/unit/test_chain_queryset_editable.py +++ b/tests/apps/chains/unit/test_chain_queryset_editable.py @@ -1,6 +1,6 @@ import pytest -from chains.models import Chain +from apps.chains.models import Chain pytestmark = [ pytest.mark.django_db, diff --git a/src/chains/tests/unit/test_progress_get_last.py b/tests/apps/chains/unit/test_progress_get_last.py similarity index 95% rename from src/chains/tests/unit/test_progress_get_last.py rename to tests/apps/chains/unit/test_progress_get_last.py index 73ac12607da..9b91e1635f8 100644 --- a/src/chains/tests/unit/test_progress_get_last.py +++ b/tests/apps/chains/unit/test_progress_get_last.py @@ -1,6 +1,6 @@ import pytest -from chains.models import Progress +from apps.chains.models import Progress pytestmark = [ pytest.mark.django_db, diff --git a/src/diplomas/tests/api/conftest.py b/tests/apps/diplomas/api/conftest.py similarity index 88% rename from src/diplomas/tests/api/conftest.py rename to tests/apps/diplomas/api/conftest.py index b2a51530224..1a10e1340b3 100644 --- a/src/diplomas/tests/api/conftest.py +++ b/tests/apps/diplomas/api/conftest.py @@ -1,6 +1,6 @@ import pytest -from diplomas.models import Languages +from apps.diplomas.models import Languages pytestmark = [pytest.mark.django_db] diff --git a/src/diplomas/tests/api/tests_diploma_create.py b/tests/apps/diplomas/api/tests_diploma_create.py similarity index 93% rename from src/diplomas/tests/api/tests_diploma_create.py rename to tests/apps/diplomas/api/tests_diploma_create.py index 7c7f8b6027a..ec8033cfe5b 100644 --- a/src/diplomas/tests/api/tests_diploma_create.py +++ b/tests/apps/diplomas/api/tests_diploma_create.py @@ -1,7 +1,7 @@ import pytest -from diplomas.models import Diploma -from diplomas.models import Languages +from apps.diplomas.models import Diploma +from apps.diplomas.models import Languages pytestmark = [pytest.mark.django_db] diff --git a/src/diplomas/tests/api/tests_diploma_deletion.py b/tests/apps/diplomas/api/tests_diploma_deletion.py similarity index 100% rename from src/diplomas/tests/api/tests_diploma_deletion.py rename to tests/apps/diplomas/api/tests_diploma_deletion.py diff --git a/src/diplomas/tests/api/tests_diploma_list.py b/tests/apps/diplomas/api/tests_diploma_list.py similarity index 100% rename from src/diplomas/tests/api/tests_diploma_list.py rename to tests/apps/diplomas/api/tests_diploma_list.py diff --git a/src/diplomas/tests/api/tests_diploma_retrieve.py b/tests/apps/diplomas/api/tests_diploma_retrieve.py similarity index 96% rename from src/diplomas/tests/api/tests_diploma_retrieve.py rename to tests/apps/diplomas/api/tests_diploma_retrieve.py index 9f7c717b1b3..7f3115d73e0 100644 --- a/src/diplomas/tests/api/tests_diploma_retrieve.py +++ b/tests/apps/diplomas/api/tests_diploma_retrieve.py @@ -1,6 +1,6 @@ import pytest -from diplomas.models import Languages +from apps.diplomas.models import Languages pytestmark = [pytest.mark.django_db] diff --git a/src/diplomas/tests/api/tests_diploma_update_is_disabled.py b/tests/apps/diplomas/api/tests_diploma_update_is_disabled.py similarity index 100% rename from src/diplomas/tests/api/tests_diploma_update_is_disabled.py rename to tests/apps/diplomas/api/tests_diploma_update_is_disabled.py diff --git a/src/diplomas/tests/conftest.py b/tests/apps/diplomas/conftest.py similarity index 88% rename from src/diplomas/tests/conftest.py rename to tests/apps/diplomas/conftest.py index ecbe08cd678..52a1dec2301 100644 --- a/src/diplomas/tests/conftest.py +++ b/tests/apps/diplomas/conftest.py @@ -1,9 +1,9 @@ from functools import partial import pytest -from diplomas.models import Languages -from diplomas.services import DiplomaGenerator -from users.models import User +from apps.diplomas.models import Languages +from apps.diplomas.services import DiplomaGenerator +from apps.users.models import User @pytest.fixture(autouse=True) diff --git a/src/diplomas/tests/diploma_generator/tests_diploma_generator_functional.py b/tests/apps/diplomas/diploma_generator/tests_diploma_generator_functional.py similarity index 93% rename from src/diplomas/tests/diploma_generator/tests_diploma_generator_functional.py rename to tests/apps/diplomas/diploma_generator/tests_diploma_generator_functional.py index 8e1b9f32f53..1584ef05982 100644 --- a/src/diplomas/tests/diploma_generator/tests_diploma_generator_functional.py +++ b/tests/apps/diplomas/diploma_generator/tests_diploma_generator_functional.py @@ -2,8 +2,8 @@ from respx import MockRouter -from diplomas.models import Diploma -from diplomas.tasks import generate_diploma +from apps.diplomas.models import Diploma +from apps.diplomas.tasks import generate_diploma pytestmark = [ pytest.mark.django_db, diff --git a/src/diplomas/tests/diploma_generator/tests_diploma_generator_retry.py b/tests/apps/diplomas/diploma_generator/tests_diploma_generator_retry.py similarity index 92% rename from src/diplomas/tests/diploma_generator/tests_diploma_generator_retry.py rename to tests/apps/diplomas/diploma_generator/tests_diploma_generator_retry.py index 2c1c8f01a7e..14e87850983 100644 --- a/src/diplomas/tests/diploma_generator/tests_diploma_generator_retry.py +++ b/tests/apps/diplomas/diploma_generator/tests_diploma_generator_retry.py @@ -3,7 +3,7 @@ import httpx from respx import MockRouter -from diplomas.services.diploma_generator import WrongDiplomaServiceResponse +from apps.diplomas.services.diploma_generator import WrongDiplomaServiceResponse pytestmark = [ pytest.mark.slow, diff --git a/src/diplomas/tests/diploma_generator/tests_diploma_generator_unit.py b/tests/apps/diplomas/diploma_generator/tests_diploma_generator_unit.py similarity index 96% rename from src/diplomas/tests/diploma_generator/tests_diploma_generator_unit.py rename to tests/apps/diplomas/diploma_generator/tests_diploma_generator_unit.py index 06183649590..7186e367799 100644 --- a/src/diplomas/tests/diploma_generator/tests_diploma_generator_unit.py +++ b/tests/apps/diplomas/diploma_generator/tests_diploma_generator_unit.py @@ -1,7 +1,7 @@ import pytest -from diplomas.models import DiplomaTemplate -from users.models import User +from apps.diplomas.models import DiplomaTemplate +from apps.users.models import User pytestmark = [ pytest.mark.django_db, diff --git a/src/diplomas/tests/diploma_queryset/test_diploma_filter_with_template.py b/tests/apps/diplomas/diploma_queryset/test_diploma_filter_with_template.py similarity index 92% rename from src/diplomas/tests/diploma_queryset/test_diploma_filter_with_template.py rename to tests/apps/diplomas/diploma_queryset/test_diploma_filter_with_template.py index 762be668a9b..896fa3a6427 100644 --- a/src/diplomas/tests/diploma_queryset/test_diploma_filter_with_template.py +++ b/tests/apps/diplomas/diploma_queryset/test_diploma_filter_with_template.py @@ -1,7 +1,7 @@ import pytest -from diplomas.models import Diploma -from diplomas.models import Languages +from apps.diplomas.models import Diploma +from apps.diplomas.models import Languages pytestmark = [ pytest.mark.django_db, diff --git a/src/diplomas/tests/tests_diploma_get_absolute_url.py b/tests/apps/diplomas/tests_diploma_get_absolute_url.py similarity index 100% rename from src/diplomas/tests/tests_diploma_get_absolute_url.py rename to tests/apps/diplomas/tests_diploma_get_absolute_url.py diff --git a/src/diplomas/tests/tests_diploma_regenerator.py b/tests/apps/diplomas/tests_diploma_regenerator.py similarity index 89% rename from src/diplomas/tests/tests_diploma_regenerator.py rename to tests/apps/diplomas/tests_diploma_regenerator.py index 59e6af604c7..b70794dd185 100644 --- a/src/diplomas/tests/tests_diploma_regenerator.py +++ b/tests/apps/diplomas/tests_diploma_regenerator.py @@ -1,10 +1,10 @@ import pytest -from diplomas import tasks -from diplomas.models import Diploma -from diplomas.models import Languages -from diplomas.services import DiplomaGenerator -from diplomas.services import DiplomaRegenerator +from apps.diplomas import tasks +from apps.diplomas.models import Diploma +from apps.diplomas.models import Languages +from apps.diplomas.services import DiplomaGenerator +from apps.diplomas.services import DiplomaRegenerator pytestmark = [ pytest.mark.django_db, @@ -14,7 +14,7 @@ @pytest.fixture(autouse=True) def _mock_diploma_generator_fetch_image(mocker, factory): image = factory.image() - mocker.patch("diplomas.services.diploma_regenerator.DiplomaGenerator.fetch_image", return_value=image) + mocker.patch("apps.diplomas.services.diploma_regenerator.DiplomaGenerator.fetch_image", return_value=image) @pytest.fixture(autouse=True) @@ -40,12 +40,12 @@ def diploma_en(mixer, order): @pytest.fixture def mock_diploma_generator(mocker): - return mocker.patch("diplomas.services.diploma_generator.DiplomaGenerator.__call__", autospec=True) + return mocker.patch("apps.diplomas.services.diploma_generator.DiplomaGenerator.__call__", autospec=True) @pytest.fixture def mock_diploma_regenerator(mocker): - return mocker.patch("diplomas.services.diploma_regenerator.DiplomaRegenerator.__call__", autospec=True) + return mocker.patch("apps.diplomas.services.diploma_regenerator.DiplomaRegenerator.__call__", autospec=True) @pytest.fixture diff --git a/src/homework/tests/answers/tests_answer_get_purchased_course.py b/tests/apps/homework/answers/tests_answer_get_purchased_course.py similarity index 100% rename from src/homework/tests/answers/tests_answer_get_purchased_course.py rename to tests/apps/homework/answers/tests_answer_get_purchased_course.py diff --git a/src/homework/tests/answers/tests_answer_str.py b/tests/apps/homework/answers/tests_answer_str.py similarity index 100% rename from src/homework/tests/answers/tests_answer_str.py rename to tests/apps/homework/answers/tests_answer_str.py diff --git a/src/homework/tests/answers/tests_answers_allowed_for_user_queryset.py b/tests/apps/homework/answers/tests_answers_allowed_for_user_queryset.py similarity index 98% rename from src/homework/tests/answers/tests_answers_allowed_for_user_queryset.py rename to tests/apps/homework/answers/tests_answers_allowed_for_user_queryset.py index 63ef2e6d41c..8b8fd940852 100644 --- a/src/homework/tests/answers/tests_answers_allowed_for_user_queryset.py +++ b/tests/apps/homework/answers/tests_answers_allowed_for_user_queryset.py @@ -1,6 +1,6 @@ import pytest -from homework.models import Answer +from apps.homework.models import Answer pytestmark = [pytest.mark.django_db] diff --git a/src/homework/tests/answers/tests_answers_get_absolute_urls.py b/tests/apps/homework/answers/tests_answers_get_absolute_urls.py similarity index 100% rename from src/homework/tests/answers/tests_answers_get_absolute_urls.py rename to tests/apps/homework/answers/tests_answers_get_absolute_urls.py diff --git a/src/homework/tests/api/conftest.py b/tests/apps/homework/api/conftest.py similarity index 100% rename from src/homework/tests/api/conftest.py rename to tests/apps/homework/api/conftest.py diff --git a/src/homework/tests/api/tests_answer_create.py b/tests/apps/homework/api/tests_answer_create.py similarity index 99% rename from src/homework/tests/api/tests_answer_create.py rename to tests/apps/homework/api/tests_answer_create.py index 4cc7bb0dd26..c07eec7d20e 100644 --- a/src/homework/tests/api/tests_answer_create.py +++ b/tests/apps/homework/api/tests_answer_create.py @@ -1,6 +1,6 @@ import pytest -from homework.models import Answer +from apps.homework.models import Answer pytestmark = [ pytest.mark.django_db, diff --git a/src/homework/tests/api/tests_answer_destroy.py b/tests/apps/homework/api/tests_answer_destroy.py similarity index 97% rename from src/homework/tests/api/tests_answer_destroy.py rename to tests/apps/homework/api/tests_answer_destroy.py index 43610e08fd3..95acc202bdf 100644 --- a/src/homework/tests/api/tests_answer_destroy.py +++ b/tests/apps/homework/api/tests_answer_destroy.py @@ -1,6 +1,6 @@ import pytest -from homework.models import Answer +from apps.homework.models import Answer pytestmark = [ pytest.mark.django_db, diff --git a/src/homework/tests/api/tests_answer_image_upload.py b/tests/apps/homework/api/tests_answer_image_upload.py similarity index 96% rename from src/homework/tests/api/tests_answer_image_upload.py rename to tests/apps/homework/api/tests_answer_image_upload.py index 222b601c3ca..3548aa9af89 100644 --- a/src/homework/tests/api/tests_answer_image_upload.py +++ b/tests/apps/homework/api/tests_answer_image_upload.py @@ -1,6 +1,6 @@ import pytest -from homework.models import AnswerImage +from apps.homework.models import AnswerImage pytestmark = [pytest.mark.django_db] diff --git a/src/homework/tests/api/tests_answer_list.py b/tests/apps/homework/api/tests_answer_list.py similarity index 100% rename from src/homework/tests/api/tests_answer_list.py rename to tests/apps/homework/api/tests_answer_list.py diff --git a/src/homework/tests/api/tests_answer_retrieval_access_logs.py b/tests/apps/homework/api/tests_answer_retrieval_access_logs.py similarity index 96% rename from src/homework/tests/api/tests_answer_retrieval_access_logs.py rename to tests/apps/homework/api/tests_answer_retrieval_access_logs.py index d89e6c2fd81..67427daf54b 100644 --- a/src/homework/tests/api/tests_answer_retrieval_access_logs.py +++ b/tests/apps/homework/api/tests_answer_retrieval_access_logs.py @@ -1,6 +1,6 @@ import pytest -from homework.models import AnswerAccessLogEntry +from apps.homework.models import AnswerAccessLogEntry pytestmark = [ pytest.mark.django_db, diff --git a/src/homework/tests/api/tests_answer_retrieve.py b/tests/apps/homework/api/tests_answer_retrieve.py similarity index 100% rename from src/homework/tests/api/tests_answer_retrieve.py rename to tests/apps/homework/api/tests_answer_retrieve.py diff --git a/src/homework/tests/api/tests_answer_update.py b/tests/apps/homework/api/tests_answer_update.py similarity index 98% rename from src/homework/tests/api/tests_answer_update.py rename to tests/apps/homework/api/tests_answer_update.py index c47e6a7b702..d7a9196e23b 100644 --- a/src/homework/tests/api/tests_answer_update.py +++ b/tests/apps/homework/api/tests_answer_update.py @@ -3,7 +3,7 @@ from datetime import timezone import pytest -from homework.models import Answer +from apps.homework.models import Answer pytestmark = [ pytest.mark.django_db, diff --git a/src/homework/tests/api/tests_comments_list.py b/tests/apps/homework/api/tests_comments_list.py similarity index 100% rename from src/homework/tests/api/tests_comments_list.py rename to tests/apps/homework/api/tests_comments_list.py diff --git a/src/homework/tests/api/tests_comments_list_descendants.py b/tests/apps/homework/api/tests_comments_list_descendants.py similarity index 100% rename from src/homework/tests/api/tests_comments_list_descendants.py rename to tests/apps/homework/api/tests_comments_list_descendants.py diff --git a/src/homework/tests/api/tests_markdown_sanitization.py b/tests/apps/homework/api/tests_markdown_sanitization.py similarity index 100% rename from src/homework/tests/api/tests_markdown_sanitization.py rename to tests/apps/homework/api/tests_markdown_sanitization.py diff --git a/src/homework/tests/api/tests_question_retrieve.py b/tests/apps/homework/api/tests_question_retrieve.py similarity index 100% rename from src/homework/tests/api/tests_question_retrieve.py rename to tests/apps/homework/api/tests_question_retrieve.py diff --git a/src/homework/tests/api/tests_reaction_create.py b/tests/apps/homework/api/tests_reaction_create.py similarity index 96% rename from src/homework/tests/api/tests_reaction_create.py rename to tests/apps/homework/api/tests_reaction_create.py index e928b0d6ece..09a18e48e1d 100644 --- a/src/homework/tests/api/tests_reaction_create.py +++ b/tests/apps/homework/api/tests_reaction_create.py @@ -1,6 +1,6 @@ import pytest -from homework.models.reaction import Reaction +from apps.homework.models.reaction import Reaction pytestmark = [ pytest.mark.django_db, diff --git a/src/homework/tests/api/tests_reaction_destroy.py b/tests/apps/homework/api/tests_reaction_destroy.py similarity index 92% rename from src/homework/tests/api/tests_reaction_destroy.py rename to tests/apps/homework/api/tests_reaction_destroy.py index af7a9c83077..23ec2726462 100644 --- a/src/homework/tests/api/tests_reaction_destroy.py +++ b/tests/apps/homework/api/tests_reaction_destroy.py @@ -1,6 +1,6 @@ import pytest -from homework.models.reaction import Reaction +from apps.homework.models.reaction import Reaction pytestmark = [ pytest.mark.django_db, diff --git a/src/homework/tests/conftest.py b/tests/apps/homework/conftest.py similarity index 100% rename from src/homework/tests/conftest.py rename to tests/apps/homework/conftest.py diff --git a/src/homework/tests/cross_check/conftest.py b/tests/apps/homework/cross_check/conftest.py similarity index 83% rename from src/homework/tests/cross_check/conftest.py rename to tests/apps/homework/cross_check/conftest.py index 77e6f68883a..d5ac1af5998 100644 --- a/src/homework/tests/cross_check/conftest.py +++ b/tests/apps/homework/cross_check/conftest.py @@ -1,7 +1,7 @@ import pytest -from homework.services import AnswerCrossCheckDispatcher -from homework.services import QuestionCrossCheckDispatcher +from apps.homework.services import AnswerCrossCheckDispatcher +from apps.homework.services import QuestionCrossCheckDispatcher pytestmark = [pytest.mark.django_db] diff --git a/src/homework/tests/cross_check/tests_crosscheck_dispatcher.py b/tests/apps/homework/cross_check/tests_crosscheck_dispatcher.py similarity index 93% rename from src/homework/tests/cross_check/tests_crosscheck_dispatcher.py rename to tests/apps/homework/cross_check/tests_crosscheck_dispatcher.py index db6d3ea70ed..9fdb29ae987 100644 --- a/src/homework/tests/cross_check/tests_crosscheck_dispatcher.py +++ b/tests/apps/homework/cross_check/tests_crosscheck_dispatcher.py @@ -1,6 +1,6 @@ import pytest -from homework.models import AnswerCrossCheck +from apps.homework.models import AnswerCrossCheck pytestmark = [pytest.mark.django_db] diff --git a/src/homework/tests/cross_check/tests_crosscheck_is_checked.py b/tests/apps/homework/cross_check/tests_crosscheck_is_checked.py similarity index 100% rename from src/homework/tests/cross_check/tests_crosscheck_is_checked.py rename to tests/apps/homework/cross_check/tests_crosscheck_is_checked.py diff --git a/src/homework/tests/cross_check/tests_dispatch_answers_of_the_same_user.py b/tests/apps/homework/cross_check/tests_dispatch_answers_of_the_same_user.py similarity index 95% rename from src/homework/tests/cross_check/tests_dispatch_answers_of_the_same_user.py rename to tests/apps/homework/cross_check/tests_dispatch_answers_of_the_same_user.py index 8f8655bb35b..0ed9ca46de3 100644 --- a/src/homework/tests/cross_check/tests_dispatch_answers_of_the_same_user.py +++ b/tests/apps/homework/cross_check/tests_dispatch_answers_of_the_same_user.py @@ -1,6 +1,6 @@ import pytest -from homework.models import AnswerCrossCheck +from apps.homework.models import AnswerCrossCheck pytestmark = [ pytest.mark.django_db, diff --git a/src/homework/tests/cross_check/tests_get_answer_to_check.py b/tests/apps/homework/cross_check/tests_get_answer_to_check.py similarity index 96% rename from src/homework/tests/cross_check/tests_get_answer_to_check.py rename to tests/apps/homework/cross_check/tests_get_answer_to_check.py index caf72a1ea33..f533e056769 100644 --- a/src/homework/tests/cross_check/tests_get_answer_to_check.py +++ b/tests/apps/homework/cross_check/tests_get_answer_to_check.py @@ -1,6 +1,6 @@ import pytest -from homework.models import Answer +from apps.homework.models import Answer pytestmark = [ pytest.mark.django_db, diff --git a/src/homework/tests/cross_check/tests_get_crosscheck_count.py b/tests/apps/homework/cross_check/tests_get_crosscheck_count.py similarity index 100% rename from src/homework/tests/cross_check/tests_get_crosscheck_count.py rename to tests/apps/homework/cross_check/tests_get_crosscheck_count.py diff --git a/src/homework/tests/cross_check/tests_question_crosscheck_dispatcher.py b/tests/apps/homework/cross_check/tests_question_crosscheck_dispatcher.py similarity index 93% rename from src/homework/tests/cross_check/tests_question_crosscheck_dispatcher.py rename to tests/apps/homework/cross_check/tests_question_crosscheck_dispatcher.py index fc42d0aac74..759e52e781b 100644 --- a/src/homework/tests/cross_check/tests_question_crosscheck_dispatcher.py +++ b/tests/apps/homework/cross_check/tests_question_crosscheck_dispatcher.py @@ -1,7 +1,7 @@ import pytest -from homework import tasks -from homework.models import AnswerCrossCheck +from apps.homework import tasks +from apps.homework.models import AnswerCrossCheck pytestmark = [pytest.mark.django_db] diff --git a/src/homework/tests/cross_check/tests_question_crosscheck_queryset.py b/tests/apps/homework/cross_check/tests_question_crosscheck_queryset.py similarity index 100% rename from src/homework/tests/cross_check/tests_question_crosscheck_queryset.py rename to tests/apps/homework/cross_check/tests_question_crosscheck_queryset.py diff --git a/src/homework/tests/new_answer_notifier/conftest.py b/tests/apps/homework/new_answer_notifier/conftest.py similarity index 87% rename from src/homework/tests/new_answer_notifier/conftest.py rename to tests/apps/homework/new_answer_notifier/conftest.py index cea48c8a611..fbf0f481176 100644 --- a/src/homework/tests/new_answer_notifier/conftest.py +++ b/tests/apps/homework/new_answer_notifier/conftest.py @@ -1,6 +1,6 @@ import pytest -from homework.services import NewAnswerNotifier +from apps.homework.services import NewAnswerNotifier @pytest.fixture diff --git a/src/homework/tests/new_answer_notifier/tests_answer_notifier_get_template_context.py b/tests/apps/homework/new_answer_notifier/tests_answer_notifier_get_template_context.py similarity index 100% rename from src/homework/tests/new_answer_notifier/tests_answer_notifier_get_template_context.py rename to tests/apps/homework/new_answer_notifier/tests_answer_notifier_get_template_context.py diff --git a/src/homework/tests/new_answer_notifier/tests_get_users_to_notify.py b/tests/apps/homework/new_answer_notifier/tests_get_users_to_notify.py similarity index 100% rename from src/homework/tests/new_answer_notifier/tests_get_users_to_notify.py rename to tests/apps/homework/new_answer_notifier/tests_get_users_to_notify.py diff --git a/src/homework/tests/new_answer_notifier/tests_new_answer_email.py b/tests/apps/homework/new_answer_notifier/tests_new_answer_email.py similarity index 100% rename from src/homework/tests/new_answer_notifier/tests_new_answer_email.py rename to tests/apps/homework/new_answer_notifier/tests_new_answer_email.py diff --git a/src/homework/tests/new_answer_notifier/tests_new_answer_notifier_integration.py b/tests/apps/homework/new_answer_notifier/tests_new_answer_notifier_integration.py similarity index 98% rename from src/homework/tests/new_answer_notifier/tests_new_answer_notifier_integration.py rename to tests/apps/homework/new_answer_notifier/tests_new_answer_notifier_integration.py index bb826d344ce..d2d25d9268e 100644 --- a/src/homework/tests/new_answer_notifier/tests_new_answer_notifier_integration.py +++ b/tests/apps/homework/new_answer_notifier/tests_new_answer_notifier_integration.py @@ -1,6 +1,6 @@ import pytest -from homework.models import Answer +from apps.homework.models import Answer pytestmark = [ pytest.mark.django_db, diff --git a/src/homework/tests/questions/tests_question_absolute_url.py b/tests/apps/homework/questions/tests_question_absolute_url.py similarity index 100% rename from src/homework/tests/questions/tests_question_absolute_url.py rename to tests/apps/homework/questions/tests_question_absolute_url.py diff --git a/src/homework/tests/reactions/test_reaction_creator.py b/tests/apps/homework/reactions/test_reaction_creator.py similarity index 91% rename from src/homework/tests/reactions/test_reaction_creator.py rename to tests/apps/homework/reactions/test_reaction_creator.py index 9a5aad17470..460499f72a7 100644 --- a/src/homework/tests/reactions/test_reaction_creator.py +++ b/tests/apps/homework/reactions/test_reaction_creator.py @@ -2,9 +2,9 @@ from emoji import EMOJI_DATA -from homework.models.reaction import Reaction -from homework.services import ReactionCreator -from homework.services.reaction_creator import ReactionCreatorException +from apps.homework.models.reaction import Reaction +from apps.homework.services import ReactionCreator +from apps.homework.services.reaction_creator import ReactionCreatorException pytestmark = [pytest.mark.django_db] diff --git a/src/homework/tests/tests_crosscheck_integration.py b/tests/apps/homework/tests_crosscheck_integration.py similarity index 95% rename from src/homework/tests/tests_crosscheck_integration.py rename to tests/apps/homework/tests_crosscheck_integration.py index 5865efb1655..05d27c6ecff 100644 --- a/src/homework/tests/tests_crosscheck_integration.py +++ b/tests/apps/homework/tests_crosscheck_integration.py @@ -1,7 +1,7 @@ import pytest -from homework import tasks -from homework.models import AnswerCrossCheck +from apps.homework import tasks +from apps.homework.models import AnswerCrossCheck pytestmark = [pytest.mark.django_db] diff --git a/src/magnets/tests/conftest.py b/tests/apps/magnets/conftest.py similarity index 84% rename from src/magnets/tests/conftest.py rename to tests/apps/magnets/conftest.py index 7cc4ebef815..2330f1bfb68 100644 --- a/src/magnets/tests/conftest.py +++ b/tests/apps/magnets/conftest.py @@ -1,7 +1,7 @@ from functools import partial import pytest -from magnets.creator import LeadCreator +from apps.magnets.creator import LeadCreator @pytest.fixture diff --git a/src/magnets/tests/email_lead_magnet/conftest.py b/tests/apps/magnets/email_lead_magnet/conftest.py similarity index 100% rename from src/magnets/tests/email_lead_magnet/conftest.py rename to tests/apps/magnets/email_lead_magnet/conftest.py diff --git a/src/magnets/tests/email_lead_magnet/tests_emaiL_lead_magnet_creating_api.py b/tests/apps/magnets/email_lead_magnet/tests_emaiL_lead_magnet_creating_api.py similarity index 97% rename from src/magnets/tests/email_lead_magnet/tests_emaiL_lead_magnet_creating_api.py rename to tests/apps/magnets/email_lead_magnet/tests_emaiL_lead_magnet_creating_api.py index 95aecb9a19a..9deb53758d2 100644 --- a/src/magnets/tests/email_lead_magnet/tests_emaiL_lead_magnet_creating_api.py +++ b/tests/apps/magnets/email_lead_magnet/tests_emaiL_lead_magnet_creating_api.py @@ -1,6 +1,6 @@ import pytest -from users.models import User +from apps.users.models import User pytestmark = [pytest.mark.django_db] diff --git a/src/magnets/tests/email_lead_magnet/tests_email_lead_magnet_execution.py b/tests/apps/magnets/email_lead_magnet/tests_email_lead_magnet_execution.py similarity index 96% rename from src/magnets/tests/email_lead_magnet/tests_email_lead_magnet_execution.py rename to tests/apps/magnets/email_lead_magnet/tests_email_lead_magnet_execution.py index 20fe2cf3c2d..d8adaeffe43 100644 --- a/src/magnets/tests/email_lead_magnet/tests_email_lead_magnet_execution.py +++ b/tests/apps/magnets/email_lead_magnet/tests_email_lead_magnet_execution.py @@ -2,7 +2,7 @@ from django.core import mail -from mailing.models import EmailLogEntry +from apps.mailing.models import EmailLogEntry pytestmark = [pytest.mark.django_db] diff --git a/src/magnets/tests/tests_lead_magnet_creator.py b/tests/apps/magnets/tests_lead_magnet_creator.py similarity index 88% rename from src/magnets/tests/tests_lead_magnet_creator.py rename to tests/apps/magnets/tests_lead_magnet_creator.py index cbd399335e4..b5e62289934 100644 --- a/src/magnets/tests/tests_lead_magnet_creator.py +++ b/tests/apps/magnets/tests_lead_magnet_creator.py @@ -1,19 +1,19 @@ import pytest -from magnets.models import LeadCampaignLogEntry -from users.models import User +from apps.magnets.models import LeadCampaignLogEntry +from apps.users.models import User pytestmark = [pytest.mark.django_db] @pytest.fixture(autouse=True) def rebuild_tags(mocker): - return mocker.patch("users.services.user_creator.rebuild_tags.delay") + return mocker.patch("apps.users.services.user_creator.rebuild_tags.delay") @pytest.fixture def execute(mocker): - return mocker.patch("magnets.models.EmailLeadMagnetCampaign.execute") + return mocker.patch("apps.magnets.models.EmailLeadMagnetCampaign.execute") def get_user(): diff --git a/src/magnets/tests/tests_lead_magnet_lead_count.py b/tests/apps/magnets/tests_lead_magnet_lead_count.py similarity index 93% rename from src/magnets/tests/tests_lead_magnet_lead_count.py rename to tests/apps/magnets/tests_lead_magnet_lead_count.py index a392f39bace..d23ddbbdb45 100644 --- a/src/magnets/tests/tests_lead_magnet_lead_count.py +++ b/tests/apps/magnets/tests_lead_magnet_lead_count.py @@ -1,6 +1,6 @@ import pytest -from magnets.models import EmailLeadMagnetCampaign +from apps.magnets.models import EmailLeadMagnetCampaign pytestmark = [ pytest.mark.django_db, diff --git a/src/mailing/tests/configuration/conftest.py b/tests/apps/mailing/configuration/conftest.py similarity index 100% rename from src/mailing/tests/configuration/conftest.py rename to tests/apps/mailing/configuration/conftest.py diff --git a/src/mailing/tests/configuration/test_get_configuration.py b/tests/apps/mailing/configuration/test_get_configuration.py similarity index 95% rename from src/mailing/tests/configuration/test_get_configuration.py rename to tests/apps/mailing/configuration/test_get_configuration.py index b9533c1e707..8ffccb01e44 100644 --- a/src/mailing/tests/configuration/test_get_configuration.py +++ b/tests/apps/mailing/configuration/test_get_configuration.py @@ -1,7 +1,7 @@ import pytest -from mailing.configuration import get_configuration -from orders.models import Order +from apps.mailing.configuration import get_configuration +from apps.orders.models import Order pytestmark = [pytest.mark.django_db] diff --git a/src/mailing/tests/owl/conftest.py b/tests/apps/mailing/owl/conftest.py similarity index 90% rename from src/mailing/tests/owl/conftest.py rename to tests/apps/mailing/owl/conftest.py index 1f27f181a25..67f33b101d4 100644 --- a/src/mailing/tests/owl/conftest.py +++ b/tests/apps/mailing/owl/conftest.py @@ -1,7 +1,7 @@ from functools import partial import pytest -from mailing.owl import Owl +from apps.mailing.owl import Owl pytestmark = [pytest.mark.django_db] diff --git a/src/mailing/tests/owl/tests_owl_antispam.py b/tests/apps/mailing/owl/tests_owl_antispam.py similarity index 93% rename from src/mailing/tests/owl/tests_owl_antispam.py rename to tests/apps/mailing/owl/tests_owl_antispam.py index 1ac961671f7..41f7cb7b2e7 100644 --- a/src/mailing/tests/owl/tests_owl_antispam.py +++ b/tests/apps/mailing/owl/tests_owl_antispam.py @@ -2,8 +2,8 @@ from django.core import mail -from mailing.models import EmailLogEntry -from mailing.tasks import send_mail +from apps.mailing.models import EmailLogEntry +from apps.mailing.tasks import send_mail pytestmark = [pytest.mark.django_db] diff --git a/src/mailing/tests/owl/tests_owl_configuration.py b/tests/apps/mailing/owl/tests_owl_configuration.py similarity index 92% rename from src/mailing/tests/owl/tests_owl_configuration.py rename to tests/apps/mailing/owl/tests_owl_configuration.py index ee8630d8538..e258ebdd611 100644 --- a/src/mailing/tests/owl/tests_owl_configuration.py +++ b/tests/apps/mailing/owl/tests_owl_configuration.py @@ -1,6 +1,6 @@ import pytest -from mailing.models import EmailConfiguration +from apps.mailing.models import EmailConfiguration pytestmark = [pytest.mark.django_db] @@ -35,7 +35,7 @@ def email_configration(mixer): @pytest.fixture def configuration(email_configration, mocker): - return mocker.patch("mailing.owl.get_configuration", return_value=email_configration) + return mocker.patch("apps.mailing.owl.get_configuration", return_value=email_configration) @pytest.fixture diff --git a/src/mailing/tests/owl/tests_owl_functional.py b/tests/apps/mailing/owl/tests_owl_functional.py similarity index 100% rename from src/mailing/tests/owl/tests_owl_functional.py rename to tests/apps/mailing/owl/tests_owl_functional.py diff --git a/src/mailing/tests/owl/tests_owl_unit.py b/tests/apps/mailing/owl/tests_owl_unit.py similarity index 96% rename from src/mailing/tests/owl/tests_owl_unit.py rename to tests/apps/mailing/owl/tests_owl_unit.py index f38b525aaab..664a8f5fc03 100644 --- a/src/mailing/tests/owl/tests_owl_unit.py +++ b/tests/apps/mailing/owl/tests_owl_unit.py @@ -1,6 +1,6 @@ import pytest -from mailing.owl import Owl +from apps.mailing.owl import Owl pytestmark = [pytest.mark.django_db] diff --git a/src/mailing/tests/owl/tests_send_mail_task.py b/tests/apps/mailing/owl/tests_send_mail_task.py similarity index 77% rename from src/mailing/tests/owl/tests_send_mail_task.py rename to tests/apps/mailing/owl/tests_send_mail_task.py index 9fbbe5901f3..1fe926fcb04 100644 --- a/src/mailing/tests/owl/tests_send_mail_task.py +++ b/tests/apps/mailing/owl/tests_send_mail_task.py @@ -1,18 +1,18 @@ import pytest -from mailing.tasks import send_mail +from apps.mailing.tasks import send_mail pytestmark = [pytest.mark.django_db] @pytest.fixture def init(mocker): - return mocker.patch("mailing.tasks.Owl") + return mocker.patch("apps.mailing.tasks.Owl") @pytest.fixture def call(mocker): - return mocker.patch("mailing.tasks.Owl.__call__") + return mocker.patch("apps.mailing.tasks.Owl.__call__") ARGS = dict( diff --git a/src/notion/tests/api/conftest.py b/tests/apps/notion/api/conftest.py similarity index 79% rename from src/notion/tests/api/conftest.py rename to tests/apps/notion/api/conftest.py index eae0454a22e..ff27943e1fb 100644 --- a/src/notion/tests/api/conftest.py +++ b/tests/apps/notion/api/conftest.py @@ -1,6 +1,6 @@ import pytest -from notion.page import NotionPage +from apps.notion.page import NotionPage pytestmark = [pytest.mark.django_db] @@ -42,9 +42,9 @@ def material(mixer, course): @pytest.fixture def mock_notion_response(mocker, page: NotionPage): - return mocker.patch("notion.client.NotionClient.fetch_page_recursively", return_value=page) + return mocker.patch("apps.notion.client.NotionClient.fetch_page_recursively", return_value=page) @pytest.fixture def _disable_notion_cache(mocker): - mocker.patch("notion.cache.should_bypass_cache", return_value=True) + mocker.patch("apps.notion.cache.should_bypass_cache", return_value=True) diff --git a/src/notion/tests/api/test_notion_cache_api.py b/tests/apps/notion/api/test_notion_cache_api.py similarity index 92% rename from src/notion/tests/api/test_notion_cache_api.py rename to tests/apps/notion/api/test_notion_cache_api.py index 27ac4d77ccd..e5bb5bea689 100644 --- a/src/notion/tests/api/test_notion_cache_api.py +++ b/tests/apps/notion/api/test_notion_cache_api.py @@ -2,8 +2,8 @@ from respx import MockRouter -from app.test.api_client import DRFClient -from notion.models import NotionCacheEntry +from core.test.api_client import DRFClient +from apps.notion.models import NotionCacheEntry pytestmark = [ pytest.mark.django_db, @@ -46,7 +46,7 @@ def _ok(respx_mock: MockRouter): @pytest.fixture(autouse=True) def mock_blocks_fetching(mocker): - return mocker.patch("notion.block.NotionBlockList.get_underlying_block_ids", return_value=[]) + return mocker.patch("apps.notion.block.NotionBlockList.get_underlying_block_ids", return_value=[]) def test_request_is_done_for_the_first_time(api, respx_mock: MockRouter): diff --git a/src/notion/tests/api/test_notion_material_api.py b/tests/apps/notion/api/test_notion_material_api.py similarity index 100% rename from src/notion/tests/api/test_notion_material_api.py rename to tests/apps/notion/api/test_notion_material_api.py diff --git a/src/notion/tests/api/test_notion_material_api_permissions.py b/tests/apps/notion/api/test_notion_material_api_permissions.py similarity index 100% rename from src/notion/tests/api/test_notion_material_api_permissions.py rename to tests/apps/notion/api/test_notion_material_api_permissions.py diff --git a/src/notion/tests/block_list/conftest.py b/tests/apps/notion/block_list/conftest.py similarity index 95% rename from src/notion/tests/block_list/conftest.py rename to tests/apps/notion/block_list/conftest.py index 2b58e3c1bfe..1ae59a51e50 100644 --- a/src/notion/tests/block_list/conftest.py +++ b/tests/apps/notion/block_list/conftest.py @@ -1,6 +1,6 @@ import pytest -from notion.block import NotionBlock +from apps.notion.block import NotionBlock @pytest.fixture diff --git a/src/notion/tests/block_list/test_get_underlying_block_ids.py b/tests/apps/notion/block_list/test_get_underlying_block_ids.py similarity index 97% rename from src/notion/tests/block_list/test_get_underlying_block_ids.py rename to tests/apps/notion/block_list/test_get_underlying_block_ids.py index 2eb77af5050..e77d966a02a 100644 --- a/src/notion/tests/block_list/test_get_underlying_block_ids.py +++ b/tests/apps/notion/block_list/test_get_underlying_block_ids.py @@ -1,4 +1,4 @@ -from notion.block import NotionBlockList +from apps.notion.block import NotionBlockList def test_no_content(block_without_content): diff --git a/src/notion/tests/conftest.py b/tests/apps/notion/conftest.py similarity index 84% rename from src/notion/tests/conftest.py rename to tests/apps/notion/conftest.py index 64d13e02b1a..1b49eac9407 100644 --- a/src/notion/tests/conftest.py +++ b/tests/apps/notion/conftest.py @@ -1,9 +1,9 @@ import pytest -from notion.block import NotionBlock -from notion.block import NotionBlockList -from notion.client import NotionClient -from notion.page import NotionPage +from apps.notion.block import NotionBlock +from apps.notion.block import NotionBlockList +from apps.notion.client import NotionClient +from apps.notion.page import NotionPage pytestmark = [ pytest.mark.django_db, @@ -30,12 +30,12 @@ def _freeze_notion_middleware_url(settings): @pytest.fixture def fetch_blocks(mocker): - return mocker.patch("notion.client.NotionClient.fetch_blocks") + return mocker.patch("apps.notion.client.NotionClient.fetch_blocks") @pytest.fixture def fetch_page(mocker): - return mocker.patch("notion.client.NotionClient.fetch_page") + return mocker.patch("apps.notion.client.NotionClient.fetch_page") @pytest.fixture diff --git a/src/notion/tests/test_celery_tasks.py b/tests/apps/notion/test_celery_tasks.py similarity index 79% rename from src/notion/tests/test_celery_tasks.py rename to tests/apps/notion/test_celery_tasks.py index 6e8a578b795..70ae49d6009 100644 --- a/src/notion/tests/test_celery_tasks.py +++ b/tests/apps/notion/test_celery_tasks.py @@ -1,7 +1,7 @@ import pytest -from notion.tasks import update_cache_for_all_active_notion_materials -from notion.tasks import update_cache_notion_material +from apps.notion.tasks import update_cache_for_all_active_notion_materials +from apps.notion.tasks import update_cache_notion_material pytestmark = [ pytest.mark.django_db, @@ -11,14 +11,14 @@ @pytest.fixture def mock_fetch_page_recursively(mocker, page): return mocker.patch( - "notion.client.NotionClient.fetch_page_recursively", + "apps.notion.client.NotionClient.fetch_page_recursively", return_value=page, ) @pytest.fixture def mock_cache_set(mocker): - return mocker.patch("notion.cache.NotionCache.set") + return mocker.patch("apps.notion.cache.NotionCache.set") def test_call_update_cache_notion_material(mock_fetch_page_recursively, mock_cache_set, material, page): diff --git a/src/notion/tests/test_fetch_blocks.py b/tests/apps/notion/test_fetch_blocks.py similarity index 100% rename from src/notion/tests/test_fetch_blocks.py rename to tests/apps/notion/test_fetch_blocks.py diff --git a/src/notion/tests/test_fetch_page.py b/tests/apps/notion/test_fetch_page.py similarity index 96% rename from src/notion/tests/test_fetch_page.py rename to tests/apps/notion/test_fetch_page.py index ace7dc92d37..60c75412f64 100644 --- a/src/notion/tests/test_fetch_page.py +++ b/tests/apps/notion/test_fetch_page.py @@ -2,8 +2,8 @@ from respx import MockRouter -from notion.exceptions import NotionResponseError -from notion.exceptions import NotSharedForWeb +from apps.notion.exceptions import NotionResponseError +from apps.notion.exceptions import NotSharedForWeb pytestmark = [ pytest.mark.django_db, diff --git a/src/notion/tests/test_fetch_page_recursively.py b/tests/apps/notion/test_fetch_page_recursively.py similarity index 93% rename from src/notion/tests/test_fetch_page_recursively.py rename to tests/apps/notion/test_fetch_page_recursively.py index 3bebf3a3d8f..35f2fabc6cb 100644 --- a/src/notion/tests/test_fetch_page_recursively.py +++ b/tests/apps/notion/test_fetch_page_recursively.py @@ -1,8 +1,8 @@ import pytest -from notion.block import NotionBlock -from notion.block import NotionBlockList -from notion.page import NotionPage +from apps.notion.block import NotionBlock +from apps.notion.block import NotionBlockList +from apps.notion.page import NotionPage @pytest.fixture diff --git a/src/notion/tests/test_id_to_uuid.py b/tests/apps/notion/test_id_to_uuid.py similarity index 88% rename from src/notion/tests/test_id_to_uuid.py rename to tests/apps/notion/test_id_to_uuid.py index bb0fbec39c7..1f2cc52f143 100644 --- a/src/notion/tests/test_id_to_uuid.py +++ b/tests/apps/notion/test_id_to_uuid.py @@ -1,6 +1,6 @@ import pytest -from notion.helpers import id_to_uuid +from apps.notion.helpers import id_to_uuid @pytest.mark.parametrize( diff --git a/src/notion/tests/test_material_get_absolute_url.py b/tests/apps/notion/test_material_get_absolute_url.py similarity index 100% rename from src/notion/tests/test_material_get_absolute_url.py rename to tests/apps/notion/test_material_get_absolute_url.py diff --git a/src/notion/tests/test_notion_block.py b/tests/apps/notion/test_notion_block.py similarity index 93% rename from src/notion/tests/test_notion_block.py rename to tests/apps/notion/test_notion_block.py index 3b3689bb119..fe12eec04bd 100644 --- a/src/notion/tests/test_notion_block.py +++ b/tests/apps/notion/test_notion_block.py @@ -1,6 +1,6 @@ import pytest -from notion.block import NotionBlock +from apps.notion.block import NotionBlock @pytest.mark.parametrize( diff --git a/src/notion/tests/test_notion_cache.py b/tests/apps/notion/test_notion_cache.py similarity index 86% rename from src/notion/tests/test_notion_cache.py rename to tests/apps/notion/test_notion_cache.py index f07355a76e9..e02db2eac9a 100644 --- a/src/notion/tests/test_notion_cache.py +++ b/tests/apps/notion/test_notion_cache.py @@ -3,13 +3,13 @@ from django.utils import timezone -from notion.block import NotionBlock -from notion.block import NotionBlockList -from notion.cache import get_cached_page -from notion.cache import NotionCache -from notion.cache import TIMEOUT -from notion.models import NotionCacheEntry -from notion.page import NotionPage +from apps.notion.block import NotionBlock +from apps.notion.block import NotionBlockList +from apps.notion.cache import get_cached_page +from apps.notion.cache import NotionCache +from apps.notion.cache import TIMEOUT +from apps.notion.models import NotionCacheEntry +from apps.notion.page import NotionPage pytestmark = [ pytest.mark.django_db, @@ -18,22 +18,22 @@ @pytest.fixture def current_user_staff(mocker, staff_user): - return mocker.patch("notion.cache.get_current_user", return_value=staff_user) + return mocker.patch("apps.notion.cache.get_current_user", return_value=staff_user) @pytest.fixture def current_user_casual(mocker, user): - return mocker.patch("notion.cache.get_current_user", return_value=user) + return mocker.patch("apps.notion.cache.get_current_user", return_value=user) @pytest.fixture def mock_cache_set(mocker): - return mocker.patch("notion.cache.NotionCache.set") + return mocker.patch("apps.notion.cache.NotionCache.set") @pytest.fixture def mock_fetch_page(mocker): - return mocker.patch("notion.client.NotionClient.fetch_page_recursively") + return mocker.patch("apps.notion.client.NotionClient.fetch_page_recursively") @pytest.fixture diff --git a/src/notion/tests/test_notion_rewrite_links.py b/tests/apps/notion/test_notion_rewrite_links.py similarity index 97% rename from src/notion/tests/test_notion_rewrite_links.py rename to tests/apps/notion/test_notion_rewrite_links.py index 9b4c4d23188..70032168605 100644 --- a/src/notion/tests/test_notion_rewrite_links.py +++ b/tests/apps/notion/test_notion_rewrite_links.py @@ -1,12 +1,12 @@ import pytest -from notion.rewrite import rewrite +from apps.notion.rewrite import rewrite @pytest.fixture(autouse=True) def rewrite_mapping(mocker): return mocker.patch( - "notion.rewrite.get_rewrite_mapping", + "apps.notion.rewrite.get_rewrite_mapping", return_value={ "their-material-id": "a4a1c6f6d2ea441ebf1fdd8b5b99445a", }, diff --git a/src/notion/tests/test_page_url_to_id.py b/tests/apps/notion/test_page_url_to_id.py similarity index 92% rename from src/notion/tests/test_page_url_to_id.py rename to tests/apps/notion/test_page_url_to_id.py index afaaca2c537..7166817f0c3 100644 --- a/src/notion/tests/test_page_url_to_id.py +++ b/tests/apps/notion/test_page_url_to_id.py @@ -1,6 +1,6 @@ import pytest -from notion.helpers import page_url_to_id +from apps.notion.helpers import page_url_to_id @pytest.mark.parametrize( diff --git a/src/orders/tests/configurable_bank/conftest.py b/tests/apps/orders/configurable_bank/conftest.py similarity index 52% rename from src/orders/tests/configurable_bank/conftest.py rename to tests/apps/orders/configurable_bank/conftest.py index 402e67ca69f..0e5c2761acf 100644 --- a/src/orders/tests/configurable_bank/conftest.py +++ b/tests/apps/orders/configurable_bank/conftest.py @@ -32,35 +32,35 @@ def call_purchase(api, default_user_data): @pytest.fixture(autouse=True) def tinkoff_bank(mocker): - return mocker.patch("tinkoff.bank.TinkoffBank.get_initial_payment_url", return_value="https://mocked.link") + return mocker.patch("apps.tinkoff.bank.TinkoffBank.get_initial_payment_url", return_value="https://mocked.link") @pytest.fixture(autouse=True) def tinkoff_credit(mocker): - return mocker.patch("tinkoff.credit.TinkoffCredit.get_initial_payment_url", return_value="https://mocked.link") + return mocker.patch("apps.tinkoff.credit.TinkoffCredit.get_initial_payment_url", return_value="https://mocked.link") @pytest.fixture(autouse=True) def stripe_bank(mocker): - return mocker.patch("stripebank.bank.StripeBank.get_initial_payment_url", return_value="https://mocked.link") + return mocker.patch("apps.stripebank.bank.StripeBank.get_initial_payment_url", return_value="https://mocked.link") @pytest.fixture(autouse=True) def dolyame_bank(mocker): - return mocker.patch("tinkoff.dolyame.Dolyame.get_initial_payment_url", return_value="https://mocked.link") + return mocker.patch("apps.tinkoff.dolyame.Dolyame.get_initial_payment_url", return_value="https://mocked.link") @pytest.fixture(autouse=True) def _freeze_ue_rate(mocker): - mocker.patch("tinkoff.bank.TinkoffBank.ue", 11) - mocker.patch("tinkoff.credit.TinkoffCredit.ue", 22) - mocker.patch("stripebank.bank.StripeBank.ue", 33) - mocker.patch("tinkoff.dolyame.Dolyame.ue", 44) + mocker.patch("apps.tinkoff.bank.TinkoffBank.ue", 11) + mocker.patch("apps.tinkoff.credit.TinkoffCredit.ue", 22) + mocker.patch("apps.stripebank.bank.StripeBank.ue", 33) + mocker.patch("apps.tinkoff.dolyame.Dolyame.ue", 44) @pytest.fixture(autouse=True) def _freeze_acquiring_percent(mocker): - mocker.patch("tinkoff.bank.TinkoffBank.acquiring_percent", "1.2") - mocker.patch("tinkoff.credit.TinkoffCredit.acquiring_percent", "1.3") - mocker.patch("stripebank.bank.StripeBank.acquiring_percent", "1.4") - mocker.patch("tinkoff.dolyame.Dolyame.acquiring_percent", "1.5") + mocker.patch("apps.tinkoff.bank.TinkoffBank.acquiring_percent", "1.2") + mocker.patch("apps.tinkoff.credit.TinkoffCredit.acquiring_percent", "1.3") + mocker.patch("apps.stripebank.bank.StripeBank.acquiring_percent", "1.4") + mocker.patch("apps.tinkoff.dolyame.Dolyame.acquiring_percent", "1.5") diff --git a/src/orders/tests/configurable_bank/tests_configurable_bank.py b/tests/apps/orders/configurable_bank/tests_configurable_bank.py similarity index 98% rename from src/orders/tests/configurable_bank/tests_configurable_bank.py rename to tests/apps/orders/configurable_bank/tests_configurable_bank.py index d7d0b4e191c..a62cd62ab06 100644 --- a/src/orders/tests/configurable_bank/tests_configurable_bank.py +++ b/tests/apps/orders/configurable_bank/tests_configurable_bank.py @@ -1,7 +1,7 @@ from decimal import Decimal import pytest -from orders.models import Order +from apps.orders.models import Order pytestmark = [pytest.mark.django_db] diff --git a/src/orders/tests/configurable_bank/tests_zero_price_bank.py b/tests/apps/orders/configurable_bank/tests_zero_price_bank.py similarity index 100% rename from src/orders/tests/configurable_bank/tests_zero_price_bank.py rename to tests/apps/orders/configurable_bank/tests_zero_price_bank.py diff --git a/src/orders/tests/conftest.py b/tests/apps/orders/conftest.py similarity index 100% rename from src/orders/tests/conftest.py rename to tests/apps/orders/conftest.py diff --git a/tests/apps/orders/human_readable/__init__.py b/tests/apps/orders/human_readable/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/orders/tests/human_readable/conftest.py b/tests/apps/orders/human_readable/conftest.py similarity index 100% rename from src/orders/tests/human_readable/conftest.py rename to tests/apps/orders/human_readable/conftest.py diff --git a/src/orders/tests/human_readable/test_get_customer.py b/tests/apps/orders/human_readable/test_get_customer.py similarity index 96% rename from src/orders/tests/human_readable/test_get_customer.py rename to tests/apps/orders/human_readable/test_get_customer.py index 407c9d450f5..1a46990c983 100644 --- a/src/orders/tests/human_readable/test_get_customer.py +++ b/tests/apps/orders/human_readable/test_get_customer.py @@ -1,6 +1,6 @@ import pytest -from orders import human_readable +from apps.orders import human_readable pytestmark = [ pytest.mark.django_db, diff --git a/src/orders/tests/human_readable/test_get_payment_method_name.py b/tests/apps/orders/human_readable/test_get_payment_method_name.py similarity index 93% rename from src/orders/tests/human_readable/test_get_payment_method_name.py rename to tests/apps/orders/human_readable/test_get_payment_method_name.py index e1d208a948d..c1407ba1c54 100644 --- a/src/orders/tests/human_readable/test_get_payment_method_name.py +++ b/tests/apps/orders/human_readable/test_get_payment_method_name.py @@ -1,9 +1,9 @@ from datetime import datetime import pytest -from banking.selector import BANK_KEYS -from banking.selector import BANKS -from orders import human_readable +from apps.banking.selector import BANK_KEYS +from apps.banking.selector import BANKS +from apps.orders import human_readable pytestmark = [ pytest.mark.django_db, diff --git a/src/orders/tests/models/order_content_type_replacement/conftest.py b/tests/apps/orders/models/order_content_type_replacement/conftest.py similarity index 100% rename from src/orders/tests/models/order_content_type_replacement/conftest.py rename to tests/apps/orders/models/order_content_type_replacement/conftest.py diff --git a/src/orders/tests/models/order_content_type_replacement/tests_order_item.py b/tests/apps/orders/models/order_content_type_replacement/tests_order_item.py similarity index 100% rename from src/orders/tests/models/order_content_type_replacement/tests_order_item.py rename to tests/apps/orders/models/order_content_type_replacement/tests_order_item.py diff --git a/src/orders/tests/models/order_content_type_replacement/tests_order_item_foreignkey.py b/tests/apps/orders/models/order_content_type_replacement/tests_order_item_foreignkey.py similarity index 100% rename from src/orders/tests/models/order_content_type_replacement/tests_order_item_foreignkey.py rename to tests/apps/orders/models/order_content_type_replacement/tests_order_item_foreignkey.py diff --git a/src/orders/tests/models/order_content_type_replacement/tests_order_set_item.py b/tests/apps/orders/models/order_content_type_replacement/tests_order_set_item.py similarity index 92% rename from src/orders/tests/models/order_content_type_replacement/tests_order_set_item.py rename to tests/apps/orders/models/order_content_type_replacement/tests_order_set_item.py index 198495005f3..bc9326dc11c 100644 --- a/src/orders/tests/models/order_content_type_replacement/tests_order_set_item.py +++ b/tests/apps/orders/models/order_content_type_replacement/tests_order_set_item.py @@ -1,6 +1,6 @@ import pytest -from orders.exceptions import UnknownItemException +from apps.orders.exceptions import UnknownItemException pytestmark = [pytest.mark.django_db] diff --git a/src/orders/tests/models/test_order_item_constraints.py b/tests/apps/orders/models/test_order_item_constraints.py similarity index 93% rename from src/orders/tests/models/test_order_item_constraints.py rename to tests/apps/orders/models/test_order_item_constraints.py index 049d477b73f..34cf82a4d98 100644 --- a/src/orders/tests/models/test_order_item_constraints.py +++ b/tests/apps/orders/models/test_order_item_constraints.py @@ -2,8 +2,8 @@ from django.db.utils import IntegrityError -from orders.models.order import Order -from users.models import User +from apps.orders.models.order import Order +from apps.users.models import User pytestmark = [pytest.mark.django_db] diff --git a/src/orders/tests/models/tests_order_refund.py b/tests/apps/orders/models/tests_order_refund.py similarity index 94% rename from src/orders/tests/models/tests_order_refund.py rename to tests/apps/orders/models/tests_order_refund.py index 4016fc8d2c6..bc00a9bacc5 100644 --- a/src/orders/tests/models/tests_order_refund.py +++ b/tests/apps/orders/models/tests_order_refund.py @@ -2,7 +2,7 @@ from datetime import timezone import pytest -from orders.services import OrderRefunder +from apps.orders.services import OrderRefunder pytestmark = [pytest.mark.django_db] diff --git a/src/orders/tests/order_confirmation/conftest.py b/tests/apps/orders/order_confirmation/conftest.py similarity index 84% rename from src/orders/tests/order_confirmation/conftest.py rename to tests/apps/orders/order_confirmation/conftest.py index f191d76a89a..bedfdfe2bd7 100644 --- a/src/orders/tests/order_confirmation/conftest.py +++ b/tests/apps/orders/order_confirmation/conftest.py @@ -18,4 +18,4 @@ def order(factory, course): @pytest.fixture(autouse=True) def ship(mocker): - return mocker.patch("products.models.Course.ship") + return mocker.patch("apps.products.models.Course.ship") diff --git a/src/orders/tests/order_confirmation/tests_order_confirmation_api.py b/tests/apps/orders/order_confirmation/tests_order_confirmation_api.py similarity index 100% rename from src/orders/tests/order_confirmation/tests_order_confirmation_api.py rename to tests/apps/orders/order_confirmation/tests_order_confirmation_api.py diff --git a/src/orders/tests/order_creator/conftest.py b/tests/apps/orders/order_creator/conftest.py similarity index 76% rename from src/orders/tests/order_creator/conftest.py rename to tests/apps/orders/order_creator/conftest.py index c73063ddd25..9781e9011f7 100644 --- a/src/orders/tests/order_creator/conftest.py +++ b/tests/apps/orders/order_creator/conftest.py @@ -1,6 +1,6 @@ import pytest -from orders.services import OrderCreator +from apps.orders.services import OrderCreator pytestmark = [pytest.mark.django_db] diff --git a/src/orders/tests/order_creator/tests_order_creator.py b/tests/apps/orders/order_creator/tests_order_creator.py similarity index 96% rename from src/orders/tests/order_creator/tests_order_creator.py rename to tests/apps/orders/order_creator/tests_order_creator.py index 5d8dc681776..4f0df5a987f 100644 --- a/src/orders/tests/order_creator/tests_order_creator.py +++ b/tests/apps/orders/order_creator/tests_order_creator.py @@ -1,6 +1,6 @@ import pytest -from orders.models import Order +from apps.orders.models import Order pytestmark = [pytest.mark.django_db] diff --git a/src/orders/tests/order_creator/tests_order_creator_confirmation_message.py b/tests/apps/orders/order_creator/tests_order_creator_confirmation_message.py similarity index 95% rename from src/orders/tests/order_creator/tests_order_creator_confirmation_message.py rename to tests/apps/orders/order_creator/tests_order_creator_confirmation_message.py index f1ba3ec7f12..c9fccf010dd 100644 --- a/src/orders/tests/order_creator/tests_order_creator_confirmation_message.py +++ b/tests/apps/orders/order_creator/tests_order_creator_confirmation_message.py @@ -7,7 +7,7 @@ @pytest.fixture(autouse=True) def send_mail(mocker): - return mocker.patch("mailing.tasks.send_mail.delay") + return mocker.patch("apps.mailing.tasks.send_mail.delay") @pytest.fixture(autouse=True) diff --git a/src/orders/tests/order_creator/tests_order_creator_promocodes.py b/tests/apps/orders/order_creator/tests_order_creator_promocodes.py similarity index 93% rename from src/orders/tests/order_creator/tests_order_creator_promocodes.py rename to tests/apps/orders/order_creator/tests_order_creator_promocodes.py index 1d7f61629d2..88cd074ad4b 100644 --- a/src/orders/tests/order_creator/tests_order_creator_promocodes.py +++ b/tests/apps/orders/order_creator/tests_order_creator_promocodes.py @@ -1,6 +1,6 @@ import pytest -from orders.models import Order +from apps.orders.models import Order pytestmark = [pytest.mark.django_db] diff --git a/src/orders/tests/order_creator/tests_order_creator_update_chain.py b/tests/apps/orders/order_creator/tests_order_creator_update_chain.py similarity index 90% rename from src/orders/tests/order_creator/tests_order_creator_update_chain.py rename to tests/apps/orders/order_creator/tests_order_creator_update_chain.py index 01a5d1f88f9..8c9503bba8a 100644 --- a/src/orders/tests/order_creator/tests_order_creator_update_chain.py +++ b/tests/apps/orders/order_creator/tests_order_creator_update_chain.py @@ -7,27 +7,27 @@ @pytest.fixture def mock_update_user_chain(mocker): - return mocker.patch("orders.services.order_creator.chain") + return mocker.patch("apps.orders.services.order_creator.chain") @pytest.fixture def mock_rebuild_tags(mocker): - return mocker.patch("users.tasks.rebuild_tags.si") + return mocker.patch("apps.users.tasks.rebuild_tags.si") @pytest.fixture def rebuild_tags(mocker): - return mocker.patch("users.tasks.rebuild_tags.delay") + return mocker.patch("apps.users.tasks.rebuild_tags.delay") @pytest.fixture def mock_push_customer(mocker): - return mocker.patch("amocrm.tasks.push_user.si") + return mocker.patch("apps.amocrm.tasks.push_user.si") @pytest.fixture def mock_push_order(mocker): - return mocker.patch("amocrm.tasks.push_order.si") + return mocker.patch("apps.amocrm.tasks.push_order.si") def test_if_subscribe_and_amocrm_enabled(create, user, course, mock_update_user_chain, mock_rebuild_tags, mock_push_customer, settings, mock_push_order): diff --git a/src/orders/tests/order_email_changer/conftest.py b/tests/apps/orders/order_email_changer/conftest.py similarity index 71% rename from src/orders/tests/order_email_changer/conftest.py rename to tests/apps/orders/order_email_changer/conftest.py index df33b810b13..4fc6fe4aeee 100644 --- a/src/orders/tests/order_email_changer/conftest.py +++ b/tests/apps/orders/order_email_changer/conftest.py @@ -1,6 +1,6 @@ import pytest -from orders.services import OrderEmailChanger +from apps.orders.services import OrderEmailChanger pytestmark = [pytest.mark.django_db] @@ -22,12 +22,12 @@ def nameless_user(mixer): @pytest.fixture def ship(mocker): - return mocker.patch("studying.shipment_factory.ship") + return mocker.patch("apps.studying.shipment_factory.ship") @pytest.fixture def unship(mocker): - return mocker.patch("studying.shipment_factory.unship") + return mocker.patch("apps.studying.shipment_factory.unship") @pytest.fixture @@ -37,4 +37,4 @@ def order(factory, nameless_user, course): @pytest.fixture(autouse=True) def subscribe(mocker): - return mocker.patch("app.tasks.update_dashamail_subscription.delay") + return mocker.patch("core.tasks.update_dashamail_subscription.delay") diff --git a/src/orders/tests/order_email_changer/tests_order_email_changer.py b/tests/apps/orders/order_email_changer/tests_order_email_changer.py similarity index 100% rename from src/orders/tests/order_email_changer/tests_order_email_changer.py rename to tests/apps/orders/order_email_changer/tests_order_email_changer.py diff --git a/src/orders/tests/order_queryset/conftest.py b/tests/apps/orders/order_queryset/conftest.py similarity index 100% rename from src/orders/tests/order_queryset/conftest.py rename to tests/apps/orders/order_queryset/conftest.py diff --git a/src/orders/tests/order_queryset/test_order_paid_queryset.py b/tests/apps/orders/order_queryset/test_order_paid_queryset.py similarity index 94% rename from src/orders/tests/order_queryset/test_order_paid_queryset.py rename to tests/apps/orders/order_queryset/test_order_paid_queryset.py index 9a5bf58546c..577de612efa 100644 --- a/src/orders/tests/order_queryset/test_order_paid_queryset.py +++ b/tests/apps/orders/order_queryset/test_order_paid_queryset.py @@ -2,7 +2,7 @@ from django.utils import timezone -from orders.models import Order +from apps.orders.models import Order pytestmark = [pytest.mark.django_db] diff --git a/src/orders/tests/order_queryset/test_order_shipped_without_payment_queryset.py b/tests/apps/orders/order_queryset/test_order_shipped_without_payment_queryset.py similarity index 95% rename from src/orders/tests/order_queryset/test_order_shipped_without_payment_queryset.py rename to tests/apps/orders/order_queryset/test_order_shipped_without_payment_queryset.py index e37225fa6d7..dc50606bfdb 100644 --- a/src/orders/tests/order_queryset/test_order_shipped_without_payment_queryset.py +++ b/tests/apps/orders/order_queryset/test_order_shipped_without_payment_queryset.py @@ -2,7 +2,7 @@ from django.utils import timezone -from orders.models import Order +from apps.orders.models import Order pytestmark = [pytest.mark.django_db] diff --git a/src/orders/tests/order_shipping/conftest.py b/tests/apps/orders/order_shipping/conftest.py similarity index 72% rename from src/orders/tests/order_shipping/conftest.py rename to tests/apps/orders/order_shipping/conftest.py index 6ae2aee978e..54d4fccdac7 100644 --- a/src/orders/tests/order_shipping/conftest.py +++ b/tests/apps/orders/order_shipping/conftest.py @@ -5,22 +5,22 @@ @pytest.fixture def mock_rebuild_tags(mocker): - return mocker.patch("users.tasks.rebuild_tags.si") + return mocker.patch("apps.users.tasks.rebuild_tags.si") @pytest.fixture def mock_push_customer(mocker): - return mocker.patch("amocrm.tasks.push_user.si") + return mocker.patch("apps.amocrm.tasks.push_user.si") @pytest.fixture def mock_push_order(mocker): - return mocker.patch("amocrm.tasks.push_order.si") + return mocker.patch("apps.amocrm.tasks.push_order.si") @pytest.fixture(autouse=True) def rebuild_tags(mocker): - return mocker.patch("users.tasks.rebuild_tags.delay") + return mocker.patch("apps.users.tasks.rebuild_tags.delay") @pytest.fixture @@ -30,7 +30,7 @@ def user(mixer): @pytest.fixture def ship(mocker): - return mocker.patch("studying.shipment_factory.ship") + return mocker.patch("apps.studying.shipment_factory.ship") @pytest.fixture diff --git a/src/orders/tests/order_shipping/tests_order_set_paid.py b/tests/apps/orders/order_shipping/tests_order_set_paid.py similarity index 97% rename from src/orders/tests/order_shipping/tests_order_set_paid.py rename to tests/apps/orders/order_shipping/tests_order_set_paid.py index 380fb3f5dfe..b5a9bfe3078 100644 --- a/src/orders/tests/order_shipping/tests_order_set_paid.py +++ b/tests/apps/orders/order_shipping/tests_order_set_paid.py @@ -10,7 +10,7 @@ @pytest.fixture def mock_update_user_chain(mocker): - return mocker.patch("orders.services.order_paid_setter.chain") + return mocker.patch("apps.orders.services.order_paid_setter.chain") def test_works(order): diff --git a/src/orders/tests/order_shipping/tests_sending_happiness_messages.py b/tests/apps/orders/order_shipping/tests_sending_happiness_messages.py similarity index 88% rename from src/orders/tests/order_shipping/tests_sending_happiness_messages.py rename to tests/apps/orders/order_shipping/tests_sending_happiness_messages.py index 0fde2a2d4eb..5d7ef779f4f 100644 --- a/src/orders/tests/order_shipping/tests_sending_happiness_messages.py +++ b/tests/apps/orders/order_shipping/tests_sending_happiness_messages.py @@ -1,8 +1,8 @@ import pytest -from banking.selector import BANK_KEYS -from banking.selector import BANKS -from orders.services import OrderShipper +from apps.banking.selector import BANK_KEYS +from apps.banking.selector import BANKS +from apps.orders.services import OrderShipper pytestmark = [pytest.mark.django_db] @@ -15,12 +15,12 @@ def _adjust_settings(settings): @pytest.fixture(autouse=True) def tg_message(mocker): - return mocker.patch("app.integrations.tg.send_message") + return mocker.patch("core.integrations.tg.send_message") @pytest.fixture def mock_get_happiness_message(mocker): - return mocker.patch("orders.services.order_shipper.OrderShipper.get_order_happiness_message", return_value="happiness_message") + return mocker.patch("apps.orders.services.order_shipper.OrderShipper.get_order_happiness_message", return_value="happiness_message") def test(tg_message, order, mock_get_happiness_message): diff --git a/src/orders/tests/order_shipping/tests_shipping_without_payment.py b/tests/apps/orders/order_shipping/tests_shipping_without_payment.py similarity index 100% rename from src/orders/tests/order_shipping/tests_shipping_without_payment.py rename to tests/apps/orders/order_shipping/tests_shipping_without_payment.py diff --git a/src/orders/tests/pay_signals/test_setting_order_as_paid_on_dolyame_transaction.py b/tests/apps/orders/pay_signals/test_setting_order_as_paid_on_dolyame_transaction.py similarity index 93% rename from src/orders/tests/pay_signals/test_setting_order_as_paid_on_dolyame_transaction.py rename to tests/apps/orders/pay_signals/test_setting_order_as_paid_on_dolyame_transaction.py index d64816a0017..c5f4016dff6 100644 --- a/src/orders/tests/pay_signals/test_setting_order_as_paid_on_dolyame_transaction.py +++ b/tests/apps/orders/pay_signals/test_setting_order_as_paid_on_dolyame_transaction.py @@ -16,7 +16,7 @@ def order(factory): @pytest.fixture(autouse=True) def _disable_dolyame_authn(mocker): - mocker.patch("tinkoff.api.permissions.DolyameNetmaskPermission.has_permission", return_value=True) + mocker.patch("apps.tinkoff.api.permissions.DolyameNetmaskPermission.has_permission", return_value=True) @pytest.fixture diff --git a/src/orders/tests/pay_signals/test_setting_order_as_paid_on_stripe_bank_transaction.py b/tests/apps/orders/pay_signals/test_setting_order_as_paid_on_stripe_bank_transaction.py similarity index 93% rename from src/orders/tests/pay_signals/test_setting_order_as_paid_on_stripe_bank_transaction.py rename to tests/apps/orders/pay_signals/test_setting_order_as_paid_on_stripe_bank_transaction.py index 14cb83d6d79..d52ebb39dcb 100644 --- a/src/orders/tests/pay_signals/test_setting_order_as_paid_on_stripe_bank_transaction.py +++ b/tests/apps/orders/pay_signals/test_setting_order_as_paid_on_stripe_bank_transaction.py @@ -16,13 +16,12 @@ def order(factory): @pytest.fixture def webhook(order): - with open("./stripebank/tests/.fixtures/webhook.json", "r") as fp: + with open("./tests/apps/stripebank/.fixtures/webhook.json", "r") as fp: bank_data = json.load(fp) bank_data["data"]["object"]["client_reference_id"] = order.slug return bank_data - @pytest.fixture(autouse=True) def _disable_signature_verification(mocker): mocker.patch("stripe.webhook.WebhookSignature.verify_header", return_value=True) diff --git a/src/orders/tests/pay_signals/test_setting_order_as_paid_on_tinkoff_bank_transaction.py b/tests/apps/orders/pay_signals/test_setting_order_as_paid_on_tinkoff_bank_transaction.py similarity index 93% rename from src/orders/tests/pay_signals/test_setting_order_as_paid_on_tinkoff_bank_transaction.py rename to tests/apps/orders/pay_signals/test_setting_order_as_paid_on_tinkoff_bank_transaction.py index 77521992e12..213a80e5836 100644 --- a/src/orders/tests/pay_signals/test_setting_order_as_paid_on_tinkoff_bank_transaction.py +++ b/tests/apps/orders/pay_signals/test_setting_order_as_paid_on_tinkoff_bank_transaction.py @@ -22,7 +22,7 @@ def _tinkoff_credentials(settings): @pytest.fixture(autouse=True) def disable_token_validation(mocker): - return mocker.patch("tinkoff.api.views.TinkoffNotificationsTokenValidator.__call__", return_value=True) + return mocker.patch("apps.tinkoff.api.views.TinkoffNotificationsTokenValidator.__call__", return_value=True) @pytest.fixture diff --git a/src/orders/tests/pay_signals/test_setting_order_as_paid_on_tinkoff_credit_transaction.py b/tests/apps/orders/pay_signals/test_setting_order_as_paid_on_tinkoff_credit_transaction.py similarity index 93% rename from src/orders/tests/pay_signals/test_setting_order_as_paid_on_tinkoff_credit_transaction.py rename to tests/apps/orders/pay_signals/test_setting_order_as_paid_on_tinkoff_credit_transaction.py index e371957e3f2..cdafb749d25 100644 --- a/src/orders/tests/pay_signals/test_setting_order_as_paid_on_tinkoff_credit_transaction.py +++ b/tests/apps/orders/pay_signals/test_setting_order_as_paid_on_tinkoff_credit_transaction.py @@ -16,7 +16,7 @@ def order(factory): @pytest.fixture(autouse=True) def _disable_tinkoff_authn(mocker): - mocker.patch("tinkoff.api.permissions.TinkoffCreditNetmaskPermission.has_permission", return_value=True) + mocker.patch("apps.tinkoff.api.permissions.TinkoffCreditNetmaskPermission.has_permission", return_value=True) @pytest.fixture diff --git a/src/orders/tests/promocode/conftest.py b/tests/apps/orders/promocode/conftest.py similarity index 100% rename from src/orders/tests/promocode/conftest.py rename to tests/apps/orders/promocode/conftest.py diff --git a/src/orders/tests/promocode/tests_price_with_promocode.py b/tests/apps/orders/promocode/tests_price_with_promocode.py similarity index 96% rename from src/orders/tests/promocode/tests_price_with_promocode.py rename to tests/apps/orders/promocode/tests_price_with_promocode.py index 3cda1e510b1..9b57a42bb6d 100644 --- a/src/orders/tests/promocode/tests_price_with_promocode.py +++ b/tests/apps/orders/promocode/tests_price_with_promocode.py @@ -8,7 +8,7 @@ @pytest.fixture(autouse=True) def _freeze_stripe_course(mocker): - mocker.patch("stripebank.bank.StripeBank.ue", 70) # let it be forever :'( + mocker.patch("apps.stripebank.bank.StripeBank.ue", 70) # let it be forever :'( @pytest.mark.parametrize( diff --git a/src/orders/tests/promocode/tests_promocode_apply.py b/tests/apps/orders/promocode/tests_promocode_apply.py similarity index 100% rename from src/orders/tests/promocode/tests_promocode_apply.py rename to tests/apps/orders/promocode/tests_promocode_apply.py diff --git a/src/orders/tests/promocode/tests_promocode_compatible_with.py b/tests/apps/orders/promocode/tests_promocode_compatible_with.py similarity index 100% rename from src/orders/tests/promocode/tests_promocode_compatible_with.py rename to tests/apps/orders/promocode/tests_promocode_compatible_with.py diff --git a/src/orders/tests/promocode/tests_promocode_get_or_nothing.py b/tests/apps/orders/promocode/tests_promocode_get_or_nothing.py similarity index 97% rename from src/orders/tests/promocode/tests_promocode_get_or_nothing.py rename to tests/apps/orders/promocode/tests_promocode_get_or_nothing.py index 8b457a62c5f..4b8c0cd773c 100644 --- a/src/orders/tests/promocode/tests_promocode_get_or_nothing.py +++ b/tests/apps/orders/promocode/tests_promocode_get_or_nothing.py @@ -1,6 +1,6 @@ import pytest -from orders.models import PromoCode +from apps.orders.models import PromoCode pytestmark = [pytest.mark.django_db] diff --git a/src/orders/tests/promocode/tests_promocode_order_count.py b/tests/apps/orders/promocode/tests_promocode_order_count.py similarity index 96% rename from src/orders/tests/promocode/tests_promocode_order_count.py rename to tests/apps/orders/promocode/tests_promocode_order_count.py index ab16879737c..a1de7692739 100644 --- a/src/orders/tests/promocode/tests_promocode_order_count.py +++ b/tests/apps/orders/promocode/tests_promocode_order_count.py @@ -1,6 +1,6 @@ import pytest -from orders.models import PromoCode +from apps.orders.models import PromoCode pytestmark = [ pytest.mark.django_db, diff --git a/src/orders/tests/services/tests_order_refunder.py b/tests/apps/orders/services/tests_order_refunder.py similarity index 90% rename from src/orders/tests/services/tests_order_refunder.py rename to tests/apps/orders/services/tests_order_refunder.py index 17675a2f31f..60e53aec192 100644 --- a/src/orders/tests/services/tests_order_refunder.py +++ b/tests/apps/orders/services/tests_order_refunder.py @@ -3,10 +3,10 @@ from datetime import timezone import pytest -from app import current_user -from banking.selector import BANKS -from orders.services import OrderRefunder -from orders.services import OrderUnshipper +from core import current_user +from apps.banking.selector import BANKS +from apps.orders.services import OrderRefunder +from apps.orders.services import OrderUnshipper pytestmark = [ pytest.mark.django_db, @@ -36,12 +36,12 @@ def _set_current_user(user): @pytest.fixture(autouse=True) def mock_dolyame_refund(mocker): - return mocker.patch("tinkoff.dolyame.Dolyame.refund") + return mocker.patch("apps.tinkoff.dolyame.Dolyame.refund") @pytest.fixture(autouse=True) def mock_send_mail(mocker): - return mocker.patch("mailing.tasks.send_mail.delay") + return mocker.patch("apps.mailing.tasks.send_mail.delay") @pytest.fixture @@ -56,7 +56,7 @@ def get_send_mail_call_email_context(): @pytest.fixture def mock_rebuild_tags(mocker): - return mocker.patch("users.tasks.rebuild_tags.delay") + return mocker.patch("apps.users.tasks.rebuild_tags.delay") @pytest.fixture @@ -205,9 +205,9 @@ def test_update_user_tags(paid_order, mock_rebuild_tags, refund): @pytest.mark.usefixtures("_enable_amocrm") def test_call_update_user_celery_chain_with_subscription(paid_order, refund, mocker): mock_celery_chain = mocker.patch("celery.chain") - mock_first_rebuild_tags = mocker.patch("users.tasks.rebuild_tags.si") - mock_second_push_customer = mocker.patch("amocrm.tasks.push_user.si") - mock_third_return_order_in_amocrm = mocker.patch("amocrm.tasks.return_order.si") + mock_first_rebuild_tags = mocker.patch("apps.users.tasks.rebuild_tags.si") + mock_second_push_customer = mocker.patch("apps.amocrm.tasks.push_user.si") + mock_third_return_order_in_amocrm = mocker.patch("apps.amocrm.tasks.return_order.si") refund(paid_order) diff --git a/src/orders/tests/services/tests_order_unshipper.py b/tests/apps/orders/services/tests_order_unshipper.py similarity index 86% rename from src/orders/tests/services/tests_order_unshipper.py rename to tests/apps/orders/services/tests_order_unshipper.py index 474d7d729d1..e39b3811325 100644 --- a/src/orders/tests/services/tests_order_unshipper.py +++ b/tests/apps/orders/services/tests_order_unshipper.py @@ -2,8 +2,8 @@ from datetime import timezone import pytest -from orders.models import Order -from orders.services import OrderUnshipper +from apps.orders.models import Order +from apps.orders.services import OrderUnshipper pytestmark = [ pytest.mark.django_db, @@ -23,7 +23,7 @@ def order(factory, course): @pytest.fixture def mock_item_unshipping(mocker): - return mocker.patch("studying.shipment_factory.unship") + return mocker.patch("apps.studying.shipment_factory.unship") @pytest.fixture @@ -43,7 +43,7 @@ def test_unshipper_actually_unship_order_and_item_and_nothing_else(order, unship def test_does_not_unship_twice(unship, mock_item_unshipping, mocker): - mock_order_save = mocker.patch("orders.models.Order.save") + mock_order_save = mocker.patch("apps.orders.models.Order.save") unship() unship() diff --git a/src/orders/tests/test_purchasing_order_with_non_trimmed_email.py b/tests/apps/orders/test_purchasing_order_with_non_trimmed_email.py similarity index 89% rename from src/orders/tests/test_purchasing_order_with_non_trimmed_email.py rename to tests/apps/orders/test_purchasing_order_with_non_trimmed_email.py index 45972f2c483..ff9f484ea59 100644 --- a/src/orders/tests/test_purchasing_order_with_non_trimmed_email.py +++ b/tests/apps/orders/test_purchasing_order_with_non_trimmed_email.py @@ -19,7 +19,7 @@ def user_with_the_same_username_but_without_a_space_in_the_end(mixer): @pytest.fixture(autouse=True) def bank(mocker): - return mocker.patch("tinkoff.bank.TinkoffBank.get_initial_payment_url", return_value="https://mocked") + return mocker.patch("apps.tinkoff.bank.TinkoffBank.get_initial_payment_url", return_value="https://mocked") @pytest.fixture diff --git a/src/orders/tests/tests_order_diploma_generator.py b/tests/apps/orders/tests_order_diploma_generator.py similarity index 83% rename from src/orders/tests/tests_order_diploma_generator.py rename to tests/apps/orders/tests_order_diploma_generator.py index 4144133689c..2429e7aa669 100644 --- a/src/orders/tests/tests_order_diploma_generator.py +++ b/tests/apps/orders/tests_order_diploma_generator.py @@ -1,9 +1,9 @@ import pytest -from diplomas.models import Languages -from orders import tasks -from orders.services import OrderDiplomaGenerator -from users.models import User +from apps.diplomas.models import Languages +from apps.orders import tasks +from apps.orders.services import OrderDiplomaGenerator +from apps.users.models import User pytestmark = [pytest.mark.django_db] @@ -31,7 +31,7 @@ def template(mixer, course): @pytest.fixture def diploma_generator(mocker): - return mocker.patch("orders.services.order_diploma_generator.generate_diploma.delay") + return mocker.patch("apps.orders.services.order_diploma_generator.generate_diploma.delay") @pytest.mark.parametrize("language", [Languages.RU, Languages.EN]) @@ -59,7 +59,7 @@ def test_task(diploma_generator, order, student, course): def test_student_without_a_name_does_not_get_the_diploma(diploma_generator, order, mocker): - mocker.patch("users.models.User.get_printable_name", return_value=None) + mocker.patch("apps.users.models.User.get_printable_name", return_value=None) tasks.generate_diploma.delay(order_id=order.id) diff --git a/src/products/tests/bundles/tests_bundle_deprecated.py b/tests/apps/products/bundles/tests_bundle_deprecated.py similarity index 100% rename from src/products/tests/bundles/tests_bundle_deprecated.py rename to tests/apps/products/bundles/tests_bundle_deprecated.py diff --git a/src/products/tests/conftest.py b/tests/apps/products/conftest.py similarity index 85% rename from src/products/tests/conftest.py rename to tests/apps/products/conftest.py index 747254ce7d9..47d71e371e8 100644 --- a/src/products/tests/conftest.py +++ b/tests/apps/products/conftest.py @@ -10,7 +10,7 @@ def testcode(mixer): @pytest.fixture(autouse=True) def rebuild_tags(mocker): - return mocker.patch("users.services.user_creator.rebuild_tags.delay") + return mocker.patch("apps.users.services.user_creator.rebuild_tags.delay") @pytest.fixture diff --git a/src/products/tests/course_api/conftest.py b/tests/apps/products/course_api/conftest.py similarity index 95% rename from src/products/tests/course_api/conftest.py rename to tests/apps/products/course_api/conftest.py index f6984811e2f..ceea4e50ace 100644 --- a/src/products/tests/course_api/conftest.py +++ b/tests/apps/products/course_api/conftest.py @@ -1,6 +1,6 @@ import pytest -from tinkoff.bank import TinkoffBank +from apps.tinkoff.bank import TinkoffBank pytestmark = [pytest.mark.django_db] diff --git a/src/products/tests/course_api/tests_purchasing_course.py b/tests/apps/products/course_api/tests_purchasing_course.py similarity index 87% rename from src/products/tests/course_api/tests_purchasing_course.py rename to tests/apps/products/course_api/tests_purchasing_course.py index a9a5c23b6bf..5314cbbef5a 100644 --- a/src/products/tests/course_api/tests_purchasing_course.py +++ b/tests/apps/products/course_api/tests_purchasing_course.py @@ -1,34 +1,34 @@ from decimal import Decimal import pytest -from orders.models import Order +from apps.orders.models import Order pytestmark = [pytest.mark.django_db] @pytest.fixture def mock_update_chain(mocker): - return mocker.patch("orders.services.purchase_creator.chain") + return mocker.patch("apps.orders.services.purchase_creator.chain") @pytest.fixture def mock_rebuild_tags(mocker): - return mocker.patch("users.tasks.rebuild_tags.si") + return mocker.patch("apps.users.tasks.rebuild_tags.si") @pytest.fixture def rebuild_tags(mocker): - return mocker.patch("users.tasks.rebuild_tags.delay") + return mocker.patch("apps.users.tasks.rebuild_tags.delay") @pytest.fixture def mock_push_customer(mocker): - return mocker.patch("amocrm.tasks.push_user.si") + return mocker.patch("apps.amocrm.tasks.push_user.si") @pytest.fixture def mock_push_order(mocker): - return mocker.patch("amocrm.tasks.push_order.si") + return mocker.patch("apps.amocrm.tasks.push_order.si") def get_order(): diff --git a/src/products/tests/course_api/tests_purchasing_course_with_promocode.py b/tests/apps/products/course_api/tests_purchasing_course_with_promocode.py similarity index 97% rename from src/products/tests/course_api/tests_purchasing_course_with_promocode.py rename to tests/apps/products/course_api/tests_purchasing_course_with_promocode.py index c8b20967290..82b34e99be1 100644 --- a/src/products/tests/course_api/tests_purchasing_course_with_promocode.py +++ b/tests/apps/products/course_api/tests_purchasing_course_with_promocode.py @@ -1,7 +1,7 @@ from decimal import Decimal import pytest -from orders.models import Order +from apps.orders.models import Order pytestmark = [ pytest.mark.django_db, diff --git a/src/products/tests/course_api/tests_purchasing_zero_priced_course.py b/tests/apps/products/course_api/tests_purchasing_zero_priced_course.py similarity index 95% rename from src/products/tests/course_api/tests_purchasing_zero_priced_course.py rename to tests/apps/products/course_api/tests_purchasing_zero_priced_course.py index 6deba6cc700..6100467541a 100644 --- a/src/products/tests/course_api/tests_purchasing_zero_priced_course.py +++ b/tests/apps/products/course_api/tests_purchasing_zero_priced_course.py @@ -1,7 +1,7 @@ from decimal import Decimal import pytest -from orders.models import Order +from apps.orders.models import Order pytestmark = [pytest.mark.django_db] diff --git a/src/products/tests/courses/tests_course_get_purchased_users.py b/tests/apps/products/courses/tests_course_get_purchased_users.py similarity index 100% rename from src/products/tests/courses/tests_course_get_purchased_users.py rename to tests/apps/products/courses/tests_course_get_purchased_users.py diff --git a/src/products/tests/courses/tests_course_get_template_id.py b/tests/apps/products/courses/tests_course_get_template_id.py similarity index 100% rename from src/products/tests/courses/tests_course_get_template_id.py rename to tests/apps/products/courses/tests_course_get_template_id.py diff --git a/src/products/tests/courses/tests_course_send_email_to_all_purchased_users.py b/tests/apps/products/courses/tests_course_send_email_to_all_purchased_users.py similarity index 100% rename from src/products/tests/courses/tests_course_send_email_to_all_purchased_users.py rename to tests/apps/products/courses/tests_course_send_email_to_all_purchased_users.py diff --git a/src/products/tests/courses/tests_course_str.py b/tests/apps/products/courses/tests_course_str.py similarity index 100% rename from src/products/tests/courses/tests_course_str.py rename to tests/apps/products/courses/tests_course_str.py diff --git a/src/products/tests/records/tests_record_deprecated.py b/tests/apps/products/records/tests_record_deprecated.py similarity index 100% rename from src/products/tests/records/tests_record_deprecated.py rename to tests/apps/products/records/tests_record_deprecated.py diff --git a/src/products/tests/shippable/tests_get_price.py b/tests/apps/products/shippable/tests_get_price.py similarity index 100% rename from src/products/tests/shippable/tests_get_price.py rename to tests/apps/products/shippable/tests_get_price.py diff --git a/src/stripebank/tests/.fixtures/webhook.json b/tests/apps/stripebank/.fixtures/webhook.json similarity index 100% rename from src/stripebank/tests/.fixtures/webhook.json rename to tests/apps/stripebank/.fixtures/webhook.json diff --git a/src/stripebank/tests/conftest.py b/tests/apps/stripebank/conftest.py similarity index 78% rename from src/stripebank/tests/conftest.py rename to tests/apps/stripebank/conftest.py index 68b3e550303..3b73a1824a7 100644 --- a/src/stripebank/tests/conftest.py +++ b/tests/apps/stripebank/conftest.py @@ -1,7 +1,7 @@ import json import pytest -from stripebank.bank import StripeBank +from apps.stripebank.bank import StripeBank pytestmark = [pytest.mark.django_db] @@ -18,7 +18,7 @@ def _set_stripe_key(settings): @pytest.fixture(autouse=True) def _fix_stripe_course(mocker): - mocker.patch("stripebank.bank.StripeBank.ue", 70) # let it be forever :'( + mocker.patch("apps.stripebank.bank.StripeBank.ue", 70) # let it be forever :'( @pytest.fixture @@ -33,7 +33,7 @@ def order(course, factory): @pytest.fixture def webhook(order): - with open("./stripebank/tests/.fixtures/webhook.json", "r") as fp: + with open("./tests/apps/stripebank/.fixtures/webhook.json", "r") as fp: webhook = json.load(fp) webhook["data"]["object"]["client_reference_id"] = order.slug diff --git a/src/stripebank/tests/test_stripe_get_items.py b/tests/apps/stripebank/test_stripe_get_items.py similarity index 100% rename from src/stripebank/tests/test_stripe_get_items.py rename to tests/apps/stripebank/test_stripe_get_items.py diff --git a/src/stripebank/tests/test_stripe_webhook.py b/tests/apps/stripebank/test_stripe_webhook.py similarity index 93% rename from src/stripebank/tests/test_stripe_webhook.py rename to tests/apps/stripebank/test_stripe_webhook.py index 0d5503ee6f3..c51a317f26b 100644 --- a/src/stripebank/tests/test_stripe_webhook.py +++ b/tests/apps/stripebank/test_stripe_webhook.py @@ -1,7 +1,7 @@ from decimal import Decimal import pytest -from stripebank.models import StripeNotification +from apps.stripebank.models import StripeNotification pytestmark = [ pytest.mark.django_db, diff --git a/src/studying/tests/api/test_home_page_slug.py b/tests/apps/studying/api/test_home_page_slug.py similarity index 100% rename from src/studying/tests/api/test_home_page_slug.py rename to tests/apps/studying/api/test_home_page_slug.py diff --git a/src/studying/tests/api/test_purchased_courses_view.py b/tests/apps/studying/api/test_purchased_courses_view.py similarity index 100% rename from src/studying/tests/api/test_purchased_courses_view.py rename to tests/apps/studying/api/test_purchased_courses_view.py diff --git a/src/studying/tests/conftest.py b/tests/apps/studying/conftest.py similarity index 100% rename from src/studying/tests/conftest.py rename to tests/apps/studying/conftest.py diff --git a/src/studying/tests/course_shipment/conftest.py b/tests/apps/studying/course_shipment/conftest.py similarity index 90% rename from src/studying/tests/course_shipment/conftest.py rename to tests/apps/studying/course_shipment/conftest.py index c24173c671c..bd34e48ab96 100644 --- a/src/studying/tests/course_shipment/conftest.py +++ b/tests/apps/studying/course_shipment/conftest.py @@ -1,7 +1,7 @@ from functools import partial import pytest -from studying.shipment import CourseShipment +from apps.studying.shipment import CourseShipment pytestmark = [pytest.mark.django_db] diff --git a/src/studying/tests/course_shipment/tests_course_shipment_study_model.py b/tests/apps/studying/course_shipment/tests_course_shipment_study_model.py similarity index 95% rename from src/studying/tests/course_shipment/tests_course_shipment_study_model.py rename to tests/apps/studying/course_shipment/tests_course_shipment_study_model.py index ec922001a92..4c43e0b3e30 100644 --- a/src/studying/tests/course_shipment/tests_course_shipment_study_model.py +++ b/tests/apps/studying/course_shipment/tests_course_shipment_study_model.py @@ -1,6 +1,6 @@ import pytest -from studying.models import Study +from apps.studying.models import Study pytestmark = [pytest.mark.django_db] diff --git a/src/studying/tests/course_shipment/tests_course_shipment_welcome_letter.py b/tests/apps/studying/course_shipment/tests_course_shipment_welcome_letter.py similarity index 100% rename from src/studying/tests/course_shipment/tests_course_shipment_welcome_letter.py rename to tests/apps/studying/course_shipment/tests_course_shipment_welcome_letter.py diff --git a/src/studying/tests/course_shipment/tests_course_template_context.py b/tests/apps/studying/course_shipment/tests_course_template_context.py similarity index 100% rename from src/studying/tests/course_shipment/tests_course_template_context.py rename to tests/apps/studying/course_shipment/tests_course_template_context.py diff --git a/src/studying/tests/shipping_factory/conftest.py b/tests/apps/studying/shipping_factory/conftest.py similarity index 100% rename from src/studying/tests/shipping_factory/conftest.py rename to tests/apps/studying/shipping_factory/conftest.py diff --git a/src/studying/tests/shipping_factory/tests_shippable_mixin.py b/tests/apps/studying/shipping_factory/tests_shippable_mixin.py similarity index 79% rename from src/studying/tests/shipping_factory/tests_shippable_mixin.py rename to tests/apps/studying/shipping_factory/tests_shippable_mixin.py index b994469ee60..ca78f65ea95 100644 --- a/src/studying/tests/shipping_factory/tests_shippable_mixin.py +++ b/tests/apps/studying/shipping_factory/tests_shippable_mixin.py @@ -5,7 +5,7 @@ @pytest.fixture def ship(mocker): - return mocker.patch("studying.shipment.CourseShipment.ship") + return mocker.patch("apps.studying.shipment.CourseShipment.ship") @pytest.fixture diff --git a/src/studying/tests/shipping_factory/tests_shipping_factory_get.py b/tests/apps/studying/shipping_factory/tests_shipping_factory_get.py similarity index 76% rename from src/studying/tests/shipping_factory/tests_shipping_factory_get.py rename to tests/apps/studying/shipping_factory/tests_shipping_factory_get.py index 86d57f61b00..601168ce589 100644 --- a/src/studying/tests/shipping_factory/tests_shipping_factory_get.py +++ b/tests/apps/studying/shipping_factory/tests_shipping_factory_get.py @@ -1,7 +1,7 @@ import pytest -from studying import shipment_factory as factory -from studying.shipment import CourseShipment +from apps.studying import shipment_factory as factory +from apps.studying.shipment import CourseShipment pytestmark = [pytest.mark.django_db] diff --git a/src/studying/tests/shipping_factory/tests_shipping_factory_ship.py b/tests/apps/studying/shipping_factory/tests_shipping_factory_ship.py similarity index 78% rename from src/studying/tests/shipping_factory/tests_shipping_factory_ship.py rename to tests/apps/studying/shipping_factory/tests_shipping_factory_ship.py index 08d3cd25259..4c5646706d9 100644 --- a/src/studying/tests/shipping_factory/tests_shipping_factory_ship.py +++ b/tests/apps/studying/shipping_factory/tests_shipping_factory_ship.py @@ -1,13 +1,13 @@ import pytest -from studying import shipment_factory as factory +from apps.studying import shipment_factory as factory pytestmark = [pytest.mark.django_db] @pytest.fixture def ship_course(mocker): - return mocker.patch("studying.shipment.CourseShipment.ship") + return mocker.patch("apps.studying.shipment.CourseShipment.ship") def test_course(course, ship_course, user, order): diff --git a/src/studying/tests/shipping_factory/tests_shipping_factory_unship.py b/tests/apps/studying/shipping_factory/tests_shipping_factory_unship.py similarity index 81% rename from src/studying/tests/shipping_factory/tests_shipping_factory_unship.py rename to tests/apps/studying/shipping_factory/tests_shipping_factory_unship.py index 7d06fb6533d..89920231bd1 100644 --- a/src/studying/tests/shipping_factory/tests_shipping_factory_unship.py +++ b/tests/apps/studying/shipping_factory/tests_shipping_factory_unship.py @@ -1,13 +1,13 @@ import pytest -from studying import shipment_factory +from apps.studying import shipment_factory pytestmark = [pytest.mark.django_db] @pytest.fixture def unship_course(mocker): - return mocker.patch("studying.shipment.CourseShipment.unship") + return mocker.patch("apps.studying.shipment.CourseShipment.unship") def test_course(course, unship_course, factory): diff --git a/src/tinkoff/tests/.fixtures/testing.pem b/tests/apps/tinkoff/.fixtures/testing.pem similarity index 100% rename from src/tinkoff/tests/.fixtures/testing.pem rename to tests/apps/tinkoff/.fixtures/testing.pem diff --git a/src/tinkoff/tests/bank_client/conftest.py b/tests/apps/tinkoff/bank_client/conftest.py similarity index 92% rename from src/tinkoff/tests/bank_client/conftest.py rename to tests/apps/tinkoff/bank_client/conftest.py index dace94b582e..511aa2bf111 100644 --- a/src/tinkoff/tests/bank_client/conftest.py +++ b/tests/apps/tinkoff/bank_client/conftest.py @@ -2,7 +2,7 @@ import respx -from tinkoff.bank import TinkoffBank +from apps.tinkoff.bank import TinkoffBank pytestmark = [pytest.mark.django_db] diff --git a/src/tinkoff/tests/bank_client/tests_tinkoff_bank_success_and_fail_urls.py b/tests/apps/tinkoff/bank_client/tests_tinkoff_bank_success_and_fail_urls.py similarity index 94% rename from src/tinkoff/tests/bank_client/tests_tinkoff_bank_success_and_fail_urls.py rename to tests/apps/tinkoff/bank_client/tests_tinkoff_bank_success_and_fail_urls.py index f1a587db1cd..904edfe6cd8 100644 --- a/src/tinkoff/tests/bank_client/tests_tinkoff_bank_success_and_fail_urls.py +++ b/tests/apps/tinkoff/bank_client/tests_tinkoff_bank_success_and_fail_urls.py @@ -1,6 +1,6 @@ import pytest -from tinkoff.bank import TinkoffBank +from apps.tinkoff.bank import TinkoffBank pytestmark = [pytest.mark.django_db] diff --git a/src/tinkoff/tests/bank_client/tests_tinkoff_get_initial_payment_url.py b/tests/apps/tinkoff/bank_client/tests_tinkoff_get_initial_payment_url.py similarity index 96% rename from src/tinkoff/tests/bank_client/tests_tinkoff_get_initial_payment_url.py rename to tests/apps/tinkoff/bank_client/tests_tinkoff_get_initial_payment_url.py index 65a25b9b260..76d620ebeeb 100644 --- a/src/tinkoff/tests/bank_client/tests_tinkoff_get_initial_payment_url.py +++ b/tests/apps/tinkoff/bank_client/tests_tinkoff_get_initial_payment_url.py @@ -6,7 +6,7 @@ @pytest.fixture def req(mocker): return mocker.patch( - "tinkoff.bank.TinkoffBank.call", + "apps.tinkoff.bank.TinkoffBank.call", return_value={ "PaymentURL": "https://mocked.in.fixture/", }, diff --git a/src/tinkoff/tests/bank_client/tests_tinkoff_receipt.py b/tests/apps/tinkoff/bank_client/tests_tinkoff_receipt.py similarity index 100% rename from src/tinkoff/tests/bank_client/tests_tinkoff_receipt.py rename to tests/apps/tinkoff/bank_client/tests_tinkoff_receipt.py diff --git a/src/tinkoff/tests/bank_client/tests_tinkoff_refund.py b/tests/apps/tinkoff/bank_client/tests_tinkoff_refund.py similarity index 96% rename from src/tinkoff/tests/bank_client/tests_tinkoff_refund.py rename to tests/apps/tinkoff/bank_client/tests_tinkoff_refund.py index 8bf77852f00..f45f2ff1256 100644 --- a/src/tinkoff/tests/bank_client/tests_tinkoff_refund.py +++ b/tests/apps/tinkoff/bank_client/tests_tinkoff_refund.py @@ -1,6 +1,6 @@ import pytest -from tinkoff.bank import TinkoffBank +from apps.tinkoff.bank import TinkoffBank pytestmark = [ pytest.mark.django_db, diff --git a/src/tinkoff/tests/bank_client/tests_tinkoff_request_signing.py b/tests/apps/tinkoff/bank_client/tests_tinkoff_request_signing.py similarity index 100% rename from src/tinkoff/tests/bank_client/tests_tinkoff_request_signing.py rename to tests/apps/tinkoff/bank_client/tests_tinkoff_request_signing.py diff --git a/src/tinkoff/tests/conftest.py b/tests/apps/tinkoff/conftest.py similarity index 100% rename from src/tinkoff/tests/conftest.py rename to tests/apps/tinkoff/conftest.py diff --git a/src/tinkoff/tests/credit_client/conftest.py b/tests/apps/tinkoff/credit_client/conftest.py similarity index 92% rename from src/tinkoff/tests/credit_client/conftest.py rename to tests/apps/tinkoff/credit_client/conftest.py index 854c900d521..981d1b552c3 100644 --- a/src/tinkoff/tests/credit_client/conftest.py +++ b/tests/apps/tinkoff/credit_client/conftest.py @@ -2,7 +2,7 @@ import respx -from tinkoff.credit import TinkoffCredit +from apps.tinkoff.credit import TinkoffCredit pytestmark = [pytest.mark.django_db] diff --git a/src/tinkoff/tests/credit_client/tests_tinkoff_credit_creation.py b/tests/apps/tinkoff/credit_client/tests_tinkoff_credit_creation.py similarity index 92% rename from src/tinkoff/tests/credit_client/tests_tinkoff_credit_creation.py rename to tests/apps/tinkoff/credit_client/tests_tinkoff_credit_creation.py index c8e3ddcd79a..3906d185742 100644 --- a/src/tinkoff/tests/credit_client/tests_tinkoff_credit_creation.py +++ b/tests/apps/tinkoff/credit_client/tests_tinkoff_credit_creation.py @@ -5,7 +5,7 @@ @pytest.fixture(autouse=True) def api_call(mocker): - return mocker.patch("tinkoff.credit.TinkoffCredit.call", return_value={"link": "__mocked"}) + return mocker.patch("apps.tinkoff.credit.TinkoffCredit.call", return_value={"link": "__mocked"}) def test_items(tinkoff): diff --git a/src/tinkoff/tests/credit_client/tests_tinkoff_credit_demo_mode.py b/tests/apps/tinkoff/credit_client/tests_tinkoff_credit_demo_mode.py similarity index 100% rename from src/tinkoff/tests/credit_client/tests_tinkoff_credit_demo_mode.py rename to tests/apps/tinkoff/credit_client/tests_tinkoff_credit_demo_mode.py diff --git a/src/tinkoff/tests/credit_notifications/conftest.py b/tests/apps/tinkoff/credit_notifications/conftest.py similarity index 94% rename from src/tinkoff/tests/credit_notifications/conftest.py rename to tests/apps/tinkoff/credit_notifications/conftest.py index 758f161e726..497fb68a52b 100644 --- a/src/tinkoff/tests/credit_notifications/conftest.py +++ b/tests/apps/tinkoff/credit_notifications/conftest.py @@ -1,6 +1,6 @@ import pytest -from app.test.api_client import DRFClient +from core.test.api_client import DRFClient pytestmark = [pytest.mark.django_db] diff --git a/src/tinkoff/tests/credit_notifications/tests_tinkoff_credit_notification.py b/tests/apps/tinkoff/credit_notifications/tests_tinkoff_credit_notification.py similarity index 96% rename from src/tinkoff/tests/credit_notifications/tests_tinkoff_credit_notification.py rename to tests/apps/tinkoff/credit_notifications/tests_tinkoff_credit_notification.py index 37ba66df76c..2fe4de3fdad 100644 --- a/src/tinkoff/tests/credit_notifications/tests_tinkoff_credit_notification.py +++ b/tests/apps/tinkoff/credit_notifications/tests_tinkoff_credit_notification.py @@ -1,7 +1,7 @@ from decimal import Decimal import pytest -from tinkoff.models import CreditNotification +from apps.tinkoff.models import CreditNotification pytestmark = [pytest.mark.django_db] diff --git a/src/tinkoff/tests/credit_notifications/tests_tinkoff_credit_notification_permissions.py b/tests/apps/tinkoff/credit_notifications/tests_tinkoff_credit_notification_permissions.py similarity index 79% rename from src/tinkoff/tests/credit_notifications/tests_tinkoff_credit_notification_permissions.py rename to tests/apps/tinkoff/credit_notifications/tests_tinkoff_credit_notification_permissions.py index 9aa834a8b3b..cbcde9a8d80 100644 --- a/src/tinkoff/tests/credit_notifications/tests_tinkoff_credit_notification_permissions.py +++ b/tests/apps/tinkoff/credit_notifications/tests_tinkoff_credit_notification_permissions.py @@ -1,7 +1,7 @@ import pytest -from app.test.api_client import DRFClient -from tinkoff.models import CreditNotification +from core.test.api_client import DRFClient +from apps.tinkoff.models import CreditNotification pytestmark = [pytest.mark.django_db] diff --git a/src/tinkoff/tests/dolyame_client/conftest.py b/tests/apps/tinkoff/dolyame_client/conftest.py similarity index 74% rename from src/tinkoff/tests/dolyame_client/conftest.py rename to tests/apps/tinkoff/dolyame_client/conftest.py index e23dcfe4ada..c48d77bde1d 100644 --- a/src/tinkoff/tests/dolyame_client/conftest.py +++ b/tests/apps/tinkoff/dolyame_client/conftest.py @@ -1,6 +1,6 @@ import pytest -from tinkoff.dolyame import Dolyame +from apps.tinkoff.dolyame import Dolyame pytestmark = [pytest.mark.django_db] @@ -9,7 +9,7 @@ def _credentials(settings): settings.DOLYAME_LOGIN = "root" settings.DOLYAME_PASSWORD = "l0ve" - settings.DOLYAME_CERTIFICATE_PATH = "tinkoff/tests/.fixtures/testing.pem" + settings.DOLYAME_CERTIFICATE_PATH = "tests/apps/tinkoff/.fixtures/testing.pem" @pytest.fixture(autouse=True) diff --git a/src/tinkoff/tests/dolyame_client/test_dolyame_common_methods.py b/tests/apps/tinkoff/dolyame_client/test_dolyame_common_methods.py similarity index 100% rename from src/tinkoff/tests/dolyame_client/test_dolyame_common_methods.py rename to tests/apps/tinkoff/dolyame_client/test_dolyame_common_methods.py diff --git a/src/tinkoff/tests/dolyame_client/test_dolyame_creation.py b/tests/apps/tinkoff/dolyame_client/test_dolyame_creation.py similarity index 100% rename from src/tinkoff/tests/dolyame_client/test_dolyame_creation.py rename to tests/apps/tinkoff/dolyame_client/test_dolyame_creation.py diff --git a/src/tinkoff/tests/dolyame_client/test_dolyame_refund.py b/tests/apps/tinkoff/dolyame_client/test_dolyame_refund.py similarity index 98% rename from src/tinkoff/tests/dolyame_client/test_dolyame_refund.py rename to tests/apps/tinkoff/dolyame_client/test_dolyame_refund.py index 8e63cdcb768..7eaede65a09 100644 --- a/src/tinkoff/tests/dolyame_client/test_dolyame_refund.py +++ b/tests/apps/tinkoff/dolyame_client/test_dolyame_refund.py @@ -3,7 +3,7 @@ from respx import MockRouter -from tinkoff import tasks +from apps.tinkoff import tasks pytestmark = [pytest.mark.django_db] diff --git a/src/tinkoff/tests/dolyame_notifications/conftest.py b/tests/apps/tinkoff/dolyame_notifications/conftest.py similarity index 92% rename from src/tinkoff/tests/dolyame_notifications/conftest.py rename to tests/apps/tinkoff/dolyame_notifications/conftest.py index 80440a39425..337a1dc62f9 100644 --- a/src/tinkoff/tests/dolyame_notifications/conftest.py +++ b/tests/apps/tinkoff/dolyame_notifications/conftest.py @@ -1,13 +1,13 @@ import pytest -from app.test.api_client import DRFClient +from core.test.api_client import DRFClient @pytest.fixture(autouse=True) def _credentials(settings): settings.DOLYAME_LOGIN = "root" settings.DOLYAME_PASSWORD = "l0ve" - settings.DOLYAME_CERTIFICATE_PATH = "tinkoff/tests/.fixtures/testing.pem" + settings.DOLYAME_CERTIFICATE_PATH = "tests/apps/tinkoff/.fixtures/testing.pem" @pytest.fixture diff --git a/src/tinkoff/tests/dolyame_notifications/test_creating_dolyame_notifications.py b/tests/apps/tinkoff/dolyame_notifications/test_creating_dolyame_notifications.py similarity index 97% rename from src/tinkoff/tests/dolyame_notifications/test_creating_dolyame_notifications.py rename to tests/apps/tinkoff/dolyame_notifications/test_creating_dolyame_notifications.py index 746eb40540d..0bc804edaa1 100644 --- a/src/tinkoff/tests/dolyame_notifications/test_creating_dolyame_notifications.py +++ b/tests/apps/tinkoff/dolyame_notifications/test_creating_dolyame_notifications.py @@ -1,7 +1,7 @@ from decimal import Decimal import pytest -from tinkoff.models import DolyameNotification +from apps.tinkoff.models import DolyameNotification pytestmark = [pytest.mark.django_db] diff --git a/src/tinkoff/tests/payment_notifications/conftest.py b/tests/apps/tinkoff/payment_notifications/conftest.py similarity index 72% rename from src/tinkoff/tests/payment_notifications/conftest.py rename to tests/apps/tinkoff/payment_notifications/conftest.py index 27a24f26e8b..75023f7506f 100644 --- a/src/tinkoff/tests/payment_notifications/conftest.py +++ b/tests/apps/tinkoff/payment_notifications/conftest.py @@ -11,4 +11,4 @@ def _set_tinkoff_credentials(settings): @pytest.fixture def _disable_token_validation(mocker): - mocker.patch("tinkoff.api.views.TinkoffNotificationsTokenValidator.__call__", return_value=True) + mocker.patch("apps.tinkoff.api.views.TinkoffNotificationsTokenValidator.__call__", return_value=True) diff --git a/src/tinkoff/tests/payment_notifications/tests_tinkoff_payment_notification_api.py b/tests/apps/tinkoff/payment_notifications/tests_tinkoff_payment_notification_api.py similarity index 93% rename from src/tinkoff/tests/payment_notifications/tests_tinkoff_payment_notification_api.py rename to tests/apps/tinkoff/payment_notifications/tests_tinkoff_payment_notification_api.py index 828eb8f70d0..68d3aa5b43e 100644 --- a/src/tinkoff/tests/payment_notifications/tests_tinkoff_payment_notification_api.py +++ b/tests/apps/tinkoff/payment_notifications/tests_tinkoff_payment_notification_api.py @@ -1,9 +1,9 @@ from decimal import Decimal import pytest -from orders.models import Order -from tinkoff.exceptions import TinkoffPaymentNotificationInvalidToken -from tinkoff.models import PaymentNotification +from apps.orders.models import Order +from apps.tinkoff.exceptions import TinkoffPaymentNotificationInvalidToken +from apps.tinkoff.models import PaymentNotification pytestmark = [ pytest.mark.django_db, diff --git a/src/tinkoff/tests/payment_notifications/tests_tinkoff_token_validator.py b/tests/apps/tinkoff/payment_notifications/tests_tinkoff_token_validator.py similarity index 90% rename from src/tinkoff/tests/payment_notifications/tests_tinkoff_token_validator.py rename to tests/apps/tinkoff/payment_notifications/tests_tinkoff_token_validator.py index 6d5e0ab14bd..f2c14bcde75 100644 --- a/src/tinkoff/tests/payment_notifications/tests_tinkoff_token_validator.py +++ b/tests/apps/tinkoff/payment_notifications/tests_tinkoff_token_validator.py @@ -1,8 +1,8 @@ import pytest -from tinkoff.exceptions import TinkoffPaymentNotificationInvalidToken -from tinkoff.exceptions import TinkoffPaymentNotificationNoTokenPassed -from tinkoff.token_validator import TinkoffNotificationsTokenValidator +from apps.tinkoff.exceptions import TinkoffPaymentNotificationInvalidToken +from apps.tinkoff.exceptions import TinkoffPaymentNotificationNoTokenPassed +from apps.tinkoff.token_validator import TinkoffNotificationsTokenValidator @pytest.mark.parametrize( diff --git a/src/users/tests/api/tests_user_self_view.py b/tests/apps/users/api/tests_user_self_view.py similarity index 91% rename from src/users/tests/api/tests_user_self_view.py rename to tests/apps/users/api/tests_user_self_view.py index b7faefba5c5..97d68827c0c 100644 --- a/src/users/tests/api/tests_user_self_view.py +++ b/tests/apps/users/api/tests_user_self_view.py @@ -1,6 +1,6 @@ import pytest -from users.models import User +from apps.users.models import User pytestmark = [pytest.mark.django_db] @@ -99,7 +99,7 @@ def test_edit_user_data_response(api): ["first_name", "last_name", "first_name_en", "last_name_en"], ) def test_user_update_first_or_last_names_triggers_diploma_regeneration(api, mocker, field_used_in_diplomas): - diploma_regenerator = mocker.patch("diplomas.tasks.regenerate_diplomas.delay") + diploma_regenerator = mocker.patch("apps.diplomas.tasks.regenerate_diplomas.delay") api.patch( "/api/v2/users/me/", @@ -112,7 +112,7 @@ def test_user_update_first_or_last_names_triggers_diploma_regeneration(api, mock def test_user_update_gender_triggers_diploma_regeneration(api, mocker): - diploma_regenerator = mocker.patch("diplomas.tasks.regenerate_diplomas.delay") + diploma_regenerator = mocker.patch("apps.diplomas.tasks.regenerate_diplomas.delay") api.patch( "/api/v2/users/me/", @@ -129,7 +129,7 @@ def test_user_update_gender_triggers_diploma_regeneration(api, mocker): ["github_username", "linkedin_username", "telegram_username"], ) def test_non_diploma_fields_not_triggers_diploma_regeneration(api, mocker, field_not_used_in_diplomas): - diploma_regenerator = mocker.patch("diplomas.tasks.regenerate_diplomas.delay") + diploma_regenerator = mocker.patch("apps.diplomas.tasks.regenerate_diplomas.delay") api.patch( "/api/v2/users/me/", diff --git a/src/users/tests/tags/conftest.py b/tests/apps/users/tags/conftest.py similarity index 100% rename from src/users/tests/tags/conftest.py rename to tests/apps/users/tags/conftest.py diff --git a/src/users/tests/tags/test_any_purchase_tag.py b/tests/apps/users/tags/test_any_purchase_tag.py similarity index 90% rename from src/users/tests/tags/test_any_purchase_tag.py rename to tests/apps/users/tags/test_any_purchase_tag.py index 0371e445090..dd686d4084e 100644 --- a/src/users/tests/tags/test_any_purchase_tag.py +++ b/tests/apps/users/tags/test_any_purchase_tag.py @@ -1,6 +1,6 @@ import pytest -from users.tags.pipeline import generate_tags +from apps.users.tags.pipeline import generate_tags pytestmark = [pytest.mark.django_db] diff --git a/src/users/tests/tags/test_b2b_tag.py b/tests/apps/users/tags/test_b2b_tag.py similarity index 92% rename from src/users/tests/tags/test_b2b_tag.py rename to tests/apps/users/tags/test_b2b_tag.py index 975baa573cc..fb6e0166a62 100644 --- a/src/users/tests/tags/test_b2b_tag.py +++ b/tests/apps/users/tags/test_b2b_tag.py @@ -1,6 +1,7 @@ import pytest -from users.tags.pipeline import generate_tags +from apps.users.tags.pipeline import generate_tags +from apps.mailing.models import PersonalEmailDomain pytestmark = [ pytest.mark.django_db, diff --git a/src/users/tests/tags/test_rebuild_tags_task.py b/tests/apps/users/tags/test_rebuild_tags_task.py similarity index 73% rename from src/users/tests/tags/test_rebuild_tags_task.py rename to tests/apps/users/tags/test_rebuild_tags_task.py index 467756b61a1..0472fbb74a1 100644 --- a/src/users/tests/tags/test_rebuild_tags_task.py +++ b/tests/apps/users/tags/test_rebuild_tags_task.py @@ -1,6 +1,6 @@ import pytest -from users import tasks +from apps.users import tasks pytestmark = [ pytest.mark.django_db, @@ -9,12 +9,12 @@ @pytest.fixture(autouse=True) def update_subscription(mocker): - return mocker.patch("app.tasks.update_dashamail_subscription.delay") + return mocker.patch("core.tasks.update_dashamail_subscription.delay") @pytest.fixture(autouse=True) def generate_tags(mocker): - return mocker.patch("users.tasks.generate_tags") + return mocker.patch("apps.users.tasks.generate_tags") def test_task(user, generate_tags, update_subscription): diff --git a/src/users/tests/tags/test_started_and_purchased_tags.py b/tests/apps/users/tags/test_started_and_purchased_tags.py similarity index 97% rename from src/users/tests/tags/test_started_and_purchased_tags.py rename to tests/apps/users/tags/test_started_and_purchased_tags.py index 695c3d6628f..7365f1025dc 100644 --- a/src/users/tests/tags/test_started_and_purchased_tags.py +++ b/tests/apps/users/tags/test_started_and_purchased_tags.py @@ -1,6 +1,6 @@ import pytest -from users.tags.pipeline import generate_tags +from apps.users.tags.pipeline import generate_tags pytestmark = [pytest.mark.django_db] diff --git a/src/users/tests/test_freezegun_not_broken.py b/tests/apps/users/test_freezegun_not_broken.py similarity index 95% rename from src/users/tests/test_freezegun_not_broken.py rename to tests/apps/users/test_freezegun_not_broken.py index 618a9de10ec..6df8fba26ab 100644 --- a/src/users/tests/test_freezegun_not_broken.py +++ b/tests/apps/users/test_freezegun_not_broken.py @@ -1,6 +1,6 @@ import pytest -from users.models import User +from apps.users.models import User pytestmark = [ pytest.mark.django_db, diff --git a/src/users/tests/test_user_diploma_languages.py b/tests/apps/users/test_user_diploma_languages.py similarity index 100% rename from src/users/tests/test_user_diploma_languages.py rename to tests/apps/users/test_user_diploma_languages.py diff --git a/src/users/tests/tests_name_parsing.py b/tests/apps/users/tests_name_parsing.py similarity index 93% rename from src/users/tests/tests_name_parsing.py rename to tests/apps/users/tests_name_parsing.py index 0a1f92c7246..f67ee2aae1b 100644 --- a/src/users/tests/tests_name_parsing.py +++ b/tests/apps/users/tests_name_parsing.py @@ -1,6 +1,6 @@ import pytest -from users.models import User +from apps.users.models import User pytestmark = [pytest.mark.django_db] diff --git a/src/users/tests/tests_user_printable_gender.py b/tests/apps/users/tests_user_printable_gender.py similarity index 91% rename from src/users/tests/tests_user_printable_gender.py rename to tests/apps/users/tests_user_printable_gender.py index 5b0082c3f89..7a3f5668923 100644 --- a/src/users/tests/tests_user_printable_gender.py +++ b/tests/apps/users/tests_user_printable_gender.py @@ -1,6 +1,6 @@ import pytest -from users.models import User +from apps.users.models import User pytestmark = [pytest.mark.django_db] diff --git a/src/users/tests/tests_user_printable_name.py b/tests/apps/users/tests_user_printable_name.py similarity index 100% rename from src/users/tests/tests_user_printable_name.py rename to tests/apps/users/tests_user_printable_name.py diff --git a/src/users/tests/tests_user_str.py b/tests/apps/users/tests_user_str.py similarity index 100% rename from src/users/tests/tests_user_str.py rename to tests/apps/users/tests_user_str.py diff --git a/src/users/tests/user_creator/conftest.py b/tests/apps/users/user_creator/conftest.py similarity index 100% rename from src/users/tests/user_creator/conftest.py rename to tests/apps/users/user_creator/conftest.py diff --git a/src/users/tests/user_creator/tests_user_creator_for_existing_users.py b/tests/apps/users/user_creator/tests_user_creator_for_existing_users.py similarity index 97% rename from src/users/tests/user_creator/tests_user_creator_for_existing_users.py rename to tests/apps/users/user_creator/tests_user_creator_for_existing_users.py index f9316ef0045..438bab5708e 100644 --- a/src/users/tests/user_creator/tests_user_creator_for_existing_users.py +++ b/tests/apps/users/user_creator/tests_user_creator_for_existing_users.py @@ -1,6 +1,6 @@ import pytest -from users.services import UserCreator +from apps.users.services import UserCreator pytestmark = [pytest.mark.django_db] diff --git a/src/users/tests/user_creator/tests_user_creator_name_and_email.py b/tests/apps/users/user_creator/tests_user_creator_name_and_email.py similarity index 97% rename from src/users/tests/user_creator/tests_user_creator_name_and_email.py rename to tests/apps/users/user_creator/tests_user_creator_name_and_email.py index 24012ce6943..6f57214654a 100644 --- a/src/users/tests/user_creator/tests_user_creator_name_and_email.py +++ b/tests/apps/users/user_creator/tests_user_creator_name_and_email.py @@ -1,6 +1,6 @@ import pytest -from users.services import UserCreator +from apps.users.services import UserCreator pytestmark = [pytest.mark.django_db] diff --git a/src/users/tests/user_creator/tests_user_creator_subscription.py b/tests/apps/users/user_creator/tests_user_creator_subscription.py similarity index 91% rename from src/users/tests/user_creator/tests_user_creator_subscription.py rename to tests/apps/users/user_creator/tests_user_creator_subscription.py index 85548b47ad5..88b006b9b23 100644 --- a/src/users/tests/user_creator/tests_user_creator_subscription.py +++ b/tests/apps/users/user_creator/tests_user_creator_subscription.py @@ -1,13 +1,13 @@ import pytest -from users.services import UserCreator +from apps.users.services import UserCreator pytestmark = [pytest.mark.django_db] @pytest.fixture(autouse=True) def rebuild_tags(mocker): - return mocker.patch("users.tasks.rebuild_tags.delay") + return mocker.patch("apps.users.tasks.rebuild_tags.delay") def test_user_is_not_subscribed_to_dashamail_by_default(rebuild_tags): diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 00000000000..be30e8a1209 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,23 @@ +import pytest + +from django.core.cache import cache + +# fmt: off +pytest_plugins = [ + "tests.factories.apps.diplomas", + "tests.factories.apps.orders", + "tests.factories.apps.products", + "tests.factories.core", + + "tests.fixtures.apps.products", + "tests.fixtures.apps.users", + "tests.fixtures.core", +] +# fmt: on + + +@pytest.fixture(autouse=True) +def _cache(request): + """Clear django cache after each test run.""" + yield + cache.clear() diff --git a/src/app/tests/dashamail/conftest.py b/tests/core/dashamail/conftest.py similarity index 87% rename from src/app/tests/dashamail/conftest.py rename to tests/core/dashamail/conftest.py index 192ecb8742f..73667ebafd2 100644 --- a/src/app/tests/dashamail/conftest.py +++ b/tests/core/dashamail/conftest.py @@ -2,7 +2,7 @@ from respx import MockRouter -from app.integrations.dashamail import AppDashamail +from core.integrations.dashamail import AppDashamail pytestmark = [pytest.mark.django_db] @@ -55,7 +55,7 @@ def fail_response_json(): @pytest.fixture def post(mocker, successful_response_json): - return mocker.patch("app.integrations.dashamail.http.DashamailHTTP.post", return_value=successful_response_json) + return mocker.patch("core.integrations.dashamail.http.DashamailHTTP.post", return_value=successful_response_json) @pytest.fixture diff --git a/src/app/tests/dashamail/test_subscription_updater.py b/tests/core/dashamail/test_subscription_updater.py similarity index 74% rename from src/app/tests/dashamail/test_subscription_updater.py rename to tests/core/dashamail/test_subscription_updater.py index 3c84de5b833..07a7c7482b6 100644 --- a/src/app/tests/dashamail/test_subscription_updater.py +++ b/tests/core/dashamail/test_subscription_updater.py @@ -1,6 +1,6 @@ import pytest -from app.integrations.dashamail.subscription_updater import SubscriptionUpdater +from core.integrations.dashamail.subscription_updater import SubscriptionUpdater pytestmark = [pytest.mark.django_db] @@ -12,27 +12,27 @@ def updater(): @pytest.fixture def subscribe_user(mocker): - return mocker.patch("app.integrations.dashamail.client.AppDashamail.subscribe_user") + return mocker.patch("core.integrations.dashamail.client.AppDashamail.subscribe_user") @pytest.fixture def get_subscriber_doesnt_exist(mocker): - return mocker.patch("app.integrations.dashamail.client.AppDashamail.get_subscriber", return_value=(None, False)) + return mocker.patch("core.integrations.dashamail.client.AppDashamail.get_subscriber", return_value=(None, False)) @pytest.fixture def get_subscriber_active(mocker): - return mocker.patch("app.integrations.dashamail.client.AppDashamail.get_subscriber", return_value=(1337, True)) + return mocker.patch("core.integrations.dashamail.client.AppDashamail.get_subscriber", return_value=(1337, True)) @pytest.fixture def get_subscriber_inactive(mocker): - return mocker.patch("app.integrations.dashamail.client.AppDashamail.get_subscriber", return_value=(1337, False)) + return mocker.patch("core.integrations.dashamail.client.AppDashamail.get_subscriber", return_value=(1337, False)) @pytest.fixture def update_subscriber(mocker): - return mocker.patch("app.integrations.dashamail.client.AppDashamail.update_subscriber") + return mocker.patch("core.integrations.dashamail.client.AppDashamail.update_subscriber") @pytest.mark.usefixtures("get_subscriber_active") diff --git a/src/app/tests/dashamail/tests_dashamail_get_subscriber.py b/tests/core/dashamail/tests_dashamail_get_subscriber.py similarity index 100% rename from src/app/tests/dashamail/tests_dashamail_get_subscriber.py rename to tests/core/dashamail/tests_dashamail_get_subscriber.py diff --git a/src/app/tests/dashamail/tests_dashamail_http.py b/tests/core/dashamail/tests_dashamail_http.py similarity index 95% rename from src/app/tests/dashamail/tests_dashamail_http.py rename to tests/core/dashamail/tests_dashamail_http.py index 78894c8f44d..c3d15e758ac 100644 --- a/src/app/tests/dashamail/tests_dashamail_http.py +++ b/tests/core/dashamail/tests_dashamail_http.py @@ -1,6 +1,6 @@ import pytest -from app.integrations.dashamail.exceptions import DashamailWrongResponse +from core.integrations.dashamail.exceptions import DashamailWrongResponse pytestmark = [pytest.mark.django_db] diff --git a/src/app/tests/dashamail/tests_dashamail_subscribe.py b/tests/core/dashamail/tests_dashamail_subscribe.py similarity index 93% rename from src/app/tests/dashamail/tests_dashamail_subscribe.py rename to tests/core/dashamail/tests_dashamail_subscribe.py index 4dbca0d37ff..00b9a0e87ee 100644 --- a/src/app/tests/dashamail/tests_dashamail_subscribe.py +++ b/tests/core/dashamail/tests_dashamail_subscribe.py @@ -1,6 +1,6 @@ import pytest -from app.integrations.dashamail.exceptions import DashamailSubscriptionFailed +from core.integrations.dashamail.exceptions import DashamailSubscriptionFailed pytestmark = [pytest.mark.django_db] diff --git a/src/app/tests/dashamail/tests_dashamail_subscribe_task.py b/tests/core/dashamail/tests_dashamail_subscribe_task.py similarity index 52% rename from src/app/tests/dashamail/tests_dashamail_subscribe_task.py rename to tests/core/dashamail/tests_dashamail_subscribe_task.py index e3a4f637203..b843a81b118 100644 --- a/src/app/tests/dashamail/tests_dashamail_subscribe_task.py +++ b/tests/core/dashamail/tests_dashamail_subscribe_task.py @@ -1,6 +1,6 @@ import pytest -from app import tasks +from core import tasks pytestmark = [ pytest.mark.django_db, @@ -9,8 +9,8 @@ @pytest.fixture def subscription_updater(mocker): - mocker.patch("app.integrations.dashamail.subscription_updater.SubscriptionUpdater.__call__") - return mocker.patch("app.integrations.dashamail.subscription_updater.SubscriptionUpdater.__init__", return_value=None) + mocker.patch("core.integrations.dashamail.subscription_updater.SubscriptionUpdater.__call__") + return mocker.patch("core.integrations.dashamail.subscription_updater.SubscriptionUpdater.__init__", return_value=None) def test_task(user, subscription_updater): diff --git a/src/app/tests/dashamail/tests_dashamail_update_subscriber.py b/tests/core/dashamail/tests_dashamail_update_subscriber.py similarity index 93% rename from src/app/tests/dashamail/tests_dashamail_update_subscriber.py rename to tests/core/dashamail/tests_dashamail_update_subscriber.py index 967343307ed..ce43e3ba1e3 100644 --- a/src/app/tests/dashamail/tests_dashamail_update_subscriber.py +++ b/tests/core/dashamail/tests_dashamail_update_subscriber.py @@ -1,6 +1,6 @@ import pytest -from app.integrations.dashamail.exceptions import DashamailUpdateFailed +from core.integrations.dashamail.exceptions import DashamailUpdateFailed pytestmark = [pytest.mark.django_db] diff --git a/src/app/tests/dashamail/tests_dashamail_url.py b/tests/core/dashamail/tests_dashamail_url.py similarity index 100% rename from src/app/tests/dashamail/tests_dashamail_url.py rename to tests/core/dashamail/tests_dashamail_url.py diff --git a/src/app/tests/helpers/tests_lower_first.py b/tests/core/helpers/tests_lower_first.py similarity index 87% rename from src/app/tests/helpers/tests_lower_first.py rename to tests/core/helpers/tests_lower_first.py index 9986fe19471..e89aa546573 100644 --- a/src/app/tests/helpers/tests_lower_first.py +++ b/tests/core/helpers/tests_lower_first.py @@ -1,6 +1,6 @@ import pytest -from app.helpers import lower_first +from core.helpers import lower_first @pytest.mark.parametrize( diff --git a/src/app/tests/pricing/tests_format_old_price_helper.py b/tests/core/pricing/tests_format_old_price_helper.py similarity index 92% rename from src/app/tests/pricing/tests_format_old_price_helper.py rename to tests/core/pricing/tests_format_old_price_helper.py index b4d626e6e74..e45cca0095e 100644 --- a/src/app/tests/pricing/tests_format_old_price_helper.py +++ b/tests/core/pricing/tests_format_old_price_helper.py @@ -1,7 +1,7 @@ from decimal import Decimal import pytest -from app.pricing import format_old_price +from core.pricing import format_old_price pytestmark = [pytest.mark.django_db] diff --git a/src/app/tests/pricing/tests_format_price_helper.py b/tests/core/pricing/tests_format_price_helper.py similarity index 91% rename from src/app/tests/pricing/tests_format_price_helper.py rename to tests/core/pricing/tests_format_price_helper.py index d8ed9ea494a..fa0bd589028 100644 --- a/src/app/tests/pricing/tests_format_price_helper.py +++ b/tests/core/pricing/tests_format_price_helper.py @@ -1,7 +1,7 @@ from decimal import Decimal import pytest -from app.pricing import format_price +from core.pricing import format_price pytestmark = [pytest.mark.django_db] diff --git a/src/app/tests/tests_drf_spectacular_view.py b/tests/core/tests_drf_spectacular_view.py similarity index 100% rename from src/app/tests/tests_drf_spectacular_view.py rename to tests/core/tests_drf_spectacular_view.py diff --git a/src/app/tests/tests_home_page_view.py b/tests/core/tests_home_page_view.py similarity index 100% rename from src/app/tests/tests_home_page_view.py rename to tests/core/tests_home_page_view.py diff --git a/src/app/tests/tests_s3_client.py b/tests/core/tests_s3_client.py similarity index 80% rename from src/app/tests/tests_s3_client.py rename to tests/core/tests_s3_client.py index b9d6cfffc4d..7bf8a32c6c9 100644 --- a/src/app/tests/tests_s3_client.py +++ b/tests/core/tests_s3_client.py @@ -1,6 +1,6 @@ import pytest -from app.integrations.s3 import AppS3 +from core.integrations.s3 import AppS3 pytestmark = [pytest.mark.django_db] diff --git a/tests/factories/__init__.py b/tests/factories/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/factories/apps/__init__.py b/tests/factories/apps/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/diplomas/factory.py b/tests/factories/apps/diplomas.py similarity index 72% rename from src/diplomas/factory.py rename to tests/factories/apps/diplomas.py index f0a802d97b7..06a8b8f3e1f 100644 --- a/src/diplomas/factory.py +++ b/tests/factories/apps/diplomas.py @@ -1,9 +1,9 @@ from typing import Any -from app.test.factory import register -from diplomas.models import Diploma -from products.models import Course -from users.models import User +from core.test.factory import register +from apps.diplomas.models import Diploma +from apps.products.models import Course +from apps.users.models import User @register diff --git a/src/orders/factory.py b/tests/factories/apps/orders.py similarity index 78% rename from src/orders/factory.py rename to tests/factories/apps/orders.py index 4f98b7e09c8..eccf13491c2 100644 --- a/src/orders/factory.py +++ b/tests/factories/apps/orders.py @@ -1,9 +1,9 @@ from typing import Any -from app.helpers import random_string -from app.test.factory import register -from orders.models import Order -from products.models import Product +from core.helpers import random_string +from core.test.factory import register +from apps.orders.models import Order +from apps.products.models import Product @register diff --git a/src/products/factory.py b/tests/factories/apps/products.py similarity index 74% rename from src/products/factory.py rename to tests/factories/apps/products.py index ab557d598d4..96ea1247f99 100644 --- a/src/products/factory.py +++ b/tests/factories/apps/products.py @@ -1,11 +1,11 @@ from typing import Any, TYPE_CHECKING -from app.helpers import random_string -from app.test.factory import register +from core.helpers import random_string +from core.test.factory import register if TYPE_CHECKING: - from products.models import Course - from products.models import Group + from apps.products.models import Course + from apps.products.models import Group @register diff --git a/src/app/factory.py b/tests/factories/core.py similarity index 81% rename from src/app/factory.py rename to tests/factories/core.py index a782dc1c553..25b457a507e 100644 --- a/src/app/factory.py +++ b/tests/factories/core.py @@ -4,12 +4,12 @@ from django.core.files.uploadedfile import SimpleUploadedFile -from app.test.factory import register +from core.test.factory import register faker = Faker() if TYPE_CHECKING: - from app.test.factory import FixtureFactory + from core.test.factory import FixtureFactory @register diff --git a/tests/fixtures/__init__.py b/tests/fixtures/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/fixtures/apps/__init__.py b/tests/fixtures/apps/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/products/fixtures.py b/tests/fixtures/apps/products.py similarity index 84% rename from src/products/fixtures.py rename to tests/fixtures/apps/products.py index 8f49d82f495..e17dda6c3d7 100644 --- a/src/products/fixtures.py +++ b/tests/fixtures/apps/products.py @@ -2,7 +2,7 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from products.models import Course + from apps.products.models import Course @pytest.fixture diff --git a/src/users/fixtures.py b/tests/fixtures/apps/users.py similarity index 100% rename from src/users/fixtures.py rename to tests/fixtures/apps/users.py diff --git a/tests/fixtures/core/__init__.py b/tests/fixtures/core/__init__.py new file mode 100644 index 00000000000..75c2e00ec77 --- /dev/null +++ b/tests/fixtures/core/__init__.py @@ -0,0 +1,21 @@ +from tests.fixtures.core.api import anon +from tests.fixtures.core.api import api +from tests.fixtures.core.api import as_ +from tests.fixtures.core.api import as_user +from tests.fixtures.core.dasha_subscription_updater import _mock_subscription_updater +from tests.fixtures.core.factory import factory +from tests.fixtures.core.factory import mixer +from tests.fixtures.core.send_mail import send_mail +from tests.fixtures.core.timezone import kamchatka_timezone + +__all__ = [ + "anon", + "api", + "as_", + "as_user", + "factory", + "mixer", + "send_mail", + "kamchatka_timezone", + "_mock_subscription_updater", +] diff --git a/src/app/fixtures/api.py b/tests/fixtures/core/api.py similarity index 85% rename from src/app/fixtures/api.py rename to tests/fixtures/core/api.py index eb9964e317c..194ee564131 100644 --- a/src/app/fixtures/api.py +++ b/tests/fixtures/core/api.py @@ -1,8 +1,8 @@ import pytest from typing import Callable -from app.test.api_client import DRFClient -from users.models import User +from core.test.api_client import DRFClient +from apps.users.models import User @pytest.fixture diff --git a/src/app/fixtures/dasha_subscription_updater.py b/tests/fixtures/core/dasha_subscription_updater.py similarity index 53% rename from src/app/fixtures/dasha_subscription_updater.py rename to tests/fixtures/core/dasha_subscription_updater.py index a9da9ca3e33..ccde1a4ae48 100644 --- a/src/app/fixtures/dasha_subscription_updater.py +++ b/tests/fixtures/core/dasha_subscription_updater.py @@ -3,4 +3,4 @@ @pytest.fixture(autouse=True) def _mock_subscription_updater(mocker): # global mock for Dashamail - mocker.patch("app.integrations.dashamail.subscription_updater.SubscriptionUpdater.__call__") + mocker.patch("core.integrations.dashamail.subscription_updater.SubscriptionUpdater.__call__") diff --git a/src/app/fixtures/factory.py b/tests/fixtures/core/factory.py similarity index 58% rename from src/app/fixtures/factory.py rename to tests/fixtures/core/factory.py index 67c4225571e..bf4ed976c75 100644 --- a/src/app/fixtures/factory.py +++ b/tests/fixtures/core/factory.py @@ -1,7 +1,7 @@ import pytest -from app.test.factory import FixtureFactory -from app.test.mixer import mixer as _mixer +from core.test.factory import FixtureFactory +from core.test.mixer import mixer as _mixer @pytest.fixture diff --git a/tests/fixtures/core/send_mail.py b/tests/fixtures/core/send_mail.py new file mode 100644 index 00000000000..e57502fceee --- /dev/null +++ b/tests/fixtures/core/send_mail.py @@ -0,0 +1,6 @@ +import pytest + + +@pytest.fixture +def send_mail(mocker): + return mocker.patch("apps.mailing.tasks.send_mail.delay") diff --git a/src/app/fixtures/timezone.py b/tests/fixtures/core/timezone.py similarity index 100% rename from src/app/fixtures/timezone.py rename to tests/fixtures/core/timezone.py