From 4422754624297c1622efd321ca75519530e15eb7 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Tue, 31 May 2022 18:09:38 +0300 Subject: [PATCH 001/101] Update ru.csv --- frappe/translations/ru.csv | 64 +++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/frappe/translations/ru.csv b/frappe/translations/ru.csv index 3fdeab5546..94a87bdcf8 100644 --- a/frappe/translations/ru.csv +++ b/frappe/translations/ru.csv @@ -840,7 +840,7 @@ Default Sending and Inbox,По умолчанию отправка и получ Default Sort Field,Поле сортировки по умолчанию, Default Sort Order,Порядок сортировки по умолчанию, Default Value,Значение по умолчанию, -"Default: ""Contact Us""","По умолчанию: ""Обратная связь""", +"Default: ""Contact Us""","По умолчанию: ""Contact Us""", DefaultValue,DefaultValue, Define workflows for forms.,Определите рабочие процессы для форм., Defines actions on states and the next step and allowed roles.,"Определяет действия на статусах, следующий шаг и роли, обладающие правами перевода статусов.", @@ -849,7 +849,7 @@ Delayed,Задерживается, Delete Data,Удалить данные, Delete comment?,Удалить комментарий?, Delete this record to allow sending to this email address,"Удалить эту запись, чтобы разрешить отправку на этот адрес электронной почты", -Delete {0} items permanently?,Удалить {0} продуктов навсегда?, +Delete {0} items permanently?,Удалить {0} объектов навсегда?, Deleted,Удаленный, Deleted DocType,Удаленный DocType, Deleted Document,Удаленный документ, @@ -914,7 +914,7 @@ Document can't saved.,Документ не может быть сохранен Document {0} has been set to state {1} by {2},Документ {0} установлен в состояние {1} на {2}, Documents,Документы, Documents assigned to you and by you.,"Документы, назначенные вам и вами.", -Domain Settings,Настройки домена, +Domain Settings,Настройка сфер деятельности, Domains HTML,Домены HTML, "Don't HTML Encode HTML tags like <script> or just characters like < or >, as they could be intentionally used in this field","Не HTML Кодировать HTML-теги, такие как <скрипт> или просто символы, такие как <или>, так как они могут быть преднамеренно использованы в этой области", Don't Override Status,Не переопределять статус, @@ -990,7 +990,7 @@ Enable Auto Reply,Включить автоматический ответ, Enable Automatic Backup,Включить автоматическое резервное копирование, Enable Chat,Включить чат, Enable Comments,Включить комментарии, -Enable Incoming,Включение входящей, +Enable Incoming,Включить входящие, Enable Outgoing,Включить исходящие, Enable Password Policy,Включить политику паролей, Enable Print Server,Включить сервер печати, @@ -1000,7 +1000,7 @@ Enable Scheduled Jobs,Включить запланированных задан Enable Social Login,Включить социальный вход, Enable Two Factor Auth,Включить двухфакторный аут, Enabled email inbox for user {0},Включен почтовый ящик для пользователя {0}, -"Encryption key is invalid, Please check site_config.json","Ключ шифрования недействителен, проверьте сайт_config.json", +"Encryption key is invalid, Please check site_config.json","Ключ шифрования недействителен, проверьте site_config.json", End Date Field,Поле конечной даты, End Date cannot be before Start Date!,Дата окончания не может быть до даты начала!, Endpoint URL,URL конечной точки, @@ -1029,8 +1029,8 @@ Error in Notification: {},Ошибка в уведомлении: {}, Error while connecting to email account {0},Ошибка при подключении к учетной записи электронной почты {0}, Error while evaluating Notification {0}. Please fix your template.,Ошибка при оценке уведомления {0}. Исправьте шаблон., Error: Document has been modified after you have opened it,"Ошибка: документ был изменен после того, как вы открыли его", -Error: Value missing for {0}: {1},Ошибка: значение отсутствует для {0}: {1}, -Errors in Background Events,Ошибки в фоновых событий, +Error: Value missing for {0}: {1},Ошибка: отсутствует значение для {0}: {1}, +Errors in Background Events,Ошибки в фоновых событиях, Event Category,Категория события, Event Participants,Участники мероприятия, Event Type,Тип события, @@ -1184,7 +1184,7 @@ Get Contacts,Получить контакты, Get Fields,Получить поля, Get your globally recognized avatar from Gravatar.com,Получить всемирно признанный аватара из Gravatar.com, GitHub,GitHub, -Give Review Points,Дайте очки обзора, +Give Review Points,Дайте баллы обзора, Global Unsubscribe,Глобальная отписка, Go to the document,Перейти к документу, Go to this URL after completing the form (only for Guest users),Перейдите по этому URL-адресу после заполнения формы (только для гостевых пользователей), @@ -1461,8 +1461,8 @@ Letter Head Name,Название заголовка письма, Letter Head in HTML,Заголовок письма в HTML, Level Name,Название уровня, Liked,Понравилось, -Liked By,В избранное К, -Liked by {0},В избранное {0}, +Liked By,Нравится, +Liked by {0},Нравится {0}, Likes,Понравившееся, Limit Number of DB Backups,Ограничение количества резервных копий БД, Line,Линия, @@ -1470,7 +1470,7 @@ Link DocType,Ссылка DocType, Link Expired,Срок действия ссылки, Link Name,Имя ссылки, Link Title,Название ссылки, -"Link that is the website home page. Standard Links (index, login, products, blog, about, contact)","Ссылка, которая является стартовой страницей сайта. Стандартные ссылки (индекс, логин, продукты, блог, о, контакт)", +"Link that is the website home page. Standard Links (index, login, products, blog, about, contact)","Ссылка, которая является стартовой страницей сайта. Стандартные ссылки (index, login, products, blog, about, contact)", Link to the page you want to open. Leave blank if you want to make it a group parent.,"Ссылка на страницу, которую вы хотите открыть. Оставьте пустым, если хотите сделать его родительским элементом группы.", Linked,Связанный, Linked With,Связанные с, @@ -2096,7 +2096,7 @@ Revert Of,Вернуть из, Reverted,Отменено, Review Level,Уровень обзора, Review Levels,Уровни обзора, -Review Points,Очки обзора, +Review Points,Баллы обзора, Reviews,Отзывы, Revoke,Аннулировать, Revoked,Аннулировано, @@ -2141,10 +2141,10 @@ SMS sent to following numbers: {0},SMS отправлено следующим SMTP Server,SMTP-сервер, SMTP Settings for outgoing emails,Настройки SMTP для исходящих писем, "SQL Conditions. Example: status=""Open""",SQL условия. Пример: статус = "Открыть", -SSL/TLS Mode,Режим SSL / TLS, +SSL/TLS Mode,Режим SSL/TLS, Salesforce,Salesforce, Same Field is entered more than once,Одно и то же поле вводится не один раз, -Save API Secret: ,Сохранить API-интерфейс:, +Save API Secret: ,Сохранить API секрет: , Save As,Сохранить как, Save Filter,Сохранить фильтр, Save Report,Сохранить отчет, @@ -2258,7 +2258,7 @@ Set Property After Alert,Задать свойство после оповеще Set Quantity,Установите Количество, Set Role For,Установить роль для, Set User Permissions,Задание разрешений пользователя, -Set Value,Задать значение, +Set Value,Установить значение, Set custom roles for page and report,Набор пользовательских ролей для страницы и отчета, "Set default format, page size, print style etc.","Установить форму, размер страницы, стиль печати и т.д., используюмых по умолчанию", Set non-standard precision for a Float or Currency field,Установите нестандартные точность для поплавка или валютной области, @@ -2337,7 +2337,7 @@ Slideshow like display for the website,"Слайд-шоу, как дисплей Small Text,Маленьикий текст, Smallest Currency Fraction Value,Минимальное дробное значение, Smallest circulating fraction unit (coin). For e.g. 1 cent for USD and it should be entered as 0.01,"Минимальная разменная денежная единица (монета). Например, для доллара — 1 цент, и его нужно ввести как 0,01", -Snapshot View,Снимок Посмотреть, +Snapshot View,Просмотр снимка, Social,Сообщество, Social Login Key,Ключ социального входа, Social Login Provider,Социальный провайдер, @@ -2418,7 +2418,7 @@ Suspend Sending,Приостановить Отправка, Switch To Desk,Переключение на рабочий стол, Symbol,Символ, Sync,Синхронизация, -Sync on Migrate,Синхронизация по Migrate, +Sync on Migrate,Синхронизировать при переносе, Syntax error in template,Синтаксическая ошибка в шаблоне, System,Система, System Page,Страница системы, @@ -2450,7 +2450,7 @@ Thank you for your interest in subscribing to our updates,Спасибо за в Thank you for your message,Спасибо за ваше сообщение, The CSV format is case sensitive,Формат CSV чувствителен к регистру, The Condition '{0}' is invalid,Условие '{0}' является недействительным, -The First User: You,Первый пользователя: Вы, +The First User: You,Первый пользователь: Вы, "The application has been updated to a new version, please refresh this page","Приложение был обновлен до новой версии, пожалуйста, обновите эту страницу", The attachments could not be correctly linked to the new document,Вложения не могут быть правильно связаны с новым документом, The document could not be correctly assigned,Документ не может быть правильно назначен, @@ -2653,7 +2653,7 @@ User Field,Поле пользователя, User ID of a Blogger,ID пользователя-блоггера, User Image,Изображение пользователя, User Name,Имя пользователя, -User Permission,Пользователь Введено, +User Permission,Разрешения пользователя, User Permissions,Разрешения пользователей, User Permissions are used to limit users to specific records.,Пользовательские разрешения используются для ограничения пользователей конкретными записями., User Permissions created sucessfully,Пользовательские разрешения созданы успешно, @@ -3068,8 +3068,8 @@ zoom-out,отдалить, {0} or {1},{0} или {1}, {0} record deleted,{0} запись удалена, {0} records deleted,{0} записей удалено, -{0} reverted your point on {1},{0} вернул вашу точку на {1}, -{0} reverted your points on {1},{0} вернул ваши очки на {1}, +{0} reverted your point on {1},{0} вернул ваш балл на {1}, +{0} reverted your points on {1},{0} вернул ваши баллы на {1}, {0} reverted {1},{0} вернул {1}, {0} room must have atmost one user.,{0} номер должен иметь самого одного пользователя., {0} rows for {1},{0} строк для {1}, @@ -3148,7 +3148,7 @@ Access not allowed from this IP Address,Доступ с этого IP-адрес Action Type,Тип действия, Activity Log by ,Активность Журнал по, Add Fields,Добавить поля, -Administration,Администрация, +Administration,Администрирование, After Cancel,После отмены, After Delete,После удаления, After Save,После сохранения, @@ -3157,7 +3157,7 @@ After Submit,После отправки, Aggregate Function Based On,"Агрегатная функция, основанная на", Aggregate Function field is required to create a dashboard chart,Поле Aggregate Function необходимо для создания диаграммы панели мониторинга., All Records,Все записи, -Allot Points To Assigned Users,Выделить очки назначенным пользователям, +Allot Points To Assigned Users,Выделить баллы назначенным пользователям, Allow Auto Repeat,Разрешить автоматическое повторение, Allow Google Calendar Access,Разрешить доступ к Календарю Google, Allow Google Contacts Access,Разрешить доступ к контактам Google, @@ -3380,7 +3380,7 @@ Invalid field name: {0},Неверное имя поля: {0}, Invalid file URL. Please contact System Administrator.,"Неверный URL файла. Пожалуйста, свяжитесь с системным администратором.", Invalid include path,Неверный путь включения, Invalid username or password,неправильное имя пользователя или пароль, -Is Primary,Первичный, +Is Primary,Основной, Is Primary Mobile,Основной мобильный, Is Primary Phone,Основной телефон, Is Tree,Дерево, @@ -3667,7 +3667,7 @@ via Data Import,через импорт данных, {0} are mandatory fields,{0} обязательные поля, {0} are required,{0} требуется, {0} assigned a new task {1} {2} to you,{0} назначил вам новое задание {1} {2}, -{0} gained {1} point for {2} {3},{0} набрал {1} очко за {2} {3}, +{0} gained {1} point for {2} {3},{0} получил {1} балл за {2} {3}, {0} gained {1} points for {2} {3},{0} набрал {1} баллов за {2} {3}, {0} has no versions tracked.,{0} не отслеживает версии., {0} is not a valid report format. Report format should one of the following {1},{0} не является допустимым форматом отчета. Формат отчета должен быть одним из следующих {1}, @@ -4045,7 +4045,7 @@ No Permitted Charts on this Dashboard,На этой панели инструм No Permitted Charts,Нет разрешенных графиков, Reset Chart,Сбросить график, via {0},через {0}, -{0} is not a valid Phone Number,{0} не является действительным номером телефона, +{0} is not a valid Phone Number,{0} недействительный номер телефона, Failed Transactions,Неудачные транзакции, Value for field {0} is too long in {1}. Length should be lesser than {2} characters,Значение поля {0} слишком длинное в {1}. Длина должна быть меньше {2} симв., Data Too Long,Данные слишком длинные, @@ -4121,8 +4121,8 @@ Using this console may allow attackers to impersonate you and steal your informa {0} w,{0} н, {0} M,{0} М, {0} y,{0} г, -yesterday,вчерашний день, -{0} years ago,{0} лет назад, +yesterday,вчера, +{0} years ago,{0} год назад, New Chart,Новый график, New Shortcut,Новый ярлык, Edit Chart,Изменить диаграмму, @@ -4700,3 +4700,11 @@ Value cannot be negative for {0}: {1},Значение не может быть Negative Value,Отрицательное значение, Authentication failed while receiving emails from Email Account: {0}.,Ошибка аутентификации при получении писем из учетной записи электронной почты: {0}., Message from server: {0},Сообщение с сервера: {0}, +Documentation,Документация, +User Forum,Форум пользователей, +Report an issue,Сообщить об ошибке, +My Profile,Мой профиль, +My Settings,Мои настройки, +Toggle Full Width,Переключить ширину, +Toggle Theme,Переключить тему, +Modules,Модули, From 8cf6d42d173e4b7d6d7c2966fbfc2dadc918e72d Mon Sep 17 00:00:00 2001 From: Aradhya Date: Fri, 10 Jun 2022 08:33:03 +0530 Subject: [PATCH 002/101] feat: Trying to replace db_query operations directly with qb --- frappe/model/db_query.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index fe52818235..6ac3402235 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -89,6 +89,9 @@ class DatabaseQuery(object): ignore_ddl=False, parent_doctype=None, ) -> List: + from frappe.database.query import Query + + self.query = Query() if ( not ignore_permissions @@ -112,6 +115,8 @@ class DatabaseQuery(object): # if `filters` is a list of strings, its probably fields filters, fields = fields, filters + self.temp_filters, self.temp_fields = filters, fields + if fields: self.fields = fields else: @@ -158,7 +163,7 @@ class DatabaseQuery(object): if not self.columns: return [] - result = self.build_and_run() + result = self.build_and_run(ignore_permissions=ignore_permissions) if with_comment_count and not as_list and self.doctype: self.add_comment_count(result) @@ -172,7 +177,7 @@ class DatabaseQuery(object): return result - def build_and_run(self): + def build_and_run(self, ignore_permissions): args = self.prepare_args() args.limit = self.add_limit() @@ -197,6 +202,15 @@ class DatabaseQuery(object): %(limit)s""" % args ) + if ignore_permissions: + sql = self.query.get_sql(self.doctype, fields=self.temp_fields, filters=self.temp_filters) + return sql.run( + as_dict=not self.as_list, + debug=self.debug, + update=self.update, + ignore_ddl=self.ignore_ddl, + run=self.run, + ) return frappe.db.sql( query, From 5f45897471be85bc96f64f0809a0c9d6bb447565 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Fri, 10 Jun 2022 13:31:53 +0300 Subject: [PATCH 003/101] Update ru.csv --- frappe/translations/ru.csv | 42 +++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/frappe/translations/ru.csv b/frappe/translations/ru.csv index 94a87bdcf8..5a23409ae8 100644 --- a/frappe/translations/ru.csv +++ b/frappe/translations/ru.csv @@ -68,7 +68,7 @@ Document Status,Статус документа, Document Type,Тип документа, Domain,Сфера деятельности, Domains,Сферы деятельности, -Draft,Проект, +Draft,Черновик, Edit,Редактировать, Email Account,Электронная почта, Email Address,Адрес электронной почты, @@ -415,7 +415,7 @@ Allowed In Mentions,Разрешено в упоминаниях, "Allowing DocType, DocType. Be careful!","Разрешение DocType, DocType. Будьте осторожны!", Already Registered,Уже регистрировались, Also adding the dependent currency field {0},Также добавление зависимого валютного поля {0}, -"Always add ""Draft"" Heading for printing draft documents",Всегда добавляйте "Черновик" Заголовок для печати проектов документов, +"Always add ""Draft"" Heading for printing draft documents","Всегда добавляйте заголовок "Черновик" для печати черновых документов", Always use Account's Email Address as Sender,Всегда использовать почту учетной записи в качестве отправителя, Always use Account's Name as Sender's Name,Всегда использовать имя учетной записи в качестве имени отправителя, Amend,Изменен, @@ -456,7 +456,7 @@ Archive,Архив, Archived,Архивные, Archived Columns,Архивные столбцы, Are you sure you want to delete the attachment?,"Вы уверены, что хотите удалить вложение?", -Are you sure you want to relink this communication to {0}?,"Вы уверены, что хотите перелинковать эту куммуникацию на {0}?", +Are you sure you want to relink this communication to {0}?,"Вы уверены, что хотите перелинковать эту коммуникацию на {0}?", Are you sure?,Вы уверены?, Arial,Arial, "As a best practice, do not assign the same set of permission rule to different Roles. Instead, set multiple Roles to the same User.","В качестве лучшего решения, не присваивайте одинаковый набор правил доступа для различных ролей. Вместо этого, установите несколько ролей одному и тому же пользователю.", @@ -795,7 +795,7 @@ Customize...,Пользовательские настройки..., Customized HTML Templates for printing transactions.,Индивидуальные шаблоны HTML для печатных операций., Cut,Вырезать, DESC,DESC, -Daily Event Digest is sent for Calendar Events where reminders are set.,"Ежедневно событие Дайджест направляется на Календарь событий, где установлены напоминания.", +Daily Event Digest is sent for Calendar Events where reminders are set.,"Ежедневный дайджест событий направляется в календарь событий, где установлены напоминания.", Danger,Опасность, Dark Color,Темный цвет, Dashboard Chart,Диаграмма приборной панели, @@ -3159,7 +3159,7 @@ Aggregate Function field is required to create a dashboard chart,Поле Aggreg All Records,Все записи, Allot Points To Assigned Users,Выделить баллы назначенным пользователям, Allow Auto Repeat,Разрешить автоматическое повторение, -Allow Google Calendar Access,Разрешить доступ к Календарю Google, +Allow Google Calendar Access,Разрешить доступ к календарю Google, Allow Google Contacts Access,Разрешить доступ к контактам Google, Allow Google Drive Access,Разрешить доступ Google Drive, Allow Guest,Разрешить гость, @@ -3181,7 +3181,7 @@ Assignment Days,Дни назначения, Assignment Rule Day,День Правил Назначения, Assignments,Назначения, Attach a web link,Прикрепите веб-ссылку, -Authorize Google Calendar Access,Авторизовать доступ к Календарю Google, +Authorize Google Calendar Access,Авторизовать доступ к календарю Google, Authorize Google Contacts Access,Авторизовать доступ к контактам Google, Authorize Google Drive Access,Авторизовать Google Drive Access, Auto Repeat Document Creation Failed,Ошибка автоматического создания документа, @@ -3325,12 +3325,12 @@ Google API Settings.,Настройки Google API., Google Calendar,Календарь Google, "Google Calendar - Could not create Calendar for {0}, error code {1}.","Календарь Google. Не удалось создать календарь для {0}, код ошибки {1}.", "Google Calendar - Could not delete Event {0} from Google Calendar, error code {1}.","Календарь Google - не удалось удалить событие {0} из календаря Google, код ошибки {1}.", -"Google Calendar - Could not fetch event from Google Calendar, error code {0}.","Календарь Google - не удалось получить событие из Календаря Google, код ошибки {0}.", +"Google Calendar - Could not fetch event from Google Calendar, error code {0}.","Календарь Google - не удалось получить событие из календаря Google, код ошибки {0}.", "Google Calendar - Could not insert contact in Google Contacts {0}, error code {1}.","Календарь Google. Не удалось вставить контакт в контакты Google {0}, код ошибки {1}.", -"Google Calendar - Could not insert event in Google Calendar {0}, error code {1}.","Календарь Google. Не удалось вставить событие в Календарь Google {0}, код ошибки {1}.", -"Google Calendar - Could not update Event {0} in Google Calendar, error code {1}.","Календарь Google - не удалось обновить событие {0} в Календаре Google, код ошибки {1}.", -Google Calendar Event ID,Идентификатор события Календаря Google, -Google Calendar Integration.,Интеграция Календаря Google., +"Google Calendar - Could not insert event in Google Calendar {0}, error code {1}.","Календарь Google. Не удалось вставить событие в календарь Google {0}, код ошибки {1}.", +"Google Calendar - Could not update Event {0} in Google Calendar, error code {1}.","Календарь Google - не удалось обновить событие {0} в календаре Google, код ошибки {1}.", +Google Calendar Event ID,Идентификатор события календаря Google, +Google Calendar Integration.,Интеграция календаря Google., Google Calendar has been configured.,Календарь Google был настроен., Google Contacts,Контакты Google, "Google Contacts - Could not sync contacts from Google Contacts {0}, error code {1}.","Контакты Google - не удалось синхронизировать контакты из контактов Google {0}, код ошибки {1}.", @@ -3434,7 +3434,7 @@ New Notification,Новое уведомление, New {0}: {1},Новый {0}: {1}, Newsletter should have atleast one recipient,Бюллетень должен иметь как минимум одного получателя, No Events Today,Сегодня нет событий, -No Google Calendar Event to sync.,Нет события Календаря Google для синхронизации., +No Google Calendar Event to sync.,Нет события в календаря Google для синхронизации., No More Activity,Нет больше активности, No Name Specified for {0},Имя не указано для {0}, No Upcoming Events,Нет предстоящих событий, @@ -3484,11 +3484,11 @@ Print Settings...,Настройки печати..., Producer Document Name,Название документа производителя, Producer URL,URL производителя, Property Depends On,Недвижимость зависит от, -Pull from Google Calendar,Вытащить из календаря Google, -Pull from Google Contacts,Вытащить из контактов Google, -Pulled from Google Calendar,Вытащил из Календаря Google, -Pulled from Google Contacts,Вытащено из контактов Google, -Push to Google Calendar,Нажмите на Google Calendar, +Pull from Google Calendar,Загрузить из календаря Google, +Pull from Google Contacts,Загрузить из контактов Google, +Pulled from Google Calendar,Загружено из календаря Google, +Pulled from Google Contacts,Загружено из контактов Google, +Push to Google Calendar,Нажмите на Google календарь, Push to Google Contacts,Нажмите на контакты Google, Queue / Worker,Очередь / Рабочий, RAW Information Log,Необработанный информационный журнал, @@ -3526,7 +3526,7 @@ Select Date Range,Выберите диапазон дат, Select Field,Выберите поле, Select Field...,Выберите поле..., Select Filters,Выберите фильтры, -Select Google Calendar to which event should be synced.,"Выберите Календарь Google, к которому нужно синхронизировать событие.", +Select Google Calendar to which event should be synced.,"Выберите календарь Google, к которому нужно синхронизировать событие.", Select Google Contacts to which contact should be synced.,"Выберите Google Контакты, с которыми контакт должен быть синхронизирован.", Select Group By...,Выбрать группу по..., Select Mandatory,Выберите Обязательный, @@ -3593,7 +3593,7 @@ Time series based on is required to create a dashboard chart,Временной Time {0} must be in format: {1},Время {0} должно быть в формате: {1}, "To configure Auto Repeat, enable ""Allow Auto Repeat"" from {0}.","Чтобы настроить автоматический повтор, включите «Разрешить автоматический повтор» из {0}.", To enable it follow the instructions in the following link: {0},"Чтобы включить его, следуйте инструкциям по следующей ссылке: {0}", -"To use Google Calendar, enable {0}.","Чтобы использовать Календарь Google, включите {0}.", +"To use Google Calendar, enable {0}.","Чтобы использовать календарь Google, включите {0}.", "To use Google Contacts, enable {0}.","Чтобы использовать контакты Google, включите {0}.", "To use Google Drive, enable {0}.","Чтобы использовать Google Диск, включите {0}.", Today's Events,Сегодняшние события, @@ -3662,7 +3662,7 @@ submitted this document {0},отправил этот документ {0}, "tag name..., e.g. #tag","имя тега ..., например #tag", uploaded file,загруженный файл, via Data Import,через импорт данных, -{0} Google Calendar Events synced.,{0} События Календаря Google синхронизированы., +{0} Google Calendar Events synced.,{0} События календаря Google синхронизированы., {0} Google Contacts synced.,{0} Google Контакты синхронизированы., {0} are mandatory fields,{0} обязательные поля, {0} are required,{0} требуется, @@ -3697,7 +3697,7 @@ Cancelled,отменен, Chart,Диаграмма, Close,Закрыть, Communication,Коммуникация, -Compact Item Print,Компактный товара печати, +Compact Item Print,Компактное отоборажение товара при печати, Company,Организация, Complete,Завершен, Completed,Завершено, From 6734379848c507f368781df8aba1b1fb38bd7e7d Mon Sep 17 00:00:00 2001 From: Vladislav Date: Fri, 10 Jun 2022 16:17:15 +0300 Subject: [PATCH 004/101] Update ru.csv --- frappe/translations/ru.csv | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/frappe/translations/ru.csv b/frappe/translations/ru.csv index 5a23409ae8..0295ab88e9 100644 --- a/frappe/translations/ru.csv +++ b/frappe/translations/ru.csv @@ -10,7 +10,7 @@ Actions,Действия, Active,Активен, Add,Добавить, Add Comment,Добавить комментарий, -Add Row,Добавить ряд, +Add Row,Добавить строку, Address,Адрес, Address Line 2,Адрес (2-я строка), Address Title,Название адреса, @@ -1357,7 +1357,7 @@ Invalid Outgoing Mail Server or Port,Неверный сервер исходя Invalid Output Format,Неверный формат выходного, Invalid Password,Неверный пароль, Invalid Password:,Неверный пароль:, -Invalid Request,Неверная заявка, +Invalid Request,Неверный запрос, Invalid Search Field {0},Неверное поле поиска {0}, Invalid Subscription,Недействительная подписка, Invalid Token,Недопустимый токен, @@ -1972,7 +1972,7 @@ Pull Insert,Вставить вкладыш, Pull Update,Pull Update, Push,От себя, Push Delete,Нажмите Удалить, -Push Failed,Ошибка нажата, +Push Failed,Ошибка отправки, Push Insert,Push Insert, Push Update,Push Update, Python Module,Модуль Python, @@ -2122,9 +2122,9 @@ Row No,Строка №, Row Status,Статус строки, Row Values Changed,Значения строк Измененные, Row {0}: Not allowed to disable Mandatory for standard fields,Строка {0}: не разрешено отключать обязательные для стандартных полей, -Row {0}: Not allowed to enable Allow on Submit for standard fields,Ряд {0}: Не разрешается включать Разрешить проведение для стандартных полей, -Rows Added,Ряды Добавлено, -Rows Removed,Ряды Удалены, +Row {0}: Not allowed to enable Allow on Submit for standard fields,Строка {0}: Не разрешается включать Разрешить проведение для стандартных полей, +Rows Added,Строки добавлены, +Rows Removed,Строки удалены, Rule,Правило, Rule Name,Название правила, Rules defining transition of state in the workflow.,"Правила, определяющие переход этапов в потоке.", @@ -2194,8 +2194,8 @@ Select File Type,Выберите тип файла, Select Language...,Выберите язык..., Select Languages,Выберите языки, Select Module,Выбор модуля, -Select Print Format,Выберите Печатную форму, -Select Print Format to Edit,Выберите Печатную форму для Редактирование, +Select Print Format,Выберите бланк для печати, +Select Print Format to Edit,Выберите печатный бланк для редактирования, Select Role,Выберите роль, Select Table Columns for {0},Выберите столбцы таблицы для {0}, Select Your Region,Выберите регион, @@ -3814,7 +3814,7 @@ and,и, {0} Name,{0} Имя, {0} is required,{0} требуется, ALL,ВСЕ, -Attach File,Прикрепить файл, +Attach File,Прикрепить файл, Barcode,Штрих-код, Beginning with,Начиная с, Bold,Жирный, @@ -4011,11 +4011,11 @@ Setup > User,Настройка> Пользователь, Setup > Customize Form,Настройка> Настройка формы, Setup > User Permissions,Настройка> Полномочия пользователя, "Error connecting to QZ Tray Application...

You need to have QZ Tray application installed and running, to use the Raw Print feature.

Click here to Download and install QZ Tray.
Click here to learn more about Raw Printing.","Ошибка подключения к приложению QZ Tray ...

Вам необходимо установить и запустить приложение QZ Tray, чтобы использовать функцию Raw Print.

Нажмите здесь, чтобы загрузить и установить QZ Tray .
Нажмите здесь, чтобы узнать больше о Raw Printing .", -No email account associated with the User. Please add an account under User > Email Inbox.,"Нет учетной записи электронной почты, связанной с пользователем. Пожалуйста, добавьте учетную запись под User> Email Inbox.", +No email account associated with the User. Please add an account under User > Email Inbox.,"Нет учетной записи электронной почты, связанной с пользователем. Пожалуйста, добавьте электронную почту в настройках пользователя", "For comparison, use >5, <10 or =324. For ranges, use 5:10 (for values between 5 & 10).","Для сравнения используйте> 5, <10 или = 324. Для диапазонов используйте 5:10 (для значений от 5 до 10).", -No default Address Template found. Please create a new one from Setup > Printing and Branding > Address Template.,"Шаблон адреса по умолчанию не найден. Создайте новый, выбрав «Настройка»> «Печать и брендинг»> «Шаблон адреса».", -Please setup default Email Account from Setup > Email > Email Account,"Пожалуйста, настройте учетную запись электронной почты по умолчанию из меню «Настройка»> «Электронная почта»>", -Email Account not setup. Please create a new Email Account from Setup > Email > Email Account,"Учетная запись электронной почты не настроена. Пожалуйста, создайте новую учетную запись электронной почты от Настройка> Электронная почта> Учетная запись электронной почты", +No default Address Template found. Please create a new one from Setup > Printing and Branding > Address Template.,"Шаблон адреса по умолчанию не найден. Создайте новый, выбрав «Настройка» > «Печать и брендинг» > «Шаблон адреса».", +Please setup default Email Account from Setup > Email > Email Account,"Пожалуйста, настройте учетную запись электронной почты по умолчанию из меню «Настройка» > «Электронная почта»>", +Email Account not setup. Please create a new Email Account from Setup > Email > Email Account,"Учетная запись электронной почты не настроена. Пожалуйста, создайте новую учетную запись электронной почты в «Настройки» > «Электронная почта» > «Учетная запись электронной почты»", Attach file,Прикрепить файл, Contribution Status,Статус вклада, Contribution Document Name,Название документа о взносе, From 718ad100f5613def280f2c33893193c7c3a90fb3 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Fri, 10 Jun 2022 16:32:18 +0300 Subject: [PATCH 005/101] Update ru.csv --- frappe/translations/ru.csv | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/frappe/translations/ru.csv b/frappe/translations/ru.csv index 0295ab88e9..2999f9fa23 100644 --- a/frappe/translations/ru.csv +++ b/frappe/translations/ru.csv @@ -181,7 +181,7 @@ Portal,Портал, Portal Settings,Настройки портала, Preview,Просмотр, Primary,Основной, -Print Format,Формат печати, +Print Format,Печатный бланк, Print Settings,Настройки печати, Print taxes with zero amount,Печать налогов с нулевой суммой, Private,Личные, @@ -745,7 +745,7 @@ Create Chart,Создать диаграмму, Create New,Создать, Create Post,Создать пост, Create User Email,Создать электронной почты пользователя, -Create a New Format,Создать новый формат, +Create a New Format,Создать новый бланк, Create a new record,Создать новую запись, Create a new {0},Создать {0}, Create and Send Newsletters,Создание и отправка рассылки, @@ -928,7 +928,7 @@ Download Report,Скачать отчет, Download Your Data,Скачать ваши данные, Download link for your backup will be emailed on the following email address: {0},Ссылка для скачивания вашей резервной копии будет отправлена на следующий электронный адрес: {0}, Download with Data,Скачать с данными, -Drag and Drop tool to build and customize Print Formats.,Конструктор для сборки и настройки форматов печати., +Drag and Drop tool to build and customize Print Formats.,Инструмент для сборки и настройки бланков для печати., Drag elements from the sidebar to add. Drag them back to trash.,"Перетащите элементы с боковой панели, чтобы добавить. Перетащите их обратно чтобы удалить.", Dropbox Access Key,Dropbox ключ доступа, Dropbox Access Secret,Dropbox секретный ключ, @@ -1605,7 +1605,7 @@ New Activity,Новая активность, New Chat,Новый чат, New Comment on {0}: {1},Новый комментарий к {0}: {1}, New Connection,Новое соединение, -New Custom Print Format,Новый пользовательский Формат печати, +New Custom Print Format,Новый пользовательский печатный бланк, New Email,Новая электронная почта, New Email Account,Новый аккаунт электронной почты, New Event,Новое событие, @@ -1616,7 +1616,7 @@ New Name,Новое имя, New Newsletter,Новый бюллетень, New Password,Новый пароль, New Password Required.,Требуется новый пароль., -New Print Format Name,Название нового формата печати, +New Print Format Name,Название нового печатного бланка, New Report name,Новое название отчёта, New Value,Новое значение, New data will be inserted.,Новые данные будут вставлены., @@ -1932,7 +1932,7 @@ Previous,Предыдущая, Previous Hash,Предыдущий хэш, Primary Color,Основной цвет, Print Documents,Печать документов, -Print Format Builder,Конструктор печатных форм, +Print Format Builder,Конструктор бланков для печати, Print Format Help,Помощь по печатным формам, Print Format Type,Тип печатной формы, Print Format {0} is disabled,Печатная форма {0} отключена, @@ -2200,7 +2200,7 @@ Select Role,Выберите роль, Select Table Columns for {0},Выберите столбцы таблицы для {0}, Select Your Region,Выберите регион, Select a Brand Image first.,Выберите бренд изображение в первую очередь., -Select a DocType to make a new format,"Выберите DOCTYPE, чтобы сделать новый формат", +Select a DocType to make a new format,"Выберите DOCTYPE, чтобы сделать новый бланк", Select a chat to start messaging.,"Выберите чат, чтобы начать обмен сообщениями.", Select a group node first.,Выберите узел группы в первую очередь., Select an existing format to edit or start a new format.,Выберите существующий формат для редактирования или начать новый формат., @@ -2360,7 +2360,7 @@ Spam,Спам, SparkPost,SparkPost, Special Characters are not allowed,Спецсимволы не допустимы, "Standard DocType cannot have default print format, use Customize Form","Стандартный DocType не может иметь формат печати по умолчанию, используйте Настроить форму", -Standard Print Format cannot be updated,Стандартный Формат печати не может быть обновлен, +Standard Print Format cannot be updated,Стандартный печатный бланк не может быть обновлен, Standard Print Style cannot be changed. Please duplicate to edit.,Стандартный стиль печати не может быть изменен. Повторите попытку для редактирования., Standard Reports,Стандартные отчеты, Standard Sidebar Menu,Стандартное боковое меню, From d3a935af604f15932b465fda7e0beb61640360dd Mon Sep 17 00:00:00 2001 From: Vladislav Date: Fri, 10 Jun 2022 17:24:30 +0300 Subject: [PATCH 006/101] Update ru.csv --- frappe/translations/ru.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/translations/ru.csv b/frappe/translations/ru.csv index 2999f9fa23..81b8bdecd2 100644 --- a/frappe/translations/ru.csv +++ b/frappe/translations/ru.csv @@ -2962,7 +2962,7 @@ question-sign,Вопрос-знак, remove-circle,удалить-круг, remove-sign,удалить-знак, removed,удален, -renamed from {0} to {1},переименован из {0} до {1}, +renamed from {0} to {1},переименован из {0} в {1}, repeat,повторение, resize-full,изменить размер-полный, resize-horizontal,изменить размер горизонтальной, From 2ea87532e7e4b511295714d719a1591288a26303 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Thu, 16 Jun 2022 23:15:51 +0300 Subject: [PATCH 007/101] Update ru.csv Fix logic!!! --- frappe/translations/ru.csv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/translations/ru.csv b/frappe/translations/ru.csv index 81b8bdecd2..31f94dfcf6 100644 --- a/frappe/translations/ru.csv +++ b/frappe/translations/ru.csv @@ -3825,14 +3825,14 @@ Clear,Отчистить, Comment,Комментарий, Comments,Комментарии, DRAFT,ЧЕРНОВИК, -Dashboard,панель инструментов, +Dashboard,Панель инструментов, DocType,DocType, Download,Скачать, EMail,Эл. адрес, Edit in Full Page,Редактировать на полной странице, Email Inbox,Email Inbox, File,Файл, -Forward,Дальше, +Forward,Переслать, Icon,Икона, In,В, Inbox,Входящие, From e1154314fe245a39b4dcacfef5053ffd6b847c4d Mon Sep 17 00:00:00 2001 From: Vladislav Date: Fri, 17 Jun 2022 00:29:16 +0300 Subject: [PATCH 008/101] Update ru.csv --- frappe/translations/ru.csv | 50 +++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/frappe/translations/ru.csv b/frappe/translations/ru.csv index 31f94dfcf6..96b48ea99c 100644 --- a/frappe/translations/ru.csv +++ b/frappe/translations/ru.csv @@ -43,7 +43,7 @@ Client Secret,Секрет клиента, Closed,Закрыт, Code,Код, Collapse All,Свернуть все, -Color,цвет, +Color,Цвет, Company Name,Название компании, Condition,Условия, Contact,Контакты, @@ -118,13 +118,13 @@ Is Active,Активен, Is Completed,Выполнен, Is Default,По умолчанию, Kanban Board,Канбан-доска, -Label,Имя поля, +Label,Имя метки, Language Name,Название языка, Last Name,Фамилия, Leaderboard,Доска почёта, Letter Head,Печатный бланк, Level,Уровень, -Limit,Предел, +Limit,Лимит, Log,Запись в журнале, Logs,Журналы, Low,Низкий, @@ -302,8 +302,8 @@ old_parent,old_parent, 1 month ago,1 месяц назад, 1 year ago,1 год назад, ; not allowed in condition,; не допускается в состоянии, -"

Default Template

\n

Uses Jinja Templating and all the fields of Address (including Custom Fields if any) will be available

\n
{{ address_line1 }}<br>\n{% if address_line2 %}{{ address_line2 }}<br>{% endif -%}\n{{ city }}<br>\n{% if state %}{{ state }}<br>{% endif -%}\n{% if pincode %} PIN:  {{ pincode }}<br>{% endif -%}\n{{ country }}<br>\n{% if phone %}Phone: {{ phone }}<br>{% endif -%}\n{% if fax %}Fax: {{ fax }}<br>{% endif -%}\n{% if email_id %}Email: {{ email_id }}<br>{% endif -%}\n
","

Шаблон по умолчанию \n <р> Использование дзиндзя Templating и все поля адрес ( в том числе Пользовательские поля если таковые имеются) будут доступны \n
 <код> {{address_line1}} & LT; BR & GT; \n {%, если address_line2%} {{address_line2}} & лт; бр & GT; { % ENDIF -%} \n {{город}} & Lt; BR & GT; \n {%, если государство%} {{состояние}} & Lt; BR & GT; {% ENDIF -%} \n {%, если пин-код%} PIN: {{пин-код}} & Lt; BR & GT; {% ENDIF -%} \n {{страна}} & Lt; BR & GT; \n {%, если телефон%} Телефон: {{телефон}} & Lt; BR & GT; { % ENDIF -%} \n {%, если факс%} Факс: {{FAX}} & Lt; BR & GT; {% ENDIF -%} \n {%, если email_id%} E-mail: {{email_id}} & Lt; BR & GT ; {% ENDIF -%} \n </ код> 

", -A Lead with this Email Address should exist,Обращение с этим адресом электронной почты должно существовать, +"

Default Template

\n

Uses Jinja Templating and all the fields of Address (including Custom Fields if any) will be available

\n
{{ address_line1 }}<br>\n{% if address_line2 %}{{ address_line2 }}<br>{% endif -%}\n{{ city }}<br>\n{% if state %}{{ state }}<br>{% endif -%}\n{% if pincode %} PIN:  {{ pincode }}<br>{% endif -%}\n{{ country }}<br>\n{% if phone %}Phone: {{ phone }}<br>{% endif -%}\n{% if fax %}Fax: {{ fax }}<br>{% endif -%}\n{% if email_id %}Email: {{ email_id }}<br>{% endif -%}\n
","

Шаблон по умолчанию

\n

Используя шаблонизатор Jinja и все поля адреса (включая настраиваемые поля, если таковые имеются) будет доступно

\n
{{ address_line1 }}<br>\n{% if address_line2 %}{{ address_line2 }}<br>{% endif -%}\n{{ city }}<br>\n{% if state %}{{ state }}<br>{% endif -%}\n{% if pincode %} PIN:  {{ pincode }}<br>{% endif -%}\n{{ country }}<br>\n{% if phone %}Телефон: {{ phone }}<br>{% endif -%}\n{% if fax %}Факс: {{ fax }}<br>{% endif -%}\n{% if email_id %}Email: {{ email_id }}<br>{% endif -%}\n
", +A Lead with this Email Address should exist,Лид с этим адресом электронной почты должно существовать, A list of resources which the Client App will have access to after the user allows it.
e.g. project,"Список ресурсов, к которым клиентское приложение будет иметь доступ после того, как пользователь разрешит это.
например. проект", A log of request errors,Журнал ошибок запроса, A new account has been created for you at {0},Новая учетная запись была создана для вас в {0}, @@ -373,12 +373,12 @@ Administrator accessed {0} on {1} via IP Address {2}.,Администратор Advanced,Продвинутый, Advanced Control,Расширенный контроль, Advanced Search,Расширенный поиск, -Align Labels to the Right,Выровнять метки справа, -Align Value,Align значение, +Align Labels to the Right,Выровнять метки по правому краю, +Align Value,Значение выравнивания, All Images attached to Website Slideshow should be public,"Все изображения, прикрепленные к Слайд-шоу веб-сайта, должны быть общедоступными", All customizations will be removed. Please confirm.,"Все настройки будут удалены. Пожалуйста, подтвердите.", -"All possible Workflow States and roles of the workflow. Docstatus Options: 0 is""Saved"", 1 is ""Submitted"" and 2 is ""Cancelled""","Все возможные статусы и роли бизнес-процесса. Варианты статуса документа: 0 — ""Сохранён (черновик)"", 1 — ""Проведён/ Утвержден"" и 2 — ""Отменен""", -All-uppercase is almost as easy to guess as all-lowercase.,"All-прописные почти так же легко догадаться, как все-строчными буквами.", +"All possible Workflow States and roles of the workflow. Docstatus Options: 0 is""Saved"", 1 is ""Submitted"" and 2 is ""Cancelled""","Все возможные статусы и роли бизнес-процесса. Варианты статуса документа: 0 — ""Сохранён"", 1 — ""Проведён/Утвержден"" и 2 — ""Отменен""", +All-uppercase is almost as easy to guess as all-lowercase.,"Все заглавные почти так же легко угадать, как и все строчные.", Allocated To,Выделяемых на, Allow,Разрешить, Allow Bulk Edit,Разрешить массовое редактирование, @@ -415,7 +415,7 @@ Allowed In Mentions,Разрешено в упоминаниях, "Allowing DocType, DocType. Be careful!","Разрешение DocType, DocType. Будьте осторожны!", Already Registered,Уже регистрировались, Also adding the dependent currency field {0},Также добавление зависимого валютного поля {0}, -"Always add ""Draft"" Heading for printing draft documents","Всегда добавляйте заголовок "Черновик" для печати черновых документов", +"Always add ""Draft"" Heading for printing draft documents","Всегда добавлять в заголовок "Черновик" при печати черновых документов", Always use Account's Email Address as Sender,Всегда использовать почту учетной записи в качестве отправителя, Always use Account's Name as Sender's Name,Всегда использовать имя учетной записи в качестве имени отправителя, Amend,Изменен, @@ -470,7 +470,7 @@ Assigned By,Назначаются, Assigned By Full Name,Присваиваемый Полное имя, Assigned By Me,Назначенные мной, Assigned To,Назначено для, -Assigned To/Owner,Назначено / Владельца, +Assigned To/Owner,Назначено для/Владелец, Assignment,Назначение, Assignment Complete,Задание выполнено, Assignment Completed,Задание выполнено, @@ -481,9 +481,9 @@ Assignment closed by {0},Назначение закрыт {0}, Assignment for {0} {1},Назначение для {0} {1}, Atleast one field of Parent Document Type is mandatory,По крайней мере одно поле родительского документа является обязательным, Attach,Прикрепить, -Attach Document Print,Прикрепите документе печать, +Attach Document Print,Прикрепить печатный документ, Attach Image,Прикрепить изображение, -Attach Print,Прикрепите Печать, +Attach Print,Прикрепите печать, Attach Your Picture,Прикрепите свою фотографию, Attach file for Import,Прикрепить файл для импорта, Attach files / urls and add in table.,Прикрепить файлы / URL-адреса и добавить в таблицу., @@ -494,7 +494,7 @@ Attachment Limit (MB),Лимит вложения (MB), Attachment Removed,Вложение удалено, Attempting Connection to QZ Tray...,Попытка подключения к QZ Tray..., Attempting to launch QZ Tray...,Попытка запустить QZ Tray..., -Auth URL Data,Данные URL-адреса Auth, +Auth URL Data,Данные URL-адреса аутентификации, Authenticating...,Проверка подлинности..., Authentication,Аутентификация, Authentication Apps you can use are: ,"Приложения аутентификации, которые вы можете использовать:", @@ -572,7 +572,7 @@ Bulk Update,Массовое обновление, Busy,Занятый, Button,Кнопка, Button Help,Кнопка помощь, -Button Label,Кнопка ярлык, +Button Label,Кнопка метка, Bypass Two Factor Auth for users who login from restricted IP Address,"Обход двух факторов для пользователей, которые подключаются с ограниченным IP-адресом", Bypass restricted IP Address check If Two Factor Auth Enabled,Обход ограниченного IP-адреса. Если включен параметр Two Factor Auth, CC,Копия, @@ -630,7 +630,7 @@ Cent,Цент, "Certain documents, like an Invoice, should not be changed once final. The final state for such documents is called Submitted. You can restrict which roles can Submit.","Некоторые документы, как, например, счета-фактуры, не подлежат изменению, если являются финальными. Конечное состояние для таких документов называется Проведенный. Вы можете ограничить, какие роли имеют право проводить документы.", Chain Integrity,Целостность цепей, Chaining Hash,Цепочный хэш, -Change Label (via Custom Translation),Изменение этикетки (с помощью пользовательского перевода), +Change Label (via Custom Translation),Изменение метки (с помощью пользовательского перевода), Change Password,Изменить пароль, "Change field properties (hide, readonly, permission etc.)","Изменение свойств поля (скрыть, только для чтения, доступ и т.д.)", Channel,Канал, @@ -684,7 +684,7 @@ Collapsible Depends On,Складные Зависит от, Column,Колонка, Column {0} already exist.,Столбец {0} уже существует., Column Break,Разрыв столбца, -Column Labels:,Колонка ярлыки:, +Column Labels:,Колонка меток:, Column Name,Имя столбца, Column Name cannot be empty,Имя столбца не может быть пустым, Columns,Колонки, @@ -789,7 +789,7 @@ Customizations Reset,Сброс настроек, Customizations for {0} exported to:
{1},Настройки для {0} экспортированы в:
{1}, Customize Form,Настроить форму, Customize Form Field,Настроить поля формы, -"Customize Label, Print Hide, Default etc.","Настроить Label, распечатать спрятать, Default т.д.", +"Customize Label, Print Hide, Default etc.","Пользовательские метки, скрыть печать, по умолчанию и т.д.", Customize...,Пользовательские настройки..., "Customized Formats for Printing, Email","Индивидуальные форматы для печати, электронной почты", Customized HTML Templates for printing transactions.,Индивидуальные шаблоны HTML для печатных операций., @@ -1421,9 +1421,9 @@ LDAP Security,LDAP Security, LDAP Server Url,URL cервера LDAP, LDAP Username Field,LDAP Имя пользователя Поле, LDAP is not enabled.,LDAP не включен., -Label Help,Ярлык Помощь, -Label and Type,Ярлык и Тип, -Label is mandatory,Ярлык является обязательным, +Label Help,Метка Помощь, +Label and Type,Метка и Тип, +Label is mandatory,Метка является обязательной, Landing Page,Страница входа, Language,Язык, Language Code,Языковой код, @@ -1796,7 +1796,7 @@ Page to show on the website\n,Страница для показа на сайт Pages in Desk (place holders),Страницы-заглушки, Parent,Родитель, Parent Error Snapshot,Родитель снимка ошибки, -Parent Label,Родительская этикетка, +Parent Label,Родительская метка, Parent Table,Родитель Таблица, Parent is required to get child table data,Родитель обязан получать данные дочерней таблицы, Parent is the name of the document to which the data will get added to.,"Родитель - это имя документа, к которому будут добавлены данные.", @@ -4300,7 +4300,7 @@ Application Version,Версия приложения, Git Branch,Git Branch, Installed Applications,Установленные приложения, Navbar Item,Элемент навигационной панели, -Item Label,Этикетка товара, +Item Label,Метка товара, Item Type,Тип объекта, Separator,Разделитель, Navbar Settings,Настройки навигационной панели, @@ -4434,7 +4434,7 @@ Meta Title,Мета-заголовок, Enable Social Sharing,Включить обмен в социальных сетях, Show CTA in Blog,Показать CTA в блоге, CTA,CTA, -CTA Label,Ярлык CTA, +CTA Label,Метка CTA, CTA URL,CTA URL, Default Portal Home,Главная страница портала по умолчанию, "Example: ""/desk""",Пример: "/ стол", @@ -4521,7 +4521,7 @@ Select Fields,Выбрать поля, Warning: Unable to find {0} in any table related to {1},"Предупреждение: невозможно найти {0} ни в одной таблице, связанной с {1}", Tree view is not available for {0},Просмотр в виде дерева недоступен для {0}, Create Card,Создать карту, -Card Label,Этикетка карты, +Card Label,Метка карты, Reports already in Queue,Отчеты уже в очереди, Proceed Anyway,Все равно продолжайте, Delete and Generate New,Удалить и создать новое, From 2a75b2b48099bdd5a62e51c3567b5c25d3125215 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Fri, 17 Jun 2022 01:04:46 +0300 Subject: [PATCH 009/101] Update ru.csv Fix logic!!! --- frappe/translations/ru.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/translations/ru.csv b/frappe/translations/ru.csv index 96b48ea99c..60e140c2a5 100644 --- a/frappe/translations/ru.csv +++ b/frappe/translations/ru.csv @@ -2023,7 +2023,7 @@ Register OAuth Client App,Регистрация OAuth Client App, Registered but disabled,Зарегистрированный но отключен, Relapsed,Повторный, Relapses,Повторные, -Relink,Перередактируйте, +Relink,Связь, Relink Communication,Повторно связать коммуникации, Relinked,Связать повторно, Reload,Обновить страницу, From ea18460cc29ed159cf3d6731605e28333babc837 Mon Sep 17 00:00:00 2001 From: vishdha Date: Fri, 10 Jun 2022 19:19:05 +0530 Subject: [PATCH 010/101] fix: date_field not able to fetch in _format_naming autoname --- frappe/model/naming.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frappe/model/naming.py b/frappe/model/naming.py index f6a3846699..9fffa4f493 100644 --- a/frappe/model/naming.py +++ b/frappe/model/naming.py @@ -213,7 +213,7 @@ def set_name_from_naming_options(autoname, doc): doc.name = _format_autoname(autoname, doc) elif "#" in autoname: doc.name = make_autoname(autoname, doc=doc) - + return doc.name def set_naming_from_document_naming_rule(doc): """ @@ -317,9 +317,9 @@ def parse_naming_series( part = frappe.defaults.get_user_default("fiscal_year") elif e.startswith("{") and doc: e = e.replace("{", "").replace("}", "") - part = doc.get(e) + part = (cstr(doc.get(e)) or "").strip() elif doc and doc.get(e): - part = doc.get(e) + part = (cstr(doc.get(e)) or "").strip() else: part = e From 27f2cdf0169ca8217093aec01375bcc45f413c23 Mon Sep 17 00:00:00 2001 From: vishdha Date: Fri, 10 Jun 2022 20:33:33 +0530 Subject: [PATCH 011/101] chore: remove unused code --- frappe/model/naming.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/model/naming.py b/frappe/model/naming.py index 9fffa4f493..b674b0cd81 100644 --- a/frappe/model/naming.py +++ b/frappe/model/naming.py @@ -213,7 +213,7 @@ def set_name_from_naming_options(autoname, doc): doc.name = _format_autoname(autoname, doc) elif "#" in autoname: doc.name = make_autoname(autoname, doc=doc) - return doc.name + def set_naming_from_document_naming_rule(doc): """ From a9e222a7066a40586aaff66b7c9aba5ab01a99d5 Mon Sep 17 00:00:00 2001 From: vishdha Date: Fri, 17 Jun 2022 13:59:00 +0530 Subject: [PATCH 012/101] chore: test case added for _auto_name format for date field --- frappe/tests/test_naming.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/frappe/tests/test_naming.py b/frappe/tests/test_naming.py index d966fd5ce8..1a60b41b2b 100644 --- a/frappe/tests/test_naming.py +++ b/frappe/tests/test_naming.py @@ -12,7 +12,7 @@ from frappe.model.naming import ( revert_series_if_last, ) from frappe.tests.utils import FrappeTestCase -from frappe.utils import now_datetime +from frappe.utils import now_datetime, nowdate class TestNaming(FrappeTestCase): @@ -100,6 +100,23 @@ class TestNaming(FrappeTestCase): self.assertEqual(doc.name, f"TODO-{now_datetime().strftime('%m')}-{description}-{series:02}") + def test_format_autoname_for_date_field(self): + """ + Test if braced params are replaced in format autoname for date field + """ + doctype = new_doctype(autoname="format:TODO-{date}-{##}").insert() + + date = nowdate() + + doc = frappe.new_doc(doctype.name) + doc.date = date + doc.insert() + + series = getseries("", 2) + series = int(series) - 1 + + self.assertEqual(doc.name, f"TODO-{date}-{series:02}") + def test_format_autoname_for_consecutive_week_number(self): """ Test if braced params are replaced for consecutive week number in format autoname From 754de9a56b7bc97993c4a3336ecb718115e75880 Mon Sep 17 00:00:00 2001 From: vishdha Date: Fri, 17 Jun 2022 14:03:29 +0530 Subject: [PATCH 013/101] fix: minor change added --- frappe/tests/test_naming.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/tests/test_naming.py b/frappe/tests/test_naming.py index 1a60b41b2b..cb95cd60b3 100644 --- a/frappe/tests/test_naming.py +++ b/frappe/tests/test_naming.py @@ -106,7 +106,7 @@ class TestNaming(FrappeTestCase): """ doctype = new_doctype(autoname="format:TODO-{date}-{##}").insert() - date = nowdate() + date = nowdate() doc = frappe.new_doc(doctype.name) doc.date = date From 2ce6597a692d60b1dd47c22c73499e5876a6d2f3 Mon Sep 17 00:00:00 2001 From: phot0n Date: Fri, 17 Jun 2022 18:47:06 +0530 Subject: [PATCH 014/101] fix: cast list to tuple when sending parameterized query for postgres --- frappe/database/postgres/database.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/frappe/database/postgres/database.py b/frappe/database/postgres/database.py index 14872b2b16..b977184e18 100644 --- a/frappe/database/postgres/database.py +++ b/frappe/database/postgres/database.py @@ -418,10 +418,16 @@ def modify_values(values): if isinstance(values, dict): for k, v in values.items(): + if isinstance(v, list): + v = tuple(v) + values[k] = stringify_value(v) elif isinstance(values, (tuple, list)): new_values = [] for val in values: + if isinstance(val, list): + val = tuple(val) + new_values.append(stringify_value(val)) values = new_values else: From 80de4349848be66cbbde9d4a78d72e52205db09c Mon Sep 17 00:00:00 2001 From: vishdha Date: Fri, 17 Jun 2022 20:07:14 +0530 Subject: [PATCH 015/101] chore: Test case added for datetime, date and time field --- frappe/tests/test_naming.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/frappe/tests/test_naming.py b/frappe/tests/test_naming.py index cb95cd60b3..f4cc28daef 100644 --- a/frappe/tests/test_naming.py +++ b/frappe/tests/test_naming.py @@ -12,7 +12,7 @@ from frappe.model.naming import ( revert_series_if_last, ) from frappe.tests.utils import FrappeTestCase -from frappe.utils import now_datetime, nowdate +from frappe.utils import now_datetime, nowdate, nowtime class TestNaming(FrappeTestCase): @@ -100,22 +100,26 @@ class TestNaming(FrappeTestCase): self.assertEqual(doc.name, f"TODO-{now_datetime().strftime('%m')}-{description}-{series:02}") - def test_format_autoname_for_date_field(self): + def test_format_autoname_for_datetime_field(self): """ - Test if braced params are replaced in format autoname for date field + Test if braced params are replaced in format autoname for datetime, date and time field """ - doctype = new_doctype(autoname="format:TODO-{date}-{##}").insert() + datetime = now_datetime() date = nowdate() + time = nowtime() - doc = frappe.new_doc(doctype.name) - doc.date = date - doc.insert() + for field in [datetime, date, time]: + doctype = new_doctype(autoname="format:TODO-{field}-{##}").insert() - series = getseries("", 2) - series = int(series) - 1 + doc = frappe.new_doc(doctype.name) + doc.field = field + doc.insert() - self.assertEqual(doc.name, f"TODO-{date}-{series:02}") + series = getseries("", 2) + series = int(series) - 1 + + self.assertEqual(doc.name, f"TODO-{field}-{series:02}") def test_format_autoname_for_consecutive_week_number(self): """ From f6c1eb10dd3e0c7cd8a5c11292d4564e4cb46e92 Mon Sep 17 00:00:00 2001 From: phot0n Date: Sat, 18 Jun 2022 10:11:58 +0530 Subject: [PATCH 016/101] refactor(minor): modify_values * don't truncate float(s) --- frappe/database/postgres/database.py | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/frappe/database/postgres/database.py b/frappe/database/postgres/database.py index b977184e18..f9a4723d72 100644 --- a/frappe/database/postgres/database.py +++ b/frappe/database/postgres/database.py @@ -403,13 +403,12 @@ def modify_query(query): def modify_values(values): - def stringify_value(value): - if isinstance(value, int): + def modify_value(value): + if isinstance(value, (list, tuple)): + value = tuple(modify_values(value)) + + elif isinstance(value, int): value = str(value) - elif isinstance(value, float): - truncated_float = int(value) - if value == truncated_float: - value = str(truncated_float) return value @@ -418,20 +417,15 @@ def modify_values(values): if isinstance(values, dict): for k, v in values.items(): - if isinstance(v, list): - v = tuple(v) - - values[k] = stringify_value(v) + values[k] = modify_value(v) elif isinstance(values, (tuple, list)): new_values = [] for val in values: - if isinstance(val, list): - val = tuple(val) + new_values.append(modify_value(val)) - new_values.append(stringify_value(val)) values = new_values else: - values = stringify_value(values) + values = modify_value(values) return values From 215507a742b5cbc0626324a416a5b18ede804dbf Mon Sep 17 00:00:00 2001 From: phot0n Date: Sat, 18 Jun 2022 10:45:40 +0530 Subject: [PATCH 017/101] test: add list value in test_modify_values --- frappe/tests/test_db.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/frappe/tests/test_db.py b/frappe/tests/test_db.py index 73b5446404..31fccd0132 100644 --- a/frappe/tests/test_db.py +++ b/frappe/tests/test_db.py @@ -834,10 +834,13 @@ class TestDDLCommandsPost(unittest.TestCase): from frappe.database.postgres.database import modify_values self.assertEqual( - {"abcd": "23", "efgh": "23", "ijkl": 23.0345, "mnop": "wow"}, - modify_values({"abcd": 23, "efgh": 23.0, "ijkl": 23.0345, "mnop": "wow"}), + {"a": "23", "b": 23.0, "c": 23.0345, "d": "wow", "e": ("1", "2", "3", "abc")}, + modify_values({"a": 23, "b": 23.0, "c": 23.0345, "d": "wow", "e": [1, 2, 3, "abc"]}), + ) + self.assertEqual( + ["23", 23.0, 23.00004345, "wow", ("1", "2", "3", "abc")], + modify_values((23, 23.0, 23.00004345, "wow", [1, 2, 3, "abc"])), ) - self.assertEqual(["23", "23", 23.00004345, "wow"], modify_values((23, 23.0, 23.00004345, "wow"))) def test_sequence_table_creation(self): from frappe.core.doctype.doctype.test_doctype import new_doctype From 5e1007940c8dea64823ebe9a69b8c0ffc37e4ac9 Mon Sep 17 00:00:00 2001 From: phot0n Date: Sat, 18 Jun 2022 10:53:43 +0530 Subject: [PATCH 018/101] refactor(minor): move test_modify_query and test_modify_values to TestDB class --- frappe/tests/test_db.py | 60 +++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/frappe/tests/test_db.py b/frappe/tests/test_db.py index 31fccd0132..69f7a7d5aa 100644 --- a/frappe/tests/test_db.py +++ b/frappe/tests/test_db.py @@ -511,6 +511,37 @@ class TestDB(unittest.TestCase): frappe.db.rollback() + @run_only_if(db_type_is.POSTGRES) + def test_modify_query(self): + from frappe.database.postgres.database import modify_query + + query = "select * from `tabtree b` where lft > 13 and rgt <= 16 and name =1.0 and parent = 4134qrsdc and isgroup = 1.00045" + self.assertEqual( + "select * from \"tabtree b\" where lft > '13' and rgt <= '16' and name = '1' and parent = 4134qrsdc and isgroup = 1.00045", + modify_query(query), + ) + + query = ( + 'select locate(".io", "frappe.io"), locate("3", cast(3 as varchar)), locate("3", 3::varchar)' + ) + self.assertEqual( + 'select strpos( "frappe.io", ".io"), strpos( cast(3 as varchar), "3"), strpos( 3::varchar, "3")', + modify_query(query), + ) + + @run_only_if(db_type_is.POSTGRES) + def test_modify_values(self): + from frappe.database.postgres.database import modify_values + + self.assertEqual( + {"a": "23", "b": 23.0, "c": 23.0345, "d": "wow", "e": ("1", "2", "3", "abc")}, + modify_values({"a": 23, "b": 23.0, "c": 23.0345, "d": "wow", "e": [1, 2, 3, "abc"]}), + ) + self.assertEqual( + ["23", 23.0, 23.00004345, "wow", ("1", "2", "3", "abc")], + modify_values((23, 23.0, 23.00004345, "wow", [1, 2, 3, "abc"])), + ) + @run_only_if(db_type_is.MARIADB) class TestDDLCommandsMaria(unittest.TestCase): @@ -813,35 +844,6 @@ class TestDDLCommandsPost(unittest.TestCase): ) self.assertEqual(len(indexs_in_table), 1) - def test_modify_query(self): - from frappe.database.postgres.database import modify_query - - query = "select * from `tabtree b` where lft > 13 and rgt <= 16 and name =1.0 and parent = 4134qrsdc and isgroup = 1.00045" - self.assertEqual( - "select * from \"tabtree b\" where lft > '13' and rgt <= '16' and name = '1' and parent = 4134qrsdc and isgroup = 1.00045", - modify_query(query), - ) - - query = ( - 'select locate(".io", "frappe.io"), locate("3", cast(3 as varchar)), locate("3", 3::varchar)' - ) - self.assertEqual( - 'select strpos( "frappe.io", ".io"), strpos( cast(3 as varchar), "3"), strpos( 3::varchar, "3")', - modify_query(query), - ) - - def test_modify_values(self): - from frappe.database.postgres.database import modify_values - - self.assertEqual( - {"a": "23", "b": 23.0, "c": 23.0345, "d": "wow", "e": ("1", "2", "3", "abc")}, - modify_values({"a": 23, "b": 23.0, "c": 23.0345, "d": "wow", "e": [1, 2, 3, "abc"]}), - ) - self.assertEqual( - ["23", 23.0, 23.00004345, "wow", ("1", "2", "3", "abc")], - modify_values((23, 23.0, 23.00004345, "wow", [1, 2, 3, "abc"])), - ) - def test_sequence_table_creation(self): from frappe.core.doctype.doctype.test_doctype import new_doctype From 69cb144b06f11edcc7fbb32208d13816c4e6c378 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 20 Jun 2022 20:05:25 +0530 Subject: [PATCH 019/101] refactor!: move plyr from default bundle --- frappe/public/js/desk.bundle.js | 1 - frappe/public/js/frappe/utils/help.js | 13 ++++++++----- frappe/public/js/frappe/utils/utils.js | 4 ++++ .../public/js/frappe/widgets/onboarding_widget.js | 2 +- .../{frappe/ui/plyr.js => video_player.bundle.js} | 2 +- frappe/tests/test_commands.py | 2 +- 6 files changed, 15 insertions(+), 9 deletions(-) rename frappe/public/js/{frappe/ui/plyr.js => video_player.bundle.js} (70%) diff --git a/frappe/public/js/desk.bundle.js b/frappe/public/js/desk.bundle.js index e056a34be2..89270bad3f 100644 --- a/frappe/public/js/desk.bundle.js +++ b/frappe/public/js/desk.bundle.js @@ -107,6 +107,5 @@ import "./frappe/utils/dashboard_utils.js"; import "./frappe/ui/chart.js"; import "./frappe/ui/datatable.js"; import "./frappe/ui/driver.js"; -import "./frappe/ui/plyr.js"; import "./frappe/barcode_scanner/index.js"; import "./frappe/scanner"; diff --git a/frappe/public/js/frappe/utils/help.js b/frappe/public/js/frappe/utils/help.js index 9b8149e20e..56109c7701 100644 --- a/frappe/public/js/frappe/utils/help.js +++ b/frappe/public/js/frappe/utils/help.js @@ -33,13 +33,16 @@ frappe.help.show_video = function (youtube_id, title) { dialog.show(); dialog.$wrapper.addClass("video-modal"); - let plyr = new frappe.Plyr(video[0], { - hideControls: true, - resetOnEnd: true, - }); + let plyr; + frappe.utils.load_video_player().then(() => { + plyr = new frappe.Plyr(video[0], { + hideControls: true, + resetOnEnd: true, + }); + }) dialog.onhide = () => { - plyr.destroy(); + plyr?.destroy(); }; } diff --git a/frappe/public/js/frappe/utils/utils.js b/frappe/public/js/frappe/utils/utils.js index aa305a9ce7..74c89aa01a 100644 --- a/frappe/public/js/frappe/utils/utils.js +++ b/frappe/public/js/frappe/utils/utils.js @@ -1528,5 +1528,9 @@ Object.assign(frappe.utils, { return [doctype, filter, val[0], val[1], false]; }); } + }, + + load_video_player() { + return frappe.require("video_player.bundle.js"); } }); diff --git a/frappe/public/js/frappe/widgets/onboarding_widget.js b/frappe/public/js/frappe/widgets/onboarding_widget.js index e560551f79..5c3b996bb1 100644 --- a/frappe/public/js/frappe/widgets/onboarding_widget.js +++ b/frappe/public/js/frappe/widgets/onboarding_widget.js @@ -5,6 +5,7 @@ frappe.provide("frappe.utils"); export default class OnboardingWidget extends Widget { async refresh() { + frappe.utils.load_video_player(); this.new && await this.get_onboarding_data(); this.set_title(); this.set_actions(); @@ -156,7 +157,6 @@ export default class OnboardingWidget extends Widget { }; toggle_content(); - // toggle_video(); } go_to_page(step) { diff --git a/frappe/public/js/frappe/ui/plyr.js b/frappe/public/js/video_player.bundle.js similarity index 70% rename from frappe/public/js/frappe/ui/plyr.js rename to frappe/public/js/video_player.bundle.js index 97b36837f9..14e2d754bd 100644 --- a/frappe/public/js/frappe/ui/plyr.js +++ b/frappe/public/js/video_player.bundle.js @@ -1,3 +1,3 @@ import Plyr from "plyr/dist/plyr.polyfilled"; -frappe.Plyr = Plyr; \ No newline at end of file +frappe.Plyr = Plyr; diff --git a/frappe/tests/test_commands.py b/frappe/tests/test_commands.py index 16fea9155d..aa00a884e1 100644 --- a/frappe/tests/test_commands.py +++ b/frappe/tests/test_commands.py @@ -699,7 +699,7 @@ class TestBenchBuild(BaseTestCommands): self.assertEqual(result.exit_code, 0) self.assertEqual(result.exception, None) - CURRENT_SIZE = 3.7 # MB + CURRENT_SIZE = 3.5 # MB JS_ASSET_THRESHOLD = 0.1 hooks = frappe.get_hooks() From 9c5d6feec131a8bf24b6aeec55a07ce7524dec64 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 21 Jun 2022 13:30:39 +0530 Subject: [PATCH 020/101] test(cypress): show full response on insert_doc failure (#17257) --- cypress/support/commands.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cypress/support/commands.js b/cypress/support/commands.js index c168b0c201..b3708a1dba 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -313,7 +313,12 @@ Cypress.Commands.add('insert_doc', (doctype, args, ignore_duplicate) => { if (ignore_duplicate) { status_codes.push(409); } - expect(res.status).to.be.oneOf(status_codes); + + let message = null; + if (ignore_duplicate && !status_codes.includes(res.status)) { + message = `Document insert failed, response: ${JSON.stringify(res, null, '\t')}`; + } + expect(res.status).to.be.oneOf(status_codes, message); return res.body.data; }); }); From ef3777badb5cccfed06005c537221e5a0bb1eb60 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Tue, 21 Jun 2022 16:22:22 +0200 Subject: [PATCH 021/101] test: refactor date naming test --- frappe/tests/test_naming.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/frappe/tests/test_naming.py b/frappe/tests/test_naming.py index f4cc28daef..305df66209 100644 --- a/frappe/tests/test_naming.py +++ b/frappe/tests/test_naming.py @@ -101,17 +101,10 @@ class TestNaming(FrappeTestCase): self.assertEqual(doc.name, f"TODO-{now_datetime().strftime('%m')}-{description}-{series:02}") def test_format_autoname_for_datetime_field(self): - """ - Test if braced params are replaced in format autoname for datetime, date and time field - """ - - datetime = now_datetime() - date = nowdate() - time = nowtime() - - for field in [datetime, date, time]: - doctype = new_doctype(autoname="format:TODO-{field}-{##}").insert() + """Test if datetime, date and time objects get converted to strings for naming.""" + doctype = new_doctype(autoname="format:TODO-{field}-{##}").insert() + for field in [now_datetime(), nowdate(), nowtime()]: doc = frappe.new_doc(doctype.name) doc.field = field doc.insert() From 891a2c7d5b45c61d70a4539eacb9e73dc5b20022 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Tue, 21 Jun 2022 20:03:00 +0530 Subject: [PATCH 022/101] feat(PageBuilder): Section IDs Set IDs on sections so that you can link to them using anchor tags --- frappe/templates/includes/navbar/navbar_items.html | 6 ++++-- frappe/templates/includes/web_block.html | 4 +++- .../website/doctype/web_page_block/web_page_block.json | 9 ++++++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/frappe/templates/includes/navbar/navbar_items.html b/frappe/templates/includes/navbar/navbar_items.html index dbc086f1f4..309027be09 100644 --- a/frappe/templates/includes/navbar/navbar_items.html +++ b/frappe/templates/includes/navbar/navbar_items.html @@ -33,14 +33,16 @@ {% else %} {% if parent %} +{% set url = item.url or '' %} +{% set url = url if url.startswith('#') else url | abs_url %} {% else %} - {{ _(item.label) }} diff --git a/frappe/templates/includes/web_block.html b/frappe/templates/includes/web_block.html index c8b22b3551..1215df63cb 100644 --- a/frappe/templates/includes/web_block.html +++ b/frappe/templates/includes/web_block.html @@ -11,7 +11,9 @@ {%- if web_template_type == 'Section' -%} {%- if not web_block.hide_block -%} -
Date: Tue, 21 Jun 2022 20:07:59 +0530 Subject: [PATCH 023/101] fix: App logo not set in website settings (#17261) * fix: App logo not set in website settings * chore: potential error in system settings --- frappe/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index 1cf3526b45..ee199c8aed 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -2231,14 +2231,14 @@ def get_website_settings(key): if not hasattr(local, "website_settings"): local.website_settings = db.get_singles_dict("Website Settings", cast=True) - return local.website_settings[key] + return local.website_settings.get(key) def get_system_settings(key): if not hasattr(local, "system_settings"): local.system_settings = db.get_singles_dict("System Settings", cast=True) - return local.system_settings[key] + return local.system_settings.get(key) def get_active_domains(): From e63e26890ce5cfa10acaf4dba20c2001a0842d96 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 21 Jun 2022 19:52:06 +0530 Subject: [PATCH 024/101] fix: show "doc modifed after" load message --- cypress/integration/form.js | 16 +++++++++++++++ cypress/support/commands.js | 28 ++++++++++++++++++++++++++ frappe/public/js/frappe/form/form.js | 6 ++---- frappe/public/js/frappe/model/model.js | 2 +- 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/cypress/integration/form.js b/cypress/integration/form.js index 99a4336bcb..4d50a5f66a 100644 --- a/cypress/integration/form.js +++ b/cypress/integration/form.js @@ -78,4 +78,20 @@ context('Form', () => { cy.get('@row2').click(); cy.get('@email_input2').should('not.have.class', 'invalid'); }); + + it('Shows version conflict warning', { scrollBehavior: false }, () => { + cy.visit('/app/todo'); + + cy.insert_doc("ToDo", {"description": "old"}).then(doc => { + cy.visit(`/app/todo/${doc.name}`); + // make form dirty + cy.fill_field("status", "Cancelled", "Select"); + + // update doc using api - simulating parallel change by another user + cy.update_doc("ToDo", doc.name, {"status": "Closed"}).then(() => { + cy.findByRole("button", {name: "Refresh"}).click(); + cy.get_field("status", "Select").should("have.value", "Closed"); + }) + }) + }); }); diff --git a/cypress/support/commands.js b/cypress/support/commands.js index b3708a1dba..5ee26348e2 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -291,7 +291,11 @@ Cypress.Commands.add('clear_datepickers', () => { cy.get('.datepicker').should('not.exist'); }); + Cypress.Commands.add('insert_doc', (doctype, args, ignore_duplicate) => { + if (!args.doctype) { + args.doctype = doctype; + } return cy .window() .its('frappe.csrf_token') @@ -324,6 +328,30 @@ Cypress.Commands.add('insert_doc', (doctype, args, ignore_duplicate) => { }); }); +Cypress.Commands.add('update_doc', (doctype, docname, args) => { + return cy + .window() + .its('frappe.csrf_token') + .then(csrf_token => { + return cy + .request({ + method: 'PUT', + url: `/api/resource/${doctype}/${docname}`, + body: args, + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + 'X-Frappe-CSRF-Token': csrf_token + }, + }) + .then(res => { + expect(res.status).to.eq(200); + return res.body.data; + }); + }); +}); + + Cypress.Commands.add('open_list_filter', () => { cy.get('.filter-section .filter-button').click(); cy.wait(300); diff --git a/frappe/public/js/frappe/form/form.js b/frappe/public/js/frappe/form/form.js index 13d61d689b..148ec7ca86 100644 --- a/frappe/public/js/frappe/form/form.js +++ b/frappe/public/js/frappe/form/form.js @@ -506,8 +506,6 @@ frappe.ui.form.Form = class FrappeForm { } initialize_new_doc() { - // moved this call to refresh function - // this.check_doctype_conflict(docname); var me = this; // hide any open grid @@ -1024,8 +1022,8 @@ frappe.ui.form.Form = class FrappeForm { if(this.doc.__unsaved) { this.dashboard.clear_headline(); this.dashboard.set_headline_alert(__("This form has been modified after you have loaded it") - + '' - + __("Refresh") + '', "alert-warning"); + + '', "alert-warning"); } else { this.reload_doc(); } diff --git a/frappe/public/js/frappe/model/model.js b/frappe/public/js/frappe/model/model.js index 4b6ee31b71..32ba1d89c2 100644 --- a/frappe/public/js/frappe/model/model.js +++ b/frappe/public/js/frappe/model/model.js @@ -54,7 +54,7 @@ $.extend(frappe.model, { if(frappe.get_route()[0]==="Form" && cur_frm.doc.doctype===doc.doctype && cur_frm.doc.name===doc.name) { if(!frappe.ui.form.is_saving && data.modified!=cur_frm.doc.modified) { doc.__needs_refresh = true; - cur_frm.check_doctype_conflict(); + cur_frm.show_conflict_message(); } } else { if(!doc.__unsaved) { From 8814041b3316754dc58f0c6dcc251d576cb38a04 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Tue, 21 Jun 2022 20:42:14 +0530 Subject: [PATCH 025/101] fix: set web-template attr in script and style tags from web templates Also, deduplication of styles and scripts when web_blocks jinja method is used --- frappe/utils/jinja_globals.py | 18 ++++++++-- .../doctype/web_page/templates/web_page.html | 23 +++++++++---- frappe/website/doctype/web_page/web_page.py | 34 +++++++++++++------ 3 files changed, 55 insertions(+), 20 deletions(-) diff --git a/frappe/utils/jinja_globals.py b/frappe/utils/jinja_globals.py index ae0523b82c..649a4c296f 100644 --- a/frappe/utils/jinja_globals.py +++ b/frappe/utils/jinja_globals.py @@ -36,6 +36,7 @@ def web_block(template, values=None, **kwargs): def web_blocks(blocks): + import frappe from frappe import _, _dict, throw from frappe.website.doctype.web_page.web_page import get_web_blocks_html @@ -62,8 +63,21 @@ def web_blocks(blocks): out = get_web_blocks_html(web_blocks) html = out.html - for script in out.scripts: - html += "".format(script) + for template, scripts in out.scripts.items(): + # deduplication of scripts when web_blocks methods are used in web pages + # see render_dynamic method web_page.py + if template not in frappe.flags.web_block_scripts: + for script in scripts: + html += f"" + frappe.flags.web_block_scripts[template] = True + + for template, styles in out.styles.items(): + # deduplication of styles when web_blocks methods are used in web pages + # see render_dynamic method web_page.py + if template not in frappe.flags.web_block_styles: + for style in styles: + html += f"" + frappe.flags.web_block_styles[template] = True return html diff --git a/frappe/website/doctype/web_page/templates/web_page.html b/frappe/website/doctype/web_page/templates/web_page.html index 384eb1f91a..c8679345c1 100644 --- a/frappe/website/doctype/web_page/templates/web_page.html +++ b/frappe/website/doctype/web_page/templates/web_page.html @@ -33,13 +33,18 @@ {% endblock %} {% block style %} - - -{%- for style in page_builder_styles -%} +{%- if style -%} +{%- endif -%} + +{%- for web_template, styles in (page_builder_styles or {}).items() -%} +{%- if styles -%} +{%- for style in styles -%} + {%- endfor -%} +{%- endif -%} +{%- endfor -%} + {% endblock %} {% block script %} @@ -47,7 +52,11 @@ {%- endif -%} - {%- for script in page_builder_scripts -%} - + {%- for web_template, scripts in (page_builder_scripts or {}).items() -%} + {%- if scripts -%} + {%- for script in scripts -%} + + {%- endfor -%} + {%- endif -%} {%- endfor -%} {% endblock %} diff --git a/frappe/website/doctype/web_page/web_page.py b/frappe/website/doctype/web_page/web_page.py index f74af1d8c7..98ecd163e6 100644 --- a/frappe/website/doctype/web_page/web_page.py +++ b/frappe/website/doctype/web_page/web_page.py @@ -77,15 +77,23 @@ class WebPage(WebsiteGenerator): def render_dynamic(self, context): # dynamic - is_jinja = context.dynamic_template or "" in context.main_section - if is_jinja or ("{{" in context.main_section): + is_jinja = ( + context.dynamic_template + or "" in context.main_section + or ("{{" in context.main_section) + ) + if is_jinja: + frappe.flags.web_block_scripts = {} + frappe.flags.web_block_styles = {} try: context["main_section"] = render_template(context.main_section, context) if not "" in context.main_section: context["no_cache"] = 1 except TemplateSyntaxError: - if is_jinja: - raise + raise + finally: + frappe.flags.web_block_scripts = {} + frappe.flags.web_block_styles = {} def set_breadcrumbs(self, context): """Build breadcrumbs template""" @@ -191,9 +199,9 @@ def check_publish_status(): def get_web_blocks_html(blocks): """Converts a list of blocks into Raw HTML and extracts out their scripts for deduplication""" - out = frappe._dict(html="", scripts=[], styles=[]) - extracted_scripts = [] - extracted_styles = [] + out = frappe._dict(html="", scripts={}, styles={}) + extracted_scripts = {} + extracted_styles = {} for block in blocks: web_template = frappe.get_cached_doc("Web Template", block.web_template) rendered_html = frappe.render_template( @@ -207,11 +215,15 @@ def get_web_blocks_html(blocks): html, scripts, styles = extract_script_and_style_tags(rendered_html) out.html += html if block.web_template not in extracted_scripts: - out.scripts += scripts - extracted_scripts.append(block.web_template) + extracted_scripts.setdefault(block.web_template, []) + extracted_scripts[block.web_template] += scripts + if block.web_template not in extracted_styles: - out.styles += styles - extracted_styles.append(block.web_template) + extracted_styles.setdefault(block.web_template, []) + extracted_styles[block.web_template] += styles + + out.scripts = extracted_scripts + out.styles = extracted_styles return out From c6d5c6bbe2d5c9f1448b45e2b7e7e2de6ec9e195 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 21 Jun 2022 21:12:38 +0530 Subject: [PATCH 026/101] fix: Migration failures for version-13 to develop --- frappe/core/doctype/doctype/doctype.py | 2 +- frappe/patches.txt | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index e834b698d5..0d46a2b746 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -1298,7 +1298,7 @@ def validate_fields(meta): frappe.throw(_("Is Published Field must be a valid fieldname"), InvalidFieldNameError) def check_website_search_field(meta): - if not meta.website_search_field: + if not meta.get("website_search_field"): return if meta.website_search_field not in fieldname_list: diff --git a/frappe/patches.txt b/frappe/patches.txt index 66422c7db0..40b5a4c881 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -121,7 +121,7 @@ execute:frappe.delete_doc_if_exists('DocType', 'GCalendar Settings') frappe.patches.v12_0.remove_example_email_thread_notify execute:from frappe.desk.page.setup_wizard.install_fixtures import update_genders;update_genders() frappe.patches.v12_0.set_correct_url_in_files -execute:frappe.reload_doc('core', 'doctype', 'doctype') +execute:frappe.reload_doc('core', 'doctype', 'doctype') #2022-06-21 execute:frappe.reload_doc('custom', 'doctype', 'property_setter') frappe.patches.v13_0.remove_invalid_options_for_data_fields frappe.patches.v13_0.website_theme_custom_scss @@ -184,6 +184,7 @@ frappe.patches.v13_0.jinja_hook frappe.patches.v13_0.update_notification_channel_if_empty frappe.patches.v13_0.set_first_day_of_the_week execute:frappe.reload_doc('custom', 'doctype', 'custom_field') +execute:frappe.reload_doc('desk', 'doctype', 'workspace_quick_list') frappe.patches.v14_0.update_workspace2 # 20.09.2021 frappe.patches.v14_0.save_ratings_in_fraction #23-12-2021 frappe.patches.v14_0.transform_todo_schema From 23cad5480203015af3f5f4fc442c16e8bf802969 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Tue, 21 Jun 2022 21:23:39 +0530 Subject: [PATCH 027/101] test(oauth): Send id_token of the authorized user instead of Guest This only affects OAuth clients that use `id_token` obtained from `frappe.integrations.oauth2.get_token`. Doesn't affect OAuth clients that ignore id_token and explicitly use `frappe.integrations.oauth2.openid_profile` endpoint for getting user details. e.g. Frappe OAuth client. A simple way to replicate this is to setup Frappe-Frappe OAuth client-server pair and use `login_via_oauth2_id_token` instead of `login_via_oauth2` in `login_via_frappe`. --- frappe/tests/test_oauth20.py | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/frappe/tests/test_oauth20.py b/frappe/tests/test_oauth20.py index b809630204..a634ace62a 100644 --- a/frappe/tests/test_oauth20.py +++ b/frappe/tests/test_oauth20.py @@ -16,7 +16,9 @@ class TestOAuth20(unittest.TestCase): def setUp(self): make_test_records("OAuth Client") make_test_records("User") - self.client_id = frappe.get_all("OAuth Client", fields=["*"])[0].get("client_id") + client = frappe.get_all("OAuth Client", fields=["*"])[0] + self.client_id = client.get("client_id") + self.client_secret = client.get("client_secret") self.form_header = {"content-type": "application/x-www-form-urlencoded"} self.scope = "all openid" self.redirect_uri = "http://localhost" @@ -90,6 +92,9 @@ class TestOAuth20(unittest.TestCase): self.assertTrue(bearer_token.get("token_type") == "Bearer") self.assertTrue(check_valid_openid_response(bearer_token.get("access_token"))) + decoded_token = self.decode_id_token(bearer_token.get("id_token")) + self.assertEqual(decoded_token["email"], "test@example.com") + def test_login_using_authorization_code_with_pkce(self): update_client_for_auth_code_grant(self.client_id) @@ -142,6 +147,9 @@ class TestOAuth20(unittest.TestCase): self.assertTrue(bearer_token.get("access_token")) self.assertTrue(bearer_token.get("id_token")) + decoded_token = self.decode_id_token(bearer_token.get("id_token")) + self.assertEqual(decoded_token["email"], "test@example.com") + def test_revoke_token(self): client = frappe.get_doc("OAuth Client", self.client_id) client.grant_type = "Authorization Code" @@ -316,16 +324,19 @@ class TestOAuth20(unittest.TestCase): # Parse bearer token json bearer_token = token_response.json() - id_token = bearer_token.get("id_token") - payload = jwt.decode( - id_token, - audience=client.client_id, - key=client.client_secret, - algorithms=["HS256"], - ) + payload = self.decode_id_token(bearer_token.get("id_token")) + self.assertEqual(payload["email"], "test@example.com") self.assertTrue(payload.get("nonce") == nonce) + def decode_id_token(self, id_token): + return jwt.decode( + id_token, + audience=self.client_id, + key=self.client_secret, + algorithms=["HS256"], + ) + def check_valid_openid_response(access_token=None): """Return True for valid response.""" From 93320ce6e7f2f40550418c67b47953260cea8a5c Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Tue, 21 Jun 2022 21:52:22 +0530 Subject: [PATCH 028/101] fix(oauth): Send id_token of the authorized user instead of Guest This only affects OAuth clients that use `id_token` obtained from `frappe.integrations.oauth2.get_token`. Doesn't affect OAuth clients that ignore id_token and explicitly use `frappe.integrations.oauth2.openid_profile` endpoint for getting user details. e.g. Frappe OAuth client. A simple way to replicate this is to setup Frappe-Frappe OAuth client-server pair and use `login_via_oauth2_id_token` instead of `login_via_oauth2` in `login_via_frappe`. --- frappe/oauth.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/frappe/oauth.py b/frappe/oauth.py index e7fa101bfd..68e21ac88b 100644 --- a/frappe/oauth.py +++ b/frappe/oauth.py @@ -323,10 +323,7 @@ class OAuthWebRequestValidator(RequestValidator): # Check whether frappe server URL is set id_token_header = {"typ": "jwt", "alg": "HS256"} - user = frappe.get_doc( - "User", - frappe.session.user, - ) + user = frappe.get_doc("User", request.user) if request.nonce: id_token["nonce"] = request.nonce From d49f9bfb8fc2651fd6bf6a4c3e93018988d68499 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Wed, 22 Jun 2022 12:04:57 +0530 Subject: [PATCH 029/101] fix: handle case where web_block is invoked from places other than web page --- frappe/utils/jinja_globals.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frappe/utils/jinja_globals.py b/frappe/utils/jinja_globals.py index 649a4c296f..44835be352 100644 --- a/frappe/utils/jinja_globals.py +++ b/frappe/utils/jinja_globals.py @@ -63,6 +63,11 @@ def web_blocks(blocks): out = get_web_blocks_html(web_blocks) html = out.html + + if not frappe.flags.web_block_scripts: + frappe.flags.web_block_scripts = {} + frappe.flags.web_block_styles = {} + for template, scripts in out.scripts.items(): # deduplication of scripts when web_blocks methods are used in web pages # see render_dynamic method web_page.py From c6d8f3bc7f1772e8d8eb3767436882ab172def91 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Wed, 22 Jun 2022 06:43:35 +0000 Subject: [PATCH 030/101] fix: dont clear `_meta` when caching doc (#17115) fix: dont clear meta when caching doc --- frappe/model/base_document.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/frappe/model/base_document.py b/frappe/model/base_document.py index d3cc662d52..8e417bb45c 100644 --- a/frappe/model/base_document.py +++ b/frappe/model/base_document.py @@ -123,8 +123,23 @@ class BaseDocument(object): return meta def __getstate__(self): - self._meta = None - return self.__dict__ + """ + Called when pickling. + Returns a copy of `__dict__` excluding unpicklable values like `_meta`. + + More info: https://docs.python.org/3/library/pickle.html#handling-stateful-objects + """ + + # Always use the dict.copy() method to avoid modifying the original state + state = self.__dict__.copy() + self.remove_unpicklable_values(state) + + return state + + def remove_unpicklable_values(self, state): + """Remove unpicklable values before pickling""" + + state.pop("_meta", None) def update(self, d): """Update multiple fields of a doctype using a dictionary of key-value pairs. From fd4a7031b976cb4d40b63b4c096d5a3798b144b5 Mon Sep 17 00:00:00 2001 From: Jannat Patel <31363128+pateljannat@users.noreply.github.com> Date: Wed, 22 Jun 2022 13:23:15 +0530 Subject: [PATCH 031/101] fix: added mailto to email displayed on contact us page (#17269) --- frappe/www/contact.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frappe/www/contact.html b/frappe/www/contact.html index 91f14985b2..a6672d63d2 100644 --- a/frappe/www/contact.html +++ b/frappe/www/contact.html @@ -67,7 +67,11 @@ {{ phone }}
{% endif %} {% if email_id %} - {{ email_id }}
+ + + {{ email_id }} + +
{% endif %} {% if skype %} {{ skype }}
From 593fd0a1780dafbf06c20ee845937ce9cdc1a38b Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Mon, 20 Jun 2022 17:00:30 +0530 Subject: [PATCH 032/101] ci: Add audit for python dependencies via pip-audit --- .github/workflows/deps-checker.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/workflows/deps-checker.yml diff --git a/.github/workflows/deps-checker.yml b/.github/workflows/deps-checker.yml new file mode 100644 index 0000000000..3f81b5c633 --- /dev/null +++ b/.github/workflows/deps-checker.yml @@ -0,0 +1,22 @@ +name: 'Python Dependency Check' +on: + pull_request: + workflow_dispatch: + push: + branches: [ develop ] + +permissions: + contents: read + +jobs: + deps-vulnerable-check: + name: 'Vulnerable Dependency' + runs-on: ubuntu-latest + + steps: + - uses: actions/setup-python@v4 + with: + python-version: 3.8 + - uses: actions/checkout@v3 + - run: pip install pip-audit + - run: pip-audit ${GITHUB_WORKSPACE} From 71531bd2906d34b53973ae6db6667f0b470fb0c4 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Tue, 21 Jun 2022 11:33:07 +0530 Subject: [PATCH 033/101] chore(deps): Bump PyJWT from 2.0.1 to 2.4.0 Consists of security & bug fixes, and seemingly no breaking changes Ref: https://pyjwt.readthedocs.io/en/stable/changelog.html --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 81be41c480..89be81eaf0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,7 @@ dependencies = [ "GitPython~=3.1.14", "Jinja2~=3.1.2", "Pillow~=9.1.1", - "PyJWT~=2.0.1", + "PyJWT~=2.4.0", "PyMySQL~=1.0.2", "PyPDF2~=2.1.0", "PyPika~=0.48.9", From 9737bb39fa25a7ba5f15d2f824ee66afd21381a3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Jun 2022 10:45:05 +0000 Subject: [PATCH 034/101] build(deps): bump shell-quote from 1.7.2 to 1.7.3 Bumps [shell-quote](https://github.com/substack/node-shell-quote) from 1.7.2 to 1.7.3. - [Release notes](https://github.com/substack/node-shell-quote/releases) - [Changelog](https://github.com/substack/node-shell-quote/blob/master/CHANGELOG.md) - [Commits](https://github.com/substack/node-shell-quote/compare/v1.7.2...1.7.3) --- updated-dependencies: - dependency-name: shell-quote dependency-type: indirect ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index bd14584723..5934bc00c3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4374,9 +4374,9 @@ shebang-regex@^3.0.0: integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== shell-quote@^1.6.1: - version "1.7.2" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" - integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg== + version "1.7.3" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" + integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw== showdown@^1.9.1: version "1.9.1" From b076ec1b91bd83ad7e523262dec5e105319f4a3c Mon Sep 17 00:00:00 2001 From: Ernesto Ruiz Date: Wed, 22 Jun 2022 09:41:48 -0600 Subject: [PATCH 035/101] fix: Make OTP link for get QR Code clickleable (#17275) --- frappe/twofactor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/twofactor.py b/frappe/twofactor.py index 9e9a2c5d76..6d01331d7d 100644 --- a/frappe/twofactor.py +++ b/frappe/twofactor.py @@ -279,7 +279,7 @@ def get_email_body_for_qr_code(kwargs_dict): """Get QRCode email body.""" body_template = _( "Please click on the following link and follow the instructions on the page. {0}" - ).format("

{{qrcode_link}}") + ).format("

{{qrcode_link}}") body = frappe.render_template(body_template, kwargs_dict) return body From 20c94a5d32582fd5b682e7ffc0b2b27761de1da0 Mon Sep 17 00:00:00 2001 From: Jannat Patel Date: Thu, 23 Jun 2022 12:26:31 +0530 Subject: [PATCH 036/101] fix: navbar child redirection issue --- frappe/templates/includes/navbar/navbar_items.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frappe/templates/includes/navbar/navbar_items.html b/frappe/templates/includes/navbar/navbar_items.html index 309027be09..9fbb22eeaa 100644 --- a/frappe/templates/includes/navbar/navbar_items.html +++ b/frappe/templates/includes/navbar/navbar_items.html @@ -32,9 +32,10 @@ {% else %} -{% if parent %} {% set url = item.url or '' %} {% set url = url if url.startswith('#') else url | abs_url %} + +{% if parent %}
  • ${item[field]}
  • `; - else info_html += `
  • ${item[field]}
  • `; + if (index == 0) info_html += `
  • ${__(item[field])}
  • `; + else info_html += `
  • ${__(item[field])}
  • `; set = true; } }); From 47483f833fc132d32a9c6166b911882859ffe35f Mon Sep 17 00:00:00 2001 From: Danny <66078599+mmdanny89@users.noreply.github.com> Date: Fri, 24 Jun 2022 07:34:49 -0400 Subject: [PATCH 041/101] feat(translations-cli): Fetch translations for a particular app (#17276) * translataions for particular app get-untranslated/update-translations string for particular app frappe#17268 (feature request) * fix: linting, making stuff DRY-er Co-authored-by: gavin --- frappe/commands/translate.py | 10 ++++++---- frappe/translate.py | 24 ++++++++++++++++++------ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/frappe/commands/translate.py b/frappe/commands/translate.py index 0b14e03002..69970d8d97 100644 --- a/frappe/commands/translate.py +++ b/frappe/commands/translate.py @@ -48,11 +48,12 @@ def new_language(context, lang_code, app): @click.command("get-untranslated") +@click.option("--app", default="_ALL_APPS") @click.argument("lang") @click.argument("untranslated_file") @click.option("--all", default=False, is_flag=True, help="Get all message strings") @pass_context -def get_untranslated(context, lang, untranslated_file, all=None): +def get_untranslated(context, lang, untranslated_file, app="_ALL_APPS", all=None): "Get untranslated strings for language" import frappe.translate @@ -60,17 +61,18 @@ def get_untranslated(context, lang, untranslated_file, all=None): try: frappe.init(site=site) frappe.connect() - frappe.translate.get_untranslated(lang, untranslated_file, get_all=all) + frappe.translate.get_untranslated(lang, untranslated_file, get_all=all, app=app) finally: frappe.destroy() @click.command("update-translations") +@click.option("--app", default="_ALL_APPS") @click.argument("lang") @click.argument("untranslated_file") @click.argument("translated-file") @pass_context -def update_translations(context, lang, untranslated_file, translated_file): +def update_translations(context, lang, untranslated_file, translated_file, app="_ALL_APPS"): "Update translated strings" import frappe.translate @@ -78,7 +80,7 @@ def update_translations(context, lang, untranslated_file, translated_file): try: frappe.init(site=site) frappe.connect() - frappe.translate.update_translations(lang, untranslated_file, translated_file) + frappe.translate.update_translations(lang, untranslated_file, translated_file, app=app) finally: frappe.destroy() diff --git a/frappe/translate.py b/frappe/translate.py index eb26124ba8..460c7db9b0 100644 --- a/frappe/translate.py +++ b/frappe/translate.py @@ -808,7 +808,7 @@ def write_csv_file(path, app_messages, lang_dict): w.writerow([message, translated_string, context]) -def get_untranslated(lang, untranslated_file, get_all=False): +def get_untranslated(lang, untranslated_file, get_all=False, app="_ALL_APPS"): """Returns all untranslated strings for a language and writes in a file :param lang: Language code. @@ -816,11 +816,16 @@ def get_untranslated(lang, untranslated_file, get_all=False): :param get_all: Return all strings, translated or not.""" clear_cache() apps = frappe.get_all_apps(True) + if app != "_ALL_APPS": + if app not in apps: + print(f"Application {app} not found!") + return + apps = [app] messages = [] untranslated = [] - for app in apps: - messages.extend(get_messages_for_app(app)) + for app_name in apps: + messages.extend(get_messages_for_app(app_name)) messages = deduplicate_messages(messages) @@ -850,7 +855,7 @@ def get_untranslated(lang, untranslated_file, get_all=False): print("all translated!") -def update_translations(lang, untranslated_file, translated_file): +def update_translations(lang, untranslated_file, translated_file, app="_ALL_APPS"): """Update translations from a source and target file for a given language. :param lang: Language code (e.g. `en`). @@ -879,9 +884,16 @@ def update_translations(lang, untranslated_file, translated_file): translation_dict[restore_newlines(key)] = restore_newlines(value) full_dict.update(translation_dict) + apps = frappe.get_all_apps(True) - for app in frappe.get_all_apps(True): - write_translations_file(app, lang, full_dict) + if app != "_ALL_APPS": + if app not in apps: + print(f"Application {app} not found!") + return + apps = [app] + + for app_name in apps: + write_translations_file(app_name, lang, full_dict) def import_translations(lang, path): From ac842872666e5ff92a9a58183efd2b6ef12c2e58 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Fri, 24 Jun 2022 18:31:43 +0530 Subject: [PATCH 042/101] fix: improve SVG for expenses icon --- frappe/public/icons/timeless/icons.svg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/public/icons/timeless/icons.svg b/frappe/public/icons/timeless/icons.svg index fbd72d6fb5..af63d0c8ff 100644 --- a/frappe/public/icons/timeless/icons.svg +++ b/frappe/public/icons/timeless/icons.svg @@ -613,8 +613,8 @@ - + From 3c617e3b06e128192dc2bbab5abccf198145d55c Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Sun, 26 Jun 2022 11:51:52 +0530 Subject: [PATCH 043/101] fix!: dont delete custom permissions when doctype is deleted --- frappe/model/delete_doc.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/frappe/model/delete_doc.py b/frappe/model/delete_doc.py index 20dac14458..04e25fe198 100644 --- a/frappe/model/delete_doc.py +++ b/frappe/model/delete_doc.py @@ -89,8 +89,6 @@ def delete_doc( update_flags(doc, flags, ignore_permissions) check_permission_and_not_submitted(doc) - - frappe.db.delete("Custom DocPerm", {"parent": name}) frappe.db.delete("__global_search", {"doctype": name}) delete_from_table(doctype, name, ignore_doctypes, None) From b6963b1dec8a9c2e8abea61df48e3c905fa02a63 Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Sun, 26 Jun 2022 12:53:38 +0530 Subject: [PATCH 044/101] fix: ignore integration request when deleting doc --- frappe/model/delete_doc.py | 1 + 1 file changed, 1 insertion(+) diff --git a/frappe/model/delete_doc.py b/frappe/model/delete_doc.py index 20dac14458..a71cfa6053 100644 --- a/frappe/model/delete_doc.py +++ b/frappe/model/delete_doc.py @@ -31,6 +31,7 @@ doctypes_to_skip = ( "Notification Log", "Email Queue", "Document Share Key", + "Integration Request", ) From 217644ac07aca387da760217686c42635c76804e Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Sun, 26 Jun 2022 19:31:03 +0000 Subject: [PATCH 045/101] fix!: remove unnecessary `get_default` API (#17295) --- frappe/client.py | 6 ------ .../js/print_format_builder/LetterHeadEditor.vue | 10 ++-------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/frappe/client.py b/frappe/client.py index 154fcf31e2..d5dc890f56 100644 --- a/frappe/client.py +++ b/frappe/client.py @@ -281,12 +281,6 @@ def set_default(key, value, parent=None): frappe.clear_cache(user=frappe.session.user) -@frappe.whitelist() -def get_default(key, parent=None): - """set a user default value""" - return frappe.db.get_default(key, parent) - - @frappe.whitelist(methods=["POST", "PUT"]) def make_width_property_setter(doc): """Set width Property Setter diff --git a/frappe/public/js/print_format_builder/LetterHeadEditor.vue b/frappe/public/js/print_format_builder/LetterHeadEditor.vue index 1eae56f81a..5dd0ee3575 100644 --- a/frappe/public/js/print_format_builder/LetterHeadEditor.vue +++ b/frappe/public/js/print_format_builder/LetterHeadEditor.vue @@ -150,14 +150,8 @@ export default { } }, mounted() { - if (!this.letterhead) { - frappe - .call("frappe.client.get_default", { key: "letter_head" }) - .then(r => { - if (r.message) { - this.set_letterhead(r.message); - } - }); + if (!this.letterhead && frappe.boot.sysdefaults.letter_head) { + this.set_letterhead(frappe.boot.sysdefaults.letter_head); } this.$watch( From c99dd7c5efb8467dcf686807980ef6169c14dd71 Mon Sep 17 00:00:00 2001 From: Abhirup Date: Thu, 16 Jun 2022 12:57:06 +0530 Subject: [PATCH 046/101] Add data titles to sidebar workspace fields for easier selection through CSS. --- frappe/public/js/frappe/views/workspace/workspace.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/views/workspace/workspace.js b/frappe/public/js/frappe/views/workspace/workspace.js index d95925eea6..6c719d5dc1 100644 --- a/frappe/public/js/frappe/views/workspace/workspace.js +++ b/frappe/public/js/frappe/views/workspace/workspace.js @@ -118,7 +118,7 @@ frappe.views.Workspace = class Workspace { } build_sidebar_section(title, root_pages) { - let sidebar_section = $(`
    `); + let sidebar_section = $(`
    `); let $title = $(`
    ${frappe.utils.icon("small-down", "xs")} From 99388652c9966b5826fafffdb2c0301a5704e467 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Mon, 27 Jun 2022 01:56:58 +0530 Subject: [PATCH 047/101] chore(redis): remove unnecessary exception handling --- frappe/utils/redis_wrapper.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/frappe/utils/redis_wrapper.py b/frappe/utils/redis_wrapper.py index 06480f0b7b..178c3d4416 100644 --- a/frappe/utils/redis_wrapper.py +++ b/frappe/utils/redis_wrapper.py @@ -105,10 +105,7 @@ class RedisWrapper(redis.Redis): def delete_keys(self, key): """Delete keys with wildcard `*`.""" - try: - self.delete_value(self.get_keys(key), make_keys=False) - except redis.exceptions.ConnectionError: - pass + self.delete_value(self.get_keys(key), make_keys=False) def delete_key(self, *args, **kwargs): self.delete_value(*args, **kwargs) @@ -202,10 +199,7 @@ class RedisWrapper(redis.Redis): frappe.local.cache[_name][key] = value elif generator: value = generator() - try: - self.hset(name, key, value) - except redis.exceptions.ConnectionError: - pass + self.hset(name, key, value) return value def hdel(self, name, key, shared=False): From bf7091b8361e09691f4f52e98fbbadc452df5bca Mon Sep 17 00:00:00 2001 From: Marco <62901164+treasuryesc@users.noreply.github.com> Date: Sun, 26 Jun 2022 19:26:35 -0300 Subject: [PATCH 048/101] Correct pt-BR translations I've sync'ed pt-BR translations based on parent pt.csv file, adapting it for local terms and expressions. --- frappe/translations/pt-BR.csv | 6234 +++++++++++++++++++++++++-------- 1 file changed, 4702 insertions(+), 1532 deletions(-) diff --git a/frappe/translations/pt-BR.csv b/frappe/translations/pt-BR.csv index d6eb53825c..49c16ee634 100644 --- a/frappe/translations/pt-BR.csv +++ b/frappe/translations/pt-BR.csv @@ -1,1532 +1,4702 @@ -apps/frappe/frappe/website/doctype/web_form/web_form.py +59,Please select a Amount Field.,Por favor selecione um campo total. -apps/frappe/frappe/desk/form/assign_to.py +168,"A new task, {0}, has been assigned to you by {1}. {2}","Uma nova tarefa, {0}, foi atribuída a você por {1}. {2}" -DocType: Email Queue,Email Queue records.,Registros da Fila de Emails. -DocType: Post,Post,Postar -apps/frappe/frappe/config/setup.py +126,Rename many items by uploading a .csv file.,Renomeie muitos itens fazendo o upload de um arquivo csv. -DocType: Workflow State,pause,pausar -DocType: System Settings,Note: Multiple sessions will be allowed in case of mobile device,Observação: Serão permitidas múltiplas sessões no caso de dispositivo móvel -apps/frappe/frappe/email/queue.py +259,Cannot send this email. You have crossed the sending limit of {0} emails for this month.,Não é possível enviar este email. Você excedeu o limite de envio de {0} emails para este mês. -apps/frappe/frappe/public/js/legacy/form.js +775,Permanently Submit {0}?,Confirmar Permanentemente {0} ? -DocType: Workflow,If Checked workflow status will not override status in list view,Uma vez selecionado o status do fluxo de trabalho não sobrescreverá o status do documentos na visualização da lista -apps/frappe/frappe/client.py +302,Invalid file path: {0},Caminho de arquivo inválido: {0} -DocType: Workflow State,eye-open,olho aberto -apps/frappe/frappe/core/doctype/file/file.py +327,Please select a file or url,"Por favor, selecione um arquivo ou url" -apps/frappe/frappe/public/js/frappe/views/treeview.js +89,{0} Tree,Árvore de {0} -DocType: User,User Emails,Emails do Usuário -DocType: User,Username,Nome de Usuário -apps/frappe/frappe/public/js/frappe/views/file/file_view.js +90,Import Zip,Importar Zip -DocType: Print Format,Print Format Builder,Criar/Editar Formato de Impressão -DocType: Workflow,Document States,Documento Unidos -apps/frappe/frappe/public/js/frappe/views/pageview.js +104,Sorry! I could not find what you were looking for.,Desculpe! Não foi possível encontrar o que você procurou. -DocType: Data Migration Run,Logs,Logs -DocType: Custom DocPerm,This role update User Permissions for a user,Este papel arualiza Permissões do Usuário para um usuário -apps/frappe/frappe/public/js/frappe/model/model.js +538,Rename {0},Mudar o nome {0} -DocType: Workflow State,zoom-out,diminuir zoom -apps/frappe/frappe/public/js/legacy/form.js +66,Cannot open {0} when its instance is open,Não é possível abrir {0} quando sua instância está aberta -apps/frappe/frappe/model/document.py +1101,Table {0} cannot be empty,Tabela {0} não pode ser vazio -apps/frappe/frappe/public/js/frappe/views/reports/grid_report.js +823,With Ledgers,Com Razões -apps/frappe/frappe/public/js/frappe/views/image/image_view.js +13,Images,Imagens -DocType: Activity Log,Reference Owner,Proprietário da Referência -DocType: Currency,Smallest circulating fraction unit (coin). For e.g. 1 cent for USD and it should be entered as 0.01,"Menor unidade fração circulante (moeda). Para, por exemplo, 1 centavo, deve ser inserido como 0,01" -apps/frappe/frappe/model/document.py +1075,Beginning with,Começando com -apps/frappe/frappe/core/doctype/data_import/exporter.py +53,Data Import Template,Modelo de importação de dados -apps/frappe/frappe/public/js/frappe/model/model.js +33,Parent,Parente -DocType: About Us Settings,"""Team Members"" or ""Management""","Membros da Equipe" ou "Gerenciamento" -apps/frappe/frappe/core/doctype/doctype/doctype.py +560,Default for 'Check' type of field must be either '0' or '1',"Padrão para ""Verificar"" o tipo de campo deve ser '0' ou '1'" -DocType: Email Account,Enable Incoming,Ativar Entrada -apps/frappe/frappe/www/login.html +21,Email Address,Endereço de Email -DocType: Communication,Unread Notification Sent,Notificação de mensagem não lida enviada -apps/frappe/frappe/public/js/frappe/misc/tools.js +10,Export not allowed. You need {0} role to export.,Exportação não é permitido. Você precisa da função {0} para exportar. -DocType: Email Group,Email Group,Grupo de Emails -apps/frappe/frappe/public/js/frappe/ui/filters/filters.js +512,Not Like,Não Parecido -apps/frappe/frappe/config/setup.py +242,"Change field properties (hide, readonly, permission etc.)","Alterar as propriedades do campo (esconder , readonly , permissão etc )" -DocType: Workflow State,lock,trancar -apps/frappe/frappe/config/website.py +78,Settings for Contact Us Page.,Configurações da Página Fale Conosco. -apps/frappe/frappe/core/doctype/user/user.py +918,Administrator Logged In,Administrador logou-se -DocType: Contact Us Settings,"Contact options, like ""Sales Query, Support Query"" etc each on a new line or separated by commas.","Opções de contato, como ""Perguntas sobre Vendas, Perguntas de suporte"", etc cada uma em uma nova linha ou separadas por vírgulas." -apps/frappe/frappe/desk/doctype/auto_repeat/auto_repeat.py +285,New {0}: #{1},Nova {0}: # {1} -DocType: Data Migration Run,Insert,Insert -DocType: Auto Repeat,Repeat on Day,Repetir no dia -DocType: Workflow State,indent-right,indentar à direita -DocType: Has Role,Has Role,Tem Função -apps/frappe/frappe/public/js/frappe/misc/pretty_date.js +47,1 minute ago,1 minuto atrás -apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +36,"Apart from System Manager, roles with Set User Permissions right can set permissions for other users for that Document Type.","Além de System Manager, os papéis com o conjunto de permissões certas pode definir permissões para outros usuários para esse tipo de documento." -DocType: Company History,Company History,Histórico da Empresa -apps/frappe/frappe/website/doctype/portal_settings/portal_settings.js +19,Reset,Restaurar -DocType: Workflow State,volume-up,aumentar volume -DocType: DocType,Default Print Format,Formato de impressão padrão -DocType: Workflow State,Tags,Tags -apps/frappe/frappe/public/js/frappe/form/workflow.js +35,None: End of Workflow,Nenhum: Fim do fluxo de trabalho -apps/frappe/frappe/model/db_schema.py +359,"{0} field cannot be set as unique in {1}, as there are non-unique existing values","{0} campo não pode ser definido como único em {1}, pois há valores duplicados existentes" -apps/frappe/frappe/core/page/permission_manager/permission_manager.js +48,Document Types,Tipos de documento -DocType: Address,Jammu and Kashmir,Jammu e Kashmir -DocType: Workflow,Workflow State Field,Campo do Status do Fluxo de Trabalho -DocType: DocType,Title Field,Campo Título -DocType: Error Log,Error Log,Log de Erro -apps/frappe/frappe/templates/emails/administrator_logged_in.html +3,"If you think this is unauthorized, please change the Administrator password.","Se você acha que isso não é autorizado, por favor mude a senha do administrador." -DocType: Chat Room,Owner,Proprietário -DocType: Communication,Visit,Visita -DocType: LDAP Settings,LDAP Search String,Palavra de Busca do LDAP -DocType: Data Import,Import Log,Log de Importação -apps/frappe/frappe/config/website.py +27,Embed image slideshows in website pages.,Incorporar apresentações de imagem em páginas do site. -DocType: Workflow Action Master,Workflow Action Name,Nome da Ação do Fluxo de Trabalho -apps/frappe/frappe/core/doctype/doctype/doctype.py +355,DocType can not be merged,DocType não podem ser mescladas -DocType: Web Form Field,Fieldtype,FieldType -apps/frappe/frappe/utils/password_strength.py +196,Capitalization doesn't help very much.,"A senha não é boa o suficiente, mas será aceita." -DocType: Error Snapshot,Friendly Title,Título Amigável -DocType: Newsletter,Email Sent?,Email enviado? -apps/frappe/frappe/public/js/frappe/views/file/file_view.js +38,File Manager,Gestor de Arquivos -DocType: GCalendar Account,Refresh Token,Token de Atualização -apps/frappe/frappe/email/doctype/newsletter/newsletter.py +40,Newsletter has already been sent,A Newsletter já foi enviada -DocType: Email Unsubscribe,Email Unsubscribe,Cancelar inscrição de email -apps/frappe/frappe/desk/page/setup_wizard/setup_wizard.js +426,The first user will become the System Manager (you can change this later).,O primeiro usuário será o System Manager (você pode mudar isso mais tarde). -,App Installer,Instalador de Aplicativos -DocType: Email Domain,Email Domain,Domínio de Email -apps/frappe/frappe/core/doctype/doctype/doctype.py +810,{0}: Cannot set Import without Create,{0}: Não é possível definir Importação sem Criar -DocType: SMS Settings,Enter url parameter for message,Digite o parâmetro da url para mensagem -apps/frappe/frappe/public/js/frappe/views/reports/reportview.js +865,Drag to sort columns,Arraste para classificar colunas -apps/frappe/frappe/printing/page/print_format_builder/print_format_builder_column_selector.html +2,Widths can be set in px or %.,Larguras podem ser definidas em px ou %. -apps/frappe/frappe/public/js/frappe/form/print.js +102,Start,Iniciar -DocType: LDAP Settings,LDAP Username Field,Campo Nome de Usuário do LDAP -DocType: Portal Settings,Standard Sidebar Menu,Menu Lateral Padrão -apps/frappe/frappe/core/doctype/file/file.py +216,Cannot delete Home and Attachments folders,Não é possível excluir pastas Inicial e Anexos -apps/frappe/frappe/config/desk.py +19,Files,Arquivos -apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +6,Permissions get applied on Users based on what Roles they are assigned.,As permissões são aplicadas em usuários com base nas funções que lhe são atribuídas. -apps/frappe/frappe/public/js/frappe/views/communication.js +539,You are not allowed to send emails related to this document,Você não tem permissão para enviar emails relacionados a este documento -apps/frappe/frappe/custom/doctype/customize_form/customize_form.js +240,Reqd,Solicitado -apps/frappe/frappe/core/doctype/communication/email.py +285,Unable to find attachment {0},Incapaz de encontrar o anexo {0} -apps/frappe/frappe/custom/doctype/customize_form/customize_form.js +228,Assign a permission level to the field.,Atribuir um nível de permissão para o campo. -apps/frappe/frappe/core/page/permission_manager/permission_manager.py +91,Cannot Remove,Não é Possível Remover -apps/frappe/frappe/core/doctype/communication/communication_list.js +14,Mark as Read,Marcar como lido -apps/frappe/frappe/www/feedback.html +34,Detailed feedback,Feedback detalhado -DocType: Report,JavaScript Format: frappe.query_reports['REPORTNAME'] = {},Formato JavaScript: frappe.query_reports [' REPORTNAME '] = {} -DocType: Bulk Update,Bulk Update,Alteração em Massa -DocType: Workflow State,chevron-up,divisa-acima -DocType: DocType,Allow Guest to View,Permitir visualização de convidado -DocType: DocShare,Internal record of document shares,Registro interno de ações de documentos -apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +17,"You can change Submitted documents by cancelling them and then, amending them.",Você pode alterar documentos cancelados -DocType: DocField,Display,exibição -apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +25,"If a Role does not have access at Level 0, then higher levels are meaningless.","Se uma função não tem acesso no nível 0, então os níveis mais altos são irrelevantes." -DocType: System Settings,Run scheduled jobs only if checked,As tarefas agendadas somente serão executadas se a opção estiver marcada -apps/frappe/frappe/public/js/frappe/views/kanban/kanban_column.html +9,Archive,Arquivar -DocType: Communication,Rating,Rating -DocType: Customize Form Field,"Print Width of the field, if the field is a column in a table","Largura de impressão do campo, se o campo é uma coluna na tabela" -DocType: Dropbox Settings,Dropbox Access Key,Dropbox Chave de Acesso -DocType: Workflow State,headphones,fones de ouvido -DocType: Email Account,e.g. replies@yourcomany.com. All replies will come to this inbox.,eg replies@yourcomany.com. Todas as respostas virão a esta caixa de entrada. -DocType: Slack Webhook URL,Slack Webhook URL,URL do Webhook do Slack -apps/frappe/frappe/templates/includes/login/login.js +39,Valid email and name required,É necessário email válido e nome -DocType: DocType,Hide Heading,Ocultar Título -DocType: Workflow State,remove-circle,remove-círculo -DocType: Contact,Is Primary Contact,É o contato principal -apps/frappe/frappe/config/website.py +68,Javascript to append to the head section of the page.,Javascript para acrescentar ao cabeçalho da página. -apps/frappe/frappe/www/printview.py +80,Not allowed to print draft documents,Não permitido para imprimir documentos de rascunho -apps/frappe/frappe/core/doctype/role_permission_for_page_and_report/role_permission_for_page_and_report.js +12,Reset to defaults,Restaurar Padrões -DocType: Workflow,Defines workflow states and rules for a document.,Define o status de fluxo de trabalho e regras para um documento. -apps/frappe/frappe/model/db_schema.py +598,Fieldname {0} cannot have special characters like {1},Fieldname {0} não pode ter caracteres especiais como {1} -apps/frappe/frappe/config/setup.py +133,Update many values at one time.,Atualizar muitas informações de uma só vez. -apps/frappe/frappe/model/document.py +646,Error: Document has been modified after you have opened it,Erro: O documento foi modificado depois de aberto -apps/frappe/frappe/core/doctype/activity_log/feed.py +56,{0} logged out: {1},{0} deslogado: {1} -apps/frappe/frappe/core/doctype/doctype/doctype.py +829,{0}: Cannot set Assign Submit if not Submittable,{0}: Não é possível definir atributo Enviar se não pode ser enviado -DocType: Web Form,Button Help,Botão de Ajuda -DocType: Kanban Board Column,purple,roxo -apps/frappe/frappe/public/js/frappe/upload.js +252,Please attach a file or set a URL,"Por favor, anexar um arquivo ou definir uma URL" -DocType: Chat Message,System Manager,Administrador do Sistema -DocType: Dropbox Settings,Allow Dropbox Access,Permitir Acesso Dropbox -DocType: Bulk Update,"SQL Conditions. Example: status=""Open""","Condições SQL. Exemplo: status=""Open""" -apps/frappe/frappe/limits.py +32,"Your subscription expired on {0}. To renew, {1}.","Sua inscrição expirou em {0}. Para renovar, {1}." -DocType: Workflow State,plus-sign,sinal de mais -apps/frappe/frappe/__init__.py +994,App {0} is not installed,App {0} não está instalado -DocType: Workflow State,Refresh,Atualizar -apps/frappe/frappe/public/js/frappe/views/reports/query_report.js +979,Nothing to show,Nada para mostrar -apps/frappe/frappe/desk/doctype/auto_repeat/auto_repeat.py +303,[Urgent] Error while creating recurring %s for %s,[Urgente] Ocorreu um erro ao criar %s recorrentes para %s -DocType: Post,Liked By,Gostou por -DocType: DocField,Print Hide If No Value,Ocultar Impressão se não Preenchido -apps/frappe/frappe/public/js/frappe/upload.js +26,Upload Attachment,Upload de Anexos -DocType: Block Module,Block Module,Módulo Bloco -apps/frappe/frappe/core/doctype/version/version_view.html +14,New Value,Novo Valor -DocType: Notification,Send Alert On,Enviar Alerta -DocType: Customize Form,"Customize Label, Print Hide, Default etc.","Personalizar Etiquetas, Cabeçalhos, Padrões, etc." -apps/frappe/frappe/printing/page/print_format_builder/print_format_builder_start.html +16,Create a New Format,Criar um novo formato -DocType: Customize Form,Is Table,É Tabela -DocType: Website Settings,Set Banner from Image,Definir imagem como banner -apps/frappe/frappe/templates/emails/new_user.html +2,A new account has been created for you at {0},Uma nova conta foi criada para você em {0} -apps/frappe/frappe/public/js/frappe/views/communication.js +528,Enter Email Recipient(s),Digite email do Destinatário(s) -DocType: Email Flag Queue,Email Flag Queue,Flag Fila de Email -apps/frappe/frappe/utils/bot.py +83,Can't identify open {0}. Try something else.,Não é possível identificar aberto {0}. Tente outra coisa. -apps/frappe/frappe/website/doctype/web_form/templates/web_form.html +208,Your information has been submitted,Suas informações foram enviadas -apps/frappe/frappe/core/doctype/user/user.py +304,User {0} cannot be deleted,O usuário {0} não pode ser excluído -apps/frappe/frappe/public/js/frappe/request.js +145,Another transaction is blocking this one. Please try again in a few seconds.,"Outra transação está bloqueando essa. Por favor, tente novamente em alguns segundos." -DocType: DocType,App,Aplicativo -DocType: Chat Message Attachment,Attachment,Anexos -apps/frappe/frappe/public/js/frappe/ui/toolbar/awesome_bar.js +139,module name...,nome do módulo ... -DocType: Custom Field,Fieldname,Nome do Campo -DocType: User,Tile,Telha -apps/frappe/frappe/templates/includes/login/login.js +118,Verifying...,Verificando... -apps/frappe/frappe/core/doctype/data_import/exporter.py +64,First data column must be blank.,Primeira coluna de dados deve estar em branco. -apps/frappe/frappe/public/js/frappe/form/layout.js +108,Dashboard,Painel de controle -apps/frappe/frappe/email/smtp.py +234,Unable to send emails at this time,Não é possível enviar emails neste momento -DocType: Contact,Sales Master Manager,Gerente de Cadastros de Vendas -apps/frappe/frappe/custom/doctype/custom_field/custom_field.js +60,Name of the Document Type (DocType) you want this field to be linked to. e.g. Customer,"Nome do Tipo de Documento (DocType) pretende que este campo a ser vinculado. por exemplo, o Cliente" -DocType: Role Profile,Roles Assigned,Funções atribuídas -apps/frappe/frappe/public/js/frappe/ui/toolbar/awesome_bar.js +143,Search Help,Procure Ajuda -DocType: Top Bar Item,Parent Label,Etiqueta pai -apps/frappe/frappe/templates/emails/auto_reply.html +2,"Your query has been received. We will reply back shortly. If you have any additional information, please reply to this mail.","Sua consulta foi recebida. Nós responderemos de volta em breve. Se você tiver qualquer informação adicional, por favor responda a este email." -DocType: Event,Repeat Till,Repita até que -apps/frappe/frappe/public/js/frappe/views/kanban/kanban_board.html +11,Loading...,Carregando... -apps/frappe/frappe/utils/response.py +194,Your system is being updated. Please refresh again after a few moments,"Seu sistema está sendo atualizado. Por favor, atualize a página em alguns instantes" -DocType: Auto Email Report,Day of Week,Dia da Semana -apps/frappe/frappe/public/js/frappe/form/controls/comment.js +19,Ctrl+Enter to add comment,Ctrl+Enter para adicionar comentário -DocType: File,File URL,URL do arquivo -apps/frappe/frappe/email/doctype/email_group/email_group.js +28,Add Subscribers,Adicionar Inscritos -DocType: Notification Recipient,Email By Document Field,Email por Campo do Documento -DocType: Domain Settings,Domain Settings,Configurações de Domínio -apps/frappe/frappe/core/page/usage_info/usage_info.js +20,Upgrade,Atualizar -apps/frappe/frappe/utils/password_strength.py +184,A word by itself is easy to guess.,Uma palavra por si só é fácil de adivinhar. -apps/frappe/frappe/utils/nestedset.py +223,Merging is only possible between Group-to-Group or Leaf Node-to-Leaf Node,A fusão só é possível entre o grupos -apps/frappe/frappe/templates/includes/search_template.html +45,No matching records. Search something new,Não há registros correspondentes. Procure algo novo -DocType: Currency,Fraction Units,Unidades Fracionadas -apps/frappe/frappe/public/js/frappe/form/footer/timeline.js +530,{0} from {1} to {2},{0} de {1} para {0} -DocType: Web Form,Amount Based On Field,Total Baseado no Campo -apps/frappe/frappe/core/doctype/docshare/docshare.py +34,User is mandatory for Share,Usuário é obrigatória para Partilhar -DocType: Web Form,Allow Incomplete Forms,Permitir Formulários Incompletos -apps/frappe/frappe/model/base_document.py +448,{0} must be set first,{0} deve ser definida primeiro -apps/frappe/frappe/utils/password_strength.py +38,"Use a few words, avoid common phrases.","Use algumas palavras, evite frases comuns." -apps/frappe/frappe/core/doctype/data_import/exporter.py +66,"If you are uploading new records, ""Naming Series"" becomes mandatory, if present.","Se você estiver fazendo upload de novos registros, a coluna ""Naming Series"" torna-se obrigatória, se presente." -apps/frappe/frappe/core/doctype/doctype/doctype.py +349,DocType can only be renamed by Administrator,DocType só pode ser renomeado pelo Administrador -apps/frappe/frappe/public/js/frappe/form/footer/timeline.js +541,changed value of {0},mudou o valor de {0} -apps/frappe/frappe/core/doctype/doctype/doctype.py +601,Fold can not be at the end of the form,Fold não pode ser no final da forma -DocType: Communication,Bounced,Bounced -DocType: Deleted Document,Deleted Name,Nome Excluído -apps/frappe/frappe/config/setup.py +14,System and Website Users,Usuários do sistema e do site -DocType: Workflow Document State,Doc Status,Status do Documento -DocType: Auto Email Report,No of Rows (Max 500),Número de linhas (max 500) -DocType: Language,Language Code,Código do Idioma -apps/frappe/frappe/public/js/frappe/ui/toolbar/toolbar.js +256,"Your download is being built, this may take a few moments...","O seu download está sendo construído, isso pode demorar alguns instantes ..." -apps/frappe/frappe/www/feedback.html +23,Your rating: ,Seu rating: -DocType: Print Settings,"Always add ""Draft"" Heading for printing draft documents","Sempre adicionar ""Rascunho"" no cabeçalho para impressão de documentos não enviados" -DocType: About Us Settings,Website Manager,Administrador do Site -apps/frappe/frappe/core/doctype/doctype/doctype.py +536,Field {0} in row {1} cannot be hidden and mandatory without default,"O campo {0} na linha {1} não pode ser escondido e obrigatória , sem padrão" -DocType: Print Settings,Send document web view link in email,Enviar link no email para visualizar o documento online -DocType: Currency,"Sub-currency. For e.g. ""Cent""",Sub-moeda. Por exemplo "Centavo" -DocType: Letter Head,Check this to make this the default letter head in all prints,Marque esta opção para tornar este o cabeçalho padrão em todas as impressões -apps/frappe/frappe/public/js/frappe/views/kanban/kanban_view.js +229,New Kanban Board,Novo Painel Kanban -apps/frappe/frappe/core/doctype/file/file.py +455,No file attached,Nenhum arquivo anexado -DocType: Version,Version,Versão -DocType: User,Fill Screen,Preencher Tela -apps/frappe/frappe/public/js/frappe/form/grid.js +681,Edit via Upload,Editar via Upload -apps/frappe/frappe/public/js/frappe/ui/toolbar/awesome_bar.js +135,"document type..., e.g. customer","Tipo de documento ..., por exemplo: cliente" -DocType: Workflow State,barcode,Código de barras -apps/frappe/frappe/config/setup.py +254,Add your own translations,Adicione suas próprias traduções -DocType: About Us Team Member,About Us Team Member,Sobre Nós - Membros da Equipe -apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +5,"Permissions are set on Roles and Document Types (called DocTypes) by setting rights like Read, Write, Create, Delete, Submit, Cancel, Amend, Report, Import, Export, Print, Email and Set User Permissions.","As permissões são definidas em Funções e Tipos de Documentos (chamados Doctypes ) , definindo direitos como Ler, Escrever, Criar, Deletar, Enviar, Cancelar, Corrigir, Reportar, Importar, Exportar, Imprimir, Email e Definir Permissões de Usuário." -apps/frappe/frappe/core/doctype/doctype/doctype.py +652,Image field must be a valid fieldname,Campo de imagem deve ser um nome de campo válido -DocType: Property Setter,ID (name) of the entity whose property is to be set,ID (nome) da entidade cuja propriedade é para ser definida -DocType: Website Settings,Website Theme Image Link,Link da Imagem do Tema do Site -DocType: Web Form,Sidebar Items,Itens da barra lateral -apps/frappe/frappe/core/report/permitted_documents_for_user/permitted_documents_for_user.js +30,Show Permissions,Mostrar Permissões -apps/frappe/frappe/core/doctype/doctype/doctype.py +672,Timeline field must be a Link or Dynamic Link,Campo Timeline deve ser um link ou link dinâmico -apps/frappe/frappe/public/js/frappe/form/multi_select_dialog.js +53,Date Range,Intervalo entre datas -DocType: About Us Settings,Introduce your company to the website visitor.,Apresente sua empresa para o visitante do site. -DocType: SMS Settings,Receiver Parameter,Parâmetro do recebedor -DocType: Communication,To,Para -apps/frappe/frappe/printing/doctype/print_format/print_format.js +18,Please duplicate this to make changes,"Por favor, duplicar este para fazer mudanças" -DocType: Print Settings,Font Size,Tamanho da Fonte -DocType: System Settings,Disable Standard Email Footer,Desativar Rodapé Padrão do Email -DocType: Workflow State,facetime-video,vídeo do facetime -DocType: Workflow State,volume-down,diminuir volume -apps/frappe/frappe/desk/reportview.py +269,No Tags,Sem tags -DocType: Email Account,Send Notification to,Enviar Notificação para -DocType: DocField,Collapsible,Desmontável -apps/frappe/frappe/custom/doctype/custom_field/custom_field.js +63,Options for select. Each option on a new line.,Opções para selecionar. Cada opção em uma nova linha. -apps/frappe/frappe/www/qrcode.html +3,QR Code,QR Code -DocType: Print Format,Style Settings,Configurações de Estilo -DocType: Contact,Sales Manager,Gerente de Vendas -apps/frappe/frappe/public/js/frappe/model/model.js +544,Rename,Renomear -DocType: Print Format,Format Data,Formato de dados -apps/frappe/frappe/public/js/frappe/ui/filters/filters.js +512,Like,Parecido -apps/frappe/frappe/config/setup.py +57,Check which Documents are readable by a User,Confira quais os documentos são lidos por um Usuário -apps/frappe/frappe/public/js/frappe/ui/filters/filter.js +283,use % as wildcard,usar % como coringa -DocType: Auto Repeat,Quarterly,Trimestralmente -apps/frappe/frappe/email/doctype/email_account/email_account.js +151,"Email Domain not configured for this account, Create one?","Domínio de email não configurado para esta conta, criar um?" -DocType: User,Reset Password Key,Redefinição de senha chave -DocType: Email Account,Enable Auto Reply,Ativar resposta automática -DocType: Workflow State,zoom-in,aumentar zoom -apps/frappe/frappe/email/doctype/email_unsubscribe/email_unsubscribe.py +13,Reference DocType and Reference Name are required,Referência DocType e nome de referência são necessários -apps/frappe/frappe/utils/jinja.py +51,Syntax error in template,Erro de sintaxe no template -DocType: Email Account,Notify if unreplied,Informar se não for respondido -DocType: System Settings,Your organization name and address for the email footer.,Nome da empresa e endereço para o rodapé do email. -apps/frappe/frappe/core/doctype/data_import/importer.py +27,Parent Table,Tabela Parent -apps/frappe/frappe/website/doctype/website_settings/website_settings.py +38,{0} in row {1} cannot have both URL and child items,{0} na linha {1} não pode ter URL e Itens vinculados ao mesmo tempo -apps/frappe/frappe/utils/nestedset.py +196,Root {0} cannot be deleted,Root {0} não pode ser excluído -apps/frappe/frappe/printing/page/print_format_builder/print_format_builder.js +126,Both DocType and Name required,Ambos DocType e Nome é obrigatório -apps/frappe/frappe/model/document.py +682,Cannot change docstatus from 1 to 0,Não é possível alterar docstatus 1-0 -apps/frappe/frappe/integrations/doctype/dropbox_settings/dropbox_settings.js +41,Take Backup Now,Fazer backup agora -DocType: Contact,Open,Aberto -DocType: Workflow Transition,Defines actions on states and the next step and allowed roles.,"Define ações em status, o próximo passo e as funções com permissão." -apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +11,"As a best practice, do not assign the same set of permission rule to different Roles. Instead, set multiple Roles to the same User.","Como uma prática recomendada , não atribua o mesmo conjunto de regras de permissão para diferentes funções. Em vez disso, definir várias funções para o mesmo usuário." -apps/frappe/frappe/email/doctype/auto_email_report/auto_email_report.py +48,Only {0} emailed reports are allowed per user,Somente {0} relatórios enviados poe email são permitidos por usuário -DocType: DefaultValue,DefaultValue,Valor padrão -apps/frappe/frappe/config/setup.py +19,User Roles,Funções do Usuário -DocType: Property Setter,Property Setter overrides a standard DocType or Field property,O configurador de propriedades substitui o DocType padrão ou propriedade de campo -apps/frappe/frappe/core/doctype/user/user.py +727,Cannot Update: Incorrect / Expired Link.,Não é possível atualizar : Link incorreto / expirado. -apps/frappe/frappe/utils/password_strength.py +70,Better add a few more letters or another word,Recomenda-se adicionar mais algumas letras ou colocar uma palavra adicional -apps/frappe/frappe/core/doctype/user/user.py +417,Username {0} already exists,O nome de usuário {0} já existe -apps/frappe/frappe/core/doctype/doctype/doctype.py +835,{0}: Cannot set import as {1} is not importable,{0}: Não é possível definir importação como {1} se não é importável -apps/frappe/frappe/contacts/doctype/address/address.py +115,There is an error in your Address Template {0},Há um erro no seu modelo de endereço {0} -DocType: User,Allow Desktop Icon,Permitir ícone no desktop -DocType: Workflow State,hdd,hdd -DocType: Integration Request,Host,Host -DocType: ToDo,High,Alta -DocType: Communication,From Full Name,De nome completo -DocType: User,Send Welcome Email,Enviar email de boas-vindas -apps/frappe/frappe/config/setup.py +125,Bulk Rename,Renomear em Massa -DocType: Workflow State,resize-vertical,redimensionamento vertical -DocType: Contact Us Settings,Introductory information for the Contact Us Page,Informação introdutória para a página Fale Conosco -DocType: Workflow State,thumbs-down,polegar para baixo -apps/frappe/frappe/core/doctype/page/page.py +37,Not in Developer Mode,Você não está no modo de desenvolvedor -DocType: DocField,In Global Search,Na Busca Global -DocType: Workflow State,indent-left,indentar à esquerda -apps/frappe/frappe/core/doctype/file/file.py +695,It is risky to delete this file: {0}. Please contact your System Manager.,É arriscado excluir este arquivo: {0}. Entre em contato com o administrador do sistema. -apps/frappe/frappe/public/js/frappe/views/inbox/inbox_view.js +175,No Emails,Nenhum Email -DocType: File,Content Hash,Hash do conteúdo -DocType: Website Theme,Google Font (Text),Google Font (Texto) -apps/frappe/frappe/email/doctype/email_unsubscribe/email_unsubscribe.py +31,{0} already unsubscribed for {1} {2},{0} já teve sua sua inscrição cancelada para {1} {2} -apps/frappe/frappe/core/page/permission_manager/permission_manager.js +318,Did not remove,Não removido -apps/frappe/frappe/desk/like.py +89,Liked,Gostou -apps/frappe/frappe/core/doctype/doctype/doctype.py +544,'In List View' not allowed for type {0} in row {1},'Visualização em Lista' não pode ser utilizado para o tipo {0} na linha {1} -DocType: Custom Field,Select the label after which you want to insert new field.,Selecione a etiqueta após a qual você deseja inserir um novo campo. -,Document Share Report,Relatório de Documentos Compartilhados -DocType: User,Last Login,Último Login -DocType: Custom Field,Adds a custom field to a DocType,Adiciona um campo personalizado para um Tipo de Documento (DocType) -DocType: File,Is Home Folder,É Home Folder -DocType: Email Account,Use IMAP,Usar IMAP -DocType: Activity Log,Activity Log,Log de Atividade -DocType: DocType,Single Types have only one record no tables associated. Values are stored in tabSingles,Tipos individuais têm apenas um registro sem tabelas associadas. Os valores são armazenados em tabSingles -DocType: Workflow,Rules defining transition of state in the workflow.,Regras que definem a transição de status no fluxo de trabalho. -apps/frappe/frappe/config/setup.py +87,Log of error during requests.,Log de erro durante a solicitações. -apps/frappe/frappe/email/doctype/newsletter/newsletter.py +199,{0} has been successfully added to the Email Group.,"{0} foi adicionado com sucesso ao grupo de emails," -apps/frappe/frappe/public/js/frappe/upload.js +427,Make file(s) private or public?,Tornar o(s) arquivo(s) privados ou públicos? -DocType: DocShare,Everyone,Todos -apps/frappe/frappe/core/doctype/doctype/doctype.py +784,"{0}: Only one rule allowed with the same Role, Level and {1}","{0}: Apenas uma regra de permissão com a mesma função, nível e {1}" -DocType: Email Queue,Add Unsubscribe Link,Adicionar link para cancelar inscrição -apps/frappe/frappe/limits.py +35,"Your subscription expired on {0}. To renew, please send an email to {1}.","Sua inscrição expirou em {0}. Para renovar, por favor envie um e-mail para {1}." -apps/frappe/frappe/core/page/usage_info/usage_info.js +20,Renew / Upgrade,Renovação / Atualização -DocType: PayPal Settings,API Password,Senha da API -apps/frappe/frappe/custom/doctype/custom_field/custom_field.py +46,Fieldname not set for Custom Field,Fieldname não definida para campo personalizado -apps/frappe/frappe/public/js/frappe/model/model.js +22,Last Updated By,Última atualização por -apps/frappe/frappe/public/js/frappe/views/communication.js +594,There were errors while sending email. Please try again.,"Ocorreram erros durante o envio de email. Por favor, tente novamente." -DocType: Portal Settings,Portal Settings,Configurações do Portal -apps/frappe/frappe/core/doctype/communication/communication.js +127,Are you sure you want to relink this communication to {0}?,Você tem certeza que deseja relinkar a comunicação para {0}? -DocType: Email Group Member,Email Group Member,Membro do Grupo de Emails -DocType: Notification,Value Changed,Valor Alterado -apps/frappe/frappe/model/base_document.py +321,Duplicate name {0} {1},Nome duplicado {0} e {1} -DocType: Web Form Field,Web Form Field,Campo de Formulário Web -apps/frappe/frappe/custom/doctype/customize_form/customize_form.js +257,Hide field in Report Builder,Ocultar campo no Report Builder -apps/frappe/frappe/core/page/permission_manager/permission_manager.js +416,Restore Original Permissions,Restaurar permissões originais -apps/frappe/frappe/printing/doctype/print_format/print_format.py +80,{0} is now default print format for {1} doctype,{0} agora é o formato de impressão padrão para o doctype {1} -apps/frappe/frappe/public/js/frappe/views/kanban/kanban_board.js +338,Archived Columns,Colunas Arquivadas -DocType: Email Account,Default Outgoing,Outgoing Padrão -DocType: Workflow State,play,jogar -apps/frappe/frappe/core/page/permission_manager/permission_manager.js +401,Did not add,Não adicionado -DocType: Contact Us Settings,Contact Us Settings,Configurações do Fale Conosco -DocType: Workflow State,text-width,largura de texto -apps/frappe/frappe/public/js/legacy/form.js +141,Maximum Attachment Limit for this record reached.,Limite máximo de anexo para este recorde atingido. -DocType: Notification,View Properties (via Customize Form),Exibir Propriedades (via Personalizar Formulário) -DocType: Note Seen By,Note Seen By,Nota Vista por -DocType: Feedback Trigger,Check Communication,Checar Comunicação -apps/frappe/frappe/core/doctype/report/report.js +5,Report Builder reports are managed directly by the report builder. Nothing to do.,Os relatórios são gerenciados diretamente pelo sistema. Nada a fazer. -apps/frappe/frappe/email/doctype/newsletter/newsletter.py +169,Please verify your Email Address,"Por favor, verifique seu endereço de email" -apps/frappe/frappe/model/document.py +1074,none of,nenhum -apps/frappe/frappe/public/js/frappe/views/communication.js +91,Send Me A Copy,Envie-me uma Cópia -apps/frappe/frappe/config/website.py +7,Web Site,Web Site -apps/frappe/frappe/core/page/desktop/all_applications_dialog.html +8,Checked items will be shown on desktop,Itens marcados serão mostrado na área de trabalho -apps/frappe/frappe/core/doctype/doctype/doctype.py +825,{0} cannot be set for Single types,{0} não pode ser ajustada para os modelos únicos -apps/frappe/frappe/public/js/frappe/form/form_viewers.js +55,{0} are currently viewing this document,{0} está vendo atualmente este documento -apps/frappe/frappe/custom/doctype/customize_form/customize_form.py +155,{0} updated,{0} atualizado(a) -apps/frappe/frappe/core/doctype/doctype/doctype.py +817,Report cannot be set for Single types,Relatório não pode ser ajustada para os modelos únicos -DocType: Email Account,Awaiting Password,Aguardando Senha -DocType: Address,Address Line 1,Endereço -apps/frappe/frappe/utils/data.py +521,Cent,Centavo -apps/frappe/frappe/config/setup.py +226,"States for workflow (e.g. Draft, Approved, Cancelled).","Status para o fluxo de trabalho (por exemplo, rascunho, aprovado, cancelado)." -DocType: Print Settings,Allow Print for Draft,Permitir impressão para rascunho -apps/frappe/frappe/public/js/legacy/form.js +348,Submit this document to confirm,Enviar este documento para confirmar -DocType: Contact,Unsubscribed,Inscrição Cancelada -apps/frappe/frappe/public/js/frappe/misc/rating_icons.html +2,Rating: ,Rating: -apps/frappe/frappe/desk/page/setup_wizard/setup_wizard.js +419,Attach Your Picture,Anexe sua Imagem -apps/frappe/frappe/public/js/frappe/views/reports/query_report.js +562,Make ,Fazer -apps/frappe/frappe/core/doctype/version/version_view.html +69,Row Values Changed,Valores das Linhas Mudaram -DocType: Workflow State,Stop,Parar -DocType: Footer Item,Link to the page you want to open. Leave blank if you want to make it a group parent.,Link para a página que você deseja abrir. Deixe em branco se você quiser torná-lo um pai grupo. -DocType: DocType,Is Single,É Único -apps/frappe/frappe/email/queue.py +335,{0} has left the conversation in {1} {2},{0} deixou a conversa em {1} {2} -DocType: Blogger,User ID of a Blogger,ID do usuário de um Blogger -apps/frappe/frappe/core/doctype/user/user.py +299,There should remain at least one System Manager,Não deve permanecer pelo menos um gestor de sistema -DocType: Workflow State,circle-arrow-right,círculo de seta à direita -apps/frappe/frappe/public/js/legacy/form.js +72,Cannot open instance when its {0} is open,"Não é possível abrir instância , quando o seu {0} é aberto" -DocType: Newsletter,Send Unsubscribe Link,Enviar link para cancelar inscrição -DocType: Report,Script Report,Relatório Script -DocType: User,Modules HTML,Módulos HTML -apps/frappe/frappe/public/js/frappe/ui/field_group.js +97,Missing Values Required,Faltando valores obrigatórios -DocType: DocType,Other Settings,Outros Ajustes -DocType: Customize Form,Change Label (via Custom Translation),Alterar etiqueta (via tradução personalizada) -apps/frappe/frappe/public/js/frappe/form/workflow.js +44,Note: Other permission rules may also apply,Observação: Outras regras de permissão também podem ser aplicáveis -apps/frappe/frappe/templates/emails/print_link.html +2,View this in your browser,Veja isto no seu navegador -apps/frappe/frappe/public/js/legacy/print_format.js +124,No document selected,Nenhum documento selecionado -apps/frappe/frappe/custom/doctype/customize_form/customize_form.js +133,Cannot delete standard field. You can hide it if you want,Não é possível excluir campo padrão. Você pode escondê-lo se você quiser -DocType: Top Bar Item,For top bar,Para barra superior -apps/frappe/frappe/core/doctype/user/user.py +206,Welcome email sent,Email de Boas Vindas enviado -apps/frappe/frappe/core/doctype/user/user.py +765,Already Registered,Já está registrado -DocType: System Settings,Float Precision,Precisão de Casas Decimais -apps/frappe/frappe/core/doctype/page/page.py +41,Only Administrator can edit,Somente o Administrador pode editar -DocType: DocType,Editable Grid,Grid Editável -DocType: Property Setter,Property Setter,Configurador de Propriedades -DocType: Web Form,Allow Print,Permitir Impressão -apps/frappe/frappe/custom/doctype/customize_form/customize_form.js +241,Mark the field as Mandatory,Marque o campo como obrigatório -DocType: DocType,Track Seen,Marcar como visto -apps/frappe/frappe/public/js/frappe/list/list_renderer.js +629,No {0} found,Nenhum(a) {0} encontrado(a) -apps/frappe/frappe/config/setup.py +264,Add custom forms.,Adicionar formulários personalizados. -apps/frappe/frappe/public/js/frappe/form/footer/timeline.js +518,submitted this document,enviou este documento -apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +9,The system provides many pre-defined roles. You can add new roles to set finer permissions.,O sistema disponibiliza várias funções pré-definidas. Você pode adicionar novas funções para definir permissões mais específicas. -DocType: Blog Category,Blog Category,Categoria do Blog -apps/frappe/frappe/model/mapper.py +123,Cannot map because following condition fails: ,Não é possível mapear porque seguinte condição de falha: -DocType: Role Permission for Page and Report,Roles HTML,Funções HTML -apps/frappe/frappe/website/doctype/website_settings/website_settings.js +10,Select a Brand Image first.,Selecione o Logo da Marca primeiro. -apps/frappe/frappe/custom/doctype/customize_form/customize_form.js +168,All customizations will be removed. Please confirm.,Todas as personalizações serão removidos. Por favor confirme. -apps/frappe/frappe/public/js/frappe/views/treeview.js +295,Further nodes can be only created under 'Group' type nodes,"Outros nós só podem ser criados dentro dos nós do tipo ""grupo""" -apps/frappe/frappe/public/js/frappe/model/model.js +90,Unknown Column: {0},Coluna desconhecida: {0} -DocType: Notification Recipient,Email By Role,Email por Função -apps/frappe/frappe/core/page/permission_manager/permission_manager.js +291,Users with role {0}:,Os usuários com a função {0}: -DocType: Workflow State,random,randômico -DocType: Newsletter Email Group,Newsletter Email Group,Grupo de Email de Newsletter -apps/frappe/frappe/desk/query_report.py +48,Must specify a Query to run,Deve especificar uma consulta para executar -apps/frappe/frappe/config/setup.py +76,"Language, Date and Time settings","Configurações de Idioma , Data e Hora" -DocType: User Email,User Email,Email do Usuário -DocType: User,Represents a User in the system.,Representa um usuário no sistema. -DocType: Communication,Label,Etiqueta -DocType: Print Format,Print Format Type,Tipo do Formato de Impressão -DocType: Newsletter,A Lead with this Email Address should exist,Um cliente em potencial com este email deve existir -apps/frappe/frappe/public/js/frappe/ui/toolbar/about.js +7,Open Source Applications for the Web,Aplicativos Open Source para a Web -DocType: Event,Call,Chamada Telefônica -DocType: Website Theme,"Add the name of a ""Google Web Font"" e.g. ""Open Sans""",Adicione o nome de um "Google Web Font" por exemplo "Open Sans" -apps/frappe/frappe/public/js/frappe/request.js +178,Request Timed Out,Solicitação expirada -DocType: Role Permission for Page and Report,Allow Roles,Permitir Funções -DocType: User,Last Active,Ativo pela última vez -DocType: Email Account,SMTP Settings for outgoing emails,Configurações de SMTP para envio de emails -DocType: Email Account,Auto Reply Message,Resposta Automática -DocType: Contact,User ID,ID de Usuário -DocType: File,Lft,LFT -apps/frappe/frappe/public/js/frappe/ui/toolbar/awesome_bar.js +138,Open a module or tool,Abra um módulo ou ferramenta -DocType: Communication,Delivery Status,Status da Entrega -DocType: Module Def,App Name,Nome do App -DocType: Workflow,"Field that represents the Workflow State of the transaction (if field is not present, a new hidden Custom Field will be created)","Campo que representa o status da transação no fluxo de trabalho (se o campo não estiver presente, um novo campo oculto personalizado será criado)" -DocType: Help Article,Knowledge Base Contributor,Colaborador da Base de Conhecimento -DocType: Communication,Sent Read Receipt,Enviar Confirmação de Leitura -DocType: Feedback Request,Reference Communication,Comunicação de Referência -DocType: Email Queue,Unsubscribe Method,Método de Cancelamento de Inscrição -apps/frappe/frappe/public/js/frappe/views/communication.js +99,Select Languages,Selecionar Idiomas -apps/frappe/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py +88,Seems API Key or API Secret is wrong !!!,Parece que a chave API ou o segredo da API estão errados !!! -DocType: File,Attached To Name,Anexado Para Nome -apps/frappe/frappe/email/receive.py +94,Invalid User Name or Support Password. Please rectify and try again.,"Nome de usuário ou senha inválidos. Por favor, corrigir e tentar novamente." -DocType: Email Account,Yahoo Mail,Email do Yahoo -apps/frappe/frappe/limits.py +77,Your subscription will expire tomorrow.,Sua inscrição expira amanhã. -apps/frappe/frappe/desk/page/setup_wizard/install_fixtures.py +16,Master,Cadastro -DocType: DocType,User Cannot Create,O Usuário não pode criar -apps/frappe/frappe/core/doctype/file/file.py +586,Folder {0} does not exist,Pasta {0} não existe -apps/frappe/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py +341,Dropbox access is approved!,O acesso ao Dropbox está aprovado! -DocType: Customize Form,Enter Form Type,Digite o Tipo de Formulário -apps/frappe/frappe/public/js/frappe/list/list_sidebar_stat.html +5,No records tagged.,Não há registros marcados. -apps/frappe/frappe/printing/page/print_format_builder/print_format_builder.js +466,Remove Field,Remover Campo -DocType: User,Send Password Update Notification,Enviar notificação de alteração de senha -apps/frappe/frappe/public/js/legacy/form.js +62,"Allowing DocType, DocType. Be careful!","Permitindo DocType , DocType . Tenha cuidado !" -apps/frappe/frappe/config/core.py +32,"Customized Formats for Printing, Email","Formatos personalizados para impressão, Email" -apps/frappe/frappe/public/js/frappe/desk.js +483,Updated To New Version,Atualizado para uma Nova Versão -DocType: Custom Field,Depends On,Depende de -apps/frappe/frappe/templates/includes/comments/comments.html +21,Login to comment,Faça login para comentar -apps/frappe/frappe/public/js/frappe/form/footer/timeline.js +573,changed values for {0},mudou o valor para {0} -DocType: Workflow State,retweet,retwitar -DocType: Workflow State,eye-close,olho fechado -DocType: OAuth Provider Settings,OAuth Provider Settings,Configurações do Provedor OAuth -apps/frappe/frappe/public/js/frappe/request.js +390,Report this issue,Reportar erro -DocType: Custom Script,Adds a custom script (client or server) to a DocType,Adiciona um script personalizado (cliente ou servidor) para um Tipo de Documento (DocType) -DocType: Address,City/Town,Cidade / Município -DocType: Address,Is Your Company Address,É o seu endereço comercial -apps/frappe/frappe/public/js/frappe/form/grid_row_form.js +43,Editing Row,Editando Linha -DocType: Workflow Action Master,Workflow Action Master,Cadastro de Ação do Fluxo de Trabalho -DocType: Custom Field,Field Type,Tipo de Campo -apps/frappe/frappe/utils/data.py +551,only.,apenas. -apps/frappe/frappe/utils/password_strength.py +135,Avoid years that are associated with you.,Evite anos associados a você. -apps/frappe/frappe/public/js/frappe/views/reports/reportview.js +669,Descending,Descendente -apps/frappe/frappe/utils/goal.py +117,Goal,Meta -apps/frappe/frappe/email/receive.py +60,Invalid Mail Server. Please rectify and try again.,"Mail Server inválido . Por favor, corrigir e tentar novamente." -DocType: DocField,"For Links, enter the DocType as range. -For Select, enter list of Options, each on a new line.","Para Links, insira o DocType como intervalo. Para Selecionar, digite lista de opções, cada um em uma nova linha." -apps/frappe/frappe/utils/nestedset.py +241,Multiple root nodes not allowed.,"Vários nós raiz, não é permitido ." -apps/frappe/frappe/public/js/frappe/views/reports/reportview.js +542,ID field is required to edit values using Report. Please select the ID field using the Column Picker,"Campo ID é necessária para editar valores usando Report. Por favor, selecione o campo ID usando o seletor de Coluna" -apps/frappe/frappe/www/login.html +59,Forgot Password?,Esqueceu a senha? -DocType: System Settings,yyyy-mm-dd,dd/mm/yyyy -apps/frappe/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py +192,Server Error,Erro de Servidor -apps/frappe/frappe/email/doctype/email_account/email_account.py +46,Login Id is required,ID de login é necessária -DocType: Website Slideshow,Website Slideshow,Slideshow do Site -DocType: Website Settings,"Link that is the website home page. Standard Links (index, login, products, blog, about, contact)","Link da home page do site. Links padrão (index, login, products, blog, about, contact)" -DocType: User,Banner Image,Imagem do Banner -apps/frappe/frappe/email/doctype/notification/notification.py +32,Please specify which date field must be checked,Por favor especificar qual campo de data deve ser verificado -DocType: Custom DocPerm,Set User Permissions,Definir Permissões de Usuário -DocType: File,old_parent,old_parent -apps/frappe/frappe/config/desk.py +54,"Newsletters to contacts, leads.",Email Marketing para Contatos e Clientes em Potencial. -DocType: Email Account,"e.g. ""Support"", ""Sales"", ""Jerry Yang""","ex: ""Pós-Venda"", "" Vendas "", ""Edmilson""" -DocType: Print Settings,Repeat Header and Footer in PDF,Repetir cabeçalho e rodapé no PDF -apps/frappe/frappe/desk/doctype/kanban_board/kanban_board.py +24,Column Name cannot be empty,Nome da coluna não pode estar em branco -DocType: Workflow State,fast-forward,avanço rápido -apps/frappe/frappe/printing/page/print_format_builder/print_format_builder_column_selector.html +1,"Check columns to select, drag to set order.","Verifique colunas para selecionar, arrastar para definir a ordem." -DocType: Event,Every Day,Todos os dias -apps/frappe/frappe/core/doctype/version/version_view.html +73,Table Field,Campo da Tabela -apps/frappe/frappe/public/js/frappe/views/kanban/kanban_view.js +278,Columns based on,Colunas baseadas em -apps/frappe/frappe/model/document.py +1272,Action Failed,A Ação Falhou -DocType: List Filter,For User,Para o Usuário -DocType: System Settings,Date and Number Format,Data e Formato de número -apps/frappe/frappe/model/document.py +1073,one of,Um dos -apps/frappe/frappe/public/js/frappe/desk.js +161,Checking one moment,"Checando, um momento" -apps/frappe/frappe/public/js/frappe/list/list_sidebar_stat.html +21,Show Tags,Mostrar Tags -DocType: Address,Billing,Faturamento -DocType: Email Queue,Not Sent,Não Enviados -DocType: Workflow State,align-justify,Justificar -apps/frappe/frappe/public/js/frappe/ui/field_group.js +98,Following fields have missing values:,Os campos a seguir estão em branco: -apps/frappe/frappe/app.py +158,You do not have enough permissions to complete the action,Você não tem permissão suficiente para completar a ação -apps/frappe/frappe/public/js/frappe/form/link_selector.js +103,No Results,nenhum resultado -DocType: System Settings,Security,Segurança -DocType: Currency,**Currency** Master,**Moeda** Principal -DocType: Email Account,No of emails remaining to be synced,Nº de emails a serem sincronizados -apps/frappe/frappe/public/js/frappe/form/footer/assign_to.js +84,Please save the document before assignment,"Por favor, salve o documento antes da atribuição" -DocType: Website Settings,Address and other legal information you may want to put in the footer.,Endereço e outras informações legais que você pode querer colocar no rodapé. -DocType: Website Sidebar Item,Website Sidebar Item,Item do Menu Lateral do Site -apps/frappe/frappe/core/page/permission_manager/permission_manager.js +49,Select Document Type,Selecione o Tipo de Documento -apps/frappe/frappe/utils/nestedset.py +217,Cannot delete {0} as it has child nodes,"Não é possível excluir {0} , pois tem nós filhos" -apps/frappe/frappe/public/js/frappe/misc/pretty_date.js +48,{0} minutes ago,{0} minutos atrás -apps/frappe/frappe/templates/includes/list/filters.html +19,clear,claro -apps/frappe/frappe/desk/doctype/event/event.py +32,Every day events should finish on the same day.,Eventos cada dia deve terminar no mesmo dia. -DocType: Communication,User Tags,Etiquetas de Usuários -DocType: Communication,Feedback Request,Solicitação de Feedback -apps/frappe/frappe/www/login.html +29,Sign in,Entrar -DocType: System Settings,Backups,Backups -apps/frappe/frappe/public/js/frappe/form/layout.js +170,Hide Details,Ocultar Detalhes -apps/frappe/frappe/www/qrcode.py +32,Page has expired!,A página expirou! -DocType: Workflow State,Tasks,Tarefas -DocType: Blog Settings,Blog Settings,Configurações do Blog -DocType: Workflow State,bullhorn,megafone -DocType: Footer Item,Target,Meta -DocType: Website Settings,Copyright,Direitos autorais -apps/frappe/frappe/public/js/frappe/views/gantt/gantt_view.js +145,Quarter Day,1/4 do Dia -DocType: Website Settings,Hide Footer Signup,Esconder Link de Inscrição do Rodapé -apps/frappe/frappe/public/js/frappe/form/footer/timeline.js +520,cancelled this document,cancelou este documento -apps/frappe/frappe/core/doctype/report/report.js +16,Write a Python file in the same folder where this is saved and return column and result.,Gravar um arquivo Python na mesma pasta onde este é guardado e coluna de retorno e resultado. -DocType: DocType,Sort Field,Ordenar por campo -apps/frappe/frappe/public/js/frappe/ui/filters/filter.js +266,Edit Filter,Edit Filter -apps/frappe/frappe/core/doctype/doctype/doctype.py +515,Field {0} of type {1} cannot be mandatory,O campo {0} do tipo {1} não pode ser obrigatória -apps/frappe/frappe/public/js/frappe/ui/slides.js +29,Add More,Adicionar mais -DocType: System Settings,Session Expiry Mobile,Duração da Sessão Móvel -apps/frappe/frappe/templates/includes/search_box.html +18,Search results for,Pesquisar resultados para -apps/frappe/frappe/public/js/frappe/views/reports/grid_report.js +821,Select To Download:,Selecione para Download: -DocType: Custom DocPerm,If user is the owner,Se o usuário é o proprietário -DocType: Note,"Help: To link to another record in the system, use ""#Form/Note/[Note Name]"" as the Link URL. (don't use ""http://"")","Ajuda: Para vincular a outro registro no sistema, use "# Form / Nota / [Nota Name]" como a ligação URL. (Não use "http://")" -apps/frappe/frappe/config/setup.py +248,Add fields to forms.,Adicionar campos nos formulários. -DocType: Portal Menu Item,Portal Menu Item,Portal item de menu -DocType: Contact Us Settings,Email ID,Email ID -DocType: Translation,Translated Text,Texto Traduzido -DocType: Patch Log,Patch Log,Log de Patches -DocType: Communication,Sent or Received,Enviados ou recebidos -DocType: DefaultValue,Key,Chave -DocType: Address,Contacts,Contatos -DocType: System Settings,Setup Complete,Instalação Concluída -apps/frappe/frappe/config/setup.py +64,Report of all document shares,Relatório de todas as ações de documentos -apps/frappe/frappe/www/update-password.html +18,New Password,Nova senha -apps/frappe/frappe/core/doctype/activity_log/activity_log.py +29,Sorry! You cannot delete auto-generated comments,Desculpe! Você não pode excluir comentários gerados automaticamente -DocType: User,System User,Usuário do Sistema -DocType: DocField,"Don't HTML Encode HTML tags like <script> or just characters like < or >, as they could be intentionally used in this field","Não etiquetas HTML Encode HTML como <script> ou apenas caracteres como <ou>, uma vez que poderia ser usado intencionalmente neste campo" -DocType: Workflow State,minus-sign,sinal de menos -apps/frappe/frappe/public/js/frappe/request.js +110,Not Found,Não encontrado -apps/frappe/frappe/custom/doctype/customize_form/customize_form.js +92,Export Custom Permissions,Exportar Permissões Personalizadas -DocType: Activity Log,Login,Entrar -DocType: System Settings,Enable Scheduled Jobs,Ativar Tarefas Agendadas -DocType: DocShare,Document Name,Nome do documento -DocType: ToDo,Medium,Média -DocType: Currency,A symbol for this currency. For e.g. $,Um símbolo para esta moeda. Por exemplo: R$ -apps/frappe/frappe/public/js/frappe/ui/toolbar/about.js +4,Frappe Framework,Frappe Framework -apps/frappe/frappe/model/naming.py +210,Name of {0} cannot be {1},Nome de {0} não pode ser {1} -apps/frappe/frappe/core/report/feedback_ratings/feedback_ratings.js +33,From Date,A Partir da Data -apps/frappe/frappe/public/js/frappe/feedback.js +95,Feedback Request for {0} is sent to {1},Solicitação de Feedback para {0} foi enviada para {1} -DocType: Kanban Board Column,Kanban Board Column,Coluna do Painel Kanban -DocType: Communication,Phone No.,Nº de Telefone. -apps/frappe/frappe/desk/doctype/bulk_update/bulk_update.py +23,; not allowed in condition,; não permitido na condição -DocType: Print Format,Custom HTML Help,Ajuda HTML Personalizado -apps/frappe/frappe/website/doctype/contact_us_settings/contact_us_settings.js +3,See on Website,Veja no Site -apps/frappe/frappe/model/db_schema.py +153,Reverting length to {0} for '{1}' in '{2}'; Setting the length as {3} will cause truncation of data.,Revertendo comprimento para {0} para '{1}' em '{2}'; Definir o comprimento como {3} irá causar truncamento de dados. -DocType: Print Format,Custom CSS,CSS Personalizado -apps/frappe/frappe/model/rename_doc.py +429,Ignored: {0} to {1},Ignorados: {0} para {1} -apps/frappe/frappe/config/setup.py +82,Log of error on automated events (scheduler).,Log de erro sobre eventos automatizados ( programador ) . -apps/frappe/frappe/utils/csvutils.py +82,Not a valid Comma Separated Value (CSV File),Não é um valor CSV válido (arquivo CSV) -DocType: Email Account,Default Incoming,Padrão de Entrada -DocType: Website Settings,Banner,Faixa -apps/frappe/frappe/core/doctype/user/user.py +763,Registered but disabled,Registrado mas desativado -DocType: DocType,Hide Copy,Ocultar Cópia -apps/frappe/frappe/public/js/frappe/roles_editor.js +40,Clear all roles,Desmarque todas as funções -apps/frappe/frappe/model/base_document.py +373,{0} must be unique,{0} já foi cadastrado e deve ser único -DocType: DocType,Track Changes,Rastrear Alterações -DocType: Chat Profile,Offline,Offline -DocType: User,API Key,Chave da API -apps/frappe/frappe/desk/page/modules/modules.js +22,Install Apps,Instalar Aplicativos -apps/frappe/frappe/custom/doctype/custom_field/custom_field.js +66,Fieldname which will be the DocType for this link field.,Nome do campo que será o DocType para este campo link. -apps/frappe/frappe/config/desk.py +14,Documents assigned to you and by you.,Documentos atribuídos a você e por você. -DocType: Website Settings,Google Analytics ID,ID do Google Analytics -DocType: Custom DocPerm,Delete,Excluir -apps/frappe/frappe/public/js/frappe/views/treeview.js +242,New {0},Novo(a) {0} -apps/frappe/frappe/public/js/frappe/form/multi_select_dialog.js +58,Make a new,Fazer um(a) novo(a) -DocType: Print Settings,PDF Page Size,Tamanho da página PDF -DocType: Communication,Recipient Unsubscribed,Destinatário com inscrição cancelada -DocType: Feedback Request,Is Sent,É Enviado -apps/frappe/frappe/core/doctype/data_import/exporter.py +68,"For updating, you can update only selective columns.","Para a atualização, você pode atualizar colunas só seletivos." -DocType: Notification,"Trigger on valid methods like ""before_insert"", ""after_update"", etc (will depend on the DocType selected)","Gatilho em métodos válidos como ""before_insert"", ""after_update"", etc. (dependerá do DocType selecionado)" -apps/frappe/frappe/core/doctype/user/user.py +132,Adding System Manager to this User as there must be atleast one System Manager,Adicionando este usuário como System Manager pois deve haver pelo menos um System Manager -DocType: Workflow State,list-alt,lista de alt- -DocType: Email Queue,Expose Recipients,Mostrar Destinatários -apps/frappe/frappe/email/doctype/email_account/email_account.py +62,Append To is mandatory for incoming mails,Para acrescentar é obrigatório para os e-mails recebidos -DocType: Report,Query Report,Relatório da Consulta -apps/frappe/frappe/email/doctype/auto_email_report/auto_email_report.py +54,"%s is not a valid report format. Report format should \ - one of the following %s",%s não é um formato válido de relatório. O formato do relatório deve ser um dos seguintes %s -DocType: Chat Message,Chat,Conversa ou Chat -apps/frappe/frappe/core/doctype/doctype/doctype.py +508,Fieldname {0} appears multiple times in rows {1},Fieldname {0} aparece várias vezes em linhas {1} -apps/frappe/frappe/public/js/frappe/form/footer/timeline.js +559,{0} from {1} to {2} in row #{3},{0} de {1} para {2} na linha #{3} -DocType: Customize Form Field,Number of columns for a field in a Grid (Total Columns in a grid should be less than 11),O número de colunas para um campo numa Grelha (O Total de Colunas em um grid deve ser inferior a 11) -apps/frappe/frappe/www/login.html +76,Have an account? Login,Possui cadastro? Entre -apps/frappe/frappe/public/js/legacy/print_format.js +148,Unknown Print Format: {0},Formato de Impressão desconhecido: {0} -DocType: Workflow State,arrow-down,seta para baixo -apps/frappe/frappe/model/delete_doc.py +171,User not allowed to delete {0}: {1},Usuário não tem permissão para excluir {0}: {1} -apps/frappe/frappe/public/js/frappe/model/model.js +21,Last Updated On,Última atualização em -DocType: SMS Settings,Message Parameter,Parâmetro da mensagem -DocType: Help Article,Likes,Likes -DocType: Website Settings,Top Bar,Barra superior -apps/frappe/frappe/core/doctype/file/test_file.py +217,Home/Test Folder 2,Início / Teste pasta 2 -apps/frappe/frappe/public/js/frappe/form/controls/attach.js +48,Please save the document before uploading.,"Por favor, salve o documento antes de fazer upload." -apps/frappe/frappe/public/js/frappe/ui/messages.js +215,Enter your password,Digite sua senha -DocType: Dropbox Settings,Dropbox Access Secret,Segredo de Acesso Dropbox -apps/frappe/frappe/core/doctype/doctype/doctype.py +599,Fold must come before a Section Break,Dobre deve vir antes de uma quebra de secção -apps/frappe/frappe/public/js/frappe/model/meta.js +185,Last Modified By,Última Alteração por -DocType: Workflow State,hand-down,mão abaixo -apps/frappe/frappe/core/doctype/doctype/doctype.py +803,{0}: Cannot set Cancel without Submit,{0}: Não é possível definir Cancelar sem Submeter -DocType: DocType,Is Submittable,Pode ser Enviado -apps/frappe/frappe/core/doctype/communication/comment.py +109,New Mention,Nova Menção -apps/frappe/frappe/core/doctype/data_import/exporter.py +268,Column Labels:,Rótulos de coluna: -apps/frappe/frappe/model/naming.py +85,Naming Series mandatory,Nomeando obrigatório Series -DocType: Workflow State,Tag,Tag -DocType: Custom Script,Script,Script -apps/frappe/frappe/public/js/frappe/ui/toolbar/navbar.html +28,My Settings,Minhas Configurações -DocType: Desktop Icon,Force Show,Forçar Exibição -apps/frappe/frappe/auth.py +82,Invalid Request,Requisição Inválida -apps/frappe/frappe/public/js/frappe/form/layout.js +28,This form does not have any input,Este formulário não tem nenhum campo a ser preenchido -DocType: Footer Item,"Select target = ""_blank"" to open in a new page.","Select target = "" _blank"" para abrir em uma nova página." -apps/frappe/frappe/public/js/frappe/model/model.js +518,Permanently delete {0}?,Excluir Permanentemente {0} ? -DocType: Website Settings,Disable Signup,Desativar Registre-se -DocType: Email Queue,Email Queue,Fila de Emails -apps/frappe/frappe/core/page/desktop/desktop.py +14,Add Employees to Manage Them,Adicione colaboradores para gerí-los -apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +7,Roles can be set for users from their User page.,As funções podem ser definidas para os usuários através de sua página de Usuário. -apps/frappe/frappe/core/doctype/doctype/doctype.py +771,{0}: No basic permissions set,{0}: Nenhum conjunto de permissões básico -apps/frappe/frappe/limits.py +80,Your subscription will expire on {0}.,Sua inscrição irá expirar em {0}. -apps/frappe/frappe/utils/backups.py +166,Download link for your backup will be emailed on the following email address: {0},Link de download para o seu backup será enviado por email no seguinte endereço de email: {0} -apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +14,"Meaning of Submit, Cancel, Amend","Significado de Enviar, Cancelar, Corrigir" -apps/frappe/frappe/desk/doctype/todo/todo_list.js +9,To Do,Atribuições -apps/frappe/frappe/desk/form/assign_to.py +197,New Message,Nova Mensagem -DocType: File,Preview HTML,Pré-visualização de HTML -apps/frappe/frappe/public/js/frappe/views/kanban/kanban_view.js +101,Filters saved,Filtros salvos -DocType: DocField,Percent,Por cento -apps/frappe/frappe/public/js/frappe/views/reports/query_report.js +660,Please set filters,"Por favor, defina filtros" -apps/frappe/frappe/public/js/frappe/form/linked_with.js +28,Linked With,Relacionado com -DocType: Website Settings,Landing Page,Página de chegada -apps/frappe/frappe/public/js/frappe/form/quick_entry.js +90,{0} Name,{0} Nome -apps/frappe/frappe/core/page/permission_manager/permission_manager.js +171,No Permissions set for this criteria.,Sem permissões definidas para este critério. -apps/frappe/frappe/public/js/frappe/form/footer/timeline.js +663,Delete comment?,Excluir comentário? -DocType: Address Template,This format is used if country specific format is not found,Este formato é usado se o formato específico país não é encontrado -apps/frappe/frappe/public/js/frappe/request.js +137,You do not have enough permissions to access this resource. Please contact your manager to get access.,"Você não tem permissão suficiente para acessar este recurso. Por favor, contate o administrador para ter acesso." -DocType: Workflow,Transitions,Transições -apps/frappe/frappe/desk/page/activity/activity_row.html +34,{0} {1} to {2},{0} {1} para {2} -DocType: User,Login After,Login após -DocType: Print Format,Monospace,Monospace -apps/frappe/frappe/core/doctype/doctype/doctype.py +566,Precision should be between 1 and 6,Precisão deve estar entre 1 e 6 -apps/frappe/frappe/patches/v6_19/comment_feed_communication.py +131,Assignment,Tarefa -DocType: Workflow State,step-backward,voltar -apps/frappe/frappe/utils/boilerplate.py +265,{app_title},{app_title} -apps/frappe/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py +259,Please set Dropbox access keys in your site config,Defina teclas de acesso Dropbox em sua configuração local -apps/frappe/frappe/email/doctype/email_unsubscribe/email_unsubscribe.py +16,Delete this record to allow sending to this email address,Excluir este registro para permitir o envio para esse endereço de email -apps/frappe/frappe/core/doctype/data_import/exporter.py +67,Only mandatory fields are necessary for new records. You can delete non-mandatory columns if you wish.,"Somente os campos obrigatórios são necessários para novos registros. Você pode excluir colunas não-obrigatórias, se desejar." -apps/frappe/frappe/website/doctype/web_form/templates/web_form.html +134,Payment Complete,Pagamento finalizado -apps/frappe/frappe/utils/bot.py +89,show,mostrar -DocType: Workflow State,text-height,altura de texto -DocType: Workflow State,map-marker,marcador do mapa -apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +39,Submit an Issue,Enviar um problema -DocType: Event,Repeat this Event,Repita este evento -DocType: Address,Maintenance User,Usuário da Manutenção -apps/frappe/frappe/utils/password_strength.py +143,Avoid dates and years that are associated with you.,Evite datas e anos associados a você. -DocType: Custom DocPerm,Amend,Corrigir -DocType: File,Is Attachments Folder,É Pasta de Anexos -apps/frappe/frappe/templates/includes/login/login.js +52,Valid Login id required.,É necessário um usuário válido. -apps/frappe/frappe/model/rename_doc.py +413,Please select a valid csv file with data,"Por favor, selecione um arquivo csv com dados válidos" -apps/frappe/frappe/core/doctype/docshare/docshare.py +56,{0} un-shared this document with {1},{0} descompartilhou este documento com {1} -DocType: DocType,"Make ""name"" searchable in Global Search","Tornar ""nome"" pesquisável na Busca Global" -apps/frappe/frappe/core/doctype/version/version_view.html +74,Row # ,Linha # -DocType: Help Category,Category Description,Descrição da Categoria -apps/frappe/frappe/model/document.py +634,Record does not exist,Registro não existe -apps/frappe/frappe/core/doctype/version/version_view.html +13,Original Value,Valor Original -DocType: Help Category,Help Category,Categoria de Ajuda -apps/frappe/frappe/utils/oauth.py +240,User {0} is disabled,Usuário {0} está desativado -apps/frappe/frappe/www/404.html +21,Page missing or moved,Página ausente ou mudou -DocType: Tag Category,Doctypes,Doctypes -apps/frappe/frappe/desk/query_report.py +52,Query must be a SELECT,Consulta deve ser um SELECT -DocType: File,Is Private,É privada -DocType: Data Export,Select DocType,Selecione o DocType -apps/frappe/frappe/public/js/frappe/request.js +148,File size exceeded the maximum allowed size of {0} MB,O tamanho do arquivo excedeu o tamanho máximo permitido de {0} MB -apps/frappe/frappe/email/doctype/notification/notification.js +33,Created On,Criado em -DocType: Workflow State,align-center,Centralizar -apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +16,"Certain documents, like an Invoice, should not be changed once final. The final state for such documents is called Submitted. You can restrict which roles can Submit.","Alguns documentos , como uma fatura , não deve ser trocada uma vez final. O estado final de tais documentos é chamado Enviado. Você pode restringir quais funções pode se submeter." -apps/frappe/frappe/templates/includes/comments/comments.html +27,Leave a Comment,Deixe um comentário -DocType: Web Page,Description for search engine optimization.,Descrição para search engine optimization. -DocType: Web Form Field,Page Break,Quebra de Página -DocType: System Settings,Allow only one session per user,Permitir apenas uma sessão por usuário -apps/frappe/frappe/core/doctype/file/test_file.py +241,Home/Test Folder 1/Test Folder 3,Pasta Principal / Teste 1 / Teste Pasta 3 -DocType: DocField,In Filter,No Filtro da Lista -apps/frappe/frappe/core/doctype/communication/communication.js +53,Relink,Relinkar -DocType: Web Page,"Page to show on the website -",Página para mostrar no site -apps/frappe/frappe/www/third_party_apps.html +47,Logged in,Logado -apps/frappe/frappe/integrations/doctype/ldap_settings/ldap_settings.py +41,Incorrect UserId or Password,Usuário ou senha inválidos -apps/frappe/frappe/email/doctype/email_account/email_account_list.js +6,Default Sending and Inbox,Padrão para Envio e Recebimento -apps/frappe/frappe/core/report/feedback_ratings/feedback_ratings.js +21,Document ID,ID do Documento -apps/frappe/frappe/core/doctype/doctype/doctype.py +654,Image field must be of type Attach Image,Campo de imagem deve ser do tipo Anexar Imagem -apps/frappe/frappe/public/js/frappe/form/save.js +150,Mandatory fields required in {0},Os campos obrigatórios exigidos no {0} -apps/frappe/frappe/core/page/permission_manager/permission_manager.js +102,Reset Permissions for {0}?,Repor permissões para {0} ? -DocType: S3 Backup Settings,S3 Backup Settings,Configurações de Backup S3 -apps/frappe/frappe/core/doctype/version/version_view.html +32,Rows Removed,Linhas Excluídas -apps/frappe/frappe/permissions.py +359,{0} {1} not found,{0} {1} não encontrado -apps/frappe/frappe/www/login.py +48,Mobile Number,Telefone Celular -DocType: Workflow State,align-left,Alinhar à esquerda -DocType: Feedback Request,Feedback Submitted,Feedback Enviado -apps/frappe/frappe/public/js/frappe/model/model.js +541,Merge with existing,Mesclar com existente -DocType: Dynamic Link,Link Title,Título do Link -DocType: Workflow State,fast-backward,retrocesso rápido -apps/frappe/frappe/public/js/frappe/form/quick_entry.js +216,Edit in full page,Editar em página completa -DocType: Report,Add Total Row,Adicionar Linha de Total -apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +19,For example if you cancel and amend INV004 it will become a new document INV004-1. This helps you to keep track of each amendment.,"Por exemplo, se você cancelar e corrigir o INV004, ele vai se tornar um novo documento chamado INV004-1. Isso ajuda você a manter o controle de cada alteração." -DocType: File,Attached To DocType,Anexado ao Doctype -DocType: DocField,Int,Inteiro -apps/frappe/frappe/www/feedback.html +96,Please give a detailed feebdack.,"Por favor, dê um feedback detalhado." -DocType: Currency,"1 Currency = [?] Fraction -For e.g. 1 USD = 100 Cent","1 Moeda = [?] Fração - Por exemplo, 1 USD = 100 Centavos" -apps/frappe/frappe/public/js/frappe/form/link_selector.js +26,You can use wildcard %,Você pode usar o coringa % -apps/frappe/frappe/public/js/frappe/upload.js +299,"Only image extensions (.gif, .jpg, .jpeg, .tiff, .png, .svg) allowed","Somente as extensões de imagem (.gif, .jpg, .jpeg, .tiff, .png, .svg) são permitidos" -DocType: DocType,Database Engine,Engine do Banco de Dados -DocType: Customize Form,"Fields separated by comma (,) will be included in the ""Search By"" list of Search dialog box","Campos separados por vírgula (,) será incluído no "Pesquisar por" lista de caixa de diálogo Pesquisar" -apps/frappe/frappe/website/doctype/website_theme/website_theme.py +35,Please Duplicate this Website Theme to customize.,Por favor Duplicar este site Tema para personalizar. -apps/frappe/frappe/config/website.py +73,Settings for About Us Page.,Configurações para a Página Sobre Nós. -DocType: Error Snapshot,Error Snapshot,Snapshot de Erro -apps/frappe/frappe/public/js/frappe/ui/filters/filters.js +512,In,em -DocType: Notification,Value Change,Mudança de Valor -apps/frappe/frappe/custom/doctype/customize_form/customize_form.js +235,Width of the input box,Largura de entrada da caixa -apps/frappe/frappe/email/smtp.py +224,Invalid Outgoing Mail Server or Port,Inválido Outgoing Mail Server ou Porto -apps/frappe/frappe/core/doctype/report/report.py +37,Only Administrator allowed to create Query / Script Reports,Somente o Administrador pode criar Consulta / Relatórios de Script -apps/frappe/frappe/public/js/frappe/form/save.js +13,Updating,Atualizando -apps/frappe/frappe/desk/doctype/bulk_update/bulk_update.js +8,"Field ""value"" is mandatory. Please specify value to be updated","O campo ""valor"" é obrigatório. Por favor, especifique o valor a ser atualizado" -DocType: Customize Form,Use this fieldname to generate title,Utilize este campo para gerar o título -apps/frappe/frappe/email/doctype/email_group/email_group.js +13,Import Email From,Importar Email do -apps/frappe/frappe/contacts/doctype/contact/contact.js +20,Invite as User,Convidar como Usuário -DocType: Data Migration Run,End Time,Horário de Término -apps/frappe/frappe/public/js/frappe/views/interaction.js +83,Select Attachments,Selecione os Anexos -apps/frappe/frappe/website/js/web_form.js +140,There were errors. Please report this.,"Houveram erros. Por favor, reporte isso." -apps/frappe/frappe/public/js/frappe/views/reports/grid_report.js +284,Loading Report,Carregando Relatório -apps/frappe/frappe/limits.py +74,Your subscription will expire today.,Sua inscrição expira hoje. -apps/frappe/frappe/core/doctype/data_import/data_import.js +43,Attach File,Anexar Arquivo -apps/frappe/frappe/public/js/frappe/form/footer/assign_to.js +59,Assignment Complete,Atribuição Concluída -DocType: Communication,Email Status,Satus do Email -apps/frappe/frappe/public/js/frappe/form/footer/assign_to.js +111,Please save the document before removing assignment,"Por favor, salve o documento antes de remover a atribuição" -apps/frappe/frappe/utils/password_strength.py +179,This is similar to a commonly used password.,Isso é parecido com uma senha comum. -apps/frappe/frappe/public/js/frappe/model/indicator.js +19,Not Saved,Não Salvo -DocType: Contact,Replied,Respondido -DocType: Custom Field,Default Value,Valor padrão -DocType: Workflow Document State,Update Field,Atualizar Campo -apps/frappe/frappe/core/doctype/communication/email.py +151,Leave this conversation,Deixar essa conversa -apps/frappe/frappe/model/base_document.py +444,Options not set for link field {0},Opções não definida para o campo link {0} -apps/frappe/frappe/core/doctype/data_import/data_import.js +220,Unselect All,Desmarcar Todos -apps/frappe/frappe/custom/doctype/customize_form/customize_form.py +208,You cannot unset 'Read Only' for field {0},"Você não pode desabilitar ""Somente leitura"" para o campo {0}" -apps/frappe/frappe/core/doctype/data_import/exporter.py +63,Please do not change the template headings.,"Por favor, não alterar as posições do modelo." -DocType: Activity Log,Linked,Relacionado -apps/frappe/frappe/config/desk.py +44,Activity log of all users.,Registro de atividade de todos os usuários. -DocType: Email Domain,Example Email Address,Exemplo de Endereço de Email -apps/frappe/frappe/public/js/frappe/ui/sort_selector.js +182,Most Used,Mais Usados -apps/frappe/frappe/www/login.html +84,Forgot Password,Esqueci a Senha -DocType: Dropbox Settings,Backup Frequency,Frequência de Backup -DocType: DocField,User permissions should not apply for this Link,As permissões de usuário não deve candidatar-se a este link -apps/frappe/frappe/model/naming.py +113,Invalid naming series (. missing),Série de nomes inválido (. Ausente) -DocType: Language,Language,Idioma -apps/frappe/frappe/public/js/frappe/views/treeview.js +378,Add to Desktop,Adicionar ao Desktop -apps/frappe/frappe/core/doctype/file/file.py +180,File {0} does not exist,Arquivo {0} não existe -apps/frappe/frappe/core/doctype/data_import/exporter.py +100,Leave blank for new records,Deixe em branco para novos registros -apps/frappe/frappe/config/website.py +63,List of themes for Website.,Lista dos temas para o site. -DocType: Activity Log,Logout,Sair -apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +26,Permissions at higher levels are Field Level permissions. All Fields have a Permission Level set against them and the rules defined at that permissions apply to the field. This is useful in case you want to hide or make certain field read-only for certain Roles.,As permissões em níveis mais elevados são permissões igualdade. Todos os campos têm um conjunto Nível de Permissão contra eles e as regras definidas em que as permissões se aplicam ao campo. Isso é útil no caso de você querer esconder ou fazer determinado campo somente leitura para certas funções. -DocType: SMS Settings,"Enter static url parameters here (Eg. sender=ERPNext, username=ERPNext, password=1234 etc.)","Digite os parâmetros da URL estática aqui (por exemplo remetente=ERPNext, usuario=ERPNext, senha=1234, etc)" -apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +38,"If these instructions where not helpful, please add in your suggestions on GitHub Issues.","Se estas instruções não forem úteis, dê sua sugestão no GitHub." -apps/frappe/frappe/core/doctype/error_snapshot/error_snapshot.html +32,Error Report,Reportar erro -apps/frappe/frappe/model/base_document.py +515,Row #{0}:,Linha # {0}: -apps/frappe/frappe/auth.py +286,Login not allowed at this time,Entrada não permitida neste momento -apps/frappe/frappe/core/doctype/data_import/log_details.html +5,Row No,Linha No -DocType: Async Task,Runtime,Runtime -DocType: DocType,Permissions Settings,Configurações de Permissões -DocType: LDAP Settings,LDAP Email Field,Campo do Email LDAP -apps/frappe/frappe/www/list.html +4,{0} List,{0} Lista(s) -apps/frappe/frappe/desk/form/assign_to.py +49,Already in user's To Do list,Já está na lista de tarefas do usuário -DocType: User Email,Enable Outgoing,Ativar Saída -apps/frappe/frappe/config/setup.py +268,Custom Tags,Tags Personalizadas -apps/frappe/frappe/public/js/frappe/form/grid.js +679,Table updated,Tabela atualizada -DocType: DocField,Text,Texto -apps/frappe/frappe/email/doctype/email_account/email_account_list.js +14,Default Sending,Padrão Envio -DocType: Workflow State,volume-off,mudo -apps/frappe/frappe/public/js/frappe/form/footer/timeline_item.html +184,Liked by {0},Aprovado por {0} -,Download Backups,Download de Backups -apps/frappe/frappe/core/doctype/file/test_file.py +202,Home/Test Folder 1,Início / Teste pasta 1 -apps/frappe/frappe/public/js/frappe/form/footer/assign_to.js +138,Assign to me,Atribuir para mim -DocType: DocField,Dynamic Link,Link dinâmico -apps/frappe/frappe/core/report/feedback_ratings/feedback_ratings.js +40,To Date,Até a Data -apps/frappe/frappe/core/page/background_jobs/background_jobs_outer.html +5,Show failed jobs,Mostrar tarefas com falha -apps/frappe/frappe/public/js/frappe/form/footer/timeline_item.html +85,Details,Detalhes -apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +3,Quick Help for Setting Permissions,Ajuda rápida para Configurar Permissões -DocType: Tag Doc Category,Doctype to Assign Tags,Doctype para Atribuir Tags -DocType: Report,Report Builder,Criar/Editar Relatório -DocType: Communication,Workflow,Fluxo de Trabalho -DocType: System Settings,Date Format,Formato da data -apps/frappe/frappe/config/setup.py +231,"Actions for workflow (e.g. Approve, Cancel).","Ações para o fluxo de trabalho (por exemplo, Aprovar , Cancelar) ." -DocType: Web Page,Text Align,Alinhar Texto -apps/frappe/frappe/model/naming.py +215,Name cannot contain special characters like {0},Nome não pode conter caracteres especiais como {0} -DocType: Contact Us Settings,Forward To Email Address,Encaminhar para Email -apps/frappe/frappe/public/js/frappe/views/reports/reportview_footer.html +9,Show all data,Mostrar todas as informações -DocType: System Settings,Session Expiry in Hours e.g. 06:00,"Duração da sessão em horas, por exemplo 06:00" -DocType: Customize Form Field,"This field will appear only if the fieldname defined here has value OR the rules are true (examples): -myfield -eval:doc.myfield=='My Value' -eval:doc.age>18",Este campo aparecerá apenas se o nome do campo definido está preenchido ou se as regras são verdadeiros (exemplos): meu_campo eval: doc.meu_campo=='Valor' eval: doc.idade>18 -apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +35,"Once you have set this, the users will only be able access documents (eg. Blog Post) where the link exists (eg. Blogger).","Depois de ter definido isso, os usuários só poderão ser acessar documentos capazes (ex. Blog Post) onde existe a ligação (por exemplo, Blogger ) ." -DocType: Error Log,Log of Scheduler Errors,Log de Erros Scheduler -DocType: User,Bio,Bio -apps/frappe/frappe/public/js/frappe/form/save.js +12,Submitting,Enviando -apps/frappe/frappe/printing/page/print_format_builder/print_format_builder.js +189,Custom HTML,HTML Personalizado -apps/frappe/frappe/public/js/frappe/views/file/file_view.js +79,Enter folder name,Digite o nome da pasta -apps/frappe/frappe/core/page/permission_manager/permission_manager.js +55,Select Role,Selecione a Função -DocType: Communication,Deleted,Excluído(a) -DocType: Website Settings,Disable Customer Signup link in Login page,Desativar Link de Inscrição na Página de Login -apps/frappe/frappe/desk/report/todo/todo.py +20,Assigned To/Owner,Atribuído a / Proprietário -DocType: Workflow State,arrow-left,seta para a esquerda -DocType: Workflow State,fullscreen,tela cheia -apps/frappe/frappe/templates/emails/feedback_request_url.html +8,1 star being lowest & 5 stars being highest rating,Sendo 1 estrela a menor e 5 estrelas a maior classificação -apps/frappe/frappe/core/doctype/error_snapshot/error_snapshot_list.js +11,First Level,Primeiro nível -DocType: Workflow Document State,Represents the states allowed in one document and role assigned to change the state.,Representa os estados permitidos em um documento e papel atribuído para alterar o estado. -apps/frappe/frappe/custom/doctype/customize_form/customize_form.js +71,Refresh Form,Atualizar Formulário -DocType: DocField,Select,Selecionar -apps/frappe/frappe/utils/csvutils.py +29,File not attached,Arquivo não anexado -DocType: Top Bar Item,"If you set this, this Item will come in a drop-down under the selected parent.","Se você definir isso, este item virá em um drop-down sob o pai selecionado ." -apps/frappe/frappe/www/printview.py +225,No template found at path: {0},Nenhum modelo encontrado no caminho: {0} -DocType: Blogger,Posts,Postagens -DocType: Social Login Key,Salesforce,Salesforce -apps/frappe/frappe/core/doctype/doctype/doctype.py +475,"DocType's name should start with a letter and it can only consist of letters, numbers, spaces and underscores","O nome de DocType deve começar com uma letra e só pode consistir de letras, números, espaços e sublinhados" -DocType: Address,Accounts User,Usuário de Contas -DocType: Web Page,HTML for header section. Optional,HTML para a seção de cabeçalho. opcional -apps/frappe/frappe/public/js/frappe/form/templates/form_sidebar.html +13,This feature is brand new and still experimental,Esta funcionalidade é nova e ainda está em fase experimental -apps/frappe/frappe/model/rename_doc.py +418,Maximum {0} rows allowed,Máximo de {0} linhas permitido -DocType: Email Unsubscribe,Global Unsubscribe,Cancelar Inscrição Global -apps/frappe/frappe/utils/password_strength.py +177,This is a very common password.,Essa é uma senha muito comum. -apps/frappe/frappe/email/doctype/email_group/email_group.js +9,View,Ver -apps/frappe/frappe/public/js/frappe/views/communication.js +97,Select Print Format,Selecione o Formato de Impressão -DocType: Portal Settings,Portal Menu,Portal menu -apps/frappe/frappe/public/js/frappe/ui/toolbar/search.js +360,Search for anything,Procurar por qualquer coisa -DocType: Data Migration Connector,Hostname,Nome do Host -DocType: DocField,Print Hide,Ocultar Impressão -apps/frappe/frappe/public/js/frappe/ui/messages.js +68,Enter Value,Digite o Valor -apps/frappe/frappe/custom/doctype/custom_field/custom_field.js +63,e.g.:,ex: -DocType: Customize Form Field,Label and Type,Etiqueta e Tipo -apps/frappe/frappe/public/js/frappe/form/form_sidebar.js +59,{0} edited this {1},{0} editou {1} -DocType: Custom DocPerm,Submit,Enviar -apps/frappe/frappe/public/js/frappe/views/file/file_view.js +65,New Folder,Nova pasta -apps/frappe/frappe/desk/query_report.py +162,Must have report permission to access this report.,Deve ter permissão para acessar relatório deste relatório. -apps/frappe/frappe/templates/emails/upcoming_events.html +8,Daily Event Digest is sent for Calendar Events where reminders are set.,O resumo de eventos diário é enviado para o Calendário de eventos onde os lembretes são definidos. -apps/frappe/frappe/website/doctype/website_settings/website_settings.js +3,View Website,Ver Site -DocType: Email Domain,If non standard port (e.g. 587),"Se não for a porta padrão (por exemplo, 587)" -apps/frappe/frappe/config/setup.py +270,Add your own Tag Categories,Adicione suas próprias categorias de tags -DocType: Integration Request,Reference DocName,Nome do Documento de Referência -DocType: Web Form,Success Message,Mensagem de sucesso -apps/frappe/frappe/custom/doctype/customize_form/customize_form.js +84,Export Customizations,Exportar Personalizações -DocType: DocType,User Cannot Search,O Usuário não pode pesquisar -DocType: Custom DocPerm,Apply this rule if the User is the Owner,Aplicar esta regra se o usuário é o proprietário -apps/frappe/frappe/desk/page/activity/activity.js +45,Build Report,Criar relatório -apps/frappe/frappe/model/rename_doc.py +155,"{0} {1} does not exist, select a new target to merge","{0} {1} não existe , selecione um novo alvo para mesclar" -apps/frappe/frappe/public/js/frappe/list/list_sidebar.html +49,Assigned To Me,Atribuído a Mim -apps/frappe/frappe/public/js/frappe/ui/messages.js +230,Verify Password,Verifique a Senha -apps/frappe/frappe/model/document.py +672,Cannot change docstatus from 0 to 2,Não é possível alterar docstatus 0-2 -DocType: File,Attached To Field,Relacionado ao campo -DocType: Error Snapshot,Snapshot View,Ver Snapshot -apps/frappe/frappe/email/doctype/newsletter/newsletter.py +106,Please save the Newsletter before sending,"Por favor, salve a Newsletter antes de enviar" -DocType: Patch Log,List of patches executed,Lista de correções executado -apps/frappe/frappe/email/doctype/email_unsubscribe/email_unsubscribe.py +21,{0} already unsubscribed,{0} já teve sua inscrição removida -DocType: Website Settings,Banner HTML,Faixa HTML -apps/frappe/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py +46,Queued for backup. It may take a few minutes to an hour.,Na fila para backup em até uma hora. -apps/frappe/frappe/config/integrations.py +63,Register OAuth Client App,Registrar App OAuth Cliente -DocType: SMS Settings,SMS Gateway URL,URL de Gateway para SMS -apps/frappe/frappe/model/base_document.py +519,"{0} {1} cannot be ""{2}"". It should be one of ""{3}""","{0} {1} não pode ser ""{2}"". Deve pertencer a ""{3}""" -apps/frappe/frappe/core/doctype/user/user.py +249,Password Update,Atualização de Senha -DocType: Workflow State,trash,lixo -DocType: System Settings,Older backups will be automatically deleted,Os backups mais antigos serão apagados automaticamente -DocType: Payment Gateway,Gateway,Porta de entrada -apps/frappe/frappe/contacts/doctype/address/address.py +37,Address Title is mandatory.,Titulo do Endereço é obrigatório. -DocType: Website Settings,"Added HTML in the <head> section of the web page, primarily used for website verification and SEO","HTML adicionado na seção <head> da página web, principalmente utilizadas para a verificação do site e SEO" -apps/frappe/frappe/core/doctype/error_snapshot/error_snapshot_list.js +9,Relapsed,Reincidente -apps/frappe/frappe/utils/nestedset.py +183,Item cannot be added to its own descendents,O artigo não pode ser acrescentado para os seus próprios descendentes -DocType: Error Snapshot,Relapses,Recaídas -DocType: Address,Preferred Shipping Address,Endereço preferido para entrega -apps/frappe/frappe/public/js/frappe/form/print.js +284,With Letter head,Com cabeçalho -apps/frappe/frappe/public/js/frappe/form/form_sidebar.js +62,{0} created this {1},{0} criou {1} -apps/frappe/frappe/public/js/frappe/form/workflow.js +38,Document is only editable by users of role,Documento só é editável por usuários da função -DocType: Print Format,Show Line Breaks after Sections,Mostrar quebras de linha após seções -DocType: Workflow State,magnet,ímã -apps/frappe/frappe/geo/doctype/currency/currency.js +7,This Currency is disabled. Enable to use in transactions,Esta moeda é desativado. Ativar para usar em transações -DocType: Contact Us Settings,"Default: ""Contact Us""","Padrão: ""Fale Conosco""" -DocType: Contact,Purchase Manager,Gerente de Compras -DocType: Event,Every Week,Todas as semanas -DocType: Custom Field,Is Mandatory Field,É campo obrigatório -DocType: User,Website User,Usuário do Site -DocType: Integration Request,Integration Request Service,Serviço de Requisição de Integração -DocType: Web Form,Allow Multiple,Permitir Multiplos -DocType: Workflow State,Icon will appear on the button,O ícone aparecerá no botão -DocType: Website Settings,Website Settings,Configurações do Site -apps/frappe/frappe/modules/utils.py +204,App not found,App não encontrado -apps/frappe/frappe/core/doctype/communication/communication.py +71,Cannot create a {0} against a child document: {1},Não é possível criar um {0} contra um documento filho: {1} -apps/frappe/frappe/config/desk.py +32,Chat messages and other notifications.,Mensagens do chat e outras notificações. -apps/frappe/frappe/custom/doctype/custom_field/custom_field.py +84,Insert After cannot be set as {0},Depois de inserir não pode ser definido como {0} -apps/frappe/frappe/public/js/frappe/desk.js +144,Email Account setup please enter your password for: ,"Configuração de email, por favor informe sua senha para:" -DocType: Workflow State,hand-up,mão acima -DocType: Blog Settings,Writers Introduction,Introdução dos Escritores -apps/frappe/frappe/core/page/permission_manager/permission_manager.js +149,Select Document Type or Role to start.,Selecione o Tipo de Documento ou Função para começar. -DocType: Contact,Passive,Sem movimento -DocType: Contact,Accounts Manager,Gerente de Contas -apps/frappe/frappe/public/js/frappe/views/reports/reportview.js +723,Select File Type,Selecionar tipo do arquivo -DocType: Help Article,Knowledge Base Editor,Editor da Base de Conhecimento -DocType: Website Slideshow,Slideshow Items,Itens da Apresentação de Slides -apps/frappe/frappe/core/doctype/version/version_view.html +32,Rows Added,Linhas Adicionadas -DocType: ToDo,Allocated To,Atribuído a -DocType: Notification,Days After,Dias Após -DocType: Newsletter,Receipient,Destinatário -DocType: Contact Us Settings,Settings for Contact Us Page,Configurações para a página Fale Conosco -DocType: Custom Script,Script Type,Tipo de Script -apps/frappe/frappe/public/js/frappe/misc/pretty_date.js +53,{0} weeks ago,{0} semanas atrás -apps/frappe/frappe/utils/verified_command.py +44,Invalid Link,Fazer a ligação inválido -DocType: Web Page,Show Title,Mostrar Título -DocType: Property Setter,Property Type,Tipo de propriedade -DocType: Workflow State,screenshot,captura de tela -apps/frappe/frappe/core/doctype/report/report.py +33,Only Administrator can save a standard report. Please rename and save.,"Somente o Administrador pode salvar um relatório padrão. Por favor, renomear e salvar." -DocType: System Settings,Background Workers,Trabalhadores em Segundo Plano -DocType: OAuth Authorization Code,OAuth Authorization Code,Código de Autorização OAuth -apps/frappe/frappe/core/doctype/data_import/importer.py +324,Not allowed to Import,Não é permitido importar -DocType: Deleted Document,Deleted DocType,DocType Excluído -DocType: Tag Category,Tag Category,Categoria da Tag -apps/frappe/frappe/public/js/frappe/views/reports/grid_report.js +788,"Ignoring Item {0}, because a group exists with the same name!","Ignorando item {0}, porque um grupo existe com o mesmo nome!" -DocType: User,Login Before,Login antes -apps/frappe/frappe/config/setup.py +281,Application Installer,Instalador de Aplicativos -apps/frappe/frappe/public/js/frappe/views/reports/reportview.js +788,New Report name,Nome do novo Relatório -DocType: Workflow State,info-sign,Sinal de Informações -DocType: Currency,"How should this currency be formatted? If not set, will use system defaults","Como essa moeda deve ser formatada? Se não for definido, serão usados os padrões do sistema" -apps/frappe/frappe/utils/response.py +151,You need to be logged in and have System Manager Role to be able to access backups.,Você precisa estar conectado e ter permissão para ser capaz de acessar backups. -apps/frappe/frappe/public/js/legacy/form.js +136,Please save before attaching.,"Por favor, salve antes de anexar." -apps/frappe/frappe/custom/doctype/customize_form/customize_form.py +338,Fieldtype cannot be changed from {0} to {1} in row {2},FieldType não pode ser alterado a partir de {0} a {1} em linha {2} -DocType: Data Migration Run,Start Time,Horário de Início -apps/frappe/frappe/public/js/frappe/form/workflow.js +43,Workflow will start after saving.,Fluxo de trabalho será iníciado após salvar. -apps/frappe/frappe/public/js/frappe/form/templates/set_sharing.html +7,Can Share,Pode Compartilhar -apps/frappe/frappe/email/smtp.py +27,Invalid recipient address,Endereço do destinatário inválido -DocType: Workflow State,step-forward,prosseguir -apps/frappe/frappe/limits.py +69,Your subscription has expired.,A sua inscrição expirou. -apps/frappe/frappe/core/doctype/user/user.js +67,Refreshing...,Atualizando... -DocType: System Settings,System Settings,Configurações do Sistema -apps/frappe/frappe/email/queue.py +515,This email was sent to {0} and copied to {1},Este email foi enviado para {0} e copiados para {1} -apps/frappe/frappe/public/js/frappe/form/controls/link.js +172,Create a new {0},Criar um(a) novo(a) {0} -apps/frappe/frappe/public/js/frappe/list/bulk_operations.js +3,Doctype required,Doctype obrigatório -DocType: Workflow State,ok-sign,ok-sinal -DocType: Newsletter,Create and Send Newsletters,Criar e enviar email marketing -apps/frappe/frappe/public/js/frappe/views/reports/grid_report.js +303,From Date must be before To Date,A data inicial deve ser anterior a data final -apps/frappe/frappe/email/doctype/notification/notification.py +35,Please specify which value field must be checked,Por favor especificar qual campo deve ser verificado -apps/frappe/frappe/core/doctype/data_import/exporter.py +71,"""Parent"" signifies the parent table in which this row must be added","""Pai"" significa a tabela pai no qual deve ser acrescentado nesta linha" -DocType: Feedback Request,Feedback Rating,Rating do Feedback -DocType: Help Category,Help Articles,Artigo de Ajuda -DocType: Communication,Unshared,Não Compartilhado -apps/frappe/frappe/desk/moduleview.py +84,Module Not Found,Módulo não encontrado -,Permitted Documents For User,Documentos Permitidos para Usuário -apps/frappe/frappe/core/doctype/docshare/docshare.py +40,"You need to have ""Share"" permission","Você precisa ter a permissão ""Compartilhar""" -DocType: Communication,Assignment Completed,Atribuição Concluída -apps/frappe/frappe/workflow/doctype/workflow/workflow_list.js +7,Not active,Inativo -DocType: About Us Settings,Settings for the About Us Page,Configurações para a página Sobre Nós -apps/frappe/frappe/custom/doctype/customize_form/customize_form.js +245,Use the field to filter records,Use o campo para filtrar registros -DocType: Website Settings,Add Google Analytics ID: eg. UA-89XXX57-1. Please search help on Google Analytics for more information.,"Adicione o ID do Google Analytics: ex. UA-89XXX57-1. Por favor, procure ajuda no Google Analytics para obter mais informações." -apps/frappe/frappe/utils/password.py +136,Password cannot be more than 100 characters long,A senha não pode ter mais de 100 caracteres -DocType: Kanban Board,Kanban Board Name,Nome do Painel Kanban -apps/frappe/frappe/email/queue.py +517,This email was sent to {0},Este email foi enviado para {0} -DocType: DocField,Remember Last Selected Value,Lembrar última seleção -DocType: Email Account,Check this to pull emails from your mailbox,Marque para baixar os emails da sua caixa de emails -apps/frappe/frappe/model/document.py +685,Cannot edit cancelled document,Não é possível editar documento cancelado -DocType: Unhandled Email,Unhandled Email,Emails não trabalhados -apps/frappe/frappe/utils/password_strength.py +92,Make use of longer keyboard patterns,Use uma combinação de letras e números mais longa -apps/frappe/frappe/utils/nestedset.py +80,Nested set error. Please contact the Administrator.,Erro conjunto aninhado . Entre em contato com o administrador. -DocType: Feedback Trigger,Email Field,Campo do Email -apps/frappe/frappe/www/update-password.html +60,New Password Required.,É necessário uma nova senha. -apps/frappe/frappe/core/doctype/docshare/docshare.py +49,{0} shared this document with {1},{0} compartilhou este documento com {1} -DocType: Website Settings,Brand Image,Imagem da Marca -apps/frappe/frappe/config/website.py +58,"Setup of top navigation bar, footer and logo.","Configuração de barra de navegação do topo, rodapé, e logotipo." -apps/frappe/frappe/core/doctype/doctype/doctype.py +767,For {0} at level {1} in {2} in row {3},Por {0} a nível {1} em {2} na linha {3} -DocType: Address,Sales User,Usuário de Vendas -apps/frappe/frappe/config/setup.py +195,Drag and Drop tool to build and customize Print Formats.,Ferramenta de segure e arraste para construir e personalizar formatos de impressão. -apps/frappe/frappe/public/js/frappe/form/link_selector.js +142,Set,Definir -DocType: Workflow State,align-right,Alinhar à direita -apps/frappe/frappe/core/doctype/file/file.py +268,Folder {0} is not empty,Pasta {0} não está vazio -apps/frappe/frappe/public/js/frappe/ui/filters/filter.js +157,Field {0} is not selectable.,O campo {0} não é selecionável. -DocType: System Settings,Session Expiry,Duração da Sessão -DocType: Auto Repeat,Desk,Mesa -apps/frappe/frappe/core/doctype/report/report.js +8,Write a SELECT query. Note result is not paged (all data is sent in one go).,Escreva uma consulta SELECT. Resultado nota não é paginada (todos os dados são enviados de uma só vez). -apps/frappe/frappe/public/js/frappe/views/reports/reportview.js +131,Setup Auto Email,Configurar Email Automático -apps/frappe/frappe/public/js/frappe/form/grid_row_form.js +67,Ctrl + Down,Ctrl + Seta para baixo -apps/frappe/frappe/utils/password_strength.py +173,This is a top-10 common password.,Essa é uma das 10 senhas mais comuns. -DocType: Workflow State,chevron-down,divisa-abaixo -apps/frappe/frappe/public/js/frappe/views/communication.js +571,Email not sent to {0} (unsubscribed / disabled),Email não enviado para {0} (inscrição cancelada / desativado) -DocType: Currency,Smallest Currency Fraction Value,Menor valor fracionado de moeda -apps/frappe/frappe/public/js/frappe/form/footer/assign_to.js +137,Assign To,Atribuir a -DocType: Web Page,Enable Comments,Ativação de comentários -DocType: User,Restrict user from this IP address only. Multiple IP addresses can be added by separating with commas. Also accepts partial IP addresses like (111.111.111),Restringir usuário a partir deste endereço IP. Vários endereços IP podem ser adicionados ao separar com vírgulas. São aceitos também endereços IP parciais como (111.111.111) -DocType: Website Theme,Google Font (Heading),Fonte do Google (cabeçalho) -apps/frappe/frappe/public/js/frappe/views/treeview.js +234,Select a group node first.,Selecione um nó de grupo primeiro. -DocType: Email Account,"Append as communication against this DocType (must have fields, ""Status"", ""Subject"")","Anexar como a comunicação contra este DocType (deve ter campos, ""status"", ""Assunto"")" -apps/frappe/frappe/model/base_document.py +586,Not allowed to change {0} after submission,Não é permitido alterar {0} após a apresentação -DocType: Chat Room,Users,Usuários -DocType: Communication,Timeline field Name,Nome do campo da timeline -apps/frappe/frappe/core/page/permission_manager/permission_manager.js +145,Loading,Carregando -apps/frappe/frappe/config/integrations.py +53,"Enter keys to enable login via Facebook, Google, GitHub.","Enter para ativar o login via Facebook , Google, GitHub ." -apps/frappe/frappe/public/js/frappe/form/controls/select.js +61,Please attach a file first.,"Por favor, anexar um arquivo primeiro" -DocType: Website Slideshow Item,Website Slideshow Item,Item do Slideshow do Site -apps/frappe/frappe/desk/form/assign_to.py +190,New Message from {0},Nova Mensagem de {0} -DocType: Portal Settings,Default Role at Time of Signup,Função padrão no momento da inscrição -DocType: DocType,Title Case,Caixa do Título -DocType: Blog Post,Email Sent,Email enviado -DocType: Website Theme,Link Color,Cor do link -apps/frappe/frappe/core/doctype/user/user.py +114,User {0} cannot be disabled,O usuário {0} não pode ser desativado -apps/frappe/frappe/templates/emails/administrator_logged_in.html +1,"Dear System Manager,","Caro Administrador de Sistemas," -apps/frappe/frappe/core/doctype/doctype/doctype.js +39,In Grid View,Na Visualização do Grid -apps/frappe/frappe/public/js/frappe/form/save.js +14,Amending,Correção -DocType: Contact Us Settings,Send enquiries to this email address,Envie perguntas para este endereço de email -DocType: Letter Head,Letter Head Name,Nome do timbrado -apps/frappe/frappe/config/website.py +18,User editable form on Website.,Formato editável do usuário no site. -DocType: Workflow State,file,arquivo -apps/frappe/frappe/www/login.html +91,Back to Login,Voltar para Login -DocType: File,File Size,Tamanho do arquivo -apps/frappe/frappe/website/doctype/web_form/web_form.py +410,You must login to submit this form,Você precisa estar logado para enviar este formulário -apps/frappe/frappe/desk/page/setup_wizard/setup_wizard.js +386,"Select your Country, Time Zone and Currency","Escolha o seu País, Fuso Horário e Moeda" -DocType: Async Task,Queued,Enfileiradas -apps/frappe/frappe/public/js/frappe/views/reports/grid_report.js +199,Invalid Filter: {0},Filtro inválido: {0} -DocType: OAuth Bearer Token,Access Token,Token de Acesso -DocType: About Us Settings,Org History,História da Organização -DocType: Auto Repeat,Next Schedule Date,Próxima data programada -DocType: Workflow,Workflow Name,Nome do Fluxo de Trabalho -DocType: DocField,In Standard Filter,Em Filtro Padrão -apps/frappe/frappe/workflow/doctype/workflow/workflow.py +72,Cannot change state of Cancelled Document. Transition row {0},Não é possível alterar o estado de Documento Cancelado . -DocType: Workflow,"Rules for how states are transitions, like next state and which role is allowed to change state etc.","Regras de como os status são alterados, como o próximo status e que função terá permissão para mudar de status, etc" -apps/frappe/frappe/email/doctype/email_account/email_account.py +87,Append To can be one of {0},Para anexar pode ser um dos {0} -DocType: DocType,Image View,Ver Imagem -DocType: DocType,Show Print First,Mostrar Impressão Primeiro -apps/frappe/frappe/public/js/frappe/form/link_selector.js +106,Make a new {0},Fazer um(a) novo(a) {0} -apps/frappe/frappe/public/js/frappe/views/inbox/inbox_view.js +169,New Email Account,Nova conta de email -apps/frappe/frappe/email/doctype/email_queue/email_queue_list.js +10,Resume Sending,Retomar Envio -DocType: Address,Purchase User,Usuário de Compras -DocType: Workflow,"Different ""States"" this document can exist in. Like ""Open"", ""Pending Approval"" etc.","""Status"" diferentes em que esse documento pode existir. Como ""Aberto"", ""Aprovação Pendente"", etc" -DocType: Web Page,Slideshow,Apresentação de Slides -apps/frappe/frappe/contacts/doctype/address_template/address_template.py +33,Default Address Template cannot be deleted,Template endereço padrão não pode ser excluído -DocType: Contact,Maintenance Manager,Gerente de Manutenção -DocType: Website Theme,Top Bar Text Color,Cor do texto da barra superior -DocType: Auto Repeat,Amended From,Corrigido a partir de -apps/frappe/frappe/core/doctype/file/file.py +670,File '{0}' not found,Arquivo '{0}' não encontrado -DocType: User,Change Password,Alterar a senha -apps/frappe/frappe/public/js/frappe/views/reports/report_view.js +398,X Axis Field,Campo do eixo X -apps/frappe/frappe/public/js/frappe/form/controls/data.js +124,Invalid Email: {0},Email inválido: {0} -apps/frappe/frappe/desk/doctype/event/event.py +25,Event end must be after start,Evento final deve ser após o início -apps/frappe/frappe/desk/query_report.py +26,You don't have permission to get a report on: {0},Você não tem permissão para acessar um relatório sobre: {0} -DocType: Blog Post,Blog Post,Mensagem do Blog -apps/frappe/frappe/email/doctype/newsletter/newsletter.py +115,You are not permitted to view the newsletter.,Você não tem permissão para visualizar a newsletter. -apps/frappe/frappe/core/doctype/user/user.py +812,Password reset instructions have been sent to your email,Instruções de redefinição de senha foram enviadas para seu email -DocType: Notification,Attach Print,Anexar cópia -apps/frappe/frappe/core/doctype/user/user.py +447,Suggested Username: {0},Nome de usuário sugerido: {0} -,Modules,módulos -apps/frappe/frappe/core/doctype/user/user.js +74,Set Desktop Icons,Definir Ícones do Desktop -apps/frappe/frappe/public/js/frappe/views/inbox/inbox_view.js +163,No {0} mail,Nenhum {0} -DocType: OAuth Bearer Token,Revoked,Revogado -DocType: Web Page,Sidebar and Comments,Menu Lateral e Comentários -apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +18,"When you Amend a document after Cancel and save it, it will get a new number that is a version of the old number.","Quando você Corrigir um documento depois de Cancelar e salvá-lo, ele irá obter um novo número que é uma versão do número antigo." -DocType: Workflow State,circle-arrow-left,círculo de seta para a esquerda -apps/frappe/frappe/sessions.py +139,Redis cache server not running. Please contact Administrator / Tech support,Servidor de cache Redis não está funcionando. Entre em contato com o Administrador de apoio / Tecnologia -apps/frappe/frappe/public/js/frappe/ui/toolbar/awesome_bar.js +132,Make a new record,Criar um novo registro -DocType: LDAP Settings,LDAP First Name Field,Campo Primeiro Nome do LDAP -DocType: Custom Field,Field Description,Descrição do Campo -apps/frappe/frappe/model/naming.py +276,Name not set via Prompt,Nome não definido através Prompt -apps/frappe/frappe/public/js/frappe/ui/toolbar/search_utils.js +250,Email Inbox,Caixa de Entrada -DocType: Auto Email Report,Filters Display,Exibição dos Filtros -DocType: Website Theme,Top Bar Color,Cor da barra superior -DocType: Address,Plant,Fábrica -DocType: DocType,Setup,Configuração -DocType: DocType,Timeline Field,Campo Timeline -DocType: Country,Time Zones,Fusos horários -apps/frappe/frappe/core/page/permission_manager/permission_manager.py +91,There must be atleast one permission rule.,É necessário que exista pelo menos uma regra de permissão. -DocType: Workflow State,remove-sign,remover-assinar -apps/frappe/frappe/config/setup.py +221,Define workflows for forms.,Defina fluxos de trabalho para formulários. -apps/frappe/frappe/printing/page/print_format_builder/print_format_builder.js +162,Start new Format,Iniciar um Novo Formato -DocType: Workflow State,font,fonte -apps/frappe/frappe/utils/password_strength.py +175,This is a top-100 common password.,Essa é uma das 100 senhas mais comuns. -apps/frappe/frappe/email/doctype/auto_email_report/auto_email_report.js +30,Please enable pop-ups,Por favor habilite os pop-ups -DocType: Contact,Mobile No,Telefone Celular -DocType: Customize Form Field,Is Custom Field,É campo personalizado -DocType: Workflow,"If checked, all other workflows become inactive.","Se marcada, todos os outros fluxos de trabalho tornam-se inativos." -apps/frappe/frappe/core/doctype/report/report.js +10,[Label]:[Field Type]/[Options]:[Width],[Label]: [Tipo do Campo] / [Opções]: [Largura] -DocType: Workflow State,folder-close,fechar pasta -apps/frappe/frappe/model/rename_doc.py +168,{0} not allowed to be renamed,não é permitido renomear {0} -DocType: Address,Address Line 2,Complemento -apps/frappe/frappe/public/js/frappe/model/model.js +26,Assigned To,Atribuído a -apps/frappe/frappe/www/update-password.html +111,Please enter the password,Por favor digite a senha -apps/frappe/frappe/www/printview.py +83,Not allowed to print cancelled documents,Não permitido para imprimir documentos cancelados -apps/frappe/frappe/core/doctype/data_import/exporter.py +272,Info:,Info: -DocType: User,Send Notifications for Transactions I Follow,Enviar notificações para transações seguidas por mim -apps/frappe/frappe/core/doctype/doctype/doctype.py +806,"{0}: Cannot set Submit, Cancel, Amend without Write","{0}: Não é possível definir Enviar, Cancelar, Alterar sem Salvar" -apps/frappe/frappe/public/js/frappe/form/footer/attachments.js +78,Are you sure you want to delete the attachment?,Tem certeza de que deseja excluir o anexo? -apps/frappe/frappe/public/js/frappe/form/save.js +11,Saving,Salvando -DocType: Print Settings,Print Style Preview,Estilo de visualização de impressão -DocType: About Us Settings,About Us Settings,Configurações do Quem Somos -DocType: Website Settings,Website Theme,Tema do Site -DocType: DocField,In List View,Mostrar na Visualização da Lista -apps/frappe/frappe/email/smtp.py +24,Invalid login or password,Login ou senha inválidos -apps/frappe/frappe/core/doctype/data_import/data_import.js +72,Download Template,Baixar Modelo -apps/frappe/frappe/config/setup.py +259,Add custom javascript to forms.,Adicionar javascript personalizado aos formulários. -,Role Permissions Manager,Gestor de Permissões por Função -DocType: Notification,Days Before or After,Dias Antes ou Após -apps/frappe/frappe/desk/doctype/auto_repeat/auto_repeat.py +75,Next Date's day and Repeat on Day of Month must be equal,No dia seguinte de Data e Repetir no dia do mês deve ser igual -apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +34,Select Document Types to set which User Permissions are used to limit access.,Selecione os tipos de documentos para definir quais as permissões de usuário são usados para limitar o acesso. -DocType: User Permission,User Permission,A permissão do usuário -apps/frappe/frappe/core/doctype/data_import/data_import.js +204,Download with data,Download com dados -DocType: Workflow State,hand-right,mão à direita -DocType: Web Form,Allow Delete,Permitir Excluir -DocType: Web Form,Login Required,Necessário Login -apps/frappe/frappe/templates/pages/integrations/payment-cancel.html +3,Payment Cancelled,Pagamento cancelado -,Addresses And Contacts,Endereços e Contatos -apps/frappe/frappe/core/doctype/error_log/error_log_list.js +12,Clear Error Logs,Limpar Logs de Erro -DocType: Email Account,Notify if unreplied for (in mins),Informar se não for respondido em (minutos) -apps/frappe/frappe/public/js/frappe/list/list_renderer.js +570,2 days ago,Há 2 dias -apps/frappe/frappe/config/website.py +47,Categorize blog posts.,Categorizar posts. -apps/frappe/frappe/core/doctype/doctype/doctype.py +637,{{{0}}} is not a valid fieldname pattern. It should be {{field_name}}.,{{{0}}} não é padrão para nome de campo válido. Deve ser {{field_name}}. -apps/frappe/frappe/public/js/frappe/views/treeview.js +183,Add Child,Adicionar sub-item -apps/frappe/frappe/model/delete_doc.py +176,{0} {1}: Submitted Record cannot be deleted.,{0} {1}: Registro enviado não pode ser excluído. -apps/frappe/frappe/printing/page/print_format_builder/print_format_builder.js +460,Align Value,Alinhar Valor -apps/frappe/frappe/website/doctype/blog_post/blog_post.py +106,Posts by {0},Posts de {0} -apps/frappe/frappe/www/login.html +55,Don't have an account? Sign up,Não tem uma conta? Se inscreva -apps/frappe/frappe/core/doctype/doctype/doctype.py +831,{0}: Cannot set Assign Amend if not Submittable,{0}: Não é possível definir atributo Corrigir se não pode ser enviado -DocType: Activity Log,Link DocType,Relacionar ao DocType -DocType: Website Slideshow,Slideshow Name,Nome da Apresentação de Slides -apps/frappe/frappe/public/js/frappe/form/save.js +15,Cancelling,Cancelando -DocType: DocType,Allow Rename,Permitir Renomear -DocType: DocType,Child Tables are shown as a Grid in other DocTypes.,Tabelas-filhas são mostradas como um grid nos outros DocTypes. -apps/frappe/frappe/www/404.html +26,Error Code: {0},Código do Erro: {0} -DocType: Blog Post,"Description for listing page, in plain text, only a couple of lines. (max 140 characters)","Descrição da página perfil, em texto simples, apenas um par de linhas. (Máximo 140 caracteres)" -DocType: DocType,Name Case,Caso Nome -apps/frappe/frappe/model/base_document.py +402,Data missing in table,Falta de dados na tabela -DocType: Web Form,Success URL,URL de Confirmação -DocType: Email Account,Append To,Acrescente Para -DocType: Workflow Document State,Only Allow Edit For,Somente permite edição para -apps/frappe/frappe/templates/includes/comments/comments.html +35,Your Name,Seu Nome -,Feedback Ratings,Ratings do Feedback -DocType: Website Theme,"If image is selected, color will be ignored.","Se a imagem for selecionada, a cor será ignorado." -DocType: User,Mute Sounds,Desativar sons -DocType: Top Bar Item,Top Bar Item,Item da barra superior -apps/frappe/frappe/utils/csvutils.py +53,"Unknown file encoding. Tried utf-8, windows-1250, windows-1252.","Codificação de arquivo desconhecida. Tentei utf-8, Windows -1250 , Windows-1252 ." -apps/frappe/frappe/core/doctype/user/user.py +191,Sorry! Sharing with Website User is prohibited.,Desculpe! Não é permitido compartilhar com o site do usuário. -apps/frappe/frappe/public/js/frappe/roles_editor.js +30,Add all roles,Adicionar todos os papéis -apps/frappe/frappe/templates/includes/contact.js +15,"Please enter both your email and message so that we \ - can get back to you. Thanks!","Digite seu email e tanto mensagem para que nós \ - pode voltar para você. Obrigado!" -apps/frappe/frappe/email/smtp.py +203,Could not connect to outgoing email server,Não foi possível conectar ao servidor de envio emails -apps/frappe/frappe/email/doctype/newsletter/newsletter.py +168,Thank you for your interest in subscribing to our updates,Agradecemos seu interesse em assinar a newsletter do site -DocType: Workflow State,resize-full,redimensionamento completo -DocType: Workflow State,off,fora -apps/frappe/frappe/desk/query_report.py +30,Report {0} is disabled,Relatório {0} está desativado -apps/frappe/frappe/custom/doctype/customize_form/customize_form.js +79,Set Permissions,Definir Permissões -DocType: Email Account,Ignore attachments over this size,Ignorar anexos maiores que este tamanho -DocType: Address,Preferred Billing Address,Endereço preferido de faturamento -apps/frappe/frappe/core/doctype/version/version_view.html +8,Values Changed,Valores Alterados -DocType: Workflow State,arrow-up,seta para cima -DocType: Error Snapshot,Exception Type,Tipo de exceção -DocType: Web Form,Accept Payment,Aceitar Pagamento -apps/frappe/frappe/config/core.py +62,A log of request errors,Um log de erros de solicitação -DocType: Report,Letter Head,Timbrado -DocType: DocType,Quick Entry,Entrada Rápida -apps/frappe/frappe/email/doctype/email_queue/email_queue_list.js +16,Suspend Sending,Suspender Envio -apps/frappe/frappe/printing/page/print_format_builder/print_format_builder_layout.html +3,Drag elements from the sidebar to add. Drag them back to trash.,Arraste os elementos da barra lateral para adicionálos. Arraste-os de volta para eliminar. -DocType: Workflow State,resize-small,redimensionamento pequeno -DocType: Address,Postal Code,CEP -apps/frappe/frappe/core/doctype/communication/communication.js +106,Relink Communication,Relinkar Comunicação -apps/frappe/frappe/www/third_party_apps.html +58,No Active Sessions,Nenhuma sessão ativa -DocType: Top Bar Item,Right,À direita -DocType: User,User Type,Tipo de Usuário -DocType: Async Task,Reference Doc,Documento de Referência -DocType: Communication,Keep a track of all communications,Manter registros de todas as comunicações -apps/frappe/frappe/desk/form/save.py +34,Did not save,Não salvou -DocType: Website Slideshow,"Note: For best results, images must be of the same size and width must be greater than height.","Observação: Para melhores resultados, as imagens devem ser do mesmo tamanho, e a largura não deve ser maior do que a altura." -apps/frappe/frappe/custom/doctype/customize_form/customize_form.js +229,Permissions can be managed via Setup > Role Permissions Manager,As permissões podem ser gerenciados através de Configuração > Gestor de Permissões por Função -DocType: Contact Us Settings,Pincode,CEP -apps/frappe/frappe/core/doctype/data_import/importer.py +106,Please make sure that there are no empty columns in the file.,"Por favor, certifique-se de que não existem colunas vazias no arquivo." -apps/frappe/frappe/utils/oauth.py +184,Please ensure that your profile has an email address,Verifique se o seu perfil tem um endereço de email -apps/frappe/frappe/core/doctype/doctype/doctype.py +562,Default for {0} must be an option,Padrão para {0} deve ser uma opção -DocType: User,User Image,Imagem do Usuário -apps/frappe/frappe/email/queue.py +345,Emails are muted,Emails são silenciados -apps/frappe/frappe/public/js/frappe/form/grid_row_form.js +67,Ctrl + Up,Ctrl + Seta para cima -DocType: Website Theme,Heading Style,Estilo do Cabeçalho -DocType: Auto Repeat,End Date,Data Final -DocType: DocField,Column Break,Quebra de coluna -apps/frappe/frappe/utils/response.py +162,You don't have permission to access this file,Você não tem permissão para acessar este arquivo -apps/frappe/frappe/model/document.py +753,Cannot link cancelled document: {0},Não é possível vincular documento cancelado: {0} -apps/frappe/frappe/contacts/doctype/address/address.py +59,"Company is mandatory, as it is your company address","Empresa é obrigatório, como é o seu endereço de empresa" -apps/frappe/frappe/printing/page/print_format_builder/print_format_builder.js +698,"For example: If you want to include the document ID, use {0}","Por exemplo: Se você quiser incluir a ID do documento, use {0}" -DocType: Custom Field,Options Help,Ajuda sobre Opções -DocType: Footer Item,Group Label,Etiqueta do Grupo -DocType: Kanban Board,Kanban Board,Painel Kanban -apps/frappe/frappe/public/js/frappe/views/treeview.js +17,Tree view not available for {0},Visualização em Árvore não disponível para {0} -DocType: Custom Field,Label Help,Ajuda sobre Etiquetas -apps/frappe/frappe/utils/password_strength.py +141,Dates are often easy to guess.,Datas são frequentemente fáceis de adivinhar. -DocType: User,These values will be automatically updated in transactions and also will be useful to restrict permissions for this user on transactions containing these values.,Esses valores serão atualizados automaticamente em transações e também serão úteis para restringir as permissões para este usuário em operações que contenham esses valores. -apps/frappe/frappe/model/rename_doc.py +431,** Failed: {0} to {1}: {2},** Falha: {0} para {1}: {2} -apps/frappe/frappe/public/js/frappe/ui/upload.html +4,Browse,Procurar -DocType: Async Task,Running,Correndo -apps/frappe/frappe/email/doctype/email_group/email_group.py +102,Please Upgrade to add more than {0} subscribers,"Por favor, atualize para adicionar mais de {0} assinantes" -DocType: Workflow State,hand-left,mão à esquerda -apps/frappe/frappe/core/doctype/doctype/doctype.py +575,Fieldtype {0} for {1} cannot be unique,FieldType {0} para {1} não pode ser exclusivo -DocType: Workflow State,play-circle,jogo-círculo -apps/frappe/frappe/printing/page/print_format_builder/print_format_builder.js +82,Select Print Format to Edit,Selecione um formato de impressão para editar -DocType: Address,Shipping,Expedição -DocType: Workflow State,circle-arrow-down,círculo de seta para baixo -apps/frappe/frappe/config/desk.py +38,Private and public Notes.,Privadas e públicas Notas. -apps/frappe/frappe/templates/includes/login/login.js +187,Not a valid user,Não é um usuário válido -DocType: Workflow State,arrow-right,seta para a direita -DocType: Workflow State,Workflow state represents the current state of a document.,O Status do Fluxo de Trabalho representa o status atual de um documento. -apps/frappe/frappe/www/update-password.html +9,Set Password,Definir senha -apps/frappe/frappe/core/doctype/file/file.py +221,Removed {0},Removido {0} -DocType: SMS Settings,SMS Settings,Configurações de SMS -apps/frappe/frappe/printing/doctype/print_format/print_format.py +19,Standard Print Format cannot be updated,Formato de impressão padrão não pode ser atualizado -DocType: Help Article,Help Article,Artigo de Ajuda -apps/frappe/frappe/custom/doctype/customize_form/customize_form.js +206,Help: Field Properties,Help: Propriedades do campo -apps/frappe/frappe/model/document.py +1090,Incorrect value in row {0}: {1} must be {2} {3},Valor incorreto na linha {0} : {1} deve ser {2} {3} -apps/frappe/frappe/workflow/doctype/workflow/workflow.py +75,Submitted Document cannot be converted back to draft. Transition row {0},Documento enviado não pode ser convertido de volta para rascunho. Linha de transição {0} -apps/frappe/frappe/workflow/doctype/workflow/workflow.py +41,Created Custom Field {0} in {1},Criado campo personalizado {0} em {1} -DocType: Communication,Relinked,Relinkado -DocType: Print Settings,Compact Item Print,Imprimir item no formato compacto -DocType: SMS Settings,Enter url parameter for receiver nos,Digite o parâmetro da url para os números de receptores -apps/frappe/frappe/email/doctype/email_queue/email_queue.py +26,Only Administrator can delete Email Queue,Somente o administrador pode deletar a fila de emails -apps/frappe/frappe/contacts/doctype/address_template/address_template.py +22,Setting this Address Template as default as there is no other default,"A definição desse modelo de endereço como padrão, pois não há outro padrão" -DocType: Workflow State,question-sign,ponto de interrogação -,Background Jobs,Tarefas em Segundo Plano -DocType: ToDo,ToDo,Lista de Atribuições -DocType: Workflow State,qrcode,QRCode -apps/frappe/frappe/www/login.html +33,Login with LDAP,Logar com LDAP -DocType: Web Form,Breadcrumbs,Breadcrumbs -apps/frappe/frappe/core/doctype/doctype/doctype.py +779,If Owner,Se proprietário -DocType: Web Page,Website Sidebar,Menu Lateral do Site -DocType: Web Form,Show Sidebar,Mostrar menu lateral -apps/frappe/frappe/public/js/frappe/form/footer/assign_to.js +142,Complete By,Finalizar até -apps/frappe/frappe/templates/includes/comments/comments.py +48,{0} by {1},{0} de {1} -DocType: Feedback Trigger,Email Fieldname,Nome do Campo do Email -DocType: Website Settings,Top Bar Items,Itens da barra superior -DocType: Notification,Print Settings,Configurações de Impressão -DocType: DocType,Max Attachments,Máx. de Anexos -apps/frappe/frappe/config/website.py +93,Knowledge Base,Base de Conhecimento -apps/frappe/frappe/model/document.py +500,Value cannot be changed for {0},Valor não pode ser alterado para {0} -DocType: Feedback Request,Is Manual,É manual -apps/frappe/frappe/desk/doctype/auto_repeat/auto_repeat.py +290,Please find attached {0} #{1},Segue em anexo {0} # {1} -DocType: Workflow State,"Style represents the button color: Success - Green, Danger - Red, Inverse - Black, Primary - Dark Blue, Info - Light Blue, Warning - Orange","Estilo representa a cor do botão: Sucesso - Verde, Perigo - Vermelho, Inverso - Preto, Primário - Azul Escuro, Informações - Azul Claro, Aviso - Laranja" -DocType: Workflow Transition,Workflow Transition,Transição do Fluxo de Trabalho -apps/frappe/frappe/public/js/frappe/misc/pretty_date.js +54,{0} months ago,{0} meses atrás -apps/frappe/frappe/public/js/frappe/model/model.js +18,Created By,Criado por -apps/frappe/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py +335,Dropbox Setup,Configuração do Dropbox -DocType: Workflow State,resize-horizontal,redimensionamento horizontal -apps/frappe/frappe/public/js/frappe/views/treeview.js +294,Group Node,Grupo de Nós -DocType: Workflow,"All possible Workflow States and roles of the workflow. Docstatus Options: 0 is""Saved"", 1 is ""Submitted"" and 2 is ""Cancelled""","Todos os status possíveis de fluxo de trabalho e as funções do fluxo de trabalho. Opções Docstatus: 0 é ""Salvo"", 1 é ""Enviado"" e 2 é ""Cancelado""" -DocType: Website Theme,Footer Text Color,Cor do Texto do Rodapé -apps/frappe/frappe/public/js/frappe/model/meta.js +182,Last Modified On,Última Alteração em -apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +24,"Permissions at level 0 are Document Level permissions, i.e. they are primary for access to the document.","As permissões para o nível 0 são permissões em nível de documento, ou seja, eles são primários para o acesso ao documento." -apps/frappe/frappe/public/js/frappe/list/list_view.js +285,Refreshing,Atualizando -DocType: About Us Settings,"""Company History""","Histórico da Empresa" -apps/frappe/frappe/core/doctype/docshare/docshare.py +47,{0} shared this document with everyone,{0} compartilhou este documento com todos -apps/frappe/frappe/desk/page/activity/activity_row.html +17,Commented on {0}: {1},Comentou sobre {0}: {1} -apps/frappe/frappe/desk/doctype/auto_repeat/auto_repeat.py +87,'Recipients' not specified,'Destinatários' não especificado -apps/frappe/frappe/public/js/frappe/ui/filters/edit_filter.html +28,Apply,Aplicar -apps/frappe/frappe/integrations/utils.py +80,{0} Settings not found,{0} Configurações não encontradas -DocType: Module Def,Module Def,Módulo Def -apps/frappe/frappe/config/core.py +22,Pages in Desk (place holders),Páginas na Desk (suportes do lugar) -DocType: DocField,Collapsible Depends On,Depende dobrável -DocType: Print Format,Print Format Help,Ajuda sobre Formatos de Impressão -apps/frappe/frappe/public/js/frappe/views/reports/grid_report.js +822,With Groups,Com Grupos -apps/frappe/frappe/core/doctype/data_import/exporter.py +72,"If you are updating, please select ""Overwrite"" else existing rows will not be deleted.","Se você estiver atualizando, por favor selecione ""Substituir"" linhas outra existentes não serão excluídos." -DocType: Event,Every Month,Todos os meses -DocType: Letter Head,Letter Head in HTML,Cabeça Carta em HTML -DocType: About Us Settings,Org History Heading,Cabeçalho da História da Organização -apps/frappe/frappe/core/doctype/user/user.py +483,Sorry. You have reached the maximum user limit for your subscription. You can either disable an existing user or buy a higher subscription plan.,Desculpa. Você atingiu o limite máximo de usuários para a sua inscrição. Você pode desativar um usuário existente ou comprar um plano de inscrição superior. -DocType: Print Settings,Allow Print for Cancelled,Permitir impressão para cancelado -DocType: Communication,Integrations can use this field to set email delivery status,Integrações pode usar este campo para definir o status de entrega de email -DocType: Web Form,Web Page Link Text,Link de Texto para Página Web -DocType: GSuite Settings,Allow GSuite access,Permitir acesso ao GSuite -DocType: DocType,Naming,Nomeação -DocType: Event,Every Year,Todo Ano -apps/frappe/frappe/core/doctype/data_import/data_import.js +211,Select All,Selecionar Tudo -apps/frappe/frappe/core/doctype/doctype/doctype.py +228,Invalid fieldname '{0}' in autoname,nome do campo inválido '{0}' em autoname -apps/frappe/frappe/custom/doctype/customize_form/customize_form.js +261,Allow field to remain editable even after submission,Permitir campo para permanecer editável mesmo após a apresentação -DocType: Website Script,Website Script,Script do Site -apps/frappe/frappe/config/setup.py +205,Customized HTML Templates for printing transactions.,Modelos HTML customizadas para operações de impressão. -DocType: Workflow,Is Active,É Ativo -apps/frappe/frappe/desk/form/utils.py +114,No further records,Não há mais registros -DocType: DocField,Long Text,Texto Longo -DocType: Workflow State,Primary,Primário -apps/frappe/frappe/core/doctype/data_import/importer.py +77,Please do not change the rows above {0},"Por favor, não alterar as linhas acima {0}" -DocType: Contact,More Information,Mais Informações -DocType: Desktop Icon,Desktop Icon,Ícone da área de trabalho -apps/frappe/frappe/utils/nestedset.py +252,{0} {1} cannot be a leaf node as it has children,"{0} {1} não pode ser um nó de extremidade , uma vez que tem filhos" -apps/frappe/frappe/public/js/frappe/views/interaction.js +156,Add Attachment,Anexar -apps/frappe/frappe/public/js/frappe/views/communication.js +93,Send Read Receipt,Enviar Confirmação de Leitura -DocType: Stripe Settings,Stripe Settings,Configurações do Stripe -apps/frappe/frappe/www/login.py +89,Invalid Login Token,Inválido símbolo de logon -apps/frappe/frappe/public/js/frappe/misc/pretty_date.js +49,1 hour ago,1 hora atrás -DocType: Error Snapshot,Parent Error Snapshot,Pai Snapshot de Erro -DocType: Workflow State,share-alt,partes-alt -DocType: Address Template,"

    Default Template

    -

    Uses Jinja Templating and all the fields of Address (including Custom Fields if any) will be available

    -
    {{ address_line1 }}<br>
    -{% if address_line2 %}{{ address_line2 }}<br>{% endif -%}
    -{{ city }}<br>
    -{% if state %}{{ state }}<br>{% endif -%}
    -{% if pincode %} PIN:  {{ pincode }}<br>{% endif -%}
    -{{ country }}<br>
    -{% if phone %}Phone: {{ phone }}<br>{% endif -%}
    -{% if fax %}Fax: {{ fax }}<br>{% endif -%}
    -{% if email_id %}Email: {{ email_id }}<br>{% endif -%}
    -
    ","

    Default Template -

    Jinja Templating e todos os campos de Endereço ( incluindo campos personalizados se houver) estará disponível -

      {{address_line1}} & lt; br & gt; 
    - {% if address_line2%} {{address_line2}} & lt; br & gt; { endif% -%} 
    - {{cidade}} & lt; br & gt; 
    - {% if estado%} {{estado}} & lt; br & gt; {% endif -%} {% 
    - se pincode%} PIN: {{pincode}} & lt; br & gt; {% endif -%} 
    - {{país}} & lt; br & gt; 
    - {% if telefone%} Telefone: {{telefone}} & lt; br & gt; { % endif -%} 
    - {% if fax%} Fax: {{fax}} & lt; br & gt; {% endif -%} 
    - {% if% email_id} Email: {{email_id}} & lt; br & gt ; {endif% -%} 
    -  "
    -apps/frappe/frappe/templates/includes/navbar/navbar_login.html +23,Switch To Desk,Ir para o Desktop
    -DocType: Workflow Document State,Workflow Document State,Status do Documento do Fluxo de Trabalho
    -apps/frappe/frappe/public/js/frappe/request.js +148,File too big,Arquivo muito grande
    -DocType: Payment Gateway,Payment Gateway,Gateway de pagamento
    -DocType: Portal Settings,Hide Standard Menu,Esconder Menu Padrão
    -apps/frappe/frappe/config/setup.py +163,Add / Manage Email Domains.,Adicionar / Gerenciar Domínios de E-mail.
    -apps/frappe/frappe/workflow/doctype/workflow/workflow.py +78,Cannot cancel before submitting. See Transition {0},Não pode cancelar antes de enviar.
    -apps/frappe/frappe/www/printview.py +211,Print Format {0} is disabled,Formato de Impressão {0} está desativado
    -,Address and Contacts,Endereços e Contatos
    -DocType: User,Allow user to login only after this hour (0-24),Permitir que o usuário faça o login somente após este horário (0-24)
    -apps/frappe/frappe/desk/doctype/todo/todo_list.js +22,Assigned By Me,Atribuído por Mim
    -apps/frappe/frappe/core/doctype/doctype/doctype.py +102,Not in Developer Mode! Set in site_config.json or make 'Custom' DocType.,Você não está no modo de desenvolvedor! Configure em site_config.json ou faça um DocType 'Personalizado'.
    -apps/frappe/frappe/custom/doctype/customize_form/customize_form.js +253,Hide field in Standard Print Format,Ocultar campo no padrão Print Format
    -DocType: Email Queue,Unsubscribe Param,Parâmetero de Cancelamento de Inscrição
    -DocType: Auto Repeat,Weekly,Semanalmente
    -DocType: SMS Settings,Eg. smsgateway.com/api/send_sms.cgi,Por exemplo: smsgateway.com / api / send_sms.cgi
    -DocType: Communication,In Reply To,Em resposta a
    -DocType: DocField,Float,Float
    -DocType: Auto Repeat,Submit on creation,Enviar ao criar
    -DocType: Contact,Purchase Master Manager,Gerente de Cadastros de Compras
    -DocType: DocType,DocType is a Table / Form in the application.,DocType é uma Tabela / Form na aplicação.
    -apps/frappe/frappe/public/js/frappe/views/reports/reportview.js +112,{0} Report,{0} Relatório
    -DocType: DocField,Print Width,Largura de impressão
    -DocType: User,Allow user to login only before this hour (0-24),Permitir que o usuário faça o login somente antes deste horário (0-24)
    -DocType: Social Login Key,Access Token URL,URL do Token de Acesso
    -apps/frappe/frappe/www/contact.py +57,New Message from Website Contact Page,Nova Mensagem da Página de Contato do Site
    -apps/frappe/frappe/core/doctype/sms_settings/sms_settings.py +28,Please enter valid mobile nos,"Por favor, indique números de celular válidos"
    -apps/frappe/frappe/utils/bot.py +185,"Don't know, ask 'help'","Não sei, peça 'ajuda'"
    -DocType: DocType,Comments and Communications will be associated with this linked document,Comentários e comunicações serão associados com este documento relacionado
    -apps/frappe/frappe/printing/page/print_format_builder/print_format_builder_sidebar.html +3,Filter...,Filtre...
    -DocType: OAuth Client, Advanced Settings,Configurações Avançadas
    -apps/frappe/frappe/website/doctype/website_settings/website_settings.py +34,{0} does not exist in row {1},{0} não existe em linha {1}
    -apps/frappe/frappe/core/doctype/sms_settings/sms_settings.py +64,Please Update SMS Settings,Atualize Configurações SMS
    -DocType: User,Last Known Versions,Últimas versões conhecidas
    -apps/frappe/frappe/config/setup.py +158,Add / Manage Email Accounts.,Adicionar / Gerenciar contas de email.
    -apps/frappe/frappe/templates/emails/auto_reply.html +1,Thank you for your email,Obrigado pelo seu email
    -apps/frappe/frappe/core/doctype/user/user.py +913,Administrator accessed {0} on {1} via IP Address {2}.,Administrador acessada {0} em {1} através do endereço IP {2}.
    -apps/frappe/frappe/public/js/frappe/ui/filters/filter.js +10,Equals,Igual
    -apps/frappe/frappe/core/doctype/doctype/doctype.py +556,Options 'Dynamic Link' type of field must point to another Link Field with options as 'DocType',"Opções 'Dynamic Link' tipo de campo deve apontar para um outro campo Ligação com opções como ""TipoDoc '"
    -DocType: About Us Settings,Team Members Heading,Título da página Membros da Equipe
    -apps/frappe/frappe/utils/csvutils.py +37,Invalid CSV Format,Formato inválido de CSV
    -DocType: DocField,Do not allow user to change after set the first time,Não permitir que o usuário altere após definir o primeiro tempo
    -apps/frappe/frappe/public/js/frappe/upload.js +281,Private or Public?,Privada ou pública?
    -DocType: Contact,Contact,Contato
    -DocType: Website Settings,Banner is above the Top Menu Bar.,A faixa está acima da barra de menu superior.
    -DocType: User,API Secret,Segredo da API
    -apps/frappe/frappe/public/js/frappe/views/reports/query_report.js +840,Export Report: ,Exportar Relatório:
    -apps/frappe/frappe/config/core.py +12,Models (building blocks) of the Application,Modelos (blocos de construção) do aplicativo
    -apps/frappe/frappe/custom/doctype/customize_form/customize_form.js +105,Select Module,Selecione o Módulo
    -apps/frappe/frappe/sessions.py +29,Cache Cleared,Cache Limpo
    -DocType: About Us Settings,More content for the bottom of the page.,Mais conteúdo na parte de baixo da página.
    -DocType: Workflow,DocType on which this Workflow is applicable.,DocType em que este fluxo de trabalho é aplicável.
    -DocType: Feedback Trigger,Enabled,Habilitado
    -apps/frappe/frappe/email/doctype/email_group/email_group.js +11,Import Subscribers,Importar Inscritos
    -DocType: Print Settings,PDF Settings,Configurações do PDF
    -DocType: Kanban Board Column,Column Name,Nome da coluna
    -DocType: Language,Based On,Baseado em
    -apps/frappe/frappe/printing/doctype/print_format/print_format.js +34,Make Default,Tornar padrão
    -apps/frappe/frappe/core/doctype/doctype/doctype.py +587,Fieldtype {0} for {1} cannot be indexed,FieldType {0} para {1} não pode ser indexado
    -DocType: Workflow State,Download,Baixar
    -DocType: Blog Post,Blog Intro,Introdução do Blog
    -DocType: DocField,Display Depends On,Visualização depende
    -DocType: ToDo,Low,Baixa
    -apps/frappe/frappe/core/doctype/data_import/exporter.py +65,"If you are uploading new records, leave the ""name"" (ID) column blank.","Se você estiver fazendo upload de novos registros, deixe a coluna ""name"" (ID) em branco."
    -apps/frappe/frappe/config/core.py +47,Errors in Background Events,Erros em Eventos em Segundo Plano
    -apps/frappe/frappe/printing/page/print_format_builder/print_format_builder.js +399,No of Columns,Nenhuma das Colunas
    -apps/frappe/frappe/model/rename_doc.py +162,"Another {0} with name {1} exists, select another name","Outra {0} com o nome {1} existe , selecione outro nome"
    -DocType: Website Settings,Website Theme Image,Imagem do Tema do Site
    -DocType: LDAP Settings,Organizational Unit,Unidade Organizacional
    -apps/frappe/frappe/public/js/frappe/model/model.js +119,Unable to load: {0},Não é possível carregar: {0}
    -DocType: DocField,Read Only,Somente Leitura
    -DocType: Print Settings,Send Print as PDF,Enviar impressão como PDF
    -DocType: Web Form,Amount,Total
    -apps/frappe/frappe/website/doctype/portal_settings/portal_settings.js +20,Restore to default settings?,Restaurar as configurações padrão?
    -apps/frappe/frappe/website/doctype/website_settings/website_settings.py +23,Invalid Home Page,Inválido Página Inicial
    -apps/frappe/frappe/public/js/frappe/views/reports/grid_report.js +169,Reset Filters,Restaurar Filtros
    -apps/frappe/frappe/core/doctype/doctype/doctype.py +796,{0}: Permission at level 0 must be set before higher levels are set,{0} : permissão no nível 0 deve ser definida antes de definir os níveis mais altos
    -apps/frappe/frappe/desk/doctype/todo/todo.py +34,Assignment closed by {0},Atribuição fechado por {0}
    -DocType: Integration Request,Remote,Remoto
    -DocType: Integration Request,Remote,Remoto
    -apps/frappe/frappe/printing/doctype/print_format/print_format.js +28,Please select DocType first,"Por favor, selecione DocType primeiro"
    -apps/frappe/frappe/email/doctype/newsletter/newsletter.py +179,Confirm Your Email,Confirme seu Email
    -apps/frappe/frappe/www/login.html +41,Or login with,Ou faça login com
    -apps/frappe/frappe/desk/page/activity/activity_row.html +19,Communicated via {0} on {1}: {2},Comunicada via {0} em {1}: {2}
    -apps/frappe/frappe/core/doctype/communication/comment.py +95,{0} mentioned you in a comment in {1},{0} mencionou você em um comentário em {1}
    -apps/frappe/frappe/public/js/frappe/ui/toolbar/awesome_bar.js +141,e.g. (55 + 434) / 4 or =Math.sin(Math.PI/2)...,por exemplo (55 + 434) / 4 ou = Math.sin (Math.PI / 2) ...
    -DocType: DocField,Perm Level,Nível Permanente
    -apps/frappe/frappe/desk/doctype/event/event.py +121,Events In Today's Calendar,Eventos no calendário de hoje
    -apps/frappe/frappe/public/js/frappe/views/treeview.js +342,View List,Ver Lista
    -apps/frappe/frappe/www/feedback.html +90,Please give a rating.,"Por favor, atribua um rating."
    -apps/frappe/frappe/public/js/frappe/feedback.js +47,{0} Feedback Request,{0} Solicitação de Feedback
    -apps/frappe/frappe/desk/page/setup_wizard/setup_wizard.js +415,The First User: You,O primeiro usuário: Você
    -DocType: Translation,Source Text,Texto Original
    -apps/frappe/frappe/www/login.py +80,Missing parameters for login,Parâmetros que faltam para o login
    -DocType: Workflow State,folder-open,abrir pasta
    -apps/frappe/frappe/custom/doctype/customize_form/customize_form.js +249,Hide field in form,Esconder campo em formulário
    -DocType: Feedback Trigger,Optional: The alert will be sent if this expression is true,Opcional: O alerta será enviado se essa expressão é verdadeira
    -DocType: Print Settings,Print with letterhead,Imprimir com o timbre
    -DocType: Unhandled Email,Raw Email,Email Puro
    -DocType: ToDo,Assigned By,Atribuído por
    -apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +27,You can use Customize Form to set levels on fields.,"Você pode usar ""Personalizar Formulário"" para definir os níveis de campos."
    -apps/frappe/frappe/desk/reportview.py +110,{0} is saved,{0} foi salvo
    -apps/frappe/frappe/core/doctype/user/user.py +339,User {0} cannot be renamed,O usuário {0} não pode ser renomeado
    -apps/frappe/frappe/config/desk.py +59,Email Group List,Lista do Grupo de Emails
    -DocType: Website Settings,An icon file with .ico extension. Should be 16 x 16 px. Generated using a favicon generator. [favicon-generator.org],Um ícone do arquivo com extensão .ico. Deve ser de 16 x 16 px. Gerado usando um gerador de favicon. [favicon-generator.org]
    -DocType: Email Account,Email Addresses,Endereço de Email
    -DocType: Email Domain,domain name,nome de domínio
    -DocType: Kanban Board Column,Order,Pedido
    -DocType: Report,Ref DocType,DocType de Ref.
    -apps/frappe/frappe/core/doctype/doctype/doctype.py +808,{0}: Cannot set Amend without Cancel,{0}: Não é possível definir Amend sem Cancelar
    -apps/frappe/frappe/public/js/frappe/form/templates/print_layout.html +25,Full Page,Página completa
    -DocType: DocType,Is Child Table,É Tabela Filho
    -apps/frappe/frappe/utils/csvutils.py +132,{0} must be one of {1},{0} deve fazer parte de {1}
    -apps/frappe/frappe/public/js/frappe/form/form_viewers.js +35,{0} is currently viewing this document,{0} está atualmente visualizando este documento
    -apps/frappe/frappe/config/core.py +52,Background Email Queue,Fila de Email em Segundo Plano
    -DocType: Communication,Opened,Inaugurado
    -DocType: Workflow State,chevron-left,divisa-esquerda
    -DocType: Communication,Sending,Transmitindo
    -apps/frappe/frappe/auth.py +272,Not allowed from this IP Address,Não é permitido a partir deste endereço IP
    -apps/frappe/frappe/config/setup.py +282,Install Applications.,Instalar aplicativos.
    -DocType: Print Settings,Send Email Print Attachments as PDF (Recommended),Enviar anexos de email em PDF (Recomendado)
    -DocType: Web Page,Left,Saiu
    -DocType: Event,All Day,O dia todo
    -DocType: Workflow Action,Workflow Action,Ação do Fluxo de Trabalho
    -DocType: Event,Send an email reminder in the morning,Enviar um email lembrete na parte da manhã
    -DocType: Blog Post,Published On,Publicado no
    -apps/frappe/frappe/website/doctype/web_form/web_form.py +350,Mandatory Information missing:,Informações obrigatórias ausente:
    -apps/frappe/frappe/core/doctype/doctype/doctype.py +584,Field '{0}' cannot be set as Unique as it has non-unique values,"O campo '{0}' não pode ser definido como único, pois tem valores não-exclusivos"
    -apps/frappe/frappe/client.py +160,Only 200 inserts allowed in one request,São permitidas somente 200 inserções por solicitação
    -DocType: Event,Repeat On,Repetir em
    -DocType: Communication,Marked As Spam,Marcado como spam
    -apps/frappe/frappe/public/js/frappe/list/list_sidebar.html +26,Tree,Árvore
    -apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +30,User Permissions,Permissões de Usuário
    -DocType: Workflow State,warning-sign,sinal de alerta
    -DocType: Workflow State,User,Usuário
    -apps/frappe/frappe/handler.py +94,Logged Out,Deslogado
    -DocType: Bulk Update,Update Value,Atualizar Valor
    -DocType: System Settings,Number Format,Formato de número
    -DocType: Custom Field,Insert After,Inserir Após
    -DocType: Desktop Icon,Reverse Icon Color,Inverta Ícone Cor
    -apps/frappe/frappe/printing/page/print_format_builder/print_format_builder.js +405,Section Heading,Cabeçalho da Seção
    -DocType: Website Settings,Title Prefix,Prefixo do Título
    -DocType: Email Account,Notifications and bulk mails will be sent from this outgoing server.,Notificações e emails em massa serão enviados por este servidor de saída.
    -apps/frappe/frappe/public/js/frappe/form/templates/form_sidebar.html +68,Currently Viewing,Atualmente Exibindo
    -apps/frappe/frappe/email/doctype/email_group/email_group.py +42,{0} subscribers added,{0} assinantes acrescentados
    -apps/frappe/frappe/public/js/frappe/ui/filters/filter.js +15,Not In,Não Presente
    -apps/frappe/frappe/public/js/frappe/ui/toolbar/search_utils.js +241,Hub,Hub
    -apps/frappe/frappe/core/doctype/doctype/doctype.py +540,Max width for type Currency is 100px in row {0},Largura máxima para o tipo de moeda é 100px na linha {0}
    -apps/frappe/frappe/config/website.py +13,Content web page.,Conteúdo da Página Web
    -apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +9,Add a New Role,Adicionar um Novo Papel
    -DocType: Deleted Document,Deleted Document,Documento Excluído
    -apps/frappe/frappe/templates/includes/login/login.js +223,Oops! Something went wrong,Ops! Aconteceu algo inesperado
    -apps/frappe/frappe/config/core.py +37,Client side script extensions in Javascript,Extensões de script do lado do cliente em Javascript
    -DocType: User,Email Settings,Configurações de Email
    -apps/frappe/frappe/workflow/doctype/workflow/workflow.py +65,{0} not a valid State,{0} não é um status válido
    -apps/frappe/frappe/core/doctype/doctype/doctype.py +617,Search field {0} is not valid,Campo de pesquisa {0} não é válido
    -DocType: Workflow State,ok-circle,ok-círculo
    -apps/frappe/frappe/utils/bot.py +150,You can find things by asking 'find orange in customers',"Você pode encontrar as coisas pedindo ""encontrar fulano em clientes"""
    -apps/frappe/frappe/core/doctype/user/user.py +189,Sorry! User should have complete access to their own record.,Desculpe! O usuário deve ter acesso completo ao seu próprio registro.
    -,Usage Info,Informações de Uso
    -apps/frappe/frappe/templates/pages/integrations/razorpay_checkout.py +33,Invalid Token,Token inválido
    -apps/frappe/frappe/custom/doctype/custom_field/custom_field.py +24,Label is mandatory,Etiqueta é obrigatório
    -DocType: PayPal Settings,API Username,Usuário da API
    -apps/frappe/frappe/public/js/frappe/views/gantt/gantt_view.js +145,Half Day,Meio Período
    -DocType: Communication,Communication Type,Tipo de comunicação
    -DocType: Email Account,Service,Manutenção do Veículo
    -DocType: File,File Name,Nome do arquivo
    -apps/frappe/frappe/core/doctype/data_import/importer.py +512,Did not find {0} for {0} ({1}),Não encontrou {0} para {0} ( {1})
    -apps/frappe/frappe/utils/bot.py +176,"Oops, you are not allowed to know that","Ops, você não tem permissão para saber isso"
    -apps/frappe/frappe/public/js/frappe/ui/slides.js +324,Next,Próximo
    -apps/frappe/frappe/handler.py +94,You have been successfully logged out,Você saiu do sistema com sucesso
    -apps/frappe/frappe/core/doctype/user/user.py +264,Complete Registration,Registro Completo
    -DocType: GCalendar Settings,Enable,Permitir
    -apps/frappe/frappe/core/doctype/data_import/exporter.py +69,You can only upload upto 5000 records in one go. (may be less in some cases),Você só pode fazer upload de até 5.000 registros de uma só vez. (Este valor pode vir a ser inferior em alguns casos)
    -apps/frappe/frappe/public/js/frappe/views/reports/reportview.js +775,Report was not saved (there were errors),O Relatório não foi salvo (houve erros)
    -apps/frappe/frappe/custom/doctype/customize_form/customize_form.py +180,Row {0}: Not allowed to enable Allow on Submit for standard fields,Linha {0}: Não é permitido habilitar Permitir ao Enviar para campos padrão
    -apps/frappe/frappe/core/doctype/role/role.py +12,Standard roles cannot be renamed,Funções padrão não podem ser renomeadas
    -DocType: SMS Settings,Static Parameters,Parâmetros estáticos
    -DocType: Chat Message,Room,Sala
    -DocType: User,Desktop Background,Papel de parede
    -DocType: Portal Settings,Custom Menu Items,Itens de Menu Personalizado
    -DocType: Workflow State,chevron-right,divisa-direito
    -apps/frappe/frappe/custom/doctype/customize_form/customize_form.js +218,"Change type of field. (Currently, Type change is \
    -						allowed among 'Currency and Float')","Alterar o tipo de campo. (Atualmente, a mudança de tipo é permitido entre \
    - 'Moeda e Float')"
    -apps/frappe/frappe/website/doctype/web_form/web_form.py +37,You need to be in developer mode to edit a Standard Web Form,Você precisa estar no modo de desenvolvedor para editar um Formulário Web Padrão
    -DocType: Workflow State,camera,câmera
    -DocType: Website Settings,Brand HTML,Marca HTML
    -apps/frappe/frappe/templates/includes/login/login.js +24,Both login and password required,Login e senha necessários
    -apps/frappe/frappe/model/document.py +648,Please refresh to get the latest document.,Por favor de atualização para obter os últimos documentos.
    -,Desktop,Área de trabalho
    -DocType: Auto Email Report,Filter Meta,Filtrar Meta
    -DocType: Web Form,Text to be displayed for Link to Web Page if this form has a web page. Link route will be automatically generated based on `page_name` and `parent_website_route`,"O texto a ser exibido para o link da página da web, se este formulário tem uma página web. Um link será gerado automaticamente com base em ` page_name` e `parent_website_route`"
    -DocType: Feedback Request,Feedback Trigger,Gatilho para Feedback
    -DocType: Patch Log,Patch,Remendo
    -DocType: User,Background Style,Estilo do Fundo
    -apps/frappe/frappe/model/rename_doc.py +77,merged {0} into {1},Combinado {0} com {1}
    -apps/frappe/frappe/core/doctype/activity_log/feed.py +51,{0} logged in,{0} logado(s)
    -DocType: Web Form,Amount Field,Campo Valor
    -DocType: Dropbox Settings,Send Notifications To,Enviar Notificações para
    -DocType: Bulk Update,Max 500 records at a time,Máximo de  500 registros por vez
    -apps/frappe/frappe/utils/csvutils.py +37,Unable to open attached file. Did you export it as CSV?,Foi impossível abrir o arquivo anexado. Você o exportou como CSV?
    -DocType: DocField,Ignore User Permissions,Ignorar permissões de usuário
    +A4,A4,
    +API Endpoint,API Endpoint,
    +API Key,Chave da API,
    +Access Token,Token de Acesso,
    +Account,Conta,
    +Accounts Manager,Gerente de Contas,
    +Accounts User,Usuário de Contas,
    +Action,Ação,
    +Actions,Ações,
    +Active,Ativo,
    +Add,Adicionar,
    +Add Comment,Adicionar Comentário,
    +Add Row,Adicionar linha,
    +Address,Endereço,
    +Address Line 2,Complemento,
    +Address Title,Título do Endereço,
    +Address Type,Tipo de Endereço,
    +Administrator,Administrador,
    +All Day,Dia Inteiro,
    +Allow Delete,Permitir Excluir,
    +Amended From,Alterado De,
    +Amount,Montante,
    +Applicable For,Aplicável Para,
    +Approval Status,Estado de Aprovação,
    +Assign,Atribuir,
    +Assign To,Atribuir a,
    +Attachment,Anexo,
    +Attachments,Anexos,
    +Author,Autor,
    +Auto Repeat,Repetição Automática,
    +Base URL,URL Base,
    +Based On,Baseado em,
    +Beginner,Principiante,
    +Billing,Faturamento,
    +Cancel,Cancelar,
    +Category,Categoria,
    +Category Name,Nome da Categoria,
    +City,Cidade,
    +City/Town,Cidade/Município,
    +Client,Cliente,
    +Client ID,ID do Cliente,
    +Client Secret,Segredo do cliente,
    +Closed,Fechado,
    +Code,Código,
    +Collapse All,Recolher todos,
    +Color,Cor,
    +Company Name,Nome da Empresa,
    +Condition,Condição,
    +Contact,Contato,
    +Contact Details,Dados de Contato,
    +Content,Conteúdo,
    +Content Type,Tipo de Conteúdo,
    +Create,Criar,
    +Created By,Criado por,
    +Current,Atual,
    +Custom HTML,HTML Personalizado,
    +Custom?,Personalizado?,
    +Date Format,Formato de Data,
    +Datetime,Data e Hora,
    +Day,Dia,
    +Default Letter Head,Cabeçalho de Carta Padrão,
    +Defaults,Padrões,
    +Delivery Status,Status da Entrega,
    +Department,Departamento,
    +Details,Detalhes,
    +Document Name,Nome do documento,
    +Document Status,Status do Documento,
    +Document Type,tipo de documento,
    +Domain,Domínio,
    +Domains,Domínios,
    +Draft,Rascunho,
    +Edit,Editar,
    +Email Account,Conta de Email,
    +Email Address,Endereço de Email,
    +Email ID,Email ID,
    +Email Sent,Email enviado,
    +Email Template,Modelo de email,
    +Enable,Permitir,
    +Enabled,Ativado,
    +End Date,Data Final,
    +Error Code: {0},Código do Erro: {0},
    +Error Log,Log de Erro,
    +Event,Evento,
    +Expand All,Expandir todos,
    +Fail,Falha,
    +Failed,Falhou,
    +Fax,Fax,
    +Feedback,Comentários,
    +Female,Feminino,
    +Field Name,Nome do Campo,
    +Fieldname,Nome do Campo,
    +Fields,Campos,
    +First Name,Nome,
    +Frequency,Frequência,
    +Friday,Sexta-feira,
    +From,De,
    +Full,Cheio,
    +Full Name,Nome Completo,
    +Further nodes can be only created under 'Group' type nodes,Outros nós só podem ser criados dentro dos nós do tipo 'Grupo',
    +Gender,Sexo,
    +GitHub Sync ID,GitHub Sync ID,
    +Guest,Convidado,
    +Half Day,Meio Período,
    +Half Yearly,Semestrais,
    +High,Alto,
    +Hourly,De hora em hora,
    +Hub Sync ID,Identificação da Sincronização do Hub,
    +IP Address,Endereço de IP,
    +Image,Imagem,
    +Image View,Visualização de Imagem,
    +Import Data,Importar dados,
    +Import Log,Log de Importação,
    +Inactive,Inativo,
    +Insert,Inserir,
    +Interests,Juros,
    +Introduction,Introdução,
    +Is Active,É Ativo,
    +Is Completed,Está completo,
    +Is Default,É Padrão,
    +Kanban Board,Painel Kanban,
    +Label,Rótulo,
    +Language Name,Nome do Idioma,
    +Last Name,Sobrenome,
    +Leaderboard,Placar,
    +Letter Head,Cabeçalho de Carta,
    +Level,Nível,
    +Limit,Limite,
    +Log,Registo,
    +Logs,Logs,
    +Low,Baixo,
    +Maintenance Manager,Gerente de Manutenção,
    +Maintenance User,Usuário da Manutenção,
    +Male,Masculino,
    +Mandatory,Obrigatório,
    +Mapping,Mapeamento,
    +Mapping Type,Tipo de mapeamento,
    +Medium,Médio,
    +Meeting,Encontro,
    +Message Examples,Exemplos de Mensagens,
    +Method,Método,
    +Middle Name,Nome do Meio,
    +Middle Name (Optional),Nome do meio (opcional),
    +Monday,Segunda-feira,
    +Monthly,Mensal,
    +More,Mais,
    +More Information,Mais Informações,
    +More...,Mais...,
    +Move,Mover,
    +My Account,Minha Conta,
    +New Address,Novo Endereço,
    +New Contact,Novo Contato,
    +Next,Próximo,
    +No Data,Sem Dados,
    +No address added yet.,Ainda não foi adicionado nenhum endereço.,
    +No contacts added yet.,Ainda não foi adicionado nenhum contato.,
    +No items found.,Nenhum item encontrado.,
    +None,Nenhum,
    +Not Permitted,Não Permitido,
    +Not active,Inativo,
    +Notes,Notas,
    +Number,Número,
    +Online,Online,
    +Operation,Operação,
    +Options,Opções,
    +Other,Outro,
    +Owner,Proprietário,
    +Page Missing or Moved,Página ausente ou mudou,
    +Parameter,Parâmetro,
    +Password,Senha,
    +Payment Gateway,Gateway de Pagamento,
    +Payment Gateway Name,Nome do Gateway de Pagamento,
    +Payments,Pagamentos,
    +Period,Período,
    +Pincode,Pincode,
    +Plan Name,Nome do Plano,
    +Please enable pop-ups,Por favor habilite os pop-ups,
    +Please select Company,"Por favor, selecione a Empresa",
    +Please select {0},"Por favor, selecione {0}",
    +Please set Email Address,"Por favor, defina o endereço de Email",
    +Portal,Portal,
    +Portal Settings,Configurações do Portal,
    +Preview,Pré-visualização,
    +Primary,Primário,
    +Print Format,Formato de Impressão,
    +Print Settings,Configurações de Impressão,
    +Print taxes with zero amount,Imprima impostos com montante zero,
    +Private,Privado,
    +Property,Propriedade,
    +Public,Público,
    +Published,Publicado,
    +Purchase Manager,Gerente de Compras,
    +Purchase Master Manager,Gerente de Cadastros de Compras,
    +Purchase User,Usuário de Compras,
    +Query Options,Opções de Consulta,
    +Range,Faixa,
    +Rating,Rating,
    +Received,Recebido,
    +Recipients,Destinatários,
    +Redirect URL,Redirecionar URL,
    +Reference,Referência,
    +Reference Date,Data de Referência,
    +Reference Document,Documento de referência,
    +Reference Document Type,Referência Tipo de Documento,
    +Reference Owner,Proprietário da Referência,
    +Reference Type,Tipo de Referência,
    +Refresh Token,Token de Atualização,
    +Region,Região,
    +Rejected,Rejeitado,
    +Reopen,Reabrir,
    +Replied,Respondido,
    +Report,Relatório,
    +Report Builder,Criador de Relatório,
    +Report Type,Tipo de Relatório,
    +Reports,Relatórios,
    +Response,Resposta,
    +Role,Função,
    +Route,Rota,
    +Sales Manager,Gerente de Vendas,
    +Sales Master Manager,Gerente de Cadastros de Vendas,
    +Sales User,Usuário de Vendas,
    +Salutation,Saudação,
    +Sample,Amostra,
    +Saturday,Sábado,
    +Saved,Salvo,
    +Scan Barcode,Scan Barcode,
    +Scheduled,Programado,
    +Search,Pesquisar,
    +Secret Key,Chave secreta,
    +Select,Selecionar,
    +Select DocType,Selecione DocType,
    +Send Now,Enviar agora,
    +Sent,Enviado,
    +Series {0} already used in {1},Série {0} já usado em {1},
    +Service,Serviço,
    +Set as Default,Definir como Padrão,
    +Settings,Configurações,
    +Shipping,Expedição,
    +Short Name,Nome Curto,
    +Slideshow,Apresentação de Slides,
    +Some information is missing,Alguma informação está faltando,
    +Source,Fonte,
    +Source Name,Nome da Fonte,
    +Standard,Padrão,
    +Start Date,Data de Início,
    +Start Import,Iniciar importação,
    +State,Estado,
    +Stopped,Parado,
    +Subject,Assunto,
    +Submit,Enviar,
    +Successful,Bem sucedido,
    +Summary,Resumo,
    +Sunday,Domingo,
    +System Manager,Administrador do Sistema,
    +Target,Meta,
    +Task,Tarefa,
    +Tax Category,Categoria de imposto,
    +Test,Teste,
    +Thank you,Obrigado,
    +The page you are looking for is missing. This could be because it is moved or there is a typo in the link.,A página que você está procurando não existe. Isto pode ser porque ela foi movido ou se houve um erro de digitação no link.,
    +Timespan,Intervalo de tempo,
    +To,Para,
    +To Date,Até a Data,
    +Tools,Ferramentas,
    +Traceback,Traceback,
    +URL,URL,
    +Unsubscribed,Inscrição Cancelada,
    +Use Sandbox,Use Sandbox,
    +User,Usuário,
    +User ID,ID de Usuário,
    +Users,Usuários,
    +Validity,Validade,
    +Warning,Aviso,
    +Website,Site,
    +Website Manager,Administrador do Site,
    +Website Settings,Configurações do Site,
    +Wednesday,Quarta-feira,
    +Week,Semana,
    +Weekdays,Dias da semana,
    +Weekly,Semanalmente,
    +Welcome email sent,Email de Boas Vindas enviado,
    +Workflow,Fluxo de Trabalho,
    +You need to be logged in to access this page,Você precisa estar logado para acessar esta página,
    +old_parent,old_parent,
    +{0} is mandatory,{0} é obrigatório,
    + to your browser, para o seu navegador,
    +"Company History","Histórico da Empresa",
    +"Parent" signifies the parent table in which this row must be added,"Pai" significa a tabela pai no qual deve ser acrescentado nesta linha,
    +"Team Members" or "Management","Membros da Equipe" ou "Gerenciamento",
    +<head> HTML,<head> HTML,
    +'In Global Search' not allowed for type {0} in row {1},'Na Pesquisa Global' não é permitido para o tipo {0} na linha {1},
    +'In List View' not allowed for type {0} in row {1},'Visualização em Lista' não pode ser utilizado para o tipo {0} na linha {1},
    +'Recipients' not specified,'Destinatários' não especificado,
    +(Ctrl + G),(Ctrl + G),
    +** Failed: {0} to {1}: {2},** Falha: {0} para {1}: {2},
    +**Currency** Master,**Moeda** Principal,
    +0 - Draft; 1 - Submitted; 2 - Cancelled,0 - Rascunho; 1 - Enviado; 2 - Cancelado,
    +0 is highest,0 é maior,
    +1 Currency = [?] Fraction\nFor e.g. 1 USD = 100 Cent,1 Moeda = [?] Fração\nPor ex: 1 EUR = 100 Cêntimos,
    +1 comment,1 comentário,
    +1 hour ago,1 hora atrás,
    +1 minute ago,1 minuto atrás,
    +1 month ago,1 mês atrás,
    +1 year ago,1 ano atrás,
    +; not allowed in condition,; não permitido na condição,
    +

    Default Template

    \n

    Uses Jinja Templating and all the fields of Address (including Custom Fields if any) will be available

    \n
    {{ address_line1 }}<br>\n{% if address_line2 %}{{ address_line2 }}<br>{% endif -%}\n{{ city }}<br>\n{% if state %}{{ state }}<br>{% endif -%}\n{% if pincode %} PIN:  {{ pincode }}<br>{% endif -%}\n{{ country }}<br>\n{% if phone %}Phone: {{ phone }}<br>{% endif -%}\n{% if fax %}Fax: {{ fax }}<br>{% endif -%}\n{% if email_id %}Email: {{ email_id }}<br>{% endif -%}\n
    ,"

    Modelo Padrão

    \n

    Utiliza O Modelo Jinja e todos os campos do Endereço (incluindo Campos Personalizados, caso haja) estarão disponíveis

    \n
    {{ address_line1 }}<br>\n{% if address_line2 %}{{ address_line2 }}<br>{% endif -%}\n{{ city }}<br>\n{% if state %}{{ state }}<br>{% endif -%}\n{% if pincode %} PIN:  {{ pincode }}<br>{% endif -%}\n{{ country }}<br>\n{% if phone %}Telefone: {{ phone }}<br>{% endif -%}\n{% if fax %}Fax: {{ fax }}<br>{% endif -%}\n{% if email_id %}Email: {{ email_id }}<br>{% endif -%}\n
    ", +A Lead with this Email Address should exist,Um Lead com este email deve existir, +A list of resources which the Client App will have access to after the user allows it.
    e.g. project,"Uma lista de recursos que o aplicativo cliente terá acesso a depois que o usuário permita.
    por exemplo, do projeto", +A log of request errors,Um log de erros de solicitação, +A new account has been created for you at {0},Uma nova conta foi criada para você em {0}, +A symbol for this currency. For e.g. $,Um símbolo para esta moeda. Por exemplo: R$, +A word by itself is easy to guess.,Uma palavra por si só é fácil de adivinhar., +API Endpoint Args,API Endpoint Args, +API Key cannot be regenerated,A chave da API não pode ser regenerada, +API Password,Senha da API, +API Secret,Segredo da API, +API Username,Usuário da API, +ASC,ASC, +About Us Settings,Configurações do Quem Somos, +About Us Team Member,Sobre Nós - Membros da Equipe, +Accept Payment,Aceitar Pagamento, +Access Key ID,ID da chave de acesso, +Access Token URL,URL do Token de Acesso, +Action Failed,A Ação Falhou, +Action Timeout (Seconds),Tempo Limite de Ação (Segundos), +"Actions for workflow (e.g. Approve, Cancel).","Ações para o fluxo de trabalho (por exemplo, Aprovar , Cancelar) .", +Active Domains,Domínios ativos, +Active Sessions,Sessões ativas, +Activity Log,Log de Atividade, +Activity log of all users.,Registro de atividade de todos os usuários., +Add / Manage Email Domains.,Adicionar / Gerenciar Domínios de E-mail., +Add / Update,Adicionar / Atualizar, +Add A New Rule,Adicionar uma Nova Regra, +Add Another Comment,Adicionar Outro Comentário, +Add Attachment,Anexar, +Add Column,Adicionar Coluna, +Add Contact,Adicionar contato, +Add Contacts,Adicionar contatos, +Add Filter,Adicionar Filtro, +Add Group,Adicionar grupo, +Add New Permission Rule,Adicionar Nova Regra de Permissão, +Add Review,Adicione uma avaliação, +Add Signature,Adicionar Assinatura, +Add Subscribers,Adicionar Inscritos, +Add Total Row,Adicionar Linha de Total, +Add Unsubscribe Link,Adicionar link para cancelar inscrição, +Add User Permissions,Adicionar permissões do usuário, +Add a New Role,Adicionar uma Nova Função, +Add a column,Adicionar uma coluna, +Add a comment,Adicionar um comentário, +Add a new section,Adicione uma nova seção, +Add a tag ...,Adicione uma tag ..., +Add all roles,Adicionar todas funções, +Add custom forms.,Adicionar formulários personalizados., +Add custom javascript to forms.,Adicionar javascript personalizado aos formulários., +Add fields to forms.,Adicionar campos nos formulários., +Add meta tags to your web pages,Adicione meta tags às suas páginas da web, +Add script for Child Table,Adicionar script para tabela filho, +Add to table,Adicionar à mesa, +Add your own translations,Adicione suas próprias traduções, +"Added HTML in the <head> section of the web page, primarily used for website verification and SEO","HTML adicionado na seção <head> da página web, principalmente utilizadas para a verificação do site e SEO", +Added {0},Adicionado {0}, +Adding System Manager to this User as there must be atleast one System Manager,Adicionando este usuário como System Manager pois deve haver pelo menos um System Manager, +Additional Permissions,Permissões Adicionais, +Address Template,Modelo de Endereço, +Address Title is mandatory.,Titulo do Endereço é obrigatório., +Address and other legal information you may want to put in the footer.,Endereço e outras informações legais que você pode querer colocar no rodapé., +Addresses And Contacts,Endereços e Contatos, +Adds a client custom script to a DocType,Adiciona um script personalizado do cliente a um DocType, +Adds a custom field to a DocType,Adiciona um campo personalizado para um Tipo de Documento (DocType), +Admin,Administrador, +Administrator Logged In,Administrador logou-se, +Administrator accessed {0} on {1} via IP Address {2}.,Administrador acessada {0} em {1} através do endereço IP {2}., +Advanced,Avançado, +Advanced Control,Controle Avançado, +Advanced Search,Pesquisa Avançada, +Align Labels to the Right,Alinhar etiquetas à direita, +Align Value,Alinhar Valor, +All Images attached to Website Slideshow should be public,Todas as imagens anexadas à apresentação de slides do site devem ser públicas, +All customizations will be removed. Please confirm.,Todas as personalizações serão removidos. Por favor confirme., +"All possible Workflow States and roles of the workflow. Docstatus Options: 0 is""Saved"", 1 is ""Submitted"" and 2 is ""Cancelled""","Todos os status possíveis de fluxo de trabalho e as funções do fluxo de trabalho. Opções Docstatus: 0 é ""Salvo"", 1 é ""Enviado"" e 2 é ""Cancelado""", +All-uppercase is almost as easy to guess as all-lowercase.,Tudo em maiúsculas é quase tão fácil de adivinhar como tudo em minúsculas., +Allocated To,Atribuído a, +Allow,Permitir, +Allow Bulk Edit,Permitir edição em massa, +Allow Comments,Permitir Comentários, +Allow Consecutive Login Attempts ,Permitir tentativas de login consecutivas, +Allow Dropbox Access,Permitir Acesso Dropbox, +Allow Edit,Permitir Editar, +Allow Guest to View,Permitir visualização de convidado, +Allow Import (via Data Import Tool),Permitir Importação (via Data Import Tool), +Allow Incomplete Forms,Permitir Formulários Incompletos, +Allow Login After Fail,Permitir login após falha, +Allow Login using Mobile Number,Permitir login usando o número de celular, +Allow Login using User Name,Permitir Login usando o nome de usuário, +Allow Modules,Permitir Módulos, +Allow Multiple,Permitir Multiplos, +Allow Print,Permitir Impressão, +Allow Print for Cancelled,Permitir impressão para cancelado, +Allow Print for Draft,Permitir impressão para rascunho, +Allow Read On All Link Options,Permitir leitura em todas as opções de link, +Allow Rename,Permitir Renomear, +Allow Roles,Permitir Funções, +Allow Self Approval,Permitir auto-aprovação, +Allow approval for creator of the document,Permitir aprovação para o criador do documento, +Allow events in timeline,Permitir eventos na linha do tempo, +Allow in Quick Entry,Permitir na entrada rápida, +Allow on Submit,Permitir ao Enviar, +Allow only one session per user,Permitir apenas uma sessão por usuário, +Allow page break inside tables,Permitir quebra de página dentro de tabelas, +Allow saving if mandatory fields are not filled,Permitir salvar se os campos obrigatórios não são preenchidas, +Allow user to login only after this hour (0-24),Permitir que o usuário faça o login somente após este horário (0-24), +Allow user to login only before this hour (0-24),Permitir que o usuário faça o login somente antes deste horário (0-24), +Allowed,Permitido, +Allowed In Mentions,Permitido nas menções, +"Allowing DocType, DocType. Be careful!","Permitindo DocType , DocType . Tenha cuidado !", +Already Registered,Já está registrado, +Also adding the dependent currency field {0},Adicionando também o campo de moeda dependente {0}, +Always add "Draft" Heading for printing draft documents,Sempre adicionar "Rascunho" no cabeçalho para impressão de documentos não enviados, +Always use Account's Email Address as Sender,Sempre use de Conta endereço de email como remetente, +Always use Account's Name as Sender's Name,Sempre use o nome da conta como nome do remetente, +Amend,Corrigir, +Amending,Correção, +Amount Based On Field,Total Baseado no Campo, +Amount Field,Campo Valor, +Amount must be greater than 0.,Montante deve ser maior que 0., +An error occured during the payment process. Please contact us.,"Ocorreu um erro durante o processo de pagamento. Por favor, entre em contato conosco.", +An icon file with .ico extension. Should be 16 x 16 px. Generated using a favicon generator. [favicon-generator.org],Um ícone do arquivo com extensão .ico. Deve ser de 16 x 16 px. Gerado usando um gerador de favicon. [favicon-generator.org], +Ancestors Of,Antepassados De, +Another transaction is blocking this one. Please try again in a few seconds.,"Outra transação está bloqueando essa. Por favor, tente novamente em alguns segundos.", +"Another {0} with name {1} exists, select another name","Outra {0} com o nome {1} existe , selecione outro nome", +Any string-based printer languages can be used. Writing raw commands requires knowledge of the printer's native language provided by the printer manufacturer. Please refer to the developer manual provided by the printer manufacturer on how to write their native commands. These commands are rendered on the server side using the Jinja Templating Language.,"Qualquer linguagem de impressora baseada em string pode ser usada. Escrever comandos simples requer conhecimento da linguagem nativa da impressora fornecida pelo fabricante da impressora. Por favor, consulte o manual do desenvolvedor fornecido pelo fabricante da impressora sobre como escrever seus comandos nativos. Esses comandos são processados no lado do servidor usando o Jinja Templating Language.", +"Apart from System Manager, roles with Set User Permissions right can set permissions for other users for that Document Type.","Além de System Manager, as funções com o conjunto de permissões certas pode definir permissões para outros usuários para esse tipo de documento.", +Api Access,Acesso Api, +App,Aplicativo, +App Access Key,App Chave de Acesso, +App Client ID,App Cliente ID, +App Client Secret,App Cliente secreto, +App Name,Nome do App, +App Secret Key,App chave secreta, +App not found,App não encontrado, +App {0} already installed,O aplicativo {0} já está instalado, +App {0} is not installed,App {0} não está instalado, +Append To,Acrescente Para, +Append To can be one of {0},Para anexar pode ser um dos {0}, +Append To is mandatory for incoming mails,Para acrescentar é obrigatório para os e-mails recebidos, +"Append as communication against this DocType (must have fields, ""Status"", ""Subject"")","Anexar como a comunicação contra este DocType (deve ter campos, ""status"", ""Assunto"")", +Applicable Document Types,Tipos de documentos aplicáveis, +Apply,Aplicar, +Apply Strict User Permissions,Aplicar permissões de usuário estrito, +Apply To All Document Types,Aplicar a todos os tipos de documentos, +Apply this rule if the User is the Owner,Aplicar esta regra se o usuário é o proprietário, +Apply to all Documents Types,Aplicar a todos os tipos de documentos, +Appreciate,Apreciar, +Appreciation,Apreciação, +Archive,Arquivar, +Archived,Arquivada, +Archived Columns,Colunas Arquivadas, +Are you sure you want to delete the attachment?,Tem certeza de que deseja excluir o anexo?, +Are you sure you want to relink this communication to {0}?,Você tem certeza que deseja relinkar a comunicação para {0}?, +Are you sure?,Você tem certeza?, +Arial,Arial, +"As a best practice, do not assign the same set of permission rule to different Roles. Instead, set multiple Roles to the same User.","Como uma prática recomendada , não atribua o mesmo conjunto de regras de permissão para diferentes funções. Em vez disso, definir várias funções para o mesmo usuário.", +Assign Condition,Atribuir condição, +Assign To Users,Atribuir aos usuários, +"Assign one by one, in sequence","Atribuir um por um, em seqüência", +Assign to me,Atribuir para mim, +Assign to the one who has the least assignments,Atribuir a quem tem menos atribuições, +Assigned,Atribuído, +Assigned By,Atribuído por, +Assigned By Full Name,Atribuído por Nome completo, +Assigned By Me,Atribuído por Mim, +Assigned To,Atribuído a, +Assigned To/Owner,Atribuído a / Proprietário, +Assignment,Tarefa, +Assignment Complete,Atribuição Concluída, +Assignment Completed,Atribuição Concluída, +Assignment Rule,Regra de Atribuição, +Assignment Rule User,Usuário da regra de atribuição, +Assignment Rules,Regras de Atribuição, +Assignment closed by {0},Atribuição fechado por {0}, +Assignment for {0} {1},Atribuição para {0} {1}, +Atleast one field of Parent Document Type is mandatory,Pelo menos um campo do tipo de documento pai é obrigatório, +Attach,Anexar, +Attach Document Print,Anexar Cópia do Documento, +Attach Image,Anexar Imagem, +Attach Print,Anexar cópia, +Attach Your Picture,Anexe sua Imagem, +Attach file for Import,Anexar arquivo para importação, +Attach files / urls and add in table.,Anexe arquivos / URLs e adicione na tabela., +Attached To DocType,Anexado ao Doctype, +Attached To Field,Relacionado ao campo, +Attached To Name,Anexado Para Nome, +Attachment Limit (MB),Limite de Anexo (MB), +Attachment Removed,Anexo Removido, +Attempting Connection to QZ Tray...,Tentando conexão com a bandeja QZ ..., +Attempting to launch QZ Tray...,Tentativa de lançar o QZ Tray ..., +Auth URL Data,Dados de URL de autenticação, +Authenticating...,Autenticando ..., +Authentication,Autenticação, +Authentication Apps you can use are: ,Os aplicativos de autenticação que você pode usar são:, +Authentication Credentials,Credenciais de Autenticação, +Authorization Code,Código de autorização, +Authorize URL,Autorizar URL, +Authorized,Autorizado, +Auto,Auto, +Auto Email Report,Relatório por Email Automático, +Auto Name,Nome Automático, +Auto Reply Message,Resposta Automática, +Auto assignment failed: {0},Atribuição automática falhou: {0}, +Automatically Assign Documents to Users,Atribuir documentos automaticamente aos usuários, +Automation,Automação, +Avatar,Avatar, +Average,Média, +Average of {0},Média de {0}, +Avoid dates and years that are associated with you.,Evite datas e anos associados a você., +Avoid recent years.,Evite anos recentes., +Avoid sequences like abc or 6543 as they are easy to guess,"Evite sequências como abc ou 6543, pois são fáceis de adivinhar", +Avoid years that are associated with you.,Evite anos associados a você., +Awaiting Password,Aguardando Senha, +Away,Longe, +BCC,BCC, +Back to Desk,De volta à mesa, +Back to Login,Voltar para Login, +Background Color,Cor de Fundo, +Background Email Queue,Fila de Email em Segundo Plano, +Background Jobs,Tarefas em Segundo Plano, +Background Workers,Trabalhadores em Segundo Plano, +Backup,Cópia de segurança, +Backup Frequency,Frequência de Backup, +Backup Limit,Limite de backup, +Backup job is already queued. You will receive an email with the download link,O trabalho de backup já está em fila. Você receberá um e-mail com o link de download, +Backups,Backups, +Banner,Faixa, +Banner HTML,Faixa HTML, +Banner Image,Imagem do Banner, +Banner is above the Top Menu Bar.,A faixa está acima da barra de menu superior., +Bar,Barra, +Base Distinguished Name (DN),Base de dados de nome distinto (DN), +Based on Permissions For User,Com base em permissões para o usuário, +Beta,Beta, +Better add a few more letters or another word,Recomenda-se adicionar mais algumas letras ou colocar uma palavra adicional, +Between,Entre, +Bio,Bio, +Birth Date,Data de nascimento, +Block Module,Módulo Bloco, +Block Modules,Bloquear Módulos, +Blocked,Bloqueado, +Blog,Blog, +Blog Category,Categoria do Blog, +Blog Intro,Introdução do Blog, +Blog Introduction,Introdução do Blog, +Blog Post,Mensagem do Blog, +Blog Settings,Configurações do Blog, +Blog Title,Título do Blog, +Blogger,Blogueiro, +Bot,Bot, +Both DocType and Name required,Ambos DocType e Nome é obrigatório, +Both login and password required,Login e senha necessários, +Bounced,Bounced, +Braintree Settings,Configurações Braintree, +Braintree payment gateway settings,Configurações do gateway de pagamento Braintree, +Brand HTML,Marca HTML, +Brand Image,Imagem da Marca, +Breadcrumbs,Breadcrumbs, +Browser not supported,Navegador não suportado, +Brute Force Security,Segurança da força bruta, +Build Report,Criar relatório, +Bulk Delete,Excluir em massa, +Bulk Edit {0},Edição em Massa {0}, +Bulk Rename,Renomear em Massa, +Bulk Update,Alteração em Massa, +Busy,Ocupado, +Button,Botão, +Button Help,Botão de Ajuda, +Button Label,Etiqueta do botão, +Bypass Two Factor Auth for users who login from restricted IP Address,Bypass Two Factor Auth para usuários que fazem login do endereço IP restrito, +Bypass restricted IP Address check If Two Factor Auth Enabled,Ignorar verificação de endereço IP restrito se dois fatores de autenticação habilitados, +CC,CC, +"CC, BCC & Email Template","CC, BCC e modelo de e-mail", +CSS,CSS, +CSV,CSV, +Cache Cleared,Cache Limpo, +Calculate,Calcular, +Calendar Name,Nome do calendário, +Calendar View,Vista Calendário, +Call,Chamada Telefônica, +Can Read,Pode Ler, +Can Share,Pode Compartilhar, +Can Write,Pode Escrever, +Can't identify open {0}. Try something else.,Não é possível identificar aberto {0}. Tente outra coisa., +Can't save the form as data import is in progress.,Não é possível salvar o formulário à medida que a importação de dados está em andamento., +Cancel {0} documents?,Cancelar {0} documentos?, +Cancelled Document restored as Draft,Documento Cancelado restaurado como Rascunho, +Cancelling,Cancelando, +Cancelling {0},Cancelando {0}, +Cannot Remove,Não é Possível Remover, +Cannot cancel before submitting. See Transition {0},Não pode cancelar antes de enviar., +Cannot change docstatus from 0 to 2,Não é possível alterar docstatus 0-2, +Cannot change docstatus from 1 to 0,Não é possível alterar docstatus 1-0, +Cannot change header content,Não é possível alterar o conteúdo do cabeçalho, +Cannot change state of Cancelled Document. Transition row {0},Não é possível alterar o estado de Documento Cancelado ., +Cannot change user details in demo. Please signup for a new account at https://erpnext.com,Não é possível alterar os detalhes do usuário na demo. Inscreva-se para uma nova conta em https://erpnext.com, +Cannot create a {0} against a child document: {1},Não é possível criar um {0} contra um documento filho: {1}, +Cannot delete Home and Attachments folders,Não é possível excluir pastas Inicial e Anexos, +Cannot delete file as it belongs to {0} {1} for which you do not have permissions,Não é possível excluir o arquivo como ele pertence a {0} {1} para o qual você não possui permissões, +Cannot delete or cancel because {0} {1} is linked with {2} {3} {4},Não é possível excluir ou cancelar porque {0} {1} está vinculado com {2} {3} {4}, +Cannot delete standard field. You can hide it if you want,Não é possível excluir campo padrão. Você pode escondê-lo se você quiser, +Cannot delete {0},Não é possível excluir {0}, +Cannot delete {0} as it has child nodes,"Não é possível excluir {0} , pois tem nós filhos", +"Cannot edit Standard Notification. To edit, please disable this and duplicate it","Não é possível editar a notificação padrão. Para editar, desative e duplique", +Cannot edit a standard report. Please duplicate and create a new report,"Não é possível editar um relatório padrão. Por favor, duplique e crie um novo relatório", +Cannot edit cancelled document,Não é possível editar documento cancelado, +Cannot edit standard fields,Não é possível editar campos padrão, +Cannot have multiple printers mapped to a single print format.,Não é possível ter várias impressoras mapeadas para um único formato de impressão., +Cannot link cancelled document: {0},Não é possível vincular documento cancelado: {0}, +Cannot map because following condition fails: ,Não é possível mapear porque seguinte condição de falha:, +Cannot move row,Não é possível mover a linha, +Cannot open instance when its {0} is open,"Não é possível abrir instância , quando o seu {0} é aberto", +Cannot open {0} when its instance is open,Não é possível abrir {0} quando sua instância está aberta, +Cannot remove ID field,Não é possível remover o campo ID, +Cannot set Notification on Document Type {0},Não é possível definir a notificação no tipo de documento {0}, +Cannot update {0},Não é possível atualizar {0}, +Cannot use sub-query in order by,"não pode usar sub-consulta, a fim de", +Cannot {0} {1},Não é possível {0} {1}, +Capitalization doesn't help very much.,"A senha não é boa o suficiente, mas será aceita.", +Card Details,Detalhes do cartão, +Categorize blog posts.,Categorizar posts., +Category Description,Descrição da Categoria, +Cent,Centavo, +"Certain documents, like an Invoice, should not be changed once final. The final state for such documents is called Submitted. You can restrict which roles can Submit.","Alguns documentos , como uma fatura , não deve ser trocada uma vez final. O estado final de tais documentos é chamado Enviado. Você pode restringir quais funções pode se submeter.", +Chain Integrity,Integridade da Corrente, +Chaining Hash,Chain Hash, +Change Label (via Custom Translation),Alterar etiqueta (via tradução personalizada), +Change Password,Alterar Senha, +"Change field properties (hide, readonly, permission etc.)","Alterar as propriedades do campo (esconder , readonly , permissão etc )", +Channel,Canal, +Chart Name,Nome do gráfico, +Chart Options,Opções de gráfico, +Chart Source,Fonte do gráfico, +Chart Type,Tipo de gráfico, +Charts,Gráficos, +Chat,Chat, +Chat Background,Fundo de bate-papo, +Chat Message,Mensagem de bate-papo, +Chat Operators,Operadores de bate-papo, +Chat Profile,Perfil do bate-papo, +Chat Profile for User {0} exists.,Perfil de bate-papo para o usuário {0} existe., +Chat Room,Sala de bate-papo, +Chat Room Name,Nome da sala de bate-papo, +Chat Room User,Usuário da sala de bate-papo, +Chat Token,Token de bate-papo, +Chat Type,Tipo de bate-papo, +Chat messages and other notifications.,Mensagens do chat e outras notificações., +Check,Verifica, +Check Request URL,URL de solicitação de verificação, +"Check columns to select, drag to set order.","Verifique colunas para selecionar, arrastar para definir a ordem.", +Check this if you are testing your payment using the Sandbox API,Marque esta opção se você estiver testando o seu pagamento usando o API Sandbox, +Check this to pull emails from your mailbox,Marque para baixar os emails da sua caixa de emails, +Check which Documents are readable by a User,Confira quais os documentos são lidos por um Usuário, +Checking one moment,"Checando,nto", +Checksum Version,Versão Checksum, +Child Table Mapping,Mapeamento de tabela infantil, +Child Tables are shown as a Grid in other DocTypes,Tabelas secundárias são mostradas como uma grade em outros DocTypes, +Choose authentication method to be used by all users,Escolha o método de autenticação a ser usado por todos os usuários, +Clear Error Logs,Limpar Logs de Erro, +Clear User Permissions,Limpar permissões do usuário, +Clear all roles,Desmarque todas as funções, +"Clearing end date, as it cannot be in the past for published pages.","Apagar data de término, como não pode ser no passado para páginas publicadas.", +Click here to post bugs and suggestions,Clique aqui para enviar erros e sugestões, +Click here to verify,Clique aqui para verificar, +Click on the link below to complete your registration and set a new password,Clique no link abaixo para completar o seu registo e definir uma nova senha, +Click on the link below to download your data,Clique no link abaixo para baixar seus dados, +Click on the link below to verify your request,Clique no link abaixo para verificar sua solicitação, +Click table to edit,Clique na tabela para editar, +Click to Set Filters,Clique para definir filtros, +Clicked,Clicado, +Client Credentials,Credenciais no cliente, +Client Information,Informação ao cliente, +Client Script,Script de Cliente, +Client URLs,URLs do Cliente, +Client side script extensions in Javascript,Extensões de script do lado do cliente em Javascript, +Collapsible,Desmontável, +Collapsible Depends On,Depende dobrável, +Column,Coluna, +Column {0} already exist.,Coluna {0} já existe., +Column Break,Quebra de coluna, +Column Labels:,Rótulos de coluna:, +Column Name,Nome da coluna, +Column Name cannot be empty,Nome da coluna não pode estar em branco, +Columns,Colunas, +Columns based on,Colunas baseadas em, +Combination of Grant Type ({0}) and Response Type ({1}) not allowed,Combinação de Tipo de Subsídio ( {0} ) e Tipo de Resposta ( {1} ) não permitido, +Comment By,Comentário por, +Comment Email,Comentário Email, +Comment Type,Tipo de Comentário, +Comment can only be edited by the owner,O comentário só pode ser editado pelo proprietário, +Commented on {0}: {1},Comentou sobre {0}: {1}, +Comments and Communications will be associated with this linked document,Comentários e comunicações serão associados com este documento relacionado, +Comments cannot have links or email addresses,Comentários não podem ter links ou endereços de e-mail, +Common names and surnames are easy to guess.,Os nomes comuns e sobrenomes são fáceis de adivinhar., +Communicated via {0} on {1}: {2},Comunicada via {0} em {1}: {2}, +Communication Type,Tipo de comunicação, +Company History,Histórico da Empresa, +Company Introduction,Introdução da Empresa, +Compiled Successfully,Compilado com sucesso, +Complete By,Finalizar até, +Complete Registration,Registro Completo, +Complete Setup,Instalação Concluída, +Completed By,Completado por, +Compose Email,Escrever um email, +Condition Detail,Detalhe da condição, +Conditions,Condições, +Configure Chart,Configurar Gráfico, +Configure Charts,Configurar Gráficos, +Confirm,Confirmar, +Confirm Deletion of Data,Confirme a exclusão de dados, +Confirm Request,Confirmar pedido, +Confirm Your Email,Confirme seu Email, +Confirmed,Confirmado, +Connected to QZ Tray!,Conectado ao QZ Tray!, +Connection Name,Nome da Conexão, +Connection Success,Sucesso de conexão, +Connection lost. Some features might not work.,Conexão perdida. Alguns recursos podem não funcionar., +Connector Name,Nome do conector, +Connector Type,Tipo de conector, +Contact Us Settings,Configurações do Fale Conosco, +"Contact options, like ""Sales Query, Support Query"" etc each on a new line or separated by commas.","Opções de contato, como ""Perguntas sobre Vendas, Perguntas de suporte"", etc cada uma em uma nova linha ou separadas por vírgulas.", +Contacts,Contatos, +Content (HTML),Conteúdo (HTML), +Content (Markdown),Conteúdo (Markdown), +Content Hash,Hash do conteúdo, +Content web page.,Conteúdo da Página Web, +Conversation Tones,Tons de conversação, +Copyright,Direitos autorais, +Core,Núcleo, +Core DocTypes cannot be customized.,DocTypes principais não podem ser personalizados., +Could not connect to outgoing email server,Não foi possível conectar ao servidor de envio emails, +Could not find {0},Não foi possível encontrar {0}, +Could not find {0} in {1},Não foi possível localizar {0} em {1}, +Could not identify {0},Não foi possível identificar {0}, +Count,Contagem, +Country Name,Nome do País, +County,Município, +Create Chart,Criar gráfico, +Create New,Criar Novo, +Create Post,Criar postagem, +Create User Email,Criar e-mail de usuário, +Create a New Format,Criar um novo formato, +Create a new record,Crie um novo registro, +Create a new {0},Criar um(a) novo(a) {0}, +Create and Send Newsletters,Criar e enviar email marketing, +Create and manage newsletter,Crie e gerencie o boletim informativo, +Created,Criado, +Created Custom Field {0} in {1},Criado campo personalizado {0} em {1}, +Created On,Criado em, +Criticism,Crítica, +Criticize,Criticar, +Ctrl + Down,Ctrl + Seta para baixo, +Ctrl + Up,Ctrl + Seta para cima, +Ctrl+Enter to add comment,Ctrl+Enter para adicionar comentário, +Currency Name,Nome da Moeda, +Currency Precision,Precisão de moeda, +Current Mapping,Mapeamento atual, +Current Mapping Action,Ação de Mapeamento atual, +Current Mapping Delete Start,Mapeamento atual Excluir Início, +Current Mapping Start,Início do mapeamento atual, +Current Mapping Type,Tipo de mapeamento atual, +Currently Viewing,Atualmente Exibindo, +Currently updating {0},Atualmente atualizando {0}, +Custom,Personalizado, +Custom Base URL,URL Base Base, +Custom CSS,CSS Personalizado, +Custom DocPerm,DocPerm personalizado, +Custom Field,Campo Personalizado, +Custom Fields can only be added to a standard DocType.,Campos personalizados só podem ser adicionados a um DocType padrão., +Custom Fields cannot be added to core DocTypes.,Campos personalizados não podem ser adicionados aos principais DocTypes., +Custom Format,Formato Personalizado, +Custom HTML Help,Ajuda HTML Personalizado, +Custom JS,JS personalizado, +Custom Menu Items,Itens de Menu Personalizado, +Custom Report,Relatório Personalizado, +Custom Reports,Relatórios Personalizados, +Custom Role,Função Personalizada, +Custom Script,Script Personalizado, +Custom Sidebar Menu,Menu de personalização da barra lateral, +Custom Translations,Traduções Personalizadas, +Customization,Personalização, +Customizations Reset,Redefinição de Personalizações, +Customizations for {0} exported to:
    {1},Personalizações para {0} exportadas para:
    {1}, +Customize Form,Personalizar Formulário, +Customize Form Field,Personalizar Campo de Formulário, +"Customize Label, Print Hide, Default etc.","Personalizar Etiquetas, Cabeçalhos, Padrões, etc.", +Customize...,Personalizar..., +"Customized Formats for Printing, Email","Formatos Personalizados para Impressão, Email", +Customized HTML Templates for printing transactions.,Modelos HTML customizados para transações de impressão., +Cut,Cortar, +DESC,DESC, +Daily Event Digest is sent for Calendar Events where reminders are set.,O resumo de eventos diário é enviado para o Calendário de eventos onde os lembretes são definidos., +Danger,Perigo, +Dark Color,Cor Escura, +Dashboard Chart,Gráfico de Dashboard, +Dashboard Chart Link,Link do Gráfico de Dashboard, +Dashboard Chart Source,Origem do Gráfico de Dashboard, +Dashboard Name,Nome do Dashboard, +Dashboards,Dashboards, +Data,Dados, +Data Export,Exportação de Dados, +Data Import,Importação de dados, +Data Import Template,Modelo de Importação de Dados, +Data Migration,Migração de Dados, +Data Migration Connector,Conector de Migração de Dados, +Data Migration Mapping,Mapeamento de Migração de Dados, +Data Migration Mapping Detail,Detalhes do Mapeamento de Migração de Dados, +Data Migration Plan,Plano de Migração de Dados, +Data Migration Plan Mapping,Mapeamento do Plano de Migração de Dados, +Data Migration Run,Execução de Migração de Dados, +Data missing in table,Falta de dados na tabela, +Database Engine,Engine do Banco de Dados, +Database Name,Nome do Banco de Dados, +Date and Number Format,Data e Formato de número, +Date {0} must be in format: {1},A data {0} deve estar no formato: {1}, +Dates are often easy to guess.,Datas são frequentemente fáceis de adivinhar., +Day of Week,Dia da Semana, +Days After,Dias Após, +Days Before,Dias Antes, +Days Before or After,Dias Antes ou Após, +"Dear System Manager,","Caro Administrador do Sistema,", +"Dear User,","Querido usuário,", +Dear {0},Caro {0}, +Default Address Template cannot be deleted,Template endereço padrão não pode ser excluído, +Default Inbox,Caixa de Entrada Padrão, +Default Incoming,Padrão de Entrada, +Default Outgoing,Outgoing Padrão, +Default Print Format,Formato de impressão padrão, +Default Print Language,Idioma de impressão padrão, +Default Redirect URI,Padrão de redirecionamento URI, +Default Role at Time of Signup,Função padrão no momento da inscrição, +Default Sending,Padrão Envio, +Default Sending and Inbox,Padrão para Envio e Recebimento, +Default Sort Field,Campo de classificação padrão, +Default Sort Order,Ordem de classificação padrão, +Default Value,Valor padrão, +Default: "Contact Us",Padrão: "Fale Conosco", +DefaultValue,Valor padrão, +Define workflows for forms.,Defina fluxos de trabalho para formulários., +Defines actions on states and the next step and allowed roles.,"Define ações em status, o próximo passo e as funções com permissão.", +Defines workflow states and rules for a document.,Define o status de fluxo de trabalho e regras para um documento., +Delayed,Atrasado, +Delete Data,Excluir dados, +Delete comment?,Excluir comentário?, +Delete this record to allow sending to this email address,Excluir este registro para permitir o envio para esse endereço de email, +Delete {0} items permanently?,Excluir {0} itens permanentemente?, +Deleted,Excluído(a), +Deleted DocType,DocType Excluído, +Deleted Document,Documento Excluído, +Deleted Documents,Documentos excluídos, +Deleted Name,Nome Excluído, +Deleting {0},Excluindo {0}, +Depends On,Depende de, +Descendants Of,Descendentes De, +Desk,Mesa, +Desk Access,Acesso ao Ambiente de Trabalho, +Desktop Icon,Ícone da área de trabalho, +Desktop Icon already exists,Ícone da área de trabalho já existe, +Developer,Desenvolvedor, +Did not add,Não adicionado, +Did not cancel,Não cancelou, +Did not find {0} for {0} ({1}),Não encontrou {0} para {0} ( {1}), +Did not remove,Não removido, +"Different ""States"" this document can exist in. Like ""Open"", ""Pending Approval"" etc.","""Status"" diferentes em que esse documento pode existir. Como ""Aberto"", ""Aprovação Pendente"", etc", +Direct,Direto, +Direct room with {0} already exists.,Sala direta com {0} já existe., +Disable Auto Refresh,Desativar atualização automática, +Disable Count,Desativar Contagem, +Disable Customer Signup link in Login page,Desativar Link de Inscrição na Página de Login, +Disable Prepared Report,Desativar relatório preparado, +Disable Report,Desativar Relatório, +Disable SMTP server authentication,Desativar autenticação do servidor SMTP, +Disable Sidebar Stats,Desativar Estatísticas da Barra Lateral, +Disable Signup,Desativar Registre-se, +Disable Standard Email Footer,Desativar Rodapé Padrão do Email, +Discard,Descartar, +Display,exibição, +Display Depends On,Visualização depende, +Do not allow user to change after set the first time,Não permitir que o usuário altere após definir o primeiro tempo, +Do not edit headers which are preset in the template,Não edite cabeçalhos que estejam predefinidos no modelo, +Do not send Emails,Não envie e-mails, +Doc Event,Evento de Doc, +Doc Events,Doc Eventos, +Doc Status,Status do Documento, +DocField,DocField, +DocPerm,DocPerm, +DocShare,DocShare, +DocType {0} provided for the field {1} must have atleast one Link field,O DocType {0} fornecido para o campo {1} deve ter pelo menos um campo Link, +DocType can not be merged,DocType não podem ser mescladas, +DocType can only be renamed by Administrator,DocType só pode ser renomeado pelo Administrador, +DocType is a Table / Form in the application.,DocType é uma Tabela / Form na aplicação., +DocType must be Submittable for the selected Doc Event,DocType deve ser enviado para o Evento de Doc selecionado, +DocType on which this Workflow is applicable.,DocType em que este fluxo de trabalho é aplicável., +"DocType's name should start with a letter and it can only consist of letters, numbers, spaces and underscores","O nome de DocType deve começar com uma letra e só pode consistir de letras, números, espaços e sublinhados", +Doctype required,Doctype obrigatório, +Document,Documento, +Document Follow,Rastrear Documento, +Document Follow Notification,Notificação de Rastreamento do Documento, +Document Queued,Documento em Fila de Espera, +Document Restored,Documento Restaurado, +Document Share Report,Relatório de Documentos Compartilhados, +Document States,Documento Unidos, +Document Type is not importable,Tipo de documento não é importável, +Document Type is not submittable,O tipo de documento não é submittable, +Document Type to Track,Tipo de Documento a Seguir, +Document Types,Tipos de documento, +Document can't saved.,O documento não pode ser salvo., +Document {0} has been set to state {1} by {2},O documento {0} foi definido para declarar {1} por {2}, +Documents,Documentos, +Documents assigned to you and by you.,Documentos atribuídos a você e por você., +Domain Settings,Configurações de Domínio, +Domains HTML,Domínios HTML, +"Don't HTML Encode HTML tags like <script> or just characters like < or >, as they could be intentionally used in this field","Não etiquetas HTML Encode HTML como <script> ou apenas caracteres como <ou>, uma vez que poderia ser usado intencionalmente neste campo", +Don't Override Status,Não Sobrescrever o Status, +Don't create new records,Não crie novos registros, +Don't have an account? Sign up,Não tem uma conta? Se inscreva, +"Don't know, ask 'help'","Não sei, peça 'ajuda'", +Download Data,Download de dados, +Download Files Backup,Download de backup de arquivos, +Download Link,Baixar link, +Download Report,Relatório de download, +Download Your Data,Baixe seus dados, +Download link for your backup will be emailed on the following email address: {0},Link de download para o seu backup será enviado por email no seguinte endereço de email: {0}, +Download with Data,Download com dados, +Drag and Drop tool to build and customize Print Formats.,Ferramenta de segure e arraste para construir e personalizar formatos de impressão., +Drag elements from the sidebar to add. Drag them back to trash.,Arraste os elementos da barra lateral para adicionálos. Arraste-os de volta para eliminar., +Dropbox Access Key,Dropbox Chave de Acesso, +Dropbox Access Secret,Segredo de Acesso Dropbox, +Dropbox Access Token,Token de acesso Dropbox, +Dropbox Settings,Configurações Dropbox, +Dropbox Setup,Configuração do Dropbox, +Dropbox access is approved!,O acesso ao Dropbox está aprovado!, +Dropbox backup settings,configurações de cópias de segurança para o Dropbox, +Duplicate Filter Name,Nome do filtro duplicado, +Dynamic Link,Link dinâmico, +Dynamic Report Filters,Filtros dinâmicos de relatórios, +ESC,ESC, +Edit Auto Email Report Settings,Editar configurações de relatório automático de e-mail, +Edit Custom HTML,Editar HTML Personalizado, +Edit DocType,Editar DocType, +Edit Filter,Editar Filtro, +Edit Format,Editar Formato, +Edit HTML,Editar HTML, +Edit Heading,Editar Cabeçalho, +Edit Properties,Editar Propriedades, +Edit to add content,Edite para adicionar conteúdo, +Edit {0},Edite {0}, +Editable Grid,Grid Editável, +Editing Row,Editando Linha, +Eg. smsgateway.com/api/send_sms.cgi,Por exemplo: smsgateway.com / api / send_sms.cgi, +Email Account Name,Nome da Conta de Email, +Email Account added multiple times,Conta de email adicionada várias vezes, +Email Addresses,Endereço de Email, +Email Domain,Domínio de Email, +"Email Domain not configured for this account, Create one?","Domínio de email não configurado para esta conta,. Criar um?", +Email Flag Queue,Flag Fila de Email, +Email Footer Address,Endereço no Rodapé do Email, +Email Group,Grupo de Email, +Email Group List,Lista do Grupo de Emails, +Email Group Member,Membro do Grupo de Emails, +Email Login ID,ID de login do e-mail, +Email Queue,Fila de Emails, +Email Queue Recipient,Email Queue Destinatário, +Email Queue records.,Registros da Fila de Emails., +Email Reply Help,Email Reply Help, +Email Rule,Regra de Email, +Email Server,Servidor de Email, +Email Settings,Configurações de Email, +Email Signature,Assinatura de Email, +Email Status,Satus do Email, +Email Sync Option,Opção Sync Email, +Email Templates for common queries.,Modelos de email para consultas comuns., +Email To,Email Para, +Email Unsubscribe,Cancelar inscrição de email, +Email has been marked as spam,O email foi marcado como spam, +Email has been moved to trash,O email foi movido para o lixo, +Email not sent to {0} (unsubscribed / disabled),Email não foi enviado para {0} (inscrição anulada / desativado), +Email not verified with {0},E-mail não verificado com {0}, +Emails are muted,Emails são silenciados, +Emails will be sent with next possible workflow actions,Os e-mails serão enviados com as próximas ações de fluxo de trabalho possíveis, +Embed image slideshows in website pages.,Incorporar apresentações de imagem em páginas do site., +Enable / Disable Domains,Ativar / Desativar Domínios, +Enable Auto Reply,Ativar resposta automática, +Enable Automatic Backup,Ativar backup automático, +Enable Chat,Ativar conversa, +Enable Comments,Ativação de comentários, +Enable Incoming,Ativar Entrada, +Enable Outgoing,Ativar Saída, +Enable Password Policy,Ativar política de senha, +Enable Print Server,Ativar servidor de impressão, +Enable Raw Printing,Ativar impressão bruta, +Enable Report,Ativar Relatório, +Enable Scheduled Jobs,Ativar Tarefas Agendadas, +Enable Social Login,Ativar Login Social, +Enable Two Factor Auth,Ativar dois fatores Auth, +Enabled email inbox for user {0},Caixa de entrada de e-mail ativada para o usuário {0}, +"Encryption key is invalid, Please check site_config.json","A chave de criptografia é inválida, verifique site_config.json", +End Date Field,Campo de data final, +End Date cannot be before Start Date!,A data de término não pode ser anterior à data de início!, +Endpoint URL,URL do endpoint, +Energy Point Log,Log de ponto de energia, +Energy Point Rule,Regra do ponto de energia, +Energy Point Settings,Configurações de ponto de energia, +Energy Points,Pontos de energia, +Enter Email Recipient(s),Digite email do Destinatário(s), +Enter Form Type,Digite o Tipo de Formulário, +"Enter default value fields (keys) and values. If you add multiple values for a field, the first one will be picked. These defaults are also used to set ""match"" permission rules. To see list of fields, go to ""Customize Form"".","Insira campos de valor padrão (teclas) e valores. Se adicionar diversos valores para um campo, será escolhido o primeiro. Estes padrões também são utilizados para definir regras de permissão de ""correspondência. Para ver a lista de campos, vá a ""Personalizar Formulário"".", +Enter folder name,Digite o nome da pasta, +"Enter keys to enable login via Facebook, Google, GitHub.","Enter para ativar o login via Facebook , Google, GitHub .", +Enter python module or select connector type,Insira o módulo python ou selecione o tipo de conector, +"Enter static url parameters here (Eg. sender=ERPNext, username=ERPNext, password=1234 etc.)","Digite os parâmetros da URL estática aqui (por exemplo remetente=ERPNext, usuario=ERPNext, senha=1234, etc)", +Enter url parameter for message,Digite o parâmetro da url para mensagem, +Enter url parameter for receiver nos,Digite o parâmetro da url para os números de receptores, +Enter your password,Digite sua senha, +Entity Name,Nome da entidade, +Equals,Igual, +Error Message,Mensagem de erro, +Error Report,Reportar erro, +Error Snapshot,Snapshot de Erro, +Error in Custom Script,Erro no script personalizado, +Error in Notification,Erro na notificação, +Error in Notification: {},Erro na notificação: {}, +Error while connecting to email account {0},Erro ao conectar-se à conta de e-mail {0}, +Error while evaluating Notification {0}. Please fix your template.,Erro ao avaliar a notificação {0}. Por favor corrija seu modelo., +Error: Document has been modified after you have opened it,Erro: O documento foi modificado depois de aberto, +Error: Value missing for {0}: {1},Erro: Falta valor para {0}: {1}, +Errors in Background Events,Erros em Eventos em Segundo Plano, +Event Category,Categoria do Evento, +Event Participants,Participantes do Evento, +Event Type,Tipo de Evento, +Event and other calendars.,Evento e outros calendários., +Events in Today's Calendar,Eventos no calendário de hoje, +Everyone,Todos, +Example,Exemplo, +Example Email Address,Exemplo de Endereço de Email, +Example: {{ subject }},Exemplo: {{subject}}, +Excel,Excel, +Exception,Exceção, +Exception Type,Tipo de exceção, +Execution Time: {0} sec,Tempo de Execução: {0} seg, +Expert,Especialista, +Expiration time,Data de validade, +Expire Notification On,Expiram Notificação Lig, +Expires In,Expira em, +Expiry time of QR Code Image Page,Tempo de expiração da página de imagem de código QR, +Export All {0} rows?,Exportar todas as linhas {0}?, +Export Custom Permissions,Exportar Permissões Personalizadas, +Export Customizations,Exportar Personalizações, +Export Data,Exportar dados, +Export Data in CSV / Excel format.,Exportar dados no formato CSV / Excel., +Export Report: {0},Relatório de exportação: {0}, +Expose Recipients,Mostrar Destinatários, +"Expression, Optional","Expressão, Opcional", +Facebook,Facebook, +Failed to complete setup,Falha ao concluir a configuração, +Failed to connect to server,Falha ao conectar-se ao servidor, +Failed while amending subscription,Falha ao alterar a assinatura, +FavIcon,FavIcon, +Feedback Request,Solicitação de Feedback, +Fetch From,Buscar de, +Fetch If Empty,Buscar se Vazio, +Fetch Images,Buscar imagens, +Fetch attached images from document,Buscar imagens anexadas do documento, +Field "route" is mandatory for Web Views,O campo "rota" é obrigatório para Web Views, +Field "value" is mandatory. Please specify value to be updated,"O campo ""valor"" é obrigatório. Por favor, especifique o valor a ser atualizado", +Field Description,Descrição do Campo, +Field Maps,Mapas de campo, +Field Type,Tipo de Campo, +"Field that represents the Workflow State of the transaction (if field is not present, a new hidden Custom Field will be created)","Campo que representa o status da transação no fluxo de trabalho (se o campo não estiver presente, um novo campo oculto personalizado será criado)", +Field to Track,Campo para rastrear, +Field type cannot be changed for {0},O tipo de campo não pode ser alterado para {0}, +Field {0} not found.,Campo {0} não encontrado., +Fieldname is limited to 64 characters ({0}),Fieldname é limitado a 64 caracteres ({0}), +Fieldname not set for Custom Field,Fieldname não definida para campo personalizado, +Fieldname which will be the DocType for this link field.,Nome do campo que será o DocType para este campo link., +Fieldname {0} cannot have special characters like {1},Fieldname {0} não pode ter caracteres especiais como {1}, +Fieldname {0} conflicting with meta object,Nome do campo {0} em conflito com meta-objeto, +Fields Multicheck,Campos Multicheck, +"Fields separated by comma (,) will be included in the ""Search By"" list of Search dialog box","Campos separados por vírgula (,) será incluído no "Pesquisar por" lista de caixa de diálogo Pesquisar", +Fieldtype,Tipo de Campo, +Fieldtype cannot be changed from {0} to {1} in row {2},FieldType não pode ser alterado a partir de {0} a {1} em linha {2}, +File '{0}' not found,Arquivo '{0}' não encontrado, +File Backup,Backup de arquivos, +File Name,Nome do arquivo, +File Size,Tamanho do arquivo, +File Type,Tipo de arquivo, +File URL,URL do arquivo, +File Upload,Upload de arquivos, +File Upload Disconnected. Please try again.,"Carregamento de arquivos desconectado. Por favor, tente novamente.", +File Upload in Progress. Please try again in a few moments.,"Carregamento de arquivos em andamento. Por favor, tente novamente em alguns instantes.", +File backup is ready,O backup do arquivo está pronto, +File not attached,Arquivo não anexado, +File size exceeded the maximum allowed size of {0} MB,O tamanho do arquivo excedeu o tamanho máximo permitido de {0} MB, +File too big,Arquivo muito grande, +File {0} does not exist,Arquivo {0} não existe, +Files,Arquivos, +Filter,Filtro, +Filter Data,Filtrar dados, +Filter List,Lista de filtros, +Filter Meta,Filtrar Meta, +Filter Name,Nome do filtro, +Filter Values,Valores de filtro, +Filter must be a tuple or list (in a list),O filtro deve ser uma tupla ou lista (em uma lista), +"Filter must have 4 values (doctype, fieldname, operator, value): {0}","O filtro deve ter 4 valores (doctype, fieldname, operador, valor): {0}", +Filter...,Filtre..., +Filtered by "{0}",Filtrados por "{0}", +Filters Display,Exibição dos Filtros, +Filters JSON,Filtros JSON, +Filters saved,Filtros salvos, +Find {0} in {1},Localizar {0} em {1}, +First Level,Primeiro nível, +First Success Message,Primeira mensagem de sucesso, +First Transaction,Primeira Transação, +First data column must be blank.,Primeira coluna de dados deve estar em branco., +First set the name and save the record.,"Primeiro, defina o nome e salve o registro.", +Flag,Bandeira, +Float,Float, +Float Precision,Precisão de Casas Decimais, +Fold,Dobrar, +Fold can not be at the end of the form,Fold não pode ser no final da forma, +Fold must come before a Section Break,Dobre deve vir antes de uma quebra de secção, +Folder,Pasta, +Folder name should not include '/' (slash),O nome da pasta não deve incluir '/' (slash), +Folder {0} is not empty,Pasta {0} não está vazio, +Follow,Segue, +Followed by,Seguido por, +Following fields are missing:,Seguintes campos estão faltando:, +Following fields have missing values:,Os campos a seguir estão em branco:, +Font,fonte, +Font Size,Tamanho da Fonte, +Fonts,Fontes, +Footer,Rodapé, +Footer HTML,HTML de rodapé, +Footer Items,Itens do Rodapé, +Footer will display correctly only in PDF,Rodapé será exibido corretamente somente em PDF, +For Document Type,Para o tipo de documento, +"For Links, enter the DocType as range.\nFor Select, enter list of Options, each on a new line.","Para os Links, insira o DocType como intervalo. Para Selecionar, insira-os na lista de Opções, cada um numa nova linha.", +For User,Para o Usuário, +For Value,Por valor, +"For currency {0}, the minimum transaction amount should be {1}","Para a moeda {0}, o valor mínimo da transação deve ser {1}", +For example if you cancel and amend INV004 it will become a new document INV004-1. This helps you to keep track of each amendment.,"Por exemplo, se você cancelar e corrigir o INV004, ele vai se tornar um novo documento chamado INV004-1. Isso ajuda você a manter o controle de cada alteração.", +"For example: If you want to include the document ID, use {0}","Por exemplo: Se você quiser incluir a ID do documento, use {0}", +"For updating, you can update only selective columns.","Para a atualização, você pode atualizar colunas só seletivos.", +For {0} at level {1} in {2} in row {3},Por {0} a nível {1} em {2} na linha {3}, +Force,Força, +Force Show,Forçar Exibição, +Forgot Password,Esqueci a Senha, +Forgot Password?,Esqueceu a senha?, +Form Customization,Personalização de Formulário, +Form Settings,Configurações de formulário, +Format,Formato, +Format Data,Formato de dados, +Forward To Email Address,Encaminhar para Email, +Fraction,Fração, +Fraction Units,Unidades Fracionadas, +Frames,Frames, +Frappe,Frappe, +Frappe Framework,Frappe Framework, +Friendly Title,Título Amigável, +From Date Field,Do campo de data, +From Document Type,Do tipo de documento, +From Full Name,De nome completo, +Full Page,Página completa, +Fw: {0},Fw: {0}, +GCalendar Sync ID,ID de sincronização do GCalendar, +GMail,Gmail, +Gantt,Gantt, +Gateway,Porta de entrada, +Gateway Controller,Gateway Controller, +Gateway Settings,Configurações do Gateway, +Generate Keys,Gerar Chaves, +Generate New Report,Gerar novo relatório, +Generated File,Arquivo gerado, +Geo,Geo, +Geolocation,Geolocalização, +Get Alerts for Today,Obter Alertas para Hoje, +Get Contacts,Obter contatos, +Get Fields,Obter campos, +Get your globally recognized avatar from Gravatar.com,Obtenha seu avatar globalmente reconhecido de Gravatar.com, +GitHub,GitHub, +Give Review Points,Dê pontos de revisão, +Global Unsubscribe,Cancelar Inscrição Global, +Go to the document,Vá para o documento, +Go to this URL after completing the form (only for Guest users),Vá para este URL depois de preencher o formulário (apenas para usuários convidados), +Go to {0},Vá para {0}, +Go to {0} List,Ir para a {0} lista, +Go to {0} Page,Ir para {0} Página, +Google,Google, +Google Analytics ID,ID do Google Analytics, +Google Calendar ID,ID da Agenda do Google, +Google Font,Google Font, +Google Services,Google Services, +Grant Type,Tipo Grant, +Group Name,Nome do grupo, +Group name cannot be empty.,O nome do grupo não pode estar vazio., +Groups of DocTypes,Grupos de DocTypes, +HTML,HTML, +HTML Editor,Editor de HTML, +"HTML Header, Robots and Redirects","Cabeçalho HTML, Robôs e Redirecionamentos", +HTML for header section. Optional,HTML para a seção de cabeçalho. opcional, +Half,Metade, +Has Attachment,possui anexo, +Has Attachments,Tem anexos, +Has Domain,Tem domínio, +Has Role,Tem Função, +Has Web View,Tem Web View, +Have an account? Login,Possui cadastro? Entre, +Header,Cabeçalho, +Header HTML,HTML de cabeçalho, +Header HTML set from attachment {0},Conjunto HTML de cabeçalho do anexo {0}, +Header Image,Imagem de cabeçalho, +Headers,Cabeçalhos, +Heading,Título, +Hello {0},Olá {0}, +Hello!,Olá!, +Help Articles,Artigo de Ajuda, +Help Category,Categoria de Ajuda, +Help on Search,Ajuda na Pesquisa, +"Help: To link to another record in the system, use ""#Form/Note/[Note Name]"" as the Link URL. (don't use ""http://"")","Ajuda: Para vincular a outro registro no sistema, use "# Form / Nota / [Nota Name]" como a ligação URL. (Não use "http://")", +Helvetica,Helvetica, +Hi {0},Oi {0}, +Hide Copy,Ocultar Cópia, +Hide Footer Signup,Esconder Link de Inscrição do Rodapé, +Hide Sidebar and Menu,Ocultar barra lateral e menu, +Hide Standard Menu,Esconder Menu Padrão, +Hide Weekends,Ocultar finais de semana, +Hide details,Ocultar Detalhes, +Hide footer in auto email reports,Ocultar o rodapé nos relatórios de e-mail automático, +Higher priority rule will be applied first,Regra de prioridade mais alta será aplicada primeiro, +Highlight,Realçar, +"Hint: Include symbols, numbers and capital letters in the password","Dica: Inclua símbolos, números e letras maiúsculas na senha", +Home Page,Pagina inicial, +Home Settings,Configurações iniciais, +Home/Test Folder 1,Início / Teste pasta 1, +Home/Test Folder 1/Test Folder 3,Pasta Principal / Teste 1 / Teste Pasta 3, +Home/Test Folder 2,Início / Teste pasta 2, +Host,Host, +Hostname,Nome do Host, +"How should this currency be formatted? If not set, will use system defaults","Como essa moeda deve ser formatada? Se não for definido, serão usados os padrões do sistema", +I found these: ,Eu encontrei estes:, +ID,ID, +ID (name) of the entity whose property is to be set,ID (nome) da entidade cuja propriedade é para ser definida, +Icon will appear on the button,O ícone aparecerá no botão, +Identity Details,Detalhes da identidade, +Idx,Idx, +"If Apply Strict User Permission is checked and User Permission is defined for a DocType for a User, then all the documents where value of the link is blank, will not be shown to that User","Se a opção Aplicar permissão de usuário estrito estiver marcada e a permissão de usuário for definida para um DocType para um usuário, todos os documentos onde o valor do link estiver em branco não serão exibidos para esse usuário", +If Checked workflow status will not override status in list view,Uma vez selecionado o status do fluxo de trabalho não sobrescreverá o status do documentos na visualização da lista, +If Owner,Se proprietário, +"If a Role does not have access at Level 0, then higher levels are meaningless.","Se uma função não tem acesso no nível 0, então os níveis mais altos são irrelevantes.", +"If checked, all other workflows become inactive.","Se marcada, todos os outros fluxos de trabalho tornam-se inativos.", +"If checked, this field will be not overwritten based on Fetch From if a value already exists.","Se marcado, este campo não será sobrescrito com base em Buscar de se um valor já existir.", +"If checked, users will not see the Confirm Access dialog.","Se selecionada, s usuáários não verão a janela Confirmar Accesso.", +"If disabled, this role will be removed from all users.",Se esta função for desativada será removida em todos os usuários., +"If enabled, user can login from any IP Address using Two Factor Auth, this can also be set for all users in System Settings","Se ativado, o usuário pode efetuar login a partir de qualquer endereço IP usando a autenticação de dois fatores, isso também pode ser definido para todos os usuários nas configurações do sistema", +"If enabled, all users can login from any IP Address using Two Factor Auth. This can also be set only for specific user(s) in User Page","Se ativado, todos os usuários podem efetuar login a partir de qualquer endereço IP usando a autenticação de dois fatores. Isso também pode ser definido apenas para usuários específicos na página do usuário", +"If enabled, changes to the document are tracked and shown in timeline","Se ativado, as alterações no documento são rastreadas e mostradas na linha do tempo", +"If enabled, document views are tracked, this can happen multiple times","Se ativado, as visualizações de documentos são rastreadas, isso pode acontecer várias vezes", +"If enabled, the document is marked as seen, the first time a user opens it","Se ativado, o documento é marcado como visto, a primeira vez que um usuário o abre", +"If enabled, the password strength will be enforced based on the Minimum Password Score value. A value of 2 being medium strong and 4 being very strong.","Se ativado, a força da senha será aplicada com base no valor Minimum Password Score. Um valor de 2 sendo médio forte e 4 sendo muito forte.", +"If enabled, users who login from Restricted IP Address, won't be prompted for Two Factor Auth","Se ativado, os usuários que fizerem login a partir do Endereço IP restrito não serão solicitados para autenticação de dois fatores", +"If enabled, users will be notified every time they login. If not enabled, users will only be notified once.","Se ativado, os usuários serão notificados sempre que iniciarem sessão. Se não estiver ativado, os usuários só serão notificados uma vez.", +If non standard port (e.g. 587),"Se não for a porta padrão (por exemplo, 587)", +"If non standard port (e.g. 587). If on Google Cloud, try port 2525.","Se não porta padrão (por exemplo, 587). Se no Google Cloud, tente a porta 2525.", +"If not set, the currency precision will depend on number format","Se não for definido, a precisão da moeda dependerá do formato de número", +If the condition is satisfied user will be rewarded with the points. eg. doc.status == 'Closed'\n,"Se a condição for satisfeita, o usuário será recompensado com os pontos. por exemplo. doc.status == 'Closed'", +"If the user has any role checked, then the user becomes a ""System User"". ""System User"" has access to the desktop","Se o usuário tiver alguma função selecionada, então o usuário torna-se um ""Usuário do Sistema"". Um ""Usuário do Sistema"" tem acesso à área de trabalho", +"If these instructions where not helpful, please add in your suggestions on GitHub Issues.","Se estas instruções não forem úteis, dê sua sugestão no GitHub.", +"If this is checked, rows with valid data will be imported and invalid rows will be dumped into a new file for you to import later.","Se isso estiver marcado, linhas com dados válidos serão importadas e linhas inválidas serão despejadas em um novo arquivo para você importar mais tarde.", +If user is the owner,Se o usuário é o proprietário, +"If you are updating, please select ""Overwrite"" else existing rows will not be deleted.","Se você estiver atualizando, por favor selecione ""Substituir"" linhas outra existentes não serão excluídos.", +If you are updating/overwriting already created records.,Se você está atualizando / substituindo registros já criados., +"If you are uploading new records, ""Naming Series"" becomes mandatory, if present.","Se você estiver fazendo upload de novos registros, a coluna ""Naming Series"" torna-se obrigatória, se presente.", +"If you are uploading new records, leave the ""name"" (ID) column blank.","Se você estiver fazendo upload de novos registros, deixe a coluna ""name"" (ID) em branco.", +If you don't want to create any new records while updating the older records.,Se você não quer criar novos registros enquanto atualiza os registros mais antigos., +"If you set this, this Item will come in a drop-down under the selected parent.","Se você definir isso, este item virá em um drop-down sob o pai selecionado .", +"If you think this is unauthorized, please change the Administrator password.","Se você acha que isso não é autorizado, por favor mude a senha do administrador.", +"If your data is in HTML, please copy paste the exact HTML code with the tags.","Se os dados estiverem em HTML, por favor, copie e cole o código HTML exato com as tags.", +Ignore User Permissions,Ignorar permissões de usuári, +Ignore XSS Filter,Ignorar Filtro XSS, +Ignore attachments over this size,Ignorar anexos maiores que este tamanho, +Ignore encoding errors,Ignorar erros de codificação, +Ignored: {0} to {1},Ignorados: {0} para {1}, +Illegal Access Token. Please try again,"Ilegal acesso token. Por favor, tente novamente", +Illegal Document Status for {0},Status ilegal do documento para {0}, +Image Field,Campo de Imagem, +Image Link,Link da Imagem, +Image field must be a valid fieldname,Campo de imagem deve ser um nome de campo válido, +Image field must be of type Attach Image,Campo de imagem deve ser do tipo Anexar Imagem, +Images,Imagens, +Implicit,Implícito, +Import,Importar, +Import Email From,Importar Email do, +Import Status,Status da importação, +Import Subscribers,Importar Inscritos, +Import Zip,Importar Zip, +In Filter,No Filtro da Lista, +In Global Search,Na Busca Global, +In Grid View,Na Visualização do Grid, +In Hours,Em horas, +In List View,Mostrar na Visualização da Lista, +In Preview,Na pré-visualização, +In Reply To,Em resposta a, +In Standard Filter,Em Filtro Padrão, +In Valid Request,Pedido inválido, +In points. Default is 9.,Em pontos. O padrão é 9., +In seconds,Em segundos, +Include Search in Top Bar,Incluem a busca no Top Bar, +"Include symbols, numbers and capital letters in the password","Inclua símbolos, números e letras maiúsculas na senha", +Incoming email account not correct,A conta de e-mail recebida não é correta, +Incomplete login details,Detalhes de login incompletos, +Incorrect User or Password,Usuário ou Senha Incorreta, +Incorrect Verification code,Código de verificação incorreto, +Incorrect value in row {0}: {1} must be {2} {3},Valor incorreto na linha {0} : {1} deve ser {2} {3}, +Incorrect value: {0} must be {1} {2},Valor incorreto: {0} deve ser {1} {2}, +Index,Índice, +Indicator,Indicador, +Info,Informações, +Info:,Info:, +Initial Sync Count,Contagem de sincronização inicial, +InnoDB,InnoDB, +Insert Above,Inserir Acima, +Insert After,Inserir Após, +Insert After cannot be set as {0},Depois de inserir não pode ser definido como {0}, +"Insert After field '{0}' mentioned in Custom Field '{1}', with label '{2}', does not exist","O campo Inserir Depois '{0}' mencionado no Campo Personalizado '{1}', com rótulo '{2}', não existe", +Insert Below,Inserir Abaixo, +Insert Column Before {0},Inserir coluna antes de {0}, +Insert Style,Inserir Estilo, +Insert new records,Inserir novos registros, +Instructions Emailed,Instruções Emailed, +Insufficient Permission for {0},Permissão insuficiente para {0}, +Int,Inteiro, +Integration Request,Pedido de Integração, +Integration Request Service,Serviço de Requisição de Integração, +Integration Type,Tipo de Integração, +Integrations,Integrações, +Integrations can use this field to set email delivery status,Integrações pode usar este campo para definir o status de entrega de email, +Internal Server Error,Erro do Servidor Interno, +Internal record of document shares,Registro interno de ações de documentos, +Introduce your company to the website visitor.,Apresente sua empresa para o visitante do site., +Introductory information for the Contact Us Page,Informação introdutória para a página Fale Conosco, +Invalid,Inválido, +Invalid "depends_on" expression,Expressão "dependente" dependente inválida, +Invalid Access Key ID or Secret Access Key.,ID de chave de acesso inválido ou chave de acesso secreto., +Invalid CSV Format,Formato inválido de CSV, +Invalid Home Page,Inválido Página Inicial, +Invalid Link,Fazer a ligação inválido, +Invalid Login Token,Inválido símbolo de logon, +Invalid Login. Try again.,Login inválido. Tente novamente., +Invalid Mail Server. Please rectify and try again.,"Mail Server inválido . Por favor, corrigir e tentar novamente.", +Invalid Outgoing Mail Server or Port,Inválido Outgoing Mail Server ou Porto, +Invalid Output Format,Formato de saída inválido, +Invalid Password,senha inválida, +Invalid Password:,Senha inválida:, +Invalid Request,Requisição Inválida, +Invalid Search Field {0},Campo de pesquisa inválido {0}, +Invalid Subscription,Inscrição inválida, +Invalid Token,Token inválido, +Invalid User Name or Support Password. Please rectify and try again.,"Nome de usuário ou senha inválidos. Por favor, corrigir e tentar novamente.", +Invalid column,Coluna inválida, +Invalid field name {0},Nome do campo inválido {0}, +Invalid fieldname '{0}' in autoname,nome do campo inválido '{0}' em autoname, +Invalid file path: {0},Caminho de arquivo inválido: {0}, +Invalid login or password,Login ou senha inválidos, +Invalid module path,Caminho do módulo inválido, +Invalid naming series (. missing),Série de nomes inválido (. Ausente), +Invalid payment gateway credentials,credenciais de gateway de pagamento inválidos, +Invalid recipient address,Endereço do destinatário inválido, +Invalid {0} condition,Condição inválida {0}, +Inverse,Inverso, +Is,É, +Is Attachments Folder,É Pasta de Anexos, +Is Child Table,É Tabela Filho, +Is Custom Field,É campo personalizado, +Is First Startup,É o primeiro arranque, +Is Folder,É Pasta, +Is Global,É global, +Is Globally Pinned,É fixado globalmente, +Is Home Folder,É Home Folder, +Is Mandatory Field,É campo obrigatório, +Is Pinned,Está preso, +Is Primary Contact,É o contato principal, +Is Private,É privada, +Is Published Field,É Publicado campo, +Is Published Field must be a valid fieldname,É Publicado O campo deve ser um nome do campo válido, +Is Single,É Único, +Is Spam,é Spam, +Is Standard,É Padrão, +Is Submittable,Pode ser Enviado, +Is Table,É Tabela, +Is Your Company Address,É o seu endereço comercial, +It is risky to delete this file: {0}. Please contact your System Manager.,É arriscado excluir este arquivo: {0}. Entre em contato com o administrador do sistema., +Item cannot be added to its own descendents,O artigo não pode ser acrescentado para os seus próprios descendentes, +JS,JS, +JSON,JSON, +JavaScript Format: frappe.query_reports['REPORTNAME'] = {},Formato JavaScript: frappe.query_reports [' REPORTNAME '] = {}, +Javascript to append to the head section of the page.,Javascript para acrescentar ao cabeçalho da página., +Jinja,Jinja, +John Doe,John Doe, +Kanban,Kanban, +Kanban Board Column,Coluna do Painel Kanban, +Kanban Board Name,Nome do Painel Kanban, +Karma,Karma, +Keep track of all update feeds,Acompanhe todos os feeds de atualização, +Keeps track of all communications,Mantém o controle de todas as comunicações, +Key,Chave, +Knowledge Base,Base de Conhecimento, +Knowledge Base Contributor,Colaborador da Base de Conhecimento, +Knowledge Base Editor,Editor da Base de Conhecimento, +LDAP Email Field,Campo do Email LDAP, +LDAP First Name Field,Campo Primeiro Nome do LDAP, +LDAP Not Installed,LDAP não instalado, +LDAP Search String,Palavra de Busca do LDAP, +"LDAP Search String needs to end with a placeholder, eg sAMAccountName={0}","A string de pesquisa do LDAP precisa terminar com um espaço reservado, por exemplo, sAMAccountName = {0}", +LDAP Security,Segurança LDAP, +LDAP Server Url,Servidor LDAP Url, +LDAP Username Field,Campo Nome de Usuário do LDAP, +LDAP is not enabled.,O LDAP não está ativado., +Label Help,Ajuda sobre Etiquetas, +Label and Type,Etiqueta e Tipo, +Label is mandatory,Etiqueta é obrigatório, +Landing Page,Página de chegada, +Language,Idioma, +Language Code,Código do Idioma, +"Language, Date and Time settings","Configurações de Idioma , Data e Hora", +Last Active,Ativo pela última vez, +Last IP,Último IP, +Last Known Versions,Últimas versões conhecidas, +Last Login,Último Login, +Last Message,Última mensagem, +Last Modified By,Última Alteração por, +Last Modified Date,Última Data Modificada, +Last Modified On,Última Alteração em, +Last Month,Mês passado, +Last Point Allocation Date,Última data de alocação de ponto, +Last Quarter,Ultimo quarto, +Last Synced On,Última sincronização em, +Last Updated By,Última atualização por, +Last Updated On,Última atualização em, +Last User,Último usuário, +Last Week,Semana passada, +Last Year,Ano passado, +Last synced {0},Última sincronização {0}, +Leave a Comment,Deixe um comentário, +Leave blank to repeat always,Deixe em branco para repetir sempre, +Leave this conversation,Deixar essa conversa, +Left this conversation,Deixou esta conversa, +Length,Comprimento, +Length of {0} should be between 1 and 1000,Comprimento de {0} deve ser entre 1 e 1000, +Let's avoid repeated words and characters,Vamos evitar palavras e caracteres repetidos, +Let's prepare the system for first use.,Vamos preparar o sistema para a primeira utilização., +Letter,Carta, +Letter Head Based On,Carta de cabeça com base em, +Letter Head Image,Carta cabeça imagem, +Letter Head Name,Nome do timbrado, +Letter Head in HTML,Cabeça Carta em HTML, +Level Name,Nome do nível, +Liked,Gostou, +Liked By,Gostou por, +Liked by {0},Aprovado por {0}, +Likes,Gostos, +Limit Number of DB Backups,Número limite de backups de banco de dados, +Line,Linha, +Link DocType,Relacionar ao DocType, +Link Expired,Link expirado, +Link Name,Nome do Link, +Link Title,Título do Link, +"Link that is the website home page. Standard Links (index, login, products, blog, about, contact)","Link da home page do site. Links padrão (index, login, products, blog, about, contact)", +Link to the page you want to open. Leave blank if you want to make it a group parent.,Link para a página que você deseja abrir. Deixe em branco se você quiser torná-lo um pai grupo., +Linked,Relacionado, +Linked With,Relacionado com, +Linked with {0},Ligado com {0}, +Links,Links, +List,Lista, +List Filter,Filtro de lista, +List View Setting,Configuração de exibição de lista, +List a document type,Lista de um tipo de documento, +"List as [{""label"": _(""Jobs""), ""route"":""jobs""}]","Lista como [{ "label": _ ( "Jobs"), "route": "empregos"}]", +List of backups available for download,Lista de backups disponíveis para download, +List of patches executed,Lista de correções executado, +List of themes for Website.,Lista dos temas para o site., +Load Balancing,Balanceamento de carga, +Loading,Carregando, +Local DocType,DocType local, +Local Fieldname,Nome do campo local, +Local Primary Key,Chave primária local, +Locals,Locais, +Log Details,Detalhes do registro, +Log of Scheduler Errors,Log de Erros Scheduler, +Log of error during requests.,Log de erro durante a solicitações., +Log of error on automated events (scheduler).,Log de erro sobre eventos automatizados ( programador ) ., +Logged Out,Deslogado, +Logged in as Guest or Administrator,Conectado como Convidado ou Administrador, +Login,Entrar, +Login After,Login após, +Login Before,Login antes, +Login Id is required,ID de login é necessária, +Login Required,Necessário Login, +Login Verification Code from {},Código de verificação de login de {}, +Login and view in Browser,Faça login e visualize no navegador, +Login not allowed at this time,Entrada não permitida neste momento, +"Login session expired, refresh page to retry","A sessão de login expirou, atualize a página para tentar novamente", +Login to comment,Faça login para comentar, +Login token required,É necessário o token de login, +Login with LDAP,Logar com LDAP, +Logout,Sair, +Long Text,Texto Longo, +Looks like something is wrong with this site's Paypal configuration.,Parece que algo está errado com a configuração do Paypal deste site., +Looks like something is wrong with this site's payment gateway configuration. No payment has been made.,Parece que algo está errado com a configuração de gateway de pagamento deste site. Nenhum pagamento foi feito., +"Looks like something went wrong during the transaction. Since we haven't confirmed the payment, Paypal will automatically refund you this amount. If it doesn't, please send us an email and mention the Correlation ID: {0}.","Parece que algo deu errado durante a transação. Desde que não tenham confirmado o pagamento, Paypal vai reembolsá-lo automaticamente esse valor. Se isso não acontecer, por favor, envie-nos um e-mail e mencionar a ID de Correlação: {0}.", +Madam,Senhora, +Main Section,Seção Principal, +Make "name" searchable in Global Search,Tornar "nome" pesquisável na Busca Global, +Make use of longer keyboard patterns,Use uma combinação de letras e números mais longa, +Manage Third Party Apps,Gerencie aplicativos de terceiros, +Mandatory Information missing:,Informações obrigatórias ausente:, +Mandatory field: set role for,Campo obrigatório: definir a função para, +Mandatory field: {0},Campo obrigatório: {0}, +"Mandatory fields required in table {0}, Row {1}","Os campos obrigatórios exigidos na tabela {0}, linha {1}", +Mandatory fields required in {0},Os campos obrigatórios exigidos no {0}, +Mandatory:,Obrigatório:, +Mapping Name,Mapeando o Nome, +Mappings,Mapeamentos, +Mark as Read,Marcar como lido, +Mark as Spam,Marcar como spam, +Mark as Unread,Marcar como não lido, +Markdown,Desconto, +Markdown Editor,Editor de Markdown, +Marked As Spam,Marcado como spam, +Max 500 records at a time,Máximo de 500 registros por vez, +Max Attachment Size (in MB),Max tamanho do anexo (em MB), +Max Attachments,Máx. de Anexos, +Max Length,Comprimento máximo, +Max Value,Max Valor, +Max width for type Currency is 100px in row {0},Largura máxima para o tipo de moeda é 100px na linha {0}, +Maximum Attachment Limit for this record reached.,Limite máximo de anexo para este recorde atingido., +Maximum {0} rows allowed,Máximo de {0} linhas permitido, +"Meaning of Submit, Cancel, Amend","Significado de Enviar, Cancelar, Corrigir", +Mention transaction completion page URL,Mencione transação página de conclusão do URL, +Mentions,Menções, +Menu,Menu, +Merchant ID,ID do comerciante, +Merge with existing,Mesclar com existente, +Merging is only possible between Group-to-Group or Leaf Node-to-Leaf Node,A fusão só é possível entre o grupos, +Message Count,Contagem de mensagens, +Message ID,ID da Mensagem, +Message Parameter,Parâmetro da mensagem, +Message Preview,Pré-visualização da mensagem, +Message clipped,Mensagem cortada, +Message not setup,Mensagem não configurada, +Message to be displayed on successful completion (only for Guest users),Mensagem a ser exibida na conclusão bem sucedida (somente para usuários convidados), +Message-id,Message-id, +Meta Tags,Meta Tags, +Migration ID Field,ID de Campo de Migração, +Milestone,Milestone, +Milestone Tracker,Milestone Tracker, +Minimum Password Score,Score Mínimo de Senha, +Miss,Senhorita, +Missing Fields,Campos ausentes, +Missing parameter Kanban Board Name,Parâmetro faltando Kanban Board Name, +Missing parameters for login,Parâmetros que faltam para o login, +Models (building blocks) of the Application,Modelos (blocos de construção) do aplicativo, +Modified By,Modificado por, +Module,Módulo, +Module Def,Def. Módulo, +Module Name,Nome do Módulo, +Module Not Found,Módulo não encontrado, +Module Path,Caminho do módulo, +Module to Export,Módulo para Exportar, +Modules HTML,Módulos HTML, +Monospace,Monospace, +More articles on {0},Mais artigos sobre {0}, +More content for the bottom of the page.,Mais conteúdo na parte de baixo da página., +Most Used,Mais Usados, +Move To,Mover Para, +Move To Trash,Mover para lixeira, +Move to Row Number,Mover para o número da linha, +Mr,Sr., +Mrs,Sra, +Ms,Sra., +Multiple root nodes not allowed.,"Vários nós raiz, não é permitido .", +Multiplier Field,Campo Multiplicador, +Must be of type "Attach Image",Deve ser do tipo "Anexar Imagem", +Must have report permission to access this report.,Deve ter permissão para acessar relatório deste relatório., +Must specify a Query to run,Deve especificar uma consulta para executar, +Mute Sounds,Desativar Sons, +MyISAM,MyISAM, +Name Case,Caso Nome, +Name cannot contain special characters like {0},Nome não pode conter caracteres especiais como {0}, +Name not set via prompt,Nome não definido através Prompt, +Name of the Document Type (DocType) you want this field to be linked to. e.g. Customer,"Nome do Tipo de Documento (DocType) pretende que este campo a ser vinculado. por exemplo, o Cliente", +Name of the new Print Format,Nome do novo Formato de Impressão, +Name of {0} cannot be {1},Nome de {0} não pode ser {1}, +Names and surnames by themselves are easy to guess.,Os nomes e sobrenomes são fáceis de adivinhar., +Naming,Nomeação, +"Naming Options:\n
    1. field:[fieldname] - By Field
    2. naming_series: - By Naming Series (field called naming_series must be present
    3. Prompt - Prompt user for a name
    4. [series] - Series by prefix (separated by a dot); for example PRE.#####
    5. \n
    6. format:EXAMPLE-{MM}morewords{fieldname1}-{fieldname2}-{#####} - Replace all braced words (fieldnames, date words (DD, MM, YY), series) with their value. Outside braces, any characters can be used.
    ","Opções de Nomenclatura:
    1. field: [fieldname] - Por campo
    2. naming_series: - Por Naming Series (campo chamado naming_series deve estar presente
    3. Prompt - Solicitar um nome para o usuário
    4. [série] - Série por prefixo (separado por um ponto); por exemplo PRE. #####
    5. format: EXAMPLE- {MM} morewords {fieldname1} - {fieldname2} - {#####} - Substitua todas as palavras braced (nomes de campo, palavras de data (DD, MM, YY), série) pelo seu valor. Chaves externas, todos os caracteres podem ser usados.
    ", +Naming Series mandatory,Nomeando obrigatório Series, +Nested set error. Please contact the Administrator.,Erro conjunto aninhado . Entre em contato com o administrador., +New Activity,Nova Atividade, +New Chat,Novo Chat, +New Comment on {0}: {1},Novo comentário em {0}: {1}, +New Connection,Nova conexão, +New Custom Print Format,Novo Formato de Impressão Personalizado, +New Email,Novo Email, +New Email Account,Nova conta de email, +New Event,Novo Evento, +New Folder,Nova Pasta, +New Kanban Board,Novo Painel Kanban, +New Message from Website Contact Page,Nova Mensagem da Página de Contato do Site, +New Name,Novo Nome, +New Newsletter,Nova Newsletter, +New Password,Nova Senha, +New Password Required.,É necessário uma nova senha., +New Print Format Name,Novo nome do formato de impressão, +New Report name,Nome do novo Relatório, +New Value,Novo Valor, +New data will be inserted.,Novos dados serão inseridos., +New updates are available,Novas atualizações estão disponíveis, +New value to be set,Novo valor a ser definido, +New {0},Novo(a) {0}, +New {} releases for the following apps are available,Novas {} versões para os seguintes aplicativos estão disponíveis, +Newsletter Email Group,Grupo de Email de Newsletter, +Newsletter Manager,Gestor de Newsletter, +Newsletter has already been sent,A Newsletter já foi enviada, +"Newsletters to contacts, leads.",Email Marketing para Contatos e Clientes em Potencial., +Next Action Email Template,Modelo de email de próxima ação, +Next Actions HTML,Próxima Ações HTML, +Next Schedule Date,Próxima data programada, +Next Scheduled Date,Próxima data agendada, +Next State,Próximo Status, +Next Sync Token,Próximo token de sincronização, +Next actions,Próximas ações, +No Active Sessions,Nenhuma sessão ativa, +No Copy,Nenhuma Cópia, +No Email Account,Sem conta de email, +No Email Accounts Assigned,Não há contas de email Assigned, +No Emails,Nenhum Email, +No Label,Sem Rótulo, +No Permissions Specified,Não há permissões especificadas, +No Permissions set for this criteria.,Sem permissões definidas para este critério., +No Preview,Não há visualização, +No Preview Available,Não há visualização disponível, +No Printer is Available.,Nenhuma impressora está disponível., +No Results,Nenhum Resultado, +No Tags,Sem Tags, +No alerts for today,Não há alertas para hoje, +No comments yet,Ainda não há comentários, +No comments yet. Start a new discussion.,Ainda não há comentários. Iniciar uma nova discussão., +No data found in the file. Please reattach the new file with data.,Nenhum dado encontrado no arquivo. Recoloque o novo arquivo com dados., +No document found for given filters,Nenhum documento encontrado para determinados filtros, +No fields found that can be used as a Kanban Column. Use the Customize Form to add a Custom Field of type "Select".,Nenhum campo encontrado que possa ser usado como uma coluna Kanban. Use o formulário Personalizar para adicionar um campo personalizado do tipo "Selecionar"., +No file attached,Nenhum arquivo anexado, +No further records,Não há mais registros, +No matching records. Search something new,Não há registros correspondentes. Procure algo novo, +"No need for symbols, digits, or uppercase letters.","Não há necessidade de símbolos, dígitos ou letras maiúsculas.", +No of Columns,Nenhuma das Colunas, +No of Rows (Max 500),Número de linhas (max 500), +No of emails remaining to be synced,Nº de emails a serem sincronizados, +No permission for {0},Sem permissão para {0}, +No permission to '{0}' {1},Sem permissão para '{0} ' {1}, +No permission to read {0},Sem permissão para ler {0}, +No permission to {0} {1} {2},Sem permissão para {0} {1} {2}, +No records deleted,Nenhum registro foi excluído, +No records present in {0},Nenhum registro presente em {0}, +No records tagged.,Não há registros marcados., +No template found at path: {0},Nenhum modelo encontrado no caminho: {0}, +No {0} found,Nenhum(a) {0} encontrado(a), +No {0} mail,Nenhum {0}, +No {0} permission,Sem permissão {0}, +None: End of Workflow,Nenhum: Fim do fluxo de trabalho, +Not Allowed: Disabled User,Não permitido: Usuário desativado, +Not Ancestors Of,Não antepassados de, +Not Descendants Of,Não Descendentes De, +Not Equals,Diferente, +Not In,Não Presente, +Not Linked to any record,Não vinculado a nenhum registro, +Not Published,Não Publicado, +Not Saved,Não Salvo, +Not Seen,Não Visto, +Not Sent,Não Enviado, +Not Set,Não Selecionado, +Not a valid Comma Separated Value (CSV File),Não é um valor CSV válido (arquivo CSV), +Not a valid User Image.,Não é uma imagem de usuário válida., +Not a valid Workflow Action,Não é uma ação válida do fluxo de trabalho, +Not a valid user,Não é um usuário válido, +Not a zip file,Não é um arquivo zip, +Not allowed for {0}: {1},Não permitido para {0}: {1}, +Not allowed for {0}: {1} in Row {2}. Restricted field: {3},Não permitido para {0}: {1} na linha {2}. Campo restrito: {3}, +Not allowed for {0}: {1}. Restricted field: {2},Não permitido para {0}: {1}. Campo restrito: {2}, +Not allowed to Import,Não é permitido importar, +Not allowed to change {0} after submission,Não é permitido alterar {0} após a apresentação, +Not allowed to print cancelled documents,Não permitido para imprimir documentos cancelados, +Not allowed to print draft documents,Não permitido para imprimir documentos de rascunho, +Not enough permission to see links,Não há permissão suficiente para ver links, +Not in Developer Mode,Você não está no modo de desenvolvedor, +Not in Developer Mode! Set in site_config.json or make 'Custom' DocType.,Você não está no modo de desenvolvedor! Configure em site_config.json ou faça um DocType 'Personalizado'., +Note Seen By,Nota Vista por, +Note:,Nota:, +Note: By default emails for failed backups are sent.,"Nota: Por padrão, os e-mails para backups com falha são enviados.", +Note: Changing the Page Name will break previous URL to this page.,Nota: Alterar o Nome da Página irá interromper o URL anterior para esta página., +"Note: For best results, images must be of the same size and width must be greater than height.","Nota: Para obter melhores resultados, as imagens devem ter o mesmo tamanho e a largura deve ser maior que a altura.", +Note: Multiple sessions will be allowed in case of mobile device,Observação: Serão permitidas múltiplas sessões no caso de dispositivo móvel, +Nothing to show,Nada para mostrar, +Nothing to update,Nada para atualizar, +Notification,Notificação, +Notification Recipient,Destinatário da Notificação, +Notification Tones,Tons de notificação, +Notifications,Notificações, +Notifications and bulk mails will be sent from this outgoing server.,Notificações e emails em massa serão enviados por este servidor de saída., +Notify Users On Every Login,Notificar usuários em cada login, +Notify if unreplied,Informar se não for respondido, +Notify if unreplied for (in mins),Informar se não for respondido em (minutos), +Notify users with a popup when they log in,Notificar os usuários com um pop-up quando eles entram, +Number Format,Formato de número, +Number of Backups,Número de Backups, +Number of DB Backups,Número de backups de banco de dados, +Number of DB backups cannot be less than 1,Número de backups de banco de dados não pode ser menor que 1, +Number of columns for a field in a Grid (Total Columns in a grid should be less than 11),O número de colunas para um campo numa Grelha (O Total de Colunas em um grid deve ser inferior a 11), +Number of columns for a field in a List View or a Grid (Total Columns should be less than 11),Número de colunas para um campo em uma lista ou de um Grid (Total de colunas deve ser inferior a 11), +OAuth Authorization Code,Código de Autorização OAuth, +OAuth Bearer Token,OAuth Bearer Token, +OAuth Client,Cliente OAuth, +OAuth Provider Settings,Configurações do Provedor OAuth, +OTP App,Aplicação OTP, +OTP Issuer Name,Nome da Emissora OTP, +OTP Secret has been reset. Re-registration will be required on next login.,OTP Secret foi reiniciado. O novo registro será requerido no próximo login., +OTP secret can only be reset by the Administrator.,O Secretário OTP só pode ser redefinido pelo Administrador., +Office,Escritório, +Office 365,Office 365, +Old Password,Senha Antiga, +Old Password Required.,Senha antiga necessária., +Older backups will be automatically deleted,Os backups mais antigos serão apagados automaticamente, +"On {0}, {1} wrote:","Em {0}, {1} escreveu:", +"Once submitted, submittable documents cannot be changed. They can only be Cancelled and Amended.","Depois de enviados, os documentos enviados não podem ser alterados. Eles só podem ser cancelados e alterados.", +"Once you have set this, the users will only be able access documents (eg. Blog Post) where the link exists (eg. Blogger).","Depois de ter definido isso, os usuários só poderão ser acessar documentos capazes (ex. Blog Post) onde existe a ligação (por exemplo, Blogger ) .", +One Last Step,Um Último Passo, +One Time Password (OTP) Registration Code from {},Código de registro de senha de uma vez (OTP) de {}, +Only 200 inserts allowed in one request,São permitidas somente 200 inserções por solicitação, +Only Administrator can delete Email Queue,Somente o administrador pode deletar a fila de emails, +Only Administrator can edit,Somente o Administrador pode editar, +Only Administrator can save a standard report. Please rename and save.,"Somente o Administrador pode salvar um relatório padrão. Por favor, renomear e salvar.", +Only Administrator is allowed to use Recorder,Apenas o administrador tem permissão para usar o gravador, +Only Allow Edit For,Somente permite edição para, +Only Send Records Updated in Last X Hours,Somente Enviar Registros Atualizados em Últimas X Horas, +Only mandatory fields are necessary for new records. You can delete non-mandatory columns if you wish.,"Somente os campos obrigatórios são necessários para novos registros. Você pode excluir colunas não-obrigatórias, se desejar.", +Only standard DocTypes are allowed to be customized from Customize Form.,Somente DocTypes padrão podem ser personalizados no Custom Form., +Only users involved in the document are listed,Somente usuários envolvidos no documento são listados, +Only {0} emailed reports are allowed per user,Somente {0} relatórios enviados poe email são permitidos por usuário, +Oops! Something went wrong,Ops! Aconteceu algo inesperado, +"Oops, you are not allowed to know that","Ops, você não tem permissão para saber isso", +Open Link,Abrir Link, +Open Source Applications for the Web,Aplicativos Open Source para a Web, +Open Translation,Open Translation, +Open a dialog with mandatory fields to create a new record quickly,Abra uma caixa de diálogo com campos obrigatórios para criar um novo registro rapidamente, +Open a module or tool,Abra um módulo ou ferramenta, +Open your authentication app on your mobile phone.,Abra seu aplicativo de autenticação em seu telefone celular., +Open {0},Abrir {0}, +Opened,Inaugurado, +Operator must be one of {0},O operador deve ser um dos {0}, +Option 1,Opção 1, +Option 2,Opção 2, +Option 3,Opção 3, +Optional: Always send to these ids. Each Email Address on a new row,Opcional: Sempre enviar para estes ids. Cada endereço de email em uma nova linha, +Optional: The alert will be sent if this expression is true,Opcional: O alerta será enviado se essa expressão é verdadeira, +Options 'Dynamic Link' type of field must point to another Link Field with options as 'DocType',Opções 'Dynamic Link' tipo de campo deve apontar para um outro campo Ligação com opções como "TipoDoc ', +Options Help,Ajuda sobre Opções, +Options for select. Each option on a new line.,Opções para selecionar. Cada opção em uma nova linha., +Options not set for link field {0},Opções não definida para o campo link {0}, +Or login with,Ou faça login com, +Order,Pedido, +Org History,História da Organização, +Org History Heading,Cabeçalho da História da Organização, +Orientation,Orientação, +Original Value,Valor Original, +Outgoing email account not correct,Conta de e-mail de saída não correto, +Outlook.com,Outlook.com, +Output,Saída, +PDF,PDF, +PDF Page Size,Tamanho da página PDF, +PDF Settings,Configurações do PDF, +PDF generation failed,Geração de PDF falhou, +PDF generation failed because of broken image links,Geração de PDF falhou por causa de links de imagens quebradas, +PDF printing via "Raw Print" is not yet supported. Please remove the printer mapping in Printer Settings and try again.,A impressão em PDF por meio de "Impressão bruta" ainda não é suportada. Remova o mapeamento da impressora em Configurações da impressora e tente novamente., +Page HTML,Página HTML, +Page Length,Comprimento da página, +Page Name,Nome da Página, +Page Settings,Configurações da página, +Page has expired!,A página expirou!, +Page not found,Página não encontrada, +Page to show on the website\n,Página a mostrar no website, +Pages in Desk (place holders),Páginas na Desk (suportes do lugar), +Parent,Principal, +Parent Error Snapshot,Pai Snapshot de Erro, +Parent Label,Etiqueta Pai, +Parent Table,Tabela Pai, +Parent is required to get child table data,Pai é necessário para obter dados da tabela filho, +Parent is the name of the document to which the data will get added to.,Pai é o nome do documento ao qual os dados serão adicionados., +Partial Success,Sucesso parcial, +Partially Successful,Parcialmente bem sucedido, +Participants,Participantes, +Passive,Passivo, +Password Reset,Redefinição de Senha, +Password Updated,Senha Atualizada, +Password for Base DN,Senha para DN de base, +Password is required or select Awaiting Password,Senha é necessária ou selecione Aguardando senha, +Password not found,Senha não encontrada, +Password reset instructions have been sent to your email,Instruções de redefinição de senha foram enviadas para seu email, +Paste,Colar, +Patch,Remendo, +Patch Log,Log de Patches, +Path to CA Certs File,Caminho para o arquivo CA Certs, +Path to Server Certificate,Caminho para o certificado do servidor, +Path to private Key File,Caminho para o arquivo de chaves privado, +PayPal Settings,Configurações PayPal, +PayPal payment gateway settings,configurações de gateway de pagamento PayPal, +Payment Cancelled,Pagamento cancelado, +Payment Failed,Pagamento falhou, +Payment Success,Sucesso de pagamento, +Pending Approval,Aprovação pendente, +Pending Verification,verificação pendente, +Percent,Por cento, +Percent Complete,Percentagem completa, +Perm Level,Nível Permanente, +Permanent,Permanente, +Permanently Cancel {0}?,Cancelar Permanentemente {0} ?, +Permanently Submit {0}?,Confirmar Permanentemente {0} ?, +Permanently delete {0}?,Excluir Permanentemente {0} ?, +Permission Error,Erro de permissão, +Permission Level,Nível de Permissão, +Permission Levels,Níveis de Permissão, +Permission Rules,Regras de Permissão, +Permissions,Permissões, +Permissions are automatically applied to Standard Reports and searches.,As permissões são aplicadas automaticamente a relatórios e pesquisas padrão., +"Permissions are set on Roles and Document Types (called DocTypes) by setting rights like Read, Write, Create, Delete, Submit, Cancel, Amend, Report, Import, Export, Print, Email and Set User Permissions.","As permissões são definidas em Funções e Tipos de Documentos (chamados Doctypes) , definindo direitos como Ler, Escrever, Criar, Deletar, Enviar, Cancelar, Corrigir, Reportar, Importar, Exportar, Imprimir, Email e Definir Permissões de Usuário.", +Permissions at higher levels are Field Level permissions. All Fields have a Permission Level set against them and the rules defined at that permissions apply to the field. This is useful in case you want to hide or make certain field read-only for certain Roles.,As permissões de níveis superiores são permissões de Nível de Campo. Todos os Campos têm um conjunto de Nível de Permissão e as regras definidas nessas permissões aplicam-se ao campo. Isto é útil caso queira ocultar ou fazer com que determinado campo seja só de leitura para certas Funções., +"Permissions at level 0 are Document Level permissions, i.e. they are primary for access to the document.","As permissões para o nível 0 são permissões em nível de documento, ou seja, eles são primários para o acesso ao documento.", +Permissions get applied on Users based on what Roles they are assigned.,As permissões são aplicadas em usuários com base nas funções que lhe são atribuídas., +Personal,Pessoal, +Personal Data Deletion Request,Solicitação de Exclusão de Dados Pessoais, +Personal Data Download Request,Solicitação de download de dados pessoais, +Phone No.,Nº de Telefone., +Pick Columns,Escolher Colunas, +Plant,Fábrica, +Please Duplicate this Website Theme to customize.,Por favor Duplicar este site Tema para personalizar., +Please Enter Your Password to Continue,"Por favor, digite sua senha para continuar", +Please Install the ldap3 library via pip to use ldap functionality.,"Por favor, instale a biblioteca ldap3 via pip para usar a funcionalidade ldap.", +Please Update SMS Settings,Atualize Configurações SMS, +Please add a subject to your email,"Por favor, adicione um assunto ao seu email", +Please ask your administrator to verify your sign-up,"Por favor, pergunte ao seu administrador para verificar a sua inscrição", +Please attach a file first.,"Por favor, anexar um arquivo primeiro", +Please attach an image file to set HTML,"Por favor, anexe um arquivo de imagem para definir HTML", +Please check your email for verification,"Por favor, verifique seu e-mail para verificação", +Please check your registered email address for instructions on how to proceed. Do not close this window as you will have to return to it.,"Verifique seu endereço de e-mail registrado para obter instruções sobre como proceder. Não feche esta janela, pois você terá que retornar a ela.", +Please close this window,"Por favor, feche esta janela", +Please confirm your action to {0} this document.,"Por favor, confirme sua ação para {0} este documento.", +Please do not change the rows above {0},"Por favor, não alterar as linhas acima {0}", +Please do not change the template headings.,"Por favor, não alterar as posições do modelo.", +Please duplicate this to make changes,"Por favor, duplicar este para fazer mudanças", +Please enable developer mode to create new connection,Ative o modo de desenvolvedor para criar uma nova conexão, +Please ensure that your profile has an email address,Verifique se o seu perfil tem um endereço de email, +Please enter Access Token URL,Digite o URL do token de acesso, +Please enter Authorize URL,Digite Autorizar URL, +Please enter Base URL,Digite o URL da Base, +Please enter Client ID before social login is enabled,Digite o ID do cliente antes que o login social seja ativado, +Please enter Client Secret before social login is enabled,Digite Client Secret antes do login social estar habilitado, +Please enter Redirect URL,Digite o URL de redirecionamento, +Please enter the password,Por favor digite a senha, +Please enter valid mobile nos,"Por favor, indique números de celular válidos", +Please enter values for App Access Key and App Secret Key,Por favor insira os valores para acesso App Key e App chave secreta, +Please make sure that there are no empty columns in the file.,"Por favor, certifique-se de que não existem colunas vazias no arquivo.", +Please make sure the Reference Communication Docs are not circularly linked.,Certifique-se de que os Documentos de Comunicação de Referência não estejam vinculados circularmente., +Please refresh to get the latest document.,Por favor de atualização para obter os últimos documentos., +Please save before attaching.,"Por favor, salve antes de anexar.", +Please save the Newsletter before sending,"Por favor, salve a Newsletter antes de enviar", +Please save the document before assignment,"Por favor, salve o documento antes da atribuição", +Please save the document before removing assignment,"Por favor, salve o documento antes de remover a atribuição", +Please save the report first,"Por favor, salve o primeiro relatório", +Please select DocType first,"Por favor, selecione DocType primeiro", +Please select Entity Type first,"Por favor, selecione Tipo de Entidade primeiro", +Please select Minimum Password Score,Selecione Mínimo de Marcação de Senha, +Please select a Amount Field.,Por favor selecione um campo total., +Please select a file or url,"Por favor, selecione um arquivo ou url", +Please select a new name to rename,Selecione um novo nome para renomear, +Please select a valid csv file with data,"Por favor, selecione um arquivo csv com dados válidos", +Please select another payment method. PayPal does not support transactions in currency '{0}',Selecione outra forma de pagamento. O PayPal não suporta transações em moeda '{0}', +Please select another payment method. Razorpay does not support transactions in currency '{0}',Selecione outra forma de pagamento. não Razorpay não suporta transações em moeda '{0}', +Please select atleast 1 column from {0} to sort/group,"Por favor, selecione pelo menos coluna 1 a partir de {0} para classificar / grupo", +Please select document type first.,"Por favor, selecione o tipo de documento primeiro.", +Please select the Document Type.,Selecione o Tipo de documento., +Please set Base URL in Social Login Key for Frappe,Defina o URL básico na chave de login social para Frappe, +Please set Dropbox access keys in your site config,Defina teclas de acesso Dropbox em sua configuração local, +Please set a printer mapping for this print format in the Printer Settings,"Por favor, defina um mapeamento de impressora para este formato de impressão nas configurações da impressora.", +Please set filters,"Por favor, defina filtros", +Please set filters value in Report Filter table.,"Por favor, definir o valor de filtros na tabela Filtro de Relatório.", +"Please setup SMS before setting it as an authentication method, via SMS Settings","Configure o SMS antes de configurá-lo como um método de autenticação, por meio de Configurações de SMS", +Please setup a message first,"Por favor, configure uma mensagem primeiro", +Please specify which date field must be checked,Por favor especificar qual campo de data deve ser verificado, +Please specify which value field must be checked,Por favor especificar qual campo deve ser verificado, +Please try again,"Por favor, tente novamente", +Please verify your Email Address,"Por favor, verifique seu endereço de email", +Point Allocation Periodicity,Periodicidade de alocação de pontos, +Points,Pontos, +Points Given,Pontos dados, +Port,Porta, +Portal Menu,Portal menu, +Portal Menu Item,Portal item de menu, +Post,Post, +Post Comment,Publicar comentário, +Postal,Postal, +Postal Code,CEP, +Postprocess Method,Método de pós-processamento, +Posts,Postagens, +Posts by {0},Posts de {0}, +Posts filed under {0},Posts arquivados em {0}, +Precision,Precisão, +Precision should be between 1 and 6,Precisão deve estar entre 1 e 6, +Predictable substitutions like '@' instead of 'a' don't help very much.,"As substituições previsíveis, como '@' em vez de 'a' não ajudam muito.", +Preferred Billing Address,Endereço preferido de faturamento, +Preferred Shipping Address,Endereço preferido para entrega, +Prepared Report,Relatório preparado, +Preparing Report,Preparando Relatório, +Preprocess Method,Método de pré-processamento, +Press Enter to save,Pressione Enter para salvar, +Preview HTML,Pré-visualização de HTML, +Preview Message,Visualizar mensagem, +Previous,Anterior, +Previous Hash,Hash anterior, +Primary Color,Cor primária, +Print Documents,Imprimir documentos, +Print Format Builder,Criar/Editar Formato de Impressão, +Print Format Help,Ajuda sobre Formatos de Impressão, +Print Format Type,Tipo do Formato de Impressão, +Print Format {0} is disabled,Formato de Impressão {0} está desativado, +Print Hide,Ocultar Impressão, +Print Hide If No Value,Ocultar Impressão se não Preenchido, +Print Sent to the printer!,Imprimir Enviado para a impressora!, +Print Server,Servidor de impressão, +Print Style,Estilo de Impressão, +Print Style Name,Nome do estilo de impressão, +Print Style Preview,Estilo de visualização de impressão, +Print Width,Largura de impressão, +"Print Width of the field, if the field is a column in a table","Largura de impressão do campo, se o campo é uma coluna na tabela", +Print with letterhead,Imprimir com o timbre, +Printer,Impressora, +Printer Mapping,Mapeamento de Impressora, +Printer Name,Nome da impressora, +Printer Settings,Configurações da Impressora, +Printing failed,Impressão falhou, +Private Key,Chave privada, +Private and public Notes.,Privadas e públicas Notas., +ProTip: Add Reference: {{ reference_doctype }} {{ reference_name }} to send document reference,Protip: Adicionar Reference: {{ reference_doctype }} {{ reference_name }} para enviar referência do documento, +Processing,Em processamento, +Processing...,Em processamento..., +Prof,Prof, +Progress,Progresso, +Property Setter,Configurador de Propriedades, +Property Setter overrides a standard DocType or Field property,O configurador de propriedades substitui o DocType padrão ou propriedade de campo, +Property Type,Tipo de propriedade, +Provider,Fornecedor, +Provider Name,Nome do provedor, +Public Key,Chave pública, +Publishable Key,Chave publicável, +Published On,Publicado no, +Pull,Puxar, +Pull Failed,Puxar falhou, +Pull Insert,Inserir puxar, +Pull Update,Puxe a Atualização, +Push,Empurrar, +Push Delete,Pressione Excluir, +Push Failed,Push Failed, +Push Insert,Push Insert, +Push Update,Atualização de envio, +Python Module,Módulo Python, +Pyver,Pyver, +QR Code,QR Code, +QR Code for Login Verification,Código QR para verificação de login, +QZ Tray Connection Active!,Conexão da Bandeja QZ Ativo!, +QZ Tray Failed: ,QZ Tray Failed:, +Quarter Day,1/4 do Dia, +Query,Consulta, +Query Report,Relatório da Consulta, +Query must be a SELECT,Consulta deve ser um SELECT, +Queue should be one of {0},A fila deve ser uma de {0}, +Queued for backup. It may take a few minutes to an hour.,Na fila para backup em até uma hora., +Queued for backup. You will receive an email with the download link,Em fila para backup. Você receberá um e-mail com o link de download, +Quick Help for Setting Permissions,Ajuda rápida para Configurar Permissões, +Rating: ,Rating:, +Raw Commands,Comandos brutos, +Raw Email,Email Puro, +Raw Printing,Impressão Raw, +Razorpay Payment gateway settings,configurações de gateway de pagamento Razorpay, +Razorpay Settings,Configurações Razorpay, +Re: ,Re: , +Re: {0},Re: {0}, +Read,Ler, +Read Only,Somente Leitura, +Read by Recipient,Lido por destinatário, +Read by Recipient On,Lido por destinatário ativado, +Rebuild,Reconstruir, +Receiver Parameter,Parâmetro do recebedor, +Recent years are easy to guess.,Os anos recentes são fáceis de adivinhar., +Recipient,Destinatário, +Recipient Unsubscribed,Destinatário com inscrição cancelada, +Record does not exist,Registro não existe, +Records for following doctypes will be filtered,Registros para seguir doctypes serão filtrados, +Redirect To,redirecionar para, +Redirect URI Bound To Auth Code,URI de redirecionamento Bound To Código Auth, +Redirect URIs,redirecionar URIs, +Redis cache server not running. Please contact Administrator / Tech support,Servidor de cache Redis não está funcionando. Entre em contato com o Administrador de apoio / Tecnologia, +Ref DocType,DocType de Ref., +Ref Report DocType,Ref Report DocType, +Reference DocName,Nome do Documento de Referência, +Reference DocType and Reference Name are required,Referência DocType e nome de referência são necessários, +Reference Report,Relatório de referência, +Reference: {0} {1},Referência: {0} {1}, +Refreshing...,Atualizando..., +Register OAuth Client App,Registrar App OAuth Cliente, +Registered but disabled,Registrado mas desativado, +Relapsed,Reincidente, +Relapses,Recaídas, +Relink,Religar, +Relink Communication,Religar Comunicação, +Relinked,Religado, +Reload,Recarregar, +Remember Last Selected Value,Lembrar última seleção, +Remote,Remoto, +Remote Fieldname,Remote Fieldname, +Remote ID,ID Remoto, +Remote Objectname,Remote Objectname, +Remote Primary Key,Chave primária remota, +Remove,Remover, +Remove Field,Remover Campo, +Remove Filter,Remover Filtro, +Remove Section,Remover Seção, +Remove Tag,Remova Tag, +Remove all customizations?,Remover todas as personalizações?, +Removed {0},Removido {0}, +Rename many items by uploading a .csv file.,Renomeie muitos itens fazendo o upload de um arquivo csv., +Rename {0},Mudar o nome {0}, +Repeat Header and Footer in PDF,Repetir cabeçalho e rodapé no PDF, +Repeat On,Repetir em, +Repeat Till,Repita até que, +Repeat on Day,Repetir no dia, +Repeat this Event,Repita este evento, +Repeats like "aaa" are easy to guess,Repetições como "aaa" são fáceis de adivinhar, +Repeats like "abcabcabc" are only slightly harder to guess than "abc",Repetições como "abcabcabc" são somente um pouco mais difícil de adivinhar que "abc", +Reply,Responder, +Reply All,Responder a todos, +Report End Time,Hora de término do relatório, +Report Filters,Filtros de relatório, +Report Hide,Ocultar Relatório, +Report Manager,Gestor de Relatórios, +Report Name,Nome do Relatório, +Report Start Time,Hora de início do relatório, +Report cannot be set for Single types,Relatório não pode ser ajustada para os modelos únicos, +Report of all document shares,Relatório de todas as ações de documentos, +Report updated successfully,Relatório atualizado com sucesso, +Report was not saved (there were errors),O Relatório não foi salvo (houve erros), +Report {0},Relatório {0}, +Report {0} is disabled,Relatório {0} está desativado, +Report:,Relatório:, +Represents a User in the system.,Representa um usuário no sistema., +Represents the states allowed in one document and role assigned to change the state.,Representa os estados permitidos em um documento e função atribuído para alterar o estado., +Request Timed Out,Solicitação expirada, +Request URL,URL do pedido, +Require Trusted Certificate,Exigir certificado confiável, +Res: {0},Res: {0}, +Reset OTP Secret,Redefinir OTP Secret, +Reset Password,Redefinir Senha, +Reset Password Key,Redefinição de senha chave, +Reset Permissions for {0}?,Repor permissões para {0} ?, +Reset to defaults,Restaurar Padrões, +Reset your password,Redefinir sua senha, +Response Type,Tipo de resposta, +Restore,Restaurar, +Restore Original Permissions,Restaurar permissões originais, +Restore or permanently delete a document.,Restaure ou exclua permanentemente um documento., +Restore to default settings?,Restaurar as configurações padrão?, +Restored,Restaurado, +Restrict IP,Restringir IP, +Restrict To Domain,Restringir ao domínio, +Restrict user for specific document,Restringir usuário para documento específico, +Restrict user from this IP address only. Multiple IP addresses can be added by separating with commas. Also accepts partial IP addresses like (111.111.111),Restringir usuário a partir deste endereço IP. Vários endereços IP podem ser adicionados ao separar com vírgulas. São aceitos também endereços IP parciais como (111.111.111), +Resume Sending,Retomar Envio, +Retake,Retomar, +Retry,Repetir, +Return to the Verification screen and enter the code displayed by your authentication app,Retorne à tela de Verificação e insira o código exibido pelo seu aplicativo de autenticação, +Reverse Icon Color,Inverta Ícone Cor, +Revert,Reverter, +Revert Of,Reverter, +Reverted,Revertido, +Review Level,Nível de revisão, +Review Levels,Revisar Níveis, +Review Points,Pontos de revisão, +Reviews,Rever, +Revoke,Revogar, +Revoked,Revogado, +Rich Text,Rich Text, +Robots.txt,Robots.txt, +Role Name,Nome da Função, +Role Permission for Page and Report,Permissão de Função para Página e Relatório, +Role Permissions,Permissões da Função, +Role Profile,Perfil de Função, +Role and Level,Função e Nível, +Roles,Funções, +Roles Assigned,Funções Atribuídas, +Roles can be set for users from their User page.,As funções podem ser definidas para os usuários através de sua página de Usuário., +Root {0} cannot be deleted,Root {0} não pode ser excluído, +Round Robin,Robin Redondo, +Route History,História da rota, +Route Redirects,Redirecionamentos de rota, +Route to Success Link,Rota para o Link de Sucesso, +Row,Linha, +Row #{0}:,Linha # {0}:, +Row Index,Índice de linhas, +Row No,Linha No, +Row Status,Status da fila, +Row Values Changed,Valores das Linhas Mudaram, +Row {0}: Not allowed to disable Mandatory for standard fields,Linha {0}: Não é permitido desativar Obrigatório para campos padrão, +Row {0}: Not allowed to enable Allow on Submit for standard fields,Linha {0}: Não é permitido habilitar Permitir ao Enviar para campos padrão, +Rows Added,Linhas Adicionadas, +Rows Removed,Linhas Excluídas, +Rule,Regra, +Rule Name,Nome da regra, +Rules defining transition of state in the workflow.,Regras que definem a transição de status no fluxo de trabalho., +"Rules for how states are transitions, like next state and which role is allowed to change state etc.","Regras de como os status são alterados, como o próximo status e que função terá permissão para mudar de status, etc", +Run,Corre, +Run scheduled jobs only if checked,As tarefas agendadas somente serão executadas se a opção estiver marcada, +S3 Backup Settings,Configurações de Backup S3, +S3 Backup complete!,S3 Backup completo!, +SMS,SMS, +SMS Gateway URL,URL de Gateway para SMS, +SMS Parameter,Parâmetro de SMS, +SMS Settings,Configurações de SMS, +SMS sent to following numbers: {0},SMS enviado a seguintes números: {0}, +SMTP Server,Servidor SMTP, +SMTP Settings for outgoing emails,Configurações de SMTP para envio de emails, +SQL Conditions. Example: status="Open",Condições SQL. Exemplo: status="Open", +SSL/TLS Mode,Modo SSL / TLS, +Salesforce,Salesforce, +Same Field is entered more than once,O mesmo campo foi inserido mais de uma vez, +Save API Secret: ,Salvar Segredo da API:, +Save As,Salvar como, +Save Filter,Salvar filtro, +Save Report,Salvar o relatorio, +Save filters,Salvar filtros, +Saving,Salvando, +Saving...,Salvando ..., +Scan the QR Code and enter the resulting code displayed.,Digitalize o Código QR e insira o código resultante exibido., +Scopes,Scopes, +Script,Script, +Script Report,Relatório Script, +Script or Query reports,Script ou consulta relatórios, +Script to attach to all web pages.,Script para anexar a todas as páginas web., +Search Fields,Campos de Pesquisa, +Search Help,Procure Ajuda, +Search field {0} is not valid,Campo de pesquisa {0} não é válido, +Search for '{0}',Pesquisar por '{0}', +Search for anything,Procurar por qualquer coisa, +Search in a document type,Pesquisar em um tipo de documento, +Search or Create a New Chat,Pesquisar ou criar um novo bate-papo, +Search or type a command,Pesquisar ou digite um comando, +Search...,Pesquisa..., +Searching,Procurando, +Searching ...,Procurando ..., +Section Break,Quebra de seção, +Section Heading,Cabeçalho da Seção, +Security,Segurança, +Security Settings,Configurações de Segurança, +See all past reports.,Veja todos os relatórios anteriores., +See on Website,Veja no Site, +See the document at {0},Veja o documento em {0}, +Seems API Key or API Secret is wrong !!!,Parece que a chave API ou o segredo da API estão errados !!!, +Seems Publishable Key or Secret Key is wrong !!!,Parece publicado chave ou secret key está errado !!!, +"Seems issue with server's razorpay config. Don't worry, in case of failure amount will get refunded to your account.","Parece um problema com a configuração do servidor razorpay. Não se preocupe, em caso de falha os valores serão estornados à sua conta.", +Seems token you are using is invalid!,Parece token que você está usando é inválido!, +Seen,Visto, +Seen By,Visto por, +Seen By Table,Visto por tabela, +Select Attachments,Selecione os Anexos, +Select Child Table,Selecionar tabela infantil, +Select Column,Selecione a coluna, +Select Columns,Selecionar Colunas, +Select Document Type,Selecione o Tipo de Documento, +Select Document Type or Role to start.,Selecione o Tipo de Documento ou Função para começar., +Select Document Types to set which User Permissions are used to limit access.,Selecione os tipos de documentos para definir quais as permissões de usuário são usados para limitar o acesso., +Select File Format,Selecione o formato do arquivo, +Select File Type,Selecionar tipo do arquivo, +Select Language...,Selecione o idioma..., +Select Languages,Selecionar Idiomas, +Select Module,Selecione o Módulo, +Select Print Format,Selecione o Formato de Impressão, +Select Print Format to Edit,Selecione um formato de impressão para editar, +Select Role,Selecione a Função, +Select Table Columns for {0},Selecionar colunas de tabela para {0}, +Select Your Region,Selecione sua região, +Select a Brand Image first.,Selecione o Logo da Marca primeiro., +Select a DocType to make a new format,Selecione um tipo de documento para fazer um novo formato, +Select a chat to start messaging.,Selecione um bate-papo para iniciar mensagens., +Select a group node first.,Selecione um nó de grupo primeiro., +Select an existing format to edit or start a new format.,Escolha um formato existente para editar ou iniciar um novo formato., +Select an image of approx width 150px with a transparent background for best results.,Selecione uma imagem de aproximadamente 150px de largura com um fundo transparente para melhores resultados., +Select atleast 1 record for printing,Selecione pelo menos 1 registro para impressão, +Select or drag across time slots to create a new event.,Selecione ou arraste intervalos de tempo para criar um novo evento., +Select records for assignment,Seleciona registros para a atribuição, +Select the label after which you want to insert new field.,Selecione a etiqueta após a qual você deseja inserir um novo campo., +"Select your Country, Time Zone and Currency","Escolha o seu País, Fuso Horário e Moeda", +Select {0},Selecione {0}, +Self approval is not allowed,Auto-aprovação não é permitida, +Send After,Envie Depois, +Send Alert On,Enviar Alerta, +Send Email Alert,Enviar alerta de email, +Send Email Print Attachments as PDF (Recommended),Enviar anexos de email em PDF (Recomendado), +Send Email for Successful Backup,Enviar email para backup bem-sucedido, +Send Me A Copy of Outgoing Emails,Envie-me uma cópia dos e-mails de saída, +Send Notification to,Enviar Notificação para, +Send Notifications To,Enviar Notificações para, +Send Print as PDF,Enviar impressão como PDF, +Send Read Receipt,Enviar Confirmação de Leitura, +Send Unsubscribe Link,Enviar link para cancelar inscrição, +Send Welcome Email,Enviar email de boas-vindas, +Send alert if date matches this field's value,Enviar alerta se a data corresponde valor deste campo, +Send alert if this field's value changes,Enviar alerta se muda o valor desse campo, +Send an email reminder in the morning,Enviar um email lembrete na parte da manhã, +Send days before or after the reference date,Enviar dias antes ou depois da data de referência, +Send enquiries to this email address,Envie perguntas para este endereço de email, +Send me a copy,Envie-me uma Cópia, +Send only if there is any data,Envie somente se houver quaisquer dados, +Send unsubscribe message in email,Enviar mensagem de cancelamento de inscrição no e-mail, +Sender,Remetente, +Sender Email,E-mail do remetente, +Sendgrid,Sendgrid, +Sent Read Receipt,Enviar Confirmação de Leitura, +Sent or Received,Enviados ou recebidos, +Sent/Received Email,E-mail enviado / recebido, +Server IP,IP do servidor, +Session Expired,Sessão expirada, +Session Expiry,Duração da Sessão, +Session Expiry Mobile,Duração da Sessão Móvel, +Session Expiry in Hours e.g. 06:00,"Duração da sessão em horas, por exemplo 06:00", +Session Expiry must be in format {0},Sessão de validade devem estar no formato {0}, +Session Start Failed,Falha ao iniciar a sessão, +Set Banner from Image,Definir imagem como banner, +Set Chart,Definir gráfico, +Set Filters,Definir filtros, +Set New Password,Definir nova senha, +Set Number of Backups,Definir número de cópias de segurança, +Set Only Once,Definir apenas uma vez, +Set Password,Definir senha, +Set Permissions,Definir Permissões, +Set Permissions on Document Types and Roles,Definir permissões em Tipos e Funções de documentos, +Set Property After Alert,Definir propriedade após o alerta, +Set Quantity,Definir Quantidade, +Set Role For,Definir papel para, +Set User Permissions,Definir Permissões de Usuário, +Set Value,Definir valor, +Set custom roles for page and report,Definir funções personalizadas para página e relatório, +"Set default format, page size, print style etc.","Definir o formato padrão, o tamanho da página, estilo de impressão, etc", +Set non-standard precision for a Float or Currency field,Definir precisão não-padrão para um campo Float ou Moeda, +Set numbering series for transactions.,Definir numeração série para transações., +Set up rules for user assignments.,Configurar regras para atribuições de usuários., +Setting this Address Template as default as there is no other default,"A definição desse modelo de endereço como padrão, pois não há outro padrão", +Setting up your system,Configurando seu sistema, +Settings for About Us Page.,Configurações para a Página Sobre Nós., +Settings for Contact Us Page,Configurações para a página Fale Conosco, +Settings for Contact Us Page.,Configurações da Página Fale Conosco., +Settings for OAuth Provider,Definições para Provedor de OAuth, +Settings for the About Us Page,Configurações para a página Sobre Nós, +Setup Auto Email,Configurar Email Automático, +Setup Complete,Instalação Concluída, +Setup Notifications based on various criteria.,Notificações de configuração com base em vários critérios., +Setup Reports to be emailed at regular intervals,Relatórios de configuração para ser enviado em intervalos regulares, +"Setup of top navigation bar, footer and logo.","Configuração de barra de navegação do topo, rodapé, e logotipo.", +Share,Compartilhar, +Share URL,URL de compartilhamento, +Share With,Compartilhar, +Share this document with,Compartilhe este documento com, +Share {0} with,Partilhar {0} com, +Shared,Compartilhado, +Shared With,Compartilhado com, +Shared with everyone,Compartilhado com todos, +Shared with {0},Compartilhado com {0}, +Shop,Loja, +Short keyboard patterns are easy to guess,padrões do teclado curtas são fáceis de adivinhar, +Show Attachments,Mostrar anexos, +Show Calendar,Mostrar calendário, +Show Dashboard,Mostrar Dashboard, +Show Full Error and Allow Reporting of Issues to the Developer,Mostrar erro completo e permitir relatórios de problemas para o desenvolvedor, +Show Line Breaks after Sections,Mostrar quebras de linha após seções, +Show Permissions,Mostrar Permissões, +Show Preview Popup,Mostrar pop-up de pré-visualização, +Show Relapses,Mostrar Relapses, +Show Report,Mostrar relatório, +Show Section Headings,Mostrar Seção Títulos, +Show Sidebar,Mostrar menu lateral, +Show Title,Mostrar Título, +Show Totals,Mostrar Totais, +Show Weekends,Mostrar fins de semana, +Show all Versions,Mostrar todas as versões, +Show as Grid,Mostrar como grade, +Show as cc,Mostrar como cc, +Show failed jobs,Mostrar tarefas com falha, +Show in Module Section,Mostrar na Seção Módulo, +Show in filter,Mostrar no filtro, +Show more details,Mostrar mais detalhes, +Show only errors,Mostrar apenas erros, +Show title in browser window as "Prefix - title",Mostrar título na janela do navegador como "Prefixo - título", +Showing only Numeric fields from Report,Mostrando apenas campos numéricos do relatório, +Sidebar Items,Itens da barra lateral, +Sidebar Settings,Configurações da barra lateral, +Sidebar and Comments,Menu Lateral e Comentários, +Sign Up,Inscrever-se, +Sign Up is disabled,Sign Up é desativado, +Signature,Assinatura, +"Simple Python Expression, Example: Status in (""Closed"", ""Cancelled"")","Expressão Python Simples, Exemplo: Status em ("Fechado", "Cancelado")", +"Simple Python Expression, Example: status == 'Open' and type == 'Bug'","Expressão Python Simples, Exemplo: status == 'Open' e digite == 'Bug'", +Simultaneous Sessions,Sessões simultâneas, +Single DocTypes cannot be customized.,DocTypes únicos não podem ser personalizados., +Single Post (article).,Resposta Única (artigo)., +Single Types have only one record no tables associated. Values are stored in tabSingles,Tipos individuais têm apenas um registro sem tabelas associadas. Os valores são armazenados em tabSingles, +Skip Authorization,Ignorar autorização, +Skip rows with errors,Ignorar linhas com erros, +Skype,Skype, +Slack,Folga, +Slack Channel,Canal de folga, +Slack Webhook Error,Erro Slack Webhook, +Slack Webhook URL,URL do Webhook do Slack, +Slack Webhooks for internal integration,Webhooks frouxos para integração interna, +Slideshow Items,Itens da Apresentação de Slides, +Slideshow Name,Nome da Apresentação de Slides, +Slideshow like display for the website,Slideshow como display para o site, +Small Text,Texto Pequeno, +Smallest Currency Fraction Value,Menor valor fracionado de moeda, +Smallest circulating fraction unit (coin). For e.g. 1 cent for USD and it should be entered as 0.01,"Menor unidade fração circulante (moeda). Para, por exemplo, 1 centavo, deve ser inserido como 0,01", +Snapshot View,Ver Snapshot, +Social,Social, +Social Login Key,Chave de login social, +Social Login Provider,Provedor de acesso social, +Social Logins,Logins sociais, +Socketio is not connected. Cannot upload,Socketio não está conectado. Não é possível carregar, +Soft-Bounced,Soft-Bounced, +Some of the features might not work in your browser. Please update your browser to the latest version.,Alguns dos recursos podem não funcionar no seu navegador. Atualize o navegador para a versão mais recente., +Something went wrong,Algo deu errado, +Something went wrong while generating dropbox access token. Please check error log for more details.,Algo deu errado ao gerar o token de acesso dropbox. Verifique o registro de erros para obter mais detalhes., +Sorry! I could not find what you were looking for.,Desculpe! Não foi possível encontrar o que você procurou., +Sorry! Sharing with Website User is prohibited.,Desculpe! Não é permitido compartilhar com o site do usuário., +Sorry! User should have complete access to their own record.,Desculpe! O usuário deve ter acesso completo ao seu próprio registro., +Sorry! You are not permitted to view this page.,Desculpe! Você não tem permissão para visualizar esta página., +"Sorry, you're not authorized.","Desculpe, você não está autorizado.", +Sort Field,Ordenar por campo, +Sort Order,Ordem de classificação, +Sort field {0} must be a valid fieldname,Ordenar campo {0} deve ser um nome do campo válido, +Source Text,Texto Original, +Spam,Spam, +SparkPost,SparkPost, +Special Characters are not allowed,Caracteres especiais não são permitidos, +"Standard DocType cannot have default print format, use Customize Form","DocType padrão não pode ter o formato de impressão padrão, use Personalizar formulário", +Standard Print Format cannot be updated,Formato de impressão padrão não pode ser atualizado, +Standard Print Style cannot be changed. Please duplicate to edit.,"O estilo de impressão padrão não pode ser alterado. Por favor, copie para editar.", +Standard Reports,Relatórios padrão, +Standard Sidebar Menu,Menu Lateral Padrão, +Standard roles cannot be disabled,Funções padrão não pode ser desativado, +Standard roles cannot be renamed,Funções padrão não podem ser renomeadas, +Standings,Classificações, +Start Date Field,Campo de Data de Início, +Start a conversation.,Comece uma conversa., +Start entering data below this line,Comece a introduzir dados abaixo desta linha, +Start new Format,Iniciar um Novo Formato, +StartTLS,StartTLS, +Started,Começado, +Starting Frappe ...,Iniciando Frappé ..., +Starts on,Inicia em, +States,Estados, +"States for workflow (e.g. Draft, Approved, Cancelled).","Status para o fluxo de trabalho (por exemplo, rascunho, aprovado, cancelado).", +Static Parameters,Parâmetros estáticos, +Stats based on last month's performance (from {0} to {1}),Estatísticas com base no desempenho do último mês (de {0} a {1}), +Stats based on last week's performance (from {0} to {1}),Estatísticas com base no desempenho da semana passada (de {0} a {1}), +Status: {0},Status: {0}, +Steps to verify your login,Etapas para verificar seu login, +Stores the JSON of last known versions of various installed apps. It is used to show release notes.,Armazena o JSON das últimas versões conhecidas de vários aplicativos instalados. Ele é usado para mostrar notas de lançamento., +Straight rows of keys are easy to guess,linhas retas de teclas são fáceis de adivinhar, +Stripe Settings,Configurações do Stripe, +Stripe payment gateway settings,Configurações do gateway de pagamento Stripe, +Style,Estilo, +Style Settings,Configurações de Estilo, +"Style represents the button color: Success - Green, Danger - Red, Inverse - Black, Primary - Dark Blue, Info - Light Blue, Warning - Orange","Estilo representa a cor do botão: Sucesso - Verde, Perigo - Vermelho, Inverso - Preto, Primário - Azul Escuro, Informações - Azul Claro, Aviso - Laranja", +Stylesheets for Print Formats,Folhas de estilos para formatos de impressão, +Sub-currency. For e.g. "Cent",Sub-moeda. Por exemplo "Centavo", +Sub-domain provided by erpnext.com,Sub-domínio fornecido pelo erpnext.com, +Subdomain,Subdomínio, +Subject Field,Subject Field, +Submit after importing,Enviar depois de importar, +Submit an Issue,Enviar um problema, +Submit this document to confirm,Enviar este documento para confirmar, +Submit {0} documents?,Envie {0} documentos?, +Submitting {0},Enviando {0}, +Submitted Document cannot be converted back to draft. Transition row {0},Documento enviado não pode ser convertido de volta para rascunho. Linha de transição {0}, +Submitting,Enviando, +Subscription Notification,Notificação de Subscrição, +Subsidiary,Subsidiário, +Success Action,Ação de Sucesso, +Success Message,Mensagem de sucesso, +Success URL,URL de Confirmação, +Successful: {0} to {1},Bem-sucedida: {0} para {1}, +Successfully Done,Feito com sucesso, +Successfully Updated,Atualizado com sucesso, +Successfully updated translations,Traduções atualizadas com êxito, +Suggested Username: {0},Nome de usuário sugerido: {0}, +Sum,Soma, +Sum of {0},Soma de {0}, +Support Email Address Not Specified,Endereço de e-mail de suporte Não especificado, +Suspend Sending,Suspender Envio, +Switch To Desk,Ir para o Desktop, +Symbol,Símbolo, +Sync,Sincronizar, +Sync on Migrate,Sync em Migrate, +Syntax error in template,Erro de sintaxe no template, +System,Sistema, +System Page,Página do sistema, +System Settings,Configurações do Sistema, +System User,Usuário do Sistema, +System and Website Users,Usuários do sistema e do site, +Table,Tabela, +Table Field,Campo da Tabela, +Table HTML,Tabela HTML, +Table MultiSelect,Tabela MultiSelect, +Table updated,Tabela atualizada, +Table {0} cannot be empty,Tabela {0} não pode ser vazio, +Take Backup Now,Fazer backup agora, +Take Photo,Tirar fotos, +Team Members,Membros da Equipe, +Team Members Heading,Título da página Membros da Equipe, +Temporarily Disabled,Temporariamente desativado, +Test Email Address,Teste de Endereço de Email, +Test Runner,Test Runner, +Test_Folder,Test_Folder, +Text,Texto, +Text Align,Alinhar Texto, +Text Color,Cor do texto, +Text Content,conteúdo de texto, +Text Editor,Editor de Texto, +Text to be displayed for Link to Web Page if this form has a web page. Link route will be automatically generated based on `page_name` and `parent_website_route`,"O texto a ser exibido para o link da página da web, se este formulário tem uma página web. Um link será gerado automaticamente com base em ` page_name` e `parent_website_route`", +Thank you for your email,Obrigado pelo seu email, +Thank you for your interest in subscribing to our updates,Agradecemos seu interesse em assinar a newsletter do site, +Thank you for your message,Obrigado por sua mensagem, +The CSV format is case sensitive,O formato CSV diferencia maiúsculas de minúsculas, +The Condition '{0}' is invalid,A condição '{0}' é inválido, +The First User: You,O primeiro usuário: Você, +"The application has been updated to a new version, please refresh this page","O aplicativo foi atualizado para uma nova versão, por favor, atualize esta página", +The attachments could not be correctly linked to the new document,Os anexos não puderam ser vinculados corretamente ao novo documento, +The document could not be correctly assigned,O documento não pôde ser atribuído corretamente, +The document has been assigned to {0},O documento foi atribuído a {0}, +The first user will become the System Manager (you can change this later).,O primeiro usuário será o System Manager (você pode mudar isso mais tarde)., +The name that will appear in Google Calendar,O nome que aparecerá no Google Agenda, +The process for deletion of {0} data associated with {1} has been initiated.,O processo de exclusão de {0} dados associados a {1} foi iniciado., +The resource you are looking for is not available,O recurso que você está procurando não está disponível, +The system provides many pre-defined roles. You can add new roles to set finer permissions.,O sistema disponibiliza várias funções pré-definidas. Você pode adicionar novas funções para definir permissões mais específicas., +The user from this field will be rewarded points,O usuário deste campo será recompensado pontos, +Theme,Tema, +Theme URL,URL do tema, +There can be only one Fold in a form,Só pode haver uma Fold de uma forma, +There is an error in your Address Template {0},Há um erro no seu modelo de endereço {0}, +There is no data to be exported,Não há dados a serem exportados, +There is some problem with the file url: {0},Há algum problema com a url do arquivo: {0}, +There must be atleast one permission rule.,É necessário que exista pelo menos uma regra de permissão., +"There seems to be an issue with the server's braintree configuration. Don't worry, in case of failure, the amount will get refunded to your account.","Parece haver um problema com a configuração braintree do servidor. Não se preocupe, em caso de falha, o valor será reembolsado para sua conta.", +There should remain at least one System Manager,Não deve permanecer pelo menos um gestor de sistema, +There was an error saving filters,Houve um erro ao salvar os filtros, +There were errors,Ocorreram erros, +There were errors while creating the document. Please try again.,"Houve erros ao criar o documento. Por favor, tente novamente.", +There were errors while sending email. Please try again.,Ocorreram erros durante o envio de email. Por favor, tente novamente., +"There were some errors setting the name, please contact the administrator","Houve alguns erros de definir o nome, por favor, entre em contato com o administrador", +These values will be automatically updated in transactions and also will be useful to restrict permissions for this user on transactions containing these values.,Esses valores serão atualizados automaticamente em transações e também serão úteis para restringir as permissões para este usuário em operações que contenham esses valores., +Third Party Apps,Aplicativos de terceiros, +Third Party Authentication,Autenticação de Terceiros, +This Currency is disabled. Enable to use in transactions,Esta moeda é desativado. Ativar para usar em transações, +This Kanban Board will be private,Este Conselho Kanban será privado, +This document cannot be reverted,Este documento não pode ser revertido, +This document has been modified after the email was sent.,Este documento foi modificado depois que o email foi enviado., +This document has been reverted,Este documento foi revertido, +This document is currently queued for execution. Please try again,"Este documento está em fila para execução. Por favor, tente novamente", +This email is autogenerated,Este e-mail é gerado automaticamente, +This email was sent to {0},Este email foi enviado para {0}, +This email was sent to {0} and copied to {1},Este email foi enviado para {0} e copiados para {1}, +This feature is brand new and still experimental,Esta funcionalidade é nova e ainda está em fase experimental, +This field will appear only if the fieldname defined here has value OR the rules are true (examples): \nmyfield\neval:doc.myfield=='My Value'\neval:doc.age>18,Este campo aparecerá apenas se o nome do campo definido aqui tem valor ou as regras são verdadeiros (exemplos): myfield eval: doc.myfield == 'Meu Valor' eval: doc.age> 18, +This form does not have any input,Este formulário não tem nenhum campo a ser preenchido, +This form has been modified after you have loaded it,Este formulário foi modificado depois de ter carregado ele, +This format is used if country specific format is not found,Este formato é usado se o formato específico país não é encontrado, +This goes above the slideshow.,Isto vai acima do slideshow., +This is a background report. Please set the appropriate filters and then generate a new one.,"Este é um relatório de fundo. Por favor, defina os filtros apropriados e, em seguida, gere um novo.", +This is a top-10 common password.,Essa é uma das 10 senhas mais comuns., +This is a top-100 common password.,Essa é uma das 100 senhas mais comuns., +This is a very common password.,Essa é uma senha muito comum., +This is an automatically generated reply,Isto é uma resposta gerada automaticamente, +This is similar to a commonly used password.,Isso é parecido com uma senha comum., +This is the template file generated with only the rows having some error. You should use this file for correction and import.,Este é o arquivo de modelo gerado com apenas as linhas com algum erro. Você deve usar esse arquivo para corrigir e importar., +This link has already been activated for verification.,Este link já foi ativado para verificação., +This link is invalid or expired. Please make sure you have pasted correctly.,"Este link é inválido ou expirou. Por favor, certifique-se de ter colado corretamente.", +This may get printed on multiple pages,Isso pode ser impresso em várias páginas, +This month,Este mês, +This query style is discontinued,Esse estilo de consulta foi interrompido, +This report was generated on {0},Este relatório foi gerado em {0}, +This report was generated {0}.,Este relatório foi gerado {0}., +This request has not yet been approved by the user.,Esta solicitação ainda não foi aprovada pelo usuário., +This role update User Permissions for a user,Este papel arualiza Permissões do Usuário para um usuário, +This will log out {0} from all other devices,Isso encerrará {0} de todos os outros dispositivos, +This will permanently remove your data.,Isso removerá permanentemente seus dados., +Throttled,Throttled, +Thumbnail URL,URL Thumbnail, +Time Interval,Intervalo de tempo, +Time Series,Séries Temporais, +Time Series Based On,Séries Temporais Baseadas em, +Time Zone,Fuso horário, +Time Zones,Fusos horários, +Time in seconds to retain QR code image on server. Min:240,Tempo em segundos para manter a imagem do código QR no servidor. Min: 240, +Timeline DocType,DocType Timeline, +Timeline Field,Campo Timeline, +Timeline Links,Links da linha do tempo, +Timeline Name,Nome Timeline, +Timeline field must be a Link or Dynamic Link,Campo Timeline deve ser um link ou link dinâmico, +Timeline field must be a valid fieldname,campo Timeline deve ser um nome de campo válido, +Timeseries,Timeseries, +Timestamp,Timestamp, +Title Case,Caixa do Título, +Title Field,Campo Título, +Title Prefix,Prefixo do Título, +Title field must be a valid fieldname,Campo Título deve ser um nome de campo válido, +To Date Field,Até o momento do campo, +To Do,Atribuições, +To User,Ao usuário, +"To add dynamic subject, use jinja tags like\n\n
    New {{ doc.doctype }} #{{ doc.name }}
    ","Para adicionar assunto dinâmico, use jinja tags como
     New {{ doc.doctype }} #{{ doc.name }} 
    ", +"To add dynamic subject, use jinja tags like\n\n
    {{ doc.name }} Delivered
    ","Para adicionar assunto dinâmico, usar marcas como Jinja
     {{ doc.name }} Delivered 
    ", +To and CC,Para e CC, +"To get the updated report, click on {0}.","Para obter o relatório atualizado, clique em {0}.", +ToDo,Lista de Atribuições, +Today,Hoje, +Toggle Chart,Tabela de alternância, +Toggle Charts,Gráficos de alternância, +Toggle Grid View,Toggle Grid View, +Toggle Sidebar,Toggle Sidebar, +Token,Símbolo, +Token is missing,Token está ausente, +"Too many users signed up recently, so the registration is disabled. Please try back in an hour","Demasiados usuários se inscreveram recentemente, de modo que o registro estiver desativado. Por favor volte em uma hora", +Too many writes in one request. Please send smaller requests,"Muitos escreve em um pedido. Por favor, enviar pedidos de menores", +Top Bar Item,Item da barra superior, +Top Bar Items,Itens da barra superior, +Top Performer,Top Performer, +Top Reviewer,Revisor Superior, +Top {0},Top {0}, +Total Pages,Páginas totais, +Total Rows,Linhas totais, +Total Subscribers,Total de Assinantes, +Total number of emails to sync in initial sync process ,número total de e-mails para sincronizar no processo de sincronização inicial, +Totals Row,Linha de totais, +Track Changes,Rastrear Alterações, +Track Email Status,Acompanhar status de e-mail, +Track Field,Trilha de corrida, +Track Seen,Marcar como visto, +Track Views,Acompanhar vistas, +"Track if your email has been opened by the recipient.\n
    \nNote: If you're sending to multiple recipients, even if 1 recipient reads the email, it'll be considered ""Opened""","Acompanhe se o seu email foi aberto pelo destinatário.
    Observação: se você estiver enviando para vários destinatários, mesmo que um destinatário leia o e-mail, ele será considerado "Aberto"", +Track milestones for any document,Acompanhe os marcos de qualquer documento, +Transaction Hash,Hash de transação, +Transaction Log,Log de transações, +Transaction Log Report,Relatório de log de transações, +Transition Rules,Regras de transição, +Transitions,Transições, +Translatable,Traduzível, +Translate {0},Traduzir {0}, +Translated Text,Texto Traduzido, +Translation,Tradução, +Translations,Traduções, +Trash,lixo, +Tree,Árvore, +Trigger Method,Método gatilho, +Trigger Name,Nome do Disparador, +"Trigger on valid methods like ""before_insert"", ""after_update"", etc (will depend on the DocType selected)","Gatilho em métodos válidos como ""before_insert"", ""after_update"", etc. (dependerá do DocType selecionado)", +Try to avoid repeated words and characters,Tente evitar palavras repetidas e personagens, +Try to use a longer keyboard pattern with more turns,Tente usar um padrão de teclado mais tempo com mais voltas, +Two Factor Authentication,Autenticação de dois fatores, +Two Factor Authentication method,Método de autenticação de dois fatores, +Type something in the search box to search,Digite algo na caixa de pesquisa para pesquisar, +Type:,Tipo:, +UID,UID, +UIDNEXT,UIDNEXT, +UIDVALIDITY,UIDVALIDITY, +UNSEEN,Por Ler, +UPPER CASE,MAIÚSCULAS, +"URIs for receiving authorization code once the user allows access, as well as failure responses. Typically a REST endpoint exposed by the Client App.\n
    e.g. http://hostname//api/method/frappe.www.login.login_via_facebook","URIs para receber o código de autorização uma vez que o usuário permite o acesso, bem como respostas de falha. Normalmente, um terminal REST expostas pelo cliente App.
    por exemplo, http: //hostname//api/method/frappe.www.login.login_via_facebook", +URLs,URLs, +Unable to find attachment {0},Incapaz de encontrar o anexo {0}, +Unable to load camera.,Não é possível carregar a câmera., +Unable to load: {0},Não é possível carregar: {0}, +Unable to open attached file. Did you export it as CSV?,Foi impossível abrir o arquivo anexado. Você o exportou como CSV?, +Unable to read file format for {0},Não foi possível ler o formato do arquivo para {0}, +Unable to send emails at this time,Não é possível enviar emails neste momento, +Unable to update event,Não é possível atualizar evento, +Unable to write file format for {0},Não foi possível escrever o formato do arquivo para {0}, +Unassign Condition,Desatribuir condição, +Under Development,Em desenvolvimento, +Unfollow,Deixar de seguir, +Unhandled Email,Emails não trabalhados, +Unique,Único, +Unknown Column: {0},Coluna desconhecida: {0}, +Unknown User,Usuário desconhecido, +"Unknown file encoding. Tried utf-8, windows-1250, windows-1252.","Codificação de arquivo desconhecida. Tentei utf-8, Windows -1250 , Windows-1252 .", +Unread,Não lida, +Unread Notification Sent,Notificação de mensagem não lida enviada, +Unselect All,Desmarcar Todos, +Unshared,Não Compartilhado, +Unsubscribe,Cancelar subscrição, +Unsubscribe Method,Método de Cancelamento de Inscrição, +Unsubscribe Param,Parâmetero de Cancelamento de Inscrição, +Unsupported File Format,Formato de arquivo não suportado, +Unzip,Descompactar, +Unzipped {0} files,Arquivos descompactados {0}, +Unzipping files...,Descompactando arquivos ..., +Upcoming Events for Today,Próximos Eventos para Hoje, +Update Field,Atualizar Campo, +Update Translations,Atualizar Traduções, +Update Value,Atualizar Valor, +Update many values at one time.,Atualizar muitas informações de uma só vez., +Update records,Atualizar registros, +Updated,Atualizado, +Updated successfully,Atualizado com sucesso, +Updated {0}: {1},Atualizado {0}: {1}, +Updating,Atualizando, +Updating {0},Atualizando {0}, +Upload Failed,Upload falhou, +Uploaded To Dropbox,Enviado para o Dropbox, +Use ASCII encoding for password,Use codificação ASCII para senha, +Use Different Email Login ID,Usar ID de Login de Email Diferente, +Use IMAP,Usar IMAP, +Use POST,Use POST, +Use SSL,Usar SSL, +Use TLS,Usar TLS, +"Use a few words, avoid common phrases.","Use algumas palavras, evite frases comuns.", +Use of sub-query or function is restricted,O uso de subconsulta ou função é restrito, +Use socketio to upload file,Use o socketio para fazer o upload do arquivo, +Use this fieldname to generate title,Utilize este campo para gerar o título, +User '{0}' already has the role '{1}',User '{0}' já tem o papel '{1}', +User Cannot Create,O Usuário não pode criar, +User Cannot Search,O Usuário não pode pesquisar, +User Defaults,Padrões de Perfil, +User Email,Email do Usuário, +User Emails,Emails do Usuário, +User Field,Campo do usuário, +User ID of a Blogger,ID do usuário de um Blogger, +User Image,Imagem do Usuário, +User Name,Nome de usuário, +User Permission,A permissão do usuário, +User Permissions,Permissões de Usuário, +User Permissions are used to limit users to specific records.,Permissões de usuário são usadas para limitar usuários a registros específicos., +User Permissions created sucessfully,Permissões de usuário criadas com sucesso, +User Roles,Funções do Usuário, +User Social Login,Login Social do Usuário, +User Tags,Etiquetas de Usuários, +User Type,Tipo de Usuário, +User can login using Email id or Mobile number,O usuário pode efetuar login usando a ID do e-mail ou o número do celular, +User can login using Email id or User Name,O usuário pode fazer login usando o ID de e-mail ou o Nome de usuário, +User editable form on Website.,Formato editável do usuário no site., +User is mandatory for Share,Usuário é obrigatória para Partilhar, +User not allowed to delete {0}: {1},Usuário não tem permissão para excluir {0}: {1}, +User permission already exists,A permissão do usuário já existe, +User permissions should not apply for this Link,As permissões de usuário não deve candidatar-se a este link, +User {0} cannot be deleted,O usuário {0} não pode ser excluído, +User {0} cannot be disabled,O usuário {0} não pode ser desativado, +User {0} cannot be renamed,O usuário {0} não pode ser renomeado, +User {0} does not have access to this document,O usuário {0} não tem acesso a este documento, +User {0} does not have doctype access via role permission for document {1},O usuário {0} não tem acesso ao tipo de documento via permissão de função para o documento {1}, +Username,Nome de Usuário, +Username {0} already exists,O nome de usuário {0} já existe, +Users with role {0}:,Os usuários com a função {0}:, +Uses the Email Address Name mentioned in this Account as the Sender's Name for all emails sent using this Account.,Usa o nome do endereço de e-mail mencionado nesta conta como o nome do remetente para todos os e-mails enviados usando esta conta., +Uses the Email Address mentioned in this Account as the Sender for all emails sent using this Account. ,Usa o endereço de e-mail mencionado nesta conta como o remetente para todos os e-mails enviados usando essa conta., +Valid,Válido, +Valid Login id required.,É necessário um usuário válido., +Valid email and name required,É necessário email válido e nome, +Value Based On,Valor Baseado em, +Value Change,Mudança de Valor, +Value Changed,Valor Alterado, +Value To Be Set,Valor a ser definido, +Value cannot be changed for {0},Valor não pode ser alterado para {0}, +Value for a check field can be either 0 or 1,Valor para um campo de verificação pode ser 0 ou 1, +Value for {0} cannot be a list,Valor para {0} não pode ser uma lista, +Value missing for,Valor em falta para, +Value too big,Valor muito grande, +Values Changed,Valores Alterados, +Verdana,Verdana, +Verfication Code,Código de Verificação, +Verification Link,Link de verificação, +Verification code has been sent to your registered email address.,O código de verificação foi enviado para o seu endereço de e-mail registrado., +Verify,Verificar, +Verify Password,Verifique a Senha, +Verifying...,Verificando..., +Version,Versão, +Version Updated,Atualização da versão, +View All,Ver tudo, +View Comment,Ver comentário, +View List,Ver Lista, +View Log,Visualizar log, +View Permitted Documents,Ver documentos permitidos, +View Properties (via Customize Form),Exibir Propriedades (via Personalizar Formulário), +View Settings,Ver Definições, +View Website,Ver Site, +View document,Ver documento, +View report in your browser,Exibir relatório no seu navegador, +View this in your browser,Veja isto no seu navegador, +View {0},Ver {0}, +Viewed By,Visto por, +Visit,Visita, +Visitor,Visitante, +We have received a request for deletion of {0} data associated with: {1},Recebemos uma solicitação para exclusão de {0} dados associados a: {1}, +We have received a request from you to download your {0} data associated with: {1},Recebemos uma solicitação sua para fazer o download de seus {0} dados associados a: {1}, +Web Form,Formulário Web, +Web Form Field,Campo de Formulário Web, +Web Form Fields,Campos de formulário Web, +Web Page,Página Web, +Web Page Link Text,Link de Texto para Página Web, +Web Site,Web Site, +Web View,web View, +Webhook,Webhook, +Webhook Data,Webhook Data, +Webhook Header,Cabeçalho Webhook, +Webhook Headers,Cabeçalhos Webhook, +Webhook Request,Pedido Webhook, +Webhook URL,URL do Webhook, +Webhooks calling API requests into web apps,Webhooks chamando pedidos de API em aplicativos da web, +Website Meta Tag,Meta Tag do Site, +Website Route Meta,Meta Rota do Site, +Website Route Redirect,Redirecionamento de Rota do Site, +Website Script,Script do Site, +Website Sidebar,Menu Lateral do Site, +Website Sidebar Item,Item do Menu Lateral do Site, +Website Slideshow,Slideshow do Site, +Website Slideshow Item,Item do Slideshow do Site, +Website Theme,Tema do Site, +Website Theme Image,Imagem do Tema do Site, +Website Theme Image Link,Link da Imagem do Tema do Site, +Website User,Usuário do Site, +Welcome Message,Mensagem de Boas-Vindas, +"When you Amend a document after Cancel and save it, it will get a new number that is a version of the old number.","Quando você Corrigir um documento depois de Cancelar e salvá-lo, ele irá obter um novo número que é uma versão do número antigo.", +Width,Largura, +Widths can be set in px or %.,Larguras podem ser definidas em px ou %., +Will be used in url (usually first name).,Será utilizado na url (geralmente o primeiro nome)., +Will be your login ID,Será seu ID de login, +Will only be shown if section headings are enabled,só será mostrado se títulos de seção estão habilitados, +With Letter head,Com cabeçalho, +With Letterhead,Com timbrado, +Workflow Action,Ação do Fluxo de Trabalho, +Workflow Action Master,Cadastro de Ação do Fluxo de Trabalho, +Workflow Action Name,Nome da Ação do Fluxo de Trabalho, +Workflow Document State,Status do Documento do Fluxo de Trabalho, +Workflow Name,Nome do Fluxo de Trabalho, +Workflow State,Status do Fluxo de Trabalho, +Workflow State Field,Campo do Status do Fluxo de Trabalho, +Workflow State not set,Estado do fluxo de trabalho não definido, +Workflow Transition,Transição do Fluxo de Trabalho, +Workflow state represents the current state of a document.,O Status do Fluxo de Trabalho representa o status atual de um documento., +Write,Escrever, +Wrong fieldname {0} in add_fetch configuration of custom script,Nome de campo errado {0} na configuração add_fetch do script personalizado, +X Axis Field,Campo do eixo X, +XLSX,XLSX, +Y Axis Fields,Campos do eixo Y, +Yahoo Mail,Email do Yahoo, +Yandex.Mail,Yandex.Mail, +Yesterday,Ontem, +You are connected to internet.,Você está conectado à internet., +You are not allowed to create columns,Você não tem permissão para criar colunas, +You are not allowed to delete a standard Website Theme,Você não tem permissão para excluir um site Tema padrão, +You are not allowed to print this document,Você não tem permissão para imprimir este documento, +You are not allowed to print this report,Você não tem permissão para imprimir este relatório, +You are not allowed to send emails related to this document,Você não tem permissão para enviar emails relacionados a este documento, +You are not allowed to update this Web Form Document,Você não tem permissão para atualizar esse formulário Documento Web, +You are not connected to Internet. Retry after sometime.,Você não está conectado à Internet. Tente novamente após algum tempo., +You are not permitted to access this page.,Você não tem permissão para acessar esta página., +You are not permitted to view the newsletter.,Você não tem permissão para visualizar a newsletter., +You are now following this document. You will receive daily updates via email. You can change this in User Settings.,Você está seguindo este documento agora. Você receberá atualizações diárias via e-mail. Você pode alterar isso nas configurações do usuário., +You can add dynamic properties from the document by using Jinja templating.,Você pode adicionar propriedades dinâmicas do documento usando Jinja templates., +You can also copy-paste this ,Você também pode copiar e colar, +"You can change Submitted documents by cancelling them and then, amending them.",Você pode alterar documentos cancelados, +You can find things by asking 'find orange in customers',Você pode encontrar as coisas pedindo "encontrar fulano em clientes", +You can only upload upto 5000 records in one go. (may be less in some cases),Você só pode fazer upload de até 5.000 registros de uma só vez. (Este valor pode vir a ser inferior em alguns casos), +You can use Customize Form to set levels on fields.,Você pode usar "Personalizar Formulário" para definir os níveis de campos., +You can use wildcard %,Você pode usar o coringa %, +You can't set 'Options' for field {0},Você não pode configurar 'Opções' para o campo {0}, +You can't set 'Translatable' for field {0},Você não pode configurar 'Traduzível' para o campo {0}, +You cannot give review points to yourself,Você não pode dar pontos de avaliação para si mesmo, +You cannot unset 'Read Only' for field {0},Você não pode desabilitar "Somente leitura" para o campo {0}, +You do not have enough permissions to access this resource. Please contact your manager to get access.,"Você não tem permissão suficiente para acessar este recurso. Por favor, contate o administrador para ter acesso.", +You do not have enough permissions to complete the action,Você não tem permissão suficiente para completar a ação, +You do not have enough points,Você não tem pontos suficientes, +You do not have enough review points,Você não tem pontos de revisão suficientes, +You don't have access to Report: {0},Você não tem acesso ao Relatório: {0}, +You don't have any messages yet.,Ainda não tem nenhuma mensagem., +You don't have permission to access this file,Você não tem permissão para acessar este arquivo, +You don't have permission to get a report on: {0},Você não tem permissão para acessar um relatório sobre: {0}, +You don't have the permissions to access this document,Você não tem as permissões para acessar este documento, +You gained {0} point,Você ganhou {0} ponto, +You gained {0} points,Você ganhou {0} pontos, +You have a new message from: ,Você tem uma nova mensagem de:, +You have been successfully logged out,Você saiu do sistema com sucesso, +You have unsaved changes in this form. Please save before you continue.,Você tem alterações não salvas neste formulário., +You must login to submit this form,Você precisa estar logado para enviar este formulário, +You need to be in developer mode to edit a Standard Web Form,Você precisa estar no modo de desenvolvedor para editar um Formulário Web Padrão, +You need to be logged in and have System Manager Role to be able to access backups.,Você precisa estar conectado e ter permissão para ser capaz de acessar backups., +You need to be logged in to access this {0}.,Você precisa estar logado para acessar esta {0}., +You need to have "Share" permission,Você precisa ter a permissão "Compartilhar", +You need write permission to rename,Você precisa escrever permissão para renomear, +You selected Draft or Cancelled documents,Você selecionou documentos preliminares ou cancelados, +You unfollowed this document,Você deixou de seguir este documento, +Your Country,Seu País, +Your Language,Seu Idioma, +Your Name,Seu Nome, +Your account has been locked and will resume after {0} seconds,Sua conta foi bloqueada e será retomada após {0} segundos, +Your connection request to Google Calendar was successfully accepted,Sua solicitação de conexão ao Google Agenda foi aceita com sucesso, +Your information has been submitted,Suas informações foram enviadas, +Your login id is,Sua identificação de acesso é, +Your organization name and address for the email footer.,Nome da empresa e endereço para o rodapé do email., +Your payment has been successfully registered.,Seu pagamento foi registrado com sucesso., +Your payment has failed.,O seu pagamento falhou., +Your payment is cancelled.,Seu pagamento está cancelado., +Your payment was successfully accepted,Seu pagamento foi aceito com sucesso, +"Your query has been received. We will reply back shortly. If you have any additional information, please reply to this mail.","Sua consulta foi recebida. Nós responderemos de volta em breve. Se você tiver qualquer informação adicional, por favor responda a este email.", +"Your session has expired, please login again to continue.","Sua sessão expirou, faça o login novamente para continuar.", +Zero,Zero, +Zero means send records updated at anytime,Zero significa enviar registros atualizados a qualquer momento, +_doctype,_doctype, +_report,_relatório, +adjust,ajustar, +after_insert,after_insert, +align-center,Centralizar, +align-justify,Justificar, +align-left,Alinhar à esquerda, +align-right,Alinhar à direita, +ap-northeast-1,ap-northeast-1, +ap-northeast-2,ap-northeast-2, +ap-northeast-3,ap-northeast-3, +ap-south-1,ap-south-1, +ap-southeast-1,ap-southeast-1, +ap-southeast-2,ap-southeast-2, +arrow-down,seta para baixo, +arrow-left,seta para a esquerda, +arrow-right,seta para a direita, +arrow-up,seta para cima, +asterisk,asterisco, +backward,para trás, +ban-circle,círculo de proibição, +bell,sino, +bookmark,favorito, +briefcase,pasta, +bullhorn,megafone, +ca-central-1,ca-central-1, +camera,câmera, +cancelled this document,cancelou este documento, +changed value of {0},mudou o valor de {0}, +changed values for {0},mudou o valor para {0}, +chevron-down,divisa-abaixo, +chevron-left,divisa-esquerda, +chevron-right,divisa-direito, +chevron-up,divisa-acima, +circle-arrow-down,círculo de seta para baixo, +circle-arrow-left,círculo de seta para a esquerda, +circle-arrow-right,círculo de seta à direita, +circle-arrow-up,círculo de seta para cima, +cn-north-1,cn-north-1, +cn-northwest-1,cn-northwest-1, +cog,roda dentada, +darkgrey,cinza escuro, +dd-mm-yyyy,dd-mm-aaaa, +dd.mm.yyyy,dd.mm.aaaa, +dd/mm/yyyy,dd/mm/aaaa, +"document type..., e.g. customer","Tipo de documento ..., por exemplo: cliente", +domain name,nome de domínio, +download-alt,download-alt, +"e.g. ""Support"", ""Sales"", ""Jerry Yang""","ex: ""Pós-Venda"", "" Vendas "", ""Edmilson""", +e.g. (55 + 434) / 4 or =Math.sin(Math.PI/2)...,por exemplo (55 + 434) / 4 ou = Math.sin (Math.PI / 2) ..., +e.g. pop.gmail.com / imap.gmail.com,ex: pop.gmail.com / imap.gmail.com, +e.g. replies@yourcomany.com. All replies will come to this inbox.,eg replies@yourcomany.com. Todas as respostas virão a esta caixa de entrada., +e.g. smtp.gmail.com,ex: smtp.gmail.com, +e.g.:,ex:, +eject,ejetar, +envelope,envelope, +eu-central-1,eu-central-1, +eu-north-1,eu-north-1, +eu-west-1,eu-west-1, +eu-west-2,eu-oeste-2, +eu-west-3,eu-oeste-3, +exclamation-sign,sinal de exclamação, +eye-close,olho fechado, +eye-open,olho aberto, +facetime-video,vídeo do facetime, +fairlogin,fairlogin, +fast-backward,retrocesso rápido, +fast-forward,avanço rápido, +film,filme, +fire,fogo, +folder-close,fechar pasta, +folder-open,abrir pasta, +fullscreen,tela cheia, +gained by {0} via automatic rule {1},ganho por {0} via regra automática {1}, +gained {0} points,ganhou {0} pontos, +gave {0} points,deu {0} pontos, +gift,presente, +glass,vidro, +globe,globo, +hand-down,mão abaixo, +hand-left,mão à esquerda, +hand-right,mão à direita, +hand-up,mão acima, +hdd,hdd, +headphones,fones de ouvido, +heart,coração, +hub,Hub, +indent-left,indentar à esquerda, +indent-right,indentar à direita, +info-sign,Sinal de Informações, +italic,itálico, +john@doe.com,john@doe.com, +just now,agora mesmo, +leaf,folha, +lightblue,azul claro, +list-alt,lista de alt-, +magnet,ímã, +map-marker,marcador do mapa, +merged {0} into {1},Combinado {0} com {1}, +minus,menos, +minus-sign,sinal de menos, +mm-dd-yyyy,mm-dd-aaaa, +mm/dd/yyyy,mm/dd/aaaa, +module name...,nome do módulo ..., +new type of document,novo tipo de documento, +no failed attempts,tentativas não falharam, +none of,nenhum, +ok,ok, +ok-circle,ok-círculo, +ok-sign,ok-sinal, +on_cancel,on_cancel, +on_change,em mudança, +on_submit,on_submit, +on_trash,on_trash, +on_update,on_update, +on_update_after_submit,on_update_after_submit, +only.,apenas., +or,ou, +pause,pausar, +pencil,lápis, +picture,imagem, +plane,avião, +play,jogar, +play-circle,jogo-círculo, +plus,mais, +plus-sign,sinal de mais, +qrcode,QRCode, +query-report,relatório-de-consulta, +question-sign,ponto de interrogação, +remove-circle,remove-círculo, +remove-sign,remover-assinar, +removed,removido, +renamed from {0} to {1},renomeado de {0} para {1}, +repeat,repetir, +resize-full,redimensionamento completo, +resize-horizontal,redimensionamento horizontal, +resize-small,redimensionamento pequeno, +resize-vertical,redimensionamento vertical, +restored {0} as {1},restaurado {0} como {1}, +retweet,retwitar, +road,estrada, +sa-east-1,sa-east-1, +screenshot,captura de tela, +share-alt,partes-alt, +shopping-cart,carrinho de compras, +show,mostrar, +signal,sinalizar, +star,estrela, +star-empty,sem estrela, +step-backward,voltar, +step-forward,prosseguir, +submitted this document,enviou este documento, +text in document type,texto em tipo de documento, +text-height,altura de texto, +text-width,largura de texto, +th,ª, +th-large,ª-grande, +th-list,ª-lista, +thumbs-down,polegar para baixo, +thumbs-up,polegar para cima, +tint,matiz, +toggle Tag,alternar Tag, +updated to {0},atualizado para {0}, +us-east-1,us-east-1, +us-east-2,us-east-2, +us-west-1,us-west-1, +us-west-2,us-west-2, +use % as wildcard,usar % como coringa, +values separated by commas,valores separados por vírgulas, +via automatic rule {0} on {1},via regra automática {0} em {1}, +viewed,visto, +volume-down,diminuir volume, +volume-off,mudo, +volume-up,aumentar volume, +warning-sign,sinal de alerta, +wrench,chave inglesa, +yyyy-mm-dd,dd/mm/yyyy, +zoom-in,aumentar zoom, +zoom-out,diminuir zoom, +{0} Calendar,{0} Calendário, +{0} Chart,{0} Gráfico, +{0} Dashboard,{0} Dashboard, +{0} List,{0} Lista(s), +{0} Modules,{0} módulos, +{0} Report,{0} Relatório, +{0} Settings not found,{0} Configurações não encontradas, +{0} Tree,Árvore de {0}, +{0} added,{0} adicionado, +{0} already exists. Select another name,{0} já existe. Selecione outro nome, +{0} already unsubscribed,{0} já teve sua inscrição removida, +{0} already unsubscribed for {1} {2},{0} já teve sua sua inscrição cancelada para {1} {2}, +{0} and {1},{0} e {1}, +{0} appreciated on {1},{0} apreciado em {1}, +{0} appreciated your work on {1} with {2} point,{0} apreciou seu trabalho em {1} com {2} ponto, +{0} appreciated your work on {1} with {2} points,{0} apreciou seu trabalho em {1} com {2} pontos, +{0} appreciated {1},{0} apreciado {1}, +{0} appreciation point for {1} {2},{0} ponto de apreciação para {1} {2}, +{0} appreciation points for {1} {2},{0} pontos de apreciação para {1} {2}, +{0} assigned {1}: {2},{0} atribuído {1}: {2}, +{0} cannot be set for Single types,{0} não pode ser ajustada para os modelos únicos, +{0} comments,{0} comentários, +{0} created successfully,{0} criado com sucesso, +{0} criticism point for {1} {2},{0} ponto de crítica para {1} {2}, +{0} criticism points for {1} {2},{0} pontos de criticismo para {1} {2}, +{0} criticized on {1},{0} criticado em {1}, +{0} criticized your work on {1} with {2} point,{0} criticou seu trabalho em {1} com {2} ponto, +{0} criticized your work on {1} with {2} points,{0} criticou seu trabalho em {1} com {2} pontos, +{0} criticized {1},{0} criticou {1}, +{0} days ago,{0} dias atrás, +{0} does not exist in row {1},{0} não existe em linha {1}, +"{0} field cannot be set as unique in {1}, as there are non-unique existing values","{0} campo não pode ser definido como único em {1}, pois há valores duplicados existentes", +{0} has already assigned default value for {1}.,{0} já atribuiu o valor padrão para {1}., +{0} has been successfully added to the Email Group.,"{0} foi adicionado com sucesso ao grupo de emails,", +{0} has left the conversation in {1} {2},{0} deixou a conversa em {1} {2}, +{0} hours ago,{0} horas atrás, +{0} in row {1} cannot have both URL and child items,{0} na linha {1} não pode ter URL e Itens vinculados ao mesmo tempo, +{0} is a mandatory field,{0} é um campo obrigatório, +{0} is an invalid email address in 'Recipients',{0} é um endereço de e-mail inválido em 'Destinatários', +{0} is not a raw printing format.,{0} não é um formato de impressão não processado., +{0} is not a valid Email Address,{0} não é um endereço de email válido, +{0} is not a valid Workflow State. Please update your Workflow and try again.,{0} não é um estado válido do fluxo de trabalho. Atualize seu fluxo de trabalho e tente novamente., +{0} is now default print format for {1} doctype,{0} agora é o formato de impressão padrão para o doctype {1}, +{0} is saved,{0} foi salvo, +{0} items selected,{0} itens selecionados, +{0} logged in,{0} logado(s), +{0} logged out: {1},{0} deslogado: {1}, +{0} minutes ago,{0} minutos atrás, +{0} months ago,{0} meses atrás, +{0} must be one of {1},{0} deve fazer parte de {1}, +{0} must be set first,{0} deve ser definida primeiro, +{0} must be unique,{0} já foi cadastrado e deve ser único, +{0} not a valid State,{0} não é um status válido, +{0} not allowed to be renamed,não é permitido renomear {0}, +{0} not found,{0} não encontrado, +{0} of {1},{0} de {1}, +{0} or {1},{0} ou {1}, +{0} record deleted,{0} registro excluído, +{0} records deleted,{0} registros excluídos, +{0} reverted your point on {1},{0} reverteu seu ponto em {1}, +{0} reverted your points on {1},{0} reverteu seus pontos em {1}, +{0} reverted {1},{0} revertido {1}, +{0} room must have atmost one user.,{0} sala deve ter no máximo um usuário., +{0} rows for {1},{0} linhas para {1}, +{0} saved successfully,{0} salvo com sucesso, +{0} self assigned this task: {1},{0} self designou esta tarefa: {1}, +{0} shared this document with everyone,{0} compartilhou este documento com todos, +{0} shared this document with {1},{0} compartilhou este documento com {1}, +{0} subscribers added,{0} assinantes acrescentados, +{0} to stop receiving emails of this type,{0} para parar de receber e-mails desse tipo, +{0} to {1},{0} para {1}, +{0} un-shared this document with {1},{0} descompartilhou este documento com {1}, +{0} updated,{0} atualizado(a), +{0} weeks ago,{0} semanas atrás, +{0} {1} added,{0} {1} adicionado, +{0} {1} already exists,{0} {1} já existe, +{0} {1} cannot be "{2}". It should be one of "{3}",{0} {1} não pode ser "{2}". Deve pertencer a "{3}", +{0} {1} cannot be a leaf node as it has children,"{0} {1} não pode ser um nó de extremidade , uma vez que tem filhos", +"{0} {1} does not exist, select a new target to merge","{0} {1} não existe , selecione um novo alvo para mesclar", +{0} {1} not found,{0} {1} não encontrado, +{0} {1} to {2},{0} {1} para {2}, +"{0}, Row {1}","{0}, Linha {1}", +"{0}: '{1}' ({3}) will get truncated, as max characters allowed is {2}","{0}: '{1}' ({3}) vai ficar truncado, pois os caracteres máximos permitidos são {2}", +{0}: Cannot set Amend without Cancel,{0}: Não é possível definir Amend sem Cancelar, +{0}: Cannot set Assign Amend if not Submittable,{0}: Não é possível definir atributo Corrigir se não pode ser enviado, +{0}: Cannot set Assign Submit if not Submittable,{0}: Não é possível definir atributo Enviar se não pode ser enviado, +{0}: Cannot set Cancel without Submit,{0}: Não é possível definir Cancelar sem Submeter, +{0}: Cannot set Import without Create,{0}: Não é possível definir Importação sem Criar, +"{0}: Cannot set Submit, Cancel, Amend without Write","{0}: Não é possível definir Enviar, Cancelar, Alterar sem Salvar", +{0}: Cannot set import as {1} is not importable,{0}: Não é possível definir importação como {1} se não é importável, +{0}: No basic permissions set,{0}: Nenhum conjunto de permissões básico, +"{0}: Only one rule allowed with the same Role, Level and {1}","{0}: Apenas uma regra de permissão com a mesma função, nível e {1}", +{0}: Permission at level 0 must be set before higher levels are set,{0} : permissão no nível 0 deve ser definida antes de definir os níveis mais altos, +{0}: {1} in {2},{0}: {1} em {2}, +{0}: {1} is set to state {2},{0}: {1} está configurado para declarar {2}, +{app_title},{app_title}, +{{{0}}} is not a valid fieldname pattern. It should be {{field_name}}.,{{{0}}} não é padrão para nome de campo válido. Deve ser {{field_name}}., +Communication Link,Link de comunicação, +Force User to Reset Password,Forçar usuário a redefinir a senha, +In Days,Em dias, +Last Password Reset Date,Data da última redefinição de senha, +The password of your account has expired.,A senha da sua conta expirou., +Workflow State transition not allowed from {0} to {1},Transição do estado do fluxo de trabalho não permitida de {0} para {1}, +{0} must be after {1},{0} deve ser depois de {1}, +{0}: Field '{1}' cannot be set as Unique as it has non-unique values,"{0}: o campo '{1}' não pode ser definido como Único, pois possui valores não exclusivos", +{0}: Field {1} in row {2} cannot be hidden and mandatory without default,{0}: o campo {1} na linha {2} não pode ser oculto e obrigatório sem padrão, +{0}: Field {1} of type {2} cannot be mandatory,{0}: o campo {1} do tipo {2} não pode ser obrigatório, +{0}: Fieldname {1} appears multiple times in rows {2},{0}: O nome do campo {1} aparece várias vezes nas linhas {2}, +{0}: Fieldtype {1} for {2} cannot be unique,{0}: o tipo de campo {1} para {2} não pode ser exclusivo, +{0}: Options must be a valid DocType for field {1} in row {2},{0}: as opções devem ser um DocType válido para o campo {1} na linha {2}, +{0}: Options required for Link or Table type field {1} in row {2},{0}: Opções necessárias para o campo Tipo de link ou tabela {1} na linha {2}, +{0}: Options {1} must be the same as doctype name {2} for the field {3},{0}: as opções {1} devem ser as mesmas que o nome do tipo de documento {2} para o campo {3}, +{0}:Fieldtype {1} for {2} cannot be indexed,{0}: o tipo de campo {1} para {2} não pode ser indexado, +Make {0},Faça {0}, +A user who posts blogs.,Um usuário que posta blogs., +Applying: {0},Aplicando: {0}, +Fieldname {0} is restricted,O nome do campo {0} é restrito, +Is Optional State,É estado opcional, +No values to show,Nenhum valor para mostrar, +View Ref,Visualizar Ref, +Workflow Action is not created for optional states,A ação do fluxo de trabalho não é criada para estados opcionais, +{0} values selected,{0} valores selecionados, +"amended_from" field must be present to do an amendment.,O campo "alterado_de" deve estar presente para fazer uma alteração., +(Mandatory),(Obrigatório), +1 Google Calendar Event synced.,1 Evento do Google Agenda sincronizado., +1 record will be exported,1 registro será exportado, +1 week ago,1 semana atrás, +5 Records,5 registros, +A recurring {0} {1} has been created for you via Auto Repeat {2}.,Um {0} {1} recorrente foi criado para você através da Repetição automática {2}., +API,API, +API Method,Método API, +About {0} minute remaining,Cerca de {0} minuto restante, +About {0} minutes remaining,Cerca de {0} minutos restantes, +About {0} seconds remaining,Cerca de {0} segundos restantes, +Access Log,Log de acesso, +Access not allowed from this IP Address,Acesso não permitido deste endereço IP, +Action Type,Tipo de acão, +Activity Log by ,Log de atividades por, +Add Fields,Adicionar campos, +Administration,Administração, +After Cancel,Após Cancelar, +After Delete,Após Excluir, +After Save,Após salvar, +After Save (Submitted Document),Após salvar (documento enviado), +After Submit,Após o envio, +Aggregate Function Based On,Função agregada com base em, +Aggregate Function field is required to create a dashboard chart,O campo Função Agregada é necessário para criar um gráfico de dashboard, +All Records,Todos os registros, +Allot Points To Assigned Users,Atribuir pontos aos usuários atribuídos, +Allow Auto Repeat,Permitir repetição automática, +Allow Google Calendar Access,Permitir acesso ao Google Agenda, +Allow Google Contacts Access,Permitir acesso aos Contatos do Google, +Allow Google Drive Access,Permitir acesso ao Google Drive, +Allow Guest,Permitir convidado, +Allow Guests to Upload Files,Permitir que os convidados façam upload de arquivos, +Also adding the status dependency field {0},Incluindo também o campo de dependência do status {0}, +An error occurred while setting Session Defaults,Ocorreu um erro ao definir os Padrões da Sessão, +Annual,Anual, +Append Emails to Sent Folder,Anexar emails à pasta enviada, +Apply Assignment Rule,Aplicar regra de atribuição, +Apply Only Once,Aplicar apenas uma vez, +Apply this rule only once per document,Aplique esta regra apenas uma vez por documento, +Approval Required,Aprovação necessária, +Approved,Aprovado, +Are you sure you want to delete all rows?,Tem certeza de que deseja excluir todas as linhas?, +Are you sure you want to delete this post?,Tem certeza de que deseja excluir esta postagem?, +Are you sure you want to merge {0} with {1}?,Tem certeza de que deseja mesclar {0} com {1}?, +Assignment Day {0} has been repeated.,O dia da tarefa {0} foi repetido., +Assignment Days,Dias de atribuição, +Assignment Rule Day,Dia da regra de atribuição, +Assignments,atribuições, +Attach a web link,Anexar um link da web, +Authorize Google Calendar Access,Autorizar acesso ao Google Agenda, +Authorize Google Contacts Access,Autorizar o acesso dos Contatos do Google, +Authorize Google Drive Access,Autorizar acesso ao Google Drive, +Auto Repeat Document Creation Failed,Falha na criação de documentos de repetição automática, +Auto Repeat Document Creation Failure,Falha na criação de documentos de repetição automática, +Auto Repeat created for this document,Repetição automática criada para este documento, +Auto Repeat failed for {0},A repetição automática falhou para {0}, +Automatic Linking can be activated only for one Email Account.,O link automático pode ser ativado apenas para uma conta de e-mail., +Automatic Linking can be activated only if Incoming is enabled.,O Link automático só pode ser ativado se a Entrada estiver ativada., +Automatically generates recurring documents.,Automaticamente gera documentos recorrentes., +Backing up to Google Drive.,Fazendo backup no Google Drive., +Backup Folder ID,ID da pasta de backup, +Backup Folder Name,Nome da pasta de backup, +Before Cancel,Antes de Cancelar, +Before Delete,Antes de excluir, +Before Insert,Antes da inserção, +Before Save,Antes de salvar, +Before Save (Submitted Document),Antes de salvar (documento enviado), +Before Submit,Antes de enviar, +Blank Template,Modelo em branco, +Callback URL,URL de retorno de chamada, +Cancel All Documents,Cancelar todos os documentos, +Cancelling documents,Cancelando documentos, +Cannot match column {0} with any field,Não é possível combinar a coluna {0} com nenhum campo, +Change,mudança, +Change User,Mudar usuário, +Check the Error Log for more information: {0},Verifique o log de erros para mais informações: {0}, +Clear Cache and Reload,Limpar cache e recarregar, +Clear Filters,Limpar filtros, +Click on Authorize Google Drive Access to authorize Google Drive Access.,Clique em Autorizar acesso ao Google Drive para autorizar o acesso ao Google Drive., +Click on a file to select it.,Clique em um arquivo para selecioná-lo., +Click on the link below to approve the request,Clique no link abaixo para aprovar o pedido, +Click on the lock icon to toggle public/private,Clique no ícone de cadeado para alternar entre público / privado, +Click on {0} to generate Refresh Token.,Clique em {0} para gerar o Token de Atualização., +Close Condition,Fechar Condição, +Column {0},Coluna {0}, +Columns / Fields,Colunas / Campos, +"Configure notifications for mentions, assignments, energy points and more.","Configure notificações para menções, atribuições, pontos de energia e muito mais.", +Contact Email,Email de Contato, +Contact Numbers,Números de contato, +Contact Phone,telefone de contato, +Contact Synced with Google Contacts.,Contato sincronizado com os contatos do Google., +Context,Contexto, +Contribute Translations,Contribuir Traduções, +Contributed,Contribuído, +Controller method get_razorpay_order missing,Falta o método get_razorpay_order do controlador, +Copied to clipboard.,Copiado para a área de transferência., +Core Modules {0} cannot be searched in Global Search.,Os módulos principais {0} não podem ser pesquisados na Pesquisa Global., +Could not create Razorpay order. Please contact Administrator,Não foi possível criar o pedido Razorpay. Entre em contato com o administrador, +Could not create razorpay order,Não foi possível criar a ordem razorpay, +Create Log,Criar log, +Create your first {0},Crie seu primeiro {0}, +Created {0} records successfully.,Criou {0} registros com sucesso., +Cron,Cron, +Cron Format,Formato Cron, +Daily Events should finish on the Same Day.,Os eventos diários devem terminar no mesmo dia., +Daily Long,Diário Longo, +Default Role on Creation,Função Padrão na Criação, +Default Theme,Tema Padrão, +Default {0},Padrão {0}, +Delete All,Excluir tudo, +Do you want to cancel all linked documents?,Deseja cancelar todos os documentos vinculados?, +DocType Action,Ação DocType, +DocType Event,Evento DocType, +DocType Link,Link DocType, +Document Share,Partilha de Documentos, +Document Tag,Etiqueta de Documento, +Document Title,Título do documento, +Document Type Field Mapping,Mapeamento de campos do tipo de documento, +Document Type Mapping,Mapeamento do tipo de documento, +Document Type {0} has been repeated.,O tipo de documento {0} foi repetido., +Document renamed from {0} to {1},Documento renomeado de {0} para {1}, +Document type is required to create a dashboard chart,O tipo de documento é necessário para criar um gráfico de dashboard, +Documentation Link,Link da documentação, +Don't Import,Não importe, +Don't Send Emails,Não envie emails, +"Drag and drop files, ","Arraste e solte arquivos,", +Drop,Solta, +Drop Here,Solta aqui, +Drop files here,Solte arquivos aqui, +Dynamic Template,Modelo dinâmico, +ERPNext Role,Função ERPNext, +Email / Notifications,Email / Notificações, +Email Account setup please enter your password for: {0},"Configuração da conta de e-mail, digite sua senha para: {0}", +Email Address whose Google Contacts are to be synced.,Endereço de e-mail cujos contatos do Google devem ser sincronizados., +"Email ID must be unique, Email Account already exists for {0}",O ID do email deve ser exclusivo. A conta de email já existe para {0}, +Email IDs,IDs de email, +Enable Allow Auto Repeat for the doctype {0} in Customize Form,Ativar Permitir repetição automática para o tipo de documento {0} em Personalizar formulário, +Enable Automatic Linking in Documents,Ativar Vinculação Automática em Documentos, +Enable Email Notifications,Ativar notificações por email, +Enable Google API in Google Settings.,Ative a API do Google nas configurações do Google., +Enable Security,Ativar segurança, +Energy Point,Ponto de energia, +Enter Client Id and Client Secret in Google Settings.,Digite o ID do cliente e o segredo do cliente nas Configurações do Google., +Enter Code displayed in OTP App.,Digite o código exibido no aplicativo OTP., +Event Configurations,Configurações de evento, +Event Consumer,Consumidor de Eventos, +Event Consumer Document Type,Tipo de documento do consumidor do evento, +Event Consumer Document Types,Tipos de documento do consumidor do evento, +Event Producer,Produtor de Eventos, +Event Producer Document Type,Tipo de documento do produtor de eventos, +Event Producer Document Types,Tipos de documento do produtor de eventos, +Event Streaming,Fluxo de Eventos, +Event Subscriber,Assinante do Evento, +Event Sync Log,Log de Sincronização de Eventos, +Event Synced with Google Calendar.,Evento sincronizado com o Google Agenda., +Event Update Log,Log de Atualização de Eventos, +Export 1 record,Exportar 1 registro, +Export Errored Rows,Exportar linhas com erro, +Export From,Exportar de, +Export Type,Tipo de exportação, +Export {0} records,Exportar {0} registros, +Failed to connect to the Event Producer site. Retry after some time.,Falha ao conectar ao site do Event Producer. Tente novamente após algum tempo., +Failed to create an Event Consumer or an Event Consumer for the current site is already registered.,Falha ao criar um Consumidor de Eventos ou Consumidor de Eventos para o site atual já está registrado., +Failure,Falha, +Fetching default Global Search documents.,Buscando documentos padrão da Pesquisa Global., +Fetching posts...,Buscando postagens ..., +Field Mapping,Mapeamento de Campo, +Field To Check,Campo a verificar, +File Information,Informações do arquivo, +Filter By,Filtrar por, +Filtered Records,Registros Filtrados, +Filters applied for {0},Filtros aplicados para {0}, +Finished,Acabado, +First,Primeiro, +For Document Event,Para evento de documento, +"For more information, click here.","Para mais informações, clique aqui .", +"For more information, {0}.","Para mais informações, {0}.", +"For performance, only the first 100 rows were processed.","Para desempenho, apenas as primeiras 100 linhas foram processadas.", +Form URL-Encoded,Codificado em URL do formulário, +Frequently Visited Links,Links visitados frequentemente, +From Date,Data De, +From User,Do Usuário, +Global Search DocType,DocType de pesquisa global, +Global Search Document Types Reset.,Redefinir tipos de documentos de pesquisa global., +Global Search Settings,Configurações globais de pesquisa, +Global Shortcuts,Atalhos Globais, +Go,Ir, +Go to next record,Vai para o próximo registro, +Go to previous record,Ir para o registro anterior, +Google API Settings.,Configurações da API do Google., +Google Calendar,Agenda do Google, +"Google Calendar - Could not create Calendar for {0}, error code {1}.","Google Agenda - Não foi possível criar a Agenda para {0}, código de erro {1}.", +"Google Calendar - Could not delete Event {0} from Google Calendar, error code {1}.","Google Agenda - Não foi possível excluir o Evento {0} do Google Agenda, código de erro {1}.", +"Google Calendar - Could not fetch event from Google Calendar, error code {0}.","Google Agenda - Não foi possível buscar o evento no Google Agenda, código de erro {0}.", +"Google Calendar - Could not insert contact in Google Contacts {0}, error code {1}.","Google Agenda - Não foi possível inserir o contato nos Contatos do Google {0}, código de erro {1}.", +"Google Calendar - Could not insert event in Google Calendar {0}, error code {1}.","Google Agenda - Não foi possível inserir o evento no Google Agenda {0}, código de erro {1}.", +"Google Calendar - Could not update Event {0} in Google Calendar, error code {1}.","Google Agenda - Não foi possível atualizar o Evento {0} no Google Agenda, código de erro {1}.", +Google Calendar Event ID,ID do evento do Google Agenda, +Google Calendar Integration.,Integração com o Google Agenda., +Google Calendar has been configured.,O Google Agenda foi configurado., +Google Contacts,Contatos do Google, +"Google Contacts - Could not sync contacts from Google Contacts {0}, error code {1}.","Contatos do Google - Não foi possível sincronizar contatos dos Contatos do Google {0}, código de erro {1}.", +"Google Contacts - Could not update contact in Google Contacts {0}, error code {1}.","Contatos do Google - Não foi possível atualizar o contato nos Contatos do Google {0}, código de erro {1}.", +Google Contacts Id,ID de contatos do Google, +Google Contacts Integration is disabled.,A integração de contatos do Google está desativada., +Google Contacts Integration.,Integração de Contatos do Google., +Google Contacts has been configured.,O Contatos do Google foi configurado., +Google Drive,Google Drive, +Google Drive - Could not create folder in Google Drive - Error Code {0},Google Drive - Não foi possível criar a pasta no Google Drive - Código de erro {0}, +Google Drive - Could not find folder in Google Drive - Error Code {0},Google Drive - Não foi possível encontrar a pasta no Google Drive - Código de erro {0}, +Google Drive Backup Successful.,Backup do Google Drive bem-sucedido., +Google Drive Backup.,Backup do Google Drive., +Google Drive Integration.,Integração com o Google Drive., +Google Drive has been configured.,O Google Drive foi configurado., +Google Integration is disabled.,A integração do Google está desativada., +Google Settings,Configurações do Google, +Group By,Agrupar por, +Group By Based On,Agrupar por Com base em, +Group By Type,Agrupar por tipo, +Group By field is required to create a dashboard chart,O campo Agrupar por é necessário para criar um gráfico de dashboard, +HH:mm,HH: mm, +HH:mm:ss,HH: mm: ss, +HOOK-.####,GANCHO-.####, +HTML Page,Página HTML, +Has Mapping,Possui mapeamento, +Hourly Long,Por hora, +"If non-standard port (e.g. POP3: 995/110, IMAP: 993/143)","Se porta não padrão (por exemplo, POP3: 995/110, IMAP: 993/143)", +If the document has different field names on the Producer and Consumer's end check this and set up the Mapping,"Se o documento tiver nomes de campos diferentes no final do produtor e do consumidor, verifique isso e configure o mapeamento", +If this is checked the documents will have the same name as they have on the Event Producer's site,"Se esta opção estiver marcada, os documentos terão o mesmo nome do site do Produtor de Eventos", +Illegal SQL Query,Consulta SQL ilegal, +Import File,Importar arquivo, +Import Log Preview,Visualização do registro de importação, +Import Preview,Visualização de importação, +Import Progress,Progresso da importação, +Import Type,Tipo de Importação, +Import Warnings,Avisos de importação, +"Import template should be of type .csv, .xlsx or .xls","O modelo de importação deve ser do tipo .csv, .xlsx ou .xls", +Import template should contain a Header and atleast one row.,"O modelo de importação deve conter um cabeçalho e, pelo menos, uma linha.", +Importing {0} of {1},Importando {0} de {1}, +"Importing {0} of {1}, {2}","Importando {0} de {1}, {2}", +Include indentation,Incluir recuo, +Incoming Change,Mudança de entrada, +Invalid Filter Value,Valor de filtro inválido, +Invalid URL,URL inválida, +Invalid field name: {0},Nome do campo inválido: {0}, +Invalid file URL. Please contact System Administrator.,URL de arquivo inválido. Entre em contato com o administrador do sistema., +Invalid include path,Caminho de inclusão inválido, +Invalid username or password,nome de usuário ou senha inválidos, +Is Primary,É primário, +Is Primary Mobile,É o celular principal, +Is Primary Phone,É o telefone principal, +Is Tree,É árvore, +JSON Request Body,Corpo da solicitação JSON, +Javascript is disabled on your browser,Javascript está desativado em seu navegador, +Job,Trabalho, +Jump to field,Ir para o campo, +Keyboard Shortcuts,Atalhos do teclado, +LDAP Group,Grupo LDAP, +LDAP Group Field,Campo do Grupo LDAP, +LDAP Group Mapping,Mapeamento do Grupo LDAP, +LDAP Group Mappings,Mapeamentos de grupo LDAP, +LDAP Last Name Field,Campo Sobrenome LDAP, +LDAP Middle Name Field,Campo de nome do meio LDAP, +LDAP Mobile Field,Campo Móvel LDAP, +LDAP Phone Field,Campo de telefone LDAP, +LDAP User Creation and Mapping,Criação e Mapeamento de Usuários LDAP, +Landscape,Panorama, +Last,Último, +Last Backup On,Último backup ativado, +Last Execution,Última Execução, +Last Sync On,Última sincronização em, +Last Update,Última atualização, +Last refreshed,Última atualização, +Link Document Type,Tipo de Documento de Link, +Link Fieldname,Nome do campo do link, +Loading import file...,Carregando arquivo de importação ..., +Local Document Type,Tipo de Documento Local, +Log Data,Dados de log, +Main Section (HTML),Seção Principal (HTML), +Main Section (Markdown),Seção Principal (Remarcação), +"Maintains a Log of all inserts, updates and deletions on Event Producer site for documents that have consumers.","Mantém um log de todas as inserções, atualizações e exclusões no site do Event Producer para documentos que possuem consumidores.", +Maintains a log of every event consumed along with the status of the sync and a Resync button in case sync fails.,"Mantém um log de todos os eventos consumidos, juntamente com o status da sincronização e um botão Resync, caso a sincronização falhe.", +Make all attachments private,Tornar todos os anexos privados, +Mandatory Depends On,Obrigatório Depende, +Map Columns,Colunas do mapa, +Map columns from {0} to fields in {1},Mapeie colunas de {0} para campos em {1}, +Mapping column {0} to field {1},Mapeando a coluna {0} para o campo {1}, +Mark all as Read,Marcar tudo como lido, +Maximum Points,Pontos Máximos, +Maximum points allowed after multiplying points with the multiplier value\n(Note: For no limit leave this field empty or set 0),"Número máximo de pontos permitido após a multiplicação de pontos pelo valor multiplicador (Nota: para sem limite, deixe este campo vazio ou defina 0)", +Me,Eu, +Mention,Menção, +Modules,módulos, +Monthly Long,Mensalmente Longo, +Naming Series,Série de Atrib. de Nomes, +Navigate Home,Navegue para casa, +Navigate list down,Navegar pela lista, +Navigate list up,Navegar pela lista, +New Notification,Nova notificação, +New {0}: {1},Novo {0}: {1}, +Newsletter should have atleast one recipient,O boletim deve ter pelo menos um destinatário, +No Events Today,Hoje não há eventos, +No Google Calendar Event to sync.,Nenhum evento do Google Agenda para sincronizar., +No More Activity,Não há mais atividade, +No Name Specified for {0},Nenhum nome especificado para {0}, +No Upcoming Events,Não há eventos futuros, +No activity,Nenhuma atividade, +No conditions provided,Nenhuma condição fornecida, +No contacts linked to document,Nenhum contato vinculado ao documento, +No data to export,Nenhum dado para exportar, +No documents found tagged with {0},Nenhum documento encontrado marcado com {0}, +No failed logs,Nenhum registro com falha, +No filters found,Nenhum filtro encontrado, +No more items to display,Não há mais itens para exibir, +No more posts,Não há mais postagens, +No new Google Contacts synced.,Nenhum novo Google Contacts sincronizado., +No pending or current jobs for this site,Não há trabalhos pendentes ou atuais para este site, +No posts yet,Ainda não há posts, +No records will be exported,Nenhum registro será exportado, +No results found for {0} in Global Search,Nenhum resultado encontrado para {0} na Pesquisa Global, +No user found,Nenhum usuário encontrado, +Not Specified,Não especificado, +Notification Log,Registro de Notificação, +Notification Settings,Configurações de notificação, +Notification Subscribed Document,Documento assinado de notificação, +Notifications Disabled,Notificações desativadas, +Number of Groups,Número de Grupos, +OAuth Client ID,ID do cliente OAuth, +OTP setup using OTP App was not completed. Please contact Administrator.,A configuração do OTP usando o aplicativo OTP não foi concluída. Entre em contato com o administrador., +Only one {0} can be set as primary.,Somente um {0} pode ser definido como primário., +Open Awesomebar,Open Awesomebar, +Open Chat,Abrir Chat, +Open Documents,Documentos abertos, +Open Help,Abra a Ajuda, +Open Settings,Abrir configurações, +Open list item,Abrir item da lista, +Organizational Unit for Users,Unidade Organizacional para Usuários, +Page Shortcuts,Atalhos de página, +Parent Field (Tree),Campo pai (árvore), +Parent Field must be a valid fieldname,O campo pai deve ser um nome de campo válido, +Pin Globally,Fixar globalmente, +Places,Lugares, +Please check the filter values set for Dashboard Chart: {},Verifique os valores de filtro definidos para o gráfico do dashboard: {}, +Please enable pop-ups in your browser,Por favor habilite pop-ups em seu navegador, +Please find attached {0}: {1},"Por favor, encontre em anexo {0}: {1}", +Please select applicable Doctypes,Por favor selecione Doctypes aplicáveis, +Portrait,Retrato, +Press Alt Key to trigger additional shortcuts in Menu and Sidebar,Pressione a tecla Alt para acionar atalhos adicionais no menu e na barra lateral, +Print Settings...,Configurações de impressão ..., +Producer Document Name,Nome do Documento do Produtor, +Producer URL,URL do produtor, +Property Depends On,Propriedade depende, +Pull from Google Calendar,Puxe do Google Agenda, +Pull from Google Contacts,Pull dos Contatos do Google, +Pulled from Google Calendar,Extraído do Google Agenda, +Pulled from Google Contacts,Extraído dos Contatos do Google, +Push to Google Calendar,Enviar para o Google Agenda, +Push to Google Contacts,Enviar para os Contatos do Google, +Queue / Worker,Fila / Trabalhador, +RAW Information Log,Registro de informações RAW, +Raw Printing Settings...,Configurações de impressão bruta ..., +Read Only Depends On,Somente leitura depende, +Recent Activity,Atividade recente, +Reference document has been cancelled,O documento de referência foi cancelado, +Reload File,Recarregar arquivo, +Remote Document Type,Tipo de documento remoto, +"Renamed files and replaced code in controllers, please check!","Renomeado arquivos e substituído o código em controladores, por favor, verifique!", +Repeat on Last Day of the Month,Repetir no último dia do mês, +Repeats {0},Repete {0}, +Report Information,Informações do Relatório, +Report with more than 10 columns looks better in Landscape mode.,Relatório com mais de 10 colunas parece melhor no modo Paisagem., +Request Structure,Estrutura da solicitação, +Restricted,Restrito, +Restrictions,Restrições, +Resync,Ressincronizar, +Row Number,Número da linha, +Row {0},Linha {0}, +Run Jobs only Daily if Inactive For (Days),Executar trabalhos apenas diariamente se inativo por (dias), +SMS was not sent. Please contact Administrator.,O SMS não foi enviado. Entre em contato com o administrador., +Saved Successfully,Salvo com sucesso, +Scheduled Job,Trabalho agendado, +Scheduled Job Log,Registro de trabalho agendado, +Scheduled Job Type,Tipo de trabalho agendado, +Scheduler Inactive,Agendador inativo, +Scheduler is inactive. Cannot import data.,O agendador está inativo. Não é possível importar dados., +Script Manager,Gerenciador de scripts, +Script Type,Tipo de Script, +Search Priorities,Prioridades de pesquisa, +Search Source Text,Texto de origem da pesquisa, +Search by filename or extension,Pesquisar por nome de arquivo ou extensão, +Select Date Range,Selecionar período, +Select Field,Selecione o campo, +Select Field...,Selecionar campo ..., +Select Filters,Selecione Filtros, +Select Google Calendar to which event should be synced.,Selecione Google Agenda com o qual o evento deve ser sincronizado., +Select Google Contacts to which contact should be synced.,Selecione Contatos do Google aos quais o contato deve ser sincronizado., +Select Group By...,Selecione Agrupar por ..., +Select Mandatory,Selecione Obrigatório, +Select atleast 2 actions,Selecione pelo menos 2 ações, +Select list item,Selecione o item da lista, +Select multiple list items,Selecione vários itens da lista, +Send an email to {0} to link it here,Envie um email para {0} para vinculá-lo aqui, +Server Action,Ação do Servidor, +Server Script,Script de Servidor, +Session Default,Default da Sessão, +Session Default Settings,Configurações padrão da sessão, +Session Defaults,Padrões de Sessão, +Session Defaults Saved,Padrões de sessão salvos, +Set as Default Theme,Definir como tema padrão, +Setting up Global Search documents.,Configurando documentos de Pesquisa Global., +Show Document,Mostrar documento, +Show Failed Logs,Mostrar logs com falha, +Show Keyboard Shortcuts,Mostrar atalhos de teclado, +Show More Activity,Mostrar mais atividade, +Show Traceback,Mostrar Traceback, +Show Warnings,Mostrar avisos, +Showing only first {0} rows out of {1},Mostrando apenas {0} primeiras linhas de {1}, +"Simple Python Expression, Example: Status in (""Invalid"")","Expressão Python simples, exemplo: status em ("inválido")", +Skipping Untitled Column,Ignorando coluna sem título, +Skipping column {0},Ignorando a coluna {0}, +Social Home,Social Home, +Some columns might get cut off when printing to PDF. Try to keep number of columns under 10.,Algumas colunas podem ser cortadas ao imprimir em PDF. Tente manter o número de colunas abaixo de 10., +Something went wrong during the token generation. Click on {0} to generate a new one.,Algo deu errado durante a geração do token. Clique em {0} para gerar um novo., +Submit After Import,Enviar após importação, +Submitting...,Enviando ..., +Success! You are good to go 👍,Sucesso! Você é bom para ir 👍, +Successful Transactions,Transações bem-sucedidas, +Successfully Submitted!,Submetido com sucesso!, +Successfully imported {0} record.,Registro {0} importado com sucesso., +Successfully imported {0} records.,Registros {0} importados com sucesso., +Successfully updated {0} record.,Registro {0} atualizado com sucesso., +Successfully updated {0} records.,Registros {0} atualizados com sucesso., +Sync Calendar,Sincronizar Calendário, +Sync Contacts,Sincronizar contatos, +Sync with Google Calendar,Sincronize com o Google Agenda, +Sync with Google Contacts,Sincronizar com os contatos do Google, +Synced,Sincronizado, +Syncing,Sincronizando, +Syncing {0} of {1},Sincronizando {0} de {1}, +Tag Link,Tag Link, +Take Backup,Fazer backup, +Template Error,Erro de modelo, +Template Options,Opções de modelo, +Template Warnings,Avisos do modelo, +The Auto Repeat for this document has been disabled.,A repetição automática para este documento foi desativada., +The following records needs to be created before we can import your file.,Os seguintes registros precisam ser criados antes que possamos importar seu arquivo., +The mapping configuration between two doctypes.,A configuração de mapeamento entre dois doctypes., +The site which is consuming your events.,O site que está consumindo seus eventos., +The site you want to subscribe to for consuming events.,O site que você deseja assinar para consumir eventos., +The webhook will be triggered if this expression is true,O webhook será acionado se esta expressão for verdadeira, +The {0} is already on auto repeat {1},O {0} já está em repetição automática {1}, +There are some linked records which needs to be created before we can import your file. Do you want to create the following missing records automatically?,Existem alguns registros vinculados que precisam ser criados antes que possamos importar seu arquivo. Deseja criar os seguintes registros ausentes automaticamente?, +There should be atleast one row for the following tables: {0},Deve haver pelo menos uma linha para as seguintes tabelas: {0}, +There should be atleast one row for {0} table,Deve haver pelo menos uma linha para a tabela {0}, +This action is only allowed for {},Esta ação é permitida apenas para {}, +This cannot be undone,Isto não pode ser desfeito, +Time Format,Formato da hora, +Time series based on is required to create a dashboard chart,As séries cronológicas baseadas em são necessárias para criar um gráfico de dashboard, +Time {0} must be in format: {1},A hora {0} deve estar no formato: {1}, +"To configure Auto Repeat, enable ""Allow Auto Repeat"" from {0}.","Para configurar a repetição automática, ative "Permitir repetição automática" de {0}.", +To enable it follow the instructions in the following link: {0},"Para habilitá-lo, siga as instruções no seguinte link: {0}", +"To use Google Calendar, enable {0}.","Para usar o Google Agenda, ative {0}.", +"To use Google Contacts, enable {0}.","Para usar os Contatos do Google, ative {0}.", +"To use Google Drive, enable {0}.","Para usar o Google Drive, ative {0}.", +Today's Events,Eventos de hoje, +Toggle Public/Private,Alternar Público / Privado, +Tracks milestones on the lifecycle of a document if it undergoes multiple stages.,Rastreia marcos no ciclo de vida de um documento se ele passar por vários estágios., +Tree structures are implemented using Nested Set,As estruturas de árvore são implementadas usando o Conjunto Aninhado, +Trigger Primary Action,Ação principal do acionador, +URL for documentation or help,URL para documentação ou ajuda, +URL must start with 'http://' or 'https://',O URL deve começar com "http: //" ou "https: //", +Unchanged,Inalterado, +Unpin,Soltar, +Untitled Column,Coluna sem título, +Untranslated,Não traduzido, +Upcoming Events,próximos eventos, +Update Existing Records,Atualizar registros existentes, +Update Type,Tipo de atualização, +Updated To A New Version 🎉,Atualizado para uma nova versão 🎉, +"Updating {0} of {1}, {2}","Atualizando {0} de {1}, {2}", +Upload file,Subir arquivo, +Upload {0} files,Carregar {0} arquivos, +Uploaded To Google Drive,Carregado no Google Drive, +Uploaded successfully,Carregado com sucesso, +Uploading {0} of {1},Fazendo upload de {0} de {1}, +Use SSL for Outgoing,Use SSL para saída, +Use Same Name,Usar o mesmo nome, +Used For Google Maps Integration.,Usado para integração com o Google Maps., +User ID Property,Propriedade de ID do usuário, +User Profile,Perfil de Usuário, +User Settings,Configurações do Usuário, +User does not exist,Usuário não existe, +User {0} has requested for data deletion,O usuário {0} solicitou a exclusão de dados, +Users assigned to the reference document will get points.,Os usuários atribuídos ao documento de referência receberão pontos., +Value must be one of {0},O valor deve ser um dos {0}, +Value {0} missing for {1},Valor {0} ausente para {1}, +Verification,Verificação, +Verification Code,Código de verificação, +Verification code email not sent. Please contact Administrator.,E-mail do código de verificação não enviado. Entre em contato com o administrador., +Verified,Verificado, +Verifier,Verificador, +View Full Log,Visualizar log completo, +"View Log of all print, download and export events","Visualizar o log de todos os eventos de impressão, download e exportação", +Visit Web Page,Visitar página da Web, +Webhook Secret,Segredo do Webhook, +Webhook Security,Segurança Webhook, +Webhook Trigger,Gatilho Webhook, +Weekly Long,Semanalmente Longo, +"When enabled this will allow guests to upload files to your application, You can enable this if you wish to collect files from user without having them to log in, for example in job applications web form.","Quando ativado, isso permitirá que os convidados façam upload de arquivos para o seu aplicativo. Você pode habilitá-lo se desejar coletar arquivos do usuário sem que eles façam login, por exemplo, no formulário da Web de pedidos de emprego.", +Will run scheduled jobs only once a day for inactive sites. Default 4 days if set to 0.,"Executará trabalhos agendados apenas uma vez por dia para sites inativos. O padrão é 4 dias, se definido como 0.", +Workflow Status,Status do fluxo de trabalho, +You are not allowed to export {} doctype,Você não tem permissão para exportar {} doctype, +You can try changing the filters of your report.,Você pode tentar alterar os filtros do seu relatório., +You do not have permissions to cancel all linked documents.,Você não tem permissão para cancelar todos os documentos vinculados., +You need to create these first: ,Você precisa criar estes primeiro:, +You need to enable JavaScript for your app to work.,Você precisa habilitar o JavaScript para que seu aplicativo funcione., +You need to install pycups to use this feature!,Você precisa instalar pycups para usar este recurso!, +Your Target,Seu objetivo, +"browse,","Squeaky toy,", +cancelled this document {0},cancelou este documento {0}, +changed value of {0} {1},valor alterado de {0} {1}, +changed values for {0} {1},valores alterados para {0} {1}, +choose an,escolha um, +empty,vazio, +of,do, +or attach a,ou anexar um, +submitted this document {0},enviou este documento {0}, +"tag name..., e.g. #tag","nome da tag ..., por exemplo, #tag", +uploaded file,arquivo enviado, +via Data Import,via importação de dados, +{0} Google Calendar Events synced.,{0} Eventos do Google Agenda sincronizados., +{0} Google Contacts synced.,{0} Contatos do Google sincronizados., +{0} are mandatory fields,{0} são campos obrigatórios, +{0} are required,{0} são obrigatórios, +{0} assigned a new task {1} {2} to you,{0} atribuiu uma nova tarefa {1} {2} a você, +{0} gained {1} point for {2} {3},{0} ganhou {1} ponto por {2} {3}, +{0} gained {1} points for {2} {3},{0} ganhou {1} pontos por {2} {3}, +{0} has no versions tracked.,{0} não possui versões controladas., +{0} is not a valid report format. Report format should one of the following {1},{0} não é um formato de relatório válido. O formato do relatório deve ser um dos seguintes {1}, +{0} mentioned you in a comment in {1} {2},{0} fez referência a você em um comentário em {1} {2}, +{0} of {1} ({2} rows with children),{0} de {1} ({2} linhas com crianças), +{0} records will be exported,{0} registros serão exportados, +{0} shared a document {1} {2} with you,{0} compartilhou um documento {1} {2} com você, +{0} should not be same as {1},{0} não deve ser o mesmo que {1}, +{0} translations pending,{0} traduções pendentes, +{0} {1} is linked with the following submitted documents: {2},{0} {1} está vinculado aos seguintes documentos enviados: {2}, +"{0}: Failed to attach new recurring document. To enable attaching document in the auto repeat notification email, enable {1} in Print Settings","{0}: falha ao anexar novo documento recorrente. Para ativar o anexo de documento no e-mail de notificação de repetição automática, ative {1} em Configurações de impressão", +{0}: Fieldname cannot be one of {1},{0}: o nome do campo não pode ser um dos {1}, +{} Complete,{} Completo, +← Back to upload files,← Voltar para upload de arquivos, +Activity,Atividade, +Add / Manage Email Accounts.,Adicionar / Gerenciar Contas de Email., +Add Child,Adicionar Sub-item, +Add Multiple,Adicionar Múltiplos, +Add Participants,Adicione participantes, +Added {0} ({1}),Adicionado {0} ({1}), +Address Line 1,Endereço, +Addresses,Endereços, +All,Todos, +Brand,Marca, +Browse,Pesquisar, +Cancelled,Cancelado, +Chart,Gráfico, +Close,Fechar, +Communication,Comunicação, +Compact Item Print,Imprimir item no formato compacto, +Company,Empresa, +Complete,Concluído, +Completed,Concluído, +Continue,Continuar, +Country,País, +Creating {0},Criando {0}, +Currency,Moeda, +Customize,Personalizar, +Daily,Diário, +Date,Data, +Dear,Caro, +Default,Padrão, +Delete,Excluir, +Description,Descrição, +Designation,Designação, +Disabled,Desativado, +Doctype,Doctype, +Download Template,Baixar Modelo, +Dr,Dr, +Due Date,Data de Vencimento, +Duplicate,Duplicar, +Edit Profile,Editar Perfil, +Email,Email, +End Time,Horário de Término, +Enter Value,Digite o Valor, +Entity Type,Tipo de entidade, +Error,Erro, +Expired,Expirado, +Export,Exportar, +Export not allowed. You need {0} role to export.,Exportação não é permitida. Você precisa da função {0} para exportar., +Fetching...,Buscando ..., +Field,Campo, +File Manager,Gestor de Arquivos, +Filters,Filtros, +Get Items,Obter Itens, +Goal,Meta, +Group,Grupo, +Group Node,Grupo de Nós, +Help,Ajuda, +Help Article,Artigo de Ajuda, +Home,Início, +Import Data from CSV / Excel files.,Importar dados de arquivos CSV / Excel., +In Progress,Em progresso, +Intermediate,Intermediário, +Invite as User,Convidar como Usuário, +"It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Parece que há um problema com a configuração de distribuição do servidor. Em caso de falha, o valor será reembolsado em sua conta.", +Loading...,Carregando..., +Location,Localização, +Looks like someone sent you to an incomplete URL. Please ask them to look into it.,"Parece que alguém lhe enviou a um URL incompleta. Por favor, pedir-lhes para olhar para ele.", +Master,Cadastro, +Message,mensagem, +Missing Values Required,Faltando valores obrigatórios, +Mobile No,Telefone Celular, +Month,Mês, +Name,Nome, +Newsletter,Newsletter, +Not Allowed,Não Desejados, +Note,Nota, +Offline,Offline, +Open,Abrir, +Page {0} of {1},Página {0} de {1}, +Pay,Pagar, +Pending,Pendente, +Phone,Telefone, +Please click on the following link to set your new password,"Por favor, clique no link a seguir para definir a sua nova senha", +Please select another payment method. Stripe does not support transactions in currency '{0}',Selecione outro método de pagamento. Stripe não suporta transações em moeda '{0}', +Please specify,"Por favor, especifique", +Printing,Impressão, +Priority,Prioridade, +Project,Projeto, +Quarterly,Trimestralmente, +Queued,Em Fila, +Quick Entry,Entrada Rápida, +Reason,Motivo, +Refreshing,Atualizando, +Rename,Renomear, +Reset,Redefinir, +Review,Reveja, +Room,Quarto, +Room Type,Tipo de Quarto, +Save,Salvar, +Search results for,Buscar resultados para, +Select All,Selecionar Tudo, +Send,Enviar, +Sending,Enviando, +Server Error,Erro de Servidor, +Set,Definir, +Setup,Configuração, +Setup Wizard,Assistente de Configuração, +Size,Tamanho, +Sr,Sr, +Start,Iniciar, +Start Time,Horário de Início, +Status,Status, +Submitted,Enviado, +Tag,Tag, +Template,Modelo, +Thursday,Quinta-feira, +Title,Título, +Total,Total, +Totals,Totais, +Tuesday,Terça-feira, +Type,Tipo, +Update,Atualizar, +User {0} is disabled,Usuário {0} está desativado, +Users and Permissions,Usuários e Permissões, +Warehouse,Armazém, +Welcome to {0},Bem-vindo ao {0}, +Year,Ano, +Yearly,Anual, +You,Você, +You can also copy-paste this link in your browser,Você também pode copiar e colar este link no seu navegador, +and,e, +{0} Name,{0} Nome, +{0} is required,{0} é necessário, +ALL,Tudo, +Attach File,Anexar Arquivo, +Barcode,Código de barras, +Beginning with,Começando com, +Bold,Negrito, +CANCELLED,CANCELADO, +Calendar,Calendário, +Center,Centro, +Clear,claro, +Comment,Comente, +Comments,Comentários, +DRAFT,Rascunho, +Dashboard,Dashboard, +DocType,DocType, +Download,Baixar, +EMail,Email, +Edit in Full Page,Editar em página completa, +Email Inbox,Caixa de Entrada, +File,Arquivo, +Forward,Frente, +Icon,Ícone, +In,Em, +Inbox,Caixa de Entrada, +Insert New Records,Inserir novos registros, +JavaScript,Javascript, +LDAP Settings,Configurações LDAP, +Left,Saiu, +Like,Parecido, +Link,Link, +Logged in,Logado, +New,Novo, +Not Found,Não encontrado, +Not Like,Não Parecido, +Notify by Email,Notificar por email, +Now,Agora, +Off,Desligado, +One of,Um dos, +Page,Página, +Print,Impressão, +Reference Name,Nome de referencia, +Refresh,Atualizar, +Repeat,Repetir, +Right,Direita, +Roles HTML,Funções HTML, +Scheduled To Send,Programado para enviar, +Search Results for ,Resultados da busca por, +Send Notification To,Enviar Notificação para, +Success,Sucesso, +Tags,Tags, +Time,Tempo, +Updated Successfully,Atualizado com sucesso, +Upload,Enviar, +User ,Usuário , +Value,Valor, +Web Link,Link da web, +Your Email Address,Seu endereço de email, +Desktop,Área de trabalho, +Usage Info,Informações de Uso, +Download Backups,Download de Backups, +Recorder,Gravador, +Role Permissions Manager,Gestor de Permissões por Função, +Translation Tool,Ferramenta de tradução, +Awaiting password,Aguardando Senha, +Current status,Status atual, +Download template,Baixar Modelo, +Edit in full page,Editar em página completa, +Email Id,Email ID, +Email address,Endereço de Email, +Ends on,Termina em, +Half-yearly,Semestralmente, +Hidden,Escondido, +Javascript,Javascript, +Ldap settings,Configurações LDAP, +Mobile number,Telefone Celular, +Mx,Mx, +No,Não, +Not found,Não encontrado, +Notes:,Notas:, +Notify by email,Notificar por Email, +Permitted Documents For User,Documentos Permitidos para Usuário, +Reference Docname,Nome do Documento de Referência, +Reference Doctype,DocType de Referência, +Reference name,Nome de Referência, +Roles Html,Funções HTML, +Row #,Linha #, +Scheduled to send,Programado para enviar, +Select Doctype,Selecione o DocType, +Send Email for Successful backup,Enviar email para backup bem-sucedido, +Sign up,inscrever-se, +Time format,Formato da hora, +Upload failed,Upload falhou, +User Id,ID de Usuário, +Yes,sim, +Your email address,Seu endereço de email, +added,adicionado, +added {0},Adicionado {0}, +barcode,Código de barras, +beginning with,Começando com, +blue,azul, +bold,negrito, +book,livro, +calendar,calendário, +certificate,certificado, +check,Verificar, +clear,limpar, +comment,Comentário, +comments,comentários, +created,Criado, +danger,Perigo, +dashboard,dashboard, +download,Baixar, +edit,editar, +email inbox,Caixa de Entrada, +file,arquivo, +filter,filtro, +flag,bandeira, +font,fonte, +forward,para a frente, +green,verde, +home,casa, +icon,ícone, +inbox,Caixa de Entrada, +like,Parecido, +link,Link, +list,Lista, +lock,trancar, +logged in,Logado, +message,Mensagem, +module,módulo, +move,mover, +music,música, +new,Novo, +now,agora, +off,fora, +one of,um dos, +orange,laranja, +page,página, +print,imprimir, +purple,roxo, +random,aleatório, +red,vermelho, +refresh,atualizar, +remove,remover, +response,resposta, +search,procurar, +share,ação, +stop,Parar, +success,sucesso, +tag,tag, +tags,tags, +tasks,tarefas, +time,tempo, +trash,lixo, +upload,upload, +user,usuário, +value,valor, +web link,link da Web, +yellow,amarelo, +Not permitted,Não permitido, +Add Chart to Dashboard,Adicionar gráfico ao Dashboard, +Add to Dashboard,Adicionar ao Dashboard, +Google Translation,Tradução do Google, +Important,Importante, +No Filters Set,Nenhum conjunto de filtros, +No Records Created,Nenhum registro criado, +Please Set Chart,Defina o gráfico, +Please create chart first,Crie primeiro o gráfico, +"Report has no data, please modify the filters or change the Report Name",O relatório não possui dados. Modifique os filtros ou altere o Nome do relatório., +Select Dashboard,Selecionar Dashboard, +Y Field,Campo Y, +You need to be in developer mode to edit this document,Você precisa estar no modo de desenvolvedor para editar este documento, +Cards,Postais, +Community Contribution,Contribuição da comunidade, +Count Filter,Filtro de contagem, +Dashboard Chart Field,Campo do Gráfico do Dashboard, +Desk Card,Desk Card, +Desk Chart,Desk Chart, +Desk Page,Página da mesa, +Desk Shortcut,Atalho de mesa, +Developer Mode Only,Somente modo desenvolvedor, +Disable User Customization,Desativar personalização do usuário, +For example: {} Open,Por exemplo: {} Abra, +Link Cards,Cartões de ligação, +Link To,Link para, +Onboarding,Onboarding, +Percentage,Percentagem, +Pie,Torta, +Pin To Bottom,Fixar na parte inferior, +Pin To Top,Fixar na parte superior, +Restrict to Domain,Restringir ao domínio, +Shortcuts,Atalhos, +X Field,Campo X, +Y Axis,Eixo Y, +workspace,área de trabalho, +Setup > User,Configuração> Usuário, +Setup > Customize Form,Configuração> Personalizar formulário, +Setup > User Permissions,Configuração> Permissões do Usuário, +"Error connecting to QZ Tray Application...

    You need to have QZ Tray application installed and running, to use the Raw Print feature.

    Click here to Download and install QZ Tray.
    Click here to learn more about Raw Printing.","Erro ao conectar ao aplicativo da bandeja QZ ...

    Você precisa ter o aplicativo QZ Tray instalado e em execução, para usar o recurso Raw Print.

    Clique aqui para baixar e instalar a bandeja QZ .
    Clique aqui para saber mais sobre a impressão em bruto .", +No email account associated with the User. Please add an account under User > Email Inbox.,Nenhuma conta de email associada ao usuário. Adicione uma conta em Usuário> Caixa de entrada de email., +"For comparison, use >5, <10 or =324. For ranges, use 5:10 (for values between 5 & 10).","Para comparação, use> 5, <10 ou = 324. Para intervalos, use 5:10 (para valores entre 5 e 10).", +No default Address Template found. Please create a new one from Setup > Printing and Branding > Address Template.,Nenhum modelo de endereço padrão encontrado. Crie um novo em Configuração> Impressão e identidade visual> Modelo de endereço., +Please setup default Email Account from Setup > Email > Email Account,Configure a Conta de email padrão em Configuração> Email> Conta de email, +Email Account not setup. Please create a new Email Account from Setup > Email > Email Account,Conta de e-mail não configurada. Crie uma nova conta de email em Configuração> Email> Conta de email, +Attach file,Anexar Arquivo, +Contribution Status,Status de contribuição, +Contribution Document Name,Nome do documento de contribuição, +Extends,Estende, +Extends Another Page,Estende outra página, +Please select target language for translation,Selecione o idioma de destino para a tradução, +Select Language,Selecione o idioma, +Confirm Translations,Confirme as traduções, +Contributed Translations,Contribuições de traduções, +Show Tags,Mostrar Tags, +Do not have permission to access {0} bucket.,Não tem permissão para acessar o intervalo {0}., +Allow document creation via Email,Permitir a criação de documentos por e-mail, +Sender Field,Campo Remetente, +Logout All Sessions on Password Reset,Sair de todas as sessões ao redefinir a senha, +Logout From All Devices After Changing Password,Saia de todos os dispositivos após alterar a senha, +Send Notifications For Documents Followed By Me,Enviar notificações para documentos seguidos por mim, +Send Notifications For Email Threads,Enviar notificações para tópicos de email, +Bypass Restricted IP Address Check If Two Factor Auth Enabled,"Ignorar endereço IP restrito, verificar se a autenticação de dois fatores estiver habilitada", +Reset LDAP Password,Redefinir senha LDAP, +Confirm New Password,Confirme a nova senha, +Logout All Sessions,Sair de todas as sessões, +Passwords do not match!,As senhas não coincidem!, +Dashboard Manager,Dashboard Manager, +Dashboard Settings,Configurações do Dashboard, +Chart Configuration,Configuração de Gráfico, +No Permitted Charts on this Dashboard,Gráficos não permitidos neste Dashboard, +No Permitted Charts,Gráficos não permitidos, +Reset Chart,Reiniciar gráfico, +via {0},via {0}, +{0} is not a valid Phone Number,{0} não é um número de telefone válido, +Failed Transactions,Transações com falha, +Value for field {0} is too long in {1}. Length should be lesser than {2} characters,O valor do campo {0} é muito longo em {1}. O comprimento deve ser menor que {2} caracteres, +Data Too Long,Dados muito longos, +via Notification,via notificação, +Log in to access this page.,Faça login para acessar esta página., +Report Document Error,Reportar erro de documento, +{0} is an invalid Data field.,{0} é um campo de dados inválido., +Only Options allowed for Data field are:,Apenas as opções permitidas para o campo de dados são:, +Select a valid Subject field for creating documents from Email,Selecione um campo de Assunto válido para criar documentos de e-mail, +"Subject Field type should be Data, Text, Long Text, Small Text, Text Editor","O tipo de campo de assunto deve ser Dados, Texto, Texto Longo, Texto Pequeno, Editor de Texto", +Select a valid Sender Field for creating documents from Email,Selecione um campo de remetente válido para criar documentos de e-mail, +Sender Field should have Email in options,O campo do remetente deve ter e-mail nas opções, +Password changed successfully.,Senha alterada com sucesso., +Failed to change password.,Falha ao alterar a senha., +No Entry for the User {0} found within LDAP!,Nenhuma entrada para o usuário {0} encontrada no LDAP!, +No LDAP User found for email: {0},Nenhum usuário LDAP encontrado para e-mail: {0}, +Prepared Report User,Usuário de relatório preparado, +Scheduler Event,Evento Scheduler, +Select Event Type,Selecione o tipo de evento, +Schedule Script,Script de programação, +Duration,Duração, +Donut,Rosquinha, +Custom Options,Opções Personalizadas, +"Ex: ""colors"": [""#d1d8dd"", ""#ff5858""]","Ex: "cores": ["# d1d8dd", "# ff5858"]", +Confirmation Email Template,Modelo de email de confirmação, +Welcome Email Template,Modelo de email de boas-vindas, +Schedule Send,Agendar envio, +Do you really want to send this email newsletter?,Tem certeza de que deseja enviar este boletim informativo por e-mail?, +Advanced Settings,Configurações avançadas, +Disable Comments,Desativar comentários, +Comments on this blog post will be disabled if checked.,Os comentários nesta postagem do blog serão desabilitados se marcados., +CSS Class,Classe CSS, +Full Width,Largura completa, +Page Builder,Construtor de Página, +Page Building Blocks,Blocos de construção de página, +Header and Breadcrumbs,Cabeçalho e breadcrumbs, +Add Custom Tags,Adicionar tags personalizadas, +Web Page Block,Bloco de página da web, +Web Template,Web Template, +Edit Values,Editar Valores, +Web Template Values,Valores de modelo da web, +Add Container,Adicionar recipiente, +Web Page View,Visualização da página da web, +Path,Caminho, +Referrer,Referrer, +Browser,Navegador, +Browser Version,Versão do navegador, +Web Template Field,Campo de modelo da web, +Section,Seção, +Hide,ocultar, +Enable In App Website Tracking,Habilitar acompanhamento de sites no aplicativo, +Enable Google Indexing,Ativar indexação do Google, +"To use Google Indexing, enable Google Settings.","Para usar a indexação do Google, ative as configurações do Google .", +Authorize API Indexing Access,Autorizar acesso de indexação de API, +Indexing Refresh Token,Token de atualização de indexação, +Indexing Authorization Code,Código de autorização de indexação, +Theme Configuration,Configuração do Tema, +Font Properties,Propriedades da fonte, +Button Rounded Corners,Botão Cantos Arredondados, +Button Shadows,Sombras de botão, +Button Gradients,Gradientes de botão, +Light Color,Cor clara, +Stylesheet,Folha de estilo, +Custom SCSS,SCSS personalizado, +Navbar,Navbar, +Source Message,Mensagem Fonte, +Translated Message,Mensagem Traduzida, +Verified By,Verificado Por, +Using this console may allow attackers to impersonate you and steal your information. Do not enter or paste code that you do not understand.,O uso deste console pode permitir que invasores se façam passar por você e roubem suas informações. Não insira nem cole códigos que você não entende., +{0} m,{0} m, +{0} h,{0} h, +{0} d,{0} d, +{0} w,{0} w, +{0} M,{0} mi, +{0} y,{0} a, +yesterday,ontem, +{0} years ago,{0} anos atrás, +New Chart,Novo Gráfico, +New Shortcut,Novo Atalho, +Edit Chart,Editar gráfico, +Edit Shortcut,Editar atalho, +Couldn't Load Desk,Não foi possível carregar a mesa, +"Something went wrong while loading Desk. Please relaod the page. If the problem persists, contact the Administrator","Ocorreu um erro ao carregar o Desk. Por favor, relaod a página . Se o problema persistir, entre em contato com o Administrador", +Customize Workspace,Personalize o Espaço de Trabalho, +Customizations Saved Successfully,Personalizações salvas com sucesso, +Something went wrong while saving customizations,Algo deu errado ao salvar as personalizações, +{} Dashboard,{} Dashboard, +No changes in document,Sem alterações no documento, +by Role,por papel, +Document is only editable by users with role,O documento só pode ser editado por usuários com função, +{0}: Other permission rules may also apply,{0}: Outras regras de permissão também podem ser aplicadas, +{0} Page Views,{0} page views, +Expand,Expandir, +Collapse,Colapso, +"Invalid Bearer token, please provide a valid access token with prefix 'Bearer'.","Token de portador inválido, forneça um token de acesso válido com o prefixo 'Portador'.", +"Failed to decode token, please provide a valid base64-encoded token.","Falha ao decodificar o token, forneça um token codificado em base64 válido.", +"Invalid token, please provide a valid token with prefix 'Basic' or 'Token'.","Token inválido, forneça um token válido com o prefixo 'Básico' ou 'Token'.", +{0} is not a valid Name,{0} não é um nome válido, +Your system is being updated. Please refresh again after a few moments.,Seu sistema está sendo atualizado. Atualize novamente após alguns momentos., +{0} {1}: Submitted Record cannot be deleted. You must {2} Cancel {3} it first.,{0} {1}: O registro enviado não pode ser excluído. Você deve {2} cancelar {3} primeiro., +Invalid naming series (. missing) for {0},Série de nomenclatura inválida (. Ausente) para {0}, +Error has occurred in {0},Ocorreu um erro em {0}, +Status Updated,Status Atualizado, +You can also copy-paste this {0} to your browser,Você também pode copiar e colar isto {0} no seu navegador, +Enabled scheduled execution for script {0},Execução programada ativada para o script {0}, +Scheduled execution for script {0} has updated,A execução agendada para o script {0} foi atualizada, +The Link specified has either been used before or Invalid,O link especificado já foi usado antes ou é inválido, +Options for {0} must be set before setting the default value.,As opções para {0} devem ser definidas antes de definir o valor padrão., +Default value for {0} must be in the list of options.,O valor padrão para {0} deve estar na lista de opções., +Google Indexing has been configured.,A indexação do Google foi configurada., +Allow API Indexing Access,Permitir acesso de indexação de API, +Allow Google Indexing Access,Permitir acesso de indexação do Google, +Custom Documents,Documentos Personalizados, +Could not save customization,Não foi possível salvar a personalização, +Transgender,Transgênero, +Genderqueer,Genderqueer, +Non-Conforming,Não conforme, +Prefer not to say,Prefiro não dizer, +Is Billing Contact,É contato de cobrança, +Address And Contacts,Endereços e Contatos, +Lead Conversion Time,Lead Conversion Time, +Due Date Based On,Data de vencimento baseada em, +Phone Number,Número de telefone, +Linked Documents,Documentos vinculados, +Account SID,SID da conta, +Steps,Passos, +email,email, +Component,Componente, +Subtitle,Subtítulo, +Global Defaults,Padrões Gerais, +Prefix,Prefixo, +Is Public,É público, +This chart will be available to all Users if this is set,Este gráfico estará disponível para todos os usuários se estiver definido, +Number Card,Cartão de Número, +Function,Função, +Minimum,Mínimo, +Maximum,Máximo, +This card will be available to all Users if this is set,Este cartão estará disponível para todos os usuários se estiver definido, +Stats,Estatísticas, +Show Percentage Stats,Mostrar estatísticas percentuais, +Stats Time Interval,Intervalo de tempo das estatísticas, +Show percentage difference according to this time interval,Mostra a diferença percentual de acordo com este intervalo de tempo, +Filters Section,Seção de Filtros, +Number Card Link,Número do link do cartão, +Card,Cartão, +API Access,Acesso API, +Access Key Secret,Segredo da chave de acesso, +S3 Bucket Details,Detalhes do balde S3, +Bucket Name,Nome do intervalo, +Backup Details,Detalhes de backup, +Backup Files,Arquivos de backup, +Backup public and private files along with the database.,Faça backup de arquivos públicos e privados junto com o banco de dados., +Set to 0 for no limit on the number of backups taken,Defina como 0 para não haver limite no número de backups feitos, +Meta Description,Meta Descrição, +Meta Image,Meta Imagem, +Google Snippet Preview,Visualização de snippet do Google, +This is an example Google SERP Preview.,Este é um exemplo de visualização do Google SERP., +Add Gray Background,Adicionar fundo cinza, +Hide Block,Esconder o Bloco, +This Week,Esta semana, +This Month,Este mês, +This Quarter,Este Trimestre, +This Year,Este ano, +All Time,Tempo todo, +Select From Date,Selecione a partir da data, +since yesterday,desde ontem, +since last week,desde a semana passada, +since last month,desde o último mês, +since last year,desde o ano passado, +Show,mostrar, +New Number Card,Novo cartão de número, +Your Shortcuts,Seus Atalhos, +You haven't added any Dashboard Charts or Number Cards yet.,Você ainda não adicionou nenhum gráfico de Dashboard ou cartão numérico., +Click On Customize to add your first widget,Clique em Personalizar para adicionar seu primeiro widget, +Are you sure you want to reset all customizations?,Tem certeza de que deseja redefinir todas as personalizações?, +"Couldn't save, please check the data you have entered","Não foi possível salvar, verifique os dados inseridos", +Validation Error,erro de validação, +"You can only upload JPG, PNG, PDF, or Microsoft documents.","Você só pode fazer upload de documentos JPG, PNG, PDF ou Microsoft.", +Reverting length to {0} for '{1}' in '{2}'. Setting the length as {3} will cause truncation of data.,Revertendo comprimento para {0} para '{1}' em '{2}'. Definir o comprimento como {3} causará o truncamento dos dados., +'{0}' not allowed for type {1} in row {2},'{0}' não permitido para o tipo {1} na linha {2}, +Option {0} for field {1} is not a child table,A opção {0} para o campo {1} não é uma tabela filha, +Invalid Option,Opção Inválida, +Request Body consists of an invalid JSON structure,O corpo da solicitação consiste em uma estrutura JSON inválida, +Invalid JSON,JSON inválido, +Party GSTIN,Festa GSTIN, +GST State,Estado GST, +Andaman and Nicobar Islands,Ilhas Andaman e Nicobar, +Andhra Pradesh,Andhra Pradesh, +Arunachal Pradesh,Arunachal Pradesh, +Assam,Assam, +Bihar,Bihar, +Chandigarh,Chandigarh, +Chhattisgarh,Chhattisgarh, +Dadra and Nagar Haveli,Dadra e Nagar Haveli, +Daman and Diu,Damão e Diu, +Delhi,Délhi, +Goa,Goa, +Gujarat,Gujarat, +Haryana,Haryana, +Himachal Pradesh,Himachal Pradesh, +Jammu and Kashmir,Jammu e Kashmir, +Jharkhand,Jharkhand, +Karnataka,Karnataka, +Kerala,Kerala, +Lakshadweep Islands,Ilhas Lakshadweep, +Madhya Pradesh,Madhya Pradesh, +Maharashtra,Maharashtra, +Manipur,Manipur, +Meghalaya,Meghalaya, +Mizoram,Mizoram, +Nagaland,Nagaland, +Odisha,Odisha, +Other Territory,Outro Território, +Pondicherry,Pondicherry, +Punjab,Punjab, +Rajasthan,Rajasthan, +Sikkim,Sikkim, +Tamil Nadu,Tamil Nadu, +Telangana,Telangana, +Tripura,Tripura, +Uttar Pradesh,Uttar Pradesh, +Uttarakhand,Uttarakhand, +West Bengal,Bengala Ocidental, +GST State Number,Número do estado GST, +Import from Google Sheets,Importar do Planilhas Google, +Must be a publicly accessible Google Sheets URL,Deve ser um URL de planilhas do Google acessível publicamente, +Refresh Google Sheet,Atualizar planilha do Google, +Import File Errors and Warnings,Erros e avisos de importação de arquivos, +"Successfully imported {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.","Importou com êxito {0} registros de {1}. Clique em Exportar Errored Rows, corrija os erros e importe novamente.", +"Successfully imported {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.","Importado com sucesso {0} registro de {1}. Clique em Exportar Errored Rows, corrija os erros e importe novamente.", +"Successfully updated {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.","Atualizado com êxito {0} registros de {1}. Clique em Exportar Errored Rows, corrija os erros e importe novamente.", +"Successfully updated {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.","Atualizado com sucesso {0} registro de {1}. Clique em Exportar Errored Rows, corrija os erros e importe novamente.", +Data Import Legacy,Legado de importação de dados, +Documents restored successfully,Documentos restaurados com sucesso, +Documents that were already restored,Documentos que já foram restaurados, +Documents that failed to restore,Documentos que não foram restaurados, +Document Restoration Summary,Resumo de restauração de documento, +Hide Days,Ocultar dias, +Hide Seconds,Ocultar segundos, +Hide Border,Ocultar borda, +Index Web Pages for Search,Índice de páginas da web para pesquisa, +Action / Route,Ação / Rota, +Document Naming Rule,Regra de Nomenclatura de Documento, +Rule Conditions,Condições da regra, +Digits,Dígitos, +Example: 00001,Exemplo: 00001, +Counter,Contador, +Document Naming Rule Condition,Condição de regra de nomenclatura de documento, +Installed Application,Aplicativo Instalado, +Application Name,Nome da Aplicação, +Application Version,Versão do aplicativo, +Git Branch,Git Branch, +Installed Applications,Aplicativos Instalados, +Navbar Item,Item Navbar, +Item Label,Etiqueta do item, +Item Type,Tipo de item, +Separator,Separador, +Navbar Settings,Configurações da barra de navegação, +Application Logo,Logo do aplicativo, +Logo Width,Largura do logotipo, +Dropdowns,Dropdowns, +Settings Dropdown,Lista suspensa de configurações, +Help Dropdown,Ajuda suspensa, +Query / Script,Consulta / Script, +"Filters will be accessible via filters.

    Send output as result = [result], or for old style data = [columns], [result]","Os filtros estarão acessíveis por meio de filters .

    Envie a saída como result = [result] ou para data = [columns], [result] estilo antigo data = [columns], [result]", +Client Code,Código do cliente, +Report Column,Coluna de Relatório, +Report Filter,Filtro de Relatório, +Wildcard Filter,Filtro Wildcard, +Will add "%" before and after the query,Irá adicionar "%" antes e depois da consulta, +Route: Example "/desk",Rota: Exemplo "/ desk", +Enable Onboarding,Habilitar Onboarding, +Password Reset Link Generation Limit,Limite de geração de link de redefinição de senha, +Hourly rate limit for generating password reset links,Limite de taxa por hora para gerar links de redefinição de senha, +Send document Web View link in email,Enviar link no email para visualizar o documento online, +Enable Auto-deletion of Prepared Reports,Habilitar exclusão automática de relatórios preparados, +Prepared Report Expiry Period (Days),Período de expiração do relatório preparado (dias), +System will automatically delete Prepared Reports after these many days since creation,O sistema excluirá automaticamente os relatórios preparados após esses muitos dias desde a criação, +Package Document Type,Tipo de Documento de Pacote, +Include Attachments,Incluir Anexos, +Overwrite,Sobrescrever, +Package Publish Target,Alvo de publicação de pacote, +Site URL,URL do site, +Package Publish Tool,Ferramenta de publicação de pacotes, +Click on the row for accessing filters.,Clique na linha para acessar os filtros., +Sites,Sites, +Last Deployed On,Última implantação em, +Console Log,Log do console, +"Set Default Options for all charts on this Dashboard (Ex: ""colors"": [""#d1d8dd"", ""#ff5858""])","Defina as opções padrão para todos os gráficos neste Dashboard (Ex: "cores": ["# d1d8dd", "# ff5858"])", +Use Report Chart,Usar gráfico de relatório, +Heatmap,Mapa de calor, +Dynamic Filters,Filtros Dinâmicos, +Dynamic Filters JSON,Filtros dinâmicos JSON, +Set Dynamic Filters,Definir Filtros Dinâmicos, +Click to Set Dynamic Filters,Clique para definir filtros dinâmicos, +Hide Custom DocTypes and Reports,Ocultar tipos de documentos e relatórios personalizados, +Checking this will hide custom doctypes and reports cards in Links section,Marcar isto irá esconder doctypes personalizados e cartões de relatórios na seção Links, +DocType View,Visualização DocType, +Which view of the associated DocType should this shortcut take you to?,Para qual visualização do DocType associado esse atalho deve levar você?, +List View Settings,Configurações de visualização de lista, +Maximum Number of Fields,Número Máximo de Campos, +Module Onboarding,Módulo Onboarding, +System managers are allowed by default,Gerentes de sistema são permitidos por padrão, +Documentation URL,URL de documentação, +Is Complete,Está completo, +Alert,Alerta, +Document Link,Link do Documento, +Attached File,Arquivo anexo, +Attachment Link,Link de Anexo, +Open Reference Document,Documento de Referência Aberto, +Custom Configuration,Configuração Personalizada, +Filters Configuration,Configuração de Filtros, +Dynamic Filters Section,Seção de Filtros Dinâmicos, +Please create Card first,"Por favor, crie o cartão primeiro", +Onboarding Permission,Permissão de integração, +Onboarding Step,Etapa de integração, +Is Mandatory,É mandatório, +Is Skipped,É pulado, +Create Entry,Criar entrada, +Update Settings,Atualizar configurações, +Show Form Tour,Show Form Tour, +View Report,Ver relatório, +Go to Page,Vá para página, +Watch Video,Assistir vídeo, +Show Full Form?,Mostrar formulário completo?, +Show full form instead of a quick entry modal,Mostrar o formulário completo em vez de um modal de entrada rápida, +Report Reference Doctype,Report Reference Doctype, +Report Description,Descrição do relatório, +This will be shown to the user in a dialog after routing to the report,Isso será mostrado ao usuário em uma caixa de diálogo após o roteamento para o relatório, +Example: #Tree/Account,Exemplo: # árvore / conta, +Callback Title,Título de retorno, +Callback Message,Mensagem de retorno, +This will be shown in a modal after routing,Isso será mostrado em um modal após o roteamento, +Validate Field,Validar Campo, +Value to Validate,Valor para Validar, +Use % for any non empty value.,Use% para qualquer valor não vazio., +Video URL,URL do vídeo, +Onboarding Step Map,Mapa de etapas de integração, +Step,Degrau, +System Console,Console do sistema, +Console,Console, +To print output use log(text),"Para imprimir a saída, use o log(text)", +Commit,Comprometer, +Execute Console script,Executar script de console, +Execute,Executar, +Create Contacts from Incoming Emails,Criar contatos de e-mails recebidos, +Inbox User,Usuário da caixa de entrada, +Disabled Auto Reply,Resposta automática desativada, +Schedule Sending,Agendar Envio, +Message (Markdown),Mensagem (Markdown), +Message (HTML),Mensagem (HTML), +Send Attachments,Enviar anexos, +Testing,Testando, +System Notification,Notificação do sistema, +WhatsApp,Whatsapp, +Twilio Number,Número Twilio, +"To use WhatsApp for Business, initialize Twilio Settings.","Para usar o WhatsApp for Business, inicialize as configurações do Twilio .", +"To use Slack Channel, add a Slack Webhook URL.","Para usar o Slack Channel, adicione um URL do Slack Webhook .", +Send System Notification,Enviar Notificação do Sistema, +"If enabled, the notification will show up in the notifications dropdown on the top right corner of the navigation bar.","Se ativada, a notificação aparecerá na lista suspensa de notificações no canto superior direito da barra de navegação.", +Send To All Assignees,Enviar para todos os cessionários, +Receiver By Document Field,Receptor por campo de documento, +Receiver By Role,Receptor por função, +Child Table,Mesa Infantil, +Remote Value Filters,Filtros de valor remoto, +API Key of the user(Event Subscriber) on the producer site,Chave API do usuário (Assinante do Evento) no site do produtor, +API Secret of the user(Event Subscriber) on the producer site,Segredo API do usuário (Assinante do Evento) no site do produtor, +Paytm Settings,Configurações de Paytm, +Merchant Key,Chave do Comerciante, +Staging,Staging, +Industry Type ID,ID do tipo de indústria, +See https://docs.aws.amazon.com/general/latest/gr/s3.html for details.,Consulte https://docs.aws.amazon.com/general/latest/gr/s3.html para obter detalhes., +af-south-1,af-south-1, +ap-east-1,ap-east-1, +eu-south-1,eu-sul-1, +me-south-1,me-south-1, +Twilio Number Group,Grupo de números Twilio, +Twilio Settings,Configurações do Twilio, +Auth Token,Token de autenticação, +Read Time,Tempo de leitura, +in minutes,em minutos, +Featured,Destaque, +Hide CTA,Ocultar CTA, +"Description for listing page, in plain text, only a couple of lines. (max 200 characters)","Descrição da página de listagem, em texto simples, apenas algumas linhas. (máx. 200 caracteres)", +Meta Title,Meta Título, +Enable Social Sharing,Ativar compartilhamento social, +Show CTA in Blog,Mostrar CTA no blog, +CTA,CTA, +CTA Label,Etiqueta CTA, +CTA URL,URL CTA, +Default Portal Home,Página inicial do portal padrão, +Example: "/desk",Exemplo: "/ desk", +Social Link Settings,Configurações de link social, +Social Link Type,Tipo de Link Social, +facebook,Facebook, +linkedin,LinkedIn, +twitter,Twitter, +"If Icon is set, it will be shown instead of Label","Se o ícone estiver definido, ele será mostrado em vez do rótulo", +Apply Document Permissions,Aplicar permissões de documento, +For help see Client Script API and Examples,"Para obter ajuda, consulte Client Script API e exemplos", +Dynamic Route,Rota Dinâmica, +Map route parameters into form variables. Example /project/<name>,Mapeie os parâmetros da rota em variáveis de formulário. Exemplo /project/<name>, +Context Script,Script de Contexto, +"

    Set context before rendering a template. Example:

    \n

    \ncontext.project = frappe.get_doc(""Project"", frappe.form_dict.name)\n
    ","

    Defina o contexto antes de renderizar um modelo. Exemplo:

     context.project = frappe.get_doc("Project", frappe.form_dict.name)
    ", +Title of the page,Título da página, +This title will be used as the title of the webpage as well as in meta tags,"Este título será usado como o título da página da web, bem como nas metatags", +Makes the page public,Torna a página pública, +Checking this will publish the page on your website and it'll be visible to everyone.,Marcar isso publicará a página em seu site e ficará visível para todos., +URL of the page,URL da página, +"This will be automatically generated when you publish the page, you can also enter a route yourself if you wish","Isso será gerado automaticamente quando você publicar a página, você também pode inserir uma rota se desejar", +Content type for building the page,Tipo de conteúdo para construir a página, +"You can select one from the following,","Você pode selecionar um dos seguintes,", +Standard rich text editor with controls,Editor de rich text padrão com controles, +Github flavoured markdown syntax,Sintaxe de marcação com sabor de Github, +HTML with jinja support,HTML com suporte jinja, +Frappe page builder using components,Construtor de páginas Frappe usando componentes, +Checking this will show a text area where you can write custom javascript that will run on this page.,Marcar isto irá mostrar uma área de texto onde você pode escrever um javascript personalizado que será executado nesta página., +Meta title for SEO,Meta título para SEO, +"By default the title is used as meta title, adding a value here will override it.","Por padrão, o título é usado como meta título, adicionar um valor aqui irá substituí-lo.", +"The meta description is an HTML attribute that provides a brief summary of a web page. Search engines such as Google often display the meta description in search results, which can influence click-through rates.","A meta descrição é um atributo HTML que fornece um breve resumo de uma página da web. Mecanismos de pesquisa como o Google geralmente exibem a meta descrição nos resultados da pesquisa, o que pode influenciar as taxas de cliques.", +"The meta image is unique image representing the content of the page. Images for this Card should be at least 280px in width, and at least 150px in height.",A meta imagem é uma imagem única que representa o conteúdo da página. As imagens para este cartão devem ter pelo menos 280 px de largura e pelo menos 150 px de altura., +Add Space on Top,Adicionar espaço no topo, +Add Space on Bottom,Adicionar espaço na parte inferior, +Is Unique,É único, +User Agent,Agente de usuário, +Table Break,Pausa para a mesa, +Hide Login,Ocultar login, +Navbar Template,Modelo Navbar, +Navbar Template Values,Valores de modelo de Navbar, +Call To Action,Apelo à ação, +Call To Action URL,URL de apelo à ação, +Footer Logo,Logotipo do rodapé, +Footer Template,Modelo de rodapé, +Footer Template Values,Valores de modelo de rodapé, +Enable Tracking Page Views,Ativar rastreamento de visualizações de página, +"Checking this will enable tracking page views for blogs, web pages, etc.","Marcar isso permitirá o rastreamento de visualizações de páginas de blogs, páginas da web, etc.", +Disable Signup for your site,Desativar inscrição para seu site, +Check this if you don't want users to sign up for an account on your site. Users won't get desk access unless you explicitly provide it.,Marque esta opção se não quiser que os usuários se inscrevam em uma conta no seu site. Os usuários não terão acesso à mesa a menos que você o forneça explicitamente., +URL to go to on clicking the slideshow image,URL para acessar ao clicar na imagem da apresentação de slides, +Custom Overrides,Substituições personalizadas, +Ignored Apps,Aplicativos ignorados, +Include Theme from Apps,Incluir tema de aplicativos, +Website Theme Ignore App,Aplicativo para ignorar tema do site, +Are you sure you want to save this document?,Tem certeza que deseja salvar este documento?, +Refresh All,Atualize tudo, +"Level 0 is for document level permissions, higher levels for field level permissions.","O nível 0 é para permissões de nível de documento, níveis mais altos para permissões de nível de campo.", +Website Analytics,Análise do site, +d,d,Dias (Campo: Duração) +h,h,Horas (Campo: Duração) +m,m,Minutos (Campo: Duração) +s,s,Segundos (Campo: Duração) +Less,Menos, +Not a valid DocType view:,Não é uma visualização válida de DocType:, +Unknown View,Vista Desconhecida, +Go Back,Volte, +Let's take you back to onboarding,Vamos levá-lo de volta à integração, +Great Job,Bom trabalho, +Looks Great,Parece ótimo, +Looks like you didn't change the value,Parece que você não alterou o valor, +Oops,Opa, +Skip Step,Pular etapa, +"You're doing great, let's take you back to the onboarding page.","Você está indo muito bem, vamos levá-lo de volta à página de integração.", +Good Work 🎉,Bom trabalho 🎉, +Submit this document to complete this step.,Envie este documento para concluir esta etapa., +Great,Ótimo, +You may continue with onboarding,Você pode continuar com a integração, +You seem good to go!,Você parece bom para ir!, +Onboarding Complete,Integração completa, +{0} Settings,{0} Configurações, +{0} Fields,{0} campos, +Reset Fields,Limpar campos, +Select Fields,Selecione os campos, +Warning: Unable to find {0} in any table related to {1},Aviso: Não foi possível encontrar {0} em nenhuma tabela relacionada a {1}, +Tree view is not available for {0},A visualização em árvore não está disponível para {0}, +Create Card,Criar cartão, +Card Label,Etiqueta do cartão, +Reports already in Queue,Relatórios já na fila, +Proceed Anyway,Continue mesmo assim, +Delete and Generate New,Excluir e gerar novo, +1 Report,1 relatório, +{0} ({1}) (1 row mandatory),{0} ({1}) (1 linha obrigatória), +Select Fields To Insert,Selecione os campos para inserir, +Select Fields To Update,Selecione os campos para atualizar, +"This document is already amended, you cannot ammend it again","Este documento já foi alterado, você não pode alterá-lo novamente", +Add to ToDo,Adicionar ao ToDo, +{0} is currently {1},{0} atualmente é {1}, +{0} are currently {1},{0} são atualmente {1}, +Currently Replying,Atualmente respondendo, +created {0},criado em {0}, +Make a call,Faça uma ligação, +Change,Troco,Moedas +Too Many Requests,Muitos pedidos, +"Invalid Authorization headers, add a token with a prefix from one of the following: {0}.","Cabeçalhos de autorização inválidos, adicione um token com um prefixo de um dos seguintes: {0}.", +"Invalid Authorization Type {0}, must be one of {1}.","Tipo de autorização inválido {0}, deve ser um de {1}.", +{} is not a valid date string.,{} não é uma string de data válida., +Invalid Date,Data inválida, +Please select a valid date filter,Selecione um filtro de data válido, +Value {0} must be in the valid duration format: d h m s,O valor {0} deve estar no formato de duração válido: dhms, +Google Sheets URL is invalid or not publicly accessible.,O URL do Planilhas Google é inválido ou não está acessível publicamente., +Google Sheets URL must end with "gid={number}". Copy and paste the URL from the browser address bar and try again.,O URL do Planilhas Google deve terminar com "gid = {número}". Copie e cole o URL da barra de endereço do navegador e tente novamente., +Incorrect URL,URL incorreto, +"{0}" is not a valid Google Sheets URL,"{0}" não é um URL válido do Planilhas Google, +Duplicate Name,Nome duplicado, +Please check the value of "Fetch From" set for field {0},Verifique o valor de "Buscar de" definido para o campo {0}, +Wrong Fetch From value,Valor errado de busca, +A field with the name '{}' already exists in doctype {}.,Já existe um campo com o nome '{}' em doctype {}., +Custom Field {0} is created by the Administrator and can only be deleted through the Administrator account.,O campo personalizado {0} é criado pelo administrador e só pode ser excluído por meio da conta do administrador., +Failed to send {0} Auto Email Report,Falha ao enviar {0} relatório de e-mail automático, +Test email sent to {0},Email de teste enviado para {0}, +Email queued to {0} recipients,Email na fila para {0} destinatários, +Newsletter should have at least one recipient,O boletim deve ter pelo menos um destinatário, +Please enable Twilio settings to send WhatsApp messages,Ative as configurações do Twilio para enviar mensagens do WhatsApp, +"Not allowed to attach {0} document, please enable Allow Print For {0} in Print Settings","Não tem permissão para anexar documento {0}, ative Permitir impressão para {0} nas configurações de impressão", +Signup Disabled,Inscrição Desativada, +Signups have been disabled for this website.,As inscrições foram desativadas para este site., +Open Document,Documento Aberto, +The comment cannot be empty,O comentário não pode estar vazio, +Hourly comment limit reached for: {0},Limite de comentários por hora atingido para: {0}, +Please add a valid comment.,"Por favor, adicione um comentário válido.", +Document {0} Already Restored,Documento {0} já restaurado, +Restoring Deleted Document,Restaurando Documento Excluído, +{function} of {fieldlabel},{função} de {fieldlabel}, +Invalid template file for import,Arquivo de modelo inválido para importação, +Invalid or corrupted content for import,Conteúdo inválido ou corrompido para importação, +Value {0} must in {1} format,O valor {0} deve estar no formato {1}, +{0} is a mandatory field asdadsf,{0} é um campo obrigatório asdadsf, +Could not map column {0} to field {1},Não foi possível mapear a coluna {0} para o campo {1}, +Skipping Duplicate Column {0},Ignorando coluna duplicada {0}, +The column {0} has {1} different date formats. Automatically setting {2} as the default format as it is the most common. Please change other values in this column to this format.,"A coluna {0} possui {1} formatos de data diferentes. Definindo automaticamente {2} como o formato padrão, pois é o mais comum. Por favor, altere outros valores nesta coluna para este formato.", +You have reached the hourly limit for generating password reset links. Please try again later.,"Você atingiu o limite de hora para gerar links de redefinição de senha. Por favor, tente novamente mais tarde.", +Please hide the standard navbar items instead of deleting them,Oculte os itens padrão da barra de navegação em vez de excluí-los, +DocType's name should not start or end with whitespace,O nome de DocType não deve começar ou terminar com um espaço em branco, +File name cannot have {0},O nome do arquivo não pode ter {0}, +{0} is not a valid file url,{0} não é um url de arquivo válido, +Error Attaching File,Erro ao anexar arquivo, +Please generate keys for the Event Subscriber User {0} first.,Gere as chaves para o Usuário Assinante do Evento {0} primeiro., +Please set API Key and Secret on the producer and consumer sites first.,Defina a chave e o segredo da API nos sites do produtor e do consumidor primeiro., +User {0} not found on the producer site,Usuário {0} não encontrado no site do produtor, +Event Subscriber has to be a System Manager.,O Assinante do Evento deve ser um Gerente do Sistema., +Row #{0}: Invalid Local Fieldname,Linha # {0}: Nome de campo local inválido, +Row #{0}: Please set Mapping or Default Value for the field {1} since its a dependency field,"Linha nº {0}: Defina o mapeamento ou valor padrão para o campo {1}, pois é um campo de dependência", +Row #{0}: Please set remote value filters for the field {1} to fetch the unique remote dependency document,Linha nº {0}: Defina filtros de valor remoto para o campo {1} para buscar o documento de dependência remota exclusivo, +Paytm payment gateway settings,Configurações de gateway de pagamento Paytm, +"Company, Fiscal Year and Currency defaults","Padrões da empresa, ano fiscal e moeda", +Razorpay Signature Verification Failed,Falha na verificação da assinatura Razorpay, +Google Drive - Could not locate - {0},Google Drive - Não foi possível localizar - {0}, +"Sync token was invalid and has been resetted, Retry syncing.",O token de sincronização era inválido e foi redefinido. Tente sincronizar novamente., +Please select another payment method. Paytm does not support transactions in currency '{0}',Selecione outro método de pagamento. Paytm não suporta transações na moeda '{0}', +Invalid Account SID or Auth Token.,SID de conta ou token de autenticação inválido., +Please enable twilio settings before sending WhatsApp messages,Ative as configurações do twilio antes de enviar mensagens do WhatsApp, +Delivery Failed,Falha na entrega, +Twilio WhatsApp Message Error,Twilio WhatsApp Message Error, +A featured post must have a cover image,Uma postagem em destaque deve ter uma imagem de capa, +Load More,Carregue mais, +Published on,Publicado em, +Enable developer mode to create a standard Web Template,Habilite o modo de desenvolvedor para criar um modelo da Web padrão, +Was this article helpful?,Esse artigo foi útil?, +Thank you for your feedback!,Obrigado pelo seu feedback!, +New Mention on {0},Nova menção em {0}, +Assignment Update on {0},Atualização de atribuição em {0}, +New Document Shared {0},Novo documento compartilhado {0}, +Energy Point Update on {0},Atualização do Energy Point em {0}, +You cannot create a dashboard chart from single DocTypes,Você não pode criar um gráfico de Dashboard de DocTypes únicos, +Invalid json added in the custom options: {0},JSON inválido adicionado nas opções personalizadas: {0}, +Invalid JSON in card links for {0},JSON inválido em links de cartão para {0}, +Standard Not Set,Padrão não definido, +Please set the following documents in this Dashboard as standard first.,Defina os seguintes documentos neste Dashboard como padrão primeiro., +Shared with the following Users with Read access:{0},Compartilhado com os seguintes usuários com acesso de leitura: {0}, +Already in the following Users ToDo list:{0},Já está na seguinte lista de tarefas de usuários: {0}, +Your assignment on {0} {1} has been removed by {2},Sua tarefa em {0} {1} foi removida por {2}, +Invalid Credentials,Credenciais inválidas, +Print UOM after Quantity,Imprimir UOM após a quantidade, +Uncaught Server Exception,Exceção de servidor não detectado, +There was an error building this page,Ocorreu um erro ao construir esta página, +Hide Traceback,Esconder Traceback, +Value from this field will be set as the due date in the ToDo,O valor deste campo será definido como a data de vencimento no ToDo, +New module created {0},Novo módulo criado em {0}, +"Report has no numeric fields, please change the Report Name","O relatório não tem campos numéricos, altere o nome do relatório", +There are documents which have workflow states that do not exist in this Workflow. It is recommended that you add these states to the Workflow and change their states before removing these states.,Existem documentos com estados de fluxo de trabalho que não existem neste fluxo de trabalho. É recomendável adicionar esses estados ao fluxo de trabalho e alterar seus estados antes de removê-los., +Worflow States Don't Exist,Estados de Worflow não existem, +Save Anyway,Salvar assim mesmo, +Energy Points:,Pontos de energia:, +Review Points:,Pontos de revisão:, +Rank:,Classificação:, +Monthly Rank:,Classificação Mensal:, +Invalid expression set in filter {0} ({1}),Expressão inválida definida no filtro {0} ({1}), +Invalid expression set in filter {0},Expressão inválida definida no filtro {0}, +{0} {1} added to Dashboard {2},{0} {1} adicionado ao Dashboard {2}, +Set Filters for {0},Definir filtros para {0}, +Not permitted to view {0},Não tem permissão para ver {0}, +Camera,câmera, +Invalid filter: {0},Filtro inválido: {0}, +Let's Get Started,Vamos começar, +Reports & Masters,Relatórios e Cadastros, +New {0} {1} added to Dashboard {2},Novo {0} {1} adicionado ao Dashboard {2}, +New {0} {1} created,Novo {0} {1} criado, +New {0} Created,Novo {0} criado, +Invalid "depends_on" expression set in filter {0},Expressão "depends_on" inválida definida no filtro {0}, +{0} Reports,{0} relatórios, +There is {0} with the same filters already in the queue:,Há {0} com os mesmos filtros já na fila:, +There are {0} with the same filters already in the queue:,Existem {0} com os mesmos filtros já na fila:, +Are you sure you want to generate a new report?,Tem certeza de que deseja gerar um novo relatório?, +{0}: {1} vs {2},{0}: {1} vs {2}, +Add a {0} Chart,Adicionar um {0} gráfico, +Currently you have {0} review points,Atualmente você tem {0} pontos de revisão, +{0} is not a valid DocType for Dynamic Link,{0} não é um DocType válido para Dynamic Link, +via Assignment Rule,via regra de atribuição, +Based on Field,Com base no campo, +Assign to the user set in this field,Atribuir ao usuário definido neste campo, +Log Setting User,Usuário de configuração de log, +Log Settings,Configurações de registro, +Error Log Notification,Notificação de log de erros, +Users To Notify,Usuários para notificar, +Log Cleanup,Limpeza de Log, +Clear Error log After,Limpar log de erros após, +Clear Activity Log After,Limpar log de atividades depois, +Clear Email Queue After,Limpar fila de e-mail após, +Please save to edit the template.,Salve para editar o modelo., +Google Analytics Anonymize IP,IP anônimo do Google Analytics, +Incorrect email or password. Please check your login credentials.,Senha ou email incorretos. Verifique suas credenciais de login., +Incorrect Configuration,Configuração Incorreta, +You are not allowed to delete Standard Report,Você não tem permissão para excluir o relatório padrão, +You have unseen {0},Você não viu {0}, +Log cleanup and notification configuration,Limpeza de registro e configuração de notificação, +State/Province,Estado / Província, +Document Actions,Ações do Documento, +Document Links,Links de documentos, +List Settings,Configurações da lista, +Cannot delete standard link. You can hide it if you want,Não é possível excluir o link padrão. Você pode esconder se quiser, +Cannot delete standard action. You can hide it if you want,Não é possível excluir a ação padrão. Você pode esconder se quiser, +Applied On,Aplicado em, +Row Name,Nome da Linha, +For DocType Link / DocType Action,Para DocType Link / DocType Action, +Cannot edit filters for standard charts,Não é possível editar filtros para gráficos padrão, +Event Producer Last Update,Última atualização do produtor de eventos, +Default for 'Check' type of field {0} must be either '0' or '1',Padrão para 'Verificar' o tipo de campo {0} deve ser '0' ou '1', +Non Negative,Não Negativo, +Rules with higher priority number will be applied first.,Regras com número de prioridade mais alta serão aplicadas primeiro., +Open URL in a New Tab,Abrir URL em uma nova guia, +Align Right,Alinhar à direita, +Loading Filters...,Carregando filtros ..., +Count Customizations,Personalizações de contagem, +For Example: {} Open,Por exemplo: {} aberto, +Choose Existing Card or create New Card,Escolha o cartão existente ou crie um novo cartão, +Number Cards,Cartões numéricos, +Function Based On,Função baseada em, +Add Filters,Adicionar Filtros, +Skip,Pular, +Dismiss,Dispensar, +Value cannot be negative for,O valor não pode ser negativo para, +Value cannot be negative for {0}: {1},O valor não pode ser negativo para {0}: {1}, +Negative Value,Valor Negativo, +Authentication failed while receiving emails from Email Account: {0}.,Falha na autenticação ao receber e-mails da conta de e-mail: {0}., +Message from server: {0},Mensagem do servidor: {0}, From 87de35af538a4251749ba5905ae8818dc968dc63 Mon Sep 17 00:00:00 2001 From: Marco <62901164+treasuryesc@users.noreply.github.com> Date: Sun, 26 Jun 2022 19:27:51 -0300 Subject: [PATCH 049/101] Correct pt-BR translations I've sync'ed pt-BR translations based on parent pt.csv file, adapting it for local terms and expressions. --- frappe/translations/pt_br.csv | 3673 +++++++++++++++++++++++++++++++-- 1 file changed, 3508 insertions(+), 165 deletions(-) diff --git a/frappe/translations/pt_br.csv b/frappe/translations/pt_br.csv index 1a3439d9f6..49c16ee634 100644 --- a/frappe/translations/pt_br.csv +++ b/frappe/translations/pt_br.csv @@ -1,574 +1,1426 @@ +A4,A4, +API Endpoint,API Endpoint, API Key,Chave da API, Access Token,Token de Acesso, +Account,Conta, Accounts Manager,Gerente de Contas, Accounts User,Usuário de Contas, +Action,Ação, +Actions,Ações, +Active,Ativo, +Add,Adicionar, +Add Comment,Adicionar Comentário, +Add Row,Adicionar linha, +Address,Endereço, Address Line 2,Complemento, -All Day,O dia todo, +Address Title,Título do Endereço, +Address Type,Tipo de Endereço, +Administrator,Administrador, +All Day,Dia Inteiro, Allow Delete,Permitir Excluir, -Amended From,Corrigido a partir de, -Amount,Total, -Applicable For,Aplicável, -Approval Status,Estado da Aprovação, +Amended From,Alterado De, +Amount,Montante, +Applicable For,Aplicável Para, +Approval Status,Estado de Aprovação, +Assign,Atribuir, Assign To,Atribuir a, -Attachment,Anexos, +Attachment,Anexo, +Attachments,Anexos, +Author,Autor, +Auto Repeat,Repetição Automática, +Base URL,URL Base, Based On,Baseado em, +Beginner,Principiante, Billing,Faturamento, -City/Town,Cidade / Município, +Cancel,Cancelar, +Category,Categoria, +Category Name,Nome da Categoria, +City,Cidade, +City/Town,Cidade/Município, +Client,Cliente, +Client ID,ID do Cliente, +Client Secret,Segredo do cliente, +Closed,Fechado, +Code,Código, +Collapse All,Recolher todos, +Color,Cor, +Company Name,Nome da Empresa, +Condition,Condição, Contact,Contato, -Contact Details,Detalhes do Contato, +Contact Details,Dados de Contato, +Content,Conteúdo, +Content Type,Tipo de Conteúdo, +Create,Criar, Created By,Criado por, +Current,Atual, Custom HTML,HTML Personalizado, -Date Format,Formato da data, -Default Letter Head,Cabeçalho Padrão, +Custom?,Personalizado?, +Date Format,Formato de Data, +Datetime,Data e Hora, +Day,Dia, +Default Letter Head,Cabeçalho de Carta Padrão, +Defaults,Padrões, Delivery Status,Status da Entrega, +Department,Departamento, Details,Detalhes, Document Name,Nome do documento, +Document Status,Status do Documento, +Document Type,tipo de documento, +Domain,Domínio, +Domains,Domínios, +Draft,Rascunho, +Edit,Editar, +Email Account,Conta de Email, +Email Address,Endereço de Email, +Email ID,Email ID, Email Sent,Email enviado, +Email Template,Modelo de email, Enable,Permitir, -Enabled,Habilitado, +Enabled,Ativado, End Date,Data Final, Error Code: {0},Código do Erro: {0}, Error Log,Log de Erro, +Event,Evento, +Expand All,Expandir todos, +Fail,Falha, +Failed,Falhou, +Fax,Fax, +Feedback,Comentários, +Female,Feminino, +Field Name,Nome do Campo, Fieldname,Nome do Campo, -Further nodes can be only created under 'Group' type nodes,"Outros nós só podem ser criados dentro dos nós do tipo ""grupo""", +Fields,Campos, +First Name,Nome, +Frequency,Frequência, +Friday,Sexta-feira, +From,De, +Full,Cheio, +Full Name,Nome Completo, +Further nodes can be only created under 'Group' type nodes,Outros nós só podem ser criados dentro dos nós do tipo 'Grupo', +Gender,Sexo, +GitHub Sync ID,GitHub Sync ID, +Guest,Convidado, Half Day,Meio Período, -Half Yearly,Semestral, -High,Alta, -Image View,Ver Imagem, +Half Yearly,Semestrais, +High,Alto, +Hourly,De hora em hora, +Hub Sync ID,Identificação da Sincronização do Hub, +IP Address,Endereço de IP, +Image,Imagem, +Image View,Visualização de Imagem, +Import Data,Importar dados, Import Log,Log de Importação, -Insert,Insert, +Inactive,Inativo, +Insert,Inserir, +Interests,Juros, +Introduction,Introdução, Is Active,É Ativo, +Is Completed,Está completo, +Is Default,É Padrão, Kanban Board,Painel Kanban, -Label,Etiqueta, -Leaderboard,Ranking de Desempenho, -Letter Head,Timbrado, +Label,Rótulo, +Language Name,Nome do Idioma, +Last Name,Sobrenome, +Leaderboard,Placar, +Letter Head,Cabeçalho de Carta, +Level,Nível, +Limit,Limite, +Log,Registo, Logs,Logs, -Low,Baixa, +Low,Baixo, Maintenance Manager,Gerente de Manutenção, Maintenance User,Usuário da Manutenção, -Medium,Média, +Male,Masculino, +Mandatory,Obrigatório, +Mapping,Mapeamento, +Mapping Type,Tipo de mapeamento, +Medium,Médio, +Meeting,Encontro, +Message Examples,Exemplos de Mensagens, +Method,Método, +Middle Name,Nome do Meio, +Middle Name (Optional),Nome do meio (opcional), +Monday,Segunda-feira, +Monthly,Mensal, +More,Mais, More Information,Mais Informações, +More...,Mais..., +Move,Mover, +My Account,Minha Conta, +New Address,Novo Endereço, New Contact,Novo Contato, Next,Próximo, -No address added yet.,Nenhum endereço adicionado ainda., -No contacts added yet.,Nenhum contato adicionado ainda., +No Data,Sem Dados, +No address added yet.,Ainda não foi adicionado nenhum endereço., +No contacts added yet.,Ainda não foi adicionado nenhum contato., +No items found.,Nenhum item encontrado., +None,Nenhum, +Not Permitted,Não Permitido, Not active,Inativo, +Notes,Notas, +Number,Número, +Online,Online, +Operation,Operação, +Options,Opções, +Other,Outro, Owner,Proprietário, Page Missing or Moved,Página ausente ou mudou, -Payment Gateway,Gateway de pagamento, -Pincode,CEP, +Parameter,Parâmetro, +Password,Senha, +Payment Gateway,Gateway de Pagamento, +Payment Gateway Name,Nome do Gateway de Pagamento, +Payments,Pagamentos, +Period,Período, +Pincode,Pincode, +Plan Name,Nome do Plano, Please enable pop-ups,Por favor habilite os pop-ups, -Please select Company,"Por favor, selecione Empresa", -Please select {0},Por favor selecione {0}, +Please select Company,"Por favor, selecione a Empresa", +Please select {0},"Por favor, selecione {0}", +Please set Email Address,"Por favor, defina o endereço de Email", +Portal,Portal, Portal Settings,Configurações do Portal, +Preview,Pré-visualização, Primary,Primário, +Print Format,Formato de Impressão, Print Settings,Configurações de Impressão, +Print taxes with zero amount,Imprima impostos com montante zero, +Private,Privado, +Property,Propriedade, +Public,Público, +Published,Publicado, Purchase Manager,Gerente de Compras, Purchase Master Manager,Gerente de Cadastros de Compras, Purchase User,Usuário de Compras, -Range,Alcance, +Query Options,Opções de Consulta, +Range,Faixa, Rating,Rating, +Received,Recebido, +Recipients,Destinatários, +Redirect URL,Redirecionar URL, +Reference,Referência, +Reference Date,Data de Referência, +Reference Document,Documento de referência, +Reference Document Type,Referência Tipo de Documento, Reference Owner,Proprietário da Referência, +Reference Type,Tipo de Referência, Refresh Token,Token de Atualização, +Region,Região, +Rejected,Rejeitado, +Reopen,Reabrir, Replied,Respondido, -Report Builder,Criar/Editar Relatório, +Report,Relatório, +Report Builder,Criador de Relatório, +Report Type,Tipo de Relatório, +Reports,Relatórios, +Response,Resposta, +Role,Função, +Route,Rota, Sales Manager,Gerente de Vendas, Sales Master Manager,Gerente de Cadastros de Vendas, Sales User,Usuário de Vendas, -Scan Barcode,Ler Código de Barras, -Scheduled,Agendado, +Salutation,Saudação, +Sample,Amostra, +Saturday,Sábado, +Saved,Salvo, +Scan Barcode,Scan Barcode, +Scheduled,Programado, +Search,Pesquisar, +Secret Key,Chave secreta, Select,Selecionar, -Select DocType,Selecione o DocType, -Service,Manutenção do Veículo, -Set as Default,Definir como padrão, +Select DocType,Selecione DocType, +Send Now,Enviar agora, +Sent,Enviado, +Series {0} already used in {1},Série {0} já usado em {1}, +Service,Serviço, +Set as Default,Definir como Padrão, +Settings,Configurações, Shipping,Expedição, +Short Name,Nome Curto, Slideshow,Apresentação de Slides, -Source,Origem, +Some information is missing,Alguma informação está faltando, +Source,Fonte, +Source Name,Nome da Fonte, +Standard,Padrão, +Start Date,Data de Início, +Start Import,Iniciar importação, +State,Estado, +Stopped,Parado, +Subject,Assunto, Submit,Enviar, +Successful,Bem sucedido, +Summary,Resumo, +Sunday,Domingo, System Manager,Administrador do Sistema, Target,Meta, +Task,Tarefa, +Tax Category,Categoria de imposto, +Test,Teste, +Thank you,Obrigado, +The page you are looking for is missing. This could be because it is moved or there is a typo in the link.,A página que você está procurando não existe. Isto pode ser porque ela foi movido ou se houve um erro de digitação no link., +Timespan,Intervalo de tempo, +To,Para, To Date,Até a Data, +Tools,Ferramentas, +Traceback,Traceback, +URL,URL, Unsubscribed,Inscrição Cancelada, +Use Sandbox,Use Sandbox, +User,Usuário, User ID,ID de Usuário, Users,Usuários, +Validity,Validade, +Warning,Aviso, +Website,Site, Website Manager,Administrador do Site, Website Settings,Configurações do Site, +Wednesday,Quarta-feira, +Week,Semana, +Weekdays,Dias da semana, Weekly,Semanalmente, Welcome email sent,Email de Boas Vindas enviado, Workflow,Fluxo de Trabalho, +You need to be logged in to access this page,Você precisa estar logado para acessar esta página, old_parent,old_parent, -"""Company History""","Histórico da Empresa", -"""Parent"" signifies the parent table in which this row must be added","""Pai"" significa a tabela pai no qual deve ser acrescentado nesta linha", -"""Team Members"" or ""Management""","Membros da Equipe" ou "Gerenciamento", +{0} is mandatory,{0} é obrigatório, + to your browser, para o seu navegador, +"Company History","Histórico da Empresa", +"Parent" signifies the parent table in which this row must be added,"Pai" significa a tabela pai no qual deve ser acrescentado nesta linha, +"Team Members" or "Management","Membros da Equipe" ou "Gerenciamento", +<head> HTML,<head> HTML, +'In Global Search' not allowed for type {0} in row {1},'Na Pesquisa Global' não é permitido para o tipo {0} na linha {1}, 'In List View' not allowed for type {0} in row {1},'Visualização em Lista' não pode ser utilizado para o tipo {0} na linha {1}, 'Recipients' not specified,'Destinatários' não especificado, +(Ctrl + G),(Ctrl + G), ** Failed: {0} to {1}: {2},** Falha: {0} para {1}: {2}, **Currency** Master,**Moeda** Principal, -1 Currency = [?] Fraction\nFor e.g. 1 USD = 100 Cent,"1 Moeda = [?] Fração \n Por exemplo, 1 USD = 100 Centavos", +0 - Draft; 1 - Submitted; 2 - Cancelled,0 - Rascunho; 1 - Enviado; 2 - Cancelado, +0 is highest,0 é maior, +1 Currency = [?] Fraction\nFor e.g. 1 USD = 100 Cent,1 Moeda = [?] Fração\nPor ex: 1 EUR = 100 Cêntimos, +1 comment,1 comentário, 1 hour ago,1 hora atrás, 1 minute ago,1 minuto atrás, +1 month ago,1 mês atrás, +1 year ago,1 ano atrás, ; not allowed in condition,; não permitido na condição, -"

    Default Template

    \n

    Uses Jinja Templating and all the fields of Address (including Custom Fields if any) will be available

    \n
    {{ address_line1 }}<br>\n{% if address_line2 %}{{ address_line2 }}<br>{% endif -%}\n{{ city }}<br>\n{% if state %}{{ state }}<br>{% endif -%}\n{% if pincode %} PIN:  {{ pincode }}<br>{% endif -%}\n{{ country }}<br>\n{% if phone %}Phone: {{ phone }}<br>{% endif -%}\n{% if fax %}Fax: {{ fax }}<br>{% endif -%}\n{% if email_id %}Email: {{ email_id }}<br>{% endif -%}\n
    ","

    Default Template \n

    Jinja Templating e todos os campos de Endereço ( incluindo campos personalizados se houver) estará disponível \n

      {{address_line1}} & lt; br & gt; \n {% if address_line2%} {{address_line2}} & lt; br & gt; { endif% -%} \n {{cidade}} & lt; br & gt; \n {% if estado%} {{estado}} & lt; br & gt; {% endif -%} {% \n se pincode%} PIN: {{pincode}} & lt; br & gt; {% endif -%} \n {{país}} & lt; br & gt; \n {% if telefone%} Telefone: {{telefone}} & lt; br & gt; { % endif -%} \n {% if fax%} Fax: {{fax}} & lt; br & gt; {% endif -%} \n {% if% email_id} Email: {{email_id}} & lt; br & gt ; {endif% -%} \n  

    ", -A Lead with this Email Address should exist,Um lead com este email deve existir, +

    Default Template

    \n

    Uses Jinja Templating and all the fields of Address (including Custom Fields if any) will be available

    \n
    {{ address_line1 }}<br>\n{% if address_line2 %}{{ address_line2 }}<br>{% endif -%}\n{{ city }}<br>\n{% if state %}{{ state }}<br>{% endif -%}\n{% if pincode %} PIN:  {{ pincode }}<br>{% endif -%}\n{{ country }}<br>\n{% if phone %}Phone: {{ phone }}<br>{% endif -%}\n{% if fax %}Fax: {{ fax }}<br>{% endif -%}\n{% if email_id %}Email: {{ email_id }}<br>{% endif -%}\n
    ,"

    Modelo Padrão

    \n

    Utiliza O Modelo Jinja e todos os campos do Endereço (incluindo Campos Personalizados, caso haja) estarão disponíveis

    \n
    {{ address_line1 }}<br>\n{% if address_line2 %}{{ address_line2 }}<br>{% endif -%}\n{{ city }}<br>\n{% if state %}{{ state }}<br>{% endif -%}\n{% if pincode %} PIN:  {{ pincode }}<br>{% endif -%}\n{{ country }}<br>\n{% if phone %}Telefone: {{ phone }}<br>{% endif -%}\n{% if fax %}Fax: {{ fax }}<br>{% endif -%}\n{% if email_id %}Email: {{ email_id }}<br>{% endif -%}\n
    ", +A Lead with this Email Address should exist,Um Lead com este email deve existir, +A list of resources which the Client App will have access to after the user allows it.
    e.g. project,"Uma lista de recursos que o aplicativo cliente terá acesso a depois que o usuário permita.
    por exemplo, do projeto", A log of request errors,Um log de erros de solicitação, A new account has been created for you at {0},Uma nova conta foi criada para você em {0}, A symbol for this currency. For e.g. $,Um símbolo para esta moeda. Por exemplo: R$, A word by itself is easy to guess.,Uma palavra por si só é fácil de adivinhar., +API Endpoint Args,API Endpoint Args, +API Key cannot be regenerated,A chave da API não pode ser regenerada, API Password,Senha da API, API Secret,Segredo da API, API Username,Usuário da API, +ASC,ASC, About Us Settings,Configurações do Quem Somos, About Us Team Member,Sobre Nós - Membros da Equipe, Accept Payment,Aceitar Pagamento, +Access Key ID,ID da chave de acesso, Access Token URL,URL do Token de Acesso, Action Failed,A Ação Falhou, +Action Timeout (Seconds),Tempo Limite de Ação (Segundos), "Actions for workflow (e.g. Approve, Cancel).","Ações para o fluxo de trabalho (por exemplo, Aprovar , Cancelar) .", +Active Domains,Domínios ativos, +Active Sessions,Sessões ativas, Activity Log,Log de Atividade, Activity log of all users.,Registro de atividade de todos os usuários., Add / Manage Email Domains.,Adicionar / Gerenciar Domínios de E-mail., +Add / Update,Adicionar / Atualizar, +Add A New Rule,Adicionar uma Nova Regra, +Add Another Comment,Adicionar Outro Comentário, Add Attachment,Anexar, +Add Column,Adicionar Coluna, +Add Contact,Adicionar contato, +Add Contacts,Adicionar contatos, +Add Filter,Adicionar Filtro, +Add Group,Adicionar grupo, +Add New Permission Rule,Adicionar Nova Regra de Permissão, +Add Review,Adicione uma avaliação, +Add Signature,Adicionar Assinatura, Add Subscribers,Adicionar Inscritos, Add Total Row,Adicionar Linha de Total, Add Unsubscribe Link,Adicionar link para cancelar inscrição, -Add a New Role,Adicionar um Novo Papel, -Add all roles,Adicionar todos os papéis, +Add User Permissions,Adicionar permissões do usuário, +Add a New Role,Adicionar uma Nova Função, +Add a column,Adicionar uma coluna, +Add a comment,Adicionar um comentário, +Add a new section,Adicione uma nova seção, +Add a tag ...,Adicione uma tag ..., +Add all roles,Adicionar todas funções, Add custom forms.,Adicionar formulários personalizados., Add custom javascript to forms.,Adicionar javascript personalizado aos formulários., Add fields to forms.,Adicionar campos nos formulários., +Add meta tags to your web pages,Adicione meta tags às suas páginas da web, +Add script for Child Table,Adicionar script para tabela filho, +Add to table,Adicionar à mesa, Add your own translations,Adicione suas próprias traduções, "Added HTML in the <head> section of the web page, primarily used for website verification and SEO","HTML adicionado na seção <head> da página web, principalmente utilizadas para a verificação do site e SEO", +Added {0},Adicionado {0}, Adding System Manager to this User as there must be atleast one System Manager,Adicionando este usuário como System Manager pois deve haver pelo menos um System Manager, +Additional Permissions,Permissões Adicionais, +Address Template,Modelo de Endereço, Address Title is mandatory.,Titulo do Endereço é obrigatório., Address and other legal information you may want to put in the footer.,Endereço e outras informações legais que você pode querer colocar no rodapé., Addresses And Contacts,Endereços e Contatos, +Adds a client custom script to a DocType,Adiciona um script personalizado do cliente a um DocType, Adds a custom field to a DocType,Adiciona um campo personalizado para um Tipo de Documento (DocType), +Admin,Administrador, Administrator Logged In,Administrador logou-se, Administrator accessed {0} on {1} via IP Address {2}.,Administrador acessada {0} em {1} através do endereço IP {2}., +Advanced,Avançado, +Advanced Control,Controle Avançado, +Advanced Search,Pesquisa Avançada, +Align Labels to the Right,Alinhar etiquetas à direita, Align Value,Alinhar Valor, +All Images attached to Website Slideshow should be public,Todas as imagens anexadas à apresentação de slides do site devem ser públicas, All customizations will be removed. Please confirm.,Todas as personalizações serão removidos. Por favor confirme., "All possible Workflow States and roles of the workflow. Docstatus Options: 0 is""Saved"", 1 is ""Submitted"" and 2 is ""Cancelled""","Todos os status possíveis de fluxo de trabalho e as funções do fluxo de trabalho. Opções Docstatus: 0 é ""Salvo"", 1 é ""Enviado"" e 2 é ""Cancelado""", +All-uppercase is almost as easy to guess as all-lowercase.,Tudo em maiúsculas é quase tão fácil de adivinhar como tudo em minúsculas., Allocated To,Atribuído a, +Allow,Permitir, +Allow Bulk Edit,Permitir edição em massa, +Allow Comments,Permitir Comentários, +Allow Consecutive Login Attempts ,Permitir tentativas de login consecutivas, Allow Dropbox Access,Permitir Acesso Dropbox, +Allow Edit,Permitir Editar, Allow Guest to View,Permitir visualização de convidado, -Allow Import (via Data Import Tool),Permitir Importação (via Ferramenta de Importação de Dados), +Allow Import (via Data Import Tool),Permitir Importação (via Data Import Tool), Allow Incomplete Forms,Permitir Formulários Incompletos, +Allow Login After Fail,Permitir login após falha, +Allow Login using Mobile Number,Permitir login usando o número de celular, +Allow Login using User Name,Permitir Login usando o nome de usuário, +Allow Modules,Permitir Módulos, Allow Multiple,Permitir Multiplos, Allow Print,Permitir Impressão, Allow Print for Cancelled,Permitir impressão para cancelado, Allow Print for Draft,Permitir impressão para rascunho, +Allow Read On All Link Options,Permitir leitura em todas as opções de link, Allow Rename,Permitir Renomear, Allow Roles,Permitir Funções, +Allow Self Approval,Permitir auto-aprovação, +Allow approval for creator of the document,Permitir aprovação para o criador do documento, +Allow events in timeline,Permitir eventos na linha do tempo, +Allow in Quick Entry,Permitir na entrada rápida, +Allow on Submit,Permitir ao Enviar, Allow only one session per user,Permitir apenas uma sessão por usuário, +Allow page break inside tables,Permitir quebra de página dentro de tabelas, +Allow saving if mandatory fields are not filled,Permitir salvar se os campos obrigatórios não são preenchidas, Allow user to login only after this hour (0-24),Permitir que o usuário faça o login somente após este horário (0-24), Allow user to login only before this hour (0-24),Permitir que o usuário faça o login somente antes deste horário (0-24), +Allowed,Permitido, +Allowed In Mentions,Permitido nas menções, "Allowing DocType, DocType. Be careful!","Permitindo DocType , DocType . Tenha cuidado !", Already Registered,Já está registrado, -"Always add ""Draft"" Heading for printing draft documents","Sempre adicionar ""Rascunho"" no cabeçalho para impressão de documentos não enviados", +Also adding the dependent currency field {0},Adicionando também o campo de moeda dependente {0}, +Always add "Draft" Heading for printing draft documents,Sempre adicionar "Rascunho" no cabeçalho para impressão de documentos não enviados, +Always use Account's Email Address as Sender,Sempre use de Conta endereço de email como remetente, +Always use Account's Name as Sender's Name,Sempre use o nome da conta como nome do remetente, Amend,Corrigir, Amending,Correção, Amount Based On Field,Total Baseado no Campo, Amount Field,Campo Valor, +Amount must be greater than 0.,Montante deve ser maior que 0., +An error occured during the payment process. Please contact us.,"Ocorreu um erro durante o processo de pagamento. Por favor, entre em contato conosco.", An icon file with .ico extension. Should be 16 x 16 px. Generated using a favicon generator. [favicon-generator.org],Um ícone do arquivo com extensão .ico. Deve ser de 16 x 16 px. Gerado usando um gerador de favicon. [favicon-generator.org], +Ancestors Of,Antepassados De, Another transaction is blocking this one. Please try again in a few seconds.,"Outra transação está bloqueando essa. Por favor, tente novamente em alguns segundos.", "Another {0} with name {1} exists, select another name","Outra {0} com o nome {1} existe , selecione outro nome", -"Apart from System Manager, roles with Set User Permissions right can set permissions for other users for that Document Type.","Além de System Manager, os papéis com o conjunto de permissões certas pode definir permissões para outros usuários para esse tipo de documento.", +Any string-based printer languages can be used. Writing raw commands requires knowledge of the printer's native language provided by the printer manufacturer. Please refer to the developer manual provided by the printer manufacturer on how to write their native commands. These commands are rendered on the server side using the Jinja Templating Language.,"Qualquer linguagem de impressora baseada em string pode ser usada. Escrever comandos simples requer conhecimento da linguagem nativa da impressora fornecida pelo fabricante da impressora. Por favor, consulte o manual do desenvolvedor fornecido pelo fabricante da impressora sobre como escrever seus comandos nativos. Esses comandos são processados no lado do servidor usando o Jinja Templating Language.", +"Apart from System Manager, roles with Set User Permissions right can set permissions for other users for that Document Type.","Além de System Manager, as funções com o conjunto de permissões certas pode definir permissões para outros usuários para esse tipo de documento.", +Api Access,Acesso Api, App,Aplicativo, +App Access Key,App Chave de Acesso, +App Client ID,App Cliente ID, +App Client Secret,App Cliente secreto, App Name,Nome do App, +App Secret Key,App chave secreta, App not found,App não encontrado, +App {0} already installed,O aplicativo {0} já está instalado, App {0} is not installed,App {0} não está instalado, Append To,Acrescente Para, Append To can be one of {0},Para anexar pode ser um dos {0}, Append To is mandatory for incoming mails,Para acrescentar é obrigatório para os e-mails recebidos, "Append as communication against this DocType (must have fields, ""Status"", ""Subject"")","Anexar como a comunicação contra este DocType (deve ter campos, ""status"", ""Assunto"")", +Applicable Document Types,Tipos de documentos aplicáveis, Apply,Aplicar, +Apply Strict User Permissions,Aplicar permissões de usuário estrito, +Apply To All Document Types,Aplicar a todos os tipos de documentos, Apply this rule if the User is the Owner,Aplicar esta regra se o usuário é o proprietário, +Apply to all Documents Types,Aplicar a todos os tipos de documentos, +Appreciate,Apreciar, +Appreciation,Apreciação, Archive,Arquivar, +Archived,Arquivada, Archived Columns,Colunas Arquivadas, Are you sure you want to delete the attachment?,Tem certeza de que deseja excluir o anexo?, Are you sure you want to relink this communication to {0}?,Você tem certeza que deseja relinkar a comunicação para {0}?, +Are you sure?,Você tem certeza?, +Arial,Arial, "As a best practice, do not assign the same set of permission rule to different Roles. Instead, set multiple Roles to the same User.","Como uma prática recomendada , não atribua o mesmo conjunto de regras de permissão para diferentes funções. Em vez disso, definir várias funções para o mesmo usuário.", +Assign Condition,Atribuir condição, +Assign To Users,Atribuir aos usuários, +"Assign one by one, in sequence","Atribuir um por um, em seqüência", Assign to me,Atribuir para mim, +Assign to the one who has the least assignments,Atribuir a quem tem menos atribuições, +Assigned,Atribuído, Assigned By,Atribuído por, +Assigned By Full Name,Atribuído por Nome completo, Assigned By Me,Atribuído por Mim, Assigned To,Atribuído a, Assigned To/Owner,Atribuído a / Proprietário, Assignment,Tarefa, Assignment Complete,Atribuição Concluída, Assignment Completed,Atribuição Concluída, +Assignment Rule,Regra de Atribuição, +Assignment Rule User,Usuário da regra de atribuição, +Assignment Rules,Regras de Atribuição, Assignment closed by {0},Atribuição fechado por {0}, +Assignment for {0} {1},Atribuição para {0} {1}, +Atleast one field of Parent Document Type is mandatory,Pelo menos um campo do tipo de documento pai é obrigatório, +Attach,Anexar, +Attach Document Print,Anexar Cópia do Documento, +Attach Image,Anexar Imagem, Attach Print,Anexar cópia, Attach Your Picture,Anexe sua Imagem, +Attach file for Import,Anexar arquivo para importação, +Attach files / urls and add in table.,Anexe arquivos / URLs e adicione na tabela., Attached To DocType,Anexado ao Doctype, Attached To Field,Relacionado ao campo, Attached To Name,Anexado Para Nome, +Attachment Limit (MB),Limite de Anexo (MB), +Attachment Removed,Anexo Removido, +Attempting Connection to QZ Tray...,Tentando conexão com a bandeja QZ ..., +Attempting to launch QZ Tray...,Tentativa de lançar o QZ Tray ..., +Auth URL Data,Dados de URL de autenticação, +Authenticating...,Autenticando ..., +Authentication,Autenticação, +Authentication Apps you can use are: ,Os aplicativos de autenticação que você pode usar são:, +Authentication Credentials,Credenciais de Autenticação, +Authorization Code,Código de autorização, +Authorize URL,Autorizar URL, +Authorized,Autorizado, +Auto,Auto, +Auto Email Report,Relatório por Email Automático, +Auto Name,Nome Automático, Auto Reply Message,Resposta Automática, +Auto assignment failed: {0},Atribuição automática falhou: {0}, +Automatically Assign Documents to Users,Atribuir documentos automaticamente aos usuários, +Automation,Automação, +Avatar,Avatar, +Average,Média, +Average of {0},Média de {0}, Avoid dates and years that are associated with you.,Evite datas e anos associados a você., +Avoid recent years.,Evite anos recentes., +Avoid sequences like abc or 6543 as they are easy to guess,"Evite sequências como abc ou 6543, pois são fáceis de adivinhar", Avoid years that are associated with you.,Evite anos associados a você., -Back to Desk,Voltar ao Desktop, +Awaiting Password,Aguardando Senha, +Away,Longe, +BCC,BCC, +Back to Desk,De volta à mesa, Back to Login,Voltar para Login, +Background Color,Cor de Fundo, Background Email Queue,Fila de Email em Segundo Plano, Background Jobs,Tarefas em Segundo Plano, Background Workers,Trabalhadores em Segundo Plano, +Backup,Cópia de segurança, Backup Frequency,Frequência de Backup, +Backup Limit,Limite de backup, +Backup job is already queued. You will receive an email with the download link,O trabalho de backup já está em fila. Você receberá um e-mail com o link de download, Backups,Backups, Banner,Faixa, Banner HTML,Faixa HTML, Banner Image,Imagem do Banner, Banner is above the Top Menu Bar.,A faixa está acima da barra de menu superior., +Bar,Barra, +Base Distinguished Name (DN),Base de dados de nome distinto (DN), +Based on Permissions For User,Com base em permissões para o usuário, +Beta,Beta, Better add a few more letters or another word,Recomenda-se adicionar mais algumas letras ou colocar uma palavra adicional, +Between,Entre, Bio,Bio, +Birth Date,Data de nascimento, Block Module,Módulo Bloco, +Block Modules,Bloquear Módulos, +Blocked,Bloqueado, +Blog,Blog, Blog Category,Categoria do Blog, Blog Intro,Introdução do Blog, +Blog Introduction,Introdução do Blog, Blog Post,Mensagem do Blog, Blog Settings,Configurações do Blog, +Blog Title,Título do Blog, +Blogger,Blogueiro, +Bot,Bot, Both DocType and Name required,Ambos DocType e Nome é obrigatório, Both login and password required,Login e senha necessários, Bounced,Bounced, +Braintree Settings,Configurações Braintree, +Braintree payment gateway settings,Configurações do gateway de pagamento Braintree, Brand HTML,Marca HTML, Brand Image,Imagem da Marca, Breadcrumbs,Breadcrumbs, +Browser not supported,Navegador não suportado, +Brute Force Security,Segurança da força bruta, Build Report,Criar relatório, +Bulk Delete,Excluir em massa, +Bulk Edit {0},Edição em Massa {0}, Bulk Rename,Renomear em Massa, Bulk Update,Alteração em Massa, +Busy,Ocupado, +Button,Botão, Button Help,Botão de Ajuda, +Button Label,Etiqueta do botão, +Bypass Two Factor Auth for users who login from restricted IP Address,Bypass Two Factor Auth para usuários que fazem login do endereço IP restrito, +Bypass restricted IP Address check If Two Factor Auth Enabled,Ignorar verificação de endereço IP restrito se dois fatores de autenticação habilitados, +CC,CC, +"CC, BCC & Email Template","CC, BCC e modelo de e-mail", +CSS,CSS, +CSV,CSV, Cache Cleared,Cache Limpo, +Calculate,Calcular, +Calendar Name,Nome do calendário, +Calendar View,Vista Calendário, Call,Chamada Telefônica, +Can Read,Pode Ler, Can Share,Pode Compartilhar, +Can Write,Pode Escrever, Can't identify open {0}. Try something else.,Não é possível identificar aberto {0}. Tente outra coisa., +Can't save the form as data import is in progress.,Não é possível salvar o formulário à medida que a importação de dados está em andamento., +Cancel {0} documents?,Cancelar {0} documentos?, +Cancelled Document restored as Draft,Documento Cancelado restaurado como Rascunho, Cancelling,Cancelando, +Cancelling {0},Cancelando {0}, Cannot Remove,Não é Possível Remover, Cannot cancel before submitting. See Transition {0},Não pode cancelar antes de enviar., Cannot change docstatus from 0 to 2,Não é possível alterar docstatus 0-2, Cannot change docstatus from 1 to 0,Não é possível alterar docstatus 1-0, +Cannot change header content,Não é possível alterar o conteúdo do cabeçalho, Cannot change state of Cancelled Document. Transition row {0},Não é possível alterar o estado de Documento Cancelado ., +Cannot change user details in demo. Please signup for a new account at https://erpnext.com,Não é possível alterar os detalhes do usuário na demo. Inscreva-se para uma nova conta em https://erpnext.com, Cannot create a {0} against a child document: {1},Não é possível criar um {0} contra um documento filho: {1}, Cannot delete Home and Attachments folders,Não é possível excluir pastas Inicial e Anexos, +Cannot delete file as it belongs to {0} {1} for which you do not have permissions,Não é possível excluir o arquivo como ele pertence a {0} {1} para o qual você não possui permissões, +Cannot delete or cancel because {0} {1} is linked with {2} {3} {4},Não é possível excluir ou cancelar porque {0} {1} está vinculado com {2} {3} {4}, Cannot delete standard field. You can hide it if you want,Não é possível excluir campo padrão. Você pode escondê-lo se você quiser, +Cannot delete {0},Não é possível excluir {0}, Cannot delete {0} as it has child nodes,"Não é possível excluir {0} , pois tem nós filhos", +"Cannot edit Standard Notification. To edit, please disable this and duplicate it","Não é possível editar a notificação padrão. Para editar, desative e duplique", +Cannot edit a standard report. Please duplicate and create a new report,"Não é possível editar um relatório padrão. Por favor, duplique e crie um novo relatório", Cannot edit cancelled document,Não é possível editar documento cancelado, +Cannot edit standard fields,Não é possível editar campos padrão, +Cannot have multiple printers mapped to a single print format.,Não é possível ter várias impressoras mapeadas para um único formato de impressão., Cannot link cancelled document: {0},Não é possível vincular documento cancelado: {0}, Cannot map because following condition fails: ,Não é possível mapear porque seguinte condição de falha:, +Cannot move row,Não é possível mover a linha, Cannot open instance when its {0} is open,"Não é possível abrir instância , quando o seu {0} é aberto", Cannot open {0} when its instance is open,Não é possível abrir {0} quando sua instância está aberta, +Cannot remove ID field,Não é possível remover o campo ID, +Cannot set Notification on Document Type {0},Não é possível definir a notificação no tipo de documento {0}, +Cannot update {0},Não é possível atualizar {0}, +Cannot use sub-query in order by,"não pode usar sub-consulta, a fim de", +Cannot {0} {1},Não é possível {0} {1}, Capitalization doesn't help very much.,"A senha não é boa o suficiente, mas será aceita.", +Card Details,Detalhes do cartão, Categorize blog posts.,Categorizar posts., Category Description,Descrição da Categoria, Cent,Centavo, "Certain documents, like an Invoice, should not be changed once final. The final state for such documents is called Submitted. You can restrict which roles can Submit.","Alguns documentos , como uma fatura , não deve ser trocada uma vez final. O estado final de tais documentos é chamado Enviado. Você pode restringir quais funções pode se submeter.", +Chain Integrity,Integridade da Corrente, +Chaining Hash,Chain Hash, Change Label (via Custom Translation),Alterar etiqueta (via tradução personalizada), -Change Password,Alterar a senha, +Change Password,Alterar Senha, "Change field properties (hide, readonly, permission etc.)","Alterar as propriedades do campo (esconder , readonly , permissão etc )", +Channel,Canal, +Chart Name,Nome do gráfico, +Chart Options,Opções de gráfico, +Chart Source,Fonte do gráfico, +Chart Type,Tipo de gráfico, +Charts,Gráficos, Chat,Chat, -Chat Background,Wallpaper do chat, -Chat Token,Token do bate-papo, +Chat Background,Fundo de bate-papo, +Chat Message,Mensagem de bate-papo, +Chat Operators,Operadores de bate-papo, +Chat Profile,Perfil do bate-papo, +Chat Profile for User {0} exists.,Perfil de bate-papo para o usuário {0} existe., +Chat Room,Sala de bate-papo, +Chat Room Name,Nome da sala de bate-papo, +Chat Room User,Usuário da sala de bate-papo, +Chat Token,Token de bate-papo, +Chat Type,Tipo de bate-papo, Chat messages and other notifications.,Mensagens do chat e outras notificações., +Check,Verifica, +Check Request URL,URL de solicitação de verificação, "Check columns to select, drag to set order.","Verifique colunas para selecionar, arrastar para definir a ordem.", +Check this if you are testing your payment using the Sandbox API,Marque esta opção se você estiver testando o seu pagamento usando o API Sandbox, Check this to pull emails from your mailbox,Marque para baixar os emails da sua caixa de emails, Check which Documents are readable by a User,Confira quais os documentos são lidos por um Usuário, -Checking one moment,"Checando, um momento", +Checking one moment,"Checando,nto", +Checksum Version,Versão Checksum, +Child Table Mapping,Mapeamento de tabela infantil, +Child Tables are shown as a Grid in other DocTypes,Tabelas secundárias são mostradas como uma grade em outros DocTypes, +Choose authentication method to be used by all users,Escolha o método de autenticação a ser usado por todos os usuários, Clear Error Logs,Limpar Logs de Erro, +Clear User Permissions,Limpar permissões do usuário, Clear all roles,Desmarque todas as funções, +"Clearing end date, as it cannot be in the past for published pages.","Apagar data de término, como não pode ser no passado para páginas publicadas.", +Click here to post bugs and suggestions,Clique aqui para enviar erros e sugestões, +Click here to verify,Clique aqui para verificar, +Click on the link below to complete your registration and set a new password,Clique no link abaixo para completar o seu registo e definir uma nova senha, +Click on the link below to download your data,Clique no link abaixo para baixar seus dados, +Click on the link below to verify your request,Clique no link abaixo para verificar sua solicitação, +Click table to edit,Clique na tabela para editar, +Click to Set Filters,Clique para definir filtros, +Clicked,Clicado, +Client Credentials,Credenciais no cliente, +Client Information,Informação ao cliente, +Client Script,Script de Cliente, +Client URLs,URLs do Cliente, Client side script extensions in Javascript,Extensões de script do lado do cliente em Javascript, Collapsible,Desmontável, Collapsible Depends On,Depende dobrável, +Column,Coluna, +Column {0} already exist.,Coluna {0} já existe., Column Break,Quebra de coluna, Column Labels:,Rótulos de coluna:, Column Name,Nome da coluna, Column Name cannot be empty,Nome da coluna não pode estar em branco, +Columns,Colunas, Columns based on,Colunas baseadas em, -Comment By,Comentado por, +Combination of Grant Type ({0}) and Response Type ({1}) not allowed,Combinação de Tipo de Subsídio ( {0} ) e Tipo de Resposta ( {1} ) não permitido, +Comment By,Comentário por, +Comment Email,Comentário Email, +Comment Type,Tipo de Comentário, +Comment can only be edited by the owner,O comentário só pode ser editado pelo proprietário, Commented on {0}: {1},Comentou sobre {0}: {1}, Comments and Communications will be associated with this linked document,Comentários e comunicações serão associados com este documento relacionado, +Comments cannot have links or email addresses,Comentários não podem ter links ou endereços de e-mail, +Common names and surnames are easy to guess.,Os nomes comuns e sobrenomes são fáceis de adivinhar., Communicated via {0} on {1}: {2},Comunicada via {0} em {1}: {2}, Communication Type,Tipo de comunicação, Company History,Histórico da Empresa, +Company Introduction,Introdução da Empresa, +Compiled Successfully,Compilado com sucesso, Complete By,Finalizar até, Complete Registration,Registro Completo, +Complete Setup,Instalação Concluída, +Completed By,Completado por, +Compose Email,Escrever um email, +Condition Detail,Detalhe da condição, +Conditions,Condições, +Configure Chart,Configurar Gráfico, +Configure Charts,Configurar Gráficos, +Confirm,Confirmar, +Confirm Deletion of Data,Confirme a exclusão de dados, +Confirm Request,Confirmar pedido, Confirm Your Email,Confirme seu Email, +Confirmed,Confirmado, +Connected to QZ Tray!,Conectado ao QZ Tray!, +Connection Name,Nome da Conexão, +Connection Success,Sucesso de conexão, +Connection lost. Some features might not work.,Conexão perdida. Alguns recursos podem não funcionar., +Connector Name,Nome do conector, +Connector Type,Tipo de conector, Contact Us Settings,Configurações do Fale Conosco, "Contact options, like ""Sales Query, Support Query"" etc each on a new line or separated by commas.","Opções de contato, como ""Perguntas sobre Vendas, Perguntas de suporte"", etc cada uma em uma nova linha ou separadas por vírgulas.", Contacts,Contatos, +Content (HTML),Conteúdo (HTML), +Content (Markdown),Conteúdo (Markdown), Content Hash,Hash do conteúdo, Content web page.,Conteúdo da Página Web, +Conversation Tones,Tons de conversação, Copyright,Direitos autorais, +Core,Núcleo, +Core DocTypes cannot be customized.,DocTypes principais não podem ser personalizados., Could not connect to outgoing email server,Não foi possível conectar ao servidor de envio emails, +Could not find {0},Não foi possível encontrar {0}, +Could not find {0} in {1},Não foi possível localizar {0} em {1}, +Could not identify {0},Não foi possível identificar {0}, +Count,Contagem, +Country Name,Nome do País, +County,Município, +Create Chart,Criar gráfico, +Create New,Criar Novo, +Create Post,Criar postagem, +Create User Email,Criar e-mail de usuário, Create a New Format,Criar um novo formato, +Create a new record,Crie um novo registro, Create a new {0},Criar um(a) novo(a) {0}, Create and Send Newsletters,Criar e enviar email marketing, -Create and manage newsletter,Criar e gerir newsletter, +Create and manage newsletter,Crie e gerencie o boletim informativo, +Created,Criado, Created Custom Field {0} in {1},Criado campo personalizado {0} em {1}, Created On,Criado em, +Criticism,Crítica, +Criticize,Criticar, Ctrl + Down,Ctrl + Seta para baixo, Ctrl + Up,Ctrl + Seta para cima, Ctrl+Enter to add comment,Ctrl+Enter para adicionar comentário, +Currency Name,Nome da Moeda, +Currency Precision,Precisão de moeda, +Current Mapping,Mapeamento atual, +Current Mapping Action,Ação de Mapeamento atual, +Current Mapping Delete Start,Mapeamento atual Excluir Início, +Current Mapping Start,Início do mapeamento atual, +Current Mapping Type,Tipo de mapeamento atual, Currently Viewing,Atualmente Exibindo, +Currently updating {0},Atualmente atualizando {0}, +Custom,Personalizado, +Custom Base URL,URL Base Base, Custom CSS,CSS Personalizado, +Custom DocPerm,DocPerm personalizado, +Custom Field,Campo Personalizado, +Custom Fields can only be added to a standard DocType.,Campos personalizados só podem ser adicionados a um DocType padrão., +Custom Fields cannot be added to core DocTypes.,Campos personalizados não podem ser adicionados aos principais DocTypes., +Custom Format,Formato Personalizado, Custom HTML Help,Ajuda HTML Personalizado, +Custom JS,JS personalizado, Custom Menu Items,Itens de Menu Personalizado, +Custom Report,Relatório Personalizado, +Custom Reports,Relatórios Personalizados, +Custom Role,Função Personalizada, +Custom Script,Script Personalizado, +Custom Sidebar Menu,Menu de personalização da barra lateral, +Custom Translations,Traduções Personalizadas, +Customization,Personalização, +Customizations Reset,Redefinição de Personalizações, +Customizations for {0} exported to:
    {1},Personalizações para {0} exportadas para:
    {1}, +Customize Form,Personalizar Formulário, +Customize Form Field,Personalizar Campo de Formulário, "Customize Label, Print Hide, Default etc.","Personalizar Etiquetas, Cabeçalhos, Padrões, etc.", -"Customized Formats for Printing, Email","Formatos personalizados para impressão, Email", -Customized HTML Templates for printing transactions.,Modelos HTML customizadas para operações de impressão., +Customize...,Personalizar..., +"Customized Formats for Printing, Email","Formatos Personalizados para Impressão, Email", +Customized HTML Templates for printing transactions.,Modelos HTML customizados para transações de impressão., +Cut,Cortar, +DESC,DESC, Daily Event Digest is sent for Calendar Events where reminders are set.,O resumo de eventos diário é enviado para o Calendário de eventos onde os lembretes são definidos., -Data Import Template,Modelo de importação de dados, +Danger,Perigo, +Dark Color,Cor Escura, +Dashboard Chart,Gráfico de Dashboard, +Dashboard Chart Link,Link do Gráfico de Dashboard, +Dashboard Chart Source,Origem do Gráfico de Dashboard, +Dashboard Name,Nome do Dashboard, +Dashboards,Dashboards, +Data,Dados, +Data Export,Exportação de Dados, +Data Import,Importação de dados, +Data Import Template,Modelo de Importação de Dados, +Data Migration,Migração de Dados, +Data Migration Connector,Conector de Migração de Dados, +Data Migration Mapping,Mapeamento de Migração de Dados, +Data Migration Mapping Detail,Detalhes do Mapeamento de Migração de Dados, +Data Migration Plan,Plano de Migração de Dados, +Data Migration Plan Mapping,Mapeamento do Plano de Migração de Dados, +Data Migration Run,Execução de Migração de Dados, Data missing in table,Falta de dados na tabela, Database Engine,Engine do Banco de Dados, +Database Name,Nome do Banco de Dados, Date and Number Format,Data e Formato de número, +Date {0} must be in format: {1},A data {0} deve estar no formato: {1}, Dates are often easy to guess.,Datas são frequentemente fáceis de adivinhar., Day of Week,Dia da Semana, Days After,Dias Após, +Days Before,Dias Antes, Days Before or After,Dias Antes ou Após, -"Dear System Manager,","Caro Administrador de Sistemas,", +"Dear System Manager,","Caro Administrador do Sistema,", +"Dear User,","Querido usuário,", +Dear {0},Caro {0}, Default Address Template cannot be deleted,Template endereço padrão não pode ser excluído, +Default Inbox,Caixa de Entrada Padrão, Default Incoming,Padrão de Entrada, Default Outgoing,Outgoing Padrão, Default Print Format,Formato de impressão padrão, +Default Print Language,Idioma de impressão padrão, +Default Redirect URI,Padrão de redirecionamento URI, Default Role at Time of Signup,Função padrão no momento da inscrição, Default Sending,Padrão Envio, Default Sending and Inbox,Padrão para Envio e Recebimento, +Default Sort Field,Campo de classificação padrão, +Default Sort Order,Ordem de classificação padrão, Default Value,Valor padrão, -"Default: ""Contact Us""","Padrão: ""Fale Conosco""", +Default: "Contact Us",Padrão: "Fale Conosco", DefaultValue,Valor padrão, Define workflows for forms.,Defina fluxos de trabalho para formulários., Defines actions on states and the next step and allowed roles.,"Define ações em status, o próximo passo e as funções com permissão.", Defines workflow states and rules for a document.,Define o status de fluxo de trabalho e regras para um documento., +Delayed,Atrasado, +Delete Data,Excluir dados, Delete comment?,Excluir comentário?, Delete this record to allow sending to this email address,Excluir este registro para permitir o envio para esse endereço de email, +Delete {0} items permanently?,Excluir {0} itens permanentemente?, Deleted,Excluído(a), Deleted DocType,DocType Excluído, Deleted Document,Documento Excluído, +Deleted Documents,Documentos excluídos, Deleted Name,Nome Excluído, +Deleting {0},Excluindo {0}, Depends On,Depende de, +Descendants Of,Descendentes De, Desk,Mesa, +Desk Access,Acesso ao Ambiente de Trabalho, Desktop Icon,Ícone da área de trabalho, +Desktop Icon already exists,Ícone da área de trabalho já existe, +Developer,Desenvolvedor, Did not add,Não adicionado, +Did not cancel,Não cancelou, Did not find {0} for {0} ({1}),Não encontrou {0} para {0} ( {1}), Did not remove,Não removido, "Different ""States"" this document can exist in. Like ""Open"", ""Pending Approval"" etc.","""Status"" diferentes em que esse documento pode existir. Como ""Aberto"", ""Aprovação Pendente"", etc", +Direct,Direto, +Direct room with {0} already exists.,Sala direta com {0} já existe., +Disable Auto Refresh,Desativar atualização automática, +Disable Count,Desativar Contagem, Disable Customer Signup link in Login page,Desativar Link de Inscrição na Página de Login, +Disable Prepared Report,Desativar relatório preparado, +Disable Report,Desativar Relatório, +Disable SMTP server authentication,Desativar autenticação do servidor SMTP, +Disable Sidebar Stats,Desativar Estatísticas da Barra Lateral, Disable Signup,Desativar Registre-se, Disable Standard Email Footer,Desativar Rodapé Padrão do Email, +Discard,Descartar, Display,exibição, Display Depends On,Visualização depende, Do not allow user to change after set the first time,Não permitir que o usuário altere após definir o primeiro tempo, +Do not edit headers which are preset in the template,Não edite cabeçalhos que estejam predefinidos no modelo, +Do not send Emails,Não envie e-mails, +Doc Event,Evento de Doc, +Doc Events,Doc Eventos, Doc Status,Status do Documento, +DocField,DocField, +DocPerm,DocPerm, +DocShare,DocShare, +DocType {0} provided for the field {1} must have atleast one Link field,O DocType {0} fornecido para o campo {1} deve ter pelo menos um campo Link, DocType can not be merged,DocType não podem ser mescladas, DocType can only be renamed by Administrator,DocType só pode ser renomeado pelo Administrador, DocType is a Table / Form in the application.,DocType é uma Tabela / Form na aplicação., +DocType must be Submittable for the selected Doc Event,DocType deve ser enviado para o Evento de Doc selecionado, DocType on which this Workflow is applicable.,DocType em que este fluxo de trabalho é aplicável., "DocType's name should start with a letter and it can only consist of letters, numbers, spaces and underscores","O nome de DocType deve começar com uma letra e só pode consistir de letras, números, espaços e sublinhados", Doctype required,Doctype obrigatório, +Document,Documento, +Document Follow,Rastrear Documento, +Document Follow Notification,Notificação de Rastreamento do Documento, +Document Queued,Documento em Fila de Espera, +Document Restored,Documento Restaurado, Document Share Report,Relatório de Documentos Compartilhados, Document States,Documento Unidos, +Document Type is not importable,Tipo de documento não é importável, +Document Type is not submittable,O tipo de documento não é submittable, +Document Type to Track,Tipo de Documento a Seguir, Document Types,Tipos de documento, +Document can't saved.,O documento não pode ser salvo., +Document {0} has been set to state {1} by {2},O documento {0} foi definido para declarar {1} por {2}, +Documents,Documentos, Documents assigned to you and by you.,Documentos atribuídos a você e por você., Domain Settings,Configurações de Domínio, +Domains HTML,Domínios HTML, "Don't HTML Encode HTML tags like <script> or just characters like < or >, as they could be intentionally used in this field","Não etiquetas HTML Encode HTML como <script> ou apenas caracteres como <ou>, uma vez que poderia ser usado intencionalmente neste campo", +Don't Override Status,Não Sobrescrever o Status, +Don't create new records,Não crie novos registros, Don't have an account? Sign up,Não tem uma conta? Se inscreva, "Don't know, ask 'help'","Não sei, peça 'ajuda'", +Download Data,Download de dados, +Download Files Backup,Download de backup de arquivos, +Download Link,Baixar link, +Download Report,Relatório de download, +Download Your Data,Baixe seus dados, Download link for your backup will be emailed on the following email address: {0},Link de download para o seu backup será enviado por email no seguinte endereço de email: {0}, Download with Data,Download com dados, Drag and Drop tool to build and customize Print Formats.,Ferramenta de segure e arraste para construir e personalizar formatos de impressão., Drag elements from the sidebar to add. Drag them back to trash.,Arraste os elementos da barra lateral para adicionálos. Arraste-os de volta para eliminar., Dropbox Access Key,Dropbox Chave de Acesso, Dropbox Access Secret,Segredo de Acesso Dropbox, +Dropbox Access Token,Token de acesso Dropbox, +Dropbox Settings,Configurações Dropbox, Dropbox Setup,Configuração do Dropbox, Dropbox access is approved!,O acesso ao Dropbox está aprovado!, +Dropbox backup settings,configurações de cópias de segurança para o Dropbox, +Duplicate Filter Name,Nome do filtro duplicado, Dynamic Link,Link dinâmico, -Edit Filter,Edit Filter, +Dynamic Report Filters,Filtros dinâmicos de relatórios, +ESC,ESC, +Edit Auto Email Report Settings,Editar configurações de relatório automático de e-mail, +Edit Custom HTML,Editar HTML Personalizado, +Edit DocType,Editar DocType, +Edit Filter,Editar Filtro, +Edit Format,Editar Formato, +Edit HTML,Editar HTML, +Edit Heading,Editar Cabeçalho, +Edit Properties,Editar Propriedades, +Edit to add content,Edite para adicionar conteúdo, +Edit {0},Edite {0}, Editable Grid,Grid Editável, Editing Row,Editando Linha, Eg. smsgateway.com/api/send_sms.cgi,Por exemplo: smsgateway.com / api / send_sms.cgi, +Email Account Name,Nome da Conta de Email, +Email Account added multiple times,Conta de email adicionada várias vezes, Email Addresses,Endereço de Email, Email Domain,Domínio de Email, -"Email Domain not configured for this account, Create one?","Domínio de email não configurado para esta conta, criar um?", +"Email Domain not configured for this account, Create one?","Domínio de email não configurado para esta conta,. Criar um?", Email Flag Queue,Flag Fila de Email, -Email Group,Grupo de Emails, +Email Footer Address,Endereço no Rodapé do Email, +Email Group,Grupo de Email, Email Group List,Lista do Grupo de Emails, Email Group Member,Membro do Grupo de Emails, +Email Login ID,ID de login do e-mail, Email Queue,Fila de Emails, +Email Queue Recipient,Email Queue Destinatário, Email Queue records.,Registros da Fila de Emails., +Email Reply Help,Email Reply Help, +Email Rule,Regra de Email, +Email Server,Servidor de Email, Email Settings,Configurações de Email, +Email Signature,Assinatura de Email, Email Status,Satus do Email, +Email Sync Option,Opção Sync Email, +Email Templates for common queries.,Modelos de email para consultas comuns., +Email To,Email Para, Email Unsubscribe,Cancelar inscrição de email, -Email not sent to {0} (unsubscribed / disabled),Email não enviado para {0} (inscrição cancelada / desativado), +Email has been marked as spam,O email foi marcado como spam, +Email has been moved to trash,O email foi movido para o lixo, +Email not sent to {0} (unsubscribed / disabled),Email não foi enviado para {0} (inscrição anulada / desativado), +Email not verified with {0},E-mail não verificado com {0}, Emails are muted,Emails são silenciados, +Emails will be sent with next possible workflow actions,Os e-mails serão enviados com as próximas ações de fluxo de trabalho possíveis, Embed image slideshows in website pages.,Incorporar apresentações de imagem em páginas do site., +Enable / Disable Domains,Ativar / Desativar Domínios, Enable Auto Reply,Ativar resposta automática, -Enable Chat,Ativar Chat, +Enable Automatic Backup,Ativar backup automático, +Enable Chat,Ativar conversa, Enable Comments,Ativação de comentários, Enable Incoming,Ativar Entrada, Enable Outgoing,Ativar Saída, +Enable Password Policy,Ativar política de senha, +Enable Print Server,Ativar servidor de impressão, +Enable Raw Printing,Ativar impressão bruta, +Enable Report,Ativar Relatório, Enable Scheduled Jobs,Ativar Tarefas Agendadas, +Enable Social Login,Ativar Login Social, +Enable Two Factor Auth,Ativar dois fatores Auth, +Enabled email inbox for user {0},Caixa de entrada de e-mail ativada para o usuário {0}, +"Encryption key is invalid, Please check site_config.json","A chave de criptografia é inválida, verifique site_config.json", +End Date Field,Campo de data final, +End Date cannot be before Start Date!,A data de término não pode ser anterior à data de início!, +Endpoint URL,URL do endpoint, +Energy Point Log,Log de ponto de energia, +Energy Point Rule,Regra do ponto de energia, +Energy Point Settings,Configurações de ponto de energia, +Energy Points,Pontos de energia, Enter Email Recipient(s),Digite email do Destinatário(s), Enter Form Type,Digite o Tipo de Formulário, -"Enter default value fields (keys) and values. If you add multiple values for a field, the first one will be picked. These defaults are also used to set ""match"" permission rules. To see list of fields, go to ""Customize Form"".","Insira campos de valor default (chaves) e valores. Se você adicionar vários valores para um campo, o primeiro vai ser escolhido. Esses padrões são também utilizados para definir "match" regras de permissão. Para ver a lista de campos, vá em "Personalizar o formulário".", +"Enter default value fields (keys) and values. If you add multiple values for a field, the first one will be picked. These defaults are also used to set ""match"" permission rules. To see list of fields, go to ""Customize Form"".","Insira campos de valor padrão (teclas) e valores. Se adicionar diversos valores para um campo, será escolhido o primeiro. Estes padrões também são utilizados para definir regras de permissão de ""correspondência. Para ver a lista de campos, vá a ""Personalizar Formulário"".", Enter folder name,Digite o nome da pasta, "Enter keys to enable login via Facebook, Google, GitHub.","Enter para ativar o login via Facebook , Google, GitHub .", +Enter python module or select connector type,Insira o módulo python ou selecione o tipo de conector, "Enter static url parameters here (Eg. sender=ERPNext, username=ERPNext, password=1234 etc.)","Digite os parâmetros da URL estática aqui (por exemplo remetente=ERPNext, usuario=ERPNext, senha=1234, etc)", Enter url parameter for message,Digite o parâmetro da url para mensagem, Enter url parameter for receiver nos,Digite o parâmetro da url para os números de receptores, Enter your password,Digite sua senha, +Entity Name,Nome da entidade, Equals,Igual, +Error Message,Mensagem de erro, Error Report,Reportar erro, Error Snapshot,Snapshot de Erro, +Error in Custom Script,Erro no script personalizado, +Error in Notification,Erro na notificação, +Error in Notification: {},Erro na notificação: {}, +Error while connecting to email account {0},Erro ao conectar-se à conta de e-mail {0}, +Error while evaluating Notification {0}. Please fix your template.,Erro ao avaliar a notificação {0}. Por favor corrija seu modelo., Error: Document has been modified after you have opened it,Erro: O documento foi modificado depois de aberto, +Error: Value missing for {0}: {1},Erro: Falta valor para {0}: {1}, Errors in Background Events,Erros em Eventos em Segundo Plano, +Event Category,Categoria do Evento, +Event Participants,Participantes do Evento, +Event Type,Tipo de Evento, +Event and other calendars.,Evento e outros calendários., +Events in Today's Calendar,Eventos no calendário de hoje, Everyone,Todos, +Example,Exemplo, Example Email Address,Exemplo de Endereço de Email, +Example: {{ subject }},Exemplo: {{subject}}, +Excel,Excel, +Exception,Exceção, Exception Type,Tipo de exceção, +Execution Time: {0} sec,Tempo de Execução: {0} seg, +Expert,Especialista, +Expiration time,Data de validade, +Expire Notification On,Expiram Notificação Lig, +Expires In,Expira em, +Expiry time of QR Code Image Page,Tempo de expiração da página de imagem de código QR, +Export All {0} rows?,Exportar todas as linhas {0}?, Export Custom Permissions,Exportar Permissões Personalizadas, Export Customizations,Exportar Personalizações, +Export Data,Exportar dados, +Export Data in CSV / Excel format.,Exportar dados no formato CSV / Excel., +Export Report: {0},Relatório de exportação: {0}, Expose Recipients,Mostrar Destinatários, +"Expression, Optional","Expressão, Opcional", +Facebook,Facebook, +Failed to complete setup,Falha ao concluir a configuração, +Failed to connect to server,Falha ao conectar-se ao servidor, +Failed while amending subscription,Falha ao alterar a assinatura, +FavIcon,FavIcon, Feedback Request,Solicitação de Feedback, -"Field ""value"" is mandatory. Please specify value to be updated","O campo ""valor"" é obrigatório. Por favor, especifique o valor a ser atualizado", +Fetch From,Buscar de, +Fetch If Empty,Buscar se Vazio, +Fetch Images,Buscar imagens, +Fetch attached images from document,Buscar imagens anexadas do documento, +Field "route" is mandatory for Web Views,O campo "rota" é obrigatório para Web Views, +Field "value" is mandatory. Please specify value to be updated,"O campo ""valor"" é obrigatório. Por favor, especifique o valor a ser atualizado", Field Description,Descrição do Campo, +Field Maps,Mapas de campo, Field Type,Tipo de Campo, "Field that represents the Workflow State of the transaction (if field is not present, a new hidden Custom Field will be created)","Campo que representa o status da transação no fluxo de trabalho (se o campo não estiver presente, um novo campo oculto personalizado será criado)", +Field to Track,Campo para rastrear, +Field type cannot be changed for {0},O tipo de campo não pode ser alterado para {0}, +Field {0} not found.,Campo {0} não encontrado., +Fieldname is limited to 64 characters ({0}),Fieldname é limitado a 64 caracteres ({0}), Fieldname not set for Custom Field,Fieldname não definida para campo personalizado, Fieldname which will be the DocType for this link field.,Nome do campo que será o DocType para este campo link., Fieldname {0} cannot have special characters like {1},Fieldname {0} não pode ter caracteres especiais como {1}, +Fieldname {0} conflicting with meta object,Nome do campo {0} em conflito com meta-objeto, +Fields Multicheck,Campos Multicheck, "Fields separated by comma (,) will be included in the ""Search By"" list of Search dialog box","Campos separados por vírgula (,) será incluído no "Pesquisar por" lista de caixa de diálogo Pesquisar", -Fieldtype,FieldType, +Fieldtype,Tipo de Campo, Fieldtype cannot be changed from {0} to {1} in row {2},FieldType não pode ser alterado a partir de {0} a {1} em linha {2}, File '{0}' not found,Arquivo '{0}' não encontrado, +File Backup,Backup de arquivos, File Name,Nome do arquivo, File Size,Tamanho do arquivo, +File Type,Tipo de arquivo, File URL,URL do arquivo, +File Upload,Upload de arquivos, +File Upload Disconnected. Please try again.,"Carregamento de arquivos desconectado. Por favor, tente novamente.", +File Upload in Progress. Please try again in a few moments.,"Carregamento de arquivos em andamento. Por favor, tente novamente em alguns instantes.", +File backup is ready,O backup do arquivo está pronto, File not attached,Arquivo não anexado, File size exceeded the maximum allowed size of {0} MB,O tamanho do arquivo excedeu o tamanho máximo permitido de {0} MB, File too big,Arquivo muito grande, File {0} does not exist,Arquivo {0} não existe, Files,Arquivos, +Filter,Filtro, +Filter Data,Filtrar dados, +Filter List,Lista de filtros, Filter Meta,Filtrar Meta, +Filter Name,Nome do filtro, +Filter Values,Valores de filtro, +Filter must be a tuple or list (in a list),O filtro deve ser uma tupla ou lista (em uma lista), +"Filter must have 4 values (doctype, fieldname, operator, value): {0}","O filtro deve ter 4 valores (doctype, fieldname, operador, valor): {0}", Filter...,Filtre..., +Filtered by "{0}",Filtrados por "{0}", Filters Display,Exibição dos Filtros, +Filters JSON,Filtros JSON, Filters saved,Filtros salvos, +Find {0} in {1},Localizar {0} em {1}, First Level,Primeiro nível, +First Success Message,Primeira mensagem de sucesso, +First Transaction,Primeira Transação, First data column must be blank.,Primeira coluna de dados deve estar em branco., +First set the name and save the record.,"Primeiro, defina o nome e salve o registro.", +Flag,Bandeira, Float,Float, Float Precision,Precisão de Casas Decimais, +Fold,Dobrar, Fold can not be at the end of the form,Fold não pode ser no final da forma, Fold must come before a Section Break,Dobre deve vir antes de uma quebra de secção, +Folder,Pasta, +Folder name should not include '/' (slash),O nome da pasta não deve incluir '/' (slash), Folder {0} is not empty,Pasta {0} não está vazio, +Follow,Segue, +Followed by,Seguido por, +Following fields are missing:,Seguintes campos estão faltando:, Following fields have missing values:,Os campos a seguir estão em branco:, +Font,fonte, Font Size,Tamanho da Fonte, -"For Links, enter the DocType as range.\nFor Select, enter list of Options, each on a new line.","Para Links, insira o DocType como intervalo. Para Selecionar, digite lista de opções, cada um em uma nova linha.", +Fonts,Fontes, +Footer,Rodapé, +Footer HTML,HTML de rodapé, +Footer Items,Itens do Rodapé, +Footer will display correctly only in PDF,Rodapé será exibido corretamente somente em PDF, +For Document Type,Para o tipo de documento, +"For Links, enter the DocType as range.\nFor Select, enter list of Options, each on a new line.","Para os Links, insira o DocType como intervalo. Para Selecionar, insira-os na lista de Opções, cada um numa nova linha.", For User,Para o Usuário, +For Value,Por valor, +"For currency {0}, the minimum transaction amount should be {1}","Para a moeda {0}, o valor mínimo da transação deve ser {1}", For example if you cancel and amend INV004 it will become a new document INV004-1. This helps you to keep track of each amendment.,"Por exemplo, se você cancelar e corrigir o INV004, ele vai se tornar um novo documento chamado INV004-1. Isso ajuda você a manter o controle de cada alteração.", "For example: If you want to include the document ID, use {0}","Por exemplo: Se você quiser incluir a ID do documento, use {0}", "For updating, you can update only selective columns.","Para a atualização, você pode atualizar colunas só seletivos.", For {0} at level {1} in {2} in row {3},Por {0} a nível {1} em {2} na linha {3}, +Force,Força, Force Show,Forçar Exibição, Forgot Password,Esqueci a Senha, Forgot Password?,Esqueceu a senha?, +Form Customization,Personalização de Formulário, +Form Settings,Configurações de formulário, +Format,Formato, Format Data,Formato de dados, Forward To Email Address,Encaminhar para Email, +Fraction,Fração, Fraction Units,Unidades Fracionadas, +Frames,Frames, +Frappe,Frappe, Frappe Framework,Frappe Framework, Friendly Title,Título Amigável, +From Date Field,Do campo de data, +From Document Type,Do tipo de documento, From Full Name,De nome completo, Full Page,Página completa, +Fw: {0},Fw: {0}, +GCalendar Sync ID,ID de sincronização do GCalendar, +GMail,Gmail, +Gantt,Gantt, Gateway,Porta de entrada, +Gateway Controller,Gateway Controller, +Gateway Settings,Configurações do Gateway, +Generate Keys,Gerar Chaves, +Generate New Report,Gerar novo relatório, +Generated File,Arquivo gerado, +Geo,Geo, +Geolocation,Geolocalização, +Get Alerts for Today,Obter Alertas para Hoje, +Get Contacts,Obter contatos, +Get Fields,Obter campos, +Get your globally recognized avatar from Gravatar.com,Obtenha seu avatar globalmente reconhecido de Gravatar.com, +GitHub,GitHub, +Give Review Points,Dê pontos de revisão, Global Unsubscribe,Cancelar Inscrição Global, +Go to the document,Vá para o documento, +Go to this URL after completing the form (only for Guest users),Vá para este URL depois de preencher o formulário (apenas para usuários convidados), +Go to {0},Vá para {0}, +Go to {0} List,Ir para a {0} lista, +Go to {0} Page,Ir para {0} Página, +Google,Google, Google Analytics ID,ID do Google Analytics, +Google Calendar ID,ID da Agenda do Google, +Google Font,Google Font, +Google Services,Google Services, +Grant Type,Tipo Grant, +Group Name,Nome do grupo, +Group name cannot be empty.,O nome do grupo não pode estar vazio., +Groups of DocTypes,Grupos de DocTypes, +HTML,HTML, +HTML Editor,Editor de HTML, +"HTML Header, Robots and Redirects","Cabeçalho HTML, Robôs e Redirecionamentos", HTML for header section. Optional,HTML para a seção de cabeçalho. opcional, +Half,Metade, +Has Attachment,possui anexo, +Has Attachments,Tem anexos, +Has Domain,Tem domínio, Has Role,Tem Função, +Has Web View,Tem Web View, Have an account? Login,Possui cadastro? Entre, +Header,Cabeçalho, +Header HTML,HTML de cabeçalho, +Header HTML set from attachment {0},Conjunto HTML de cabeçalho do anexo {0}, +Header Image,Imagem de cabeçalho, +Headers,Cabeçalhos, +Heading,Título, +Hello {0},Olá {0}, +Hello!,Olá!, Help Articles,Artigo de Ajuda, Help Category,Categoria de Ajuda, +Help on Search,Ajuda na Pesquisa, "Help: To link to another record in the system, use ""#Form/Note/[Note Name]"" as the Link URL. (don't use ""http://"")","Ajuda: Para vincular a outro registro no sistema, use "# Form / Nota / [Nota Name]" como a ligação URL. (Não use "http://")", +Helvetica,Helvetica, +Hi {0},Oi {0}, Hide Copy,Ocultar Cópia, Hide Footer Signup,Esconder Link de Inscrição do Rodapé, +Hide Sidebar and Menu,Ocultar barra lateral e menu, Hide Standard Menu,Esconder Menu Padrão, +Hide Weekends,Ocultar finais de semana, Hide details,Ocultar Detalhes, +Hide footer in auto email reports,Ocultar o rodapé nos relatórios de e-mail automático, +Higher priority rule will be applied first,Regra de prioridade mais alta será aplicada primeiro, +Highlight,Realçar, +"Hint: Include symbols, numbers and capital letters in the password","Dica: Inclua símbolos, números e letras maiúsculas na senha", +Home Page,Pagina inicial, +Home Settings,Configurações iniciais, Home/Test Folder 1,Início / Teste pasta 1, Home/Test Folder 1/Test Folder 3,Pasta Principal / Teste 1 / Teste Pasta 3, Home/Test Folder 2,Início / Teste pasta 2, Host,Host, Hostname,Nome do Host, "How should this currency be formatted? If not set, will use system defaults","Como essa moeda deve ser formatada? Se não for definido, serão usados os padrões do sistema", +I found these: ,Eu encontrei estes:, +ID,ID, ID (name) of the entity whose property is to be set,ID (nome) da entidade cuja propriedade é para ser definida, Icon will appear on the button,O ícone aparecerá no botão, +Identity Details,Detalhes da identidade, +Idx,Idx, +"If Apply Strict User Permission is checked and User Permission is defined for a DocType for a User, then all the documents where value of the link is blank, will not be shown to that User","Se a opção Aplicar permissão de usuário estrito estiver marcada e a permissão de usuário for definida para um DocType para um usuário, todos os documentos onde o valor do link estiver em branco não serão exibidos para esse usuário", If Checked workflow status will not override status in list view,Uma vez selecionado o status do fluxo de trabalho não sobrescreverá o status do documentos na visualização da lista, If Owner,Se proprietário, "If a Role does not have access at Level 0, then higher levels are meaningless.","Se uma função não tem acesso no nível 0, então os níveis mais altos são irrelevantes.", "If checked, all other workflows become inactive.","Se marcada, todos os outros fluxos de trabalho tornam-se inativos.", +"If checked, this field will be not overwritten based on Fetch From if a value already exists.","Se marcado, este campo não será sobrescrito com base em Buscar de se um valor já existir.", +"If checked, users will not see the Confirm Access dialog.","Se selecionada, s usuáários não verão a janela Confirmar Accesso.", +"If disabled, this role will be removed from all users.",Se esta função for desativada será removida em todos os usuários., +"If enabled, user can login from any IP Address using Two Factor Auth, this can also be set for all users in System Settings","Se ativado, o usuário pode efetuar login a partir de qualquer endereço IP usando a autenticação de dois fatores, isso também pode ser definido para todos os usuários nas configurações do sistema", +"If enabled, all users can login from any IP Address using Two Factor Auth. This can also be set only for specific user(s) in User Page","Se ativado, todos os usuários podem efetuar login a partir de qualquer endereço IP usando a autenticação de dois fatores. Isso também pode ser definido apenas para usuários específicos na página do usuário", +"If enabled, changes to the document are tracked and shown in timeline","Se ativado, as alterações no documento são rastreadas e mostradas na linha do tempo", +"If enabled, document views are tracked, this can happen multiple times","Se ativado, as visualizações de documentos são rastreadas, isso pode acontecer várias vezes", +"If enabled, the document is marked as seen, the first time a user opens it","Se ativado, o documento é marcado como visto, a primeira vez que um usuário o abre", +"If enabled, the password strength will be enforced based on the Minimum Password Score value. A value of 2 being medium strong and 4 being very strong.","Se ativado, a força da senha será aplicada com base no valor Minimum Password Score. Um valor de 2 sendo médio forte e 4 sendo muito forte.", +"If enabled, users who login from Restricted IP Address, won't be prompted for Two Factor Auth","Se ativado, os usuários que fizerem login a partir do Endereço IP restrito não serão solicitados para autenticação de dois fatores", +"If enabled, users will be notified every time they login. If not enabled, users will only be notified once.","Se ativado, os usuários serão notificados sempre que iniciarem sessão. Se não estiver ativado, os usuários só serão notificados uma vez.", If non standard port (e.g. 587),"Se não for a porta padrão (por exemplo, 587)", -"If the user has any role checked, then the user becomes a ""System User"". ""System User"" has access to the desktop","Se o usuário tem um papel marcada, então o usuário torna-se um "usuário do sistema". "Usuário do Sistema" tem acesso à área de trabalho", +"If non standard port (e.g. 587). If on Google Cloud, try port 2525.","Se não porta padrão (por exemplo, 587). Se no Google Cloud, tente a porta 2525.", +"If not set, the currency precision will depend on number format","Se não for definido, a precisão da moeda dependerá do formato de número", +If the condition is satisfied user will be rewarded with the points. eg. doc.status == 'Closed'\n,"Se a condição for satisfeita, o usuário será recompensado com os pontos. por exemplo. doc.status == 'Closed'", +"If the user has any role checked, then the user becomes a ""System User"". ""System User"" has access to the desktop","Se o usuário tiver alguma função selecionada, então o usuário torna-se um ""Usuário do Sistema"". Um ""Usuário do Sistema"" tem acesso à área de trabalho", "If these instructions where not helpful, please add in your suggestions on GitHub Issues.","Se estas instruções não forem úteis, dê sua sugestão no GitHub.", +"If this is checked, rows with valid data will be imported and invalid rows will be dumped into a new file for you to import later.","Se isso estiver marcado, linhas com dados válidos serão importadas e linhas inválidas serão despejadas em um novo arquivo para você importar mais tarde.", If user is the owner,Se o usuário é o proprietário, "If you are updating, please select ""Overwrite"" else existing rows will not be deleted.","Se você estiver atualizando, por favor selecione ""Substituir"" linhas outra existentes não serão excluídos.", +If you are updating/overwriting already created records.,Se você está atualizando / substituindo registros já criados., "If you are uploading new records, ""Naming Series"" becomes mandatory, if present.","Se você estiver fazendo upload de novos registros, a coluna ""Naming Series"" torna-se obrigatória, se presente.", "If you are uploading new records, leave the ""name"" (ID) column blank.","Se você estiver fazendo upload de novos registros, deixe a coluna ""name"" (ID) em branco.", +If you don't want to create any new records while updating the older records.,Se você não quer criar novos registros enquanto atualiza os registros mais antigos., "If you set this, this Item will come in a drop-down under the selected parent.","Se você definir isso, este item virá em um drop-down sob o pai selecionado .", "If you think this is unauthorized, please change the Administrator password.","Se você acha que isso não é autorizado, por favor mude a senha do administrador.", -Ignore User Permissions,Ignorar permissões de usuário, +"If your data is in HTML, please copy paste the exact HTML code with the tags.","Se os dados estiverem em HTML, por favor, copie e cole o código HTML exato com as tags.", +Ignore User Permissions,Ignorar permissões de usuári, +Ignore XSS Filter,Ignorar Filtro XSS, Ignore attachments over this size,Ignorar anexos maiores que este tamanho, +Ignore encoding errors,Ignorar erros de codificação, Ignored: {0} to {1},Ignorados: {0} para {1}, +Illegal Access Token. Please try again,"Ilegal acesso token. Por favor, tente novamente", +Illegal Document Status for {0},Status ilegal do documento para {0}, +Image Field,Campo de Imagem, +Image Link,Link da Imagem, Image field must be a valid fieldname,Campo de imagem deve ser um nome de campo válido, Image field must be of type Attach Image,Campo de imagem deve ser do tipo Anexar Imagem, Images,Imagens, +Implicit,Implícito, +Import,Importar, Import Email From,Importar Email do, +Import Status,Status da importação, Import Subscribers,Importar Inscritos, Import Zip,Importar Zip, In Filter,No Filtro da Lista, In Global Search,Na Busca Global, In Grid View,Na Visualização do Grid, +In Hours,Em horas, In List View,Mostrar na Visualização da Lista, +In Preview,Na pré-visualização, In Reply To,Em resposta a, In Standard Filter,Em Filtro Padrão, +In Valid Request,Pedido inválido, +In points. Default is 9.,Em pontos. O padrão é 9., +In seconds,Em segundos, +Include Search in Top Bar,Incluem a busca no Top Bar, +"Include symbols, numbers and capital letters in the password","Inclua símbolos, números e letras maiúsculas na senha", +Incoming email account not correct,A conta de e-mail recebida não é correta, +Incomplete login details,Detalhes de login incompletos, +Incorrect User or Password,Usuário ou Senha Incorreta, +Incorrect Verification code,Código de verificação incorreto, Incorrect value in row {0}: {1} must be {2} {3},Valor incorreto na linha {0} : {1} deve ser {2} {3}, +Incorrect value: {0} must be {1} {2},Valor incorreto: {0} deve ser {1} {2}, +Index,Índice, +Indicator,Indicador, +Info,Informações, Info:,Info:, +Initial Sync Count,Contagem de sincronização inicial, +InnoDB,InnoDB, +Insert Above,Inserir Acima, Insert After,Inserir Após, Insert After cannot be set as {0},Depois de inserir não pode ser definido como {0}, +"Insert After field '{0}' mentioned in Custom Field '{1}', with label '{2}', does not exist","O campo Inserir Depois '{0}' mencionado no Campo Personalizado '{1}', com rótulo '{2}', não existe", +Insert Below,Inserir Abaixo, +Insert Column Before {0},Inserir coluna antes de {0}, +Insert Style,Inserir Estilo, +Insert new records,Inserir novos registros, +Instructions Emailed,Instruções Emailed, +Insufficient Permission for {0},Permissão insuficiente para {0}, Int,Inteiro, +Integration Request,Pedido de Integração, Integration Request Service,Serviço de Requisição de Integração, +Integration Type,Tipo de Integração, +Integrations,Integrações, Integrations can use this field to set email delivery status,Integrações pode usar este campo para definir o status de entrega de email, +Internal Server Error,Erro do Servidor Interno, Internal record of document shares,Registro interno de ações de documentos, Introduce your company to the website visitor.,Apresente sua empresa para o visitante do site., Introductory information for the Contact Us Page,Informação introdutória para a página Fale Conosco, +Invalid,Inválido, +Invalid "depends_on" expression,Expressão "dependente" dependente inválida, +Invalid Access Key ID or Secret Access Key.,ID de chave de acesso inválido ou chave de acesso secreto., Invalid CSV Format,Formato inválido de CSV, Invalid Home Page,Inválido Página Inicial, Invalid Link,Fazer a ligação inválido, Invalid Login Token,Inválido símbolo de logon, +Invalid Login. Try again.,Login inválido. Tente novamente., Invalid Mail Server. Please rectify and try again.,"Mail Server inválido . Por favor, corrigir e tentar novamente.", Invalid Outgoing Mail Server or Port,Inválido Outgoing Mail Server ou Porto, -Invalid Password,Senha inválida, +Invalid Output Format,Formato de saída inválido, +Invalid Password,senha inválida, +Invalid Password:,Senha inválida:, Invalid Request,Requisição Inválida, -Invalid Subscription,assinatura inválida, +Invalid Search Field {0},Campo de pesquisa inválido {0}, +Invalid Subscription,Inscrição inválida, Invalid Token,Token inválido, Invalid User Name or Support Password. Please rectify and try again.,"Nome de usuário ou senha inválidos. Por favor, corrigir e tentar novamente.", +Invalid column,Coluna inválida, +Invalid field name {0},Nome do campo inválido {0}, Invalid fieldname '{0}' in autoname,nome do campo inválido '{0}' em autoname, Invalid file path: {0},Caminho de arquivo inválido: {0}, Invalid login or password,Login ou senha inválidos, +Invalid module path,Caminho do módulo inválido, Invalid naming series (. missing),Série de nomes inválido (. Ausente), +Invalid payment gateway credentials,credenciais de gateway de pagamento inválidos, Invalid recipient address,Endereço do destinatário inválido, +Invalid {0} condition,Condição inválida {0}, +Inverse,Inverso, +Is,É, Is Attachments Folder,É Pasta de Anexos, Is Child Table,É Tabela Filho, Is Custom Field,É campo personalizado, +Is First Startup,É o primeiro arranque, +Is Folder,É Pasta, +Is Global,É global, +Is Globally Pinned,É fixado globalmente, Is Home Folder,É Home Folder, Is Mandatory Field,É campo obrigatório, +Is Pinned,Está preso, Is Primary Contact,É o contato principal, Is Private,É privada, +Is Published Field,É Publicado campo, +Is Published Field must be a valid fieldname,É Publicado O campo deve ser um nome do campo válido, Is Single,É Único, +Is Spam,é Spam, +Is Standard,É Padrão, Is Submittable,Pode ser Enviado, Is Table,É Tabela, Is Your Company Address,É o seu endereço comercial, It is risky to delete this file: {0}. Please contact your System Manager.,É arriscado excluir este arquivo: {0}. Entre em contato com o administrador do sistema., Item cannot be added to its own descendents,O artigo não pode ser acrescentado para os seus próprios descendentes, +JS,JS, +JSON,JSON, JavaScript Format: frappe.query_reports['REPORTNAME'] = {},Formato JavaScript: frappe.query_reports [' REPORTNAME '] = {}, Javascript to append to the head section of the page.,Javascript para acrescentar ao cabeçalho da página., +Jinja,Jinja, +John Doe,John Doe, +Kanban,Kanban, Kanban Board Column,Coluna do Painel Kanban, Kanban Board Name,Nome do Painel Kanban, +Karma,Karma, +Keep track of all update feeds,Acompanhe todos os feeds de atualização, +Keeps track of all communications,Mantém o controle de todas as comunicações, Key,Chave, Knowledge Base,Base de Conhecimento, Knowledge Base Contributor,Colaborador da Base de Conhecimento, Knowledge Base Editor,Editor da Base de Conhecimento, LDAP Email Field,Campo do Email LDAP, LDAP First Name Field,Campo Primeiro Nome do LDAP, +LDAP Not Installed,LDAP não instalado, LDAP Search String,Palavra de Busca do LDAP, +"LDAP Search String needs to end with a placeholder, eg sAMAccountName={0}","A string de pesquisa do LDAP precisa terminar com um espaço reservado, por exemplo, sAMAccountName = {0}", +LDAP Security,Segurança LDAP, +LDAP Server Url,Servidor LDAP Url, LDAP Username Field,Campo Nome de Usuário do LDAP, +LDAP is not enabled.,O LDAP não está ativado., Label Help,Ajuda sobre Etiquetas, Label and Type,Etiqueta e Tipo, Label is mandatory,Etiqueta é obrigatório, @@ -577,150 +1429,345 @@ Language,Idioma, Language Code,Código do Idioma, "Language, Date and Time settings","Configurações de Idioma , Data e Hora", Last Active,Ativo pela última vez, +Last IP,Último IP, Last Known Versions,Últimas versões conhecidas, Last Login,Último Login, +Last Message,Última mensagem, Last Modified By,Última Alteração por, +Last Modified Date,Última Data Modificada, Last Modified On,Última Alteração em, +Last Month,Mês passado, +Last Point Allocation Date,Última data de alocação de ponto, +Last Quarter,Ultimo quarto, +Last Synced On,Última sincronização em, Last Updated By,Última atualização por, Last Updated On,Última atualização em, +Last User,Último usuário, +Last Week,Semana passada, +Last Year,Ano passado, +Last synced {0},Última sincronização {0}, Leave a Comment,Deixe um comentário, +Leave blank to repeat always,Deixe em branco para repetir sempre, Leave this conversation,Deixar essa conversa, +Left this conversation,Deixou esta conversa, +Length,Comprimento, +Length of {0} should be between 1 and 1000,Comprimento de {0} deve ser entre 1 e 1000, +Let's avoid repeated words and characters,Vamos evitar palavras e caracteres repetidos, +Let's prepare the system for first use.,Vamos preparar o sistema para a primeira utilização., +Letter,Carta, +Letter Head Based On,Carta de cabeça com base em, +Letter Head Image,Carta cabeça imagem, Letter Head Name,Nome do timbrado, Letter Head in HTML,Cabeça Carta em HTML, +Level Name,Nome do nível, Liked,Gostou, Liked By,Gostou por, Liked by {0},Aprovado por {0}, -Likes,Likes, +Likes,Gostos, +Limit Number of DB Backups,Número limite de backups de banco de dados, +Line,Linha, Link DocType,Relacionar ao DocType, +Link Expired,Link expirado, +Link Name,Nome do Link, Link Title,Título do Link, "Link that is the website home page. Standard Links (index, login, products, blog, about, contact)","Link da home page do site. Links padrão (index, login, products, blog, about, contact)", Link to the page you want to open. Leave blank if you want to make it a group parent.,Link para a página que você deseja abrir. Deixe em branco se você quiser torná-lo um pai grupo., Linked,Relacionado, Linked With,Relacionado com, +Linked with {0},Ligado com {0}, +Links,Links, +List,Lista, +List Filter,Filtro de lista, +List View Setting,Configuração de exibição de lista, +List a document type,Lista de um tipo de documento, +"List as [{""label"": _(""Jobs""), ""route"":""jobs""}]","Lista como [{ "label": _ ( "Jobs"), "route": "empregos"}]", +List of backups available for download,Lista de backups disponíveis para download, List of patches executed,Lista de correções executado, List of themes for Website.,Lista dos temas para o site., +Load Balancing,Balanceamento de carga, Loading,Carregando, +Local DocType,DocType local, +Local Fieldname,Nome do campo local, +Local Primary Key,Chave primária local, +Locals,Locais, +Log Details,Detalhes do registro, Log of Scheduler Errors,Log de Erros Scheduler, Log of error during requests.,Log de erro durante a solicitações., Log of error on automated events (scheduler).,Log de erro sobre eventos automatizados ( programador ) ., Logged Out,Deslogado, +Logged in as Guest or Administrator,Conectado como Convidado ou Administrador, Login,Entrar, Login After,Login após, Login Before,Login antes, Login Id is required,ID de login é necessária, Login Required,Necessário Login, +Login Verification Code from {},Código de verificação de login de {}, +Login and view in Browser,Faça login e visualize no navegador, Login not allowed at this time,Entrada não permitida neste momento, +"Login session expired, refresh page to retry","A sessão de login expirou, atualize a página para tentar novamente", Login to comment,Faça login para comentar, +Login token required,É necessário o token de login, Login with LDAP,Logar com LDAP, Logout,Sair, Long Text,Texto Longo, -"Make ""name"" searchable in Global Search","Tornar ""nome"" pesquisável na Busca Global", +Looks like something is wrong with this site's Paypal configuration.,Parece que algo está errado com a configuração do Paypal deste site., +Looks like something is wrong with this site's payment gateway configuration. No payment has been made.,Parece que algo está errado com a configuração de gateway de pagamento deste site. Nenhum pagamento foi feito., +"Looks like something went wrong during the transaction. Since we haven't confirmed the payment, Paypal will automatically refund you this amount. If it doesn't, please send us an email and mention the Correlation ID: {0}.","Parece que algo deu errado durante a transação. Desde que não tenham confirmado o pagamento, Paypal vai reembolsá-lo automaticamente esse valor. Se isso não acontecer, por favor, envie-nos um e-mail e mencionar a ID de Correlação: {0}.", +Madam,Senhora, +Main Section,Seção Principal, +Make "name" searchable in Global Search,Tornar "nome" pesquisável na Busca Global, Make use of longer keyboard patterns,Use uma combinação de letras e números mais longa, +Manage Third Party Apps,Gerencie aplicativos de terceiros, Mandatory Information missing:,Informações obrigatórias ausente:, +Mandatory field: set role for,Campo obrigatório: definir a função para, +Mandatory field: {0},Campo obrigatório: {0}, +"Mandatory fields required in table {0}, Row {1}","Os campos obrigatórios exigidos na tabela {0}, linha {1}", Mandatory fields required in {0},Os campos obrigatórios exigidos no {0}, +Mandatory:,Obrigatório:, +Mapping Name,Mapeando o Nome, +Mappings,Mapeamentos, Mark as Read,Marcar como lido, -Markdown,Markdown, +Mark as Spam,Marcar como spam, +Mark as Unread,Marcar como não lido, +Markdown,Desconto, +Markdown Editor,Editor de Markdown, Marked As Spam,Marcado como spam, Max 500 records at a time,Máximo de 500 registros por vez, +Max Attachment Size (in MB),Max tamanho do anexo (em MB), Max Attachments,Máx. de Anexos, +Max Length,Comprimento máximo, +Max Value,Max Valor, Max width for type Currency is 100px in row {0},Largura máxima para o tipo de moeda é 100px na linha {0}, Maximum Attachment Limit for this record reached.,Limite máximo de anexo para este recorde atingido., Maximum {0} rows allowed,Máximo de {0} linhas permitido, "Meaning of Submit, Cancel, Amend","Significado de Enviar, Cancelar, Corrigir", -Menu,Opções, +Mention transaction completion page URL,Mencione transação página de conclusão do URL, +Mentions,Menções, +Menu,Menu, +Merchant ID,ID do comerciante, Merge with existing,Mesclar com existente, Merging is only possible between Group-to-Group or Leaf Node-to-Leaf Node,A fusão só é possível entre o grupos, +Message Count,Contagem de mensagens, +Message ID,ID da Mensagem, Message Parameter,Parâmetro da mensagem, -Milestone,Marco, -Missing parameter Kanban Board Name,Parâmetro faltando Nome do Painel Kanban, +Message Preview,Pré-visualização da mensagem, +Message clipped,Mensagem cortada, +Message not setup,Mensagem não configurada, +Message to be displayed on successful completion (only for Guest users),Mensagem a ser exibida na conclusão bem sucedida (somente para usuários convidados), +Message-id,Message-id, +Meta Tags,Meta Tags, +Migration ID Field,ID de Campo de Migração, +Milestone,Milestone, +Milestone Tracker,Milestone Tracker, +Minimum Password Score,Score Mínimo de Senha, +Miss,Senhorita, +Missing Fields,Campos ausentes, +Missing parameter Kanban Board Name,Parâmetro faltando Kanban Board Name, Missing parameters for login,Parâmetros que faltam para o login, Models (building blocks) of the Application,Modelos (blocos de construção) do aplicativo, -Module Def,Módulo Def, +Modified By,Modificado por, +Module,Módulo, +Module Def,Def. Módulo, +Module Name,Nome do Módulo, Module Not Found,Módulo não encontrado, +Module Path,Caminho do módulo, +Module to Export,Módulo para Exportar, Modules HTML,Módulos HTML, Monospace,Monospace, +More articles on {0},Mais artigos sobre {0}, More content for the bottom of the page.,Mais conteúdo na parte de baixo da página., Most Used,Mais Usados, +Move To,Mover Para, +Move To Trash,Mover para lixeira, +Move to Row Number,Mover para o número da linha, +Mr,Sr., +Mrs,Sra, +Ms,Sra., Multiple root nodes not allowed.,"Vários nós raiz, não é permitido .", +Multiplier Field,Campo Multiplicador, +Must be of type "Attach Image",Deve ser do tipo "Anexar Imagem", Must have report permission to access this report.,Deve ter permissão para acessar relatório deste relatório., Must specify a Query to run,Deve especificar uma consulta para executar, -Mute Sounds,Desativar sons, +Mute Sounds,Desativar Sons, +MyISAM,MyISAM, Name Case,Caso Nome, Name cannot contain special characters like {0},Nome não pode conter caracteres especiais como {0}, Name not set via prompt,Nome não definido através Prompt, Name of the Document Type (DocType) you want this field to be linked to. e.g. Customer,"Nome do Tipo de Documento (DocType) pretende que este campo a ser vinculado. por exemplo, o Cliente", +Name of the new Print Format,Nome do novo Formato de Impressão, Name of {0} cannot be {1},Nome de {0} não pode ser {1}, +Names and surnames by themselves are easy to guess.,Os nomes e sobrenomes são fáceis de adivinhar., Naming,Nomeação, +"Naming Options:\n
    1. field:[fieldname] - By Field
    2. naming_series: - By Naming Series (field called naming_series must be present
    3. Prompt - Prompt user for a name
    4. [series] - Series by prefix (separated by a dot); for example PRE.#####
    5. \n
    6. format:EXAMPLE-{MM}morewords{fieldname1}-{fieldname2}-{#####} - Replace all braced words (fieldnames, date words (DD, MM, YY), series) with their value. Outside braces, any characters can be used.
    ","Opções de Nomenclatura:
    1. field: [fieldname] - Por campo
    2. naming_series: - Por Naming Series (campo chamado naming_series deve estar presente
    3. Prompt - Solicitar um nome para o usuário
    4. [série] - Série por prefixo (separado por um ponto); por exemplo PRE. #####
    5. format: EXAMPLE- {MM} morewords {fieldname1} - {fieldname2} - {#####} - Substitua todas as palavras braced (nomes de campo, palavras de data (DD, MM, YY), série) pelo seu valor. Chaves externas, todos os caracteres podem ser usados.
    ", Naming Series mandatory,Nomeando obrigatório Series, Nested set error. Please contact the Administrator.,Erro conjunto aninhado . Entre em contato com o administrador., +New Activity,Nova Atividade, +New Chat,Novo Chat, +New Comment on {0}: {1},Novo comentário em {0}: {1}, +New Connection,Nova conexão, +New Custom Print Format,Novo Formato de Impressão Personalizado, +New Email,Novo Email, New Email Account,Nova conta de email, -New Folder,Nova pasta, +New Event,Novo Evento, +New Folder,Nova Pasta, New Kanban Board,Novo Painel Kanban, New Message from Website Contact Page,Nova Mensagem da Página de Contato do Site, -New Password,Nova senha, +New Name,Novo Nome, +New Newsletter,Nova Newsletter, +New Password,Nova Senha, New Password Required.,É necessário uma nova senha., +New Print Format Name,Novo nome do formato de impressão, New Report name,Nome do novo Relatório, New Value,Novo Valor, +New data will be inserted.,Novos dados serão inseridos., +New updates are available,Novas atualizações estão disponíveis, +New value to be set,Novo valor a ser definido, New {0},Novo(a) {0}, +New {} releases for the following apps are available,Novas {} versões para os seguintes aplicativos estão disponíveis, Newsletter Email Group,Grupo de Email de Newsletter, +Newsletter Manager,Gestor de Newsletter, Newsletter has already been sent,A Newsletter já foi enviada, -"Newsletters to contacts, leads.","Email Marketing para Contatos, Leads.", +"Newsletters to contacts, leads.",Email Marketing para Contatos e Clientes em Potencial., +Next Action Email Template,Modelo de email de próxima ação, +Next Actions HTML,Próxima Ações HTML, Next Schedule Date,Próxima data programada, +Next Scheduled Date,Próxima data agendada, +Next State,Próximo Status, +Next Sync Token,Próximo token de sincronização, +Next actions,Próximas ações, No Active Sessions,Nenhuma sessão ativa, +No Copy,Nenhuma Cópia, +No Email Account,Sem conta de email, +No Email Accounts Assigned,Não há contas de email Assigned, No Emails,Nenhum Email, +No Label,Sem Rótulo, +No Permissions Specified,Não há permissões especificadas, No Permissions set for this criteria.,Sem permissões definidas para este critério., -No Results,nenhum resultado, -No Tags,Sem tags, +No Preview,Não há visualização, +No Preview Available,Não há visualização disponível, +No Printer is Available.,Nenhuma impressora está disponível., +No Results,Nenhum Resultado, +No Tags,Sem Tags, +No alerts for today,Não há alertas para hoje, +No comments yet,Ainda não há comentários, +No comments yet. Start a new discussion.,Ainda não há comentários. Iniciar uma nova discussão., +No data found in the file. Please reattach the new file with data.,Nenhum dado encontrado no arquivo. Recoloque o novo arquivo com dados., +No document found for given filters,Nenhum documento encontrado para determinados filtros, +No fields found that can be used as a Kanban Column. Use the Customize Form to add a Custom Field of type "Select".,Nenhum campo encontrado que possa ser usado como uma coluna Kanban. Use o formulário Personalizar para adicionar um campo personalizado do tipo "Selecionar"., No file attached,Nenhum arquivo anexado, No further records,Não há mais registros, No matching records. Search something new,Não há registros correspondentes. Procure algo novo, +"No need for symbols, digits, or uppercase letters.","Não há necessidade de símbolos, dígitos ou letras maiúsculas.", No of Columns,Nenhuma das Colunas, No of Rows (Max 500),Número de linhas (max 500), No of emails remaining to be synced,Nº de emails a serem sincronizados, +No permission for {0},Sem permissão para {0}, +No permission to '{0}' {1},Sem permissão para '{0} ' {1}, +No permission to read {0},Sem permissão para ler {0}, +No permission to {0} {1} {2},Sem permissão para {0} {1} {2}, +No records deleted,Nenhum registro foi excluído, +No records present in {0},Nenhum registro presente em {0}, No records tagged.,Não há registros marcados., No template found at path: {0},Nenhum modelo encontrado no caminho: {0}, No {0} found,Nenhum(a) {0} encontrado(a), No {0} mail,Nenhum {0}, +No {0} permission,Sem permissão {0}, None: End of Workflow,Nenhum: Fim do fluxo de trabalho, -Not Equals,Diferente de, +Not Allowed: Disabled User,Não permitido: Usuário desativado, +Not Ancestors Of,Não antepassados de, +Not Descendants Of,Não Descendentes De, +Not Equals,Diferente, Not In,Não Presente, +Not Linked to any record,Não vinculado a nenhum registro, +Not Published,Não Publicado, Not Saved,Não Salvo, -Not Sent,Não Enviados, -Not Set,Não Definido, +Not Seen,Não Visto, +Not Sent,Não Enviado, +Not Set,Não Selecionado, Not a valid Comma Separated Value (CSV File),Não é um valor CSV válido (arquivo CSV), +Not a valid User Image.,Não é uma imagem de usuário válida., +Not a valid Workflow Action,Não é uma ação válida do fluxo de trabalho, Not a valid user,Não é um usuário válido, +Not a zip file,Não é um arquivo zip, +Not allowed for {0}: {1},Não permitido para {0}: {1}, +Not allowed for {0}: {1} in Row {2}. Restricted field: {3},Não permitido para {0}: {1} na linha {2}. Campo restrito: {3}, +Not allowed for {0}: {1}. Restricted field: {2},Não permitido para {0}: {1}. Campo restrito: {2}, Not allowed to Import,Não é permitido importar, Not allowed to change {0} after submission,Não é permitido alterar {0} após a apresentação, Not allowed to print cancelled documents,Não permitido para imprimir documentos cancelados, Not allowed to print draft documents,Não permitido para imprimir documentos de rascunho, +Not enough permission to see links,Não há permissão suficiente para ver links, Not in Developer Mode,Você não está no modo de desenvolvedor, Not in Developer Mode! Set in site_config.json or make 'Custom' DocType.,Você não está no modo de desenvolvedor! Configure em site_config.json ou faça um DocType 'Personalizado'., Note Seen By,Nota Vista por, +Note:,Nota:, +Note: By default emails for failed backups are sent.,"Nota: Por padrão, os e-mails para backups com falha são enviados.", +Note: Changing the Page Name will break previous URL to this page.,Nota: Alterar o Nome da Página irá interromper o URL anterior para esta página., +"Note: For best results, images must be of the same size and width must be greater than height.","Nota: Para obter melhores resultados, as imagens devem ter o mesmo tamanho e a largura deve ser maior que a altura.", Note: Multiple sessions will be allowed in case of mobile device,Observação: Serão permitidas múltiplas sessões no caso de dispositivo móvel, Nothing to show,Nada para mostrar, +Nothing to update,Nada para atualizar, +Notification,Notificação, +Notification Recipient,Destinatário da Notificação, +Notification Tones,Tons de notificação, +Notifications,Notificações, Notifications and bulk mails will be sent from this outgoing server.,Notificações e emails em massa serão enviados por este servidor de saída., +Notify Users On Every Login,Notificar usuários em cada login, Notify if unreplied,Informar se não for respondido, Notify if unreplied for (in mins),Informar se não for respondido em (minutos), +Notify users with a popup when they log in,Notificar os usuários com um pop-up quando eles entram, Number Format,Formato de número, +Number of Backups,Número de Backups, +Number of DB Backups,Número de backups de banco de dados, +Number of DB backups cannot be less than 1,Número de backups de banco de dados não pode ser menor que 1, Number of columns for a field in a Grid (Total Columns in a grid should be less than 11),O número de colunas para um campo numa Grelha (O Total de Colunas em um grid deve ser inferior a 11), +Number of columns for a field in a List View or a Grid (Total Columns should be less than 11),Número de colunas para um campo em uma lista ou de um Grid (Total de colunas deve ser inferior a 11), OAuth Authorization Code,Código de Autorização OAuth, +OAuth Bearer Token,OAuth Bearer Token, +OAuth Client,Cliente OAuth, OAuth Provider Settings,Configurações do Provedor OAuth, +OTP App,Aplicação OTP, +OTP Issuer Name,Nome da Emissora OTP, +OTP Secret has been reset. Re-registration will be required on next login.,OTP Secret foi reiniciado. O novo registro será requerido no próximo login., +OTP secret can only be reset by the Administrator.,O Secretário OTP só pode ser redefinido pelo Administrador., +Office,Escritório, +Office 365,Office 365, +Old Password,Senha Antiga, +Old Password Required.,Senha antiga necessária., Older backups will be automatically deleted,Os backups mais antigos serão apagados automaticamente, +"On {0}, {1} wrote:","Em {0}, {1} escreveu:", +"Once submitted, submittable documents cannot be changed. They can only be Cancelled and Amended.","Depois de enviados, os documentos enviados não podem ser alterados. Eles só podem ser cancelados e alterados.", "Once you have set this, the users will only be able access documents (eg. Blog Post) where the link exists (eg. Blogger).","Depois de ter definido isso, os usuários só poderão ser acessar documentos capazes (ex. Blog Post) onde existe a ligação (por exemplo, Blogger ) .", +One Last Step,Um Último Passo, +One Time Password (OTP) Registration Code from {},Código de registro de senha de uma vez (OTP) de {}, Only 200 inserts allowed in one request,São permitidas somente 200 inserções por solicitação, Only Administrator can delete Email Queue,Somente o administrador pode deletar a fila de emails, Only Administrator can edit,Somente o Administrador pode editar, Only Administrator can save a standard report. Please rename and save.,"Somente o Administrador pode salvar um relatório padrão. Por favor, renomear e salvar.", +Only Administrator is allowed to use Recorder,Apenas o administrador tem permissão para usar o gravador, Only Allow Edit For,Somente permite edição para, +Only Send Records Updated in Last X Hours,Somente Enviar Registros Atualizados em Últimas X Horas, Only mandatory fields are necessary for new records. You can delete non-mandatory columns if you wish.,"Somente os campos obrigatórios são necessários para novos registros. Você pode excluir colunas não-obrigatórias, se desejar.", +Only standard DocTypes are allowed to be customized from Customize Form.,Somente DocTypes padrão podem ser personalizados no Custom Form., +Only users involved in the document are listed,Somente usuários envolvidos no documento são listados, Only {0} emailed reports are allowed per user,Somente {0} relatórios enviados poe email são permitidos por usuário, Oops! Something went wrong,Ops! Aconteceu algo inesperado, "Oops, you are not allowed to know that","Ops, você não tem permissão para saber isso", +Open Link,Abrir Link, Open Source Applications for the Web,Aplicativos Open Source para a Web, +Open Translation,Open Translation, +Open a dialog with mandatory fields to create a new record quickly,Abra uma caixa de diálogo com campos obrigatórios para criar um novo registro rapidamente, Open a module or tool,Abra um módulo ou ferramenta, +Open your authentication app on your mobile phone.,Abra seu aplicativo de autenticação em seu telefone celular., +Open {0},Abrir {0}, Opened,Inaugurado, +Operator must be one of {0},O operador deve ser um dos {0}, +Option 1,Opção 1, +Option 2,Opção 2, +Option 3,Opção 3, +Optional: Always send to these ids. Each Email Address on a new row,Opcional: Sempre enviar para estes ids. Cada endereço de email em uma nova linha, Optional: The alert will be sent if this expression is true,Opcional: O alerta será enviado se essa expressão é verdadeira, -Options 'Dynamic Link' type of field must point to another Link Field with options as 'DocType',"Opções 'Dynamic Link' tipo de campo deve apontar para um outro campo Ligação com opções como ""TipoDoc '", +Options 'Dynamic Link' type of field must point to another Link Field with options as 'DocType',Opções 'Dynamic Link' tipo de campo deve apontar para um outro campo Ligação com opções como "TipoDoc ', Options Help,Ajuda sobre Opções, Options for select. Each option on a new line.,Opções para selecionar. Cada opção em uma nova linha., Options not set for link field {0},Opções não definida para o campo link {0}, @@ -728,109 +1775,270 @@ Or login with,Ou faça login com, Order,Pedido, Org History,História da Organização, Org History Heading,Cabeçalho da História da Organização, +Orientation,Orientação, Original Value,Valor Original, +Outgoing email account not correct,Conta de e-mail de saída não correto, +Outlook.com,Outlook.com, +Output,Saída, +PDF,PDF, PDF Page Size,Tamanho da página PDF, PDF Settings,Configurações do PDF, +PDF generation failed,Geração de PDF falhou, +PDF generation failed because of broken image links,Geração de PDF falhou por causa de links de imagens quebradas, +PDF printing via "Raw Print" is not yet supported. Please remove the printer mapping in Printer Settings and try again.,A impressão em PDF por meio de "Impressão bruta" ainda não é suportada. Remova o mapeamento da impressora em Configurações da impressora e tente novamente., +Page HTML,Página HTML, +Page Length,Comprimento da página, +Page Name,Nome da Página, +Page Settings,Configurações da página, Page has expired!,A página expirou!, -Page to show on the website\n,Página para mostrar no site, +Page not found,Página não encontrada, +Page to show on the website\n,Página a mostrar no website, Pages in Desk (place holders),Páginas na Desk (suportes do lugar), -Parent,Parente, +Parent,Principal, Parent Error Snapshot,Pai Snapshot de Erro, -Parent Label,Etiqueta pai, -Parent Table,Tabela Parent, -Passive,Sem movimento, +Parent Label,Etiqueta Pai, +Parent Table,Tabela Pai, +Parent is required to get child table data,Pai é necessário para obter dados da tabela filho, +Parent is the name of the document to which the data will get added to.,Pai é o nome do documento ao qual os dados serão adicionados., +Partial Success,Sucesso parcial, +Partially Successful,Parcialmente bem sucedido, +Participants,Participantes, +Passive,Passivo, +Password Reset,Redefinição de Senha, +Password Updated,Senha Atualizada, +Password for Base DN,Senha para DN de base, +Password is required or select Awaiting Password,Senha é necessária ou selecione Aguardando senha, +Password not found,Senha não encontrada, Password reset instructions have been sent to your email,Instruções de redefinição de senha foram enviadas para seu email, +Paste,Colar, Patch,Remendo, Patch Log,Log de Patches, +Path to CA Certs File,Caminho para o arquivo CA Certs, +Path to Server Certificate,Caminho para o certificado do servidor, +Path to private Key File,Caminho para o arquivo de chaves privado, +PayPal Settings,Configurações PayPal, +PayPal payment gateway settings,configurações de gateway de pagamento PayPal, Payment Cancelled,Pagamento cancelado, +Payment Failed,Pagamento falhou, +Payment Success,Sucesso de pagamento, +Pending Approval,Aprovação pendente, +Pending Verification,verificação pendente, Percent,Por cento, +Percent Complete,Percentagem completa, Perm Level,Nível Permanente, +Permanent,Permanente, +Permanently Cancel {0}?,Cancelar Permanentemente {0} ?, Permanently Submit {0}?,Confirmar Permanentemente {0} ?, Permanently delete {0}?,Excluir Permanentemente {0} ?, -"Permissions are set on Roles and Document Types (called DocTypes) by setting rights like Read, Write, Create, Delete, Submit, Cancel, Amend, Report, Import, Export, Print, Email and Set User Permissions.","As permissões são definidas em Funções e Tipos de Documentos (chamados Doctypes ) , definindo direitos como Ler, Escrever, Criar, Deletar, Enviar, Cancelar, Corrigir, Reportar, Importar, Exportar, Imprimir, Email e Definir Permissões de Usuário.", -Permissions at higher levels are Field Level permissions. All Fields have a Permission Level set against them and the rules defined at that permissions apply to the field. This is useful in case you want to hide or make certain field read-only for certain Roles.,As permissões em níveis mais elevados são permissões igualdade. Todos os campos têm um conjunto Nível de Permissão contra eles e as regras definidas em que as permissões se aplicam ao campo. Isso é útil no caso de você querer esconder ou fazer determinado campo somente leitura para certas funções., +Permission Error,Erro de permissão, +Permission Level,Nível de Permissão, +Permission Levels,Níveis de Permissão, +Permission Rules,Regras de Permissão, +Permissions,Permissões, +Permissions are automatically applied to Standard Reports and searches.,As permissões são aplicadas automaticamente a relatórios e pesquisas padrão., +"Permissions are set on Roles and Document Types (called DocTypes) by setting rights like Read, Write, Create, Delete, Submit, Cancel, Amend, Report, Import, Export, Print, Email and Set User Permissions.","As permissões são definidas em Funções e Tipos de Documentos (chamados Doctypes) , definindo direitos como Ler, Escrever, Criar, Deletar, Enviar, Cancelar, Corrigir, Reportar, Importar, Exportar, Imprimir, Email e Definir Permissões de Usuário.", +Permissions at higher levels are Field Level permissions. All Fields have a Permission Level set against them and the rules defined at that permissions apply to the field. This is useful in case you want to hide or make certain field read-only for certain Roles.,As permissões de níveis superiores são permissões de Nível de Campo. Todos os Campos têm um conjunto de Nível de Permissão e as regras definidas nessas permissões aplicam-se ao campo. Isto é útil caso queira ocultar ou fazer com que determinado campo seja só de leitura para certas Funções., "Permissions at level 0 are Document Level permissions, i.e. they are primary for access to the document.","As permissões para o nível 0 são permissões em nível de documento, ou seja, eles são primários para o acesso ao documento.", Permissions get applied on Users based on what Roles they are assigned.,As permissões são aplicadas em usuários com base nas funções que lhe são atribuídas., +Personal,Pessoal, +Personal Data Deletion Request,Solicitação de Exclusão de Dados Pessoais, +Personal Data Download Request,Solicitação de download de dados pessoais, Phone No.,Nº de Telefone., +Pick Columns,Escolher Colunas, Plant,Fábrica, Please Duplicate this Website Theme to customize.,Por favor Duplicar este site Tema para personalizar., +Please Enter Your Password to Continue,"Por favor, digite sua senha para continuar", +Please Install the ldap3 library via pip to use ldap functionality.,"Por favor, instale a biblioteca ldap3 via pip para usar a funcionalidade ldap.", Please Update SMS Settings,Atualize Configurações SMS, +Please add a subject to your email,"Por favor, adicione um assunto ao seu email", +Please ask your administrator to verify your sign-up,"Por favor, pergunte ao seu administrador para verificar a sua inscrição", Please attach a file first.,"Por favor, anexar um arquivo primeiro", +Please attach an image file to set HTML,"Por favor, anexe um arquivo de imagem para definir HTML", +Please check your email for verification,"Por favor, verifique seu e-mail para verificação", +Please check your registered email address for instructions on how to proceed. Do not close this window as you will have to return to it.,"Verifique seu endereço de e-mail registrado para obter instruções sobre como proceder. Não feche esta janela, pois você terá que retornar a ela.", +Please close this window,"Por favor, feche esta janela", +Please confirm your action to {0} this document.,"Por favor, confirme sua ação para {0} este documento.", Please do not change the rows above {0},"Por favor, não alterar as linhas acima {0}", Please do not change the template headings.,"Por favor, não alterar as posições do modelo.", Please duplicate this to make changes,"Por favor, duplicar este para fazer mudanças", +Please enable developer mode to create new connection,Ative o modo de desenvolvedor para criar uma nova conexão, Please ensure that your profile has an email address,Verifique se o seu perfil tem um endereço de email, +Please enter Access Token URL,Digite o URL do token de acesso, +Please enter Authorize URL,Digite Autorizar URL, +Please enter Base URL,Digite o URL da Base, +Please enter Client ID before social login is enabled,Digite o ID do cliente antes que o login social seja ativado, +Please enter Client Secret before social login is enabled,Digite Client Secret antes do login social estar habilitado, +Please enter Redirect URL,Digite o URL de redirecionamento, Please enter the password,Por favor digite a senha, Please enter valid mobile nos,"Por favor, indique números de celular válidos", +Please enter values for App Access Key and App Secret Key,Por favor insira os valores para acesso App Key e App chave secreta, Please make sure that there are no empty columns in the file.,"Por favor, certifique-se de que não existem colunas vazias no arquivo.", +Please make sure the Reference Communication Docs are not circularly linked.,Certifique-se de que os Documentos de Comunicação de Referência não estejam vinculados circularmente., Please refresh to get the latest document.,Por favor de atualização para obter os últimos documentos., Please save before attaching.,"Por favor, salve antes de anexar.", Please save the Newsletter before sending,"Por favor, salve a Newsletter antes de enviar", Please save the document before assignment,"Por favor, salve o documento antes da atribuição", Please save the document before removing assignment,"Por favor, salve o documento antes de remover a atribuição", +Please save the report first,"Por favor, salve o primeiro relatório", Please select DocType first,"Por favor, selecione DocType primeiro", +Please select Entity Type first,"Por favor, selecione Tipo de Entidade primeiro", +Please select Minimum Password Score,Selecione Mínimo de Marcação de Senha, Please select a Amount Field.,Por favor selecione um campo total., Please select a file or url,"Por favor, selecione um arquivo ou url", +Please select a new name to rename,Selecione um novo nome para renomear, Please select a valid csv file with data,"Por favor, selecione um arquivo csv com dados válidos", +Please select another payment method. PayPal does not support transactions in currency '{0}',Selecione outra forma de pagamento. O PayPal não suporta transações em moeda '{0}', +Please select another payment method. Razorpay does not support transactions in currency '{0}',Selecione outra forma de pagamento. não Razorpay não suporta transações em moeda '{0}', +Please select atleast 1 column from {0} to sort/group,"Por favor, selecione pelo menos coluna 1 a partir de {0} para classificar / grupo", +Please select document type first.,"Por favor, selecione o tipo de documento primeiro.", +Please select the Document Type.,Selecione o Tipo de documento., +Please set Base URL in Social Login Key for Frappe,Defina o URL básico na chave de login social para Frappe, Please set Dropbox access keys in your site config,Defina teclas de acesso Dropbox em sua configuração local, -Please set filters,Por favor defina os filtros, +Please set a printer mapping for this print format in the Printer Settings,"Por favor, defina um mapeamento de impressora para este formato de impressão nas configurações da impressora.", +Please set filters,"Por favor, defina filtros", +Please set filters value in Report Filter table.,"Por favor, definir o valor de filtros na tabela Filtro de Relatório.", +"Please setup SMS before setting it as an authentication method, via SMS Settings","Configure o SMS antes de configurá-lo como um método de autenticação, por meio de Configurações de SMS", +Please setup a message first,"Por favor, configure uma mensagem primeiro", Please specify which date field must be checked,Por favor especificar qual campo de data deve ser verificado, Please specify which value field must be checked,Por favor especificar qual campo deve ser verificado, +Please try again,"Por favor, tente novamente", Please verify your Email Address,"Por favor, verifique seu endereço de email", +Point Allocation Periodicity,Periodicidade de alocação de pontos, +Points,Pontos, +Points Given,Pontos dados, +Port,Porta, Portal Menu,Portal menu, Portal Menu Item,Portal item de menu, -Post,Postar, +Post,Post, +Post Comment,Publicar comentário, +Postal,Postal, Postal Code,CEP, +Postprocess Method,Método de pós-processamento, Posts,Postagens, Posts by {0},Posts de {0}, +Posts filed under {0},Posts arquivados em {0}, +Precision,Precisão, Precision should be between 1 and 6,Precisão deve estar entre 1 e 6, +Predictable substitutions like '@' instead of 'a' don't help very much.,"As substituições previsíveis, como '@' em vez de 'a' não ajudam muito.", Preferred Billing Address,Endereço preferido de faturamento, Preferred Shipping Address,Endereço preferido para entrega, +Prepared Report,Relatório preparado, +Preparing Report,Preparando Relatório, +Preprocess Method,Método de pré-processamento, +Press Enter to save,Pressione Enter para salvar, Preview HTML,Pré-visualização de HTML, +Preview Message,Visualizar mensagem, +Previous,Anterior, +Previous Hash,Hash anterior, +Primary Color,Cor primária, +Print Documents,Imprimir documentos, Print Format Builder,Criar/Editar Formato de Impressão, Print Format Help,Ajuda sobre Formatos de Impressão, Print Format Type,Tipo do Formato de Impressão, Print Format {0} is disabled,Formato de Impressão {0} está desativado, Print Hide,Ocultar Impressão, Print Hide If No Value,Ocultar Impressão se não Preenchido, +Print Sent to the printer!,Imprimir Enviado para a impressora!, +Print Server,Servidor de impressão, +Print Style,Estilo de Impressão, +Print Style Name,Nome do estilo de impressão, Print Style Preview,Estilo de visualização de impressão, Print Width,Largura de impressão, "Print Width of the field, if the field is a column in a table","Largura de impressão do campo, se o campo é uma coluna na tabela", Print with letterhead,Imprimir com o timbre, +Printer,Impressora, +Printer Mapping,Mapeamento de Impressora, +Printer Name,Nome da impressora, +Printer Settings,Configurações da Impressora, +Printing failed,Impressão falhou, +Private Key,Chave privada, Private and public Notes.,Privadas e públicas Notas., +ProTip: Add Reference: {{ reference_doctype }} {{ reference_name }} to send document reference,Protip: Adicionar Reference: {{ reference_doctype }} {{ reference_name }} para enviar referência do documento, +Processing,Em processamento, +Processing...,Em processamento..., +Prof,Prof, +Progress,Progresso, Property Setter,Configurador de Propriedades, Property Setter overrides a standard DocType or Field property,O configurador de propriedades substitui o DocType padrão ou propriedade de campo, Property Type,Tipo de propriedade, +Provider,Fornecedor, +Provider Name,Nome do provedor, +Public Key,Chave pública, +Publishable Key,Chave publicável, Published On,Publicado no, +Pull,Puxar, +Pull Failed,Puxar falhou, +Pull Insert,Inserir puxar, +Pull Update,Puxe a Atualização, +Push,Empurrar, +Push Delete,Pressione Excluir, +Push Failed,Push Failed, +Push Insert,Push Insert, +Push Update,Atualização de envio, +Python Module,Módulo Python, +Pyver,Pyver, QR Code,QR Code, +QR Code for Login Verification,Código QR para verificação de login, +QZ Tray Connection Active!,Conexão da Bandeja QZ Ativo!, +QZ Tray Failed: ,QZ Tray Failed:, Quarter Day,1/4 do Dia, +Query,Consulta, Query Report,Relatório da Consulta, Query must be a SELECT,Consulta deve ser um SELECT, +Queue should be one of {0},A fila deve ser uma de {0}, Queued for backup. It may take a few minutes to an hour.,Na fila para backup em até uma hora., +Queued for backup. You will receive an email with the download link,Em fila para backup. Você receberá um e-mail com o link de download, Quick Help for Setting Permissions,Ajuda rápida para Configurar Permissões, Rating: ,Rating:, +Raw Commands,Comandos brutos, Raw Email,Email Puro, +Raw Printing,Impressão Raw, +Razorpay Payment gateway settings,configurações de gateway de pagamento Razorpay, +Razorpay Settings,Configurações Razorpay, +Re: ,Re: , +Re: {0},Re: {0}, +Read,Ler, Read Only,Somente Leitura, +Read by Recipient,Lido por destinatário, +Read by Recipient On,Lido por destinatário ativado, +Rebuild,Reconstruir, Receiver Parameter,Parâmetro do recebedor, +Recent years are easy to guess.,Os anos recentes são fáceis de adivinhar., +Recipient,Destinatário, Recipient Unsubscribed,Destinatário com inscrição cancelada, Record does not exist,Registro não existe, -Redirect To,Redirecionar para, +Records for following doctypes will be filtered,Registros para seguir doctypes serão filtrados, +Redirect To,redirecionar para, +Redirect URI Bound To Auth Code,URI de redirecionamento Bound To Código Auth, +Redirect URIs,redirecionar URIs, Redis cache server not running. Please contact Administrator / Tech support,Servidor de cache Redis não está funcionando. Entre em contato com o Administrador de apoio / Tecnologia, Ref DocType,DocType de Ref., +Ref Report DocType,Ref Report DocType, +Reference DocName,Nome do Documento de Referência, Reference DocType and Reference Name are required,Referência DocType e nome de referência são necessários, +Reference Report,Relatório de referência, +Reference: {0} {1},Referência: {0} {1}, Refreshing...,Atualizando..., Register OAuth Client App,Registrar App OAuth Cliente, Registered but disabled,Registrado mas desativado, Relapsed,Reincidente, Relapses,Recaídas, -Relink,Relinkar, -Relink Communication,Relinkar Comunicação, -Relinked,Relinkado, +Relink,Religar, +Relink Communication,Religar Comunicação, +Relinked,Religado, Reload,Recarregar, Remember Last Selected Value,Lembrar última seleção, Remote,Remoto, +Remote Fieldname,Remote Fieldname, +Remote ID,ID Remoto, +Remote Objectname,Remote Objectname, +Remote Primary Key,Chave primária remota, Remove,Remover, Remove Field,Remover Campo, +Remove Filter,Remover Filtro, +Remove Section,Remover Seção, +Remove Tag,Remova Tag, +Remove all customizations?,Remover todas as personalizações?, Removed {0},Removido {0}, Rename many items by uploading a .csv file.,Renomeie muitos itens fazendo o upload de um arquivo csv., Rename {0},Mudar o nome {0}, @@ -839,246 +2047,693 @@ Repeat On,Repetir em, Repeat Till,Repita até que, Repeat on Day,Repetir no dia, Repeat this Event,Repita este evento, +Repeats like "aaa" are easy to guess,Repetições como "aaa" são fáceis de adivinhar, +Repeats like "abcabcabc" are only slightly harder to guess than "abc",Repetições como "abcabcabc" são somente um pouco mais difícil de adivinhar que "abc", +Reply,Responder, +Reply All,Responder a todos, +Report End Time,Hora de término do relatório, +Report Filters,Filtros de relatório, +Report Hide,Ocultar Relatório, +Report Manager,Gestor de Relatórios, +Report Name,Nome do Relatório, +Report Start Time,Hora de início do relatório, Report cannot be set for Single types,Relatório não pode ser ajustada para os modelos únicos, Report of all document shares,Relatório de todas as ações de documentos, +Report updated successfully,Relatório atualizado com sucesso, Report was not saved (there were errors),O Relatório não foi salvo (houve erros), +Report {0},Relatório {0}, Report {0} is disabled,Relatório {0} está desativado, +Report:,Relatório:, Represents a User in the system.,Representa um usuário no sistema., -Represents the states allowed in one document and role assigned to change the state.,Representa os estados permitidos em um documento e papel atribuído para alterar o estado., +Represents the states allowed in one document and role assigned to change the state.,Representa os estados permitidos em um documento e função atribuído para alterar o estado., Request Timed Out,Solicitação expirada, +Request URL,URL do pedido, +Require Trusted Certificate,Exigir certificado confiável, +Res: {0},Res: {0}, +Reset OTP Secret,Redefinir OTP Secret, +Reset Password,Redefinir Senha, Reset Password Key,Redefinição de senha chave, Reset Permissions for {0}?,Repor permissões para {0} ?, Reset to defaults,Restaurar Padrões, +Reset your password,Redefinir sua senha, +Response Type,Tipo de resposta, +Restore,Restaurar, Restore Original Permissions,Restaurar permissões originais, +Restore or permanently delete a document.,Restaure ou exclua permanentemente um documento., Restore to default settings?,Restaurar as configurações padrão?, +Restored,Restaurado, +Restrict IP,Restringir IP, +Restrict To Domain,Restringir ao domínio, +Restrict user for specific document,Restringir usuário para documento específico, Restrict user from this IP address only. Multiple IP addresses can be added by separating with commas. Also accepts partial IP addresses like (111.111.111),Restringir usuário a partir deste endereço IP. Vários endereços IP podem ser adicionados ao separar com vírgulas. São aceitos também endereços IP parciais como (111.111.111), Resume Sending,Retomar Envio, -Reverse Icon Color,Inverter Cor do Ícone, +Retake,Retomar, +Retry,Repetir, +Return to the Verification screen and enter the code displayed by your authentication app,Retorne à tela de Verificação e insira o código exibido pelo seu aplicativo de autenticação, +Reverse Icon Color,Inverta Ícone Cor, +Revert,Reverter, +Revert Of,Reverter, +Reverted,Revertido, +Review Level,Nível de revisão, +Review Levels,Revisar Níveis, +Review Points,Pontos de revisão, +Reviews,Rever, +Revoke,Revogar, Revoked,Revogado, -Rich Text,Texto formatado, -Roles Assigned,Funções atribuídas, +Rich Text,Rich Text, +Robots.txt,Robots.txt, +Role Name,Nome da Função, +Role Permission for Page and Report,Permissão de Função para Página e Relatório, +Role Permissions,Permissões da Função, +Role Profile,Perfil de Função, +Role and Level,Função e Nível, +Roles,Funções, +Roles Assigned,Funções Atribuídas, Roles can be set for users from their User page.,As funções podem ser definidas para os usuários através de sua página de Usuário., Root {0} cannot be deleted,Root {0} não pode ser excluído, +Round Robin,Robin Redondo, +Route History,História da rota, +Route Redirects,Redirecionamentos de rota, +Route to Success Link,Rota para o Link de Sucesso, +Row,Linha, Row #{0}:,Linha # {0}:, +Row Index,Índice de linhas, Row No,Linha No, +Row Status,Status da fila, Row Values Changed,Valores das Linhas Mudaram, +Row {0}: Not allowed to disable Mandatory for standard fields,Linha {0}: Não é permitido desativar Obrigatório para campos padrão, Row {0}: Not allowed to enable Allow on Submit for standard fields,Linha {0}: Não é permitido habilitar Permitir ao Enviar para campos padrão, Rows Added,Linhas Adicionadas, Rows Removed,Linhas Excluídas, +Rule,Regra, +Rule Name,Nome da regra, Rules defining transition of state in the workflow.,Regras que definem a transição de status no fluxo de trabalho., "Rules for how states are transitions, like next state and which role is allowed to change state etc.","Regras de como os status são alterados, como o próximo status e que função terá permissão para mudar de status, etc", +Run,Corre, Run scheduled jobs only if checked,As tarefas agendadas somente serão executadas se a opção estiver marcada, S3 Backup Settings,Configurações de Backup S3, +S3 Backup complete!,S3 Backup completo!, +SMS,SMS, SMS Gateway URL,URL de Gateway para SMS, +SMS Parameter,Parâmetro de SMS, SMS Settings,Configurações de SMS, +SMS sent to following numbers: {0},SMS enviado a seguintes números: {0}, +SMTP Server,Servidor SMTP, SMTP Settings for outgoing emails,Configurações de SMTP para envio de emails, -"SQL Conditions. Example: status=""Open""","Condições SQL. Exemplo: status=""Open""", +SQL Conditions. Example: status="Open",Condições SQL. Exemplo: status="Open", +SSL/TLS Mode,Modo SSL / TLS, Salesforce,Salesforce, +Same Field is entered more than once,O mesmo campo foi inserido mais de uma vez, +Save API Secret: ,Salvar Segredo da API:, +Save As,Salvar como, +Save Filter,Salvar filtro, +Save Report,Salvar o relatorio, +Save filters,Salvar filtros, Saving,Salvando, +Saving...,Salvando ..., +Scan the QR Code and enter the resulting code displayed.,Digitalize o Código QR e insira o código resultante exibido., +Scopes,Scopes, Script,Script, Script Report,Relatório Script, +Script or Query reports,Script ou consulta relatórios, +Script to attach to all web pages.,Script para anexar a todas as páginas web., +Search Fields,Campos de Pesquisa, Search Help,Procure Ajuda, Search field {0} is not valid,Campo de pesquisa {0} não é válido, +Search for '{0}',Pesquisar por '{0}', Search for anything,Procurar por qualquer coisa, +Search in a document type,Pesquisar em um tipo de documento, +Search or Create a New Chat,Pesquisar ou criar um novo bate-papo, +Search or type a command,Pesquisar ou digite um comando, +Search...,Pesquisa..., +Searching,Procurando, +Searching ...,Procurando ..., +Section Break,Quebra de seção, Section Heading,Cabeçalho da Seção, Security,Segurança, +Security Settings,Configurações de Segurança, +See all past reports.,Veja todos os relatórios anteriores., See on Website,Veja no Site, +See the document at {0},Veja o documento em {0}, Seems API Key or API Secret is wrong !!!,Parece que a chave API ou o segredo da API estão errados !!!, -Seems token you are using is invalid!,O token que você está usando é aparentemente inválido!, +Seems Publishable Key or Secret Key is wrong !!!,Parece publicado chave ou secret key está errado !!!, +"Seems issue with server's razorpay config. Don't worry, in case of failure amount will get refunded to your account.","Parece um problema com a configuração do servidor razorpay. Não se preocupe, em caso de falha os valores serão estornados à sua conta.", +Seems token you are using is invalid!,Parece token que você está usando é inválido!, +Seen,Visto, +Seen By,Visto por, +Seen By Table,Visto por tabela, Select Attachments,Selecione os Anexos, +Select Child Table,Selecionar tabela infantil, +Select Column,Selecione a coluna, +Select Columns,Selecionar Colunas, Select Document Type,Selecione o Tipo de Documento, Select Document Type or Role to start.,Selecione o Tipo de Documento ou Função para começar., Select Document Types to set which User Permissions are used to limit access.,Selecione os tipos de documentos para definir quais as permissões de usuário são usados para limitar o acesso., +Select File Format,Selecione o formato do arquivo, Select File Type,Selecionar tipo do arquivo, +Select Language...,Selecione o idioma..., Select Languages,Selecionar Idiomas, Select Module,Selecione o Módulo, Select Print Format,Selecione o Formato de Impressão, Select Print Format to Edit,Selecione um formato de impressão para editar, Select Role,Selecione a Função, +Select Table Columns for {0},Selecionar colunas de tabela para {0}, +Select Your Region,Selecione sua região, Select a Brand Image first.,Selecione o Logo da Marca primeiro., +Select a DocType to make a new format,Selecione um tipo de documento para fazer um novo formato, +Select a chat to start messaging.,Selecione um bate-papo para iniciar mensagens., Select a group node first.,Selecione um nó de grupo primeiro., +Select an existing format to edit or start a new format.,Escolha um formato existente para editar ou iniciar um novo formato., +Select an image of approx width 150px with a transparent background for best results.,Selecione uma imagem de aproximadamente 150px de largura com um fundo transparente para melhores resultados., +Select atleast 1 record for printing,Selecione pelo menos 1 registro para impressão, +Select or drag across time slots to create a new event.,Selecione ou arraste intervalos de tempo para criar um novo evento., +Select records for assignment,Seleciona registros para a atribuição, Select the label after which you want to insert new field.,Selecione a etiqueta após a qual você deseja inserir um novo campo., "Select your Country, Time Zone and Currency","Escolha o seu País, Fuso Horário e Moeda", +Select {0},Selecione {0}, +Self approval is not allowed,Auto-aprovação não é permitida, +Send After,Envie Depois, Send Alert On,Enviar Alerta, +Send Email Alert,Enviar alerta de email, Send Email Print Attachments as PDF (Recommended),Enviar anexos de email em PDF (Recomendado), +Send Email for Successful Backup,Enviar email para backup bem-sucedido, +Send Me A Copy of Outgoing Emails,Envie-me uma cópia dos e-mails de saída, +Send Notification to,Enviar Notificação para, Send Notifications To,Enviar Notificações para, Send Print as PDF,Enviar impressão como PDF, Send Read Receipt,Enviar Confirmação de Leitura, Send Unsubscribe Link,Enviar link para cancelar inscrição, Send Welcome Email,Enviar email de boas-vindas, +Send alert if date matches this field's value,Enviar alerta se a data corresponde valor deste campo, +Send alert if this field's value changes,Enviar alerta se muda o valor desse campo, Send an email reminder in the morning,Enviar um email lembrete na parte da manhã, +Send days before or after the reference date,Enviar dias antes ou depois da data de referência, Send enquiries to this email address,Envie perguntas para este endereço de email, Send me a copy,Envie-me uma Cópia, +Send only if there is any data,Envie somente se houver quaisquer dados, +Send unsubscribe message in email,Enviar mensagem de cancelamento de inscrição no e-mail, +Sender,Remetente, +Sender Email,E-mail do remetente, +Sendgrid,Sendgrid, Sent Read Receipt,Enviar Confirmação de Leitura, Sent or Received,Enviados ou recebidos, +Sent/Received Email,E-mail enviado / recebido, +Server IP,IP do servidor, +Session Expired,Sessão expirada, Session Expiry,Duração da Sessão, Session Expiry Mobile,Duração da Sessão Móvel, Session Expiry in Hours e.g. 06:00,"Duração da sessão em horas, por exemplo 06:00", +Session Expiry must be in format {0},Sessão de validade devem estar no formato {0}, +Session Start Failed,Falha ao iniciar a sessão, Set Banner from Image,Definir imagem como banner, -Set Chart,Definir Gráfico, +Set Chart,Definir gráfico, +Set Filters,Definir filtros, +Set New Password,Definir nova senha, +Set Number of Backups,Definir número de cópias de segurança, +Set Only Once,Definir apenas uma vez, Set Password,Definir senha, Set Permissions,Definir Permissões, +Set Permissions on Document Types and Roles,Definir permissões em Tipos e Funções de documentos, +Set Property After Alert,Definir propriedade após o alerta, +Set Quantity,Definir Quantidade, +Set Role For,Definir papel para, Set User Permissions,Definir Permissões de Usuário, +Set Value,Definir valor, +Set custom roles for page and report,Definir funções personalizadas para página e relatório, +"Set default format, page size, print style etc.","Definir o formato padrão, o tamanho da página, estilo de impressão, etc", +Set non-standard precision for a Float or Currency field,Definir precisão não-padrão para um campo Float ou Moeda, +Set numbering series for transactions.,Definir numeração série para transações., +Set up rules for user assignments.,Configurar regras para atribuições de usuários., Setting this Address Template as default as there is no other default,"A definição desse modelo de endereço como padrão, pois não há outro padrão", +Setting up your system,Configurando seu sistema, Settings for About Us Page.,Configurações para a Página Sobre Nós., Settings for Contact Us Page,Configurações para a página Fale Conosco, Settings for Contact Us Page.,Configurações da Página Fale Conosco., +Settings for OAuth Provider,Definições para Provedor de OAuth, Settings for the About Us Page,Configurações para a página Sobre Nós, Setup Auto Email,Configurar Email Automático, Setup Complete,Instalação Concluída, +Setup Notifications based on various criteria.,Notificações de configuração com base em vários critérios., +Setup Reports to be emailed at regular intervals,Relatórios de configuração para ser enviado em intervalos regulares, "Setup of top navigation bar, footer and logo.","Configuração de barra de navegação do topo, rodapé, e logotipo.", -Share URL,Compartilhar URL, +Share,Compartilhar, +Share URL,URL de compartilhamento, +Share With,Compartilhar, +Share this document with,Compartilhe este documento com, +Share {0} with,Partilhar {0} com, +Shared,Compartilhado, +Shared With,Compartilhado com, +Shared with everyone,Compartilhado com todos, +Shared with {0},Compartilhado com {0}, +Shop,Loja, +Short keyboard patterns are easy to guess,padrões do teclado curtas são fáceis de adivinhar, +Show Attachments,Mostrar anexos, +Show Calendar,Mostrar calendário, +Show Dashboard,Mostrar Dashboard, +Show Full Error and Allow Reporting of Issues to the Developer,Mostrar erro completo e permitir relatórios de problemas para o desenvolvedor, Show Line Breaks after Sections,Mostrar quebras de linha após seções, Show Permissions,Mostrar Permissões, +Show Preview Popup,Mostrar pop-up de pré-visualização, +Show Relapses,Mostrar Relapses, +Show Report,Mostrar relatório, +Show Section Headings,Mostrar Seção Títulos, Show Sidebar,Mostrar menu lateral, Show Title,Mostrar Título, +Show Totals,Mostrar Totais, +Show Weekends,Mostrar fins de semana, +Show all Versions,Mostrar todas as versões, +Show as Grid,Mostrar como grade, +Show as cc,Mostrar como cc, Show failed jobs,Mostrar tarefas com falha, +Show in Module Section,Mostrar na Seção Módulo, +Show in filter,Mostrar no filtro, +Show more details,Mostrar mais detalhes, +Show only errors,Mostrar apenas erros, +Show title in browser window as "Prefix - title",Mostrar título na janela do navegador como "Prefixo - título", +Showing only Numeric fields from Report,Mostrando apenas campos numéricos do relatório, Sidebar Items,Itens da barra lateral, +Sidebar Settings,Configurações da barra lateral, Sidebar and Comments,Menu Lateral e Comentários, -Sign Up is disabled,O cadastro esta desativado, +Sign Up,Inscrever-se, +Sign Up is disabled,Sign Up é desativado, +Signature,Assinatura, +"Simple Python Expression, Example: Status in (""Closed"", ""Cancelled"")","Expressão Python Simples, Exemplo: Status em ("Fechado", "Cancelado")", +"Simple Python Expression, Example: status == 'Open' and type == 'Bug'","Expressão Python Simples, Exemplo: status == 'Open' e digite == 'Bug'", +Simultaneous Sessions,Sessões simultâneas, +Single DocTypes cannot be customized.,DocTypes únicos não podem ser personalizados., +Single Post (article).,Resposta Única (artigo)., Single Types have only one record no tables associated. Values are stored in tabSingles,Tipos individuais têm apenas um registro sem tabelas associadas. Os valores são armazenados em tabSingles, +Skip Authorization,Ignorar autorização, +Skip rows with errors,Ignorar linhas com erros, +Skype,Skype, +Slack,Folga, +Slack Channel,Canal de folga, +Slack Webhook Error,Erro Slack Webhook, Slack Webhook URL,URL do Webhook do Slack, +Slack Webhooks for internal integration,Webhooks frouxos para integração interna, Slideshow Items,Itens da Apresentação de Slides, Slideshow Name,Nome da Apresentação de Slides, +Slideshow like display for the website,Slideshow como display para o site, +Small Text,Texto Pequeno, Smallest Currency Fraction Value,Menor valor fracionado de moeda, Smallest circulating fraction unit (coin). For e.g. 1 cent for USD and it should be entered as 0.01,"Menor unidade fração circulante (moeda). Para, por exemplo, 1 centavo, deve ser inserido como 0,01", Snapshot View,Ver Snapshot, +Social,Social, +Social Login Key,Chave de login social, +Social Login Provider,Provedor de acesso social, +Social Logins,Logins sociais, +Socketio is not connected. Cannot upload,Socketio não está conectado. Não é possível carregar, +Soft-Bounced,Soft-Bounced, +Some of the features might not work in your browser. Please update your browser to the latest version.,Alguns dos recursos podem não funcionar no seu navegador. Atualize o navegador para a versão mais recente., +Something went wrong,Algo deu errado, +Something went wrong while generating dropbox access token. Please check error log for more details.,Algo deu errado ao gerar o token de acesso dropbox. Verifique o registro de erros para obter mais detalhes., Sorry! I could not find what you were looking for.,Desculpe! Não foi possível encontrar o que você procurou., Sorry! Sharing with Website User is prohibited.,Desculpe! Não é permitido compartilhar com o site do usuário., Sorry! User should have complete access to their own record.,Desculpe! O usuário deve ter acesso completo ao seu próprio registro., +Sorry! You are not permitted to view this page.,Desculpe! Você não tem permissão para visualizar esta página., +"Sorry, you're not authorized.","Desculpe, você não está autorizado.", Sort Field,Ordenar por campo, +Sort Order,Ordem de classificação, +Sort field {0} must be a valid fieldname,Ordenar campo {0} deve ser um nome do campo válido, Source Text,Texto Original, +Spam,Spam, +SparkPost,SparkPost, +Special Characters are not allowed,Caracteres especiais não são permitidos, +"Standard DocType cannot have default print format, use Customize Form","DocType padrão não pode ter o formato de impressão padrão, use Personalizar formulário", Standard Print Format cannot be updated,Formato de impressão padrão não pode ser atualizado, +Standard Print Style cannot be changed. Please duplicate to edit.,"O estilo de impressão padrão não pode ser alterado. Por favor, copie para editar.", +Standard Reports,Relatórios padrão, Standard Sidebar Menu,Menu Lateral Padrão, +Standard roles cannot be disabled,Funções padrão não pode ser desativado, Standard roles cannot be renamed,Funções padrão não podem ser renomeadas, -Start a conversation.,Inicie uma conversa., +Standings,Classificações, +Start Date Field,Campo de Data de Início, +Start a conversation.,Comece uma conversa., +Start entering data below this line,Comece a introduzir dados abaixo desta linha, Start new Format,Iniciar um Novo Formato, -Started,Iniciado, +StartTLS,StartTLS, +Started,Começado, +Starting Frappe ...,Iniciando Frappé ..., +Starts on,Inicia em, +States,Estados, "States for workflow (e.g. Draft, Approved, Cancelled).","Status para o fluxo de trabalho (por exemplo, rascunho, aprovado, cancelado).", Static Parameters,Parâmetros estáticos, +Stats based on last month's performance (from {0} to {1}),Estatísticas com base no desempenho do último mês (de {0} a {1}), +Stats based on last week's performance (from {0} to {1}),Estatísticas com base no desempenho da semana passada (de {0} a {1}), +Status: {0},Status: {0}, +Steps to verify your login,Etapas para verificar seu login, +Stores the JSON of last known versions of various installed apps. It is used to show release notes.,Armazena o JSON das últimas versões conhecidas de vários aplicativos instalados. Ele é usado para mostrar notas de lançamento., +Straight rows of keys are easy to guess,linhas retas de teclas são fáceis de adivinhar, Stripe Settings,Configurações do Stripe, +Stripe payment gateway settings,Configurações do gateway de pagamento Stripe, +Style,Estilo, Style Settings,Configurações de Estilo, "Style represents the button color: Success - Green, Danger - Red, Inverse - Black, Primary - Dark Blue, Info - Light Blue, Warning - Orange","Estilo representa a cor do botão: Sucesso - Verde, Perigo - Vermelho, Inverso - Preto, Primário - Azul Escuro, Informações - Azul Claro, Aviso - Laranja", -"Sub-currency. For e.g. ""Cent""",Sub-moeda. Por exemplo "Centavo", +Stylesheets for Print Formats,Folhas de estilos para formatos de impressão, +Sub-currency. For e.g. "Cent",Sub-moeda. Por exemplo "Centavo", +Sub-domain provided by erpnext.com,Sub-domínio fornecido pelo erpnext.com, +Subdomain,Subdomínio, +Subject Field,Subject Field, +Submit after importing,Enviar depois de importar, Submit an Issue,Enviar um problema, -Submit this document to confirm,Envie este documento para confirmar, +Submit this document to confirm,Enviar este documento para confirmar, +Submit {0} documents?,Envie {0} documentos?, +Submitting {0},Enviando {0}, Submitted Document cannot be converted back to draft. Transition row {0},Documento enviado não pode ser convertido de volta para rascunho. Linha de transição {0}, Submitting,Enviando, +Subscription Notification,Notificação de Subscrição, +Subsidiary,Subsidiário, +Success Action,Ação de Sucesso, Success Message,Mensagem de sucesso, Success URL,URL de Confirmação, +Successful: {0} to {1},Bem-sucedida: {0} para {1}, +Successfully Done,Feito com sucesso, +Successfully Updated,Atualizado com sucesso, +Successfully updated translations,Traduções atualizadas com êxito, Suggested Username: {0},Nome de usuário sugerido: {0}, +Sum,Soma, +Sum of {0},Soma de {0}, +Support Email Address Not Specified,Endereço de e-mail de suporte Não especificado, Suspend Sending,Suspender Envio, Switch To Desk,Ir para o Desktop, +Symbol,Símbolo, +Sync,Sincronizar, +Sync on Migrate,Sync em Migrate, Syntax error in template,Erro de sintaxe no template, +System,Sistema, +System Page,Página do sistema, System Settings,Configurações do Sistema, System User,Usuário do Sistema, System and Website Users,Usuários do sistema e do site, +Table,Tabela, Table Field,Campo da Tabela, +Table HTML,Tabela HTML, +Table MultiSelect,Tabela MultiSelect, Table updated,Tabela atualizada, Table {0} cannot be empty,Tabela {0} não pode ser vazio, Take Backup Now,Fazer backup agora, +Take Photo,Tirar fotos, +Team Members,Membros da Equipe, Team Members Heading,Título da página Membros da Equipe, +Temporarily Disabled,Temporariamente desativado, +Test Email Address,Teste de Endereço de Email, +Test Runner,Test Runner, +Test_Folder,Test_Folder, Text,Texto, Text Align,Alinhar Texto, +Text Color,Cor do texto, +Text Content,conteúdo de texto, +Text Editor,Editor de Texto, Text to be displayed for Link to Web Page if this form has a web page. Link route will be automatically generated based on `page_name` and `parent_website_route`,"O texto a ser exibido para o link da página da web, se este formulário tem uma página web. Um link será gerado automaticamente com base em ` page_name` e `parent_website_route`", Thank you for your email,Obrigado pelo seu email, Thank you for your interest in subscribing to our updates,Agradecemos seu interesse em assinar a newsletter do site, +Thank you for your message,Obrigado por sua mensagem, +The CSV format is case sensitive,O formato CSV diferencia maiúsculas de minúsculas, +The Condition '{0}' is invalid,A condição '{0}' é inválido, The First User: You,O primeiro usuário: Você, +"The application has been updated to a new version, please refresh this page","O aplicativo foi atualizado para uma nova versão, por favor, atualize esta página", +The attachments could not be correctly linked to the new document,Os anexos não puderam ser vinculados corretamente ao novo documento, +The document could not be correctly assigned,O documento não pôde ser atribuído corretamente, +The document has been assigned to {0},O documento foi atribuído a {0}, The first user will become the System Manager (you can change this later).,O primeiro usuário será o System Manager (você pode mudar isso mais tarde)., +The name that will appear in Google Calendar,O nome que aparecerá no Google Agenda, +The process for deletion of {0} data associated with {1} has been initiated.,O processo de exclusão de {0} dados associados a {1} foi iniciado., +The resource you are looking for is not available,O recurso que você está procurando não está disponível, The system provides many pre-defined roles. You can add new roles to set finer permissions.,O sistema disponibiliza várias funções pré-definidas. Você pode adicionar novas funções para definir permissões mais específicas., +The user from this field will be rewarded points,O usuário deste campo será recompensado pontos, +Theme,Tema, +Theme URL,URL do tema, +There can be only one Fold in a form,Só pode haver uma Fold de uma forma, There is an error in your Address Template {0},Há um erro no seu modelo de endereço {0}, +There is no data to be exported,Não há dados a serem exportados, +There is some problem with the file url: {0},Há algum problema com a url do arquivo: {0}, There must be atleast one permission rule.,É necessário que exista pelo menos uma regra de permissão., +"There seems to be an issue with the server's braintree configuration. Don't worry, in case of failure, the amount will get refunded to your account.","Parece haver um problema com a configuração braintree do servidor. Não se preocupe, em caso de falha, o valor será reembolsado para sua conta.", There should remain at least one System Manager,Não deve permanecer pelo menos um gestor de sistema, -There was an error saving filters,Houve um erro ao tentar salvar os filtros, -There were errors while sending email. Please try again.,"Ocorreram erros durante o envio de email. Por favor, tente novamente.", +There was an error saving filters,Houve um erro ao salvar os filtros, +There were errors,Ocorreram erros, +There were errors while creating the document. Please try again.,"Houve erros ao criar o documento. Por favor, tente novamente.", +There were errors while sending email. Please try again.,Ocorreram erros durante o envio de email. Por favor, tente novamente., +"There were some errors setting the name, please contact the administrator","Houve alguns erros de definir o nome, por favor, entre em contato com o administrador", These values will be automatically updated in transactions and also will be useful to restrict permissions for this user on transactions containing these values.,Esses valores serão atualizados automaticamente em transações e também serão úteis para restringir as permissões para este usuário em operações que contenham esses valores., +Third Party Apps,Aplicativos de terceiros, +Third Party Authentication,Autenticação de Terceiros, This Currency is disabled. Enable to use in transactions,Esta moeda é desativado. Ativar para usar em transações, +This Kanban Board will be private,Este Conselho Kanban será privado, +This document cannot be reverted,Este documento não pode ser revertido, +This document has been modified after the email was sent.,Este documento foi modificado depois que o email foi enviado., +This document has been reverted,Este documento foi revertido, +This document is currently queued for execution. Please try again,"Este documento está em fila para execução. Por favor, tente novamente", +This email is autogenerated,Este e-mail é gerado automaticamente, This email was sent to {0},Este email foi enviado para {0}, This email was sent to {0} and copied to {1},Este email foi enviado para {0} e copiados para {1}, This feature is brand new and still experimental,Esta funcionalidade é nova e ainda está em fase experimental, -This field will appear only if the fieldname defined here has value OR the rules are true (examples): \nmyfield\neval:doc.myfield=='My Value'\neval:doc.age>18,Este campo aparecerá apenas se o nome do campo definido está preenchido ou se as regras são verdadeiros (exemplos): meu_campo eval: doc.meu_campo=='Valor' eval: doc.idade>18, +This field will appear only if the fieldname defined here has value OR the rules are true (examples): \nmyfield\neval:doc.myfield=='My Value'\neval:doc.age>18,Este campo aparecerá apenas se o nome do campo definido aqui tem valor ou as regras são verdadeiros (exemplos): myfield eval: doc.myfield == 'Meu Valor' eval: doc.age> 18, This form does not have any input,Este formulário não tem nenhum campo a ser preenchido, +This form has been modified after you have loaded it,Este formulário foi modificado depois de ter carregado ele, This format is used if country specific format is not found,Este formato é usado se o formato específico país não é encontrado, -This is a background report. Please set the appropriate filters and then generate a new one.,Este é um relatório de segundo plano. Por favor configure os filtros apropriados e gere um novo relatório., +This goes above the slideshow.,Isto vai acima do slideshow., +This is a background report. Please set the appropriate filters and then generate a new one.,"Este é um relatório de fundo. Por favor, defina os filtros apropriados e, em seguida, gere um novo.", This is a top-10 common password.,Essa é uma das 10 senhas mais comuns., This is a top-100 common password.,Essa é uma das 100 senhas mais comuns., This is a very common password.,Essa é uma senha muito comum., +This is an automatically generated reply,Isto é uma resposta gerada automaticamente, This is similar to a commonly used password.,Isso é parecido com uma senha comum., +This is the template file generated with only the rows having some error. You should use this file for correction and import.,Este é o arquivo de modelo gerado com apenas as linhas com algum erro. Você deve usar esse arquivo para corrigir e importar., +This link has already been activated for verification.,Este link já foi ativado para verificação., +This link is invalid or expired. Please make sure you have pasted correctly.,"Este link é inválido ou expirou. Por favor, certifique-se de ter colado corretamente.", +This may get printed on multiple pages,Isso pode ser impresso em várias páginas, +This month,Este mês, +This query style is discontinued,Esse estilo de consulta foi interrompido, +This report was generated on {0},Este relatório foi gerado em {0}, +This report was generated {0}.,Este relatório foi gerado {0}., +This request has not yet been approved by the user.,Esta solicitação ainda não foi aprovada pelo usuário., This role update User Permissions for a user,Este papel arualiza Permissões do Usuário para um usuário, +This will log out {0} from all other devices,Isso encerrará {0} de todos os outros dispositivos, +This will permanently remove your data.,Isso removerá permanentemente seus dados., +Throttled,Throttled, +Thumbnail URL,URL Thumbnail, +Time Interval,Intervalo de tempo, +Time Series,Séries Temporais, +Time Series Based On,Séries Temporais Baseadas em, +Time Zone,Fuso horário, Time Zones,Fusos horários, +Time in seconds to retain QR code image on server. Min:240,Tempo em segundos para manter a imagem do código QR no servidor. Min: 240, +Timeline DocType,DocType Timeline, Timeline Field,Campo Timeline, +Timeline Links,Links da linha do tempo, +Timeline Name,Nome Timeline, Timeline field must be a Link or Dynamic Link,Campo Timeline deve ser um link ou link dinâmico, +Timeline field must be a valid fieldname,campo Timeline deve ser um nome de campo válido, +Timeseries,Timeseries, +Timestamp,Timestamp, Title Case,Caixa do Título, Title Field,Campo Título, Title Prefix,Prefixo do Título, +Title field must be a valid fieldname,Campo Título deve ser um nome de campo válido, +To Date Field,Até o momento do campo, To Do,Atribuições, +To User,Ao usuário, +"To add dynamic subject, use jinja tags like\n\n
    New {{ doc.doctype }} #{{ doc.name }}
    ","Para adicionar assunto dinâmico, use jinja tags como
     New {{ doc.doctype }} #{{ doc.name }} 
    ", +"To add dynamic subject, use jinja tags like\n\n
    {{ doc.name }} Delivered
    ","Para adicionar assunto dinâmico, usar marcas como Jinja
     {{ doc.name }} Delivered 
    ", +To and CC,Para e CC, +"To get the updated report, click on {0}.","Para obter o relatório atualizado, clique em {0}.", ToDo,Lista de Atribuições, -Toggle Charts,Alternar Gráficos, +Today,Hoje, +Toggle Chart,Tabela de alternância, +Toggle Charts,Gráficos de alternância, +Toggle Grid View,Toggle Grid View, +Toggle Sidebar,Toggle Sidebar, +Token,Símbolo, +Token is missing,Token está ausente, +"Too many users signed up recently, so the registration is disabled. Please try back in an hour","Demasiados usuários se inscreveram recentemente, de modo que o registro estiver desativado. Por favor volte em uma hora", +Too many writes in one request. Please send smaller requests,"Muitos escreve em um pedido. Por favor, enviar pedidos de menores", Top Bar Item,Item da barra superior, Top Bar Items,Itens da barra superior, +Top Performer,Top Performer, +Top Reviewer,Revisor Superior, +Top {0},Top {0}, +Total Pages,Páginas totais, +Total Rows,Linhas totais, +Total Subscribers,Total de Assinantes, +Total number of emails to sync in initial sync process ,número total de e-mails para sincronizar no processo de sincronização inicial, +Totals Row,Linha de totais, Track Changes,Rastrear Alterações, +Track Email Status,Acompanhar status de e-mail, +Track Field,Trilha de corrida, Track Seen,Marcar como visto, +Track Views,Acompanhar vistas, +"Track if your email has been opened by the recipient.\n
    \nNote: If you're sending to multiple recipients, even if 1 recipient reads the email, it'll be considered ""Opened""","Acompanhe se o seu email foi aberto pelo destinatário.
    Observação: se você estiver enviando para vários destinatários, mesmo que um destinatário leia o e-mail, ele será considerado "Aberto"", +Track milestones for any document,Acompanhe os marcos de qualquer documento, +Transaction Hash,Hash de transação, +Transaction Log,Log de transações, +Transaction Log Report,Relatório de log de transações, +Transition Rules,Regras de transição, Transitions,Transições, +Translatable,Traduzível, +Translate {0},Traduzir {0}, Translated Text,Texto Traduzido, +Translation,Tradução, +Translations,Traduções, +Trash,lixo, Tree,Árvore, +Trigger Method,Método gatilho, +Trigger Name,Nome do Disparador, "Trigger on valid methods like ""before_insert"", ""after_update"", etc (will depend on the DocType selected)","Gatilho em métodos válidos como ""before_insert"", ""after_update"", etc. (dependerá do DocType selecionado)", +Try to avoid repeated words and characters,Tente evitar palavras repetidas e personagens, +Try to use a longer keyboard pattern with more turns,Tente usar um padrão de teclado mais tempo com mais voltas, +Two Factor Authentication,Autenticação de dois fatores, +Two Factor Authentication method,Método de autenticação de dois fatores, +Type something in the search box to search,Digite algo na caixa de pesquisa para pesquisar, +Type:,Tipo:, +UID,UID, +UIDNEXT,UIDNEXT, +UIDVALIDITY,UIDVALIDITY, +UNSEEN,Por Ler, +UPPER CASE,MAIÚSCULAS, +"URIs for receiving authorization code once the user allows access, as well as failure responses. Typically a REST endpoint exposed by the Client App.\n
    e.g. http://hostname//api/method/frappe.www.login.login_via_facebook","URIs para receber o código de autorização uma vez que o usuário permite o acesso, bem como respostas de falha. Normalmente, um terminal REST expostas pelo cliente App.
    por exemplo, http: //hostname//api/method/frappe.www.login.login_via_facebook", +URLs,URLs, Unable to find attachment {0},Incapaz de encontrar o anexo {0}, +Unable to load camera.,Não é possível carregar a câmera., Unable to load: {0},Não é possível carregar: {0}, Unable to open attached file. Did you export it as CSV?,Foi impossível abrir o arquivo anexado. Você o exportou como CSV?, +Unable to read file format for {0},Não foi possível ler o formato do arquivo para {0}, Unable to send emails at this time,Não é possível enviar emails neste momento, +Unable to update event,Não é possível atualizar evento, +Unable to write file format for {0},Não foi possível escrever o formato do arquivo para {0}, +Unassign Condition,Desatribuir condição, +Under Development,Em desenvolvimento, +Unfollow,Deixar de seguir, Unhandled Email,Emails não trabalhados, +Unique,Único, Unknown Column: {0},Coluna desconhecida: {0}, +Unknown User,Usuário desconhecido, "Unknown file encoding. Tried utf-8, windows-1250, windows-1252.","Codificação de arquivo desconhecida. Tentei utf-8, Windows -1250 , Windows-1252 .", +Unread,Não lida, Unread Notification Sent,Notificação de mensagem não lida enviada, Unselect All,Desmarcar Todos, Unshared,Não Compartilhado, +Unsubscribe,Cancelar subscrição, Unsubscribe Method,Método de Cancelamento de Inscrição, Unsubscribe Param,Parâmetero de Cancelamento de Inscrição, +Unsupported File Format,Formato de arquivo não suportado, +Unzip,Descompactar, +Unzipped {0} files,Arquivos descompactados {0}, +Unzipping files...,Descompactando arquivos ..., +Upcoming Events for Today,Próximos Eventos para Hoje, Update Field,Atualizar Campo, +Update Translations,Atualizar Traduções, Update Value,Atualizar Valor, Update many values at one time.,Atualizar muitas informações de uma só vez., +Update records,Atualizar registros, +Updated,Atualizado, +Updated successfully,Atualizado com sucesso, +Updated {0}: {1},Atualizado {0}: {1}, Updating,Atualizando, +Updating {0},Atualizando {0}, +Upload Failed,Upload falhou, +Uploaded To Dropbox,Enviado para o Dropbox, +Use ASCII encoding for password,Use codificação ASCII para senha, +Use Different Email Login ID,Usar ID de Login de Email Diferente, Use IMAP,Usar IMAP, +Use POST,Use POST, +Use SSL,Usar SSL, +Use TLS,Usar TLS, "Use a few words, avoid common phrases.","Use algumas palavras, evite frases comuns.", +Use of sub-query or function is restricted,O uso de subconsulta ou função é restrito, +Use socketio to upload file,Use o socketio para fazer o upload do arquivo, Use this fieldname to generate title,Utilize este campo para gerar o título, +User '{0}' already has the role '{1}',User '{0}' já tem o papel '{1}', User Cannot Create,O Usuário não pode criar, User Cannot Search,O Usuário não pode pesquisar, +User Defaults,Padrões de Perfil, User Email,Email do Usuário, User Emails,Emails do Usuário, +User Field,Campo do usuário, User ID of a Blogger,ID do usuário de um Blogger, User Image,Imagem do Usuário, +User Name,Nome de usuário, User Permission,A permissão do usuário, User Permissions,Permissões de Usuário, +User Permissions are used to limit users to specific records.,Permissões de usuário são usadas para limitar usuários a registros específicos., +User Permissions created sucessfully,Permissões de usuário criadas com sucesso, User Roles,Funções do Usuário, +User Social Login,Login Social do Usuário, User Tags,Etiquetas de Usuários, User Type,Tipo de Usuário, +User can login using Email id or Mobile number,O usuário pode efetuar login usando a ID do e-mail ou o número do celular, +User can login using Email id or User Name,O usuário pode fazer login usando o ID de e-mail ou o Nome de usuário, User editable form on Website.,Formato editável do usuário no site., User is mandatory for Share,Usuário é obrigatória para Partilhar, User not allowed to delete {0}: {1},Usuário não tem permissão para excluir {0}: {1}, +User permission already exists,A permissão do usuário já existe, User permissions should not apply for this Link,As permissões de usuário não deve candidatar-se a este link, User {0} cannot be deleted,O usuário {0} não pode ser excluído, User {0} cannot be disabled,O usuário {0} não pode ser desativado, User {0} cannot be renamed,O usuário {0} não pode ser renomeado, +User {0} does not have access to this document,O usuário {0} não tem acesso a este documento, +User {0} does not have doctype access via role permission for document {1},O usuário {0} não tem acesso ao tipo de documento via permissão de função para o documento {1}, Username,Nome de Usuário, Username {0} already exists,O nome de usuário {0} já existe, Users with role {0}:,Os usuários com a função {0}:, +Uses the Email Address Name mentioned in this Account as the Sender's Name for all emails sent using this Account.,Usa o nome do endereço de e-mail mencionado nesta conta como o nome do remetente para todos os e-mails enviados usando esta conta., +Uses the Email Address mentioned in this Account as the Sender for all emails sent using this Account. ,Usa o endereço de e-mail mencionado nesta conta como o remetente para todos os e-mails enviados usando essa conta., +Valid,Válido, Valid Login id required.,É necessário um usuário válido., Valid email and name required,É necessário email válido e nome, +Value Based On,Valor Baseado em, Value Change,Mudança de Valor, Value Changed,Valor Alterado, +Value To Be Set,Valor a ser definido, Value cannot be changed for {0},Valor não pode ser alterado para {0}, +Value for a check field can be either 0 or 1,Valor para um campo de verificação pode ser 0 ou 1, +Value for {0} cannot be a list,Valor para {0} não pode ser uma lista, +Value missing for,Valor em falta para, +Value too big,Valor muito grande, Values Changed,Valores Alterados, +Verdana,Verdana, +Verfication Code,Código de Verificação, +Verification Link,Link de verificação, +Verification code has been sent to your registered email address.,O código de verificação foi enviado para o seu endereço de e-mail registrado., +Verify,Verificar, Verify Password,Verifique a Senha, Verifying...,Verificando..., Version,Versão, +Version Updated,Atualização da versão, +View All,Ver tudo, +View Comment,Ver comentário, View List,Ver Lista, +View Log,Visualizar log, +View Permitted Documents,Ver documentos permitidos, View Properties (via Customize Form),Exibir Propriedades (via Personalizar Formulário), +View Settings,Ver Definições, View Website,Ver Site, +View document,Ver documento, +View report in your browser,Exibir relatório no seu navegador, View this in your browser,Veja isto no seu navegador, +View {0},Ver {0}, +Viewed By,Visto por, Visit,Visita, +Visitor,Visitante, +We have received a request for deletion of {0} data associated with: {1},Recebemos uma solicitação para exclusão de {0} dados associados a: {1}, +We have received a request from you to download your {0} data associated with: {1},Recebemos uma solicitação sua para fazer o download de seus {0} dados associados a: {1}, +Web Form,Formulário Web, Web Form Field,Campo de Formulário Web, +Web Form Fields,Campos de formulário Web, +Web Page,Página Web, Web Page Link Text,Link de Texto para Página Web, Web Site,Web Site, +Web View,web View, +Webhook,Webhook, +Webhook Data,Webhook Data, +Webhook Header,Cabeçalho Webhook, +Webhook Headers,Cabeçalhos Webhook, +Webhook Request,Pedido Webhook, +Webhook URL,URL do Webhook, +Webhooks calling API requests into web apps,Webhooks chamando pedidos de API em aplicativos da web, +Website Meta Tag,Meta Tag do Site, +Website Route Meta,Meta Rota do Site, +Website Route Redirect,Redirecionamento de Rota do Site, Website Script,Script do Site, Website Sidebar,Menu Lateral do Site, Website Sidebar Item,Item do Menu Lateral do Site, @@ -1088,49 +2743,119 @@ Website Theme,Tema do Site, Website Theme Image,Imagem do Tema do Site, Website Theme Image Link,Link da Imagem do Tema do Site, Website User,Usuário do Site, +Welcome Message,Mensagem de Boas-Vindas, "When you Amend a document after Cancel and save it, it will get a new number that is a version of the old number.","Quando você Corrigir um documento depois de Cancelar e salvá-lo, ele irá obter um novo número que é uma versão do número antigo.", +Width,Largura, Widths can be set in px or %.,Larguras podem ser definidas em px ou %., +Will be used in url (usually first name).,Será utilizado na url (geralmente o primeiro nome)., +Will be your login ID,Será seu ID de login, +Will only be shown if section headings are enabled,só será mostrado se títulos de seção estão habilitados, With Letter head,Com cabeçalho, +With Letterhead,Com timbrado, Workflow Action,Ação do Fluxo de Trabalho, Workflow Action Master,Cadastro de Ação do Fluxo de Trabalho, Workflow Action Name,Nome da Ação do Fluxo de Trabalho, Workflow Document State,Status do Documento do Fluxo de Trabalho, Workflow Name,Nome do Fluxo de Trabalho, +Workflow State,Status do Fluxo de Trabalho, Workflow State Field,Campo do Status do Fluxo de Trabalho, +Workflow State not set,Estado do fluxo de trabalho não definido, Workflow Transition,Transição do Fluxo de Trabalho, Workflow state represents the current state of a document.,O Status do Fluxo de Trabalho representa o status atual de um documento., +Write,Escrever, +Wrong fieldname {0} in add_fetch configuration of custom script,Nome de campo errado {0} na configuração add_fetch do script personalizado, X Axis Field,Campo do eixo X, +XLSX,XLSX, +Y Axis Fields,Campos do eixo Y, Yahoo Mail,Email do Yahoo, +Yandex.Mail,Yandex.Mail, +Yesterday,Ontem, +You are connected to internet.,Você está conectado à internet., +You are not allowed to create columns,Você não tem permissão para criar colunas, +You are not allowed to delete a standard Website Theme,Você não tem permissão para excluir um site Tema padrão, +You are not allowed to print this document,Você não tem permissão para imprimir este documento, +You are not allowed to print this report,Você não tem permissão para imprimir este relatório, You are not allowed to send emails related to this document,Você não tem permissão para enviar emails relacionados a este documento, +You are not allowed to update this Web Form Document,Você não tem permissão para atualizar esse formulário Documento Web, +You are not connected to Internet. Retry after sometime.,Você não está conectado à Internet. Tente novamente após algum tempo., +You are not permitted to access this page.,Você não tem permissão para acessar esta página., You are not permitted to view the newsletter.,Você não tem permissão para visualizar a newsletter., +You are now following this document. You will receive daily updates via email. You can change this in User Settings.,Você está seguindo este documento agora. Você receberá atualizações diárias via e-mail. Você pode alterar isso nas configurações do usuário., +You can add dynamic properties from the document by using Jinja templating.,Você pode adicionar propriedades dinâmicas do documento usando Jinja templates., +You can also copy-paste this ,Você também pode copiar e colar, "You can change Submitted documents by cancelling them and then, amending them.",Você pode alterar documentos cancelados, -You can find things by asking 'find orange in customers',"Você pode encontrar as coisas pedindo ""encontrar fulano em clientes""", +You can find things by asking 'find orange in customers',Você pode encontrar as coisas pedindo "encontrar fulano em clientes", You can only upload upto 5000 records in one go. (may be less in some cases),Você só pode fazer upload de até 5.000 registros de uma só vez. (Este valor pode vir a ser inferior em alguns casos), -You can use Customize Form to set levels on fields.,"Você pode usar ""Personalizar Formulário"" para definir os níveis de campos.", +You can use Customize Form to set levels on fields.,Você pode usar "Personalizar Formulário" para definir os níveis de campos., You can use wildcard %,Você pode usar o coringa %, -You cannot unset 'Read Only' for field {0},"Você não pode desabilitar ""Somente leitura"" para o campo {0}", +You can't set 'Options' for field {0},Você não pode configurar 'Opções' para o campo {0}, +You can't set 'Translatable' for field {0},Você não pode configurar 'Traduzível' para o campo {0}, +You cannot give review points to yourself,Você não pode dar pontos de avaliação para si mesmo, +You cannot unset 'Read Only' for field {0},Você não pode desabilitar "Somente leitura" para o campo {0}, You do not have enough permissions to access this resource. Please contact your manager to get access.,"Você não tem permissão suficiente para acessar este recurso. Por favor, contate o administrador para ter acesso.", You do not have enough permissions to complete the action,Você não tem permissão suficiente para completar a ação, +You do not have enough points,Você não tem pontos suficientes, +You do not have enough review points,Você não tem pontos de revisão suficientes, +You don't have access to Report: {0},Você não tem acesso ao Relatório: {0}, +You don't have any messages yet.,Ainda não tem nenhuma mensagem., You don't have permission to access this file,Você não tem permissão para acessar este arquivo, You don't have permission to get a report on: {0},Você não tem permissão para acessar um relatório sobre: {0}, +You don't have the permissions to access this document,Você não tem as permissões para acessar este documento, +You gained {0} point,Você ganhou {0} ponto, +You gained {0} points,Você ganhou {0} pontos, +You have a new message from: ,Você tem uma nova mensagem de:, You have been successfully logged out,Você saiu do sistema com sucesso, +You have unsaved changes in this form. Please save before you continue.,Você tem alterações não salvas neste formulário., You must login to submit this form,Você precisa estar logado para enviar este formulário, You need to be in developer mode to edit a Standard Web Form,Você precisa estar no modo de desenvolvedor para editar um Formulário Web Padrão, You need to be logged in and have System Manager Role to be able to access backups.,Você precisa estar conectado e ter permissão para ser capaz de acessar backups., -"You need to have ""Share"" permission","Você precisa ter a permissão ""Compartilhar""", +You need to be logged in to access this {0}.,Você precisa estar logado para acessar esta {0}., +You need to have "Share" permission,Você precisa ter a permissão "Compartilhar", +You need write permission to rename,Você precisa escrever permissão para renomear, +You selected Draft or Cancelled documents,Você selecionou documentos preliminares ou cancelados, +You unfollowed this document,Você deixou de seguir este documento, +Your Country,Seu País, +Your Language,Seu Idioma, Your Name,Seu Nome, +Your account has been locked and will resume after {0} seconds,Sua conta foi bloqueada e será retomada após {0} segundos, +Your connection request to Google Calendar was successfully accepted,Sua solicitação de conexão ao Google Agenda foi aceita com sucesso, Your information has been submitted,Suas informações foram enviadas, +Your login id is,Sua identificação de acesso é, Your organization name and address for the email footer.,Nome da empresa e endereço para o rodapé do email., +Your payment has been successfully registered.,Seu pagamento foi registrado com sucesso., +Your payment has failed.,O seu pagamento falhou., +Your payment is cancelled.,Seu pagamento está cancelado., +Your payment was successfully accepted,Seu pagamento foi aceito com sucesso, "Your query has been received. We will reply back shortly. If you have any additional information, please reply to this mail.","Sua consulta foi recebida. Nós responderemos de volta em breve. Se você tiver qualquer informação adicional, por favor responda a este email.", +"Your session has expired, please login again to continue.","Sua sessão expirou, faça o login novamente para continuar.", +Zero,Zero, +Zero means send records updated at anytime,Zero significa enviar registros atualizados a qualquer momento, +_doctype,_doctype, +_report,_relatório, +adjust,ajustar, +after_insert,after_insert, align-center,Centralizar, align-justify,Justificar, align-left,Alinhar à esquerda, align-right,Alinhar à direita, +ap-northeast-1,ap-northeast-1, +ap-northeast-2,ap-northeast-2, +ap-northeast-3,ap-northeast-3, +ap-south-1,ap-south-1, +ap-southeast-1,ap-southeast-1, +ap-southeast-2,ap-southeast-2, arrow-down,seta para baixo, arrow-left,seta para a esquerda, arrow-right,seta para a direita, arrow-up,seta para cima, +asterisk,asterisco, +backward,para trás, +ban-circle,círculo de proibição, +bell,sino, +bookmark,favorito, +briefcase,pasta, bullhorn,megafone, +ca-central-1,ca-central-1, camera,câmera, cancelled this document,cancelou este documento, changed value of {0},mudou o valor de {0}, @@ -1142,83 +2867,193 @@ chevron-up,divisa-acima, circle-arrow-down,círculo de seta para baixo, circle-arrow-left,círculo de seta para a esquerda, circle-arrow-right,círculo de seta à direita, +circle-arrow-up,círculo de seta para cima, +cn-north-1,cn-north-1, +cn-northwest-1,cn-northwest-1, +cog,roda dentada, +darkgrey,cinza escuro, +dd-mm-yyyy,dd-mm-aaaa, +dd.mm.yyyy,dd.mm.aaaa, +dd/mm/yyyy,dd/mm/aaaa, "document type..., e.g. customer","Tipo de documento ..., por exemplo: cliente", domain name,nome de domínio, +download-alt,download-alt, "e.g. ""Support"", ""Sales"", ""Jerry Yang""","ex: ""Pós-Venda"", "" Vendas "", ""Edmilson""", e.g. (55 + 434) / 4 or =Math.sin(Math.PI/2)...,por exemplo (55 + 434) / 4 ou = Math.sin (Math.PI / 2) ..., +e.g. pop.gmail.com / imap.gmail.com,ex: pop.gmail.com / imap.gmail.com, e.g. replies@yourcomany.com. All replies will come to this inbox.,eg replies@yourcomany.com. Todas as respostas virão a esta caixa de entrada., +e.g. smtp.gmail.com,ex: smtp.gmail.com, e.g.:,ex:, +eject,ejetar, +envelope,envelope, +eu-central-1,eu-central-1, +eu-north-1,eu-north-1, +eu-west-1,eu-west-1, +eu-west-2,eu-oeste-2, +eu-west-3,eu-oeste-3, +exclamation-sign,sinal de exclamação, eye-close,olho fechado, eye-open,olho aberto, facetime-video,vídeo do facetime, +fairlogin,fairlogin, fast-backward,retrocesso rápido, fast-forward,avanço rápido, +film,filme, +fire,fogo, folder-close,fechar pasta, folder-open,abrir pasta, fullscreen,tela cheia, +gained by {0} via automatic rule {1},ganho por {0} via regra automática {1}, +gained {0} points,ganhou {0} pontos, +gave {0} points,deu {0} pontos, +gift,presente, +glass,vidro, +globe,globo, hand-down,mão abaixo, hand-left,mão à esquerda, hand-right,mão à direita, hand-up,mão acima, hdd,hdd, headphones,fones de ouvido, +heart,coração, hub,Hub, indent-left,indentar à esquerda, indent-right,indentar à direita, info-sign,Sinal de Informações, +italic,itálico, +john@doe.com,john@doe.com, +just now,agora mesmo, +leaf,folha, +lightblue,azul claro, list-alt,lista de alt-, magnet,ímã, map-marker,marcador do mapa, merged {0} into {1},Combinado {0} com {1}, +minus,menos, minus-sign,sinal de menos, +mm-dd-yyyy,mm-dd-aaaa, +mm/dd/yyyy,mm/dd/aaaa, module name...,nome do módulo ..., +new type of document,novo tipo de documento, +no failed attempts,tentativas não falharam, none of,nenhum, +ok,ok, ok-circle,ok-círculo, ok-sign,ok-sinal, +on_cancel,on_cancel, +on_change,em mudança, +on_submit,on_submit, +on_trash,on_trash, +on_update,on_update, +on_update_after_submit,on_update_after_submit, only.,apenas., +or,ou, +pause,pausar, +pencil,lápis, +picture,imagem, +plane,avião, play,jogar, play-circle,jogo-círculo, +plus,mais, plus-sign,sinal de mais, qrcode,QRCode, +query-report,relatório-de-consulta, question-sign,ponto de interrogação, remove-circle,remove-círculo, remove-sign,remover-assinar, +removed,removido, +renamed from {0} to {1},renomeado de {0} para {1}, +repeat,repetir, resize-full,redimensionamento completo, resize-horizontal,redimensionamento horizontal, resize-small,redimensionamento pequeno, resize-vertical,redimensionamento vertical, +restored {0} as {1},restaurado {0} como {1}, retweet,retwitar, +road,estrada, +sa-east-1,sa-east-1, screenshot,captura de tela, share-alt,partes-alt, +shopping-cart,carrinho de compras, show,mostrar, +signal,sinalizar, +star,estrela, +star-empty,sem estrela, step-backward,voltar, step-forward,prosseguir, submitted this document,enviou este documento, +text in document type,texto em tipo de documento, text-height,altura de texto, text-width,largura de texto, +th,ª, +th-large,ª-grande, +th-list,ª-lista, thumbs-down,polegar para baixo, +thumbs-up,polegar para cima, +tint,matiz, +toggle Tag,alternar Tag, +updated to {0},atualizado para {0}, +us-east-1,us-east-1, +us-east-2,us-east-2, +us-west-1,us-west-1, +us-west-2,us-west-2, use % as wildcard,usar % como coringa, +values separated by commas,valores separados por vírgulas, +via automatic rule {0} on {1},via regra automática {0} em {1}, +viewed,visto, volume-down,diminuir volume, volume-off,mudo, volume-up,aumentar volume, warning-sign,sinal de alerta, +wrench,chave inglesa, yyyy-mm-dd,dd/mm/yyyy, zoom-in,aumentar zoom, zoom-out,diminuir zoom, +{0} Calendar,{0} Calendário, +{0} Chart,{0} Gráfico, +{0} Dashboard,{0} Dashboard, {0} List,{0} Lista(s), +{0} Modules,{0} módulos, {0} Report,{0} Relatório, {0} Settings not found,{0} Configurações não encontradas, {0} Tree,Árvore de {0}, +{0} added,{0} adicionado, +{0} already exists. Select another name,{0} já existe. Selecione outro nome, {0} already unsubscribed,{0} já teve sua inscrição removida, {0} already unsubscribed for {1} {2},{0} já teve sua sua inscrição cancelada para {1} {2}, +{0} and {1},{0} e {1}, +{0} appreciated on {1},{0} apreciado em {1}, +{0} appreciated your work on {1} with {2} point,{0} apreciou seu trabalho em {1} com {2} ponto, +{0} appreciated your work on {1} with {2} points,{0} apreciou seu trabalho em {1} com {2} pontos, +{0} appreciated {1},{0} apreciado {1}, +{0} appreciation point for {1} {2},{0} ponto de apreciação para {1} {2}, +{0} appreciation points for {1} {2},{0} pontos de apreciação para {1} {2}, +{0} assigned {1}: {2},{0} atribuído {1}: {2}, {0} cannot be set for Single types,{0} não pode ser ajustada para os modelos únicos, +{0} comments,{0} comentários, +{0} created successfully,{0} criado com sucesso, +{0} criticism point for {1} {2},{0} ponto de crítica para {1} {2}, +{0} criticism points for {1} {2},{0} pontos de criticismo para {1} {2}, +{0} criticized on {1},{0} criticado em {1}, +{0} criticized your work on {1} with {2} point,{0} criticou seu trabalho em {1} com {2} ponto, +{0} criticized your work on {1} with {2} points,{0} criticou seu trabalho em {1} com {2} pontos, +{0} criticized {1},{0} criticou {1}, +{0} days ago,{0} dias atrás, {0} does not exist in row {1},{0} não existe em linha {1}, "{0} field cannot be set as unique in {1}, as there are non-unique existing values","{0} campo não pode ser definido como único em {1}, pois há valores duplicados existentes", +{0} has already assigned default value for {1}.,{0} já atribuiu o valor padrão para {1}., {0} has been successfully added to the Email Group.,"{0} foi adicionado com sucesso ao grupo de emails,", {0} has left the conversation in {1} {2},{0} deixou a conversa em {1} {2}, +{0} hours ago,{0} horas atrás, {0} in row {1} cannot have both URL and child items,{0} na linha {1} não pode ter URL e Itens vinculados ao mesmo tempo, +{0} is a mandatory field,{0} é um campo obrigatório, +{0} is an invalid email address in 'Recipients',{0} é um endereço de e-mail inválido em 'Destinatários', +{0} is not a raw printing format.,{0} não é um formato de impressão não processado., +{0} is not a valid Email Address,{0} não é um endereço de email válido, +{0} is not a valid Workflow State. Please update your Workflow and try again.,{0} não é um estado válido do fluxo de trabalho. Atualize seu fluxo de trabalho e tente novamente., {0} is now default print format for {1} doctype,{0} agora é o formato de impressão padrão para o doctype {1}, {0} is saved,{0} foi salvo, +{0} items selected,{0} itens selecionados, {0} logged in,{0} logado(s), {0} logged out: {1},{0} deslogado: {1}, {0} minutes ago,{0} minutos atrás, @@ -1228,18 +3063,35 @@ zoom-out,diminuir zoom, {0} must be unique,{0} já foi cadastrado e deve ser único, {0} not a valid State,{0} não é um status válido, {0} not allowed to be renamed,não é permitido renomear {0}, -{0} self assigned this task: {1},{0} autodesignou esta tarefa: {1}, +{0} not found,{0} não encontrado, +{0} of {1},{0} de {1}, +{0} or {1},{0} ou {1}, +{0} record deleted,{0} registro excluído, +{0} records deleted,{0} registros excluídos, +{0} reverted your point on {1},{0} reverteu seu ponto em {1}, +{0} reverted your points on {1},{0} reverteu seus pontos em {1}, +{0} reverted {1},{0} revertido {1}, +{0} room must have atmost one user.,{0} sala deve ter no máximo um usuário., +{0} rows for {1},{0} linhas para {1}, +{0} saved successfully,{0} salvo com sucesso, +{0} self assigned this task: {1},{0} self designou esta tarefa: {1}, {0} shared this document with everyone,{0} compartilhou este documento com todos, {0} shared this document with {1},{0} compartilhou este documento com {1}, {0} subscribers added,{0} assinantes acrescentados, +{0} to stop receiving emails of this type,{0} para parar de receber e-mails desse tipo, +{0} to {1},{0} para {1}, {0} un-shared this document with {1},{0} descompartilhou este documento com {1}, {0} updated,{0} atualizado(a), {0} weeks ago,{0} semanas atrás, -"{0} {1} cannot be ""{2}"". It should be one of ""{3}""","{0} {1} não pode ser ""{2}"". Deve pertencer a ""{3}""", +{0} {1} added,{0} {1} adicionado, +{0} {1} already exists,{0} {1} já existe, +{0} {1} cannot be "{2}". It should be one of "{3}",{0} {1} não pode ser "{2}". Deve pertencer a "{3}", {0} {1} cannot be a leaf node as it has children,"{0} {1} não pode ser um nó de extremidade , uma vez que tem filhos", "{0} {1} does not exist, select a new target to merge","{0} {1} não existe , selecione um novo alvo para mesclar", {0} {1} not found,{0} {1} não encontrado, {0} {1} to {2},{0} {1} para {2}, +"{0}, Row {1}","{0}, Linha {1}", +"{0}: '{1}' ({3}) will get truncated, as max characters allowed is {2}","{0}: '{1}' ({3}) vai ficar truncado, pois os caracteres máximos permitidos são {2}", {0}: Cannot set Amend without Cancel,{0}: Não é possível definir Amend sem Cancelar, {0}: Cannot set Assign Amend if not Submittable,{0}: Não é possível definir atributo Corrigir se não pode ser enviado, {0}: Cannot set Assign Submit if not Submittable,{0}: Não é possível definir atributo Enviar se não pode ser enviado, @@ -1250,110 +3102,1601 @@ zoom-out,diminuir zoom, {0}: No basic permissions set,{0}: Nenhum conjunto de permissões básico, "{0}: Only one rule allowed with the same Role, Level and {1}","{0}: Apenas uma regra de permissão com a mesma função, nível e {1}", {0}: Permission at level 0 must be set before higher levels are set,{0} : permissão no nível 0 deve ser definida antes de definir os níveis mais altos, +{0}: {1} in {2},{0}: {1} em {2}, +{0}: {1} is set to state {2},{0}: {1} está configurado para declarar {2}, {app_title},{app_title}, {{{0}}} is not a valid fieldname pattern. It should be {{field_name}}.,{{{0}}} não é padrão para nome de campo válido. Deve ser {{field_name}}., -Allow Google Drive Access,Permitir acesso Google Drive, -Change,Alteração, -Clear Filters,Remover Filtros, -Contact Email,Email do Contato, -From Date,A Partir da Data, -Keyboard Shortcuts,Atalhos do Teclado, -Mark all as Read,Marcar todas como lidas, +Communication Link,Link de comunicação, +Force User to Reset Password,Forçar usuário a redefinir a senha, +In Days,Em dias, +Last Password Reset Date,Data da última redefinição de senha, +The password of your account has expired.,A senha da sua conta expirou., +Workflow State transition not allowed from {0} to {1},Transição do estado do fluxo de trabalho não permitida de {0} para {1}, +{0} must be after {1},{0} deve ser depois de {1}, +{0}: Field '{1}' cannot be set as Unique as it has non-unique values,"{0}: o campo '{1}' não pode ser definido como Único, pois possui valores não exclusivos", +{0}: Field {1} in row {2} cannot be hidden and mandatory without default,{0}: o campo {1} na linha {2} não pode ser oculto e obrigatório sem padrão, +{0}: Field {1} of type {2} cannot be mandatory,{0}: o campo {1} do tipo {2} não pode ser obrigatório, +{0}: Fieldname {1} appears multiple times in rows {2},{0}: O nome do campo {1} aparece várias vezes nas linhas {2}, +{0}: Fieldtype {1} for {2} cannot be unique,{0}: o tipo de campo {1} para {2} não pode ser exclusivo, +{0}: Options must be a valid DocType for field {1} in row {2},{0}: as opções devem ser um DocType válido para o campo {1} na linha {2}, +{0}: Options required for Link or Table type field {1} in row {2},{0}: Opções necessárias para o campo Tipo de link ou tabela {1} na linha {2}, +{0}: Options {1} must be the same as doctype name {2} for the field {3},{0}: as opções {1} devem ser as mesmas que o nome do tipo de documento {2} para o campo {3}, +{0}:Fieldtype {1} for {2} cannot be indexed,{0}: o tipo de campo {1} para {2} não pode ser indexado, +Make {0},Faça {0}, +A user who posts blogs.,Um usuário que posta blogs., +Applying: {0},Aplicando: {0}, +Fieldname {0} is restricted,O nome do campo {0} é restrito, +Is Optional State,É estado opcional, +No values to show,Nenhum valor para mostrar, +View Ref,Visualizar Ref, +Workflow Action is not created for optional states,A ação do fluxo de trabalho não é criada para estados opcionais, +{0} values selected,{0} valores selecionados, +"amended_from" field must be present to do an amendment.,O campo "alterado_de" deve estar presente para fazer uma alteração., +(Mandatory),(Obrigatório), +1 Google Calendar Event synced.,1 Evento do Google Agenda sincronizado., +1 record will be exported,1 registro será exportado, +1 week ago,1 semana atrás, +5 Records,5 registros, +A recurring {0} {1} has been created for you via Auto Repeat {2}.,Um {0} {1} recorrente foi criado para você através da Repetição automática {2}., +API,API, +API Method,Método API, +About {0} minute remaining,Cerca de {0} minuto restante, +About {0} minutes remaining,Cerca de {0} minutos restantes, +About {0} seconds remaining,Cerca de {0} segundos restantes, +Access Log,Log de acesso, +Access not allowed from this IP Address,Acesso não permitido deste endereço IP, +Action Type,Tipo de acão, +Activity Log by ,Log de atividades por, +Add Fields,Adicionar campos, +Administration,Administração, +After Cancel,Após Cancelar, +After Delete,Após Excluir, +After Save,Após salvar, +After Save (Submitted Document),Após salvar (documento enviado), +After Submit,Após o envio, +Aggregate Function Based On,Função agregada com base em, +Aggregate Function field is required to create a dashboard chart,O campo Função Agregada é necessário para criar um gráfico de dashboard, +All Records,Todos os registros, +Allot Points To Assigned Users,Atribuir pontos aos usuários atribuídos, +Allow Auto Repeat,Permitir repetição automática, +Allow Google Calendar Access,Permitir acesso ao Google Agenda, +Allow Google Contacts Access,Permitir acesso aos Contatos do Google, +Allow Google Drive Access,Permitir acesso ao Google Drive, +Allow Guest,Permitir convidado, +Allow Guests to Upload Files,Permitir que os convidados façam upload de arquivos, +Also adding the status dependency field {0},Incluindo também o campo de dependência do status {0}, +An error occurred while setting Session Defaults,Ocorreu um erro ao definir os Padrões da Sessão, +Annual,Anual, +Append Emails to Sent Folder,Anexar emails à pasta enviada, +Apply Assignment Rule,Aplicar regra de atribuição, +Apply Only Once,Aplicar apenas uma vez, +Apply this rule only once per document,Aplique esta regra apenas uma vez por documento, +Approval Required,Aprovação necessária, +Approved,Aprovado, +Are you sure you want to delete all rows?,Tem certeza de que deseja excluir todas as linhas?, +Are you sure you want to delete this post?,Tem certeza de que deseja excluir esta postagem?, +Are you sure you want to merge {0} with {1}?,Tem certeza de que deseja mesclar {0} com {1}?, +Assignment Day {0} has been repeated.,O dia da tarefa {0} foi repetido., +Assignment Days,Dias de atribuição, +Assignment Rule Day,Dia da regra de atribuição, +Assignments,atribuições, +Attach a web link,Anexar um link da web, +Authorize Google Calendar Access,Autorizar acesso ao Google Agenda, +Authorize Google Contacts Access,Autorizar o acesso dos Contatos do Google, +Authorize Google Drive Access,Autorizar acesso ao Google Drive, +Auto Repeat Document Creation Failed,Falha na criação de documentos de repetição automática, +Auto Repeat Document Creation Failure,Falha na criação de documentos de repetição automática, +Auto Repeat created for this document,Repetição automática criada para este documento, +Auto Repeat failed for {0},A repetição automática falhou para {0}, +Automatic Linking can be activated only for one Email Account.,O link automático pode ser ativado apenas para uma conta de e-mail., +Automatic Linking can be activated only if Incoming is enabled.,O Link automático só pode ser ativado se a Entrada estiver ativada., +Automatically generates recurring documents.,Automaticamente gera documentos recorrentes., +Backing up to Google Drive.,Fazendo backup no Google Drive., +Backup Folder ID,ID da pasta de backup, +Backup Folder Name,Nome da pasta de backup, +Before Cancel,Antes de Cancelar, +Before Delete,Antes de excluir, +Before Insert,Antes da inserção, +Before Save,Antes de salvar, +Before Save (Submitted Document),Antes de salvar (documento enviado), +Before Submit,Antes de enviar, +Blank Template,Modelo em branco, +Callback URL,URL de retorno de chamada, +Cancel All Documents,Cancelar todos os documentos, +Cancelling documents,Cancelando documentos, +Cannot match column {0} with any field,Não é possível combinar a coluna {0} com nenhum campo, +Change,mudança, +Change User,Mudar usuário, +Check the Error Log for more information: {0},Verifique o log de erros para mais informações: {0}, +Clear Cache and Reload,Limpar cache e recarregar, +Clear Filters,Limpar filtros, +Click on Authorize Google Drive Access to authorize Google Drive Access.,Clique em Autorizar acesso ao Google Drive para autorizar o acesso ao Google Drive., +Click on a file to select it.,Clique em um arquivo para selecioná-lo., +Click on the link below to approve the request,Clique no link abaixo para aprovar o pedido, +Click on the lock icon to toggle public/private,Clique no ícone de cadeado para alternar entre público / privado, +Click on {0} to generate Refresh Token.,Clique em {0} para gerar o Token de Atualização., +Close Condition,Fechar Condição, +Column {0},Coluna {0}, +Columns / Fields,Colunas / Campos, +"Configure notifications for mentions, assignments, energy points and more.","Configure notificações para menções, atribuições, pontos de energia e muito mais.", +Contact Email,Email de Contato, +Contact Numbers,Números de contato, +Contact Phone,telefone de contato, +Contact Synced with Google Contacts.,Contato sincronizado com os contatos do Google., +Context,Contexto, +Contribute Translations,Contribuir Traduções, +Contributed,Contribuído, +Controller method get_razorpay_order missing,Falta o método get_razorpay_order do controlador, +Copied to clipboard.,Copiado para a área de transferência., +Core Modules {0} cannot be searched in Global Search.,Os módulos principais {0} não podem ser pesquisados na Pesquisa Global., +Could not create Razorpay order. Please contact Administrator,Não foi possível criar o pedido Razorpay. Entre em contato com o administrador, +Could not create razorpay order,Não foi possível criar a ordem razorpay, +Create Log,Criar log, +Create your first {0},Crie seu primeiro {0}, +Created {0} records successfully.,Criou {0} registros com sucesso., +Cron,Cron, +Cron Format,Formato Cron, +Daily Events should finish on the Same Day.,Os eventos diários devem terminar no mesmo dia., +Daily Long,Diário Longo, +Default Role on Creation,Função Padrão na Criação, +Default Theme,Tema Padrão, +Default {0},Padrão {0}, +Delete All,Excluir tudo, +Do you want to cancel all linked documents?,Deseja cancelar todos os documentos vinculados?, +DocType Action,Ação DocType, +DocType Event,Evento DocType, +DocType Link,Link DocType, +Document Share,Partilha de Documentos, +Document Tag,Etiqueta de Documento, +Document Title,Título do documento, +Document Type Field Mapping,Mapeamento de campos do tipo de documento, +Document Type Mapping,Mapeamento do tipo de documento, +Document Type {0} has been repeated.,O tipo de documento {0} foi repetido., +Document renamed from {0} to {1},Documento renomeado de {0} para {1}, +Document type is required to create a dashboard chart,O tipo de documento é necessário para criar um gráfico de dashboard, +Documentation Link,Link da documentação, +Don't Import,Não importe, +Don't Send Emails,Não envie emails, +"Drag and drop files, ","Arraste e solte arquivos,", +Drop,Solta, +Drop Here,Solta aqui, +Drop files here,Solte arquivos aqui, +Dynamic Template,Modelo dinâmico, +ERPNext Role,Função ERPNext, +Email / Notifications,Email / Notificações, +Email Account setup please enter your password for: {0},"Configuração da conta de e-mail, digite sua senha para: {0}", +Email Address whose Google Contacts are to be synced.,Endereço de e-mail cujos contatos do Google devem ser sincronizados., +"Email ID must be unique, Email Account already exists for {0}",O ID do email deve ser exclusivo. A conta de email já existe para {0}, +Email IDs,IDs de email, +Enable Allow Auto Repeat for the doctype {0} in Customize Form,Ativar Permitir repetição automática para o tipo de documento {0} em Personalizar formulário, +Enable Automatic Linking in Documents,Ativar Vinculação Automática em Documentos, +Enable Email Notifications,Ativar notificações por email, +Enable Google API in Google Settings.,Ative a API do Google nas configurações do Google., +Enable Security,Ativar segurança, +Energy Point,Ponto de energia, +Enter Client Id and Client Secret in Google Settings.,Digite o ID do cliente e o segredo do cliente nas Configurações do Google., +Enter Code displayed in OTP App.,Digite o código exibido no aplicativo OTP., +Event Configurations,Configurações de evento, +Event Consumer,Consumidor de Eventos, +Event Consumer Document Type,Tipo de documento do consumidor do evento, +Event Consumer Document Types,Tipos de documento do consumidor do evento, +Event Producer,Produtor de Eventos, +Event Producer Document Type,Tipo de documento do produtor de eventos, +Event Producer Document Types,Tipos de documento do produtor de eventos, +Event Streaming,Fluxo de Eventos, +Event Subscriber,Assinante do Evento, +Event Sync Log,Log de Sincronização de Eventos, +Event Synced with Google Calendar.,Evento sincronizado com o Google Agenda., +Event Update Log,Log de Atualização de Eventos, +Export 1 record,Exportar 1 registro, +Export Errored Rows,Exportar linhas com erro, +Export From,Exportar de, +Export Type,Tipo de exportação, +Export {0} records,Exportar {0} registros, +Failed to connect to the Event Producer site. Retry after some time.,Falha ao conectar ao site do Event Producer. Tente novamente após algum tempo., +Failed to create an Event Consumer or an Event Consumer for the current site is already registered.,Falha ao criar um Consumidor de Eventos ou Consumidor de Eventos para o site atual já está registrado., +Failure,Falha, +Fetching default Global Search documents.,Buscando documentos padrão da Pesquisa Global., +Fetching posts...,Buscando postagens ..., +Field Mapping,Mapeamento de Campo, +Field To Check,Campo a verificar, +File Information,Informações do arquivo, +Filter By,Filtrar por, +Filtered Records,Registros Filtrados, +Filters applied for {0},Filtros aplicados para {0}, +Finished,Acabado, +First,Primeiro, +For Document Event,Para evento de documento, +"For more information, click here.","Para mais informações, clique aqui .", +"For more information, {0}.","Para mais informações, {0}.", +"For performance, only the first 100 rows were processed.","Para desempenho, apenas as primeiras 100 linhas foram processadas.", +Form URL-Encoded,Codificado em URL do formulário, +Frequently Visited Links,Links visitados frequentemente, +From Date,Data De, +From User,Do Usuário, +Global Search DocType,DocType de pesquisa global, +Global Search Document Types Reset.,Redefinir tipos de documentos de pesquisa global., +Global Search Settings,Configurações globais de pesquisa, +Global Shortcuts,Atalhos Globais, +Go,Ir, +Go to next record,Vai para o próximo registro, +Go to previous record,Ir para o registro anterior, +Google API Settings.,Configurações da API do Google., +Google Calendar,Agenda do Google, +"Google Calendar - Could not create Calendar for {0}, error code {1}.","Google Agenda - Não foi possível criar a Agenda para {0}, código de erro {1}.", +"Google Calendar - Could not delete Event {0} from Google Calendar, error code {1}.","Google Agenda - Não foi possível excluir o Evento {0} do Google Agenda, código de erro {1}.", +"Google Calendar - Could not fetch event from Google Calendar, error code {0}.","Google Agenda - Não foi possível buscar o evento no Google Agenda, código de erro {0}.", +"Google Calendar - Could not insert contact in Google Contacts {0}, error code {1}.","Google Agenda - Não foi possível inserir o contato nos Contatos do Google {0}, código de erro {1}.", +"Google Calendar - Could not insert event in Google Calendar {0}, error code {1}.","Google Agenda - Não foi possível inserir o evento no Google Agenda {0}, código de erro {1}.", +"Google Calendar - Could not update Event {0} in Google Calendar, error code {1}.","Google Agenda - Não foi possível atualizar o Evento {0} no Google Agenda, código de erro {1}.", +Google Calendar Event ID,ID do evento do Google Agenda, +Google Calendar Integration.,Integração com o Google Agenda., +Google Calendar has been configured.,O Google Agenda foi configurado., +Google Contacts,Contatos do Google, +"Google Contacts - Could not sync contacts from Google Contacts {0}, error code {1}.","Contatos do Google - Não foi possível sincronizar contatos dos Contatos do Google {0}, código de erro {1}.", +"Google Contacts - Could not update contact in Google Contacts {0}, error code {1}.","Contatos do Google - Não foi possível atualizar o contato nos Contatos do Google {0}, código de erro {1}.", +Google Contacts Id,ID de contatos do Google, +Google Contacts Integration is disabled.,A integração de contatos do Google está desativada., +Google Contacts Integration.,Integração de Contatos do Google., +Google Contacts has been configured.,O Contatos do Google foi configurado., +Google Drive,Google Drive, +Google Drive - Could not create folder in Google Drive - Error Code {0},Google Drive - Não foi possível criar a pasta no Google Drive - Código de erro {0}, +Google Drive - Could not find folder in Google Drive - Error Code {0},Google Drive - Não foi possível encontrar a pasta no Google Drive - Código de erro {0}, +Google Drive Backup Successful.,Backup do Google Drive bem-sucedido., +Google Drive Backup.,Backup do Google Drive., +Google Drive Integration.,Integração com o Google Drive., +Google Drive has been configured.,O Google Drive foi configurado., +Google Integration is disabled.,A integração do Google está desativada., +Google Settings,Configurações do Google, +Group By,Agrupar por, +Group By Based On,Agrupar por Com base em, +Group By Type,Agrupar por tipo, +Group By field is required to create a dashboard chart,O campo Agrupar por é necessário para criar um gráfico de dashboard, +HH:mm,HH: mm, +HH:mm:ss,HH: mm: ss, +HOOK-.####,GANCHO-.####, +HTML Page,Página HTML, +Has Mapping,Possui mapeamento, +Hourly Long,Por hora, +"If non-standard port (e.g. POP3: 995/110, IMAP: 993/143)","Se porta não padrão (por exemplo, POP3: 995/110, IMAP: 993/143)", +If the document has different field names on the Producer and Consumer's end check this and set up the Mapping,"Se o documento tiver nomes de campos diferentes no final do produtor e do consumidor, verifique isso e configure o mapeamento", +If this is checked the documents will have the same name as they have on the Event Producer's site,"Se esta opção estiver marcada, os documentos terão o mesmo nome do site do Produtor de Eventos", +Illegal SQL Query,Consulta SQL ilegal, +Import File,Importar arquivo, +Import Log Preview,Visualização do registro de importação, +Import Preview,Visualização de importação, +Import Progress,Progresso da importação, +Import Type,Tipo de Importação, +Import Warnings,Avisos de importação, +"Import template should be of type .csv, .xlsx or .xls","O modelo de importação deve ser do tipo .csv, .xlsx ou .xls", +Import template should contain a Header and atleast one row.,"O modelo de importação deve conter um cabeçalho e, pelo menos, uma linha.", +Importing {0} of {1},Importando {0} de {1}, +"Importing {0} of {1}, {2}","Importando {0} de {1}, {2}", +Include indentation,Incluir recuo, +Incoming Change,Mudança de entrada, +Invalid Filter Value,Valor de filtro inválido, +Invalid URL,URL inválida, +Invalid field name: {0},Nome do campo inválido: {0}, +Invalid file URL. Please contact System Administrator.,URL de arquivo inválido. Entre em contato com o administrador do sistema., +Invalid include path,Caminho de inclusão inválido, +Invalid username or password,nome de usuário ou senha inválidos, +Is Primary,É primário, +Is Primary Mobile,É o celular principal, +Is Primary Phone,É o telefone principal, +Is Tree,É árvore, +JSON Request Body,Corpo da solicitação JSON, +Javascript is disabled on your browser,Javascript está desativado em seu navegador, +Job,Trabalho, +Jump to field,Ir para o campo, +Keyboard Shortcuts,Atalhos do teclado, +LDAP Group,Grupo LDAP, +LDAP Group Field,Campo do Grupo LDAP, +LDAP Group Mapping,Mapeamento do Grupo LDAP, +LDAP Group Mappings,Mapeamentos de grupo LDAP, +LDAP Last Name Field,Campo Sobrenome LDAP, +LDAP Middle Name Field,Campo de nome do meio LDAP, +LDAP Mobile Field,Campo Móvel LDAP, +LDAP Phone Field,Campo de telefone LDAP, +LDAP User Creation and Mapping,Criação e Mapeamento de Usuários LDAP, +Landscape,Panorama, +Last,Último, +Last Backup On,Último backup ativado, +Last Execution,Última Execução, +Last Sync On,Última sincronização em, +Last Update,Última atualização, +Last refreshed,Última atualização, +Link Document Type,Tipo de Documento de Link, +Link Fieldname,Nome do campo do link, +Loading import file...,Carregando arquivo de importação ..., +Local Document Type,Tipo de Documento Local, +Log Data,Dados de log, +Main Section (HTML),Seção Principal (HTML), +Main Section (Markdown),Seção Principal (Remarcação), +"Maintains a Log of all inserts, updates and deletions on Event Producer site for documents that have consumers.","Mantém um log de todas as inserções, atualizações e exclusões no site do Event Producer para documentos que possuem consumidores.", +Maintains a log of every event consumed along with the status of the sync and a Resync button in case sync fails.,"Mantém um log de todos os eventos consumidos, juntamente com o status da sincronização e um botão Resync, caso a sincronização falhe.", +Make all attachments private,Tornar todos os anexos privados, +Mandatory Depends On,Obrigatório Depende, +Map Columns,Colunas do mapa, +Map columns from {0} to fields in {1},Mapeie colunas de {0} para campos em {1}, +Mapping column {0} to field {1},Mapeando a coluna {0} para o campo {1}, +Mark all as Read,Marcar tudo como lido, +Maximum Points,Pontos Máximos, +Maximum points allowed after multiplying points with the multiplier value\n(Note: For no limit leave this field empty or set 0),"Número máximo de pontos permitido após a multiplicação de pontos pelo valor multiplicador (Nota: para sem limite, deixe este campo vazio ou defina 0)", +Me,Eu, +Mention,Menção, Modules,módulos, -Naming Series,Código dos Documentos, -No Events Today,Nenhum evento hoje, -Notification Settings,Configurações de Notificação, -Open Documents,Documentos Abertos, +Monthly Long,Mensalmente Longo, +Naming Series,Série de Atrib. de Nomes, +Navigate Home,Navegue para casa, +Navigate list down,Navegar pela lista, +Navigate list up,Navegar pela lista, +New Notification,Nova notificação, +New {0}: {1},Novo {0}: {1}, +Newsletter should have atleast one recipient,O boletim deve ter pelo menos um destinatário, +No Events Today,Hoje não há eventos, +No Google Calendar Event to sync.,Nenhum evento do Google Agenda para sincronizar., +No More Activity,Não há mais atividade, +No Name Specified for {0},Nenhum nome especificado para {0}, +No Upcoming Events,Não há eventos futuros, +No activity,Nenhuma atividade, +No conditions provided,Nenhuma condição fornecida, +No contacts linked to document,Nenhum contato vinculado ao documento, +No data to export,Nenhum dado para exportar, +No documents found tagged with {0},Nenhum documento encontrado marcado com {0}, +No failed logs,Nenhum registro com falha, +No filters found,Nenhum filtro encontrado, +No more items to display,Não há mais itens para exibir, +No more posts,Não há mais postagens, +No new Google Contacts synced.,Nenhum novo Google Contacts sincronizado., +No pending or current jobs for this site,Não há trabalhos pendentes ou atuais para este site, +No posts yet,Ainda não há posts, +No records will be exported,Nenhum registro será exportado, +No results found for {0} in Global Search,Nenhum resultado encontrado para {0} na Pesquisa Global, +No user found,Nenhum usuário encontrado, +Not Specified,Não especificado, +Notification Log,Registro de Notificação, +Notification Settings,Configurações de notificação, +Notification Subscribed Document,Documento assinado de notificação, +Notifications Disabled,Notificações desativadas, +Number of Groups,Número de Grupos, +OAuth Client ID,ID do cliente OAuth, +OTP setup using OTP App was not completed. Please contact Administrator.,A configuração do OTP usando o aplicativo OTP não foi concluída. Entre em contato com o administrador., +Only one {0} can be set as primary.,Somente um {0} pode ser definido como primário., +Open Awesomebar,Open Awesomebar, +Open Chat,Abrir Chat, +Open Documents,Documentos abertos, +Open Help,Abra a Ajuda, +Open Settings,Abrir configurações, +Open list item,Abrir item da lista, +Organizational Unit for Users,Unidade Organizacional para Usuários, +Page Shortcuts,Atalhos de página, +Parent Field (Tree),Campo pai (árvore), +Parent Field must be a valid fieldname,O campo pai deve ser um nome de campo válido, +Pin Globally,Fixar globalmente, +Places,Lugares, +Please check the filter values set for Dashboard Chart: {},Verifique os valores de filtro definidos para o gráfico do dashboard: {}, +Please enable pop-ups in your browser,Por favor habilite pop-ups em seu navegador, +Please find attached {0}: {1},"Por favor, encontre em anexo {0}: {1}", +Please select applicable Doctypes,Por favor selecione Doctypes aplicáveis, +Portrait,Retrato, +Press Alt Key to trigger additional shortcuts in Menu and Sidebar,Pressione a tecla Alt para acionar atalhos adicionais no menu e na barra lateral, +Print Settings...,Configurações de impressão ..., +Producer Document Name,Nome do Documento do Produtor, +Producer URL,URL do produtor, +Property Depends On,Propriedade depende, +Pull from Google Calendar,Puxe do Google Agenda, +Pull from Google Contacts,Pull dos Contatos do Google, +Pulled from Google Calendar,Extraído do Google Agenda, +Pulled from Google Contacts,Extraído dos Contatos do Google, +Push to Google Calendar,Enviar para o Google Agenda, +Push to Google Contacts,Enviar para os Contatos do Google, +Queue / Worker,Fila / Trabalhador, +RAW Information Log,Registro de informações RAW, +Raw Printing Settings...,Configurações de impressão bruta ..., +Read Only Depends On,Somente leitura depende, +Recent Activity,Atividade recente, +Reference document has been cancelled,O documento de referência foi cancelado, +Reload File,Recarregar arquivo, +Remote Document Type,Tipo de documento remoto, +"Renamed files and replaced code in controllers, please check!","Renomeado arquivos e substituído o código em controladores, por favor, verifique!", +Repeat on Last Day of the Month,Repetir no último dia do mês, +Repeats {0},Repete {0}, +Report Information,Informações do Relatório, +Report with more than 10 columns looks better in Landscape mode.,Relatório com mais de 10 colunas parece melhor no modo Paisagem., +Request Structure,Estrutura da solicitação, +Restricted,Restrito, +Restrictions,Restrições, +Resync,Ressincronizar, +Row Number,Número da linha, +Row {0},Linha {0}, +Run Jobs only Daily if Inactive For (Days),Executar trabalhos apenas diariamente se inativo por (dias), +SMS was not sent. Please contact Administrator.,O SMS não foi enviado. Entre em contato com o administrador., +Saved Successfully,Salvo com sucesso, +Scheduled Job,Trabalho agendado, +Scheduled Job Log,Registro de trabalho agendado, +Scheduled Job Type,Tipo de trabalho agendado, +Scheduler Inactive,Agendador inativo, +Scheduler is inactive. Cannot import data.,O agendador está inativo. Não é possível importar dados., +Script Manager,Gerenciador de scripts, Script Type,Tipo de Script, -Select Mandatory,Selecionar Campos Obrigatórios, -Today's Events,Eventos de Hoje, -Upcoming Events,Próximos Eventos, -Add / Manage Email Accounts.,Adicionar / Gerenciar contas de email., -Add Child,Adicionar sub-item, +Search Priorities,Prioridades de pesquisa, +Search Source Text,Texto de origem da pesquisa, +Search by filename or extension,Pesquisar por nome de arquivo ou extensão, +Select Date Range,Selecionar período, +Select Field,Selecione o campo, +Select Field...,Selecionar campo ..., +Select Filters,Selecione Filtros, +Select Google Calendar to which event should be synced.,Selecione Google Agenda com o qual o evento deve ser sincronizado., +Select Google Contacts to which contact should be synced.,Selecione Contatos do Google aos quais o contato deve ser sincronizado., +Select Group By...,Selecione Agrupar por ..., +Select Mandatory,Selecione Obrigatório, +Select atleast 2 actions,Selecione pelo menos 2 ações, +Select list item,Selecione o item da lista, +Select multiple list items,Selecione vários itens da lista, +Send an email to {0} to link it here,Envie um email para {0} para vinculá-lo aqui, +Server Action,Ação do Servidor, +Server Script,Script de Servidor, +Session Default,Default da Sessão, +Session Default Settings,Configurações padrão da sessão, +Session Defaults,Padrões de Sessão, +Session Defaults Saved,Padrões de sessão salvos, +Set as Default Theme,Definir como tema padrão, +Setting up Global Search documents.,Configurando documentos de Pesquisa Global., +Show Document,Mostrar documento, +Show Failed Logs,Mostrar logs com falha, +Show Keyboard Shortcuts,Mostrar atalhos de teclado, +Show More Activity,Mostrar mais atividade, +Show Traceback,Mostrar Traceback, +Show Warnings,Mostrar avisos, +Showing only first {0} rows out of {1},Mostrando apenas {0} primeiras linhas de {1}, +"Simple Python Expression, Example: Status in (""Invalid"")","Expressão Python simples, exemplo: status em ("inválido")", +Skipping Untitled Column,Ignorando coluna sem título, +Skipping column {0},Ignorando a coluna {0}, +Social Home,Social Home, +Some columns might get cut off when printing to PDF. Try to keep number of columns under 10.,Algumas colunas podem ser cortadas ao imprimir em PDF. Tente manter o número de colunas abaixo de 10., +Something went wrong during the token generation. Click on {0} to generate a new one.,Algo deu errado durante a geração do token. Clique em {0} para gerar um novo., +Submit After Import,Enviar após importação, +Submitting...,Enviando ..., +Success! You are good to go 👍,Sucesso! Você é bom para ir 👍, +Successful Transactions,Transações bem-sucedidas, +Successfully Submitted!,Submetido com sucesso!, +Successfully imported {0} record.,Registro {0} importado com sucesso., +Successfully imported {0} records.,Registros {0} importados com sucesso., +Successfully updated {0} record.,Registro {0} atualizado com sucesso., +Successfully updated {0} records.,Registros {0} atualizados com sucesso., +Sync Calendar,Sincronizar Calendário, +Sync Contacts,Sincronizar contatos, +Sync with Google Calendar,Sincronize com o Google Agenda, +Sync with Google Contacts,Sincronizar com os contatos do Google, +Synced,Sincronizado, +Syncing,Sincronizando, +Syncing {0} of {1},Sincronizando {0} de {1}, +Tag Link,Tag Link, +Take Backup,Fazer backup, +Template Error,Erro de modelo, +Template Options,Opções de modelo, +Template Warnings,Avisos do modelo, +The Auto Repeat for this document has been disabled.,A repetição automática para este documento foi desativada., +The following records needs to be created before we can import your file.,Os seguintes registros precisam ser criados antes que possamos importar seu arquivo., +The mapping configuration between two doctypes.,A configuração de mapeamento entre dois doctypes., +The site which is consuming your events.,O site que está consumindo seus eventos., +The site you want to subscribe to for consuming events.,O site que você deseja assinar para consumir eventos., +The webhook will be triggered if this expression is true,O webhook será acionado se esta expressão for verdadeira, +The {0} is already on auto repeat {1},O {0} já está em repetição automática {1}, +There are some linked records which needs to be created before we can import your file. Do you want to create the following missing records automatically?,Existem alguns registros vinculados que precisam ser criados antes que possamos importar seu arquivo. Deseja criar os seguintes registros ausentes automaticamente?, +There should be atleast one row for the following tables: {0},Deve haver pelo menos uma linha para as seguintes tabelas: {0}, +There should be atleast one row for {0} table,Deve haver pelo menos uma linha para a tabela {0}, +This action is only allowed for {},Esta ação é permitida apenas para {}, +This cannot be undone,Isto não pode ser desfeito, +Time Format,Formato da hora, +Time series based on is required to create a dashboard chart,As séries cronológicas baseadas em são necessárias para criar um gráfico de dashboard, +Time {0} must be in format: {1},A hora {0} deve estar no formato: {1}, +"To configure Auto Repeat, enable ""Allow Auto Repeat"" from {0}.","Para configurar a repetição automática, ative "Permitir repetição automática" de {0}.", +To enable it follow the instructions in the following link: {0},"Para habilitá-lo, siga as instruções no seguinte link: {0}", +"To use Google Calendar, enable {0}.","Para usar o Google Agenda, ative {0}.", +"To use Google Contacts, enable {0}.","Para usar os Contatos do Google, ative {0}.", +"To use Google Drive, enable {0}.","Para usar o Google Drive, ative {0}.", +Today's Events,Eventos de hoje, +Toggle Public/Private,Alternar Público / Privado, +Tracks milestones on the lifecycle of a document if it undergoes multiple stages.,Rastreia marcos no ciclo de vida de um documento se ele passar por vários estágios., +Tree structures are implemented using Nested Set,As estruturas de árvore são implementadas usando o Conjunto Aninhado, +Trigger Primary Action,Ação principal do acionador, +URL for documentation or help,URL para documentação ou ajuda, +URL must start with 'http://' or 'https://',O URL deve começar com "http: //" ou "https: //", +Unchanged,Inalterado, +Unpin,Soltar, +Untitled Column,Coluna sem título, +Untranslated,Não traduzido, +Upcoming Events,próximos eventos, +Update Existing Records,Atualizar registros existentes, +Update Type,Tipo de atualização, +Updated To A New Version 🎉,Atualizado para uma nova versão 🎉, +"Updating {0} of {1}, {2}","Atualizando {0} de {1}, {2}", +Upload file,Subir arquivo, +Upload {0} files,Carregar {0} arquivos, +Uploaded To Google Drive,Carregado no Google Drive, +Uploaded successfully,Carregado com sucesso, +Uploading {0} of {1},Fazendo upload de {0} de {1}, +Use SSL for Outgoing,Use SSL para saída, +Use Same Name,Usar o mesmo nome, +Used For Google Maps Integration.,Usado para integração com o Google Maps., +User ID Property,Propriedade de ID do usuário, +User Profile,Perfil de Usuário, +User Settings,Configurações do Usuário, +User does not exist,Usuário não existe, +User {0} has requested for data deletion,O usuário {0} solicitou a exclusão de dados, +Users assigned to the reference document will get points.,Os usuários atribuídos ao documento de referência receberão pontos., +Value must be one of {0},O valor deve ser um dos {0}, +Value {0} missing for {1},Valor {0} ausente para {1}, +Verification,Verificação, +Verification Code,Código de verificação, +Verification code email not sent. Please contact Administrator.,E-mail do código de verificação não enviado. Entre em contato com o administrador., +Verified,Verificado, +Verifier,Verificador, +View Full Log,Visualizar log completo, +"View Log of all print, download and export events","Visualizar o log de todos os eventos de impressão, download e exportação", +Visit Web Page,Visitar página da Web, +Webhook Secret,Segredo do Webhook, +Webhook Security,Segurança Webhook, +Webhook Trigger,Gatilho Webhook, +Weekly Long,Semanalmente Longo, +"When enabled this will allow guests to upload files to your application, You can enable this if you wish to collect files from user without having them to log in, for example in job applications web form.","Quando ativado, isso permitirá que os convidados façam upload de arquivos para o seu aplicativo. Você pode habilitá-lo se desejar coletar arquivos do usuário sem que eles façam login, por exemplo, no formulário da Web de pedidos de emprego.", +Will run scheduled jobs only once a day for inactive sites. Default 4 days if set to 0.,"Executará trabalhos agendados apenas uma vez por dia para sites inativos. O padrão é 4 dias, se definido como 0.", +Workflow Status,Status do fluxo de trabalho, +You are not allowed to export {} doctype,Você não tem permissão para exportar {} doctype, +You can try changing the filters of your report.,Você pode tentar alterar os filtros do seu relatório., +You do not have permissions to cancel all linked documents.,Você não tem permissão para cancelar todos os documentos vinculados., +You need to create these first: ,Você precisa criar estes primeiro:, +You need to enable JavaScript for your app to work.,Você precisa habilitar o JavaScript para que seu aplicativo funcione., +You need to install pycups to use this feature!,Você precisa instalar pycups para usar este recurso!, +Your Target,Seu objetivo, +"browse,","Squeaky toy,", +cancelled this document {0},cancelou este documento {0}, +changed value of {0} {1},valor alterado de {0} {1}, +changed values for {0} {1},valores alterados para {0} {1}, +choose an,escolha um, +empty,vazio, +of,do, +or attach a,ou anexar um, +submitted this document {0},enviou este documento {0}, +"tag name..., e.g. #tag","nome da tag ..., por exemplo, #tag", +uploaded file,arquivo enviado, +via Data Import,via importação de dados, +{0} Google Calendar Events synced.,{0} Eventos do Google Agenda sincronizados., +{0} Google Contacts synced.,{0} Contatos do Google sincronizados., +{0} are mandatory fields,{0} são campos obrigatórios, +{0} are required,{0} são obrigatórios, +{0} assigned a new task {1} {2} to you,{0} atribuiu uma nova tarefa {1} {2} a você, +{0} gained {1} point for {2} {3},{0} ganhou {1} ponto por {2} {3}, +{0} gained {1} points for {2} {3},{0} ganhou {1} pontos por {2} {3}, +{0} has no versions tracked.,{0} não possui versões controladas., +{0} is not a valid report format. Report format should one of the following {1},{0} não é um formato de relatório válido. O formato do relatório deve ser um dos seguintes {1}, +{0} mentioned you in a comment in {1} {2},{0} fez referência a você em um comentário em {1} {2}, +{0} of {1} ({2} rows with children),{0} de {1} ({2} linhas com crianças), +{0} records will be exported,{0} registros serão exportados, +{0} shared a document {1} {2} with you,{0} compartilhou um documento {1} {2} com você, +{0} should not be same as {1},{0} não deve ser o mesmo que {1}, +{0} translations pending,{0} traduções pendentes, +{0} {1} is linked with the following submitted documents: {2},{0} {1} está vinculado aos seguintes documentos enviados: {2}, +"{0}: Failed to attach new recurring document. To enable attaching document in the auto repeat notification email, enable {1} in Print Settings","{0}: falha ao anexar novo documento recorrente. Para ativar o anexo de documento no e-mail de notificação de repetição automática, ative {1} em Configurações de impressão", +{0}: Fieldname cannot be one of {1},{0}: o nome do campo não pode ser um dos {1}, +{} Complete,{} Completo, +← Back to upload files,← Voltar para upload de arquivos, +Activity,Atividade, +Add / Manage Email Accounts.,Adicionar / Gerenciar Contas de Email., +Add Child,Adicionar Sub-item, +Add Multiple,Adicionar Múltiplos, +Add Participants,Adicione participantes, +Added {0} ({1}),Adicionado {0} ({1}), Address Line 1,Endereço, -Browse,Procurar, -Close,fechar, +Addresses,Endereços, +All,Todos, +Brand,Marca, +Browse,Pesquisar, +Cancelled,Cancelado, +Chart,Gráfico, +Close,Fechar, +Communication,Comunicação, Compact Item Print,Imprimir item no formato compacto, +Company,Empresa, +Complete,Concluído, +Completed,Concluído, +Continue,Continuar, +Country,País, +Creating {0},Criando {0}, +Currency,Moeda, +Customize,Personalizar, +Daily,Diário, +Date,Data, +Dear,Caro, +Default,Padrão, Delete,Excluir, +Description,Descrição, +Designation,Designação, +Disabled,Desativado, +Doctype,Doctype, Download Template,Baixar Modelo, -Email,Enviar e-mail, +Dr,Dr, +Due Date,Data de Vencimento, +Duplicate,Duplicar, +Edit Profile,Editar Perfil, +Email,Email, End Time,Horário de Término, Enter Value,Digite o Valor, -Export not allowed. You need {0} role to export.,Exportação não é permitido. Você precisa da função {0} para exportar., +Entity Type,Tipo de entidade, +Error,Erro, +Expired,Expirado, +Export,Exportar, +Export not allowed. You need {0} role to export.,Exportação não é permitida. Você precisa da função {0} para exportar., +Fetching...,Buscando ..., +Field,Campo, File Manager,Gestor de Arquivos, +Filters,Filtros, +Get Items,Obter Itens, Goal,Meta, +Group,Grupo, Group Node,Grupo de Nós, +Help,Ajuda, Help Article,Artigo de Ajuda, +Home,Início, +Import Data from CSV / Excel files.,Importar dados de arquivos CSV / Excel., +In Progress,Em progresso, +Intermediate,Intermediário, Invite as User,Convidar como Usuário, +"It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Parece que há um problema com a configuração de distribuição do servidor. Em caso de falha, o valor será reembolsado em sua conta.", Loading...,Carregando..., +Location,Localização, +Looks like someone sent you to an incomplete URL. Please ask them to look into it.,"Parece que alguém lhe enviou a um URL incompleta. Por favor, pedir-lhes para olhar para ele.", Master,Cadastro, -Missing Values Required,Faltando informações obrigatórias, +Message,mensagem, +Missing Values Required,Faltando valores obrigatórios, Mobile No,Telefone Celular, +Month,Mês, +Name,Nome, +Newsletter,Newsletter, +Not Allowed,Não Desejados, +Note,Nota, Offline,Offline, -Open,Aberto, +Open,Abrir, +Page {0} of {1},Página {0} de {1}, +Pay,Pagar, +Pending,Pendente, +Phone,Telefone, +Please click on the following link to set your new password,"Por favor, clique no link a seguir para definir a sua nova senha", +Please select another payment method. Stripe does not support transactions in currency '{0}',Selecione outro método de pagamento. Stripe não suporta transações em moeda '{0}', +Please specify,"Por favor, especifique", +Printing,Impressão, +Priority,Prioridade, +Project,Projeto, Quarterly,Trimestralmente, -Queued,Enfileiradas, +Queued,Em Fila, Quick Entry,Entrada Rápida, +Reason,Motivo, Refreshing,Atualizando, Rename,Renomear, -Reset,Restaurar, -Room,Sala, -Search results for,Pesquisar resultados para, +Reset,Redefinir, +Review,Reveja, +Room,Quarto, +Room Type,Tipo de Quarto, +Save,Salvar, +Search results for,Buscar resultados para, Select All,Selecionar Tudo, -Sending,Transmitindo, +Send,Enviar, +Sending,Enviando, Server Error,Erro de Servidor, Set,Definir, Setup,Configuração, +Setup Wizard,Assistente de Configuração, +Size,Tamanho, +Sr,Sr, Start,Iniciar, Start Time,Horário de Início, +Status,Status, +Submitted,Enviado, +Tag,Tag, +Template,Modelo, +Thursday,Quinta-feira, +Title,Título, +Total,Total, +Totals,Totais, +Tuesday,Terça-feira, +Type,Tipo, +Update,Atualizar, User {0} is disabled,Usuário {0} está desativado, Users and Permissions,Usuários e Permissões, +Warehouse,Armazém, +Welcome to {0},Bem-vindo ao {0}, +Year,Ano, +Yearly,Anual, +You,Você, +You can also copy-paste this link in your browser,Você também pode copiar e colar este link no seu navegador, +and,e, {0} Name,{0} Nome, +{0} is required,{0} é necessário, +ALL,Tudo, Attach File,Anexar Arquivo, -In,em, +Barcode,Código de barras, +Beginning with,Começando com, +Bold,Negrito, +CANCELLED,CANCELADO, +Calendar,Calendário, +Center,Centro, +Clear,claro, +Comment,Comente, +Comments,Comentários, +DRAFT,Rascunho, +Dashboard,Dashboard, +DocType,DocType, +Download,Baixar, +EMail,Email, +Edit in Full Page,Editar em página completa, +Email Inbox,Caixa de Entrada, +File,Arquivo, +Forward,Frente, +Icon,Ícone, +In,Em, +Inbox,Caixa de Entrada, +Insert New Records,Inserir novos registros, +JavaScript,Javascript, +LDAP Settings,Configurações LDAP, Left,Saiu, +Like,Parecido, +Link,Link, +Logged in,Logado, +New,Novo, Not Found,Não encontrado, Not Like,Não Parecido, +Notify by Email,Notificar por email, +Now,Agora, +Off,Desligado, +One of,Um dos, +Page,Página, +Print,Impressão, +Reference Name,Nome de referencia, Refresh,Atualizar, -Right,À direita, +Repeat,Repetir, +Right,Direita, Roles HTML,Funções HTML, +Scheduled To Send,Programado para enviar, +Search Results for ,Resultados da busca por, Send Notification To,Enviar Notificação para, +Success,Sucesso, Tags,Tags, +Time,Tempo, +Updated Successfully,Atualizado com sucesso, +Upload,Enviar, +User ,Usuário , +Value,Valor, +Web Link,Link da web, +Your Email Address,Seu endereço de email, Desktop,Área de trabalho, Usage Info,Informações de Uso, Download Backups,Download de Backups, +Recorder,Gravador, Role Permissions Manager,Gestor de Permissões por Função, +Translation Tool,Ferramenta de tradução, Awaiting password,Aguardando Senha, +Current status,Status atual, Download template,Baixar Modelo, Edit in full page,Editar em página completa, Email Id,Email ID, Email address,Endereço de Email, +Ends on,Termina em, +Half-yearly,Semestralmente, +Hidden,Escondido, +Javascript,Javascript, +Ldap settings,Configurações LDAP, +Mobile number,Telefone Celular, +Mx,Mx, +No,Não, +Not found,Não encontrado, +Notes:,Notas:, +Notify by email,Notificar por Email, Permitted Documents For User,Documentos Permitidos para Usuário, Reference Docname,Nome do Documento de Referência, +Reference Doctype,DocType de Referência, +Reference name,Nome de Referência, Roles Html,Funções HTML, +Row #,Linha #, +Scheduled to send,Programado para enviar, Select Doctype,Selecione o DocType, +Send Email for Successful backup,Enviar email para backup bem-sucedido, +Sign up,inscrever-se, +Time format,Formato da hora, +Upload failed,Upload falhou, User Id,ID de Usuário, +Yes,sim, +Your email address,Seu endereço de email, +added,adicionado, +added {0},Adicionado {0}, barcode,Código de barras, beginning with,Começando com, -clear,claro, -dashboard,Painel de controle, +blue,azul, +bold,negrito, +book,livro, +calendar,calendário, +certificate,certificado, +check,Verificar, +clear,limpar, +comment,Comentário, +comments,comentários, +created,Criado, +danger,Perigo, +dashboard,dashboard, download,Baixar, +edit,editar, email inbox,Caixa de Entrada, file,arquivo, +filter,filtro, +flag,bandeira, font,fonte, +forward,para a frente, +green,verde, +home,casa, +icon,ícone, +inbox,Caixa de Entrada, like,Parecido, +link,Link, +list,Lista, lock,trancar, logged in,Logado, +message,Mensagem, +module,módulo, +move,mover, +music,música, +new,Novo, +now,agora, off,fora, -one of,Um dos, +one of,um dos, +orange,laranja, +page,página, +print,imprimir, purple,roxo, -random,randômico, +random,aleatório, +red,vermelho, +refresh,atualizar, +remove,remover, +response,resposta, +search,procurar, +share,ação, stop,Parar, -tag,Tag, -tags,Tags, -tasks,Tarefas, +success,sucesso, +tag,tag, +tags,tags, +tasks,tarefas, +time,tempo, trash,lixo, -user,Usuário, -Verified By,Verificado por, -Lead Conversion Time,Tempo de Conversão do Lead, -Global Defaults,Padrões Globais, +upload,upload, +user,usuário, +value,valor, +web link,link da Web, +yellow,amarelo, +Not permitted,Não permitido, +Add Chart to Dashboard,Adicionar gráfico ao Dashboard, +Add to Dashboard,Adicionar ao Dashboard, +Google Translation,Tradução do Google, +Important,Importante, +No Filters Set,Nenhum conjunto de filtros, +No Records Created,Nenhum registro criado, +Please Set Chart,Defina o gráfico, +Please create chart first,Crie primeiro o gráfico, +"Report has no data, please modify the filters or change the Report Name",O relatório não possui dados. Modifique os filtros ou altere o Nome do relatório., +Select Dashboard,Selecionar Dashboard, +Y Field,Campo Y, +You need to be in developer mode to edit this document,Você precisa estar no modo de desenvolvedor para editar este documento, +Cards,Postais, +Community Contribution,Contribuição da comunidade, +Count Filter,Filtro de contagem, +Dashboard Chart Field,Campo do Gráfico do Dashboard, +Desk Card,Desk Card, +Desk Chart,Desk Chart, +Desk Page,Página da mesa, +Desk Shortcut,Atalho de mesa, +Developer Mode Only,Somente modo desenvolvedor, +Disable User Customization,Desativar personalização do usuário, +For example: {} Open,Por exemplo: {} Abra, +Link Cards,Cartões de ligação, +Link To,Link para, +Onboarding,Onboarding, +Percentage,Percentagem, +Pie,Torta, +Pin To Bottom,Fixar na parte inferior, +Pin To Top,Fixar na parte superior, +Restrict to Domain,Restringir ao domínio, +Shortcuts,Atalhos, +X Field,Campo X, +Y Axis,Eixo Y, +workspace,área de trabalho, +Setup > User,Configuração> Usuário, +Setup > Customize Form,Configuração> Personalizar formulário, +Setup > User Permissions,Configuração> Permissões do Usuário, +"Error connecting to QZ Tray Application...

    You need to have QZ Tray application installed and running, to use the Raw Print feature.

    Click here to Download and install QZ Tray.
    Click here to learn more about Raw Printing.","Erro ao conectar ao aplicativo da bandeja QZ ...

    Você precisa ter o aplicativo QZ Tray instalado e em execução, para usar o recurso Raw Print.

    Clique aqui para baixar e instalar a bandeja QZ .
    Clique aqui para saber mais sobre a impressão em bruto .", +No email account associated with the User. Please add an account under User > Email Inbox.,Nenhuma conta de email associada ao usuário. Adicione uma conta em Usuário> Caixa de entrada de email., +"For comparison, use >5, <10 or =324. For ranges, use 5:10 (for values between 5 & 10).","Para comparação, use> 5, <10 ou = 324. Para intervalos, use 5:10 (para valores entre 5 e 10).", +No default Address Template found. Please create a new one from Setup > Printing and Branding > Address Template.,Nenhum modelo de endereço padrão encontrado. Crie um novo em Configuração> Impressão e identidade visual> Modelo de endereço., +Please setup default Email Account from Setup > Email > Email Account,Configure a Conta de email padrão em Configuração> Email> Conta de email, +Email Account not setup. Please create a new Email Account from Setup > Email > Email Account,Conta de e-mail não configurada. Crie uma nova conta de email em Configuração> Email> Conta de email, +Attach file,Anexar Arquivo, +Contribution Status,Status de contribuição, +Contribution Document Name,Nome do documento de contribuição, +Extends,Estende, +Extends Another Page,Estende outra página, +Please select target language for translation,Selecione o idioma de destino para a tradução, +Select Language,Selecione o idioma, +Confirm Translations,Confirme as traduções, +Contributed Translations,Contribuições de traduções, +Show Tags,Mostrar Tags, +Do not have permission to access {0} bucket.,Não tem permissão para acessar o intervalo {0}., +Allow document creation via Email,Permitir a criação de documentos por e-mail, +Sender Field,Campo Remetente, +Logout All Sessions on Password Reset,Sair de todas as sessões ao redefinir a senha, +Logout From All Devices After Changing Password,Saia de todos os dispositivos após alterar a senha, +Send Notifications For Documents Followed By Me,Enviar notificações para documentos seguidos por mim, +Send Notifications For Email Threads,Enviar notificações para tópicos de email, +Bypass Restricted IP Address Check If Two Factor Auth Enabled,"Ignorar endereço IP restrito, verificar se a autenticação de dois fatores estiver habilitada", +Reset LDAP Password,Redefinir senha LDAP, +Confirm New Password,Confirme a nova senha, +Logout All Sessions,Sair de todas as sessões, +Passwords do not match!,As senhas não coincidem!, +Dashboard Manager,Dashboard Manager, +Dashboard Settings,Configurações do Dashboard, +Chart Configuration,Configuração de Gráfico, +No Permitted Charts on this Dashboard,Gráficos não permitidos neste Dashboard, +No Permitted Charts,Gráficos não permitidos, +Reset Chart,Reiniciar gráfico, +via {0},via {0}, +{0} is not a valid Phone Number,{0} não é um número de telefone válido, +Failed Transactions,Transações com falha, +Value for field {0} is too long in {1}. Length should be lesser than {2} characters,O valor do campo {0} é muito longo em {1}. O comprimento deve ser menor que {2} caracteres, +Data Too Long,Dados muito longos, +via Notification,via notificação, +Log in to access this page.,Faça login para acessar esta página., +Report Document Error,Reportar erro de documento, +{0} is an invalid Data field.,{0} é um campo de dados inválido., +Only Options allowed for Data field are:,Apenas as opções permitidas para o campo de dados são:, +Select a valid Subject field for creating documents from Email,Selecione um campo de Assunto válido para criar documentos de e-mail, +"Subject Field type should be Data, Text, Long Text, Small Text, Text Editor","O tipo de campo de assunto deve ser Dados, Texto, Texto Longo, Texto Pequeno, Editor de Texto", +Select a valid Sender Field for creating documents from Email,Selecione um campo de remetente válido para criar documentos de e-mail, +Sender Field should have Email in options,O campo do remetente deve ter e-mail nas opções, +Password changed successfully.,Senha alterada com sucesso., +Failed to change password.,Falha ao alterar a senha., +No Entry for the User {0} found within LDAP!,Nenhuma entrada para o usuário {0} encontrada no LDAP!, +No LDAP User found for email: {0},Nenhum usuário LDAP encontrado para e-mail: {0}, +Prepared Report User,Usuário de relatório preparado, +Scheduler Event,Evento Scheduler, +Select Event Type,Selecione o tipo de evento, +Schedule Script,Script de programação, +Duration,Duração, +Donut,Rosquinha, +Custom Options,Opções Personalizadas, +"Ex: ""colors"": [""#d1d8dd"", ""#ff5858""]","Ex: "cores": ["# d1d8dd", "# ff5858"]", +Confirmation Email Template,Modelo de email de confirmação, +Welcome Email Template,Modelo de email de boas-vindas, +Schedule Send,Agendar envio, +Do you really want to send this email newsletter?,Tem certeza de que deseja enviar este boletim informativo por e-mail?, +Advanced Settings,Configurações avançadas, +Disable Comments,Desativar comentários, +Comments on this blog post will be disabled if checked.,Os comentários nesta postagem do blog serão desabilitados se marcados., +CSS Class,Classe CSS, +Full Width,Largura completa, +Page Builder,Construtor de Página, +Page Building Blocks,Blocos de construção de página, +Header and Breadcrumbs,Cabeçalho e breadcrumbs, +Add Custom Tags,Adicionar tags personalizadas, +Web Page Block,Bloco de página da web, +Web Template,Web Template, +Edit Values,Editar Valores, +Web Template Values,Valores de modelo da web, +Add Container,Adicionar recipiente, +Web Page View,Visualização da página da web, +Path,Caminho, +Referrer,Referrer, +Browser,Navegador, +Browser Version,Versão do navegador, +Web Template Field,Campo de modelo da web, +Section,Seção, +Hide,ocultar, +Enable In App Website Tracking,Habilitar acompanhamento de sites no aplicativo, +Enable Google Indexing,Ativar indexação do Google, +"To use Google Indexing, enable Google Settings.","Para usar a indexação do Google, ative as configurações do Google .", +Authorize API Indexing Access,Autorizar acesso de indexação de API, +Indexing Refresh Token,Token de atualização de indexação, +Indexing Authorization Code,Código de autorização de indexação, +Theme Configuration,Configuração do Tema, +Font Properties,Propriedades da fonte, +Button Rounded Corners,Botão Cantos Arredondados, +Button Shadows,Sombras de botão, +Button Gradients,Gradientes de botão, +Light Color,Cor clara, +Stylesheet,Folha de estilo, +Custom SCSS,SCSS personalizado, +Navbar,Navbar, +Source Message,Mensagem Fonte, +Translated Message,Mensagem Traduzida, +Verified By,Verificado Por, +Using this console may allow attackers to impersonate you and steal your information. Do not enter or paste code that you do not understand.,O uso deste console pode permitir que invasores se façam passar por você e roubem suas informações. Não insira nem cole códigos que você não entende., +{0} m,{0} m, +{0} h,{0} h, +{0} d,{0} d, +{0} w,{0} w, +{0} M,{0} mi, +{0} y,{0} a, +yesterday,ontem, +{0} years ago,{0} anos atrás, +New Chart,Novo Gráfico, +New Shortcut,Novo Atalho, +Edit Chart,Editar gráfico, +Edit Shortcut,Editar atalho, +Couldn't Load Desk,Não foi possível carregar a mesa, +"Something went wrong while loading Desk. Please relaod the page. If the problem persists, contact the Administrator","Ocorreu um erro ao carregar o Desk. Por favor, relaod a página . Se o problema persistir, entre em contato com o Administrador", +Customize Workspace,Personalize o Espaço de Trabalho, +Customizations Saved Successfully,Personalizações salvas com sucesso, +Something went wrong while saving customizations,Algo deu errado ao salvar as personalizações, +{} Dashboard,{} Dashboard, +No changes in document,Sem alterações no documento, +by Role,por papel, +Document is only editable by users with role,O documento só pode ser editado por usuários com função, +{0}: Other permission rules may also apply,{0}: Outras regras de permissão também podem ser aplicadas, +{0} Page Views,{0} page views, +Expand,Expandir, +Collapse,Colapso, +"Invalid Bearer token, please provide a valid access token with prefix 'Bearer'.","Token de portador inválido, forneça um token de acesso válido com o prefixo 'Portador'.", +"Failed to decode token, please provide a valid base64-encoded token.","Falha ao decodificar o token, forneça um token codificado em base64 válido.", +"Invalid token, please provide a valid token with prefix 'Basic' or 'Token'.","Token inválido, forneça um token válido com o prefixo 'Básico' ou 'Token'.", +{0} is not a valid Name,{0} não é um nome válido, +Your system is being updated. Please refresh again after a few moments.,Seu sistema está sendo atualizado. Atualize novamente após alguns momentos., +{0} {1}: Submitted Record cannot be deleted. You must {2} Cancel {3} it first.,{0} {1}: O registro enviado não pode ser excluído. Você deve {2} cancelar {3} primeiro., +Invalid naming series (. missing) for {0},Série de nomenclatura inválida (. Ausente) para {0}, +Error has occurred in {0},Ocorreu um erro em {0}, +Status Updated,Status Atualizado, +You can also copy-paste this {0} to your browser,Você também pode copiar e colar isto {0} no seu navegador, +Enabled scheduled execution for script {0},Execução programada ativada para o script {0}, +Scheduled execution for script {0} has updated,A execução agendada para o script {0} foi atualizada, +The Link specified has either been used before or Invalid,O link especificado já foi usado antes ou é inválido, +Options for {0} must be set before setting the default value.,As opções para {0} devem ser definidas antes de definir o valor padrão., +Default value for {0} must be in the list of options.,O valor padrão para {0} deve estar na lista de opções., +Google Indexing has been configured.,A indexação do Google foi configurada., +Allow API Indexing Access,Permitir acesso de indexação de API, +Allow Google Indexing Access,Permitir acesso de indexação do Google, +Custom Documents,Documentos Personalizados, +Could not save customization,Não foi possível salvar a personalização, +Transgender,Transgênero, +Genderqueer,Genderqueer, +Non-Conforming,Não conforme, +Prefer not to say,Prefiro não dizer, +Is Billing Contact,É contato de cobrança, +Address And Contacts,Endereços e Contatos, +Lead Conversion Time,Lead Conversion Time, +Due Date Based On,Data de vencimento baseada em, +Phone Number,Número de telefone, +Linked Documents,Documentos vinculados, +Account SID,SID da conta, +Steps,Passos, +email,email, +Component,Componente, +Subtitle,Subtítulo, +Global Defaults,Padrões Gerais, +Prefix,Prefixo, +Is Public,É público, +This chart will be available to all Users if this is set,Este gráfico estará disponível para todos os usuários se estiver definido, +Number Card,Cartão de Número, +Function,Função, +Minimum,Mínimo, +Maximum,Máximo, +This card will be available to all Users if this is set,Este cartão estará disponível para todos os usuários se estiver definido, +Stats,Estatísticas, +Show Percentage Stats,Mostrar estatísticas percentuais, +Stats Time Interval,Intervalo de tempo das estatísticas, +Show percentage difference according to this time interval,Mostra a diferença percentual de acordo com este intervalo de tempo, +Filters Section,Seção de Filtros, +Number Card Link,Número do link do cartão, +Card,Cartão, +API Access,Acesso API, +Access Key Secret,Segredo da chave de acesso, +S3 Bucket Details,Detalhes do balde S3, +Bucket Name,Nome do intervalo, +Backup Details,Detalhes de backup, +Backup Files,Arquivos de backup, +Backup public and private files along with the database.,Faça backup de arquivos públicos e privados junto com o banco de dados., +Set to 0 for no limit on the number of backups taken,Defina como 0 para não haver limite no número de backups feitos, +Meta Description,Meta Descrição, +Meta Image,Meta Imagem, +Google Snippet Preview,Visualização de snippet do Google, +This is an example Google SERP Preview.,Este é um exemplo de visualização do Google SERP., +Add Gray Background,Adicionar fundo cinza, +Hide Block,Esconder o Bloco, +This Week,Esta semana, +This Month,Este mês, +This Quarter,Este Trimestre, +This Year,Este ano, +All Time,Tempo todo, +Select From Date,Selecione a partir da data, +since yesterday,desde ontem, +since last week,desde a semana passada, +since last month,desde o último mês, +since last year,desde o ano passado, +Show,mostrar, +New Number Card,Novo cartão de número, +Your Shortcuts,Seus Atalhos, +You haven't added any Dashboard Charts or Number Cards yet.,Você ainda não adicionou nenhum gráfico de Dashboard ou cartão numérico., +Click On Customize to add your first widget,Clique em Personalizar para adicionar seu primeiro widget, +Are you sure you want to reset all customizations?,Tem certeza de que deseja redefinir todas as personalizações?, +"Couldn't save, please check the data you have entered","Não foi possível salvar, verifique os dados inseridos", +Validation Error,erro de validação, +"You can only upload JPG, PNG, PDF, or Microsoft documents.","Você só pode fazer upload de documentos JPG, PNG, PDF ou Microsoft.", +Reverting length to {0} for '{1}' in '{2}'. Setting the length as {3} will cause truncation of data.,Revertendo comprimento para {0} para '{1}' em '{2}'. Definir o comprimento como {3} causará o truncamento dos dados., +'{0}' not allowed for type {1} in row {2},'{0}' não permitido para o tipo {1} na linha {2}, +Option {0} for field {1} is not a child table,A opção {0} para o campo {1} não é uma tabela filha, +Invalid Option,Opção Inválida, +Request Body consists of an invalid JSON structure,O corpo da solicitação consiste em uma estrutura JSON inválida, +Invalid JSON,JSON inválido, +Party GSTIN,Festa GSTIN, +GST State,Estado GST, +Andaman and Nicobar Islands,Ilhas Andaman e Nicobar, +Andhra Pradesh,Andhra Pradesh, +Arunachal Pradesh,Arunachal Pradesh, +Assam,Assam, +Bihar,Bihar, +Chandigarh,Chandigarh, +Chhattisgarh,Chhattisgarh, +Dadra and Nagar Haveli,Dadra e Nagar Haveli, +Daman and Diu,Damão e Diu, +Delhi,Délhi, +Goa,Goa, +Gujarat,Gujarat, +Haryana,Haryana, +Himachal Pradesh,Himachal Pradesh, +Jammu and Kashmir,Jammu e Kashmir, +Jharkhand,Jharkhand, +Karnataka,Karnataka, +Kerala,Kerala, +Lakshadweep Islands,Ilhas Lakshadweep, +Madhya Pradesh,Madhya Pradesh, +Maharashtra,Maharashtra, +Manipur,Manipur, +Meghalaya,Meghalaya, +Mizoram,Mizoram, +Nagaland,Nagaland, +Odisha,Odisha, +Other Territory,Outro Território, +Pondicherry,Pondicherry, +Punjab,Punjab, +Rajasthan,Rajasthan, +Sikkim,Sikkim, +Tamil Nadu,Tamil Nadu, +Telangana,Telangana, +Tripura,Tripura, +Uttar Pradesh,Uttar Pradesh, +Uttarakhand,Uttarakhand, +West Bengal,Bengala Ocidental, +GST State Number,Número do estado GST, +Import from Google Sheets,Importar do Planilhas Google, +Must be a publicly accessible Google Sheets URL,Deve ser um URL de planilhas do Google acessível publicamente, +Refresh Google Sheet,Atualizar planilha do Google, +Import File Errors and Warnings,Erros e avisos de importação de arquivos, +"Successfully imported {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.","Importou com êxito {0} registros de {1}. Clique em Exportar Errored Rows, corrija os erros e importe novamente.", +"Successfully imported {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.","Importado com sucesso {0} registro de {1}. Clique em Exportar Errored Rows, corrija os erros e importe novamente.", +"Successfully updated {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.","Atualizado com êxito {0} registros de {1}. Clique em Exportar Errored Rows, corrija os erros e importe novamente.", +"Successfully updated {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.","Atualizado com sucesso {0} registro de {1}. Clique em Exportar Errored Rows, corrija os erros e importe novamente.", +Data Import Legacy,Legado de importação de dados, +Documents restored successfully,Documentos restaurados com sucesso, +Documents that were already restored,Documentos que já foram restaurados, +Documents that failed to restore,Documentos que não foram restaurados, +Document Restoration Summary,Resumo de restauração de documento, +Hide Days,Ocultar dias, +Hide Seconds,Ocultar segundos, +Hide Border,Ocultar borda, +Index Web Pages for Search,Índice de páginas da web para pesquisa, +Action / Route,Ação / Rota, +Document Naming Rule,Regra de Nomenclatura de Documento, +Rule Conditions,Condições da regra, +Digits,Dígitos, +Example: 00001,Exemplo: 00001, +Counter,Contador, +Document Naming Rule Condition,Condição de regra de nomenclatura de documento, +Installed Application,Aplicativo Instalado, +Application Name,Nome da Aplicação, +Application Version,Versão do aplicativo, +Git Branch,Git Branch, +Installed Applications,Aplicativos Instalados, +Navbar Item,Item Navbar, +Item Label,Etiqueta do item, +Item Type,Tipo de item, +Separator,Separador, +Navbar Settings,Configurações da barra de navegação, +Application Logo,Logo do aplicativo, +Logo Width,Largura do logotipo, +Dropdowns,Dropdowns, +Settings Dropdown,Lista suspensa de configurações, +Help Dropdown,Ajuda suspensa, +Query / Script,Consulta / Script, +"Filters will be accessible via filters.

    Send output as result = [result], or for old style data = [columns], [result]","Os filtros estarão acessíveis por meio de filters .

    Envie a saída como result = [result] ou para data = [columns], [result] estilo antigo data = [columns], [result]", +Client Code,Código do cliente, +Report Column,Coluna de Relatório, +Report Filter,Filtro de Relatório, +Wildcard Filter,Filtro Wildcard, +Will add "%" before and after the query,Irá adicionar "%" antes e depois da consulta, +Route: Example "/desk",Rota: Exemplo "/ desk", +Enable Onboarding,Habilitar Onboarding, +Password Reset Link Generation Limit,Limite de geração de link de redefinição de senha, +Hourly rate limit for generating password reset links,Limite de taxa por hora para gerar links de redefinição de senha, +Send document Web View link in email,Enviar link no email para visualizar o documento online, +Enable Auto-deletion of Prepared Reports,Habilitar exclusão automática de relatórios preparados, +Prepared Report Expiry Period (Days),Período de expiração do relatório preparado (dias), +System will automatically delete Prepared Reports after these many days since creation,O sistema excluirá automaticamente os relatórios preparados após esses muitos dias desde a criação, +Package Document Type,Tipo de Documento de Pacote, +Include Attachments,Incluir Anexos, +Overwrite,Sobrescrever, +Package Publish Target,Alvo de publicação de pacote, +Site URL,URL do site, +Package Publish Tool,Ferramenta de publicação de pacotes, +Click on the row for accessing filters.,Clique na linha para acessar os filtros., +Sites,Sites, +Last Deployed On,Última implantação em, +Console Log,Log do console, +"Set Default Options for all charts on this Dashboard (Ex: ""colors"": [""#d1d8dd"", ""#ff5858""])","Defina as opções padrão para todos os gráficos neste Dashboard (Ex: "cores": ["# d1d8dd", "# ff5858"])", +Use Report Chart,Usar gráfico de relatório, +Heatmap,Mapa de calor, +Dynamic Filters,Filtros Dinâmicos, +Dynamic Filters JSON,Filtros dinâmicos JSON, +Set Dynamic Filters,Definir Filtros Dinâmicos, +Click to Set Dynamic Filters,Clique para definir filtros dinâmicos, +Hide Custom DocTypes and Reports,Ocultar tipos de documentos e relatórios personalizados, +Checking this will hide custom doctypes and reports cards in Links section,Marcar isto irá esconder doctypes personalizados e cartões de relatórios na seção Links, +DocType View,Visualização DocType, +Which view of the associated DocType should this shortcut take you to?,Para qual visualização do DocType associado esse atalho deve levar você?, +List View Settings,Configurações de visualização de lista, +Maximum Number of Fields,Número Máximo de Campos, +Module Onboarding,Módulo Onboarding, +System managers are allowed by default,Gerentes de sistema são permitidos por padrão, +Documentation URL,URL de documentação, +Is Complete,Está completo, +Alert,Alerta, +Document Link,Link do Documento, +Attached File,Arquivo anexo, +Attachment Link,Link de Anexo, +Open Reference Document,Documento de Referência Aberto, +Custom Configuration,Configuração Personalizada, +Filters Configuration,Configuração de Filtros, +Dynamic Filters Section,Seção de Filtros Dinâmicos, +Please create Card first,"Por favor, crie o cartão primeiro", +Onboarding Permission,Permissão de integração, +Onboarding Step,Etapa de integração, +Is Mandatory,É mandatório, +Is Skipped,É pulado, +Create Entry,Criar entrada, +Update Settings,Atualizar configurações, +Show Form Tour,Show Form Tour, +View Report,Ver relatório, +Go to Page,Vá para página, +Watch Video,Assistir vídeo, +Show Full Form?,Mostrar formulário completo?, +Show full form instead of a quick entry modal,Mostrar o formulário completo em vez de um modal de entrada rápida, +Report Reference Doctype,Report Reference Doctype, +Report Description,Descrição do relatório, +This will be shown to the user in a dialog after routing to the report,Isso será mostrado ao usuário em uma caixa de diálogo após o roteamento para o relatório, +Example: #Tree/Account,Exemplo: # árvore / conta, +Callback Title,Título de retorno, +Callback Message,Mensagem de retorno, +This will be shown in a modal after routing,Isso será mostrado em um modal após o roteamento, +Validate Field,Validar Campo, +Value to Validate,Valor para Validar, +Use % for any non empty value.,Use% para qualquer valor não vazio., +Video URL,URL do vídeo, +Onboarding Step Map,Mapa de etapas de integração, +Step,Degrau, +System Console,Console do sistema, +Console,Console, +To print output use log(text),"Para imprimir a saída, use o log(text)", +Commit,Comprometer, +Execute Console script,Executar script de console, +Execute,Executar, +Create Contacts from Incoming Emails,Criar contatos de e-mails recebidos, +Inbox User,Usuário da caixa de entrada, +Disabled Auto Reply,Resposta automática desativada, +Schedule Sending,Agendar Envio, +Message (Markdown),Mensagem (Markdown), +Message (HTML),Mensagem (HTML), +Send Attachments,Enviar anexos, +Testing,Testando, +System Notification,Notificação do sistema, +WhatsApp,Whatsapp, +Twilio Number,Número Twilio, +"To use WhatsApp for Business, initialize Twilio Settings.","Para usar o WhatsApp for Business, inicialize as configurações do Twilio .", +"To use Slack Channel, add a Slack Webhook URL.","Para usar o Slack Channel, adicione um URL do Slack Webhook .", +Send System Notification,Enviar Notificação do Sistema, +"If enabled, the notification will show up in the notifications dropdown on the top right corner of the navigation bar.","Se ativada, a notificação aparecerá na lista suspensa de notificações no canto superior direito da barra de navegação.", +Send To All Assignees,Enviar para todos os cessionários, +Receiver By Document Field,Receptor por campo de documento, +Receiver By Role,Receptor por função, +Child Table,Mesa Infantil, +Remote Value Filters,Filtros de valor remoto, +API Key of the user(Event Subscriber) on the producer site,Chave API do usuário (Assinante do Evento) no site do produtor, +API Secret of the user(Event Subscriber) on the producer site,Segredo API do usuário (Assinante do Evento) no site do produtor, +Paytm Settings,Configurações de Paytm, +Merchant Key,Chave do Comerciante, +Staging,Staging, +Industry Type ID,ID do tipo de indústria, +See https://docs.aws.amazon.com/general/latest/gr/s3.html for details.,Consulte https://docs.aws.amazon.com/general/latest/gr/s3.html para obter detalhes., +af-south-1,af-south-1, +ap-east-1,ap-east-1, +eu-south-1,eu-sul-1, +me-south-1,me-south-1, +Twilio Number Group,Grupo de números Twilio, +Twilio Settings,Configurações do Twilio, +Auth Token,Token de autenticação, +Read Time,Tempo de leitura, +in minutes,em minutos, +Featured,Destaque, +Hide CTA,Ocultar CTA, +"Description for listing page, in plain text, only a couple of lines. (max 200 characters)","Descrição da página de listagem, em texto simples, apenas algumas linhas. (máx. 200 caracteres)", +Meta Title,Meta Título, +Enable Social Sharing,Ativar compartilhamento social, +Show CTA in Blog,Mostrar CTA no blog, +CTA,CTA, +CTA Label,Etiqueta CTA, +CTA URL,URL CTA, +Default Portal Home,Página inicial do portal padrão, +Example: "/desk",Exemplo: "/ desk", +Social Link Settings,Configurações de link social, +Social Link Type,Tipo de Link Social, +facebook,Facebook, +linkedin,LinkedIn, +twitter,Twitter, +"If Icon is set, it will be shown instead of Label","Se o ícone estiver definido, ele será mostrado em vez do rótulo", +Apply Document Permissions,Aplicar permissões de documento, +For help see Client Script API and Examples,"Para obter ajuda, consulte Client Script API e exemplos", +Dynamic Route,Rota Dinâmica, +Map route parameters into form variables. Example /project/<name>,Mapeie os parâmetros da rota em variáveis de formulário. Exemplo /project/<name>, +Context Script,Script de Contexto, +"

    Set context before rendering a template. Example:

    \n

    \ncontext.project = frappe.get_doc(""Project"", frappe.form_dict.name)\n
    ","

    Defina o contexto antes de renderizar um modelo. Exemplo:

     context.project = frappe.get_doc("Project", frappe.form_dict.name)
    ", +Title of the page,Título da página, +This title will be used as the title of the webpage as well as in meta tags,"Este título será usado como o título da página da web, bem como nas metatags", +Makes the page public,Torna a página pública, +Checking this will publish the page on your website and it'll be visible to everyone.,Marcar isso publicará a página em seu site e ficará visível para todos., +URL of the page,URL da página, +"This will be automatically generated when you publish the page, you can also enter a route yourself if you wish","Isso será gerado automaticamente quando você publicar a página, você também pode inserir uma rota se desejar", +Content type for building the page,Tipo de conteúdo para construir a página, +"You can select one from the following,","Você pode selecionar um dos seguintes,", +Standard rich text editor with controls,Editor de rich text padrão com controles, +Github flavoured markdown syntax,Sintaxe de marcação com sabor de Github, +HTML with jinja support,HTML com suporte jinja, +Frappe page builder using components,Construtor de páginas Frappe usando componentes, +Checking this will show a text area where you can write custom javascript that will run on this page.,Marcar isto irá mostrar uma área de texto onde você pode escrever um javascript personalizado que será executado nesta página., +Meta title for SEO,Meta título para SEO, +"By default the title is used as meta title, adding a value here will override it.","Por padrão, o título é usado como meta título, adicionar um valor aqui irá substituí-lo.", +"The meta description is an HTML attribute that provides a brief summary of a web page. Search engines such as Google often display the meta description in search results, which can influence click-through rates.","A meta descrição é um atributo HTML que fornece um breve resumo de uma página da web. Mecanismos de pesquisa como o Google geralmente exibem a meta descrição nos resultados da pesquisa, o que pode influenciar as taxas de cliques.", +"The meta image is unique image representing the content of the page. Images for this Card should be at least 280px in width, and at least 150px in height.",A meta imagem é uma imagem única que representa o conteúdo da página. As imagens para este cartão devem ter pelo menos 280 px de largura e pelo menos 150 px de altura., +Add Space on Top,Adicionar espaço no topo, +Add Space on Bottom,Adicionar espaço na parte inferior, +Is Unique,É único, +User Agent,Agente de usuário, +Table Break,Pausa para a mesa, +Hide Login,Ocultar login, +Navbar Template,Modelo Navbar, +Navbar Template Values,Valores de modelo de Navbar, +Call To Action,Apelo à ação, +Call To Action URL,URL de apelo à ação, +Footer Logo,Logotipo do rodapé, +Footer Template,Modelo de rodapé, +Footer Template Values,Valores de modelo de rodapé, +Enable Tracking Page Views,Ativar rastreamento de visualizações de página, +"Checking this will enable tracking page views for blogs, web pages, etc.","Marcar isso permitirá o rastreamento de visualizações de páginas de blogs, páginas da web, etc.", +Disable Signup for your site,Desativar inscrição para seu site, +Check this if you don't want users to sign up for an account on your site. Users won't get desk access unless you explicitly provide it.,Marque esta opção se não quiser que os usuários se inscrevam em uma conta no seu site. Os usuários não terão acesso à mesa a menos que você o forneça explicitamente., +URL to go to on clicking the slideshow image,URL para acessar ao clicar na imagem da apresentação de slides, +Custom Overrides,Substituições personalizadas, +Ignored Apps,Aplicativos ignorados, +Include Theme from Apps,Incluir tema de aplicativos, +Website Theme Ignore App,Aplicativo para ignorar tema do site, +Are you sure you want to save this document?,Tem certeza que deseja salvar este documento?, +Refresh All,Atualize tudo, +"Level 0 is for document level permissions, higher levels for field level permissions.","O nível 0 é para permissões de nível de documento, níveis mais altos para permissões de nível de campo.", +Website Analytics,Análise do site, +d,d,Dias (Campo: Duração) +h,h,Horas (Campo: Duração) +m,m,Minutos (Campo: Duração) +s,s,Segundos (Campo: Duração) +Less,Menos, +Not a valid DocType view:,Não é uma visualização válida de DocType:, +Unknown View,Vista Desconhecida, +Go Back,Volte, +Let's take you back to onboarding,Vamos levá-lo de volta à integração, +Great Job,Bom trabalho, +Looks Great,Parece ótimo, +Looks like you didn't change the value,Parece que você não alterou o valor, +Oops,Opa, +Skip Step,Pular etapa, +"You're doing great, let's take you back to the onboarding page.","Você está indo muito bem, vamos levá-lo de volta à página de integração.", +Good Work 🎉,Bom trabalho 🎉, +Submit this document to complete this step.,Envie este documento para concluir esta etapa., +Great,Ótimo, +You may continue with onboarding,Você pode continuar com a integração, +You seem good to go!,Você parece bom para ir!, +Onboarding Complete,Integração completa, +{0} Settings,{0} Configurações, +{0} Fields,{0} campos, +Reset Fields,Limpar campos, +Select Fields,Selecione os campos, +Warning: Unable to find {0} in any table related to {1},Aviso: Não foi possível encontrar {0} em nenhuma tabela relacionada a {1}, +Tree view is not available for {0},A visualização em árvore não está disponível para {0}, +Create Card,Criar cartão, +Card Label,Etiqueta do cartão, +Reports already in Queue,Relatórios já na fila, +Proceed Anyway,Continue mesmo assim, +Delete and Generate New,Excluir e gerar novo, +1 Report,1 relatório, +{0} ({1}) (1 row mandatory),{0} ({1}) (1 linha obrigatória), +Select Fields To Insert,Selecione os campos para inserir, +Select Fields To Update,Selecione os campos para atualizar, +"This document is already amended, you cannot ammend it again","Este documento já foi alterado, você não pode alterá-lo novamente", +Add to ToDo,Adicionar ao ToDo, +{0} is currently {1},{0} atualmente é {1}, +{0} are currently {1},{0} são atualmente {1}, +Currently Replying,Atualmente respondendo, +created {0},criado em {0}, +Make a call,Faça uma ligação, +Change,Troco,Moedas +Too Many Requests,Muitos pedidos, +"Invalid Authorization headers, add a token with a prefix from one of the following: {0}.","Cabeçalhos de autorização inválidos, adicione um token com um prefixo de um dos seguintes: {0}.", +"Invalid Authorization Type {0}, must be one of {1}.","Tipo de autorização inválido {0}, deve ser um de {1}.", +{} is not a valid date string.,{} não é uma string de data válida., +Invalid Date,Data inválida, +Please select a valid date filter,Selecione um filtro de data válido, +Value {0} must be in the valid duration format: d h m s,O valor {0} deve estar no formato de duração válido: dhms, +Google Sheets URL is invalid or not publicly accessible.,O URL do Planilhas Google é inválido ou não está acessível publicamente., +Google Sheets URL must end with "gid={number}". Copy and paste the URL from the browser address bar and try again.,O URL do Planilhas Google deve terminar com "gid = {número}". Copie e cole o URL da barra de endereço do navegador e tente novamente., +Incorrect URL,URL incorreto, +"{0}" is not a valid Google Sheets URL,"{0}" não é um URL válido do Planilhas Google, +Duplicate Name,Nome duplicado, +Please check the value of "Fetch From" set for field {0},Verifique o valor de "Buscar de" definido para o campo {0}, +Wrong Fetch From value,Valor errado de busca, +A field with the name '{}' already exists in doctype {}.,Já existe um campo com o nome '{}' em doctype {}., +Custom Field {0} is created by the Administrator and can only be deleted through the Administrator account.,O campo personalizado {0} é criado pelo administrador e só pode ser excluído por meio da conta do administrador., +Failed to send {0} Auto Email Report,Falha ao enviar {0} relatório de e-mail automático, +Test email sent to {0},Email de teste enviado para {0}, +Email queued to {0} recipients,Email na fila para {0} destinatários, +Newsletter should have at least one recipient,O boletim deve ter pelo menos um destinatário, +Please enable Twilio settings to send WhatsApp messages,Ative as configurações do Twilio para enviar mensagens do WhatsApp, +"Not allowed to attach {0} document, please enable Allow Print For {0} in Print Settings","Não tem permissão para anexar documento {0}, ative Permitir impressão para {0} nas configurações de impressão", +Signup Disabled,Inscrição Desativada, +Signups have been disabled for this website.,As inscrições foram desativadas para este site., +Open Document,Documento Aberto, +The comment cannot be empty,O comentário não pode estar vazio, +Hourly comment limit reached for: {0},Limite de comentários por hora atingido para: {0}, +Please add a valid comment.,"Por favor, adicione um comentário válido.", +Document {0} Already Restored,Documento {0} já restaurado, +Restoring Deleted Document,Restaurando Documento Excluído, +{function} of {fieldlabel},{função} de {fieldlabel}, +Invalid template file for import,Arquivo de modelo inválido para importação, +Invalid or corrupted content for import,Conteúdo inválido ou corrompido para importação, +Value {0} must in {1} format,O valor {0} deve estar no formato {1}, +{0} is a mandatory field asdadsf,{0} é um campo obrigatório asdadsf, +Could not map column {0} to field {1},Não foi possível mapear a coluna {0} para o campo {1}, +Skipping Duplicate Column {0},Ignorando coluna duplicada {0}, +The column {0} has {1} different date formats. Automatically setting {2} as the default format as it is the most common. Please change other values in this column to this format.,"A coluna {0} possui {1} formatos de data diferentes. Definindo automaticamente {2} como o formato padrão, pois é o mais comum. Por favor, altere outros valores nesta coluna para este formato.", +You have reached the hourly limit for generating password reset links. Please try again later.,"Você atingiu o limite de hora para gerar links de redefinição de senha. Por favor, tente novamente mais tarde.", +Please hide the standard navbar items instead of deleting them,Oculte os itens padrão da barra de navegação em vez de excluí-los, +DocType's name should not start or end with whitespace,O nome de DocType não deve começar ou terminar com um espaço em branco, +File name cannot have {0},O nome do arquivo não pode ter {0}, +{0} is not a valid file url,{0} não é um url de arquivo válido, +Error Attaching File,Erro ao anexar arquivo, +Please generate keys for the Event Subscriber User {0} first.,Gere as chaves para o Usuário Assinante do Evento {0} primeiro., +Please set API Key and Secret on the producer and consumer sites first.,Defina a chave e o segredo da API nos sites do produtor e do consumidor primeiro., +User {0} not found on the producer site,Usuário {0} não encontrado no site do produtor, +Event Subscriber has to be a System Manager.,O Assinante do Evento deve ser um Gerente do Sistema., +Row #{0}: Invalid Local Fieldname,Linha # {0}: Nome de campo local inválido, +Row #{0}: Please set Mapping or Default Value for the field {1} since its a dependency field,"Linha nº {0}: Defina o mapeamento ou valor padrão para o campo {1}, pois é um campo de dependência", +Row #{0}: Please set remote value filters for the field {1} to fetch the unique remote dependency document,Linha nº {0}: Defina filtros de valor remoto para o campo {1} para buscar o documento de dependência remota exclusivo, +Paytm payment gateway settings,Configurações de gateway de pagamento Paytm, +"Company, Fiscal Year and Currency defaults","Padrões da empresa, ano fiscal e moeda", +Razorpay Signature Verification Failed,Falha na verificação da assinatura Razorpay, +Google Drive - Could not locate - {0},Google Drive - Não foi possível localizar - {0}, +"Sync token was invalid and has been resetted, Retry syncing.",O token de sincronização era inválido e foi redefinido. Tente sincronizar novamente., +Please select another payment method. Paytm does not support transactions in currency '{0}',Selecione outro método de pagamento. Paytm não suporta transações na moeda '{0}', +Invalid Account SID or Auth Token.,SID de conta ou token de autenticação inválido., +Please enable twilio settings before sending WhatsApp messages,Ative as configurações do twilio antes de enviar mensagens do WhatsApp, +Delivery Failed,Falha na entrega, +Twilio WhatsApp Message Error,Twilio WhatsApp Message Error, +A featured post must have a cover image,Uma postagem em destaque deve ter uma imagem de capa, +Load More,Carregue mais, +Published on,Publicado em, +Enable developer mode to create a standard Web Template,Habilite o modo de desenvolvedor para criar um modelo da Web padrão, +Was this article helpful?,Esse artigo foi útil?, +Thank you for your feedback!,Obrigado pelo seu feedback!, +New Mention on {0},Nova menção em {0}, +Assignment Update on {0},Atualização de atribuição em {0}, +New Document Shared {0},Novo documento compartilhado {0}, +Energy Point Update on {0},Atualização do Energy Point em {0}, +You cannot create a dashboard chart from single DocTypes,Você não pode criar um gráfico de Dashboard de DocTypes únicos, +Invalid json added in the custom options: {0},JSON inválido adicionado nas opções personalizadas: {0}, +Invalid JSON in card links for {0},JSON inválido em links de cartão para {0}, +Standard Not Set,Padrão não definido, +Please set the following documents in this Dashboard as standard first.,Defina os seguintes documentos neste Dashboard como padrão primeiro., +Shared with the following Users with Read access:{0},Compartilhado com os seguintes usuários com acesso de leitura: {0}, +Already in the following Users ToDo list:{0},Já está na seguinte lista de tarefas de usuários: {0}, +Your assignment on {0} {1} has been removed by {2},Sua tarefa em {0} {1} foi removida por {2}, +Invalid Credentials,Credenciais inválidas, +Print UOM after Quantity,Imprimir UOM após a quantidade, +Uncaught Server Exception,Exceção de servidor não detectado, +There was an error building this page,Ocorreu um erro ao construir esta página, +Hide Traceback,Esconder Traceback, +Value from this field will be set as the due date in the ToDo,O valor deste campo será definido como a data de vencimento no ToDo, +New module created {0},Novo módulo criado em {0}, +"Report has no numeric fields, please change the Report Name","O relatório não tem campos numéricos, altere o nome do relatório", +There are documents which have workflow states that do not exist in this Workflow. It is recommended that you add these states to the Workflow and change their states before removing these states.,Existem documentos com estados de fluxo de trabalho que não existem neste fluxo de trabalho. É recomendável adicionar esses estados ao fluxo de trabalho e alterar seus estados antes de removê-los., +Worflow States Don't Exist,Estados de Worflow não existem, +Save Anyway,Salvar assim mesmo, +Energy Points:,Pontos de energia:, +Review Points:,Pontos de revisão:, +Rank:,Classificação:, +Monthly Rank:,Classificação Mensal:, +Invalid expression set in filter {0} ({1}),Expressão inválida definida no filtro {0} ({1}), +Invalid expression set in filter {0},Expressão inválida definida no filtro {0}, +{0} {1} added to Dashboard {2},{0} {1} adicionado ao Dashboard {2}, +Set Filters for {0},Definir filtros para {0}, +Not permitted to view {0},Não tem permissão para ver {0}, +Camera,câmera, +Invalid filter: {0},Filtro inválido: {0}, +Let's Get Started,Vamos começar, +Reports & Masters,Relatórios e Cadastros, +New {0} {1} added to Dashboard {2},Novo {0} {1} adicionado ao Dashboard {2}, +New {0} {1} created,Novo {0} {1} criado, +New {0} Created,Novo {0} criado, +Invalid "depends_on" expression set in filter {0},Expressão "depends_on" inválida definida no filtro {0}, +{0} Reports,{0} relatórios, +There is {0} with the same filters already in the queue:,Há {0} com os mesmos filtros já na fila:, +There are {0} with the same filters already in the queue:,Existem {0} com os mesmos filtros já na fila:, +Are you sure you want to generate a new report?,Tem certeza de que deseja gerar um novo relatório?, +{0}: {1} vs {2},{0}: {1} vs {2}, +Add a {0} Chart,Adicionar um {0} gráfico, +Currently you have {0} review points,Atualmente você tem {0} pontos de revisão, +{0} is not a valid DocType for Dynamic Link,{0} não é um DocType válido para Dynamic Link, +via Assignment Rule,via regra de atribuição, +Based on Field,Com base no campo, +Assign to the user set in this field,Atribuir ao usuário definido neste campo, +Log Setting User,Usuário de configuração de log, +Log Settings,Configurações de registro, +Error Log Notification,Notificação de log de erros, +Users To Notify,Usuários para notificar, +Log Cleanup,Limpeza de Log, +Clear Error log After,Limpar log de erros após, +Clear Activity Log After,Limpar log de atividades depois, +Clear Email Queue After,Limpar fila de e-mail após, +Please save to edit the template.,Salve para editar o modelo., +Google Analytics Anonymize IP,IP anônimo do Google Analytics, +Incorrect email or password. Please check your login credentials.,Senha ou email incorretos. Verifique suas credenciais de login., +Incorrect Configuration,Configuração Incorreta, +You are not allowed to delete Standard Report,Você não tem permissão para excluir o relatório padrão, +You have unseen {0},Você não viu {0}, +Log cleanup and notification configuration,Limpeza de registro e configuração de notificação, +State/Province,Estado / Província, +Document Actions,Ações do Documento, +Document Links,Links de documentos, +List Settings,Configurações da lista, +Cannot delete standard link. You can hide it if you want,Não é possível excluir o link padrão. Você pode esconder se quiser, +Cannot delete standard action. You can hide it if you want,Não é possível excluir a ação padrão. Você pode esconder se quiser, +Applied On,Aplicado em, +Row Name,Nome da Linha, +For DocType Link / DocType Action,Para DocType Link / DocType Action, +Cannot edit filters for standard charts,Não é possível editar filtros para gráficos padrão, +Event Producer Last Update,Última atualização do produtor de eventos, +Default for 'Check' type of field {0} must be either '0' or '1',Padrão para 'Verificar' o tipo de campo {0} deve ser '0' ou '1', +Non Negative,Não Negativo, +Rules with higher priority number will be applied first.,Regras com número de prioridade mais alta serão aplicadas primeiro., +Open URL in a New Tab,Abrir URL em uma nova guia, +Align Right,Alinhar à direita, +Loading Filters...,Carregando filtros ..., +Count Customizations,Personalizações de contagem, +For Example: {} Open,Por exemplo: {} aberto, +Choose Existing Card or create New Card,Escolha o cartão existente ou crie um novo cartão, +Number Cards,Cartões numéricos, +Function Based On,Função baseada em, +Add Filters,Adicionar Filtros, +Skip,Pular, +Dismiss,Dispensar, +Value cannot be negative for,O valor não pode ser negativo para, +Value cannot be negative for {0}: {1},O valor não pode ser negativo para {0}: {1}, +Negative Value,Valor Negativo, +Authentication failed while receiving emails from Email Account: {0}.,Falha na autenticação ao receber e-mails da conta de e-mail: {0}., +Message from server: {0},Mensagem do servidor: {0}, From f89dc40b94e30e3a00b1c54434df2f3a05d4c610 Mon Sep 17 00:00:00 2001 From: Shariq Ansari <30859809+shariquerik@users.noreply.github.com> Date: Mon, 27 Jun 2022 14:46:06 +0530 Subject: [PATCH 050/101] fix: Allow permitted number card of type report (#17316) --- frappe/desk/doctype/number_card/number_card.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/frappe/desk/doctype/number_card/number_card.py b/frappe/desk/doctype/number_card/number_card.py index 2290e49656..74c8e9eb99 100644 --- a/frappe/desk/doctype/number_card/number_card.py +++ b/frappe/desk/doctype/number_card/number_card.py @@ -4,6 +4,7 @@ import frappe from frappe import _ +from frappe.boot import get_allowed_reports from frappe.config import get_modules_from_all_apps_for_user from frappe.model.document import Document from frappe.model.naming import append_number_if_name_exists @@ -90,9 +91,16 @@ def has_permission(doc, ptype, user): if "System Manager" in roles: return True - allowed_doctypes = tuple(frappe.permissions.get_doctypes_with_read()) - if doc.document_type in allowed_doctypes: - return True + if doc.type == "Report": + allowed_reports = [ + key if type(key) == str else key.encode("UTF8") for key in get_allowed_reports() + ] + if doc.report_name in allowed_reports: + return True + else: + allowed_doctypes = tuple(frappe.permissions.get_doctypes_with_read()) + if doc.document_type in allowed_doctypes: + return True return False From 084a1e6c31520de09d639dbb5db129fb7e757d4b Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Mon, 27 Jun 2022 15:18:06 +0530 Subject: [PATCH 051/101] refactor: get_permissions * Show page even if dangling Custom DocPerm records encountered * Add typing hints * Cleanup APIs --- .../permission_manager/permission_manager.py | 25 +++++++++++++------ frappe/permissions.py | 23 ++++++++--------- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/frappe/core/page/permission_manager/permission_manager.py b/frappe/core/page/permission_manager/permission_manager.py index ad12e0fd4c..e2d08488c0 100644 --- a/frappe/core/page/permission_manager/permission_manager.py +++ b/frappe/core/page/permission_manager/permission_manager.py @@ -1,6 +1,8 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE +from typing import Optional + import frappe import frappe.defaults from frappe import _ @@ -8,6 +10,7 @@ from frappe.core.doctype.doctype.doctype import ( clear_permissions_cache, validate_permissions_for_doctype, ) +from frappe.exceptions import DoesNotExistError from frappe.modules.import_file import get_file_path, read_doc_from_file from frappe.permissions import ( add_permission, @@ -68,17 +71,19 @@ def get_roles_and_doctypes(): @frappe.whitelist() -def get_permissions(doctype=None, role=None): +def get_permissions(doctype: Optional[str] = None, role: Optional[str] = None): frappe.only_for("System Manager") + if role: out = get_all_perms(role) if doctype: out = [p for p in out if p.parent == doctype] + else: - filters = dict(parent=doctype) + filters = {"parent": doctype} if frappe.session.user != "Administrator": - custom_roles = frappe.get_all("Role", filters={"is_custom": 1}) - filters["role"] = ["not in", [row.name for row in custom_roles]] + custom_roles = frappe.get_all("Role", filters={"is_custom": 1}, pluck="name") + filters["role"] = ["not in", custom_roles] out = frappe.get_all("Custom DocPerm", fields="*", filters=filters, order_by="permlevel") if not out: @@ -86,11 +91,15 @@ def get_permissions(doctype=None, role=None): linked_doctypes = {} for d in out: - if not d.parent in linked_doctypes: - linked_doctypes[d.parent] = get_linked_doctypes(d.parent) + if d.parent not in linked_doctypes: + try: + linked_doctypes[d.parent] = get_linked_doctypes(d.parent) + except DoesNotExistError: + # exclude & continue if linked doctype is not found + frappe.clear_last_message() + continue d.linked_doctypes = linked_doctypes[d.parent] - meta = frappe.get_meta(d.parent) - if meta: + if meta := frappe.get_meta(d.parent): d.is_submittable = meta.is_submittable d.in_create = meta.in_create diff --git a/frappe/permissions.py b/frappe/permissions.py index 8980d2e63e..55a7c0e5f3 100644 --- a/frappe/permissions.py +++ b/frappe/permissions.py @@ -1,6 +1,7 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE import copy +from typing import List import frappe import frappe.share @@ -605,19 +606,17 @@ def reset_perms(doctype): frappe.db.delete("Custom DocPerm", {"parent": doctype}) -def get_linked_doctypes(dt): - return list( - set( - [dt] - + [ - d.options - for d in frappe.get_meta(dt).get( - "fields", - {"fieldtype": "Link", "ignore_user_permissions": ("!=", 1), "options": ("!=", "[Select]")}, - ) - ] +def get_linked_doctypes(dt: str) -> List: + meta = frappe.get_meta(dt) + linked_doctypes = [dt] + [ + d.options + for d in meta.get( + "fields", + {"fieldtype": "Link", "ignore_user_permissions": ("!=", 1), "options": ("!=", "[Select]")}, ) - ) + ] + + return list(set(linked_doctypes)) def get_doc_name(doc): From fba75c35951982631322a17b3af1778ed2d129aa Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 27 Jun 2022 15:55:54 +0530 Subject: [PATCH 052/101] fix: use console.error for logging errors (#17318) Currently if uncaught exception occurs on server side, there's no simple way to find it out. Converting these console.log to console.error simplifies this for UI tests. Also converted `console.trace to` `console.error`; Both are practically same and give stack trace too, `trace` expands tracebacks by default. This is done to make spying on window.console.error easier. --- frappe/public/js/frappe/request.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/frappe/public/js/frappe/request.js b/frappe/public/js/frappe/request.js index 87ab06ce18..dd4c352f41 100644 --- a/frappe/public/js/frappe/request.js +++ b/frappe/public/js/frappe/request.js @@ -280,7 +280,7 @@ frappe.request.call = function(opts) { } } catch(e) { console.log("Unable to handle success response", data); // eslint-disable-line - console.trace(e); // eslint-disable-line + console.error(e); // eslint-disable-line } }) @@ -332,7 +332,7 @@ frappe.request.call = function(opts) { opts.error_callback && opts.error_callback(xhr); } catch(e) { console.log("Unable to handle failed response"); // eslint-disable-line - console.trace(e); // eslint-disable-line + console.error(e); // eslint-disable-line } }); } @@ -433,13 +433,13 @@ frappe.request.cleanup = function(opts, r) { if(r.exc) { r.exc = JSON.parse(r.exc); if(r.exc instanceof Array) { - $.each(r.exc, function(i, v) { - if(v) { - console.log(v); + r.exc.forEach(exc => { + if(exc) { + console.error(exc); } - }) + }); } else { - console.log(r.exc); + console.error(r.exc); } } From 112f11359847cd286752177b42a357d4b6910cc3 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 27 Jun 2022 17:04:34 +0530 Subject: [PATCH 053/101] fix!: remove dangerous "rollback_on_exception" flag (#17321) --- frappe/__init__.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index ee199c8aed..9104cd5109 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -432,9 +432,6 @@ def msgprint( def _raise_exception(): if raise_exception: - if flags.rollback_on_exception: - db.rollback() - if inspect.isclass(raise_exception) and issubclass(raise_exception, Exception): raise raise_exception(msg) else: From b7514a05ca9039bf9336ece3938b69bdeecb6585 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Tue, 28 Jun 2022 00:37:31 +0530 Subject: [PATCH 054/101] fix(redis): pass shared param when setting value based on generator --- frappe/utils/redis_wrapper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/utils/redis_wrapper.py b/frappe/utils/redis_wrapper.py index 178c3d4416..c29836af32 100644 --- a/frappe/utils/redis_wrapper.py +++ b/frappe/utils/redis_wrapper.py @@ -199,7 +199,7 @@ class RedisWrapper(redis.Redis): frappe.local.cache[_name][key] = value elif generator: value = generator() - self.hset(name, key, value) + self.hset(name, key, value, shared=shared) return value def hdel(self, name, key, shared=False): From 5604b090c0b2e891a19d1b122ea2e30ff23b543d Mon Sep 17 00:00:00 2001 From: Samuel Danieli <23150094+scdanieli@users.noreply.github.com> Date: Mon, 27 Jun 2022 22:15:23 +0200 Subject: [PATCH 055/101] feat: enable further translations --- frappe/public/js/frappe/ui/sort_selector.html | 2 +- frappe/public/js/frappe/ui/sort_selector.js | 2 +- frappe/public/js/frappe/ui/toolbar/toolbar.js | 2 +- frappe/public/js/frappe/utils/dashboard_utils.js | 4 +++- frappe/public/js/frappe/views/kanban/kanban_column.html | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/frappe/public/js/frappe/ui/sort_selector.html b/frappe/public/js/frappe/ui/sort_selector.html index 6f79f986a1..4e1945c46c 100644 --- a/frappe/public/js/frappe/ui/sort_selector.html +++ b/frappe/public/js/frappe/ui/sort_selector.html @@ -2,7 +2,7 @@
    `; @@ -24,10 +24,12 @@ frappe.dashboard_utils = { if (filter.fieldnames) { options_html = filter.options.map((option, i) => + // TODO: Make option translatable - be careful, since the text of the a tag is later used to perform some action `
  • ${option}
  • `).join(''); } else { + // TODO: Make option translatable - be careful, since the text of the a tag is later used to perform some action options_html = filter.options.map( option => `
  • ${option}
  • `).join(''); } diff --git a/frappe/public/js/frappe/views/kanban/kanban_column.html b/frappe/public/js/frappe/views/kanban/kanban_column.html index 9c9f1eede0..5e6b6e1e7b 100644 --- a/frappe/public/js/frappe/views/kanban/kanban_column.html +++ b/frappe/public/js/frappe/views/kanban/kanban_column.html @@ -17,7 +17,7 @@
    - + {{ __("Add " + doctype) }} + + {{ __("Add {0}", [__(doctype)]) }}
    From 3263bf8324d645e57b93289d29ca1795a11247ce Mon Sep 17 00:00:00 2001 From: Samuel Danieli <23150094+scdanieli@users.noreply.github.com> Date: Mon, 27 Jun 2022 22:19:05 +0200 Subject: [PATCH 056/101] style: indent --- frappe/public/js/frappe/views/kanban/kanban_column.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/views/kanban/kanban_column.html b/frappe/public/js/frappe/views/kanban/kanban_column.html index 5e6b6e1e7b..8606cdc69d 100644 --- a/frappe/public/js/frappe/views/kanban/kanban_column.html +++ b/frappe/public/js/frappe/views/kanban/kanban_column.html @@ -17,7 +17,7 @@
    - + {{ __("Add {0}", [__(doctype)]) }} + + {{ __("Add {0}", [__(doctype)]) }}
    From 19a13931525b15427f34836e0e922e952de7c7b7 Mon Sep 17 00:00:00 2001 From: Samuel Danieli <23150094+scdanieli@users.noreply.github.com> Date: Mon, 27 Jun 2022 23:32:55 +0200 Subject: [PATCH 057/101] feat: make field label translatable --- .../print_format_builder_column_selector.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/printing/page/print_format_builder/print_format_builder_column_selector.html b/frappe/printing/page/print_format_builder/print_format_builder_column_selector.html index 5292531e4c..495b837f48 100644 --- a/frappe/printing/page/print_format_builder/print_format_builder_column_selector.html +++ b/frappe/printing/page/print_format_builder/print_format_builder_column_selector.html @@ -20,7 +20,7 @@ - {{ f.label }} + {{ __(f.label) }}

    From c6fa8ab090fdc0d07dbd295b5a262ed2a5acf456 Mon Sep 17 00:00:00 2001 From: Shariq Ansari <30859809+shariquerik@users.noreply.github.com> Date: Tue, 28 Jun 2022 11:50:57 +0530 Subject: [PATCH 058/101] fix: email not sent if contain file with current site url (#17250) --- frappe/core/doctype/file/file.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/frappe/core/doctype/file/file.py b/frappe/core/doctype/file/file.py index e8b8da76ab..bb4b441680 100755 --- a/frappe/core/doctype/file/file.py +++ b/frappe/core/doctype/file/file.py @@ -16,7 +16,7 @@ from requests.exceptions import HTTPError, SSLError import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import call_hook_method, cint, get_files_path, get_hook_method +from frappe.utils import call_hook_method, cint, get_files_path, get_hook_method, get_url from frappe.utils.file_manager import is_safe_path from frappe.utils.image import optimize_image, strip_exif_data @@ -61,7 +61,12 @@ class File(Document): self.set_file_name() self.validate_attachment_limit() - if not self.is_folder and not self.is_remote_file: + if self.is_folder: + return + + if self.is_remote_file: + self.validate_remote_file() + else: self.save_file(content=self.get_content()) self.flags.new_file = True frappe.local.rollback_observers.append(self) @@ -255,6 +260,12 @@ class File(Document): title=_("Attachment Limit Reached"), ) + def validate_remote_file(self): + """Validates if file uploaded using URL already exist""" + site_url = get_url() + if "/files/" in self.file_url and self.file_url.startswith(site_url): + self.file_url = self.file_url.split(site_url, 1)[1] + def set_folder_name(self): """Make parent folders if not exists based on reference doctype and name""" if self.folder: @@ -445,6 +456,10 @@ class File(Document): file_path = self.file_url or self.file_name + site_url = get_url() + if "/files/" in file_path and file_path.startswith(site_url): + file_path = file_path.split(site_url, 1)[1] + if "/" not in file_path: if self.is_private: file_path = f"/private/files/{file_path}" From 9bd753551b6af9cb25a445526969f563bb738e5a Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 28 Jun 2022 12:07:34 +0530 Subject: [PATCH 059/101] ci: temp fix for semgrep (#17228) * ci: respekt my authoritah * ci: use pip semgrep --- .github/helper/roulette.py | 8 ++++---- .github/workflows/linters.yml | 16 +++++++--------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/.github/helper/roulette.py b/.github/helper/roulette.py index 9165198012..b859b87047 100644 --- a/.github/helper/roulette.py +++ b/.github/helper/roulette.py @@ -77,13 +77,13 @@ if __name__ == "__main__": updated_py_file_count = len(list(filter(is_py, files_list))) only_py_changed = updated_py_file_count == len(files_list) - if ci_files_changed: - print("CI related files were updated, running all build processes.") - - elif has_skip_ci_label(pr_number, repo): + if has_skip_ci_label(pr_number, repo): print("Found `Skip CI` label on pr, stopping build process.") sys.exit(0) + elif ci_files_changed: + print("CI related files were updated, running all build processes.") + elif only_docs_changed: print("Only docs were updated, stopping build process.") sys.exit(0) diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index 4c845dba8c..6d1029d51d 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -11,10 +11,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up Python 3.8 + - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: '3.10' - name: Install and Run Pre-commit uses: pre-commit/action@v3.0.0 @@ -22,10 +22,8 @@ jobs: - name: Download Semgrep rules run: git clone --depth 1 https://github.com/frappe/semgrep-rules.git frappe-semgrep-rules - - uses: returntocorp/semgrep-action@v1 - env: - SEMGREP_TIMEOUT: 120 - with: - config: >- - r/python.lang.correctness - ./frappe-semgrep-rules/rules + - name: Download semgrep + run: pip install semgrep==0.97.0 + + - name: Run Semgrep rules + run: semgrep ci --config ./frappe-semgrep-rules/rules --config r/python.lang.correctness From 07d7b34fd9d3b60eb4c03b61069f6718cff84b6d Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Tue, 28 Jun 2022 11:31:17 +0530 Subject: [PATCH 060/101] refactor: get_unsubscribe_message * Add fallback label "Unsubscribe" instead of printing None in the email * Add typing hints, f-stringify & make code DRY-er for better readability --- frappe/__init__.py | 2 +- .../email/doctype/email_queue/email_queue.py | 16 ++++---- frappe/email/email_body.py | 3 +- frappe/email/queue.py | 37 ++++++------------- 4 files changed, 23 insertions(+), 35 deletions(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index 9104cd5109..063a62c84b 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -78,7 +78,7 @@ class _dict(dict): return _dict(self) -def _(msg, lang=None, context=None): +def _(msg, lang=None, context=None) -> str: """Returns translated string in current lang, if exists. Usage: _('Change') diff --git a/frappe/email/doctype/email_queue/email_queue.py b/frappe/email/doctype/email_queue/email_queue.py index c3002607b4..330dab9e7f 100644 --- a/frappe/email/doctype/email_queue/email_queue.py +++ b/frappe/email/doctype/email_queue/email_queue.py @@ -183,7 +183,7 @@ def send_mail(email_queue_name, is_background_task=False): class SendMailContext: def __init__(self, queue_doc: Document, is_background_task: bool = False): - self.queue_doc = queue_doc + self.queue_doc: EmailQueue = queue_doc self.is_background_task = is_background_task self.email_account_doc = queue_doc.get_email_account() self.smtp_server = self.email_account_doc.get_smtp_server() @@ -287,16 +287,16 @@ class SendMailContext: ).decode() return message - def get_unsubscribe_str(self, recipient_email): + def get_unsubscribe_str(self, recipient_email: str) -> str: unsubscribe_url = "" + if self.queue_doc.add_unsubscribe_link and self.queue_doc.reference_doctype: - doctype, doc_name = self.queue_doc.reference_doctype, self.queue_doc.reference_name unsubscribe_url = get_unsubcribed_url( - doctype, - doc_name, - recipient_email, - self.queue_doc.unsubscribe_method, - self.queue_doc.unsubscribe_param, + reference_doctype=self.queue_doc.reference_doctype, + reference_name=self.queue_doc.reference_name, + email=recipient_email, + unsubscribe_method=self.queue_doc.unsubscribe_method, + unsubscribe_params=self.queue_doc.unsubscribe_param, ) return quopri.encodestring(unsubscribe_url.encode()).decode() diff --git a/frappe/email/email_body.py b/frappe/email/email_body.py index 50c66e1ad2..3a952e1487 100755 --- a/frappe/email/email_body.py +++ b/frappe/email/email_body.py @@ -7,6 +7,7 @@ import re from email import policy from email.header import Header from email.mime.multipart import MIMEMultipart +from typing import Optional import frappe from frappe.email.doctype.email_account.email_account import EmailAccount @@ -353,7 +354,7 @@ def get_formatted_html( print_html=None, email_account=None, header=None, - unsubscribe_link=None, + unsubscribe_link: Optional[frappe._dict] = None, sender=None, with_container=False, ): diff --git a/frappe/email/queue.py b/frappe/email/queue.py index 1519c26841..45abe0374a 100755 --- a/frappe/email/queue.py +++ b/frappe/email/queue.py @@ -67,37 +67,24 @@ def get_emails_sent_today(email_account=None): return frappe.db.sql(q, q_args)[0][0] -def get_unsubscribe_message(unsubscribe_message, expose_recipients): - if unsubscribe_message: - unsubscribe_html = """{0}""".format( - unsubscribe_message - ) - else: - unsubscribe_link = """{0}""".format( - _("Unsubscribe") - ) - unsubscribe_html = _("{0} to stop receiving emails of this type").format(unsubscribe_link) - - html = """""" + text = f"\n\n{unsubscribe_message}: \n" if expose_recipients == "footer": - text = "\n" - else: - text = "" - text += "\n\n{unsubscribe_message}: \n".format( - unsubscribe_message=unsubscribe_message - ) + text = f"\n{text}" - return frappe._dict({"html": html, "text": text}) + return frappe._dict(html=html, text=text) def get_unsubcribed_url( From 4bf7cd8210d92e89e9ad818fc9c72e317688d8d7 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 28 Jun 2022 12:19:52 +0530 Subject: [PATCH 061/101] fix: ignore virtual docfield property conflicts --- frappe/core/doctype/doctype/doctype.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index b4cbbd6233..e56803acb7 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -171,7 +171,7 @@ class DocType(Document): if docfield.fieldname in method_set: conflict_type = "controller method" - if docfield.fieldname in property_set: + if docfield.fieldname in property_set and not docfield.is_virtual: conflict_type = "class property" if conflict_type: From 600186488866709b2099630fc3a402b6d0e5bb30 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 28 Jun 2022 11:38:40 +0530 Subject: [PATCH 062/101] fix(UX): show next execution time on scheduled job --- .../scheduled_job_type.json | 25 +++++++++++++++++-- .../scheduled_job_type/scheduled_job_type.py | 4 +++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/frappe/core/doctype/scheduled_job_type/scheduled_job_type.json b/frappe/core/doctype/scheduled_job_type/scheduled_job_type.json index d4d79b21fb..cc2a0e870a 100644 --- a/frappe/core/doctype/scheduled_job_type/scheduled_job_type.json +++ b/frappe/core/doctype/scheduled_job_type/scheduled_job_type.json @@ -16,8 +16,11 @@ "server_script", "frequency", "cron_format", + "create_log", + "status_section", "last_execution", - "create_log" + "column_break_9", + "next_execution" ], "fields": [ { @@ -72,6 +75,22 @@ "options": "Server Script", "read_only": 1, "search_index": 1 + }, + { + "fieldname": "next_execution", + "fieldtype": "Datetime", + "is_virtual": 1, + "label": "Next Execution", + "read_only": 1 + }, + { + "fieldname": "status_section", + "fieldtype": "Section Break", + "label": "Status" + }, + { + "fieldname": "column_break_9", + "fieldtype": "Column Break" } ], "in_create": 1, @@ -81,7 +100,7 @@ "link_fieldname": "scheduled_job_type" } ], - "modified": "2020-10-07 10:39:24.519460", + "modified": "2022-06-28 02:55:12.470915", "modified_by": "Administrator", "module": "Core", "name": "Scheduled Job Type", @@ -103,5 +122,7 @@ "quick_entry": 1, "sort_field": "modified", "sort_order": "DESC", + "states": [], + "title_field": "method", "track_changes": 1 } \ No newline at end of file diff --git a/frappe/core/doctype/scheduled_job_type/scheduled_job_type.py b/frappe/core/doctype/scheduled_job_type/scheduled_job_type.py index 318b156dcd..673805ae8b 100644 --- a/frappe/core/doctype/scheduled_job_type/scheduled_job_type.py +++ b/frappe/core/doctype/scheduled_job_type/scheduled_job_type.py @@ -50,6 +50,10 @@ class ScheduledJobType(Document): queued_jobs = get_jobs(site=frappe.local.site, key="job_type")[frappe.local.site] return self.method in queued_jobs + @property + def next_execution(self): + return self.get_next_execution() + def get_next_execution(self): CRON_MAP = { "Yearly": "0 0 1 1 *", From 971b8160a33fab9ce939e9c751fa45da7499e387 Mon Sep 17 00:00:00 2001 From: Shariq Ansari <30859809+shariquerik@users.noreply.github.com> Date: Tue, 28 Jun 2022 12:39:45 +0530 Subject: [PATCH 063/101] fix: extra column in excel after exporting report with group by (#17126) Co-authored-by: gavin --- frappe/desk/reportview.py | 22 ++++++++++++++++------ frappe/model/db_query.py | 5 +++++ frappe/tests/test_db_query.py | 4 +--- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/frappe/desk/reportview.py b/frappe/desk/reportview.py index d6dce68399..893c2a6606 100644 --- a/frappe/desk/reportview.py +++ b/frappe/desk/reportview.py @@ -156,8 +156,6 @@ def setup_group_by(data): **data ) ) - if data.aggregate_on_field: - data.fields.append(f"`tab{data.aggregate_on_doctype}`.`{data.aggregate_on_field}`") else: raise_invalid_field(data.aggregate_on_field) @@ -435,11 +433,20 @@ def append_totals_row(data): def get_labels(fields, doctype): """get column labels based on column names""" labels = [] + doctype = doctype.lower() for key in fields: - key = key.split(" as ")[0] + aggregate_function = "" + + key = key.casefold().split(" as ", maxsplit=1)[0] if key.startswith(("count(", "sum(", "avg(")): - continue + # Get aggregate function and _aggregate_column + # key = 'sum(`tabDocType`.`fieldname`)' + if not key.rstrip().endswith(")"): + continue + _agg_fn, _key = key.split("(", maxsplit=1) + aggregate_function = _agg_fn.lower() # aggregate_function = 'sum' + key = _key[:-1] # key = `tabDocType`.`fieldname` if "." in key: parenttype, fieldname = key.split(".")[0][4:-1], key.split(".")[1].strip("`") @@ -455,7 +462,10 @@ def get_labels(fields, doctype): if parenttype != doctype: # If the column is from a child table, append the child doctype. # For example, "Item Code (Sales Invoice Item)". - label += f" ({ _(parenttype) })" + label += f" ({ _(parenttype.title()) })" + + if aggregate_function: + label = _("{0} of {1}").format(aggregate_function.capitalize(), label) labels.append(label) @@ -464,7 +474,7 @@ def get_labels(fields, doctype): def handle_duration_fieldtype_values(doctype, data, fields): for field in fields: - key = field.split(" as ")[0] + key = field.casefold().split(" as ", maxsplit=1)[0] if key.startswith(("count(", "sum(", "avg(")): continue diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 7fb38848e2..0b8f790246 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -417,6 +417,8 @@ class DatabaseQuery(object): "extract(", "locate(", "strpos(", + ] + aggregate_functions = [ "count(", "sum(", "avg(", @@ -427,6 +429,9 @@ class DatabaseQuery(object): if not ("tab" in field and "." in field) or any(x for x in sql_functions if x in field): continue + if any(x for x in aggregate_functions if x in field): + field = field.split("(", 1)[1][:-1] + table_name = field.split(".")[0] if table_name.lower().startswith("group_concat("): diff --git a/frappe/tests/test_db_query.py b/frappe/tests/test_db_query.py index c1b2e05266..2dd1743767 100644 --- a/frappe/tests/test_db_query.py +++ b/frappe/tests/test_db_query.py @@ -643,9 +643,7 @@ class TestReportview(unittest.TestCase): ) response = execute_cmd("frappe.desk.reportview.get") - self.assertListEqual( - response["keys"], ["field_label", "field_name", "_aggregate_column", "columns"] - ) + self.assertListEqual(response["keys"], ["field_label", "field_name", "_aggregate_column"]) def test_cast_name(self): from frappe.core.doctype.doctype.test_doctype import new_doctype From 4dff0d25a36942560bf65ace9e58bbb2da73d351 Mon Sep 17 00:00:00 2001 From: Shariq Ansari <30859809+shariquerik@users.noreply.github.com> Date: Tue, 28 Jun 2022 16:17:26 +0530 Subject: [PATCH 064/101] feat: add email retry limit in system settings (#17259) **MAX_RETRY_COUNT** for email was hard coded as 3. Added **Email Retry Limit** field in **Email** section in **System Settings** image >no-docs --- .../doctype/system_settings/system_settings.json | 13 ++++++++++--- frappe/email/doctype/email_queue/email_queue.py | 8 +++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/frappe/core/doctype/system_settings/system_settings.json b/frappe/core/doctype/system_settings/system_settings.json index c954e41202..a444062b5a 100644 --- a/frappe/core/doctype/system_settings/system_settings.json +++ b/frappe/core/doctype/system_settings/system_settings.json @@ -63,6 +63,7 @@ "otp_issuer_name", "email", "email_footer_address", + "email_retry_limit", "column_break_18", "disable_standard_email_footer", "hide_footer_in_auto_email_reports", @@ -495,8 +496,8 @@ "fieldname": "allow_older_web_view_links", "fieldtype": "Check", "label": "Allow Older Web View Links (Insecure)" - }, - { + }, + { "fieldname": "column_break_64", "fieldtype": "Column Break" }, @@ -518,12 +519,18 @@ "fieldtype": "Duration", "label": "Reset Password Link Expiry Duration", "non_negative": 1 + }, + { + "default": "3", + "fieldname": "email_retry_limit", + "fieldtype": "Int", + "label": "Email Retry Limit" } ], "icon": "fa fa-cog", "issingle": 1, "links": [], - "modified": "2022-05-19 00:00:18.095269", + "modified": "2022-06-21 13:55:04.796152", "modified_by": "Administrator", "module": "Core", "name": "System Settings", diff --git a/frappe/email/doctype/email_queue/email_queue.py b/frappe/email/doctype/email_queue/email_queue.py index c3002607b4..4fc828eb62 100644 --- a/frappe/email/doctype/email_queue/email_queue.py +++ b/frappe/email/doctype/email_queue/email_queue.py @@ -30,8 +30,6 @@ from frappe.utils import ( split_emails, ) -MAX_RETRY_COUNT = 3 - class EmailQueue(Document): DOCTYPE = "Email Queue" @@ -210,7 +208,7 @@ class SendMailContext: email_status = (self.sent_to and "Partially Sent") or "Not Sent" self.queue_doc.update_status(status=email_status, commit=True) elif exc_type: - if self.queue_doc.retry < MAX_RETRY_COUNT: + if self.queue_doc.retry < get_email_retry_limit(): update_fields = {"status": "Not Sent", "retry": self.queue_doc.retry + 1} else: update_fields = {"status": (self.sent_to and "Partially Errored") or "Error"} @@ -372,6 +370,10 @@ def on_doctype_update(): ) +def get_email_retry_limit(): + return cint(frappe.db.get_system_setting("email_retry_limit")) or 3 + + class QueueBuilder: """Builds Email Queue from the given data""" From d58f2ed8e7cf1ef33df8196174193c760f2d2daf Mon Sep 17 00:00:00 2001 From: Samuel Danieli <23150094+scdanieli@users.noreply.github.com> Date: Tue, 28 Jun 2022 13:58:27 +0200 Subject: [PATCH 065/101] fix: german translations (#17324) --- frappe/translations/de.csv | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/frappe/translations/de.csv b/frappe/translations/de.csv index d00548458c..b22befd321 100644 --- a/frappe/translations/de.csv +++ b/frappe/translations/de.csv @@ -1993,7 +1993,7 @@ QR Code,QR-Code, QR Code for Login Verification,QR Code für Login-Bestätigung, QZ Tray Connection Active!,QZ-Tray-Verbindung aktiv!, QZ Tray Failed: ,QZ-Fach fehlgeschlagen:, -Quarter Day,Quartalstag, +Quarter Day,Viertel-Tag, Query,Abfrage, Query Report,Abfragebericht, Query must be a SELECT,Abfrage muss ein SELECT sein, @@ -4793,3 +4793,17 @@ Reset to default,Auf Standard zurücksetzen, Column Width,Spaltenbreite, Choose Kanban Board,Kanban-Tafel auswählen, Create New Board,Neue Tafel erstellen, +Only If Creator,Nur wenn Ersteller, +Rebuild Tree,Baum neu aufbauen, +Customize Dashboard,Dashboard anpassen, +Reset Dashboard Customizations,Dashboard-Anpassungen zurücksetzen, +Add {0},{0} hinzufügen, +descending,absteigend, +ascending,aufsteigend, +Next Document,Nächstes Dokument, +Previous Document,Vorheriges Dokument, +Mark all as read,Alle als gelesen markieren, +See all Activity,Alle Aktivitäten anzeigen, +Go to Notification Settings List,Gehe zur Listenansicht Benachrichtigungseinstellungen, +Load more,Mehr laden, +Edit Full Form,Vollständiges Formular bearbeiten, From d35d7ffbe24c641dc62b9680cf99f1ce719643d7 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 28 Jun 2022 18:01:12 +0530 Subject: [PATCH 066/101] fix: remove bare exception catching A bare except catches lots of things (like generator iteration end) and should never be used. --- .github/helper/flake8.conf | 1 - frappe/build.py | 2 +- frappe/commands/scheduler.py | 2 +- frappe/core/doctype/doctype/test_doctype.py | 2 +- frappe/core/doctype/user/user.py | 2 +- frappe/database/database.py | 2 +- .../doctype/system_console/system_console.py | 2 +- frappe/email/__init__.py | 30 ++++++++----------- frappe/email/doctype/newsletter/newsletter.py | 2 +- .../doctype/notification/notification.py | 2 +- frappe/email/receive.py | 6 ++-- frappe/installer.py | 2 +- .../razorpay_settings/razorpay_settings.py | 16 ++++------ frappe/model/mapper.py | 2 +- .../generate_theme_files_in_public_folder.py | 2 +- frappe/twofactor.py | 2 +- frappe/utils/background_jobs.py | 2 +- frappe/utils/data.py | 4 +-- frappe/utils/pdf.py | 2 +- frappe/utils/scheduler.py | 2 +- 20 files changed, 39 insertions(+), 48 deletions(-) diff --git a/.github/helper/flake8.conf b/.github/helper/flake8.conf index a7f1f70da3..20d4b912ca 100644 --- a/.github/helper/flake8.conf +++ b/.github/helper/flake8.conf @@ -69,7 +69,6 @@ ignore = F841, E713, E712, - E722, max-line-length = 200 diff --git a/frappe/build.py b/frappe/build.py index 5923bd05ec..a7fdb47677 100644 --- a/frappe/build.py +++ b/frappe/build.py @@ -205,7 +205,7 @@ def symlink(target, link_name, overwrite=False): os.replace(temp_link_name, link_name) except AttributeError: os.renames(temp_link_name, link_name) - except: + except Exception: if os.path.islink(temp_link_name): os.remove(temp_link_name) raise diff --git a/frappe/commands/scheduler.py b/frappe/commands/scheduler.py index ed6a0dea57..a39a604ece 100755 --- a/frappe/commands/scheduler.py +++ b/frappe/commands/scheduler.py @@ -15,7 +15,7 @@ def _is_scheduler_enabled(): enable_scheduler = ( cint(frappe.db.get_single_value("System Settings", "enable_scheduler")) and True or False ) - except: + except Exception: pass finally: frappe.db.close() diff --git a/frappe/core/doctype/doctype/test_doctype.py b/frappe/core/doctype/doctype/test_doctype.py index 569cf9af2f..5b0b575201 100644 --- a/frappe/core/doctype/doctype/test_doctype.py +++ b/frappe/core/doctype/doctype/test_doctype.py @@ -318,7 +318,7 @@ class TestDocType(unittest.TestCase): self.assertListEqual( test_doctype_json["field_order"], ["field_4", "field_5", "field_1", "field_2"] ) - except: + except Exception: raise finally: frappe.flags.allow_doctype_export = 0 diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index 531fd316b1..cfb2f4d871 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -586,7 +586,7 @@ class User(Document): for p in self.social_logins: if p.provider == provider: return p.userid - except: + except Exception: return None def set_social_login_userid(self, provider, userid, username=None): diff --git a/frappe/database/database.py b/frappe/database/database.py index c68368ba38..a52264ed6d 100644 --- a/frappe/database/database.py +++ b/frappe/database/database.py @@ -271,7 +271,7 @@ class Database(object): else: try: return self._cursor.mogrify(query, values) - except: # noqa: E722 + except Exception: return (query, values) def explain_query(self, query, values=None): diff --git a/frappe/desk/doctype/system_console/system_console.py b/frappe/desk/doctype/system_console/system_console.py index f1324403c3..063b3d37d0 100644 --- a/frappe/desk/doctype/system_console/system_console.py +++ b/frappe/desk/doctype/system_console/system_console.py @@ -19,7 +19,7 @@ class SystemConsole(Document): self.output = "\n".join(frappe.debug_log) elif self.type == "SQL": self.output = frappe.as_json(read_sql(self.console, as_dict=1)) - except: # noqa: E722 + except Exception: self.output = frappe.get_traceback() if self.commit: diff --git a/frappe/email/__init__.py b/frappe/email/__init__.py index fae60baebf..42fcb7b01a 100644 --- a/frappe/email/__init__.py +++ b/frappe/email/__init__.py @@ -17,24 +17,20 @@ def get_contact_list(txt, page_length=20): if cached_contacts: return cached_contacts[:page_length] - try: - match_conditions = build_match_conditions("Contact") - match_conditions = "and {0}".format(match_conditions) if match_conditions else "" + match_conditions = build_match_conditions("Contact") + match_conditions = "and {0}".format(match_conditions) if match_conditions else "" - out = frappe.db.sql( - """select email_id as value, - concat(first_name, ifnull(concat(' ',last_name), '' )) as description - from tabContact - where name like %(txt)s or email_id like %(txt)s - %(condition)s - limit %(page_length)s""", - {"txt": "%" + txt + "%", "condition": match_conditions, "page_length": page_length}, - as_dict=True, - ) - out = filter(None, out) - - except: - raise + out = frappe.db.sql( + """select email_id as value, + concat(first_name, ifnull(concat(' ',last_name), '' )) as description + from tabContact + where name like %(txt)s or email_id like %(txt)s + %(condition)s + limit %(page_length)s""", + {"txt": "%" + txt + "%", "condition": match_conditions, "page_length": page_length}, + as_dict=True, + ) + out = filter(None, out) update_contact_cache(out) diff --git a/frappe/email/doctype/newsletter/newsletter.py b/frappe/email/doctype/newsletter/newsletter.py index 18ca440738..6fcdce482f 100644 --- a/frappe/email/doctype/newsletter/newsletter.py +++ b/frappe/email/doctype/newsletter/newsletter.py @@ -66,7 +66,7 @@ class Newsletter(WebsiteGenerator): response = requests.head(url, verify=False, timeout=5) if response.status_code >= 400: broken_links.append(url) - except: + except Exception: broken_links.append(url) return broken_links diff --git a/frappe/email/doctype/notification/notification.py b/frappe/email/doctype/notification/notification.py index 5543ae6b5d..c8079f94e8 100644 --- a/frappe/email/doctype/notification/notification.py +++ b/frappe/email/doctype/notification/notification.py @@ -140,7 +140,7 @@ def get_context(context): if self.channel == "System Notification" or self.send_system_notification: self.create_system_notification(doc, context) - except: + except Exception: self.log_error("Failed to send Notification") if self.set_property_after_alert: diff --git a/frappe/email/receive.py b/frappe/email/receive.py index 12ab04eb4b..dd8273d778 100644 --- a/frappe/email/receive.py +++ b/frappe/email/receive.py @@ -377,7 +377,7 @@ class EmailServer: try: # retrieve headers incoming_mail = Email(b"\n".join(self.pop.top(msg_num, 5)[1])) - except: + except Exception: pass if incoming_mail: @@ -437,7 +437,7 @@ class Email: utc = email.utils.mktime_tz(email.utils.parsedate_tz(self.mail["Date"])) utc_dt = datetime.datetime.utcfromtimestamp(utc) self.date = convert_utc_to_user_timezone(utc_dt).strftime("%Y-%m-%d %H:%M:%S") - except: + except Exception: self.date = now() else: self.date = now() @@ -572,7 +572,7 @@ class Email: try: fname = fname.replace("\n", " ").replace("\r", "") fname = cstr(decode_header(fname)[0][0]) - except: + except Exception: fname = get_random_filename(content_type=content_type) else: fname = get_random_filename(content_type=content_type) diff --git a/frappe/installer.py b/frappe/installer.py index c8373ff06f..59c5dc6602 100644 --- a/frappe/installer.py +++ b/frappe/installer.py @@ -696,7 +696,7 @@ def extract_files(site_name, file_path): subprocess.check_output(["tar", "xvf", tar_path, "--strip", "2"], cwd=abs_site_path) elif file_path.endswith(".tgz"): subprocess.check_output(["tar", "zxvf", tar_path, "--strip", "2"], cwd=abs_site_path) - except: + except Exception: raise finally: frappe.destroy() diff --git a/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py b/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py index b48d21187c..b13319803f 100644 --- a/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py +++ b/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py @@ -141,8 +141,8 @@ class RazorpaySettings(Document): ) if not resp.get("id"): frappe.log_error(message=str(resp), title="Razorpay Failed while creating subscription") - except: - frappe.log_error(frappe.get_traceback()) + except Exception: + frappe.log_error() # failed pass @@ -181,10 +181,8 @@ class RazorpaySettings(Document): else: frappe.log_error(message=str(resp), title="Razorpay Failed while creating subscription") - except: - frappe.log_error(frappe.get_traceback()) - # failed - pass + except Exception: + frappe.log_error() def prepare_subscription_details(self, settings, **kwargs): if not kwargs.get("subscription_id"): @@ -283,10 +281,8 @@ class RazorpaySettings(Document): else: frappe.log_error(message=str(resp), title="Razorpay Payment not authorized") - except: - frappe.log_error(frappe.get_traceback()) - # failed - pass + except Exception: + frappe.log_error() status = frappe.flags.integration_request.status_code diff --git a/frappe/model/mapper.py b/frappe/model/mapper.py index 6a6522ad07..59f211e322 100644 --- a/frappe/model/mapper.py +++ b/frappe/model/mapper.py @@ -243,7 +243,7 @@ def map_fetch_fields(target_doc, df, no_copy_fields): if not linked_doc: try: linked_doc = frappe.get_doc(df.options, target_doc.get(df.fieldname)) - except: + except Exception: return val = linked_doc.get(source_fieldname) diff --git a/frappe/patches/v13_0/generate_theme_files_in_public_folder.py b/frappe/patches/v13_0/generate_theme_files_in_public_folder.py index 9b905a9bbb..29ddca1108 100644 --- a/frappe/patches/v13_0/generate_theme_files_in_public_folder.py +++ b/frappe/patches/v13_0/generate_theme_files_in_public_folder.py @@ -14,6 +14,6 @@ def execute(): try: doc.generate_bootstrap_theme() doc.save() - except: # noqa: E722 + except Exception: print("Ignoring....") print(frappe.get_traceback()) diff --git a/frappe/twofactor.py b/frappe/twofactor.py index 6d01331d7d..c803a5ff87 100644 --- a/frappe/twofactor.py +++ b/frappe/twofactor.py @@ -301,7 +301,7 @@ def send_token_via_sms(otpsecret, token=None, phone_no=None): """Send token as sms to user.""" try: from frappe.core.doctype.sms_settings.sms_settings import send_request - except: + except Exception: return False if not phone_no: diff --git a/frappe/utils/background_jobs.py b/frappe/utils/background_jobs.py index f49c641673..a7956717d4 100755 --- a/frappe/utils/background_jobs.py +++ b/frappe/utils/background_jobs.py @@ -166,7 +166,7 @@ def execute_job(site, method, event, job_name, kwargs, user=None, is_async=True, frappe.log_error(title=method_name) raise - except: + except Exception: frappe.db.rollback() frappe.log_error(title=method_name) frappe.db.commit() diff --git a/frappe/utils/data.py b/frappe/utils/data.py index 49f9ead437..dcc435e8fd 100644 --- a/frappe/utils/data.py +++ b/frappe/utils/data.py @@ -966,7 +966,7 @@ def floor(s): """ try: num = cint(math.floor(flt(s))) - except: + except Exception: num = 0 return num @@ -988,7 +988,7 @@ def ceil(s): """ try: num = cint(math.ceil(flt(s))) - except: + except Exception: num = 0 return num diff --git a/frappe/utils/pdf.py b/frappe/utils/pdf.py index 811a6511fd..ddab2f2b18 100644 --- a/frappe/utils/pdf.py +++ b/frappe/utils/pdf.py @@ -173,7 +173,7 @@ def read_options_from_html(html): match = pattern.findall(html) if match: options[attr] = str(match[-1][3]).strip() - except: + except Exception: pass return str(soup), options diff --git a/frappe/utils/scheduler.py b/frappe/utils/scheduler.py index 6444a2d079..48826b13c6 100755 --- a/frappe/utils/scheduler.py +++ b/frappe/utils/scheduler.py @@ -84,7 +84,7 @@ def enqueue_events_for_site(site): frappe.logger("scheduler").debug("Access denied for site {0}".format(site)) else: log_and_raise() - except: + except Exception: log_and_raise() finally: From c8ac3f922e88336f6398219063de2f2a368683d2 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 28 Jun 2022 18:40:27 +0530 Subject: [PATCH 067/101] Revert "fix: extra column in excel after exporting report with group by (#17126)" This reverts commit 971b8160a33fab9ce939e9c751fa45da7499e387. --- frappe/desk/reportview.py | 22 ++++++---------------- frappe/model/db_query.py | 5 ----- frappe/tests/test_db_query.py | 4 +++- 3 files changed, 9 insertions(+), 22 deletions(-) diff --git a/frappe/desk/reportview.py b/frappe/desk/reportview.py index 893c2a6606..d6dce68399 100644 --- a/frappe/desk/reportview.py +++ b/frappe/desk/reportview.py @@ -156,6 +156,8 @@ def setup_group_by(data): **data ) ) + if data.aggregate_on_field: + data.fields.append(f"`tab{data.aggregate_on_doctype}`.`{data.aggregate_on_field}`") else: raise_invalid_field(data.aggregate_on_field) @@ -433,20 +435,11 @@ def append_totals_row(data): def get_labels(fields, doctype): """get column labels based on column names""" labels = [] - doctype = doctype.lower() for key in fields: - aggregate_function = "" - - key = key.casefold().split(" as ", maxsplit=1)[0] + key = key.split(" as ")[0] if key.startswith(("count(", "sum(", "avg(")): - # Get aggregate function and _aggregate_column - # key = 'sum(`tabDocType`.`fieldname`)' - if not key.rstrip().endswith(")"): - continue - _agg_fn, _key = key.split("(", maxsplit=1) - aggregate_function = _agg_fn.lower() # aggregate_function = 'sum' - key = _key[:-1] # key = `tabDocType`.`fieldname` + continue if "." in key: parenttype, fieldname = key.split(".")[0][4:-1], key.split(".")[1].strip("`") @@ -462,10 +455,7 @@ def get_labels(fields, doctype): if parenttype != doctype: # If the column is from a child table, append the child doctype. # For example, "Item Code (Sales Invoice Item)". - label += f" ({ _(parenttype.title()) })" - - if aggregate_function: - label = _("{0} of {1}").format(aggregate_function.capitalize(), label) + label += f" ({ _(parenttype) })" labels.append(label) @@ -474,7 +464,7 @@ def get_labels(fields, doctype): def handle_duration_fieldtype_values(doctype, data, fields): for field in fields: - key = field.casefold().split(" as ", maxsplit=1)[0] + key = field.split(" as ")[0] if key.startswith(("count(", "sum(", "avg(")): continue diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 0b8f790246..7fb38848e2 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -417,8 +417,6 @@ class DatabaseQuery(object): "extract(", "locate(", "strpos(", - ] - aggregate_functions = [ "count(", "sum(", "avg(", @@ -429,9 +427,6 @@ class DatabaseQuery(object): if not ("tab" in field and "." in field) or any(x for x in sql_functions if x in field): continue - if any(x for x in aggregate_functions if x in field): - field = field.split("(", 1)[1][:-1] - table_name = field.split(".")[0] if table_name.lower().startswith("group_concat("): diff --git a/frappe/tests/test_db_query.py b/frappe/tests/test_db_query.py index 2dd1743767..c1b2e05266 100644 --- a/frappe/tests/test_db_query.py +++ b/frappe/tests/test_db_query.py @@ -643,7 +643,9 @@ class TestReportview(unittest.TestCase): ) response = execute_cmd("frappe.desk.reportview.get") - self.assertListEqual(response["keys"], ["field_label", "field_name", "_aggregate_column"]) + self.assertListEqual( + response["keys"], ["field_label", "field_name", "_aggregate_column", "columns"] + ) def test_cast_name(self): from frappe.core.doctype.doctype.test_doctype import new_doctype From d1f5c49b0292c503dc6c1cc1c9c70b2ce7d6a360 Mon Sep 17 00:00:00 2001 From: Aradhya Date: Fri, 10 Jun 2022 11:27:16 +0530 Subject: [PATCH 068/101] refactor(qb-engine): frappe.db.query * feat: Added support for True as filter and pluck in the query engine * feat: Added join support * fix: return if filters are None * feat: Added support for sets as filters and additional conditions * fix: fixed IS operator in query builder * feat: Added support for 'as' in query engine * fix: fixed 'as' for criterion objects passed directly * fix: fixed frappe.db.count * fix: fixed functions in fieldname * feat: Added support for multiple fields passed as a single string :) fixed None fields in a list * feat: Added support for "as" in single string fields * fix: fixed queries with invalid syntax --- frappe/database/query.py | 49 +++++++++++++++++-- .../integrations/doctype/webhook/__init__.py | 2 +- frappe/model/db_query.py | 17 +++++-- frappe/share.py | 12 ++--- .../workflow_action/workflow_action.py | 2 +- 5 files changed, 68 insertions(+), 14 deletions(-) diff --git a/frappe/database/query.py b/frappe/database/query.py index f7cc143cf7..22b3074cad 100644 --- a/frappe/database/query.py +++ b/frappe/database/query.py @@ -93,7 +93,7 @@ def func_between(key: Field, value: Union[List, Tuple]) -> frappe.qb: def func_is(key, value): "Wrapper for IS" - return Field(key).isnotnull() if value.lower() == "set" else Field(key).isnull() + return key.isnotnull() if value.lower() == "set" else key.isnull() def func_timespan(key: Field, value: str) -> frappe.qb: @@ -238,7 +238,7 @@ class Query: Returns: conditions (frappe.qb): frappe.qb object """ - if kwargs.get("orderby"): + if kwargs.get("orderby") and kwargs.get("orderby") != "KEEP_DEFAULT_ORDERING": orderby = kwargs.get("orderby") if isinstance(orderby, str) and len(orderby.split()) > 1: for ordby in orderby.split(","): @@ -250,6 +250,7 @@ class Query: if kwargs.get("limit"): conditions = conditions.limit(kwargs.get("limit")) + conditions = conditions.offset(kwargs.get("offset", 0)) if kwargs.get("distinct"): conditions = conditions.distinct() @@ -257,6 +258,9 @@ class Query: if kwargs.get("for_update"): conditions = conditions.for_update() + if kwargs.get("groupby"): + conditions = conditions.groupby(kwargs.get("groupby")) + return conditions def misc_query(self, table: str, filters: Union[List, Tuple] = None, **kwargs): @@ -308,6 +312,10 @@ class Query: conditions = self.add_conditions(conditions, **kwargs) return conditions + for key, value in filters.items(): + if isinstance(value, bool): + filters.update({key: str(int(value))}) + for key in filters: value = filters.get(key) _operator = self.OPERATOR_MAP["="] @@ -354,6 +362,36 @@ class Query: return criterion + def set_fields(self, fields, **kwargs): + fields = kwargs.get("pluck") if kwargs.get("pluck") else fields or "name" + if isinstance(fields, str) and "," in fields: + fields = fields.split(",") + fields = [field.replace(" ", "") if "as" not in field else field for field in fields] + + if isinstance(fields, str): + if fields == "*": + return fields + if " as " in fields: + fields, reference = fields.split(" as ") + fields = Field(fields).as_(reference) + else: + if issubclass(type(fields), Criterion): + return fields + updated_fields = list() + for field in fields: + if not isinstance(field, Criterion) and field: + if " as " in field: + field, reference = field.split(" as ") + updated_fields.append(Field(field).as_(reference)) + else: + updated_fields.append(Field(field)) + fields = updated_fields + + if not isinstance(fields, (list, tuple, str, Criterion)): + fields = list(fields) + + return fields + def get_sql( self, table: str, @@ -364,12 +402,17 @@ class Query: # Clean up state before each query self.tables = {} criterion = self.build_conditions(table, filters, **kwargs) + fields = self.set_fields(fields, **kwargs) + + join = kwargs.get("join").replace(" ", "_") if kwargs.get("join") else "left_join" if len(self.tables) > 1: primary_table = self.tables[table] del self.tables[table] for table_object in self.tables.values(): - criterion = criterion.left_join(table_object).on(table_object.parent == primary_table.name) + criterion = getattr(criterion, join)(table_object).on( + table_object.parent == primary_table.name + ) if isinstance(fields, (list, tuple)): query = criterion.select(*kwargs.get("field_objects", fields)) diff --git a/frappe/integrations/doctype/webhook/__init__.py b/frappe/integrations/doctype/webhook/__init__.py index 915d2819ee..077b39101e 100644 --- a/frappe/integrations/doctype/webhook/__init__.py +++ b/frappe/integrations/doctype/webhook/__init__.py @@ -25,7 +25,7 @@ def run_webhooks(doc, method): # query webhooks webhooks_list = frappe.get_all( "Webhook", - fields=["name", "`condition`", "webhook_docevent", "webhook_doctype"], + fields=["name", "condition", "webhook_docevent", "webhook_doctype"], filters={"enabled": True}, ) diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 6ac3402235..49b324b794 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -163,7 +163,7 @@ class DatabaseQuery(object): if not self.columns: return [] - result = self.build_and_run(ignore_permissions=ignore_permissions) + result = self.build_and_run(ignore_permissions=ignore_permissions, pluck=pluck) if with_comment_count and not as_list and self.doctype: self.add_comment_count(result) @@ -177,7 +177,7 @@ class DatabaseQuery(object): return result - def build_and_run(self, ignore_permissions): + def build_and_run(self, ignore_permissions, pluck): args = self.prepare_args() args.limit = self.add_limit() @@ -203,7 +203,18 @@ class DatabaseQuery(object): % args ) if ignore_permissions: - sql = self.query.get_sql(self.doctype, fields=self.temp_fields, filters=self.temp_filters) + sql = self.query.get_sql( + self.doctype, + fields=self.temp_fields, + filters=self.temp_filters, + pluck=pluck, + join=self.join, + orderby=self.order_by, + groupby=self.group_by, + distinct=self.distinct, + limit=self.limit_page_length, + offset=self.limit_start, + ) return sql.run( as_dict=not self.as_list, debug=self.debug, diff --git a/frappe/share.py b/frappe/share.py index 3edcb1be38..2933017048 100644 --- a/frappe/share.py +++ b/frappe/share.py @@ -104,12 +104,12 @@ def get_users(doctype, name): return frappe.db.get_all( "DocShare", fields=[ - "`name`", - "`user`", - "`read`", - "`write`", - "`submit`", - "`share`", + "name", + "user", + "read", + "write", + "submit", + "share", "everyone", "owner", "creation", diff --git a/frappe/workflow/doctype/workflow_action/workflow_action.py b/frappe/workflow/doctype/workflow_action/workflow_action.py index 038a3021d2..545ad6ec77 100644 --- a/frappe/workflow/doctype/workflow_action/workflow_action.py +++ b/frappe/workflow/doctype/workflow_action/workflow_action.py @@ -290,7 +290,7 @@ def update_completed_workflow_actions_using_user(doc, user=None): def get_next_possible_transitions(workflow_name, state, doc=None): transitions = frappe.get_all( "Workflow Transition", - fields=["allowed", "action", "state", "allow_self_approval", "next_state", "`condition`"], + fields=["allowed", "action", "state", "allow_self_approval", "next_state", "condition"], filters=[["parent", "=", workflow_name], ["state", "=", state]], ) From d0680941adacb6ebaa9bc9334be784566cf97a82 Mon Sep 17 00:00:00 2001 From: Aradhya Date: Mon, 13 Jun 2022 16:25:47 +0530 Subject: [PATCH 069/101] refactor: frappe.qb.engine * feat: supporting empty iterables for Contains objects * fix: explicitly setting empty iterables as tuples to support more operators * feat: Added locate to frappe.qb Functions * feat: Added support for functions passed as strings in fields * feat: Included Criterion objects as fields * fix: picking up only function intended fields to pass to get_function_objects * feat: Added iterable for available functions, added support for Field objects * fix: fixed * passed in fields in lists --- frappe/database/query.py | 90 +++++++++++++++++++++++++++---- frappe/model/db_query.py | 25 +-------- frappe/query_builder/functions.py | 16 ++++++ 3 files changed, 99 insertions(+), 32 deletions(-) diff --git a/frappe/database/query.py b/frappe/database/query.py index 22b3074cad..b9de427c60 100644 --- a/frappe/database/query.py +++ b/frappe/database/query.py @@ -1,5 +1,6 @@ import operator import re +from ast import literal_eval from functools import cached_property from typing import Any, Callable, Dict, List, Tuple, Union @@ -325,7 +326,8 @@ class Query: continue if isinstance(value, (list, tuple)): _operator = self.OPERATOR_MAP[value[0].casefold()] - conditions = conditions.where(_operator(Field(key), value[1])) + _value = value[1] if value[1] else ("",) + conditions = conditions.where(_operator(Field(key), _value)) else: if value is not None: conditions = conditions.where(_operator(Field(key), value)) @@ -364,32 +366,102 @@ class Query: def set_fields(self, fields, **kwargs): fields = kwargs.get("pluck") if kwargs.get("pluck") else fields or "name" - if isinstance(fields, str) and "," in fields: + if isinstance(fields, list) and None in fields and Field not in fields: + return None + + is_list = isinstance(fields, (list, tuple, set)) + is_str = isinstance(fields, str) + + def add_functions(fields): + from frappe.query_builder.functions import SqlFunctions + + sql_functions = [sql_function.value for sql_function in SqlFunctions] + + def get_function_objects(fields): + from frappe.query_builder import functions + + def literal_eval_(literal): + try: + return literal_eval(literal) + except (ValueError, SyntaxError): + return literal + + func = fields.split("(")[0].casefold().split() + func = [f for f in func if f in sql_functions][0] + args = fields[len(func) + 1 : fields.index(")")].split(",") + args = [literal_eval_(arg.strip()) for arg in args] + return getattr(functions, func.capitalize())(*args) + + if is_str and any( + [func in fields.casefold() and f"{func}(" in fields.casefold() for func in sql_functions] + ): + function_objects = [] + return function_objects or [get_function_objects(fields)] + else: + functions = [] + for field in fields: + if not issubclass(type(field), Criterion): + if any( + [func in field.casefold() and f"{func}(" in field.casefold() for func in sql_functions] + ): + functions.append(field.casefold()) + return [get_function_objects(function) for function in functions] + + function_objects = ( + add_functions(fields=fields) if not issubclass(type(fields), Criterion) else [] + ) + for function in function_objects: + if is_str: + fields = re.sub( + r"\(.*?\)", "", fields.casefold().replace(str(type(function).__name__).strip().casefold(), "") + ) + + else: + updated_fields = [] + for field in fields: + if isinstance(field, str): + updated_fields.append( + re.sub(r"\(.*?\)", "", field) + .strip() + .casefold() + .replace(str(type(function).__name__).strip().casefold(), "") + ) + else: + updated_fields.append(field) + + fields = updated_fields + + if is_str and "," in fields: fields = fields.split(",") fields = [field.replace(" ", "") if "as" not in field else field for field in fields] - if isinstance(fields, str): + if is_str: if fields == "*": return fields if " as " in fields: fields, reference = fields.split(" as ") fields = Field(fields).as_(reference) - else: + + if not is_str and fields: if issubclass(type(fields), Criterion): return fields - updated_fields = list() + updated_fields = [] + if "*" in fields: + return fields for field in fields: if not isinstance(field, Criterion) and field: if " as " in field: field, reference = field.split(" as ") - updated_fields.append(Field(field).as_(reference)) + updated_fields.append(Field(field.strip()).as_(reference)) else: updated_fields.append(Field(field)) - fields = updated_fields - if not isinstance(fields, (list, tuple, str, Criterion)): - fields = list(fields) + fields = updated_fields + if not is_list: + fields = [fields] if fields else [] + + fields.extend(function_objects) return fields def get_sql( diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 49b324b794..b9c757bfa6 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -163,7 +163,7 @@ class DatabaseQuery(object): if not self.columns: return [] - result = self.build_and_run(ignore_permissions=ignore_permissions, pluck=pluck) + result = self.build_and_run() if with_comment_count and not as_list and self.doctype: self.add_comment_count(result) @@ -177,7 +177,7 @@ class DatabaseQuery(object): return result - def build_and_run(self, ignore_permissions, pluck): + def build_and_run(self): args = self.prepare_args() args.limit = self.add_limit() @@ -202,27 +202,6 @@ class DatabaseQuery(object): %(limit)s""" % args ) - if ignore_permissions: - sql = self.query.get_sql( - self.doctype, - fields=self.temp_fields, - filters=self.temp_filters, - pluck=pluck, - join=self.join, - orderby=self.order_by, - groupby=self.group_by, - distinct=self.distinct, - limit=self.limit_page_length, - offset=self.limit_start, - ) - return sql.run( - as_dict=not self.as_list, - debug=self.debug, - update=self.update, - ignore_ddl=self.ignore_ddl, - run=self.run, - ) - return frappe.db.sql( query, as_dict=not self.as_list, diff --git a/frappe/query_builder/functions.py b/frappe/query_builder/functions.py index f03c139f57..7b260098d1 100644 --- a/frappe/query_builder/functions.py +++ b/frappe/query_builder/functions.py @@ -1,3 +1,5 @@ +from enum import Enum + from pypika.functions import * from pypika.terms import Arithmetic, ArithmeticExpression, CustomFunction, Function @@ -14,6 +16,11 @@ class Concat_ws(Function): super(Concat_ws, self).__init__("CONCAT_WS", *terms, **kwargs) +class Locate(Function): + def __init__(self, *terms, **kwargs): + super(Locate, self).__init__("LOCATE", *terms, **kwargs) + + GroupConcat = ImportMapper({db_type_is.MARIADB: GROUP_CONCAT, db_type_is.POSTGRES: STRING_AGG}) Match = ImportMapper({db_type_is.MARIADB: MATCH, db_type_is.POSTGRES: TO_TSVECTOR}) @@ -81,6 +88,15 @@ def _aggregate(function, dt, fieldname, filters, **kwargs): ) +class SqlFunctions(Enum): + DayOfYear = "dayofyear" + Extract = "extract" + Locate = "locate" + Count = "count" + Sum = "sum" + Avg = "avg" + + def _max(dt, fieldname, filters=None, **kwargs): return _aggregate(Max, dt, fieldname, filters, **kwargs) From fca026927e7fcbe1e7bd88f01bd742d8bbfef991 Mon Sep 17 00:00:00 2001 From: Aradhya Date: Wed, 15 Jun 2022 12:34:02 +0530 Subject: [PATCH 070/101] refactor: moved all query logic to query class --- frappe/database/database.py | 7 ------- frappe/database/query.py | 10 +++++++--- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/frappe/database/database.py b/frappe/database/database.py index 1de22af037..d88d3417d6 100644 --- a/frappe/database/database.py +++ b/frappe/database/database.py @@ -723,13 +723,6 @@ class Database(object): ): field_objects = [] - if not isinstance(fields, Criterion): - for field in fields: - if "(" in str(field) or " as " in str(field): - field_objects.append(PseudoColumn(field)) - else: - field_objects.append(field) - query = self.query.get_sql( table=doctype, filters=filters, diff --git a/frappe/database/query.py b/frappe/database/query.py index b9de427c60..c8e1ddabc6 100644 --- a/frappe/database/query.py +++ b/frappe/database/query.py @@ -370,6 +370,10 @@ class Query: return None is_list = isinstance(fields, (list, tuple, set)) + if is_list and len(fields) == 1: + fields = fields[0] + is_list = False + is_str = isinstance(fields, str) def add_functions(fields): @@ -389,7 +393,7 @@ class Query: func = fields.split("(")[0].casefold().split() func = [f for f in func if f in sql_functions][0] args = fields[len(func) + 1 : fields.index(")")].split(",") - args = [literal_eval_(arg.strip()) for arg in args] + args = [Field(literal_eval_((arg.strip()))) for arg in args] return getattr(functions, func.capitalize())(*args) if is_str and any( @@ -474,7 +478,7 @@ class Query: # Clean up state before each query self.tables = {} criterion = self.build_conditions(table, filters, **kwargs) - fields = self.set_fields(fields, **kwargs) + fields = self.set_fields(kwargs.get("field_objects") or fields, **kwargs) join = kwargs.get("join").replace(" ", "_") if kwargs.get("join") else "left_join" @@ -487,7 +491,7 @@ class Query: ) if isinstance(fields, (list, tuple)): - query = criterion.select(*kwargs.get("field_objects", fields)) + query = criterion.select(*fields) elif isinstance(fields, Criterion): query = criterion.select(fields) From 960952cfc337f2764bd52d20458cf3f5c2b3bbba Mon Sep 17 00:00:00 2001 From: Aradhya Date: Wed, 15 Jun 2022 13:06:56 +0530 Subject: [PATCH 071/101] feat(qb-engine): Added Aggregation function support * Added Min, Max * Added tests --- frappe/database/query.py | 3 +- .../integrations/doctype/webhook/__init__.py | 2 +- frappe/model/db_query.py | 6 +- frappe/query_builder/functions.py | 2 + frappe/share.py | 12 ++-- frappe/tests/test_query.py | 55 ++++++++++++++++++- .../workflow_action/workflow_action.py | 2 +- 7 files changed, 67 insertions(+), 15 deletions(-) diff --git a/frappe/database/query.py b/frappe/database/query.py index c8e1ddabc6..6295c4ec3e 100644 --- a/frappe/database/query.py +++ b/frappe/database/query.py @@ -462,7 +462,8 @@ class Query: fields = updated_fields - if not is_list: + # Need to check instance again since fields modified. + if not isinstance(fields, (list, tuple, set)): fields = [fields] if fields else [] fields.extend(function_objects) diff --git a/frappe/integrations/doctype/webhook/__init__.py b/frappe/integrations/doctype/webhook/__init__.py index 077b39101e..915d2819ee 100644 --- a/frappe/integrations/doctype/webhook/__init__.py +++ b/frappe/integrations/doctype/webhook/__init__.py @@ -25,7 +25,7 @@ def run_webhooks(doc, method): # query webhooks webhooks_list = frappe.get_all( "Webhook", - fields=["name", "condition", "webhook_docevent", "webhook_doctype"], + fields=["name", "`condition`", "webhook_docevent", "webhook_doctype"], filters={"enabled": True}, ) diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index b9c757bfa6..fe52818235 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -89,9 +89,6 @@ class DatabaseQuery(object): ignore_ddl=False, parent_doctype=None, ) -> List: - from frappe.database.query import Query - - self.query = Query() if ( not ignore_permissions @@ -115,8 +112,6 @@ class DatabaseQuery(object): # if `filters` is a list of strings, its probably fields filters, fields = fields, filters - self.temp_filters, self.temp_fields = filters, fields - if fields: self.fields = fields else: @@ -202,6 +197,7 @@ class DatabaseQuery(object): %(limit)s""" % args ) + return frappe.db.sql( query, as_dict=not self.as_list, diff --git a/frappe/query_builder/functions.py b/frappe/query_builder/functions.py index 7b260098d1..b55eff4298 100644 --- a/frappe/query_builder/functions.py +++ b/frappe/query_builder/functions.py @@ -95,6 +95,8 @@ class SqlFunctions(Enum): Count = "count" Sum = "sum" Avg = "avg" + Max = "max" + Min = "min" def _max(dt, fieldname, filters=None, **kwargs): diff --git a/frappe/share.py b/frappe/share.py index 2933017048..3edcb1be38 100644 --- a/frappe/share.py +++ b/frappe/share.py @@ -104,12 +104,12 @@ def get_users(doctype, name): return frappe.db.get_all( "DocShare", fields=[ - "name", - "user", - "read", - "write", - "submit", - "share", + "`name`", + "`user`", + "`read`", + "`write`", + "`submit`", + "`share`", "everyone", "owner", "creation", diff --git a/frappe/tests/test_query.py b/frappe/tests/test_query.py index 949c3e9433..d7190fe7ae 100644 --- a/frappe/tests/test_query.py +++ b/frappe/tests/test_query.py @@ -1,11 +1,12 @@ import unittest import frappe +from frappe.query_builder import Field from frappe.tests.test_query_builder import db_type_is, run_only_if -@run_only_if(db_type_is.MARIADB) class TestQuery(unittest.TestCase): + @run_only_if(db_type_is.MARIADB) def test_multiple_tables_in_filters(self): self.assertEqual( frappe.db.query.get_sql( @@ -18,3 +19,55 @@ class TestQuery(unittest.TestCase): ).get_sql(), "SELECT * FROM `tabDocType` LEFT JOIN `tabBOM Update Log` ON `tabBOM Update Log`.`parent`=`tabDocType`.`name` WHERE `tabBOM Update Log`.`name` LIKE 'f%' AND `tabDocType`.`parent`='something'", ) + + def test_string_fields(self): + self.assertEqual( + frappe.db.query.get_sql("User", fields="name, email", filters={"name": "Administrator"}), + frappe.qb.from_("User") + .select(Field("name"), Field("email")) + .where(Field("name") == "Administrator"), + ) + + self.assertEqual( + frappe.db.query.get_sql("User", fields=["name, email"], filters={"name": "Administrator"}), + frappe.qb.from_("User") + .select(Field("name"), Field("email")) + .where(Field("name") == "Administrator"), + ) + + def test_functions_fields(self): + from frappe.query_builder.functions import Count + + self.assertEqual( + frappe.db.query.get_sql("User", fields="Count(name)", filters={}), + frappe.qb.from_("User").select(Count(Field("name"))), + ) + + self.assertEqual( + frappe.db.query.get_sql("User", fields="Count(name), Max(name)", filters={}), + frappe.qb.from_("User").select(Count(Field("name")), Max(Field("name"))), + ) + + self.assertEqual( + frappe.db.query.get_sql("User", fields=["Count(name)", "Max(name)"], filters={}), + frappe.qb.from_("User").select(Count(Field("name")), Max(Field("name"))), + ) + + self.assertEqual( + frappe.db.query.get_sql("User", fields=[Count("*")], filters={}), + frappe.qb.from_("User").select(Count(Field("name")), Max(Field("name"))), + ) + + def test_qb_fields(self): + user_doctype = frappe.qb.DocType("User") + self.assertEqual( + frappe.db.query.get_sql( + user_doctype, fields=[user_doctype.name, user_doctype.email], filters={} + ), + frappe.qb.from_(user_doctype).select(user_doctype.name, user_doctype.email), + ) + + self.assertEqual( + frappe.db.query.get_sql(user_doctype, fields=user_doctype.email, filters={}), + frappe.qb.from_(user_doctype).select(user_doctype.email), + ) diff --git a/frappe/workflow/doctype/workflow_action/workflow_action.py b/frappe/workflow/doctype/workflow_action/workflow_action.py index 545ad6ec77..038a3021d2 100644 --- a/frappe/workflow/doctype/workflow_action/workflow_action.py +++ b/frappe/workflow/doctype/workflow_action/workflow_action.py @@ -290,7 +290,7 @@ def update_completed_workflow_actions_using_user(doc, user=None): def get_next_possible_transitions(workflow_name, state, doc=None): transitions = frappe.get_all( "Workflow Transition", - fields=["allowed", "action", "state", "allow_self_approval", "next_state", "condition"], + fields=["allowed", "action", "state", "allow_self_approval", "next_state", "`condition`"], filters=[["parent", "=", workflow_name], ["state", "=", state]], ) From 7732accded4ca57ac78ec3c9f81f9069b3250947 Mon Sep 17 00:00:00 2001 From: Aradhya Date: Tue, 21 Jun 2022 16:04:09 +0530 Subject: [PATCH 072/101] feat: Attached Engine object to qb & added dynamic type hints --- frappe/__init__.py | 9 +++++++-- frappe/database/database.py | 27 +++++++++------------------ frappe/database/query.py | 2 +- frappe/query_builder/__init__.py | 1 + frappe/query_builder/builder.py | 9 +++++++++ frappe/query_builder/functions.py | 4 +--- frappe/query_builder/utils.py | 6 ++++++ 7 files changed, 34 insertions(+), 24 deletions(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index 51c6ba3a74..d36a13b3a3 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -21,7 +21,12 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union import click from werkzeug.local import Local, release_local -from frappe.query_builder import get_query_builder, patch_query_aggregation, patch_query_execute +from frappe.query_builder import ( + get_qb_engine, + get_query_builder, + patch_query_aggregation, + patch_query_execute, +) from frappe.utils.caching import request_cache from frappe.utils.data import cstr, sbool @@ -234,7 +239,7 @@ def init(site, sites_path=None, new_site=False): local.session = _dict() local.dev_server = _dev_server local.qb = get_query_builder(local.conf.db_type or "mariadb") - + local.qb.engine = get_qb_engine() setup_module_map() patch_query_execute() patch_query_aggregation() diff --git a/frappe/database/database.py b/frappe/database/database.py index d88d3417d6..fd94bcfe12 100644 --- a/frappe/database/database.py +++ b/frappe/database/database.py @@ -12,7 +12,7 @@ from contextlib import contextmanager from time import time from typing import Dict, List, Optional, Tuple, Union -from pypika.terms import Criterion, NullValue, PseudoColumn +from pypika.terms import Criterion, NullValue import frappe import frappe.defaults @@ -69,15 +69,6 @@ class Database(object): self.password = password or frappe.conf.db_password self.value_cache = {} - @property - def query(self): - if not hasattr(self, "_query"): - from .query import Query - - self._query = Query() - del Query - return self._query - def setup_type_map(self): pass @@ -595,7 +586,7 @@ class Database(object): return [map(values.get, fields)] else: - r = self.query.get_sql( + r = frappe.qb.engine.get_sql( "Singles", filters={"field": ("in", tuple(fields)), "doctype": doctype}, fields=["field", "value"], @@ -625,14 +616,14 @@ class Database(object): # Get coulmn and value of the single doctype Accounts Settings account_settings = frappe.db.get_singles_dict("Accounts Settings") """ - result = self.query.get_sql( + queried_result = frappe.qb.engine.get_sql( "Singles", filters={"doctype": doctype}, fields=["field", "value"], for_update=for_update, ).run() - return frappe._dict(result) + return frappe._dict(queried_result) @staticmethod def get_all(*args, **kwargs): @@ -681,7 +672,7 @@ class Database(object): if cache and fieldname in self.value_cache[doctype]: return self.value_cache[doctype][fieldname] - val = self.query.get_sql( + val = frappe.qb.engine.get_sql( table="Singles", filters={"doctype": doctype, "field": fieldname}, fields="value", @@ -723,7 +714,7 @@ class Database(object): ): field_objects = [] - query = self.query.get_sql( + query = frappe.qb.engine.get_sql( table=doctype, filters=filters, orderby=order_by, @@ -833,7 +824,7 @@ class Database(object): frappe.clear_document_cache(dt, docname) else: - query = self.query.build_conditions(table=dt, filters=dn, update=True) + query = frappe.qb.engine.build_conditions(table=dt, filters=dn, update=True) # TODO: Fix this; doesn't work rn - gavin@frappe.io # frappe.cache().hdel_keys(dt, "document_cache") # Workaround: clear all document caches @@ -1034,7 +1025,7 @@ class Database(object): cache_count = frappe.cache().get_value("doctype:count:{}".format(dt)) if cache_count is not None: return cache_count - query = self.query.get_sql(table=dt, filters=filters, fields=Count("*"), distinct=distinct) + query = frappe.qb.engine.get_sql(table=dt, filters=filters, fields=Count("*"), distinct=distinct) count = self.sql(query, debug=debug)[0][0] if not filters and cache: frappe.cache().set_value("doctype:count:{}".format(dt), count, expires_in_sec=86400) @@ -1174,7 +1165,7 @@ class Database(object): Doctype name can be passed directly, it will be pre-pended with `tab`. """ filters = filters or kwargs.get("conditions") - query = self.query.build_conditions(table=doctype, filters=filters).delete() + query = frappe.qb.engine.build_conditions(table=doctype, filters=filters).delete() if "debug" not in kwargs: kwargs["debug"] = debug return query.run(**kwargs) diff --git a/frappe/database/query.py b/frappe/database/query.py index 6295c4ec3e..abf5c6936f 100644 --- a/frappe/database/query.py +++ b/frappe/database/query.py @@ -169,7 +169,7 @@ OPERATOR_MAP: Dict[str, Callable] = { } -class Query: +class Engine: tables: dict = {} @cached_property diff --git a/frappe/query_builder/__init__.py b/frappe/query_builder/__init__.py index 1bf9ec97d9..eb1d9df08f 100644 --- a/frappe/query_builder/__init__.py +++ b/frappe/query_builder/__init__.py @@ -7,6 +7,7 @@ from frappe.query_builder.terms import ParameterizedFunction, ParameterizedValue from frappe.query_builder.utils import ( Column, DocType, + get_qb_engine, get_query_builder, patch_query_aggregation, patch_query_execute, diff --git a/frappe/query_builder/builder.py b/frappe/query_builder/builder.py index d2fdeab324..c23d76974c 100644 --- a/frappe/query_builder/builder.py +++ b/frappe/query_builder/builder.py @@ -1,3 +1,5 @@ +import typing + from pypika import MySQLQuery, Order, PostgreSQLQuery, terms from pypika.dialects import MySQLQueryBuilder, PostgreSQLQueryBuilder from pypika.queries import QueryBuilder, Schema, Table @@ -13,6 +15,13 @@ class Base: Schema = Schema Table = Table + # Added dynamic type hints for engine attribute + # which is to be assigned later. + if typing.TYPE_CHECKING: + from frappe.database.query import Engine + + engine: Engine + @staticmethod def functions(name: str, *args, **kwargs) -> Function: return Function(name, *args, **kwargs) diff --git a/frappe/query_builder/functions.py b/frappe/query_builder/functions.py index b55eff4298..d2debd6da1 100644 --- a/frappe/query_builder/functions.py +++ b/frappe/query_builder/functions.py @@ -4,7 +4,6 @@ from pypika.functions import * from pypika.terms import Arithmetic, ArithmeticExpression, CustomFunction, Function import frappe -from frappe.database.query import Query from frappe.query_builder.custom import GROUP_CONCAT, MATCH, STRING_AGG, TO_TSVECTOR from frappe.query_builder.utils import ImportMapper, db_type_is @@ -80,8 +79,7 @@ class Cast_(Function): def _aggregate(function, dt, fieldname, filters, **kwargs): return ( - Query() - .build_conditions(dt, filters) + frappe.qb.engine.build_conditions(dt, filters) .select(function(PseudoColumn(fieldname))) .run(**kwargs)[0][0] or 0 diff --git a/frappe/query_builder/utils.py b/frappe/query_builder/utils.py index 69aee9b350..573173ef03 100644 --- a/frappe/query_builder/utils.py +++ b/frappe/query_builder/utils.py @@ -45,6 +45,12 @@ def get_query_builder(type_of_db: str) -> Union[Postgres, MariaDB]: return picks[db] +def get_qb_engine(): + from frappe.database.query import Engine + + return Engine() + + def get_attr(method_string): modulename = ".".join(method_string.split(".")[:-1]) methodname = method_string.split(".")[-1] From 4af2e1e88605b54ab0a737c15c9ae75aa6f0b698 Mon Sep 17 00:00:00 2001 From: Aradhya Date: Tue, 21 Jun 2022 16:39:15 +0530 Subject: [PATCH 073/101] refactor: replaced frappe.db.query with frappe.qb.engine --- frappe/desk/doctype/number_card/number_card.py | 2 +- frappe/desk/listview.py | 2 +- frappe/tests/test_db_query.py | 2 +- frappe/tests/test_query.py | 18 +++++++++--------- frappe/utils/goal.py | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/frappe/desk/doctype/number_card/number_card.py b/frappe/desk/doctype/number_card/number_card.py index d6d4f00b69..a9ef31cb2c 100644 --- a/frappe/desk/doctype/number_card/number_card.py +++ b/frappe/desk/doctype/number_card/number_card.py @@ -197,7 +197,7 @@ def get_cards_for_user(doctype, txt, searchfield, start, page_len, filters): if txt: search_conditions = [numberCard[field].like("%{txt}%".format(txt=txt)) for field in searchfields] - condition_query = frappe.db.query.build_conditions(doctype, filters) + condition_query = frappe.qb.engine.build_conditions(doctype, filters) return ( condition_query.select(numberCard.name, numberCard.label, numberCard.document_type) diff --git a/frappe/desk/listview.py b/frappe/desk/listview.py index 5149f8bf86..11c985d1ff 100644 --- a/frappe/desk/listview.py +++ b/frappe/desk/listview.py @@ -37,7 +37,7 @@ def get_group_by_count(doctype: str, current_filters: str, field: str) -> List[D ToDo = DocType("ToDo") User = DocType("User") count = Count("*").as_("count") - filtered_records = frappe.db.query.build_conditions(doctype, current_filters).select("name") + filtered_records = frappe.qb.engine.build_conditions(doctype, current_filters).select("name") return ( frappe.qb.from_(ToDo) diff --git a/frappe/tests/test_db_query.py b/frappe/tests/test_db_query.py index c1b2e05266..3a4e5b72bd 100644 --- a/frappe/tests/test_db_query.py +++ b/frappe/tests/test_db_query.py @@ -143,7 +143,7 @@ class TestReportview(unittest.TestCase): ) def test_none_filter(self): - query = frappe.db.query.get_sql("DocType", fields="name", filters={"restrict_to_domain": None}) + query = frappe.qb.engine.get_sql("DocType", fields="name", filters={"restrict_to_domain": None}) sql = str(query).replace("`", "").replace('"', "") condition = "restrict_to_domain IS NULL" self.assertIn(condition, sql) diff --git a/frappe/tests/test_query.py b/frappe/tests/test_query.py index d7190fe7ae..dd74d5ad18 100644 --- a/frappe/tests/test_query.py +++ b/frappe/tests/test_query.py @@ -9,7 +9,7 @@ class TestQuery(unittest.TestCase): @run_only_if(db_type_is.MARIADB) def test_multiple_tables_in_filters(self): self.assertEqual( - frappe.db.query.get_sql( + frappe.qb.engine.get_sql( "DocType", ["*"], [ @@ -22,14 +22,14 @@ class TestQuery(unittest.TestCase): def test_string_fields(self): self.assertEqual( - frappe.db.query.get_sql("User", fields="name, email", filters={"name": "Administrator"}), + frappe.qb.engine.get_sql("User", fields="name, email", filters={"name": "Administrator"}), frappe.qb.from_("User") .select(Field("name"), Field("email")) .where(Field("name") == "Administrator"), ) self.assertEqual( - frappe.db.query.get_sql("User", fields=["name, email"], filters={"name": "Administrator"}), + frappe.qb.engine.get_sql("User", fields=["name, email"], filters={"name": "Administrator"}), frappe.qb.from_("User") .select(Field("name"), Field("email")) .where(Field("name") == "Administrator"), @@ -39,35 +39,35 @@ class TestQuery(unittest.TestCase): from frappe.query_builder.functions import Count self.assertEqual( - frappe.db.query.get_sql("User", fields="Count(name)", filters={}), + frappe.qb.engine.get_sql("User", fields="Count(name)", filters={}), frappe.qb.from_("User").select(Count(Field("name"))), ) self.assertEqual( - frappe.db.query.get_sql("User", fields="Count(name), Max(name)", filters={}), + frappe.qb.engine.get_sql("User", fields="Count(name), Max(name)", filters={}), frappe.qb.from_("User").select(Count(Field("name")), Max(Field("name"))), ) self.assertEqual( - frappe.db.query.get_sql("User", fields=["Count(name)", "Max(name)"], filters={}), + frappe.qb.engine.get_sql("User", fields=["Count(name)", "Max(name)"], filters={}), frappe.qb.from_("User").select(Count(Field("name")), Max(Field("name"))), ) self.assertEqual( - frappe.db.query.get_sql("User", fields=[Count("*")], filters={}), + frappe.qb.engine.get_sql("User", fields=[Count("*")], filters={}), frappe.qb.from_("User").select(Count(Field("name")), Max(Field("name"))), ) def test_qb_fields(self): user_doctype = frappe.qb.DocType("User") self.assertEqual( - frappe.db.query.get_sql( + frappe.qb.engine.get_sql( user_doctype, fields=[user_doctype.name, user_doctype.email], filters={} ), frappe.qb.from_(user_doctype).select(user_doctype.name, user_doctype.email), ) self.assertEqual( - frappe.db.query.get_sql(user_doctype, fields=user_doctype.email, filters={}), + frappe.qb.engine.get_sql(user_doctype, fields=user_doctype.email, filters={}), frappe.qb.from_(user_doctype).select(user_doctype.email), ) diff --git a/frappe/utils/goal.py b/frappe/utils/goal.py index fb348496da..9273b83cbf 100644 --- a/frappe/utils/goal.py +++ b/frappe/utils/goal.py @@ -25,7 +25,7 @@ def get_monthly_results( date_format = "%m-%Y" if frappe.db.db_type != "postgres" else "MM-YYYY" return dict( - frappe.db.query.build_conditions(table=goal_doctype, filters=filters) + frappe.qb.engine.build_conditions(table=goal_doctype, filters=filters) .select( DateFormat(Table[date_col], date_format).as_("month_year"), Function(aggregation, goal_field), From 6db6be1f3c8b8dc9e8e458c6191e5e91e8de8943 Mon Sep 17 00:00:00 2001 From: Aradhya Date: Tue, 21 Jun 2022 18:42:06 +0530 Subject: [PATCH 074/101] refactor: frappe.qb.engine * Small fixes in set_fields and clean code * Optimize casefolds * Fixed functions passed in List * get_sql => get_query - more expressive, less confusion * Updated tests --- frappe/database/database.py | 10 ++-- frappe/database/query.py | 94 +++++++++++++++++++---------------- frappe/tests/test_db_query.py | 2 +- frappe/tests/test_query.py | 43 ++++++++-------- 4 files changed, 79 insertions(+), 70 deletions(-) diff --git a/frappe/database/database.py b/frappe/database/database.py index fd94bcfe12..b418b5e9f6 100644 --- a/frappe/database/database.py +++ b/frappe/database/database.py @@ -586,7 +586,7 @@ class Database(object): return [map(values.get, fields)] else: - r = frappe.qb.engine.get_sql( + r = frappe.qb.engine.get_query( "Singles", filters={"field": ("in", tuple(fields)), "doctype": doctype}, fields=["field", "value"], @@ -616,7 +616,7 @@ class Database(object): # Get coulmn and value of the single doctype Accounts Settings account_settings = frappe.db.get_singles_dict("Accounts Settings") """ - queried_result = frappe.qb.engine.get_sql( + queried_result = frappe.qb.engine.get_query( "Singles", filters={"doctype": doctype}, fields=["field", "value"], @@ -672,7 +672,7 @@ class Database(object): if cache and fieldname in self.value_cache[doctype]: return self.value_cache[doctype][fieldname] - val = frappe.qb.engine.get_sql( + val = frappe.qb.engine.get_query( table="Singles", filters={"doctype": doctype, "field": fieldname}, fields="value", @@ -714,7 +714,7 @@ class Database(object): ): field_objects = [] - query = frappe.qb.engine.get_sql( + query = frappe.qb.engine.get_query( table=doctype, filters=filters, orderby=order_by, @@ -1025,7 +1025,7 @@ class Database(object): cache_count = frappe.cache().get_value("doctype:count:{}".format(dt)) if cache_count is not None: return cache_count - query = frappe.qb.engine.get_sql(table=dt, filters=filters, fields=Count("*"), distinct=distinct) + query = frappe.qb.engine.get_query(table=dt, filters=filters, fields=Count("*"), distinct=distinct) count = self.sql(query, debug=debug)[0][0] if not filters and cache: frappe.cache().set_value("doctype:count:{}".format(dt), count, expires_in_sec=86400) diff --git a/frappe/database/query.py b/frappe/database/query.py index abf5c6936f..155cc99aab 100644 --- a/frappe/database/query.py +++ b/frappe/database/query.py @@ -8,10 +8,13 @@ import frappe from frappe import _ from frappe.boot import get_additional_filters_from_hooks from frappe.model.db_query import get_timespan_date_range -from frappe.query_builder import Criterion, Field, Order, Table +from frappe.query_builder import Criterion, Field, Order, Table, functions +from frappe.query_builder.functions import SqlFunctions TAB_PATTERN = re.compile("^tab") WORDS_PATTERN = re.compile(r"\w+") +BRACKETS_PATTERN = re.compile(r"\(.*?\)") +SQL_FUNCTIONS = [sql_function.value for sql_function in SqlFunctions] def like(key: Field, value: str) -> frappe.qb: @@ -144,6 +147,13 @@ def change_orderby(order: str): return order[0], Order.desc +def literal_eval_(literal): + try: + return literal_eval(literal) + except (ValueError, SyntaxError): + return literal + + # default operators OPERATOR_MAP: Dict[str, Callable] = { "+": operator.add, @@ -364,6 +374,34 @@ class Engine: return criterion + def get_function_objects(self, fields): + func = fields.split("(")[0].casefold().split() + func = [f for f in func if f in SQL_FUNCTIONS][0] + args = fields[len(func) + 1 : fields.index(")")].split(",") + args = [ + Field(literal_eval_((arg.strip()))) if "*" not in args else literal_eval_((arg.strip())) + for arg in args + ] + return getattr(functions, func.capitalize())(*args) + + def function_objects_to_fields(self, fields, is_str: bool): + if is_str: + functions = "" + for func in SQL_FUNCTIONS: + if f"{func}(" in fields: + functions = str(func) + str(BRACKETS_PATTERN.findall(fields)[0]) + return [self.get_function_objects(functions)] + if not functions: + return [] + else: + functions = [] + for field in fields: + field = field.casefold() if isinstance(field, str) else field + if not issubclass(type(field), Criterion): + if any([func in field and f"{func}(" in field for func in SQL_FUNCTIONS]): + functions.append(field) + return [self.get_function_objects(function) for function in functions] + def set_fields(self, fields, **kwargs): fields = kwargs.get("pluck") if kwargs.get("pluck") else fields or "name" if isinstance(fields, list) and None in fields and Field not in fields: @@ -375,57 +413,26 @@ class Engine: is_list = False is_str = isinstance(fields, str) - - def add_functions(fields): - from frappe.query_builder.functions import SqlFunctions - - sql_functions = [sql_function.value for sql_function in SqlFunctions] - - def get_function_objects(fields): - from frappe.query_builder import functions - - def literal_eval_(literal): - try: - return literal_eval(literal) - except (ValueError, SyntaxError): - return literal - - func = fields.split("(")[0].casefold().split() - func = [f for f in func if f in sql_functions][0] - args = fields[len(func) + 1 : fields.index(")")].split(",") - args = [Field(literal_eval_((arg.strip()))) for arg in args] - return getattr(functions, func.capitalize())(*args) - - if is_str and any( - [func in fields.casefold() and f"{func}(" in fields.casefold() for func in sql_functions] - ): - function_objects = [] - return function_objects or [get_function_objects(fields)] - else: - functions = [] - for field in fields: - if not issubclass(type(field), Criterion): - if any( - [func in field.casefold() and f"{func}(" in field.casefold() for func in sql_functions] - ): - functions.append(field.casefold()) - return [get_function_objects(function) for function in functions] + if is_str: + fields = fields.casefold() function_objects = ( - add_functions(fields=fields) if not issubclass(type(fields), Criterion) else [] + self.function_objects_to_fields(fields=fields, is_str=is_str) + if not issubclass(type(fields), Criterion) + else [] ) + for function in function_objects: if is_str: - fields = re.sub( - r"\(.*?\)", "", fields.casefold().replace(str(type(function).__name__).strip().casefold(), "") + fields = BRACKETS_PATTERN.sub( + "", fields.replace(str(type(function).__name__).strip().casefold(), "") ) - else: updated_fields = [] for field in fields: if isinstance(field, str): updated_fields.append( - re.sub(r"\(.*?\)", "", field) + BRACKETS_PATTERN.sub("", field) .strip() .casefold() .replace(str(type(function).__name__).strip().casefold(), "") @@ -433,11 +440,12 @@ class Engine: else: updated_fields.append(field) - fields = updated_fields + fields = [field for field in updated_fields if field] if is_str and "," in fields: fields = fields.split(",") fields = [field.replace(" ", "") if "as" not in field else field for field in fields] + is_list, is_str = True, False if is_str: if fields == "*": @@ -469,7 +477,7 @@ class Engine: fields.extend(function_objects) return fields - def get_sql( + def get_query( self, table: str, fields: Union[List, Tuple], diff --git a/frappe/tests/test_db_query.py b/frappe/tests/test_db_query.py index 3a4e5b72bd..8727951f4a 100644 --- a/frappe/tests/test_db_query.py +++ b/frappe/tests/test_db_query.py @@ -143,7 +143,7 @@ class TestReportview(unittest.TestCase): ) def test_none_filter(self): - query = frappe.qb.engine.get_sql("DocType", fields="name", filters={"restrict_to_domain": None}) + query = frappe.qb.engine.get_query("DocType", fields="name", filters={"restrict_to_domain": None}) sql = str(query).replace("`", "").replace('"', "") condition = "restrict_to_domain IS NULL" self.assertIn(condition, sql) diff --git a/frappe/tests/test_query.py b/frappe/tests/test_query.py index dd74d5ad18..06550b44a4 100644 --- a/frappe/tests/test_query.py +++ b/frappe/tests/test_query.py @@ -9,7 +9,7 @@ class TestQuery(unittest.TestCase): @run_only_if(db_type_is.MARIADB) def test_multiple_tables_in_filters(self): self.assertEqual( - frappe.qb.engine.get_sql( + frappe.qb.engine.get_query( "DocType", ["*"], [ @@ -22,52 +22,53 @@ class TestQuery(unittest.TestCase): def test_string_fields(self): self.assertEqual( - frappe.qb.engine.get_sql("User", fields="name, email", filters={"name": "Administrator"}), + frappe.qb.engine.get_query( + "User", fields="name, email", filters={"name": "Administrator"} + ).get_sql(), frappe.qb.from_("User") .select(Field("name"), Field("email")) - .where(Field("name") == "Administrator"), + .where(Field("name") == "Administrator") + .get_sql(), ) self.assertEqual( - frappe.qb.engine.get_sql("User", fields=["name, email"], filters={"name": "Administrator"}), + frappe.qb.engine.get_query( + "User", fields=["name, email"], filters={"name": "Administrator"} + ).get_sql(), frappe.qb.from_("User") .select(Field("name"), Field("email")) - .where(Field("name") == "Administrator"), + .where(Field("name") == "Administrator") + .get_sql(), ) def test_functions_fields(self): from frappe.query_builder.functions import Count self.assertEqual( - frappe.qb.engine.get_sql("User", fields="Count(name)", filters={}), - frappe.qb.from_("User").select(Count(Field("name"))), + frappe.qb.engine.get_query("User", fields="Count(name)", filters={}).get_sql(), + frappe.qb.from_("User").select(Count(Field("name"))).get_sql(), ) self.assertEqual( - frappe.qb.engine.get_sql("User", fields="Count(name), Max(name)", filters={}), - frappe.qb.from_("User").select(Count(Field("name")), Max(Field("name"))), + frappe.qb.engine.get_query("User", fields=["Count(name)", "Max(name)"], filters={}).get_sql(), + frappe.qb.from_("User").select(Count(Field("name")), Max(Field("name"))).get_sql(), ) self.assertEqual( - frappe.qb.engine.get_sql("User", fields=["Count(name)", "Max(name)"], filters={}), - frappe.qb.from_("User").select(Count(Field("name")), Max(Field("name"))), - ) - - self.assertEqual( - frappe.qb.engine.get_sql("User", fields=[Count("*")], filters={}), - frappe.qb.from_("User").select(Count(Field("name")), Max(Field("name"))), + frappe.qb.engine.get_query("User", fields=[Count("*")], filters={}).get_sql(), + frappe.qb.from_("User").select(Count("*")).get_sql(), ) def test_qb_fields(self): user_doctype = frappe.qb.DocType("User") self.assertEqual( - frappe.qb.engine.get_sql( + frappe.qb.engine.get_query( user_doctype, fields=[user_doctype.name, user_doctype.email], filters={} - ), - frappe.qb.from_(user_doctype).select(user_doctype.name, user_doctype.email), + ).get_sql(), + frappe.qb.from_(user_doctype).select(user_doctype.name, user_doctype.email).get_sql(), ) self.assertEqual( - frappe.qb.engine.get_sql(user_doctype, fields=user_doctype.email, filters={}), - frappe.qb.from_(user_doctype).select(user_doctype.email), + frappe.qb.engine.get_query(user_doctype, fields=user_doctype.email, filters={}).get_sql(), + frappe.qb.from_(user_doctype).select(user_doctype.email).get_sql(), ) From 303d94494d24d88f8957afb66217ac171a251771 Mon Sep 17 00:00:00 2001 From: Aradhya Date: Wed, 22 Jun 2022 16:58:27 +0530 Subject: [PATCH 075/101] refactor: atomic functions & removed complicated checks Co-authored-by: gavin --- frappe/database/query.py | 118 +++++++++++++++++++++------------------ 1 file changed, 64 insertions(+), 54 deletions(-) diff --git a/frappe/database/query.py b/frappe/database/query.py index 155cc99aab..60eeaee8c2 100644 --- a/frappe/database/query.py +++ b/frappe/database/query.py @@ -2,7 +2,7 @@ import operator import re from ast import literal_eval from functools import cached_property -from typing import Any, Callable, Dict, List, Tuple, Union +from typing import TYPE_CHECKING, Any, Callable, Dict, List, Tuple, Union import frappe from frappe import _ @@ -13,9 +13,12 @@ from frappe.query_builder.functions import SqlFunctions TAB_PATTERN = re.compile("^tab") WORDS_PATTERN = re.compile(r"\w+") -BRACKETS_PATTERN = re.compile(r"\(.*?\)") +BRACKETS_PATTERN = re.compile(r"\(.*?\)|$") SQL_FUNCTIONS = [sql_function.value for sql_function in SqlFunctions] +if TYPE_CHECKING: + from pypika.functions import Function + def like(key: Field, value: str) -> frappe.qb: """Wrapper method for `LIKE` @@ -374,77 +377,84 @@ class Engine: return criterion - def get_function_objects(self, fields): - func = fields.split("(")[0].casefold().split() - func = [f for f in func if f in SQL_FUNCTIONS][0] - args = fields[len(func) + 1 : fields.index(")")].split(",") - args = [ - Field(literal_eval_((arg.strip()))) if "*" not in args else literal_eval_((arg.strip())) - for arg in args - ] - return getattr(functions, func.capitalize())(*args) + def get_function_object(self, field: str) -> "Function": + """Expects field to look like 'SUM(*)' or 'name' or something similar. Returns PyPika Function object""" + func = field.split("(", maxsplit=1)[0].capitalize() + args_start, args_end = len(func) + 1, field.index(")") + args = field[args_start:args_end].split(",") - def function_objects_to_fields(self, fields, is_str: bool): - if is_str: - functions = "" - for func in SQL_FUNCTIONS: - if f"{func}(" in fields: - functions = str(func) + str(BRACKETS_PATTERN.findall(fields)[0]) - return [self.get_function_objects(functions)] - if not functions: - return [] - else: - functions = [] - for field in fields: - field = field.casefold() if isinstance(field, str) else field - if not issubclass(type(field), Criterion): - if any([func in field and f"{func}(" in field for func in SQL_FUNCTIONS]): - functions.append(field) - return [self.get_function_objects(function) for function in functions] + to_cast = "*" not in args + _args = [] - def set_fields(self, fields, **kwargs): - fields = kwargs.get("pluck") if kwargs.get("pluck") else fields or "name" - if isinstance(fields, list) and None in fields and Field not in fields: - return None + for arg in args: + field = literal_eval_(arg.strip()) + if to_cast: + field = Field(field) + _args.append(field) - is_list = isinstance(fields, (list, tuple, set)) - if is_list and len(fields) == 1: - fields = fields[0] - is_list = False + return getattr(functions, func)(*_args) - is_str = isinstance(fields, str) - if is_str: - fields = fields.casefold() + def function_objects_from_string(self, fields): + functions = "" + for func in SQL_FUNCTIONS: + if f"{func}(" in fields: + functions = str(func) + str(BRACKETS_PATTERN.search(fields).group()) + return [self.get_function_object(functions)] + if not functions: + return [] - function_objects = ( - self.function_objects_to_fields(fields=fields, is_str=is_str) - if not issubclass(type(fields), Criterion) - else [] - ) + def function_objects_from_list(self, fields): + functions = [] + for field in fields: + field = field.casefold() if isinstance(field, str) else field + if not issubclass(type(field), Criterion): + if any([func in field and f"{func}(" in field for func in SQL_FUNCTIONS]): + functions.append(field) + return [self.get_function_object(function) for function in functions] + def remove_string_functions(self, fields, function_objects): + """Remove string functions from fields which have already been converted to function objects""" for function in function_objects: - if is_str: - fields = BRACKETS_PATTERN.sub( - "", fields.replace(str(type(function).__name__).strip().casefold(), "") - ) + if isinstance(fields, str): + fields = BRACKETS_PATTERN.sub("", fields.replace(function.name.casefold(), "")) else: updated_fields = [] for field in fields: if isinstance(field, str): updated_fields.append( - BRACKETS_PATTERN.sub("", field) - .strip() - .casefold() - .replace(str(type(function).__name__).strip().casefold(), "") + BRACKETS_PATTERN.sub("", field).strip().casefold().replace(function.name.casefold(), "") ) else: updated_fields.append(field) fields = [field for field in updated_fields if field] + return fields + + def set_fields(self, fields, **kwargs): + fields = kwargs.get("pluck") if kwargs.get("pluck") else fields or "name" + if isinstance(fields, list) and None in fields and Field not in fields: + return None + + function_objects = [] + + is_list = isinstance(fields, (list, tuple, set)) + if is_list and len(fields) == 1: + fields = fields[0] + is_list = False + + if is_list: + function_objects += self.function_objects_from_list(fields=fields) + + is_str = isinstance(fields, str) + if is_str: + fields = fields.casefold() + function_objects += self.function_objects_from_string(fields=fields) + + fields = self.remove_string_functions(fields, function_objects) + if is_str and "," in fields: - fields = fields.split(",") - fields = [field.replace(" ", "") if "as" not in field else field for field in fields] + fields = [field.replace(" ", "") if "as" not in field else field for field in fields.split(",")] is_list, is_str = True, False if is_str: From ee18694b1b1eb9bff1f2cf161976c201ba54bc75 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Wed, 29 Jun 2022 10:40:21 +0530 Subject: [PATCH 076/101] test(fix): Import Max for test_functions_fields --- frappe/tests/test_query.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/tests/test_query.py b/frappe/tests/test_query.py index 06550b44a4..e7682a0d0c 100644 --- a/frappe/tests/test_query.py +++ b/frappe/tests/test_query.py @@ -42,7 +42,7 @@ class TestQuery(unittest.TestCase): ) def test_functions_fields(self): - from frappe.query_builder.functions import Count + from frappe.query_builder.functions import Count, Max self.assertEqual( frappe.qb.engine.get_query("User", fields="Count(name)", filters={}).get_sql(), From bd3d7bf3edada674da5ffdb97c408fd3a9cdc619 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Wed, 29 Jun 2022 10:44:55 +0530 Subject: [PATCH 077/101] ci: Run test builds on min requirement PY38 Since version pinned in pyproject.toml is 38 & we've been running on 39, we've pushed a few incompatible changes since :crie: --- .github/workflows/patch-mariadb-tests.yml | 2 +- .github/workflows/publish-assets-develop.yml | 2 +- .github/workflows/publish-assets-releases.yml | 2 +- .github/workflows/server-mariadb-tests.yml | 2 +- .github/workflows/server-postgres-tests.yml | 2 +- .github/workflows/ui-tests.yml | 2 +- frappe/utils/boilerplate.py | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/patch-mariadb-tests.yml b/.github/workflows/patch-mariadb-tests.yml index 60d0ce60af..8cfae52525 100644 --- a/.github/workflows/patch-mariadb-tests.yml +++ b/.github/workflows/patch-mariadb-tests.yml @@ -33,7 +33,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: '3.9' + python-version: '3.8' - name: Setup Node uses: actions/setup-node@v3 diff --git a/.github/workflows/publish-assets-develop.yml b/.github/workflows/publish-assets-develop.yml index 037c8c26eb..bd387a1c06 100644 --- a/.github/workflows/publish-assets-develop.yml +++ b/.github/workflows/publish-assets-develop.yml @@ -18,7 +18,7 @@ jobs: node-version: 14 - uses: actions/setup-python@v4 with: - python-version: '3.9' + python-version: '3.8' - name: Set up bench and build assets run: | npm install -g yarn diff --git a/.github/workflows/publish-assets-releases.yml b/.github/workflows/publish-assets-releases.yml index 594229a156..e3f316fd57 100644 --- a/.github/workflows/publish-assets-releases.yml +++ b/.github/workflows/publish-assets-releases.yml @@ -21,7 +21,7 @@ jobs: python-version: '12.x' - uses: actions/setup-python@v4 with: - python-version: '3.9' + python-version: '3.8' - name: Set up bench and build assets run: | npm install -g yarn diff --git a/.github/workflows/server-mariadb-tests.yml b/.github/workflows/server-mariadb-tests.yml index 51d379d5db..a32e18ae7b 100644 --- a/.github/workflows/server-mariadb-tests.yml +++ b/.github/workflows/server-mariadb-tests.yml @@ -42,7 +42,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: '3.9' + python-version: '3.8' - name: Check if build should be run id: check-build diff --git a/.github/workflows/server-postgres-tests.yml b/.github/workflows/server-postgres-tests.yml index d93edad0ec..8ff56f74f3 100644 --- a/.github/workflows/server-postgres-tests.yml +++ b/.github/workflows/server-postgres-tests.yml @@ -45,7 +45,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: '3.9' + python-version: '3.8' - name: Check if build should be run id: check-build diff --git a/.github/workflows/ui-tests.yml b/.github/workflows/ui-tests.yml index 09b2a3caf8..96f3869788 100644 --- a/.github/workflows/ui-tests.yml +++ b/.github/workflows/ui-tests.yml @@ -41,7 +41,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: '3.9' + python-version: '3.8' - name: Check if build should be run id: check-build diff --git a/frappe/utils/boilerplate.py b/frappe/utils/boilerplate.py index edb742feb4..de55a9b2ea 100644 --- a/frappe/utils/boilerplate.py +++ b/frappe/utils/boilerplate.py @@ -478,7 +478,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v2 with: - python-version: 3.9 + python-version: 3.8 - name: Setup Node uses: actions/setup-node@v2 From 091debb14fbcd646eb6569066309723a91d239bb Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Wed, 29 Jun 2022 10:56:05 +0530 Subject: [PATCH 078/101] chore: Stringify incompatible typing hints --- frappe/email/queue.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/email/queue.py b/frappe/email/queue.py index 45abe0374a..2c3e0ee011 100755 --- a/frappe/email/queue.py +++ b/frappe/email/queue.py @@ -69,7 +69,7 @@ def get_emails_sent_today(email_account=None): def get_unsubscribe_message( unsubscribe_message: str, expose_recipients: str -) -> frappe._dict[str, str]: +) -> "frappe._dict[str, str]": unsubscribe_message = unsubscribe_message or _("Unsubscribe") unsubscribe_link = f'{unsubscribe_message}' unsubscribe_html = _("{0} to stop receiving emails of this type").format(unsubscribe_link) From 069b0ec650ae8ba81a23ee4f6cfc62af4664a0ac Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 29 Jun 2022 11:01:55 +0530 Subject: [PATCH 079/101] chore: py38 safe typehint --- frappe/email/queue.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/email/queue.py b/frappe/email/queue.py index 45abe0374a..2c3e0ee011 100755 --- a/frappe/email/queue.py +++ b/frappe/email/queue.py @@ -69,7 +69,7 @@ def get_emails_sent_today(email_account=None): def get_unsubscribe_message( unsubscribe_message: str, expose_recipients: str -) -> frappe._dict[str, str]: +) -> "frappe._dict[str, str]": unsubscribe_message = unsubscribe_message or _("Unsubscribe") unsubscribe_link = f'{unsubscribe_message}' unsubscribe_html = _("{0} to stop receiving emails of this type").format(unsubscribe_link) From 6862c104032626c9dbd4d90334754d060d585206 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Wed, 29 Jun 2022 11:04:01 +0530 Subject: [PATCH 080/101] ci: PY38 compatible roulette --- .github/helper/roulette.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/helper/roulette.py b/.github/helper/roulette.py index b859b87047..ad2fd829dd 100644 --- a/.github/helper/roulette.py +++ b/.github/helper/roulette.py @@ -5,10 +5,10 @@ import shlex import subprocess import sys import urllib.request -from functools import cache +from functools import lru_cache -@cache +@lru_cache(maxsize=None) def fetch_pr_data(pr_number, repo, endpoint): api_url = f"https://api.github.com/repos/{repo}/pulls/{pr_number}" From 5f0555d982fd8b13d430136845152eff9c656865 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Wed, 29 Jun 2022 11:58:53 +0530 Subject: [PATCH 081/101] fix: Translate strings in public folders too --- frappe/translate.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/frappe/translate.py b/frappe/translate.py index 460c7db9b0..5dbbbd31f2 100644 --- a/frappe/translate.py +++ b/frappe/translate.py @@ -15,7 +15,7 @@ import operator import os import re from csv import reader -from typing import List, Tuple, Union +from typing import Dict, List, Optional, Tuple, Union from pypika.terms import PseudoColumn @@ -149,13 +149,12 @@ def set_default_language(lang): def get_lang_dict(): """Returns all languages in dict format, full name is the key e.g. `{"english":"en"}`""" - result = dict( + return dict( frappe.get_all("Language", fields=["language_name", "name"], order_by="modified", as_list=True) ) - return result -def get_dict(fortype, name=None): +def get_dict(fortype: str, name: Optional[str] = None) -> Dict: """Returns translation dict for a type of object. :param fortype: must be one of `doctype`, `page`, `report`, `include`, `jsfile`, `boot` @@ -206,7 +205,7 @@ def get_dict(fortype, name=None): translation_assets[asset_key] = message_dict cache.hset("translation_assets", frappe.local.lang, translation_assets, shared=True) - translation_map = translation_assets[asset_key] + translation_map: Dict = translation_assets[asset_key] translation_map.update(get_user_translations(frappe.local.lang)) @@ -249,13 +248,13 @@ def make_dict_from_messages(messages, full_dict=None, load_user_translation=True return out -def get_lang_js(fortype, name): +def get_lang_js(fortype: str, name: str) -> str: """Returns code snippet to be appended at the end of a JS script. :param fortype: Type of object, e.g. `DocType` :param name: Document name """ - return "\n\n$.extend(frappe._messages, %s)" % json.dumps(get_dict(fortype, name)) + return f"\n\n$.extend(frappe._messages, {json.dumps(get_dict(fortype, name))})" def get_full_dict(lang): @@ -634,10 +633,10 @@ def get_server_messages(app): inside an app""" messages = [] file_extensions = (".py", ".html", ".js", ".vue") - for basepath, folders, files in os.walk(frappe.get_pymodule_path(app)): - for dontwalk in (".git", "public", "locale"): - if dontwalk in folders: - folders.remove(dontwalk) + app_walk = os.walk(frappe.get_pymodule_path(app)) + + for basepath, folders, files in app_walk: + folders[:] = [folder for folder in folders if folder not in {".git", "__pycache__"}] for f in files: f = frappe.as_unicode(f) From a15411d1e18477f980838f421477628e60d0e2bc Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Wed, 29 Jun 2022 12:53:49 +0530 Subject: [PATCH 082/101] fix: Skip invalid field in get_print_settings_to_show --- frappe/printing/page/print/print.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frappe/printing/page/print/print.py b/frappe/printing/page/print/print.py index 82ad22656d..baf98438cd 100644 --- a/frappe/printing/page/print/print.py +++ b/frappe/printing/page/print/print.py @@ -14,6 +14,8 @@ def get_print_settings_to_show(doctype, docname): print_settings_fields = [] for fieldname in fields: df = print_settings.meta.get_field(fieldname) + if not df: + continue df.default = print_settings.get(fieldname) print_settings_fields.append(df) From 683e9a380e09e402eb93e7d84ae5e1b925cb5067 Mon Sep 17 00:00:00 2001 From: Ritwik Puri Date: Wed, 29 Jun 2022 14:29:39 +0530 Subject: [PATCH 083/101] fix: escape comma from brazilian portuguese translation (#17349) --- frappe/translations/pt-BR.csv | 2 +- frappe/translations/pt_br.csv | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/translations/pt-BR.csv b/frappe/translations/pt-BR.csv index 49c16ee634..d4dfe920ae 100644 --- a/frappe/translations/pt-BR.csv +++ b/frappe/translations/pt-BR.csv @@ -2473,7 +2473,7 @@ There should remain at least one System Manager,Não deve permanecer pelo menos There was an error saving filters,Houve um erro ao salvar os filtros, There were errors,Ocorreram erros, There were errors while creating the document. Please try again.,"Houve erros ao criar o documento. Por favor, tente novamente.", -There were errors while sending email. Please try again.,Ocorreram erros durante o envio de email. Por favor, tente novamente., +There were errors while sending email. Please try again.,"Ocorreram erros durante o envio de email. Por favor, tente novamente.", "There were some errors setting the name, please contact the administrator","Houve alguns erros de definir o nome, por favor, entre em contato com o administrador", These values will be automatically updated in transactions and also will be useful to restrict permissions for this user on transactions containing these values.,Esses valores serão atualizados automaticamente em transações e também serão úteis para restringir as permissões para este usuário em operações que contenham esses valores., Third Party Apps,Aplicativos de terceiros, diff --git a/frappe/translations/pt_br.csv b/frappe/translations/pt_br.csv index 49c16ee634..d4dfe920ae 100644 --- a/frappe/translations/pt_br.csv +++ b/frappe/translations/pt_br.csv @@ -2473,7 +2473,7 @@ There should remain at least one System Manager,Não deve permanecer pelo menos There was an error saving filters,Houve um erro ao salvar os filtros, There were errors,Ocorreram erros, There were errors while creating the document. Please try again.,"Houve erros ao criar o documento. Por favor, tente novamente.", -There were errors while sending email. Please try again.,Ocorreram erros durante o envio de email. Por favor, tente novamente., +There were errors while sending email. Please try again.,"Ocorreram erros durante o envio de email. Por favor, tente novamente.", "There were some errors setting the name, please contact the administrator","Houve alguns erros de definir o nome, por favor, entre em contato com o administrador", These values will be automatically updated in transactions and also will be useful to restrict permissions for this user on transactions containing these values.,Esses valores serão atualizados automaticamente em transações e também serão úteis para restringir as permissões para este usuário em operações que contenham esses valores., Third Party Apps,Aplicativos de terceiros, From 3ec6f7f470036c2dc3a67014803b00b8a4cd0a65 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 29 Jun 2022 15:36:18 +0530 Subject: [PATCH 084/101] refactor: merge two workspace2.0 patches --- frappe/patches.txt | 2 -- .../patches/v14_0/reload_workspace_child_tables.py | 13 ------------- frappe/patches/v14_0/update_workspace2.py | 10 ++++++++++ 3 files changed, 10 insertions(+), 15 deletions(-) delete mode 100644 frappe/patches/v14_0/reload_workspace_child_tables.py diff --git a/frappe/patches.txt b/frappe/patches.txt index 40b5a4c881..425468f06c 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -184,14 +184,12 @@ frappe.patches.v13_0.jinja_hook frappe.patches.v13_0.update_notification_channel_if_empty frappe.patches.v13_0.set_first_day_of_the_week execute:frappe.reload_doc('custom', 'doctype', 'custom_field') -execute:frappe.reload_doc('desk', 'doctype', 'workspace_quick_list') frappe.patches.v14_0.update_workspace2 # 20.09.2021 frappe.patches.v14_0.save_ratings_in_fraction #23-12-2021 frappe.patches.v14_0.transform_todo_schema frappe.patches.v14_0.remove_post_and_post_comment frappe.patches.v14_0.reset_creation_datetime frappe.patches.v14_0.remove_is_first_startup -frappe.patches.v14_0.reload_workspace_child_tables frappe.patches.v14_0.clear_long_pending_stale_logs frappe.patches.v14_0.log_settings_migration diff --git a/frappe/patches/v14_0/reload_workspace_child_tables.py b/frappe/patches/v14_0/reload_workspace_child_tables.py deleted file mode 100644 index c22774d94c..0000000000 --- a/frappe/patches/v14_0/reload_workspace_child_tables.py +++ /dev/null @@ -1,13 +0,0 @@ -import frappe - - -def execute(): - child_tables = frappe.get_all( - "DocField", - pluck="options", - filters={"fieldtype": ["in", frappe.model.table_fields], "parent": "Workspace"}, - ) - - for child_table in child_tables: - if child_table != "Has Role": - frappe.reload_doc("desk", "doctype", child_table, force=True) diff --git a/frappe/patches/v14_0/update_workspace2.py b/frappe/patches/v14_0/update_workspace2.py index c6586f46a1..a6c9db503f 100644 --- a/frappe/patches/v14_0/update_workspace2.py +++ b/frappe/patches/v14_0/update_workspace2.py @@ -7,6 +7,16 @@ from frappe import _ def execute(): frappe.reload_doc("desk", "doctype", "workspace", force=True) + child_tables = frappe.get_all( + "DocField", + pluck="options", + filters={"fieldtype": ["in", frappe.model.table_fields], "parent": "Workspace"}, + ) + + for child_table in child_tables: + if child_table != "Has Role": + frappe.reload_doc("desk", "doctype", child_table, force=True) + for seq, workspace in enumerate(frappe.get_all("Workspace", order_by="name asc")): doc = frappe.get_doc("Workspace", workspace.name) content = create_content(doc) From 813dcc1848b6409ac4a734359d54413665c02db8 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 29 Jun 2022 23:30:23 +0530 Subject: [PATCH 085/101] Revert "feat: Adding support to Query engine" --- frappe/__init__.py | 9 +- frappe/database/database.py | 32 +++- frappe/database/query.py | 156 +----------------- .../desk/doctype/number_card/number_card.py | 2 +- frappe/desk/listview.py | 2 +- frappe/query_builder/__init__.py | 1 - frappe/query_builder/builder.py | 9 - frappe/query_builder/functions.py | 22 +-- frappe/query_builder/utils.py | 6 - frappe/tests/test_db_query.py | 2 +- frappe/tests/test_query.py | 58 +------ frappe/utils/goal.py | 2 +- 12 files changed, 44 insertions(+), 257 deletions(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index 0f55854535..063a62c84b 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -22,12 +22,7 @@ from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Union import click from werkzeug.local import Local, release_local -from frappe.query_builder import ( - get_qb_engine, - get_query_builder, - patch_query_aggregation, - patch_query_execute, -) +from frappe.query_builder import get_query_builder, patch_query_aggregation, patch_query_execute from frappe.utils.caching import request_cache from frappe.utils.data import cstr, sbool @@ -245,7 +240,7 @@ def init(site, sites_path=None, new_site=False): local.session = _dict() local.dev_server = _dev_server local.qb = get_query_builder(local.conf.db_type or "mariadb") - local.qb.engine = get_qb_engine() + setup_module_map() if not _qb_patched.get(local.conf.db_type): diff --git a/frappe/database/database.py b/frappe/database/database.py index 3d48f1ebe9..a52264ed6d 100644 --- a/frappe/database/database.py +++ b/frappe/database/database.py @@ -12,7 +12,7 @@ from contextlib import contextmanager from time import time from typing import Dict, List, Optional, Tuple, Union -from pypika.terms import Criterion, NullValue +from pypika.terms import Criterion, NullValue, PseudoColumn import frappe import frappe.defaults @@ -75,6 +75,15 @@ class Database(object): self.password = password or frappe.conf.db_password self.value_cache = {} + @property + def query(self): + if not hasattr(self, "_query"): + from .query import Query + + self._query = Query() + del Query + return self._query + def setup_type_map(self): pass @@ -591,7 +600,7 @@ class Database(object): return [map(values.get, fields)] else: - r = frappe.qb.engine.get_query( + r = self.query.get_sql( "Singles", filters={"field": ("in", tuple(fields)), "doctype": doctype}, fields=["field", "value"], @@ -624,7 +633,7 @@ class Database(object): # Get coulmn and value of the single doctype Accounts Settings account_settings = frappe.db.get_singles_dict("Accounts Settings") """ - queried_result = frappe.qb.engine.get_query( + queried_result = self.query.get_sql( "Singles", filters={"doctype": doctype}, fields=["field", "value"], @@ -697,7 +706,7 @@ class Database(object): if cache and fieldname in self.value_cache[doctype]: return self.value_cache[doctype][fieldname] - val = frappe.qb.engine.get_query( + val = self.query.get_sql( table="Singles", filters={"doctype": doctype, "field": fieldname}, fields="value", @@ -739,7 +748,14 @@ class Database(object): ): field_objects = [] - query = frappe.qb.engine.get_query( + if not isinstance(fields, Criterion): + for field in fields: + if "(" in str(field) or " as " in str(field): + field_objects.append(PseudoColumn(field)) + else: + field_objects.append(field) + + query = self.query.get_sql( table=doctype, filters=filters, orderby=order_by, @@ -849,7 +865,7 @@ class Database(object): frappe.clear_document_cache(dt, docname) else: - query = frappe.qb.engine.build_conditions(table=dt, filters=dn, update=True) + query = self.query.build_conditions(table=dt, filters=dn, update=True) # TODO: Fix this; doesn't work rn - gavin@frappe.io # frappe.cache().hdel_keys(dt, "document_cache") # Workaround: clear all document caches @@ -1050,7 +1066,7 @@ class Database(object): cache_count = frappe.cache().get_value("doctype:count:{}".format(dt)) if cache_count is not None: return cache_count - query = frappe.qb.engine.get_query(table=dt, filters=filters, fields=Count("*"), distinct=distinct) + query = self.query.get_sql(table=dt, filters=filters, fields=Count("*"), distinct=distinct) count = self.sql(query, debug=debug)[0][0] if not filters and cache: frappe.cache().set_value("doctype:count:{}".format(dt), count, expires_in_sec=86400) @@ -1190,7 +1206,7 @@ class Database(object): Doctype name can be passed directly, it will be pre-pended with `tab`. """ filters = filters or kwargs.get("conditions") - query = frappe.qb.engine.build_conditions(table=doctype, filters=filters).delete() + query = self.query.build_conditions(table=doctype, filters=filters).delete() if "debug" not in kwargs: kwargs["debug"] = debug return query.run(**kwargs) diff --git a/frappe/database/query.py b/frappe/database/query.py index 60eeaee8c2..f7cc143cf7 100644 --- a/frappe/database/query.py +++ b/frappe/database/query.py @@ -1,23 +1,16 @@ import operator import re -from ast import literal_eval from functools import cached_property -from typing import TYPE_CHECKING, Any, Callable, Dict, List, Tuple, Union +from typing import Any, Callable, Dict, List, Tuple, Union import frappe from frappe import _ from frappe.boot import get_additional_filters_from_hooks from frappe.model.db_query import get_timespan_date_range -from frappe.query_builder import Criterion, Field, Order, Table, functions -from frappe.query_builder.functions import SqlFunctions +from frappe.query_builder import Criterion, Field, Order, Table TAB_PATTERN = re.compile("^tab") WORDS_PATTERN = re.compile(r"\w+") -BRACKETS_PATTERN = re.compile(r"\(.*?\)|$") -SQL_FUNCTIONS = [sql_function.value for sql_function in SqlFunctions] - -if TYPE_CHECKING: - from pypika.functions import Function def like(key: Field, value: str) -> frappe.qb: @@ -100,7 +93,7 @@ def func_between(key: Field, value: Union[List, Tuple]) -> frappe.qb: def func_is(key, value): "Wrapper for IS" - return key.isnotnull() if value.lower() == "set" else key.isnull() + return Field(key).isnotnull() if value.lower() == "set" else Field(key).isnull() def func_timespan(key: Field, value: str) -> frappe.qb: @@ -150,13 +143,6 @@ def change_orderby(order: str): return order[0], Order.desc -def literal_eval_(literal): - try: - return literal_eval(literal) - except (ValueError, SyntaxError): - return literal - - # default operators OPERATOR_MAP: Dict[str, Callable] = { "+": operator.add, @@ -182,7 +168,7 @@ OPERATOR_MAP: Dict[str, Callable] = { } -class Engine: +class Query: tables: dict = {} @cached_property @@ -252,7 +238,7 @@ class Engine: Returns: conditions (frappe.qb): frappe.qb object """ - if kwargs.get("orderby") and kwargs.get("orderby") != "KEEP_DEFAULT_ORDERING": + if kwargs.get("orderby"): orderby = kwargs.get("orderby") if isinstance(orderby, str) and len(orderby.split()) > 1: for ordby in orderby.split(","): @@ -264,7 +250,6 @@ class Engine: if kwargs.get("limit"): conditions = conditions.limit(kwargs.get("limit")) - conditions = conditions.offset(kwargs.get("offset", 0)) if kwargs.get("distinct"): conditions = conditions.distinct() @@ -272,9 +257,6 @@ class Engine: if kwargs.get("for_update"): conditions = conditions.for_update() - if kwargs.get("groupby"): - conditions = conditions.groupby(kwargs.get("groupby")) - return conditions def misc_query(self, table: str, filters: Union[List, Tuple] = None, **kwargs): @@ -326,10 +308,6 @@ class Engine: conditions = self.add_conditions(conditions, **kwargs) return conditions - for key, value in filters.items(): - if isinstance(value, bool): - filters.update({key: str(int(value))}) - for key in filters: value = filters.get(key) _operator = self.OPERATOR_MAP["="] @@ -339,8 +317,7 @@ class Engine: continue if isinstance(value, (list, tuple)): _operator = self.OPERATOR_MAP[value[0].casefold()] - _value = value[1] if value[1] else ("",) - conditions = conditions.where(_operator(Field(key), _value)) + conditions = conditions.where(_operator(Field(key), value[1])) else: if value is not None: conditions = conditions.where(_operator(Field(key), value)) @@ -377,117 +354,7 @@ class Engine: return criterion - def get_function_object(self, field: str) -> "Function": - """Expects field to look like 'SUM(*)' or 'name' or something similar. Returns PyPika Function object""" - func = field.split("(", maxsplit=1)[0].capitalize() - args_start, args_end = len(func) + 1, field.index(")") - args = field[args_start:args_end].split(",") - - to_cast = "*" not in args - _args = [] - - for arg in args: - field = literal_eval_(arg.strip()) - if to_cast: - field = Field(field) - _args.append(field) - - return getattr(functions, func)(*_args) - - def function_objects_from_string(self, fields): - functions = "" - for func in SQL_FUNCTIONS: - if f"{func}(" in fields: - functions = str(func) + str(BRACKETS_PATTERN.search(fields).group()) - return [self.get_function_object(functions)] - if not functions: - return [] - - def function_objects_from_list(self, fields): - functions = [] - for field in fields: - field = field.casefold() if isinstance(field, str) else field - if not issubclass(type(field), Criterion): - if any([func in field and f"{func}(" in field for func in SQL_FUNCTIONS]): - functions.append(field) - return [self.get_function_object(function) for function in functions] - - def remove_string_functions(self, fields, function_objects): - """Remove string functions from fields which have already been converted to function objects""" - for function in function_objects: - if isinstance(fields, str): - fields = BRACKETS_PATTERN.sub("", fields.replace(function.name.casefold(), "")) - else: - updated_fields = [] - for field in fields: - if isinstance(field, str): - updated_fields.append( - BRACKETS_PATTERN.sub("", field).strip().casefold().replace(function.name.casefold(), "") - ) - else: - updated_fields.append(field) - - fields = [field for field in updated_fields if field] - - return fields - - def set_fields(self, fields, **kwargs): - fields = kwargs.get("pluck") if kwargs.get("pluck") else fields or "name" - if isinstance(fields, list) and None in fields and Field not in fields: - return None - - function_objects = [] - - is_list = isinstance(fields, (list, tuple, set)) - if is_list and len(fields) == 1: - fields = fields[0] - is_list = False - - if is_list: - function_objects += self.function_objects_from_list(fields=fields) - - is_str = isinstance(fields, str) - if is_str: - fields = fields.casefold() - function_objects += self.function_objects_from_string(fields=fields) - - fields = self.remove_string_functions(fields, function_objects) - - if is_str and "," in fields: - fields = [field.replace(" ", "") if "as" not in field else field for field in fields.split(",")] - is_list, is_str = True, False - - if is_str: - if fields == "*": - return fields - if " as " in fields: - fields, reference = fields.split(" as ") - fields = Field(fields).as_(reference) - - if not is_str and fields: - if issubclass(type(fields), Criterion): - return fields - updated_fields = [] - if "*" in fields: - return fields - for field in fields: - if not isinstance(field, Criterion) and field: - if " as " in field: - field, reference = field.split(" as ") - updated_fields.append(Field(field.strip()).as_(reference)) - else: - updated_fields.append(Field(field)) - - fields = updated_fields - - # Need to check instance again since fields modified. - if not isinstance(fields, (list, tuple, set)): - fields = [fields] if fields else [] - - fields.extend(function_objects) - return fields - - def get_query( + def get_sql( self, table: str, fields: Union[List, Tuple], @@ -497,20 +364,15 @@ class Engine: # Clean up state before each query self.tables = {} criterion = self.build_conditions(table, filters, **kwargs) - fields = self.set_fields(kwargs.get("field_objects") or fields, **kwargs) - - join = kwargs.get("join").replace(" ", "_") if kwargs.get("join") else "left_join" if len(self.tables) > 1: primary_table = self.tables[table] del self.tables[table] for table_object in self.tables.values(): - criterion = getattr(criterion, join)(table_object).on( - table_object.parent == primary_table.name - ) + criterion = criterion.left_join(table_object).on(table_object.parent == primary_table.name) if isinstance(fields, (list, tuple)): - query = criterion.select(*fields) + query = criterion.select(*kwargs.get("field_objects", fields)) elif isinstance(fields, Criterion): query = criterion.select(fields) diff --git a/frappe/desk/doctype/number_card/number_card.py b/frappe/desk/doctype/number_card/number_card.py index 8d031aac01..74c8e9eb99 100644 --- a/frappe/desk/doctype/number_card/number_card.py +++ b/frappe/desk/doctype/number_card/number_card.py @@ -204,7 +204,7 @@ def get_cards_for_user(doctype, txt, searchfield, start, page_len, filters): if txt: search_conditions = [numberCard[field].like("%{txt}%".format(txt=txt)) for field in searchfields] - condition_query = frappe.qb.engine.build_conditions(doctype, filters) + condition_query = frappe.db.query.build_conditions(doctype, filters) return ( condition_query.select(numberCard.name, numberCard.label, numberCard.document_type) diff --git a/frappe/desk/listview.py b/frappe/desk/listview.py index 11c985d1ff..5149f8bf86 100644 --- a/frappe/desk/listview.py +++ b/frappe/desk/listview.py @@ -37,7 +37,7 @@ def get_group_by_count(doctype: str, current_filters: str, field: str) -> List[D ToDo = DocType("ToDo") User = DocType("User") count = Count("*").as_("count") - filtered_records = frappe.qb.engine.build_conditions(doctype, current_filters).select("name") + filtered_records = frappe.db.query.build_conditions(doctype, current_filters).select("name") return ( frappe.qb.from_(ToDo) diff --git a/frappe/query_builder/__init__.py b/frappe/query_builder/__init__.py index eb1d9df08f..1bf9ec97d9 100644 --- a/frappe/query_builder/__init__.py +++ b/frappe/query_builder/__init__.py @@ -7,7 +7,6 @@ from frappe.query_builder.terms import ParameterizedFunction, ParameterizedValue from frappe.query_builder.utils import ( Column, DocType, - get_qb_engine, get_query_builder, patch_query_aggregation, patch_query_execute, diff --git a/frappe/query_builder/builder.py b/frappe/query_builder/builder.py index c23d76974c..d2fdeab324 100644 --- a/frappe/query_builder/builder.py +++ b/frappe/query_builder/builder.py @@ -1,5 +1,3 @@ -import typing - from pypika import MySQLQuery, Order, PostgreSQLQuery, terms from pypika.dialects import MySQLQueryBuilder, PostgreSQLQueryBuilder from pypika.queries import QueryBuilder, Schema, Table @@ -15,13 +13,6 @@ class Base: Schema = Schema Table = Table - # Added dynamic type hints for engine attribute - # which is to be assigned later. - if typing.TYPE_CHECKING: - from frappe.database.query import Engine - - engine: Engine - @staticmethod def functions(name: str, *args, **kwargs) -> Function: return Function(name, *args, **kwargs) diff --git a/frappe/query_builder/functions.py b/frappe/query_builder/functions.py index d2debd6da1..f03c139f57 100644 --- a/frappe/query_builder/functions.py +++ b/frappe/query_builder/functions.py @@ -1,9 +1,8 @@ -from enum import Enum - from pypika.functions import * from pypika.terms import Arithmetic, ArithmeticExpression, CustomFunction, Function import frappe +from frappe.database.query import Query from frappe.query_builder.custom import GROUP_CONCAT, MATCH, STRING_AGG, TO_TSVECTOR from frappe.query_builder.utils import ImportMapper, db_type_is @@ -15,11 +14,6 @@ class Concat_ws(Function): super(Concat_ws, self).__init__("CONCAT_WS", *terms, **kwargs) -class Locate(Function): - def __init__(self, *terms, **kwargs): - super(Locate, self).__init__("LOCATE", *terms, **kwargs) - - GroupConcat = ImportMapper({db_type_is.MARIADB: GROUP_CONCAT, db_type_is.POSTGRES: STRING_AGG}) Match = ImportMapper({db_type_is.MARIADB: MATCH, db_type_is.POSTGRES: TO_TSVECTOR}) @@ -79,24 +73,14 @@ class Cast_(Function): def _aggregate(function, dt, fieldname, filters, **kwargs): return ( - frappe.qb.engine.build_conditions(dt, filters) + Query() + .build_conditions(dt, filters) .select(function(PseudoColumn(fieldname))) .run(**kwargs)[0][0] or 0 ) -class SqlFunctions(Enum): - DayOfYear = "dayofyear" - Extract = "extract" - Locate = "locate" - Count = "count" - Sum = "sum" - Avg = "avg" - Max = "max" - Min = "min" - - def _max(dt, fieldname, filters=None, **kwargs): return _aggregate(Max, dt, fieldname, filters, **kwargs) diff --git a/frappe/query_builder/utils.py b/frappe/query_builder/utils.py index b601665dee..10bab38a63 100644 --- a/frappe/query_builder/utils.py +++ b/frappe/query_builder/utils.py @@ -45,12 +45,6 @@ def get_query_builder(type_of_db: str) -> Union[Postgres, MariaDB]: return picks[db] -def get_qb_engine(): - from frappe.database.query import Engine - - return Engine() - - def get_attr(method_string): modulename = ".".join(method_string.split(".")[:-1]) methodname = method_string.split(".")[-1] diff --git a/frappe/tests/test_db_query.py b/frappe/tests/test_db_query.py index 8727951f4a..c1b2e05266 100644 --- a/frappe/tests/test_db_query.py +++ b/frappe/tests/test_db_query.py @@ -143,7 +143,7 @@ class TestReportview(unittest.TestCase): ) def test_none_filter(self): - query = frappe.qb.engine.get_query("DocType", fields="name", filters={"restrict_to_domain": None}) + query = frappe.db.query.get_sql("DocType", fields="name", filters={"restrict_to_domain": None}) sql = str(query).replace("`", "").replace('"', "") condition = "restrict_to_domain IS NULL" self.assertIn(condition, sql) diff --git a/frappe/tests/test_query.py b/frappe/tests/test_query.py index e7682a0d0c..949c3e9433 100644 --- a/frappe/tests/test_query.py +++ b/frappe/tests/test_query.py @@ -1,15 +1,14 @@ import unittest import frappe -from frappe.query_builder import Field from frappe.tests.test_query_builder import db_type_is, run_only_if +@run_only_if(db_type_is.MARIADB) class TestQuery(unittest.TestCase): - @run_only_if(db_type_is.MARIADB) def test_multiple_tables_in_filters(self): self.assertEqual( - frappe.qb.engine.get_query( + frappe.db.query.get_sql( "DocType", ["*"], [ @@ -19,56 +18,3 @@ class TestQuery(unittest.TestCase): ).get_sql(), "SELECT * FROM `tabDocType` LEFT JOIN `tabBOM Update Log` ON `tabBOM Update Log`.`parent`=`tabDocType`.`name` WHERE `tabBOM Update Log`.`name` LIKE 'f%' AND `tabDocType`.`parent`='something'", ) - - def test_string_fields(self): - self.assertEqual( - frappe.qb.engine.get_query( - "User", fields="name, email", filters={"name": "Administrator"} - ).get_sql(), - frappe.qb.from_("User") - .select(Field("name"), Field("email")) - .where(Field("name") == "Administrator") - .get_sql(), - ) - - self.assertEqual( - frappe.qb.engine.get_query( - "User", fields=["name, email"], filters={"name": "Administrator"} - ).get_sql(), - frappe.qb.from_("User") - .select(Field("name"), Field("email")) - .where(Field("name") == "Administrator") - .get_sql(), - ) - - def test_functions_fields(self): - from frappe.query_builder.functions import Count, Max - - self.assertEqual( - frappe.qb.engine.get_query("User", fields="Count(name)", filters={}).get_sql(), - frappe.qb.from_("User").select(Count(Field("name"))).get_sql(), - ) - - self.assertEqual( - frappe.qb.engine.get_query("User", fields=["Count(name)", "Max(name)"], filters={}).get_sql(), - frappe.qb.from_("User").select(Count(Field("name")), Max(Field("name"))).get_sql(), - ) - - self.assertEqual( - frappe.qb.engine.get_query("User", fields=[Count("*")], filters={}).get_sql(), - frappe.qb.from_("User").select(Count("*")).get_sql(), - ) - - def test_qb_fields(self): - user_doctype = frappe.qb.DocType("User") - self.assertEqual( - frappe.qb.engine.get_query( - user_doctype, fields=[user_doctype.name, user_doctype.email], filters={} - ).get_sql(), - frappe.qb.from_(user_doctype).select(user_doctype.name, user_doctype.email).get_sql(), - ) - - self.assertEqual( - frappe.qb.engine.get_query(user_doctype, fields=user_doctype.email, filters={}).get_sql(), - frappe.qb.from_(user_doctype).select(user_doctype.email).get_sql(), - ) diff --git a/frappe/utils/goal.py b/frappe/utils/goal.py index 9273b83cbf..fb348496da 100644 --- a/frappe/utils/goal.py +++ b/frappe/utils/goal.py @@ -25,7 +25,7 @@ def get_monthly_results( date_format = "%m-%Y" if frappe.db.db_type != "postgres" else "MM-YYYY" return dict( - frappe.qb.engine.build_conditions(table=goal_doctype, filters=filters) + frappe.db.query.build_conditions(table=goal_doctype, filters=filters) .select( DateFormat(Table[date_col], date_format).as_("month_year"), Function(aggregation, goal_field), From abfbe3daa49881f47b09df6a5912c63762ef63e2 Mon Sep 17 00:00:00 2001 From: gavin Date: Thu, 30 Jun 2022 12:21:28 +0530 Subject: [PATCH 086/101] build: Use toml defined dev dependencies over txt file (#17356) * build: Use toml defined dev dependencies over txt file * chore: Remove redundant == * ref: https://github.com/frappe/bench/releases/tag/v5.12.1 * Linter's style updates * chore(deps): Bump coverage from 5.5 to ~=6.4.1 --- dev-requirements.txt | 4 ---- pyproject.toml | 6 ++++++ 2 files changed, 6 insertions(+), 4 deletions(-) delete mode 100644 dev-requirements.txt diff --git a/dev-requirements.txt b/dev-requirements.txt deleted file mode 100644 index b67e915a16..0000000000 --- a/dev-requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -coverage==5.5 -Faker~=13.12.1 -pyngrok~=5.0.5 -unittest-xml-reporting~=3.0.4 diff --git a/pyproject.toml b/pyproject.toml index 89be81eaf0..3dc6ab4eb4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -103,3 +103,9 @@ force_grid_wrap = 0 use_parentheses = true ensure_newline_before_comments = true indent = "\t" + +[tool.bench.dev-dependencies] +coverage = "~=6.4.1" +Faker = "~=13.12.1" +pyngrok = "~=5.0.5" +unittest-xml-reporting = "~=3.0.4" From 404d5a3cd788a4375f80c59642ed4173294fcf7b Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Wed, 29 Jun 2022 18:55:56 +0530 Subject: [PATCH 087/101] build!: Bump minimum Python version to 3.10 Given how widespread PY310's usage has become, and how we're just a few months away from PY311 major release. This is a slightly late bumping but necessary to ensure smoother updates & maintenance for Frappe, ERPNext & other apps in the coming years. Almost all people who participated in the pool from the community as well as Frappe team voted (via active telegram groups) PY310 as their preferred minimum requirement for v14. --- .github/workflows/deps-checker.yml | 2 +- .github/workflows/docs-checker.yml | 2 +- .github/workflows/patch-mariadb-tests.yml | 2 +- .github/workflows/publish-assets-develop.yml | 2 +- .github/workflows/publish-assets-releases.yml | 2 +- .github/workflows/server-mariadb-tests.yml | 2 +- .github/workflows/server-postgres-tests.yml | 2 +- .github/workflows/ui-tests.yml | 2 +- frappe/utils/boilerplate.py | 2 +- pyproject.toml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/deps-checker.yml b/.github/workflows/deps-checker.yml index 3f81b5c633..d3fa8c80fb 100644 --- a/.github/workflows/deps-checker.yml +++ b/.github/workflows/deps-checker.yml @@ -16,7 +16,7 @@ jobs: steps: - uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: '3.10' - uses: actions/checkout@v3 - run: pip install pip-audit - run: pip-audit ${GITHUB_WORKSPACE} diff --git a/.github/workflows/docs-checker.yml b/.github/workflows/docs-checker.yml index dade810b64..e61ee6355a 100644 --- a/.github/workflows/docs-checker.yml +++ b/.github/workflows/docs-checker.yml @@ -15,7 +15,7 @@ jobs: - name: 'Setup Environment' uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: '3.10' - name: 'Clone repo' uses: actions/checkout@v3 diff --git a/.github/workflows/patch-mariadb-tests.yml b/.github/workflows/patch-mariadb-tests.yml index 8cfae52525..cebbc25712 100644 --- a/.github/workflows/patch-mariadb-tests.yml +++ b/.github/workflows/patch-mariadb-tests.yml @@ -33,7 +33,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: '3.8' + python-version: '3.10' - name: Setup Node uses: actions/setup-node@v3 diff --git a/.github/workflows/publish-assets-develop.yml b/.github/workflows/publish-assets-develop.yml index bd387a1c06..9219e70eb0 100644 --- a/.github/workflows/publish-assets-develop.yml +++ b/.github/workflows/publish-assets-develop.yml @@ -18,7 +18,7 @@ jobs: node-version: 14 - uses: actions/setup-python@v4 with: - python-version: '3.8' + python-version: '3.10' - name: Set up bench and build assets run: | npm install -g yarn diff --git a/.github/workflows/publish-assets-releases.yml b/.github/workflows/publish-assets-releases.yml index e3f316fd57..09c87984a9 100644 --- a/.github/workflows/publish-assets-releases.yml +++ b/.github/workflows/publish-assets-releases.yml @@ -21,7 +21,7 @@ jobs: python-version: '12.x' - uses: actions/setup-python@v4 with: - python-version: '3.8' + python-version: '3.10' - name: Set up bench and build assets run: | npm install -g yarn diff --git a/.github/workflows/server-mariadb-tests.yml b/.github/workflows/server-mariadb-tests.yml index a32e18ae7b..719972f535 100644 --- a/.github/workflows/server-mariadb-tests.yml +++ b/.github/workflows/server-mariadb-tests.yml @@ -42,7 +42,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: '3.8' + python-version: '3.10' - name: Check if build should be run id: check-build diff --git a/.github/workflows/server-postgres-tests.yml b/.github/workflows/server-postgres-tests.yml index 8ff56f74f3..8f015f43e6 100644 --- a/.github/workflows/server-postgres-tests.yml +++ b/.github/workflows/server-postgres-tests.yml @@ -45,7 +45,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: '3.8' + python-version: '3.10' - name: Check if build should be run id: check-build diff --git a/.github/workflows/ui-tests.yml b/.github/workflows/ui-tests.yml index 96f3869788..421e50ebcc 100644 --- a/.github/workflows/ui-tests.yml +++ b/.github/workflows/ui-tests.yml @@ -41,7 +41,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: '3.8' + python-version: '3.10' - name: Check if build should be run id: check-build diff --git a/frappe/utils/boilerplate.py b/frappe/utils/boilerplate.py index de55a9b2ea..bd4cff9ef9 100644 --- a/frappe/utils/boilerplate.py +++ b/frappe/utils/boilerplate.py @@ -478,7 +478,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v2 with: - python-version: 3.8 + python-version: '3.10' - name: Setup Node uses: actions/setup-node@v2 diff --git a/pyproject.toml b/pyproject.toml index 3dc6ab4eb4..ad97b1eeea 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ authors = [ { name = "Frappe Technologies Pvt Ltd", email = "developers@frappe.io"} ] description = "Metadata driven, full-stack low code web framework" -requires-python = ">=3.8" +requires-python = ">=3.10" readme = "README.md" dynamic = ["version"] dependencies = [ From ab54e72cbc2deea270859ee32420e1123bc3d8d3 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 30 Jun 2022 12:35:09 +0530 Subject: [PATCH 088/101] ci(patch): Switch Python env for each version --- .github/workflows/patch-mariadb-tests.yml | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/.github/workflows/patch-mariadb-tests.yml b/.github/workflows/patch-mariadb-tests.yml index cebbc25712..765d83dd4f 100644 --- a/.github/workflows/patch-mariadb-tests.yml +++ b/.github/workflows/patch-mariadb-tests.yml @@ -31,9 +31,10 @@ jobs: uses: actions/checkout@v3 - name: Setup Python - uses: actions/setup-python@v4 + uses: "gabrielfalcao/pyenv-action@v9" with: - python-version: '3.10' + versions: 3.10:latest, 3.7:latest, 2.7:latest + command: pyenv local 3.10 - name: Setup Node uses: actions/setup-node@v3 @@ -120,15 +121,23 @@ jobs: for version in $(seq 12 13) do echo "Updating to v$version" + if [ $version == 12 ]; then + pyenv local 2.7 + elif [ $version == 13 ]; then + pyenv local 3.7 + fi branch_name="version-$version-hotfix" git fetch --depth 1 upstream $branch_name:$branch_name - git checkout -q -f $branch_name - bench setup requirements --python + + rm -rf ~/frappe-bench/env + bench setup env bench --site test_site migrate done echo "Updating to last commit" git checkout -q -f "$GITHUB_SHA" - bench setup requirements --python + pyenv local 3.10 + rm -rf ~/frappe-bench/env + bench setup env bench --site test_site migrate From 96b3ee4dc3f036c7a76945238f8bfcea65a09cdb Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 30 Jun 2022 13:36:08 +0530 Subject: [PATCH 089/101] fix(webhook): Unbound 'r' through request timeout Errors like `requests.exceptions.ReadTimeout: HTTPSConnectionPool(host='httpbin.org', port=443): Read timed out. (read timeout=5)` ref: https://github.com/frappe/frappe/runs/7126891200?check_suite_focus=true --- frappe/integrations/doctype/webhook/webhook.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/frappe/integrations/doctype/webhook/webhook.py b/frappe/integrations/doctype/webhook/webhook.py index 3f1b60d903..22abcf9a99 100644 --- a/frappe/integrations/doctype/webhook/webhook.py +++ b/frappe/integrations/doctype/webhook/webhook.py @@ -8,6 +8,7 @@ import hashlib import hmac import json from time import sleep +from typing import Dict, Optional from urllib.parse import urlparse import requests @@ -80,8 +81,8 @@ def get_context(doc): return {"doc": doc, "utils": get_safe_globals().get("frappe").get("utils")} -def enqueue_webhook(doc, webhook): - webhook = frappe.get_doc("Webhook", webhook.get("name")) +def enqueue_webhook(doc, webhook) -> None: + webhook: Webhook = frappe.get_doc("Webhook", webhook.get("name")) headers = get_webhook_headers(doc, webhook) data = get_webhook_data(doc, webhook) @@ -98,6 +99,11 @@ def enqueue_webhook(doc, webhook): frappe.logger().debug({"webhook_success": r.text}) log_request(webhook.request_url, headers, data, r) break + + except requests.exceptions.ReadTimeout as e: + frappe.logger().debug({"webhook_error": e, "try": i + 1}) + log_request(webhook.request_url, headers, data) + except Exception as e: frappe.logger().debug({"webhook_error": e, "try": i + 1}) log_request(webhook.request_url, headers, data, r) @@ -108,7 +114,7 @@ def enqueue_webhook(doc, webhook): webhook.log_error("Webhook failed") -def log_request(url, headers, data, res): +def log_request(url: str, headers: Dict, data: Dict, res: Optional[requests.Response] = None): request_log = frappe.get_doc( { "doctype": "Webhook Request Log", From f16a24a777a20e40bb06f23949926b446c1cea38 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 30 Jun 2022 14:45:47 +0530 Subject: [PATCH 090/101] ci: Set pyenv version to 310 before running install step --- .github/workflows/patch-mariadb-tests.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/patch-mariadb-tests.yml b/.github/workflows/patch-mariadb-tests.yml index 765d83dd4f..49437167c3 100644 --- a/.github/workflows/patch-mariadb-tests.yml +++ b/.github/workflows/patch-mariadb-tests.yml @@ -34,7 +34,6 @@ jobs: uses: "gabrielfalcao/pyenv-action@v9" with: versions: 3.10:latest, 3.7:latest, 2.7:latest - command: pyenv local 3.10 - name: Setup Node uses: actions/setup-node@v3 @@ -102,7 +101,9 @@ jobs: - name: Install if: ${{ steps.check-build.outputs.build == 'strawberry' }} - run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh + run: | + pyenv local 3.10 + bash ${GITHUB_WORKSPACE}/.github/helper/install.sh env: DB: mariadb TYPE: server From 4451773daa5ebaa97b2bf30323fa7609ea3f76b1 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 30 Jun 2022 15:00:00 +0530 Subject: [PATCH 091/101] ci: Fetch pyenv installed specific version --- .github/workflows/patch-mariadb-tests.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/patch-mariadb-tests.yml b/.github/workflows/patch-mariadb-tests.yml index 49437167c3..c630b6a1dc 100644 --- a/.github/workflows/patch-mariadb-tests.yml +++ b/.github/workflows/patch-mariadb-tests.yml @@ -102,7 +102,7 @@ jobs: - name: Install if: ${{ steps.check-build.outputs.build == 'strawberry' }} run: | - pyenv local 3.10 + pyenv global $(pyenv versions | grep '3.10') bash ${GITHUB_WORKSPACE}/.github/helper/install.sh env: DB: mariadb @@ -123,9 +123,9 @@ jobs: do echo "Updating to v$version" if [ $version == 12 ]; then - pyenv local 2.7 + pyenv global $(pyenv versions | grep '2.7') elif [ $version == 13 ]; then - pyenv local 3.7 + pyenv global $(pyenv versions | grep '3.7') fi branch_name="version-$version-hotfix" git fetch --depth 1 upstream $branch_name:$branch_name @@ -138,7 +138,7 @@ jobs: echo "Updating to last commit" git checkout -q -f "$GITHUB_SHA" - pyenv local 3.10 + pyenv global $(pyenv versions | grep '3.10') rm -rf ~/frappe-bench/env bench setup env bench --site test_site migrate From f44333a18e0b34979ebea1887c6afb9815200799 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 30 Jun 2022 15:24:03 +0530 Subject: [PATCH 092/101] ci: Use bench commands with verbose option --- .github/helper/install.sh | 6 +++--- .github/workflows/patch-mariadb-tests.yml | 4 ++-- .github/workflows/publish-assets-develop.yml | 2 +- .github/workflows/publish-assets-releases.yml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/helper/install.sh b/.github/helper/install.sh index 3ef7db34f6..be5120ce7a 100644 --- a/.github/helper/install.sh +++ b/.github/helper/install.sh @@ -6,7 +6,7 @@ cd ~ || exit pip install frappe-bench -bench init frappe-bench --skip-assets --python "$(which python)" --frappe-path "${GITHUB_WORKSPACE}" +bench -v init frappe-bench --skip-assets --python "$(which python)" --frappe-path "${GITHUB_WORKSPACE}" mkdir ~/frappe-bench/sites/test_site cp "${GITHUB_WORKSPACE}/.github/helper/consumer_db/$DB.json" ~/frappe-bench/sites/test_site/site_config.json @@ -49,8 +49,8 @@ sed -i 's/^schedule:/# schedule:/g' Procfile if [ "$TYPE" == "server" ]; then sed -i 's/^socketio:/# socketio:/g' Procfile; fi if [ "$TYPE" == "server" ]; then sed -i 's/^redis_socketio:/# redis_socketio:/g' Procfile; fi -if [ "$TYPE" == "ui" ]; then bench setup requirements --node; fi -bench setup requirements --dev +if [ "$TYPE" == "ui" ]; then bench -v setup requirements --node; fi +bench -v setup requirements --dev if [ "$TYPE" == "ui" ]; then sed -i 's/^web: bench serve/web: bench serve --with-coverage/g' Procfile; fi diff --git a/.github/workflows/patch-mariadb-tests.yml b/.github/workflows/patch-mariadb-tests.yml index c630b6a1dc..ff407ab7a7 100644 --- a/.github/workflows/patch-mariadb-tests.yml +++ b/.github/workflows/patch-mariadb-tests.yml @@ -132,7 +132,7 @@ jobs: git checkout -q -f $branch_name rm -rf ~/frappe-bench/env - bench setup env + bench -v setup env bench --site test_site migrate done @@ -140,5 +140,5 @@ jobs: git checkout -q -f "$GITHUB_SHA" pyenv global $(pyenv versions | grep '3.10') rm -rf ~/frappe-bench/env - bench setup env + bench -v setup env bench --site test_site migrate diff --git a/.github/workflows/publish-assets-develop.yml b/.github/workflows/publish-assets-develop.yml index 9219e70eb0..b216718b99 100644 --- a/.github/workflows/publish-assets-develop.yml +++ b/.github/workflows/publish-assets-develop.yml @@ -23,7 +23,7 @@ jobs: run: | npm install -g yarn pip3 install -U frappe-bench - bench init frappe-bench --no-procfile --no-backups --skip-assets --skip-redis-config-generation --python $(which python) --frappe-path $GITHUB_WORKSPACE/frappe + bench -v init frappe-bench --no-procfile --no-backups --skip-assets --skip-redis-config-generation --python $(which python) --frappe-path $GITHUB_WORKSPACE/frappe cd frappe-bench && bench build - name: Package assets diff --git a/.github/workflows/publish-assets-releases.yml b/.github/workflows/publish-assets-releases.yml index 09c87984a9..2612c45bea 100644 --- a/.github/workflows/publish-assets-releases.yml +++ b/.github/workflows/publish-assets-releases.yml @@ -26,7 +26,7 @@ jobs: run: | npm install -g yarn pip3 install -U frappe-bench - bench init frappe-bench --no-procfile --no-backups --skip-assets --skip-redis-config-generation --python $(which python) --frappe-path $GITHUB_WORKSPACE/frappe + bench -v init frappe-bench --no-procfile --no-backups --skip-assets --skip-redis-config-generation --python $(which python) --frappe-path $GITHUB_WORKSPACE/frappe cd frappe-bench && bench build - name: Package assets From c2516c74609809b2e693161d04a948d84160a6a1 Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 30 Jun 2022 15:26:19 +0530 Subject: [PATCH 093/101] ci(patch): Install bench CLI on all Python envs \# HACK --- .github/workflows/patch-mariadb-tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/patch-mariadb-tests.yml b/.github/workflows/patch-mariadb-tests.yml index ff407ab7a7..8a17378f42 100644 --- a/.github/workflows/patch-mariadb-tests.yml +++ b/.github/workflows/patch-mariadb-tests.yml @@ -130,6 +130,7 @@ jobs: branch_name="version-$version-hotfix" git fetch --depth 1 upstream $branch_name:$branch_name git checkout -q -f $branch_name + pip install -U frappe-bench rm -rf ~/frappe-bench/env bench -v setup env From befabac17e0f36d0aecd145287cefd3f0b2b754f Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Thu, 30 Jun 2022 15:29:32 +0530 Subject: [PATCH 094/101] fix: correctly fetch list of users with role (#17363) fix: correctly fetch user list `HasRole` table is attached to many doctypes, only User should be filtered out. --- frappe/core/doctype/role/role.py | 5 ++++- frappe/core/doctype/role/test_role.py | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/frappe/core/doctype/role/role.py b/frappe/core/doctype/role/role.py index 7092004eaf..2119f3caa1 100644 --- a/frappe/core/doctype/role/role.py +++ b/frappe/core/doctype/role/role.py @@ -67,7 +67,10 @@ class Role(Document): def get_info_based_on_role(role, field="email"): """Get information of all users that have been assigned this role""" users = frappe.get_list( - "Has Role", filters={"role": role}, parent_doctype="User", fields=["parent as user_name"] + "Has Role", + filters={"role": role, "parenttype": "User"}, + parent_doctype="User", + fields=["parent as user_name"], ) return get_user_info(users, field) diff --git a/frappe/core/doctype/role/test_role.py b/frappe/core/doctype/role/test_role.py index a94796436d..44b9b1cdee 100644 --- a/frappe/core/doctype/role/test_role.py +++ b/frappe/core/doctype/role/test_role.py @@ -3,6 +3,7 @@ import unittest import frappe +from frappe.core.doctype.role.role import get_info_based_on_role test_records = frappe.get_test_records("Role") @@ -43,3 +44,11 @@ class TestUser(unittest.TestCase): role.save() user.reload() self.assertTrue(user.user_type == "Website User") + + def test_get_users_by_role(self): + + role = "System Manager" + sys_managers = get_info_based_on_role(role, field="name") + + for user in sys_managers: + self.assertIn(role, frappe.get_roles(user)) From 80f36b255aba66eebf5d220db4737f651d2be6da Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 30 Jun 2022 15:41:12 +0530 Subject: [PATCH 095/101] ci: Install bench CLI to system python --- .github/workflows/patch-mariadb-tests.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/patch-mariadb-tests.yml b/.github/workflows/patch-mariadb-tests.yml index 8a17378f42..c12d44e874 100644 --- a/.github/workflows/patch-mariadb-tests.yml +++ b/.github/workflows/patch-mariadb-tests.yml @@ -101,9 +101,7 @@ jobs: - name: Install if: ${{ steps.check-build.outputs.build == 'strawberry' }} - run: | - pyenv global $(pyenv versions | grep '3.10') - bash ${GITHUB_WORKSPACE}/.github/helper/install.sh + run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh env: DB: mariadb TYPE: server From 95ad77584a6a3555f0c9939243340588cb76821f Mon Sep 17 00:00:00 2001 From: Gavin D'souza Date: Thu, 30 Jun 2022 15:49:27 +0530 Subject: [PATCH 096/101] ci: Install bench CLI before switching pyenv --- .github/workflows/patch-mariadb-tests.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/patch-mariadb-tests.yml b/.github/workflows/patch-mariadb-tests.yml index c12d44e874..0c9fe2bb8a 100644 --- a/.github/workflows/patch-mariadb-tests.yml +++ b/.github/workflows/patch-mariadb-tests.yml @@ -101,7 +101,10 @@ jobs: - name: Install if: ${{ steps.check-build.outputs.build == 'strawberry' }} - run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh + run: | + pip install frappe-bench + pyenv global $(pyenv versions | grep '3.10') + bash ${GITHUB_WORKSPACE}/.github/helper/install.sh env: DB: mariadb TYPE: server From aad7ebc93834765be3f31d172e8949dd34f2d1b2 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Thu, 30 Jun 2022 20:25:29 +0530 Subject: [PATCH 097/101] fix: extra notification triggered on value change (#17364) Since value in DB and value on object can be in different type the notification gets triggered unnecessarily e.g. data(2012, 10, 10) != "2012-10-10" --- .../doctype/notification/notification.py | 8 ++--- .../doctype/notification/test_notification.py | 35 +++++++++++++++++++ frappe/utils/data.py | 2 +- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/frappe/email/doctype/notification/notification.py b/frappe/email/doctype/notification/notification.py index c8079f94e8..496a05bf6a 100644 --- a/frappe/email/doctype/notification/notification.py +++ b/frappe/email/doctype/notification/notification.py @@ -13,7 +13,7 @@ from frappe.desk.doctype.notification_log.notification_log import enqueue_create from frappe.integrations.doctype.slack_webhook_url.slack_webhook_url import send_slack_message from frappe.model.document import Document from frappe.modules.utils import export_module_json, get_doc_module -from frappe.utils import add_to_date, is_html, nowdate, parse_val, validate_email_address +from frappe.utils import add_to_date, cast, is_html, nowdate, validate_email_address from frappe.utils.jinja import validate_template from frappe.utils.safe_exec import get_safe_globals @@ -417,7 +417,7 @@ def trigger_notifications(doc, method=None): frappe.db.commit() -def evaluate_alert(doc, alert, event): +def evaluate_alert(doc: Document, alert, event): from jinja2 import TemplateError try: @@ -439,8 +439,8 @@ def evaluate_alert(doc, alert, event): doc_before_save = doc.get_doc_before_save() field_value_before_save = doc_before_save.get(alert.value_changed) if doc_before_save else None - field_value_before_save = parse_val(field_value_before_save) - if doc.get(alert.value_changed) == field_value_before_save: + fieldtype = doc.meta.get_field(alert.value_changed).fieldtype + if cast(fieldtype, doc.get(alert.value_changed)) == cast(fieldtype, field_value_before_save): # value not changed return diff --git a/frappe/email/doctype/notification/test_notification.py b/frappe/email/doctype/notification/test_notification.py index 4d8b26c559..7a31fc7434 100644 --- a/frappe/email/doctype/notification/test_notification.py +++ b/frappe/email/doctype/notification/test_notification.py @@ -2,6 +2,7 @@ # Copyright (c) 2018, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest +from contextlib import contextmanager import frappe import frappe.utils @@ -11,6 +12,15 @@ from frappe.desk.form import assign_to test_dependencies = ["User", "Notification"] +@contextmanager +def get_test_notification(config): + try: + notification = frappe.get_doc(doctype="Notification", **config).insert() + yield notification + finally: + notification.delete() + + class TestNotification(unittest.TestCase): def setUp(self): frappe.db.delete("Email Queue") @@ -345,6 +355,31 @@ class TestNotification(unittest.TestCase): self.assertTrue("test2@example.com" in recipients) self.assertTrue("test1@example.com" in recipients) + def test_notification_value_change_casted_types(self): + """Make sure value change event dont fire because of incorrect type comparisons.""" + frappe.set_user("Administrator") + + notification = { + "document_type": "User", + "subject": "User changed birthdate", + "event": "Value Change", + "channel": "System Notification", + "value_changed": "birth_date", + "recipients": [{"receiver_by_document_field": "email"}], + } + + with get_test_notification(notification) as n: + frappe.db.delete("Notification Log", {"subject": n.subject}) + + user = frappe.get_doc("User", "test@example.com") + user.birth_date = frappe.utils.add_days(user.birth_date, 1) + user.save() + + user.reload() + user.birth_date = frappe.utils.getdate(user.birth_date) + user.save() + self.assertEqual(1, frappe.db.count("Notification Log", {"subject": n.subject})) + @classmethod def tearDownClass(cls): frappe.delete_doc_if_exists("Notification", "ToDo Status Update") diff --git a/frappe/utils/data.py b/frappe/utils/data.py index dcc435e8fd..20c9dabfbf 100644 --- a/frappe/utils/data.py +++ b/frappe/utils/data.py @@ -801,7 +801,7 @@ def has_common(l1: typing.Hashable, l2: typing.Hashable) -> bool: def cast_fieldtype(fieldtype, value, show_warning=True): if show_warning: message = ( - "Function `frappe.utils.data.cast` has been deprecated in favour" + "Function `frappe.utils.data.cast_fieldtype` has been deprecated in favour" " of `frappe.utils.data.cast`. Use the newer util for safer type casting." ) secho(message, fg="yellow") From 81b37cb7d2160866afa2496873656afe53f0c145 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Fri, 1 Jul 2022 11:51:05 +0530 Subject: [PATCH 098/101] refactor: clean up code to py310 supported features (#17367) refactor: clean up code to py39+ supported syntax - f-strings instead of format - latest typing support instead of pre 3.9 TitleCase - remove UTF-8 declarations. - many more changes Powered by https://github.com/asottile/pyupgrade/ + manual cleanups --- frappe/__init__.py | 40 +++--- frappe/api.py | 2 +- frappe/app.py | 9 +- frappe/auth.py | 2 +- .../assignment_rule/assignment_rule.py | 10 +- .../assignment_rule_day.py | 1 - .../assignment_rule_user.py | 1 - .../doctype/auto_repeat/auto_repeat.py | 1 - .../doctype/auto_repeat/test_auto_repeat.py | 3 +- .../auto_repeat_day/auto_repeat_day.py | 1 - .../automation/doctype/milestone/milestone.py | 1 - .../doctype/milestone/test_milestone.py | 1 - .../milestone_tracker/milestone_tracker.py | 1 - .../test_milestone_tracker.py | 1 - frappe/build.py | 8 +- frappe/client.py | 4 +- frappe/commands/scheduler.py | 8 +- frappe/commands/site.py | 30 ++-- frappe/commands/utils.py | 14 +- frappe/contacts/address_and_contact.py | 13 +- frappe/contacts/doctype/address/address.py | 7 +- .../contacts/doctype/address/test_address.py | 1 - .../address_template/address_template.py | 1 - .../address_template/test_address_template.py | 1 - frappe/contacts/doctype/contact/contact.py | 2 +- .../contacts/doctype/contact/test_contact.py | 1 - .../doctype/contact_email/contact_email.py | 1 - .../doctype/contact_phone/contact_phone.py | 1 - frappe/contacts/doctype/gender/gender.py | 1 - frappe/contacts/doctype/gender/test_gender.py | 1 - .../contacts/doctype/salutation/salutation.py | 1 - .../doctype/salutation/test_salutation.py | 1 - frappe/core/api/file.py | 9 +- .../doctype/access_log/test_access_log.py | 3 +- frappe/core/doctype/activity_log/feed.py | 4 +- .../doctype/activity_log/test_activity_log.py | 1 - .../core/doctype/block_module/block_module.py | 1 - frappe/core/doctype/comment/comment.py | 5 +- frappe/core/doctype/comment/test_comment.py | 1 - .../doctype/communication/communication.py | 15 +- frappe/core/doctype/communication/email.py | 6 +- frappe/core/doctype/communication/mixins.py | 4 +- .../communication/test_communication.py | 2 +- .../communication_link/communication_link.py | 1 - .../doctype/custom_docperm/custom_docperm.py | 1 - .../custom_docperm/test_custom_docperm.py | 1 - .../core/doctype/custom_role/custom_role.py | 1 - .../doctype/custom_role/test_custom_role.py | 1 - .../core/doctype/data_export/data_export.py | 1 - frappe/core/doctype/data_export/exporter.py | 2 +- .../doctype/data_export/test_data_exporter.py | 1 - .../core/doctype/data_import/data_import.py | 1 - frappe/core/doctype/data_import/exporter.py | 20 ++- frappe/core/doctype/data_import/importer.py | 48 +++---- .../doctype/data_import/test_data_import.py | 1 - .../core/doctype/data_import/test_exporter.py | 1 - .../core/doctype/data_import/test_importer.py | 1 - .../deleted_document/deleted_document.py | 1 - .../deleted_document/test_deleted_document.py | 1 - frappe/core/doctype/doctype/doctype.py | 14 +- frappe/core/doctype/doctype/test_doctype.py | 8 +- .../doctype/doctype_action/doctype_action.py | 1 - .../core/doctype/doctype_link/doctype_link.py | 1 - .../document_naming_rule.py | 1 - .../test_document_naming_rule.py | 1 - .../document_naming_rule_condition.py | 1 - .../test_document_naming_rule_condition.py | 1 - .../document_naming_settings.py | 9 +- frappe/core/doctype/domain/domain.py | 9 +- frappe/core/doctype/domain/test_domain.py | 1 - .../domain_settings/domain_settings.py | 3 +- .../core/doctype/dynamic_link/dynamic_link.py | 1 - frappe/core/doctype/error_log/error_log.py | 1 - .../core/doctype/error_log/test_error_log.py | 1 - .../doctype/error_snapshot/error_snapshot.py | 1 - .../error_snapshot/test_error_snapshot.py | 1 - frappe/core/doctype/file/file.py | 13 +- frappe/core/doctype/file/utils.py | 20 +-- frappe/core/doctype/has_domain/has_domain.py | 1 - frappe/core/doctype/has_role/has_role.py | 1 - .../installed_application.py | 1 - .../installed_applications.py | 1 - .../test_installed_applications.py | 1 - frappe/core/doctype/language/language.py | 5 +- frappe/core/doctype/language/test_language.py | 1 - .../log_setting_user/log_setting_user.py | 1 - .../log_setting_user/test_log_setting_user.py | 1 - .../core/doctype/log_settings/log_settings.py | 1 - frappe/core/doctype/module_def/module_def.py | 4 +- .../doctype/module_def/test_module_def.py | 1 - .../doctype/module_profile/module_profile.py | 1 - .../module_profile/test_module_profile.py | 1 - .../core/doctype/navbar_item/navbar_item.py | 1 - .../doctype/navbar_item/test_navbar_item.py | 1 - .../navbar_settings/navbar_settings.py | 1 - .../navbar_settings/test_navbar_settings.py | 1 - frappe/core/doctype/package/package.py | 4 +- .../doctype/package_import/package_import.py | 4 +- .../package_release/package_release.py | 2 +- frappe/core/doctype/page/page.py | 8 +- .../core/doctype/patch_log/test_patch_log.py | 1 - .../payment_gateway/payment_gateway.py | 1 - .../payment_gateway/test_payment_gateway.py | 1 - .../prepared_report/prepared_report.py | 3 +- .../prepared_report/test_prepared_report.py | 1 - frappe/core/doctype/report/report.py | 6 +- frappe/core/doctype/report/test_report.py | 4 +- .../doctype/report_column/report_column.py | 1 - .../doctype/report_filter/report_filter.py | 1 - frappe/core/doctype/role/role.py | 2 +- .../role_permission_for_page_and_report.py | 1 - .../core/doctype/role_profile/role_profile.py | 1 - .../doctype/role_profile/test_role_profile.py | 1 - .../scheduled_job_log/scheduled_job_log.py | 1 - .../test_scheduled_job_log.py | 1 - .../scheduled_job_type/scheduled_job_type.py | 11 +- .../test_scheduled_job_type.py | 1 - .../doctype/server_script/server_script.py | 8 +- .../server_script/test_server_script.py | 1 - .../session_default/session_default.py | 1 - .../session_default_settings.py | 1 - .../test_session_default_settings.py | 1 - frappe/core/doctype/sms_parameter/__init__.py | 1 - frappe/core/doctype/sms_settings/__init__.py | 1 - .../core/doctype/sms_settings/sms_settings.py | 1 - .../doctype/sms_settings/test_sms_settings.py | 1 - .../doctype/success_action/success_action.py | 1 - .../system_settings/test_system_settings.py | 1 - frappe/core/doctype/test/test.py | 11 +- frappe/core/doctype/test/test_test.py | 1 - .../transaction_log/test_transaction_log.py | 1 - .../doctype/translation/test_translation.py | 1 - .../core/doctype/translation/translation.py | 1 - frappe/core/doctype/user/user.py | 12 +- .../user_document_type/user_document_type.py | 1 - frappe/core/doctype/user_email/user_email.py | 1 - .../doctype/user_group/test_user_group.py | 1 - frappe/core/doctype/user_group/user_group.py | 1 - .../test_user_group_member.py | 1 - .../user_group_member/user_group_member.py | 1 - .../user_select_document_type.py | 1 - .../user_social_login/user_social_login.py | 1 - .../core/doctype/user_type/test_user_type.py | 1 - frappe/core/doctype/user_type/user_type.py | 5 +- .../user_type_module/user_type_module.py | 1 - frappe/core/doctype/version/version.py | 3 +- frappe/core/doctype/view_log/test_view_log.py | 1 - frappe/core/doctype/view_log/view_log.py | 1 - .../page/background_jobs/background_jobs.py | 4 +- .../permission_manager/permission_manager.py | 3 +- .../permitted_documents_for_user.py | 6 +- .../client_script/test_client_script.py | 1 - .../doctype/custom_field/test_custom_field.py | 2 - .../doctype/customize_form/customize_form.py | 2 +- .../doctype/doctype_layout/doctype_layout.py | 1 - .../doctype_layout/test_doctype_layout.py | 1 - .../doctype_layout_field.py | 1 - .../property_setter/test_property_setter.py | 1 - .../test_rename_new/test_rename_new.py | 1 - .../test_rename_new/test_test_rename_new.py | 1 - frappe/database/database.py | 25 ++-- frappe/database/db_manager.py | 12 +- frappe/database/mariadb/database.py | 12 +- frappe/database/mariadb/schema.py | 16 +-- frappe/database/mariadb/setup_db.py | 4 +- frappe/database/postgres/database.py | 23 ++- frappe/database/postgres/schema.py | 16 +-- frappe/database/postgres/setup_db.py | 18 ++- frappe/database/query.py | 28 ++-- frappe/database/schema.py | 14 +- frappe/deferred_insert.py | 6 +- frappe/desk/desktop.py | 6 +- .../desk/doctype/bulk_update/bulk_update.py | 3 +- .../doctype/calendar_view/calendar_view.py | 1 - .../desk/doctype/console_log/console_log.py | 1 - .../doctype/console_log/test_console_log.py | 1 - frappe/desk/doctype/dashboard/dashboard.py | 2 +- .../desk/doctype/dashboard/test_dashboard.py | 1 - .../dashboard_chart/dashboard_chart.py | 19 ++- .../dashboard_chart/test_dashboard_chart.py | 1 - .../dashboard_chart_field.py | 1 - .../dashboard_chart_link.py | 1 - .../dashboard_chart_source.py | 2 - .../test_dashboard_chart_source.py | 1 - .../dashboard_settings/dashboard_settings.py | 3 +- .../desk/doctype/desktop_icon/desktop_icon.py | 3 +- frappe/desk/doctype/event/event.py | 6 +- frappe/desk/doctype/event/test_event.py | 2 +- .../event_participants/event_participants.py | 1 - .../global_search_doctype.py | 1 - .../global_search_settings.py | 1 - .../desk/doctype/kanban_board/kanban_board.py | 5 +- .../doctype/kanban_board/test_kanban_board.py | 1 - .../kanban_board_column.py | 1 - .../desk/doctype/list_filter/list_filter.py | 1 - .../list_view_settings/list_view_settings.py | 1 - .../test_list_view_settings.py | 1 - .../module_onboarding/module_onboarding.py | 1 - .../test_module_onboarding.py | 1 - frappe/desk/doctype/note/note.py | 2 +- .../desk/doctype/note_seen_by/note_seen_by.py | 1 - .../notification_log/notification_log.py | 5 +- .../notification_log/test_notification_log.py | 1 - .../notification_settings.py | 3 +- .../notification_subscribed_document.py | 1 - .../desk/doctype/number_card/number_card.py | 5 +- .../doctype/number_card/test_number_card.py | 1 - .../number_card_link/number_card_link.py | 1 - .../onboarding_permission.py | 1 - .../test_onboarding_permission.py | 1 - .../onboarding_step/onboarding_step.py | 1 - .../onboarding_step/test_onboarding_step.py | 1 - .../onboarding_step_map.py | 1 - .../doctype/system_console/system_console.py | 1 - .../system_console/test_system_console.py | 1 - frappe/desk/doctype/tag/tag.py | 4 +- frappe/desk/doctype/tag_link/tag_link.py | 1 - frappe/desk/doctype/tag_link/test_tag_link.py | 1 - frappe/desk/doctype/todo/test_todo.py | 1 - .../desk/doctype/workspace/test_workspace.py | 1 - frappe/desk/doctype/workspace/workspace.py | 9 +- .../workspace_chart/workspace_chart.py | 1 - .../doctype/workspace_link/workspace_link.py | 1 - .../workspace_shortcut/workspace_shortcut.py | 1 - frappe/desk/form/assign_to.py | 2 +- frappe/desk/form/document_follow.py | 4 +- frappe/desk/form/linked_with.py | 27 ++-- frappe/desk/form/load.py | 9 +- frappe/desk/form/meta.py | 6 +- frappe/desk/form/utils.py | 2 +- frappe/desk/like.py | 2 +- frappe/desk/listview.py | 3 +- frappe/desk/moduleview.py | 6 +- frappe/desk/page/activity/__init__.py | 1 - frappe/desk/page/backups/backups.py | 4 +- frappe/desk/page/setup_wizard/setup_wizard.py | 6 +- frappe/desk/query_report.py | 2 +- frappe/desk/report/todo/todo.py | 2 +- frappe/desk/report_dump.py | 2 +- frappe/desk/reportview.py | 2 +- frappe/desk/search.py | 10 +- frappe/desk/treeview.py | 4 +- frappe/email/__init__.py | 2 +- .../auto_email_report/auto_email_report.py | 7 +- .../test_auto_email_report.py | 1 - .../document_follow/document_follow.py | 1 - .../document_follow/test_document_follow.py | 1 - .../doctype/email_account/email_account.py | 13 +- .../email_account/test_email_account.py | 12 +- .../doctype/email_domain/email_domain.py | 13 +- .../doctype/email_domain/test_email_domain.py | 1 - .../email_flag_queue/email_flag_queue.py | 1 - .../email_flag_queue/test_email_flag_queue.py | 1 - .../email/doctype/email_group/email_group.py | 3 +- .../doctype/email_group/test_email_group.py | 1 - .../email_group_member/email_group_member.py | 1 - .../test_email_group_member.py | 1 - .../email/doctype/email_queue/email_queue.py | 9 +- .../doctype/email_queue/test_email_queue.py | 1 - .../email_queue_recipient.py | 1 - frappe/email/doctype/email_rule/email_rule.py | 1 - .../doctype/email_rule/test_email_rule.py | 1 - .../email_template/test_email_template.py | 1 - .../email_unsubscribe/email_unsubscribe.py | 1 - .../test_email_unsubscribe.py | 1 - frappe/email/doctype/newsletter/newsletter.py | 23 ++- .../doctype/newsletter/test_newsletter.py | 3 +- .../newsletter_email_group.py | 1 - .../doctype/notification/notification.py | 5 +- .../doctype/notification/test_notification.py | 1 - .../notification_recipient.py | 1 - .../unhandled_email/test_unhandled_email.py | 1 - .../unhandled_email/unhandled_email.py | 1 - frappe/email/email_body.py | 5 +- frappe/email/receive.py | 12 +- frappe/email/test_email_body.py | 2 +- .../document_type_field_mapping.py | 1 - .../document_type_mapping.py | 1 - .../test_document_type_mapping.py | 1 - .../doctype/event_consumer/event_consumer.py | 1 - .../event_consumer/test_event_consumer.py | 1 - .../event_consumer_document_type.py | 1 - .../doctype/event_producer/event_producer.py | 1 - .../event_producer/test_event_producer.py | 1 - .../event_producer_document_type.py | 1 - .../event_producer_last_update.py | 1 - .../test_event_producer_last_update.py | 1 - .../doctype/event_sync_log/event_sync_log.py | 1 - .../event_sync_log/test_event_sync_log.py | 1 - .../event_update_log/event_update_log.py | 1 - .../event_update_log/test_event_update_log.py | 1 - .../event_update_log_consumer.py | 1 - frappe/exceptions.py | 2 +- frappe/frappeclient.py | 10 +- frappe/geo/country_info.py | 4 +- frappe/geo/doctype/country/__init__.py | 1 - frappe/geo/doctype/currency/__init__.py | 1 - frappe/geo/utils.py | 5 +- frappe/installer.py | 23 ++- .../braintree_settings/braintree_settings.py | 3 +- .../test_braintree_settings.py | 1 - .../doctype/connected_app/connected_app.py | 1 - .../connected_app/test_connected_app.py | 1 - .../dropbox_settings/dropbox_settings.py | 9 +- .../dropbox_settings/test_dropbox_settings.py | 1 - .../google_calendar/google_calendar.py | 3 +- .../google_contacts/google_contacts.py | 3 +- .../doctype/google_drive/google_drive.py | 7 +- .../doctype/google_drive/test_google_drive.py | 1 - .../google_settings/google_settings.py | 1 - .../google_settings/test_google_settings.py | 2 - .../integration_request.py | 1 - .../test_integration_request.py | 1 - .../ldap_group_mapping/ldap_group_mapping.py | 1 - .../doctype/ldap_settings/ldap_settings.py | 15 +- .../ldap_settings/test_ldap_settings.py | 17 +-- .../oauth_authorization_code.py | 1 - .../test_oauth_authorization_code.py | 1 - .../oauth_bearer_token/oauth_bearer_token.py | 1 - .../test_oauth_bearer_token.py | 1 - .../doctype/oauth_client/oauth_client.py | 1 - .../doctype/oauth_client/test_oauth_client.py | 1 - .../oauth_provider_settings.py | 1 - .../doctype/oauth_scope/oauth_scope.py | 1 - .../paypal_settings/paypal_settings.py | 15 +- .../doctype/paytm_settings/paytm_settings.py | 3 +- .../paytm_settings/test_paytm_settings.py | 1 - .../query_parameters/query_parameters.py | 1 - .../razorpay_settings/razorpay_settings.py | 23 ++- .../s3_backup_settings/s3_backup_settings.py | 1 - .../test_s3_backup_settings.py | 1 - .../slack_webhook_url/slack_webhook_url.py | 1 - .../test_slack_webhook_url.py | 1 - .../social_login_key/social_login_key.py | 3 +- .../social_login_key/test_social_login_key.py | 1 - .../stripe_settings/stripe_settings.py | 5 +- .../stripe_settings/test_stripe_settings.py | 1 - .../doctype/token_cache/test_token_cache.py | 1 - .../doctype/token_cache/token_cache.py | 1 - .../integrations/doctype/webhook/__init__.py | 1 - .../doctype/webhook/test_webhook.py | 1 - .../integrations/doctype/webhook/webhook.py | 4 +- .../doctype/webhook_data/webhook_data.py | 1 - .../doctype/webhook_header/webhook_header.py | 1 - .../integrations/frappe_providers/__init__.py | 2 +- .../frappe_providers/frappecloud.py | 4 +- frappe/integrations/offsite_backup_utils.py | 11 +- frappe/integrations/utils.py | 7 +- frappe/middlewares.py | 2 +- frappe/model/base_document.py | 17 +-- frappe/model/db_query.py | 11 +- frappe/model/delete_doc.py | 7 +- frappe/model/docfield.py | 4 +- frappe/model/document.py | 25 ++-- frappe/model/mapper.py | 2 +- frappe/model/meta.py | 15 +- frappe/model/naming.py | 18 +-- frappe/model/rename_doc.py | 30 ++-- frappe/model/sync.py | 2 +- frappe/model/utils/__init__.py | 4 +- frappe/model/utils/link_count.py | 2 +- frappe/model/utils/rename_doc.py | 7 +- frappe/model/utils/rename_field.py | 2 +- frappe/model/utils/user_settings.py | 12 +- frappe/model/workflow.py | 14 +- frappe/modules/export_file.py | 2 +- frappe/modules/import_file.py | 12 +- frappe/modules/patch_handler.py | 7 +- frappe/modules/utils.py | 5 +- frappe/monitor.py | 1 - frappe/parallel_test_runner.py | 2 +- .../increase_single_table_column_length.py | 2 +- .../delete_duplicate_user_permissions.py | 2 +- .../drop_column_apply_user_permissions.py | 2 +- .../v11_0/fix_order_by_in_reports_json.py | 4 +- .../v11_0/update_list_user_settings.py | 2 +- .../patches/v12_0/delete_duplicate_indexes.py | 4 +- .../patches/v12_0/fix_public_private_files.py | 2 +- .../move_timeline_links_to_dynamic_links.py | 6 +- .../patches/v12_0/set_correct_url_in_files.py | 6 +- frappe/patches/v12_0/setup_tags.py | 2 +- .../patches/v13_0/set_unique_for_page_view.py | 4 +- frappe/patches/v14_0/copy_mail_data.py | 2 - ...date_color_names_in_kanban_board_column.py | 1 - frappe/permissions.py | 5 +- .../doctype/letter_head/test_letter_head.py | 1 - .../doctype/print_format/print_format.py | 1 - .../doctype/print_heading/print_heading.py | 1 - .../print_heading/test_print_heading.py | 1 - .../doctype/print_settings/print_settings.py | 1 - .../print_settings/test_print_settings.py | 1 - .../doctype/print_style/print_style.py | 1 - .../doctype/print_style/test_print_style.py | 1 - .../print_format_builder_beta.py | 3 +- frappe/query_builder/custom.py | 16 +-- frappe/query_builder/functions.py | 4 +- frappe/query_builder/terms.py | 10 +- frappe/query_builder/utils.py | 6 +- frappe/rate_limiter.py | 7 +- frappe/recorder.py | 9 +- .../energy_point_log/energy_point_log.py | 5 +- .../energy_point_log/test_energy_point_log.py | 1 - .../energy_point_rule/energy_point_rule.py | 1 - .../energy_point_settings.py | 1 - .../doctype/review_level/review_level.py | 1 - .../templates/includes/comments/comments.py | 2 +- .../templates/includes/feedback/feedback.py | 3 +- frappe/test_runner.py | 14 +- frappe/tests/test_api.py | 5 +- frappe/tests/test_bot.py | 2 - frappe/tests/test_caching.py | 3 +- frappe/tests/test_client.py | 4 +- frappe/tests/test_commands.py | 29 ++-- frappe/tests/test_db.py | 8 +- frappe/tests/test_db_update.py | 8 +- frappe/tests/test_email.py | 2 +- frappe/tests/test_fixture_import.py | 5 +- frappe/tests/test_form_load.py | 2 +- frappe/tests/test_formatter.py | 1 - frappe/tests/test_frappe_client.py | 8 +- frappe/tests/test_monitor.py | 1 - frappe/tests/test_naming.py | 14 +- frappe/tests/test_permissions.py | 2 +- frappe/tests/test_query_builder.py | 8 +- frappe/tests/test_rate_limiter.py | 2 - frappe/tests/test_recorder.py | 2 - frappe/tests/test_rename_doc.py | 5 +- frappe/tests/test_twofactor.py | 4 +- frappe/tests/test_utils.py | 16 +-- frappe/tests/tests_geo_utils.py | 1 - frappe/tests/ui_test_helpers.py | 4 +- frappe/translate.py | 21 ++- frappe/twofactor.py | 20 +-- frappe/utils/__init__.py | 26 ++-- frappe/utils/background_jobs.py | 6 +- frappe/utils/backups.py | 43 +++--- frappe/utils/boilerplate.py | 2 +- frappe/utils/caching.py | 6 +- frappe/utils/change_log.py | 14 +- frappe/utils/connections.py | 2 +- frappe/utils/csvutils.py | 2 +- frappe/utils/dashboard.py | 6 +- frappe/utils/data.py | 134 +++++++++--------- frappe/utils/dateutils.py | 2 +- frappe/utils/diff.py | 7 +- frappe/utils/doctor.py | 8 +- frappe/utils/error.py | 13 +- frappe/utils/file_manager.py | 8 +- frappe/utils/fixtures.py | 4 +- frappe/utils/formatters.py | 6 +- frappe/utils/global_search.py | 4 +- frappe/utils/goal.py | 9 +- frappe/utils/identicon.py | 4 +- frappe/utils/image.py | 2 +- frappe/utils/jinja.py | 6 +- frappe/utils/logger.py | 6 +- frappe/utils/make_random.py | 2 +- frappe/utils/nestedset.py | 2 +- frappe/utils/oauth.py | 6 +- frappe/utils/password.py | 2 +- frappe/utils/pdf.py | 9 +- frappe/utils/print_format.py | 10 +- frappe/utils/redis_wrapper.py | 42 +++--- frappe/utils/response.py | 6 +- frappe/utils/safe_exec.py | 2 +- frappe/utils/scheduler.py | 8 +- frappe/utils/user.py | 20 +-- frappe/utils/verified_command.py | 2 +- frappe/website/doctype/__init__.py | 1 - .../test_about_us_settings.py | 1 - frappe/website/doctype/blog_post/blog_post.py | 18 +-- .../blog_settings/test_blog_settings.py | 1 - frappe/website/doctype/color/color.py | 1 - frappe/website/doctype/color/test_color.py | 1 - .../doctype/help_article/test_help_article.py | 1 - .../help_category/test_help_category.py | 1 - .../personal_data_deletion_request.py | 3 +- .../test_personal_data_deletion_request.py | 1 - .../personal_data_deletion_step.py | 1 - .../personal_data_download_request.py | 1 - .../test_personal_data_download_request.py | 1 - .../portal_menu_item/portal_menu_item.py | 1 - .../portal_settings/portal_settings.py | 1 - .../portal_settings/test_portal_settings.py | 1 - .../social_link_settings.py | 1 - .../website/doctype/top_bar_item/__init__.py | 1 - frappe/website/doctype/web_form/web_form.py | 18 +-- frappe/website/doctype/web_page/__init__.py | 1 - frappe/website/doctype/web_page/web_page.py | 4 +- .../doctype/web_page_block/web_page_block.py | 1 - .../web_page_view/test_web_page_view.py | 1 - .../doctype/web_page_view/web_page_view.py | 1 - .../doctype/web_template/test_web_template.py | 1 - .../doctype/web_template/web_template.py | 3 +- .../test_web_template_field.py | 1 - .../web_template_field/web_template_field.py | 1 - .../website_meta_tag/website_meta_tag.py | 1 - .../test_website_route_meta.py | 1 - .../website_route_meta/website_route_meta.py | 1 - .../website_route_redirect.py | 1 - .../doctype/website_settings/__init__.py | 1 - .../website_settings/google_indexing.py | 3 +- .../website_settings/test_website_settings.py | 1 - .../website_settings/website_settings.py | 5 +- .../website_sidebar/test_website_sidebar.py | 1 - .../website_sidebar/website_sidebar.py | 1 - .../website_sidebar_item.py | 1 - .../test_website_slideshow.py | 1 - .../doctype/website_theme/website_theme.py | 2 +- .../website_theme_ignore_app.py | 1 - .../website/page_renderers/base_renderer.py | 2 +- .../page_renderers/base_template_page.py | 2 +- .../website/page_renderers/redirect_page.py | 2 +- .../website/page_renderers/template_page.py | 6 +- .../website_analytics/website_analytics.py | 2 +- frappe/website/router.py | 6 +- frappe/website/utils.py | 15 +- frappe/website/website_generator.py | 4 +- .../doctype/workflow/test_workflow.py | 2 +- .../workflow_action_master.py | 1 - frappe/www/__init__.py | 1 - frappe/www/_test/_test_metatags.py | 2 - frappe/www/app.py | 8 +- frappe/www/list.py | 4 +- frappe/www/login.py | 2 +- frappe/www/message.py | 2 +- frappe/www/printview.py | 10 +- frappe/www/qrcode.py | 4 +- frappe/www/rss.py | 2 +- 529 files changed, 977 insertions(+), 1441 deletions(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index 063a62c84b..8e0cc8f0a8 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -17,7 +17,7 @@ import json import os import re import warnings -from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Union +from typing import TYPE_CHECKING, Any, Callable import click from werkzeug.local import Local, release_local @@ -103,7 +103,7 @@ def _(msg, lang=None, context=None) -> str: translated_string = "" if context: - string_key = "{msg}:{context}".format(msg=msg, context=context) + string_key = f"{msg}:{context}" translated_string = get_full_dict(lang).get(string_key) if not translated_string: @@ -168,8 +168,8 @@ if TYPE_CHECKING: from frappe.query_builder.builder import MariaDB, Postgres from frappe.utils.redis_wrapper import RedisWrapper - db: Union[MariaDBDatabase, PostgresDatabase] - qb: Union[MariaDB, Postgres] + db: MariaDBDatabase | PostgresDatabase + qb: MariaDB | Postgres # end: static analysis hack @@ -308,10 +308,10 @@ def get_site_config(sites_path=None, site_path=None): try: config.update(get_file_json(site_config)) except Exception as error: - click.secho("{0}/site_config.json is invalid".format(local.site), fg="red") + click.secho(f"{local.site}/site_config.json is invalid", fg="red") print(error) elif local.site and not local.flags.new_site: - raise IncorrectSitePath("{0} does not exist".format(local.site)) + raise IncorrectSitePath(f"{local.site} does not exist") return _dict(config) @@ -993,7 +993,7 @@ def get_precision(doctype, fieldname, currency=None, doc=None): return get_field_precision(get_meta(doctype).get_field(fieldname), doc, currency) -def generate_hash(txt: Optional[str] = None, length: Optional[int] = None) -> str: +def generate_hash(txt: str | None = None, length: int | None = None) -> str: """Generates random hash for given text + current timestamp + random string.""" import hashlib import time @@ -1399,7 +1399,7 @@ def get_doc_hooks(): @request_cache -def _load_app_hooks(app_name: Optional[str] = None): +def _load_app_hooks(app_name: str | None = None): hooks = {} apps = [app_name] if app_name else get_installed_apps(sort=True) @@ -1422,7 +1422,7 @@ def _load_app_hooks(app_name: Optional[str] = None): def get_hooks( - hook: str = None, default: Optional[Any] = "_KEEP_DEFAULT_LIST", app_name: str = None + hook: str = None, default: Any | None = "_KEEP_DEFAULT_LIST", app_name: str = None ) -> _dict: """Get hooks via `app/hooks.py` @@ -1505,7 +1505,7 @@ def get_file_items(path, raise_not_found=False, ignore_empty_lines=True): def get_file_json(path): """Read a file and return parsed JSON object.""" - with open(path, "r") as f: + with open(path) as f: return json.load(f) @@ -1515,10 +1515,10 @@ def read_file(path, raise_not_found=False): path = path.encode("utf-8") if os.path.exists(path): - with open(path, "r") as f: + with open(path) as f: return as_unicode(f.read()) elif raise_not_found: - raise IOError("{} Not Found".format(path)) + raise OSError(f"{path} Not Found") else: return None @@ -1548,7 +1548,7 @@ def call(fn, *args, **kwargs): return fn(*args, **newargs) -def get_newargs(fn: Callable, kwargs: Dict[str, Any]) -> Dict[str, Any]: +def get_newargs(fn: Callable, kwargs: dict[str, Any]) -> dict[str, Any]: """Remove any kwargs that are not supported by the function. Example: @@ -1785,8 +1785,8 @@ def redirect_to_message(title, html, http_status_code=None, context=None, indica if indicator_color: message["context"].update({"indicator_color": indicator_color}) - cache().set_value("message_id:{0}".format(message_id), message, expires_in_sec=60) - location = "/message?id={0}".format(message_id) + cache().set_value(f"message_id:{message_id}", message, expires_in_sec=60) + location = f"/message?id={message_id}" if not getattr(local, "is_ajax", False): local.response["type"] = "redirect" @@ -1872,7 +1872,7 @@ def get_value(*args, **kwargs): return db.get_value(*args, **kwargs) -def as_json(obj: Union[Dict, List], indent=1, separators=None) -> str: +def as_json(obj: dict | list, indent=1, separators=None) -> str: from frappe.utils.response import json_handler if separators is None: @@ -1903,7 +1903,7 @@ def get_test_records(doctype): get_module_path(get_doctype_module(doctype)), "doctype", scrub(doctype), "test_records.json" ) if os.path.exists(path): - with open(path, "r") as f: + with open(path) as f: return json.loads(f.read()) else: return [] @@ -2183,7 +2183,7 @@ def get_desk_link(doctype, name): def bold(text): - return "{0}".format(text) + return f"{text}" def safe_eval(code, eval_globals=None, eval_locals=None): @@ -2211,10 +2211,10 @@ def safe_eval(code, eval_globals=None, eval_locals=None): for attribute in UNSAFE_ATTRIBUTES: if attribute in code: - throw('Illegal rule {0}. Cannot use "{1}"'.format(bold(code), attribute)) + throw(f'Illegal rule {bold(code)}. Cannot use "{attribute}"') if "__" in code: - throw('Illegal rule {0}. Cannot use "__"'.format(bold(code))) + throw(f'Illegal rule {bold(code)}. Cannot use "__"') if not eval_globals: eval_globals = {} diff --git a/frappe/api.py b/frappe/api.py index 32e19a1b43..1048468077 100644 --- a/frappe/api.py +++ b/frappe/api.py @@ -167,7 +167,7 @@ def validate_auth(): """ Authenticate and sets user for the request. """ - authorization_header = frappe.get_request_header("Authorization", str()).split(" ") + authorization_header = frappe.get_request_header("Authorization", "").split(" ") if len(authorization_header) == 2: validate_oauth(authorization_header) diff --git a/frappe/app.py b/frappe/app.py index f8c81478c0..d05febba9e 100644 --- a/frappe/app.py +++ b/frappe/app.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE @@ -34,7 +33,7 @@ SAFE_HTTP_METHODS = ("GET", "HEAD", "OPTIONS") UNSAFE_HTTP_METHODS = ("POST", "PUT", "DELETE", "PATCH") -class RequestContext(object): +class RequestContext: def __init__(self, environ): self.request = Request(environ) @@ -331,12 +330,10 @@ def serve( if not os.environ.get("NO_STATICS"): application = SharedDataMiddleware( - application, {str("/assets"): str(os.path.join(sites_path, "assets"))} + application, {"/assets": str(os.path.join(sites_path, "assets"))} ) - application = StaticDataMiddleware( - application, {str("/files"): str(os.path.abspath(sites_path))} - ) + application = StaticDataMiddleware(application, {"/files": str(os.path.abspath(sites_path))}) application.debug = True application.config = {"SERVER_NAME": "localhost:8000"} diff --git a/frappe/auth.py b/frappe/auth.py index 80141d1d6c..3737681d71 100644 --- a/frappe/auth.py +++ b/frappe/auth.py @@ -471,7 +471,7 @@ def get_login_attempt_tracker(user_name: str, raise_locked_exception: bool = Tru return tracker -class LoginAttemptTracker(object): +class LoginAttemptTracker: """Track login attemts of a user. Lock the account for s number of seconds if there have been n consecutive unsuccessful attempts to log in. diff --git a/frappe/automation/doctype/assignment_rule/assignment_rule.py b/frappe/automation/doctype/assignment_rule/assignment_rule.py index 0ca64e54c2..508ed317c6 100644 --- a/frappe/automation/doctype/assignment_rule/assignment_rule.py +++ b/frappe/automation/doctype/assignment_rule/assignment_rule.py @@ -1,7 +1,7 @@ # Copyright (c) 2022, Frappe Technologies and contributors # License: MIT. See LICENSE -from typing import Dict, Iterable, List +from collections.abc import Iterable import frappe from frappe import _ @@ -157,7 +157,7 @@ class AssignmentRule(Document): return assignment_days and today not in assignment_days -def get_assignments(doc) -> List[Dict]: +def get_assignments(doc) -> list[dict]: return frappe.get_all( "ToDo", fields=["name", "assignment_rule"], @@ -228,7 +228,7 @@ def apply(doc=None, method=None, doctype=None, name=None): ) # multiple auto assigns - assignment_rule_docs: List[AssignmentRule] = [ + assignment_rule_docs: list[AssignmentRule] = [ frappe.get_cached_doc("Assignment Rule", d.get("name")) for d in assignment_rules ] @@ -356,11 +356,11 @@ def update_due_date(doc, state=None): todo_doc.save(ignore_permissions=True) -def get_assignment_rules() -> List[str]: +def get_assignment_rules() -> list[str]: return frappe.get_all("Assignment Rule", filters={"disabled": 0}, pluck="document_type") -def get_repeated(values: Iterable) -> List: +def get_repeated(values: Iterable) -> list: unique = set() repeated = set() diff --git a/frappe/automation/doctype/assignment_rule_day/assignment_rule_day.py b/frappe/automation/doctype/assignment_rule_day/assignment_rule_day.py index 2a7e6dd66f..5a1af94696 100644 --- a/frappe/automation/doctype/assignment_rule_day/assignment_rule_day.py +++ b/frappe/automation/doctype/assignment_rule_day/assignment_rule_day.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/automation/doctype/assignment_rule_user/assignment_rule_user.py b/frappe/automation/doctype/assignment_rule_user/assignment_rule_user.py index 3f47f3c866..8b848589c3 100644 --- a/frappe/automation/doctype/assignment_rule_user/assignment_rule_user.py +++ b/frappe/automation/doctype/assignment_rule_user/assignment_rule_user.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/automation/doctype/auto_repeat/auto_repeat.py b/frappe/automation/doctype/auto_repeat/auto_repeat.py index d3399f7726..0442be0976 100644 --- a/frappe/automation/doctype/auto_repeat/auto_repeat.py +++ b/frappe/automation/doctype/auto_repeat/auto_repeat.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors # License: MIT. See LICENSE diff --git a/frappe/automation/doctype/auto_repeat/test_auto_repeat.py b/frappe/automation/doctype/auto_repeat/test_auto_repeat.py index e1db7ca6d1..ee0addf847 100644 --- a/frappe/automation/doctype/auto_repeat/test_auto_repeat.py +++ b/frappe/automation/doctype/auto_repeat/test_auto_repeat.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest @@ -200,7 +199,7 @@ class TestAutoRepeat(unittest.TestCase): # next_schedule_date is set as on or after current date # it should not be a previous month's date - self.assertTrue((doc.next_schedule_date >= current_date)) + self.assertTrue(doc.next_schedule_date >= current_date) todo = frappe.get_doc( dict( diff --git a/frappe/automation/doctype/auto_repeat_day/auto_repeat_day.py b/frappe/automation/doctype/auto_repeat_day/auto_repeat_day.py index 95d75bf9da..6453f2e80d 100644 --- a/frappe/automation/doctype/auto_repeat_day/auto_repeat_day.py +++ b/frappe/automation/doctype/auto_repeat_day/auto_repeat_day.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/automation/doctype/milestone/milestone.py b/frappe/automation/doctype/milestone/milestone.py index 4059a2eb73..40d6fae989 100644 --- a/frappe/automation/doctype/milestone/milestone.py +++ b/frappe/automation/doctype/milestone/milestone.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/automation/doctype/milestone/test_milestone.py b/frappe/automation/doctype/milestone/test_milestone.py index 1824220497..5ac0754e5a 100644 --- a/frappe/automation/doctype/milestone/test_milestone.py +++ b/frappe/automation/doctype/milestone/test_milestone.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/automation/doctype/milestone_tracker/milestone_tracker.py b/frappe/automation/doctype/milestone_tracker/milestone_tracker.py index 16b2fe9204..5388797b80 100644 --- a/frappe/automation/doctype/milestone_tracker/milestone_tracker.py +++ b/frappe/automation/doctype/milestone_tracker/milestone_tracker.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/automation/doctype/milestone_tracker/test_milestone_tracker.py b/frappe/automation/doctype/milestone_tracker/test_milestone_tracker.py index 4e53072348..2b48a76805 100644 --- a/frappe/automation/doctype/milestone_tracker/test_milestone_tracker.py +++ b/frappe/automation/doctype/milestone_tracker/test_milestone_tracker.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/build.py b/frappe/build.py index a7fdb47677..e66da4bd79 100644 --- a/frappe/build.py +++ b/frappe/build.py @@ -200,7 +200,7 @@ def symlink(target, link_name, overwrite=False): try: # Pre-empt os.replace on a directory with a nicer message if os.path.isdir(link_name): - raise IsADirectoryError("Cannot symlink over existing directory: '{}'".format(link_name)) + raise IsADirectoryError(f"Cannot symlink over existing directory: '{link_name}'") try: os.replace(temp_link_name, link_name) except AttributeError: @@ -239,10 +239,10 @@ def bundle( make_asset_dirs(hard_link=hard_link) mode = "production" if mode == "production" else "build" - command = "yarn run {mode}".format(mode=mode) + command = f"yarn run {mode}" if apps: - command += " --apps {apps}".format(apps=apps) + command += f" --apps {apps}" if skip_frappe: command += " --skip_frappe" @@ -263,7 +263,7 @@ def watch(apps=None): command = "yarn run watch" if apps: - command += " --apps {apps}".format(apps=apps) + command += f" --apps {apps}" live_reload = frappe.utils.cint(os.environ.get("LIVE_RELOAD", frappe.conf.live_reload)) diff --git a/frappe/client.py b/frappe/client.py index d5dc890f56..bd5c3b275b 100644 --- a/frappe/client.py +++ b/frappe/client.py @@ -349,13 +349,13 @@ def get_js(items): frappe.throw(_("Invalid file path: {0}").format("/".join(src))) contentpath = os.path.join(frappe.local.sites_path, *src) - with open(contentpath, "r") as srcfile: + with open(contentpath) as srcfile: code = frappe.utils.cstr(srcfile.read()) if frappe.local.lang != "en": messages = frappe.get_lang_dict("jsfile", contentpath) messages = json.dumps(messages) - code += "\n\n$.extend(frappe._messages, {})".format(messages) + code += f"\n\n$.extend(frappe._messages, {messages})" out.append(code) diff --git a/frappe/commands/scheduler.py b/frappe/commands/scheduler.py index a39a604ece..f26180e169 100755 --- a/frappe/commands/scheduler.py +++ b/frappe/commands/scheduler.py @@ -114,7 +114,7 @@ def scheduler(context, state, site=None): frappe.utils.scheduler.enable_scheduler() frappe.db.commit() - print("Scheduler {0}d for site {1}".format(state, site)) + print(f"Scheduler {state}d for site {site}") finally: frappe.destroy() @@ -182,7 +182,7 @@ def purge_jobs(site=None, queue=None, event=None): frappe.init(site or "") count = purge_pending_jobs(event=event, site=site, queue=queue) - print("Purged {} jobs".format(count)) + print(f"Purged {count} jobs") @click.command("schedule") @@ -218,11 +218,11 @@ def ready_for_migration(context, site=None): pending_jobs = get_pending_jobs(site=site) if pending_jobs: - print("NOT READY for migration: site {0} has pending background jobs".format(site)) + print(f"NOT READY for migration: site {site} has pending background jobs") sys.exit(1) else: - print("READY for migration: site {0} does not have any background jobs".format(site)) + print(f"READY for migration: site {site} does not have any background jobs") return 0 finally: diff --git a/frappe/commands/site.py b/frappe/commands/site.py index a8667d6595..626da058c3 100644 --- a/frappe/commands/site.py +++ b/frappe/commands/site.py @@ -256,7 +256,7 @@ def restore( os.remove(private) _backup.decryption_rollback() - success_message = "Site {0} has been restored{1}".format( + success_message = "Site {} has been restored{}".format( site, " with files" if (with_public_files or with_private_files) else "" ) click.secho(success_message, fg="green") @@ -413,12 +413,12 @@ def install_app(context, apps, force=False): try: _install_app(app, verbose=context.verbose, force=force) except frappe.IncompatibleApp as err: - err_msg = ":\n{}".format(err) if str(err) else "" - print("App {} is Incompatible with Site {}{}".format(app, site, err_msg)) + err_msg = f":\n{err}" if str(err) else "" + print(f"App {app} is Incompatible with Site {site}{err_msg}") exit_code = 1 except Exception as err: - err_msg = ": {}\n{}".format(str(err), frappe.get_traceback()) - print("An error occurred while installing {}{}".format(app, err_msg)) + err_msg = f": {str(err)}\n{frappe.get_traceback()}" + print(f"An error occurred while installing {app}{err_msg}") exit_code = 1 frappe.destroy() @@ -448,8 +448,8 @@ def list_apps(context, format): apps = frappe.get_single("Installed Applications").installed_applications if apps: - name_len, ver_len = [max([len(x.get(y)) for x in apps]) for y in ["app_name", "app_version"]] - template = "{{0:{0}}} {{1:{1}}} {{2}}".format(name_len, ver_len) + name_len, ver_len = (max(len(x.get(y)) for x in apps) for y in ["app_name", "app_version"]) + template = f"{{0:{name_len}}} {{1:{ver_len}}} {{2}}" installed_applications = [ template.format(app.app_name, app.app_version, app.git_branch) for app in apps @@ -607,7 +607,7 @@ def reload_doctype(context, doctype): def add_to_hosts(context): "Add site to hosts" for site in context.sites: - frappe.commands.popen("echo 127.0.0.1\t{0} | sudo tee -a /etc/hosts".format(site)) + frappe.commands.popen(f"echo 127.0.0.1\t{site} | sudo tee -a /etc/hosts") if not context.sites: raise SiteNotSpecifiedError @@ -623,9 +623,9 @@ def use(site, sites_path="."): if os.path.exists(os.path.join(sites_path, site)): with open(os.path.join(sites_path, "currentsite.txt"), "w") as sitefile: sitefile.write(site) - print("Current Site set to {}".format(site)) + print(f"Current Site set to {site}") else: - print("Site {} does not exist".format(site)) + print(f"Site {site} does not exist") @click.command("backup") @@ -699,7 +699,7 @@ def backup( ) except Exception: click.secho( - "Backup failed for Site {0}. Database or site_config.json may be corrupted".format(site), + f"Backup failed for Site {site}. Database or site_config.json may be corrupted", fg="red", ) if verbose: @@ -713,7 +713,7 @@ def backup( odb.print_summary() click.secho( - "Backup for Site {0} has been successfully completed{1}".format( + "Backup for Site {} has been successfully completed{}".format( site, " with files" if with_files else "" ), fg="green", @@ -830,8 +830,8 @@ def _drop_site( else: messages = [ "=" * 80, - "Error: The operation has stopped because backup of {0}'s database failed.".format(site), - "Reason: {0}\n".format(str(err)), + f"Error: The operation has stopped because backup of {site}'s database failed.", + f"Reason: {str(err)}\n", "Fix the issue and try again.", "Hint: Use 'bench drop-site {0} --force' to force the removal of {0}".format(site), ] @@ -1080,7 +1080,7 @@ def build_search_index(context): if not site: raise SiteNotSpecifiedError - print("Building search index for {}".format(site)) + print(f"Building search index for {site}") frappe.init(site=site) frappe.connect() try: diff --git a/frappe/commands/utils.py b/frappe/commands/utils.py index 41a4b27bcf..1b63914030 100644 --- a/frappe/commands/utils.py +++ b/frappe/commands/utils.py @@ -387,7 +387,7 @@ def import_doc(context, path, force=False): if not os.path.exists(path): path = os.path.join("..", path) if not os.path.exists(path): - print("Invalid path {0}".format(path)) + print(f"Invalid path {path}") sys.exit(1) for site in context.sites: @@ -471,7 +471,7 @@ def bulk_rename(context, doctype, path): site = get_site(context) - with open(path, "r") as csvfile: + with open(path) as csvfile: rows = read_csv_content(csvfile.read()) frappe.init(site=site) @@ -566,7 +566,7 @@ def jupyter(context): try: os.stat(jupyter_notebooks_path) except OSError: - print("Creating folder to keep jupyter notebooks at {}".format(jupyter_notebooks_path)) + print(f"Creating folder to keep jupyter notebooks at {jupyter_notebooks_path}") os.mkdir(jupyter_notebooks_path) bin_path = os.path.abspath("../env/bin") print( @@ -585,9 +585,9 @@ frappe.db.connect() ) ) os.execv( - "{0}/jupyter".format(bin_path), + f"{bin_path}/jupyter", [ - "{0}/jupyter".format(bin_path), + f"{bin_path}/jupyter", "notebook", jupyter_notebooks_path, ], @@ -780,7 +780,7 @@ def run_tests( if not (allow_tests or os.environ.get("CI")): click.secho("Testing is disabled for the site!", bold=True) click.secho("You can enable tests by entering following command:") - click.secho("bench --site {0} set-config allow_tests true".format(site), fg="green") + click.secho(f"bench --site {site} set-config allow_tests true", fg="green") return frappe.init(site=site) @@ -955,7 +955,7 @@ def request(context, args=None, path=None): if args.startswith("/api/method"): frappe.local.form_dict.cmd = args.split("?")[0].split("/")[-1] elif path: - with open(os.path.join("..", path), "r") as f: + with open(os.path.join("..", path)) as f: args = json.loads(f.read()) frappe.local.form_dict = frappe._dict(args) diff --git a/frappe/contacts/address_and_contact.py b/frappe/contacts/address_and_contact.py index 1c5803ffea..4df32c6705 100644 --- a/frappe/contacts/address_and_contact.py +++ b/frappe/contacts/address_and_contact.py @@ -3,7 +3,6 @@ import functools import re -from typing import Dict, List import frappe from frappe import _ @@ -117,9 +116,7 @@ def get_permission_query_conditions(doctype): # when everything is not permitted for df in links.get("not_permitted_links"): # like ifnull(customer, '')='' and ifnull(supplier, '')='' - conditions.append( - "ifnull(`tab{doctype}`.`{fieldname}`, '')=''".format(doctype=doctype, fieldname=df.fieldname) - ) + conditions.append(f"ifnull(`tab{doctype}`.`{df.fieldname}`, '')=''") return "( " + " and ".join(conditions) + " )" @@ -128,9 +125,7 @@ def get_permission_query_conditions(doctype): for df in links.get("permitted_links"): # like ifnull(customer, '')!='' or ifnull(supplier, '')!='' - conditions.append( - "ifnull(`tab{doctype}`.`{fieldname}`, '')!=''".format(doctype=doctype, fieldname=df.fieldname) - ) + conditions.append(f"ifnull(`tab{doctype}`.`{df.fieldname}`, '')!=''") return "( " + " or ".join(conditions) + " )" @@ -171,8 +166,8 @@ def delete_contact_and_address(doctype, docname): @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs def filter_dynamic_link_doctypes( - doctype, txt: str, searchfield, start, page_len, filters: Dict -) -> List[List[str]]: + doctype, txt: str, searchfield, start, page_len, filters: dict +) -> list[list[str]]: from frappe.permissions import get_doctypes_with_read txt = txt or "" diff --git a/frappe/contacts/doctype/address/address.py b/frappe/contacts/doctype/address/address.py index c7564e8866..42dbdd6177 100644 --- a/frappe/contacts/doctype/address/address.py +++ b/frappe/contacts/doctype/address/address.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -236,7 +235,7 @@ def address_query(doctype, txt, searchfield, start, page_len, filters): meta = frappe.get_meta("Address") for fieldname, value in filters.items(): if meta.get_field(fieldname) or fieldname in frappe.db.DEFAULT_COLUMNS: - condition += " and {field}={value}".format(field=fieldname, value=frappe.db.escape(value)) + condition += f" and {fieldname}={frappe.db.escape(value)}" searchfields = meta.get_search_fields() @@ -246,9 +245,9 @@ def address_query(doctype, txt, searchfield, start, page_len, filters): search_condition = "" for field in searchfields: if search_condition == "": - search_condition += "`tabAddress`.`{field}` like %(txt)s".format(field=field) + search_condition += f"`tabAddress`.`{field}` like %(txt)s" else: - search_condition += " or `tabAddress`.`{field}` like %(txt)s".format(field=field) + search_condition += f" or `tabAddress`.`{field}` like %(txt)s" return frappe.db.sql( """select diff --git a/frappe/contacts/doctype/address/test_address.py b/frappe/contacts/doctype/address/test_address.py index 4a6e6e53f7..edcf87f5bc 100644 --- a/frappe/contacts/doctype/address/test_address.py +++ b/frappe/contacts/doctype/address/test_address.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/contacts/doctype/address_template/address_template.py b/frappe/contacts/doctype/address_template/address_template.py index 85e9a986ef..a8806b336b 100644 --- a/frappe/contacts/doctype/address_template/address_template.py +++ b/frappe/contacts/doctype/address_template/address_template.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/contacts/doctype/address_template/test_address_template.py b/frappe/contacts/doctype/address_template/test_address_template.py index 699de5ada0..8045313c69 100644 --- a/frappe/contacts/doctype/address_template/test_address_template.py +++ b/frappe/contacts/doctype/address_template/test_address_template.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/contacts/doctype/contact/contact.py b/frappe/contacts/doctype/contact/contact.py index 4036cda853..a17f46216b 100644 --- a/frappe/contacts/doctype/contact/contact.py +++ b/frappe/contacts/doctype/contact/contact.py @@ -290,7 +290,7 @@ def get_contact_with_phone_number(number): return contacts = frappe.get_all( - "Contact Phone", filters=[["phone", "like", "%{0}".format(number)]], fields=["parent"], limit=1 + "Contact Phone", filters=[["phone", "like", f"%{number}"]], fields=["parent"], limit=1 ) return contacts[0].parent if contacts else None diff --git a/frappe/contacts/doctype/contact/test_contact.py b/frappe/contacts/doctype/contact/test_contact.py index 7ca47476e8..bf0d1037db 100644 --- a/frappe/contacts/doctype/contact/test_contact.py +++ b/frappe/contacts/doctype/contact/test_contact.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/contacts/doctype/contact_email/contact_email.py b/frappe/contacts/doctype/contact_email/contact_email.py index ed794ac06c..b6be852e57 100644 --- a/frappe/contacts/doctype/contact_email/contact_email.py +++ b/frappe/contacts/doctype/contact_email/contact_email.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/contacts/doctype/contact_phone/contact_phone.py b/frappe/contacts/doctype/contact_phone/contact_phone.py index 2a842c9c9e..ba6cd89834 100644 --- a/frappe/contacts/doctype/contact_phone/contact_phone.py +++ b/frappe/contacts/doctype/contact_phone/contact_phone.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/contacts/doctype/gender/gender.py b/frappe/contacts/doctype/gender/gender.py index 8e9951eaf9..fa38a5a6b0 100644 --- a/frappe/contacts/doctype/gender/gender.py +++ b/frappe/contacts/doctype/gender/gender.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/contacts/doctype/gender/test_gender.py b/frappe/contacts/doctype/gender/test_gender.py index 6b795749ee..c8df3b566d 100644 --- a/frappe/contacts/doctype/gender/test_gender.py +++ b/frappe/contacts/doctype/gender/test_gender.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/contacts/doctype/salutation/salutation.py b/frappe/contacts/doctype/salutation/salutation.py index 57fb2d6abc..66469c4700 100644 --- a/frappe/contacts/doctype/salutation/salutation.py +++ b/frappe/contacts/doctype/salutation/salutation.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/contacts/doctype/salutation/test_salutation.py b/frappe/contacts/doctype/salutation/test_salutation.py index 5149ced3dd..2c35e5bd2b 100644 --- a/frappe/contacts/doctype/salutation/test_salutation.py +++ b/frappe/contacts/doctype/salutation/test_salutation.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/api/file.py b/frappe/core/api/file.py index e558f2f7e3..ec305aff4f 100644 --- a/frappe/core/api/file.py +++ b/frappe/core/api/file.py @@ -1,5 +1,4 @@ import json -from typing import Dict, List import frappe from frappe.core.doctype.file.file import File, setup_folder_path @@ -14,7 +13,7 @@ def unzip_file(name: str): @frappe.whitelist() -def get_attached_images(doctype: str, names: List[str]) -> frappe._dict: +def get_attached_images(doctype: str, names: list[str]) -> frappe._dict: """get list of image urls attached in form returns {name: ['image.jpg', 'image.png']}""" @@ -40,7 +39,7 @@ def get_attached_images(doctype: str, names: List[str]) -> frappe._dict: @frappe.whitelist() -def get_files_in_folder(folder: str, start: int = 0, page_length: int = 20) -> Dict: +def get_files_in_folder(folder: str, start: int = 0, page_length: int = 20) -> dict: start = cint(start) page_length = cint(page_length) @@ -66,7 +65,7 @@ def get_files_in_folder(folder: str, start: int = 0, page_length: int = 20) -> D @frappe.whitelist() -def get_files_by_search_text(text: str) -> List[Dict]: +def get_files_by_search_text(text: str) -> list[dict]: if not text: return [] @@ -102,7 +101,7 @@ def create_new_folder(file_name: str, folder: str) -> File: @frappe.whitelist() -def move_file(file_list: List[File], new_parent: str, old_parent: str) -> None: +def move_file(file_list: list[File], new_parent: str, old_parent: str) -> None: if isinstance(file_list, str): file_list = json.loads(file_list) diff --git a/frappe/core/doctype/access_log/test_access_log.py b/frappe/core/doctype/access_log/test_access_log.py index 983e3cb5e4..ee0422e11a 100644 --- a/frappe/core/doctype/access_log/test_access_log.py +++ b/frappe/core/doctype/access_log/test_access_log.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE @@ -28,7 +27,7 @@ class TestAccessLog(unittest.TestCase): "User", frappe.session.user, fieldname="api_secret" ) api_key = frappe.db.get_value("User", "Administrator", "api_key") - self.header = {"Authorization": "token {}:{}".format(api_key, generated_secret)} + self.header = {"Authorization": f"token {api_key}:{generated_secret}"} self.test_html_template = """ diff --git a/frappe/core/doctype/activity_log/feed.py b/frappe/core/doctype/activity_log/feed.py index 3e29154242..eb040927e1 100644 --- a/frappe/core/doctype/activity_log/feed.py +++ b/frappe/core/doctype/activity_log/feed.py @@ -74,9 +74,7 @@ def get_feed_match_conditions(user=None, doctype="Comment"): user_permissions = frappe.permissions.get_user_permissions(user) can_read = frappe.get_user().get_can_read() - can_read_doctypes = [ - "'{}'".format(dt) for dt in list(set(can_read) - set(list(user_permissions))) - ] + can_read_doctypes = [f"'{dt}'" for dt in list(set(can_read) - set(list(user_permissions)))] if can_read_doctypes: conditions += [ diff --git a/frappe/core/doctype/activity_log/test_activity_log.py b/frappe/core/doctype/activity_log/test_activity_log.py index f5f94dc44b..c362fca521 100644 --- a/frappe/core/doctype/activity_log/test_activity_log.py +++ b/frappe/core/doctype/activity_log/test_activity_log.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # License: MIT. See LICENSE import time diff --git a/frappe/core/doctype/block_module/block_module.py b/frappe/core/doctype/block_module/block_module.py index 456df5037c..b9de5b325e 100644 --- a/frappe/core/doctype/block_module/block_module.py +++ b/frappe/core/doctype/block_module/block_module.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/comment/comment.py b/frappe/core/doctype/comment/comment.py index 1456f1ec93..dab9cfbfe4 100644 --- a/frappe/core/doctype/comment/comment.py +++ b/frappe/core/doctype/comment/comment.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE import json @@ -51,7 +50,7 @@ class Comment(Document): return frappe.publish_realtime( - "update_docinfo_for_{}_{}".format(self.reference_doctype, self.reference_name), + f"update_docinfo_for_{self.reference_doctype}_{self.reference_name}", {"doc": self.as_dict(), "key": key, "action": action}, after_commit=True, ) @@ -183,7 +182,7 @@ def update_comments_in_parent(reference_doctype, reference_name, _comments): try: # use sql, so that we do not mess with the timestamp frappe.db.sql( - """update `tab{0}` set `_comments`=%s where name=%s""".format(reference_doctype), # nosec + f"""update `tab{reference_doctype}` set `_comments`=%s where name=%s""", # nosec (json.dumps(_comments[-100:]), reference_name), ) diff --git a/frappe/core/doctype/comment/test_comment.py b/frappe/core/doctype/comment/test_comment.py index 3072f8b5b9..bedcea6e7e 100644 --- a/frappe/core/doctype/comment/test_comment.py +++ b/frappe/core/doctype/comment/test_comment.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE import json diff --git a/frappe/core/doctype/communication/communication.py b/frappe/core/doctype/communication/communication.py index 9b86f18726..fac8ac74b9 100644 --- a/frappe/core/doctype/communication/communication.py +++ b/frappe/core/doctype/communication/communication.py @@ -3,7 +3,6 @@ from collections import Counter from email.utils import getaddresses -from typing import List from urllib.parse import unquote from parse import compile @@ -204,7 +203,7 @@ class Communication(Document, CommunicationEmailMixin): """ emails = split_emails(emails) if isinstance(emails, str) else (emails or []) if exclude_displayname: - return [email.lower() for email in set([parse_addr(email)[1] for email in emails]) if email] + return [email.lower() for email in {parse_addr(email)[1] for email in emails} if email] return [email.lower() for email in set(emails) if email] def to_list(self, exclude_displayname=True): @@ -229,7 +228,7 @@ class Communication(Document, CommunicationEmailMixin): def notify_change(self, action): frappe.publish_realtime( - "update_docinfo_for_{}_{}".format(self.reference_doctype, self.reference_name), + f"update_docinfo_for_{self.reference_doctype}_{self.reference_name}", {"doc": self.as_dict(), "key": "communications", "action": action}, after_commit=True, ) @@ -425,7 +424,7 @@ def get_permission_query_conditions_for_communication(user): ) -def get_contacts(email_strings: List[str], auto_create_contact=False) -> List[str]: +def get_contacts(email_strings: list[str], auto_create_contact=False) -> list[str]: email_addrs = get_emails(email_strings) contacts = [] for email in email_addrs: @@ -437,9 +436,7 @@ def get_contacts(email_strings: List[str], auto_create_contact=False) -> List[st first_name = frappe.unscrub(email_parts[0]) try: - contact_name = ( - "{0}-{1}".format(first_name, email_parts[1]) if first_name == "Contact" else first_name - ) + contact_name = f"{first_name}-{email_parts[1]}" if first_name == "Contact" else first_name contact = frappe.get_doc( {"doctype": "Contact", "first_name": contact_name, "name": contact_name} ) @@ -455,7 +452,7 @@ def get_contacts(email_strings: List[str], auto_create_contact=False) -> List[st return contacts -def get_emails(email_strings: List[str]) -> List[str]: +def get_emails(email_strings: list[str]) -> list[str]: email_addrs = [] for email_string in email_strings: @@ -522,7 +519,7 @@ def get_email_without_link(email): except IndexError: return email - return "{0}@{1}".format(email_id, email_host) + return f"{email_id}@{email_host}" def update_parent_document_on_communication(doc): diff --git a/frappe/core/doctype/communication/email.py b/frappe/core/doctype/communication/email.py index 2c8a65fafe..c5585fd463 100755 --- a/frappe/core/doctype/communication/email.py +++ b/frappe/core/doctype/communication/email.py @@ -2,7 +2,7 @@ # License: MIT. See LICENSE import json -from typing import TYPE_CHECKING, Dict +from typing import TYPE_CHECKING import frappe import frappe.email.smtp @@ -45,7 +45,7 @@ def make( email_template=None, communication_type=None, **kwargs, -) -> Dict[str, str]: +) -> dict[str, str]: """Make a new communication. Checks for email permissions for specified Document. :param doctype: Reference DocType. @@ -122,7 +122,7 @@ def _make( email_template=None, communication_type=None, add_signature=True, -) -> Dict[str, str]: +) -> dict[str, str]: """Internal method to make a new communication that ignores Permission checks.""" sender = sender or get_formatted_email(frappe.session.user) diff --git a/frappe/core/doctype/communication/mixins.py b/frappe/core/doctype/communication/mixins.py index 0263cfeac5..695b8bebae 100644 --- a/frappe/core/doctype/communication/mixins.py +++ b/frappe/core/doctype/communication/mixins.py @@ -1,5 +1,3 @@ -from typing import List - import frappe from frappe import _ from frappe.core.utils import get_parent_doc @@ -201,7 +199,7 @@ class CommunicationEmailMixin: return _("Leave this conversation") return "" - def exclude_emails_list(self, is_inbound_mail_communcation=False, include_sender=False) -> List: + def exclude_emails_list(self, is_inbound_mail_communcation=False, include_sender=False) -> list: """List of mail id's excluded while sending mail.""" all_ids = self.get_all_email_addresses(exclude_displayname=True) diff --git a/frappe/core/doctype/communication/test_communication.py b/frappe/core/doctype/communication/test_communication.py index a338295374..77f83b7f91 100644 --- a/frappe/core/doctype/communication/test_communication.py +++ b/frappe/core/doctype/communication/test_communication.py @@ -236,7 +236,7 @@ class TestCommunication(unittest.TestCase): "communication_medium": "Email", "subject": "Document Link in Email", "sender": "comm_sender@example.com", - "recipients": "comm_recipient+{0}+{1}@example.com".format(quote("Note"), quote(note.name)), + "recipients": "comm_recipient+{}+{}@example.com".format(quote("Note"), quote(note.name)), } ).insert(ignore_permissions=True) diff --git a/frappe/core/doctype/communication_link/communication_link.py b/frappe/core/doctype/communication_link/communication_link.py index 21b6a7828a..07633ad174 100644 --- a/frappe/core/doctype/communication_link/communication_link.py +++ b/frappe/core/doctype/communication_link/communication_link.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/custom_docperm/custom_docperm.py b/frappe/core/doctype/custom_docperm/custom_docperm.py index 23815e9bf6..e24c765df4 100644 --- a/frappe/core/doctype/custom_docperm/custom_docperm.py +++ b/frappe/core/doctype/custom_docperm/custom_docperm.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/custom_docperm/test_custom_docperm.py b/frappe/core/doctype/custom_docperm/test_custom_docperm.py index 51923718b6..4aa04f0223 100644 --- a/frappe/core/doctype/custom_docperm/test_custom_docperm.py +++ b/frappe/core/doctype/custom_docperm/test_custom_docperm.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/custom_role/custom_role.py b/frappe/core/doctype/custom_role/custom_role.py index dd215dea17..4d96def662 100644 --- a/frappe/core/doctype/custom_role/custom_role.py +++ b/frappe/core/doctype/custom_role/custom_role.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/custom_role/test_custom_role.py b/frappe/core/doctype/custom_role/test_custom_role.py index 9c12bddd26..79c66255c0 100644 --- a/frappe/core/doctype/custom_role/test_custom_role.py +++ b/frappe/core/doctype/custom_role/test_custom_role.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/data_export/data_export.py b/frappe/core/doctype/data_export/data_export.py index 268182fbd4..b27966aa3d 100644 --- a/frappe/core/doctype/data_export/data_export.py +++ b/frappe/core/doctype/data_export/data_export.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/data_export/exporter.py b/frappe/core/doctype/data_export/exporter.py index 514be16694..b7f69ab43d 100644 --- a/frappe/core/doctype/data_export/exporter.py +++ b/frappe/core/doctype/data_export/exporter.py @@ -331,7 +331,7 @@ class DataExporter: order_by = None table_columns = frappe.db.get_table_columns(self.parent_doctype) if "lft" in table_columns and "rgt" in table_columns: - order_by = "`tab{doctype}`.`lft` asc".format(doctype=self.parent_doctype) + order_by = f"`tab{self.parent_doctype}`.`lft` asc" # get permitted data only self.data = frappe.get_list( self.doctype, fields=["*"], filters=self.filters, limit_page_length=None, order_by=order_by diff --git a/frappe/core/doctype/data_export/test_data_exporter.py b/frappe/core/doctype/data_export/test_data_exporter.py index 7b7dfc0069..812f65aaad 100644 --- a/frappe/core/doctype/data_export/test_data_exporter.py +++ b/frappe/core/doctype/data_export/test_data_exporter.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/data_import/data_import.py b/frappe/core/doctype/data_import/data_import.py index 06282e5831..5ad603e416 100644 --- a/frappe/core/doctype/data_import/data_import.py +++ b/frappe/core/doctype/data_import/data_import.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/data_import/exporter.py b/frappe/core/doctype/data_import/exporter.py index b647bdcb62..8c73391bd0 100644 --- a/frappe/core/doctype/data_import/exporter.py +++ b/frappe/core/doctype/data_import/exporter.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE @@ -132,8 +131,7 @@ class Exporter: child_doctype = table_df.options rows = self.add_data_row(child_doctype, child_row.parentfield, child_row, rows, i) - for row in rows: - yield row + yield from rows def add_data_row(self, doctype, parentfield, doc, rows, row_idx): if len(rows) < row_idx + 1: @@ -156,14 +154,14 @@ class Exporter: def get_data_as_docs(self): def format_column_name(df): - return "`tab{0}`.`{1}`".format(df.parent, df.fieldname) + return f"`tab{df.parent}`.`{df.fieldname}`" filters = self.export_filters if self.meta.is_nested_set(): - order_by = "`tab{0}`.`lft` ASC".format(self.doctype) + order_by = f"`tab{self.doctype}`.`lft` ASC" else: - order_by = "`tab{0}`.`creation` DESC".format(self.doctype) + order_by = f"`tab{self.doctype}`.`creation` DESC" parent_fields = [format_column_name(df) for df in self.fields if df.parent == self.doctype] parent_data = frappe.db.get_list( @@ -183,7 +181,7 @@ class Exporter: child_table_df = self.meta.get_field(key) child_table_doctype = child_table_df.options child_fields = ["name", "idx", "parent", "parentfield"] + list( - set([format_column_name(df) for df in self.fields if df.parent == child_table_doctype]) + {format_column_name(df) for df in self.fields if df.parent == child_table_doctype} ) data = frappe.db.get_all( child_table_doctype, @@ -211,16 +209,16 @@ class Exporter: if is_parent: label = _(df.label) else: - label = "{0} ({1})".format(_(df.label), _(df.child_table_df.label)) + label = f"{_(df.label)} ({_(df.child_table_df.label)})" if label in header: # this label is already in the header, # which means two fields with the same label # add the fieldname to avoid clash if is_parent: - label = "{0}".format(df.fieldname) + label = f"{df.fieldname}" else: - label = "{0}.{1}".format(df.child_table_df.fieldname, df.fieldname) + label = f"{df.child_table_df.fieldname}.{df.fieldname}" header.append(label) @@ -253,5 +251,5 @@ class Exporter: def build_xlsx_response(self): build_xlsx_response(self.get_csv_array_for_export(), _(self.doctype)) - def group_children_data_by_parent(self, children_data: typing.Dict[str, list]): + def group_children_data_by_parent(self, children_data: dict[str, list]): return groupby_metric(children_data, key="parent") diff --git a/frappe/core/doctype/data_import/importer.py b/frappe/core/doctype/data_import/importer.py index 06d7588aef..9e741ab590 100644 --- a/frappe/core/doctype/data_import/importer.py +++ b/frappe/core/doctype/data_import/importer.py @@ -150,7 +150,7 @@ class Importer: if self.console: update_progress_bar( - "Importing {0} records".format(total_payload_count), + f"Importing {total_payload_count} records", current_index, total_payload_count, ) @@ -342,7 +342,7 @@ class Importer: row_number = json.loads(log.get("row_indexes"))[0] status = "Success" if log.get("success") else "Failure" message = ( - "Successfully Imported {0}".format(log.get("docname")) + "Successfully Imported {}".format(log.get("docname")) if log.get("success") else log.get("messages") ) @@ -357,19 +357,17 @@ class Importer: if successful_records: print() - print( - "Successfully imported {0} records out of {1}".format(len(successful_records), len(import_log)) - ) + print(f"Successfully imported {len(successful_records)} records out of {len(import_log)}") if failed_records: - print("Failed to import {0} records".format(len(failed_records))) - file_name = "{0}_import_on_{1}.txt".format(self.doctype, frappe.utils.now()) - print("Check {0} for errors".format(os.path.join("sites", file_name))) + print(f"Failed to import {len(failed_records)} records") + file_name = f"{self.doctype}_import_on_{frappe.utils.now()}.txt" + print("Check {} for errors".format(os.path.join("sites", file_name))) text = "" for w in failed_records: - text += "Row Indexes: {0}\n".format(str(w.get("row_indexes", []))) - text += "Messages:\n{0}\n".format("\n".join(w.get("messages", []))) - text += "Traceback:\n{0}\n\n".format(w.get("exception")) + text += "Row Indexes: {}\n".format(str(w.get("row_indexes", []))) + text += "Messages:\n{}\n".format("\n".join(w.get("messages", []))) + text += "Traceback:\n{}\n\n".format(w.get("exception")) with open(file_name, "w") as f: f.write(text) @@ -384,7 +382,7 @@ class Importer: other_warnings.append(w) for row_number, warnings in warnings_by_row.items(): - print("Row {0}".format(row_number)) + print(f"Row {row_number}") for w in warnings: print(w.get("message")) @@ -578,7 +576,7 @@ class ImportFile: extn = os.path.splitext(file_path)[1][1:] file_content = None - with io.open(file_path, mode="rb") as f: + with open(file_path, mode="rb") as f: file_content = f.read() return file_content, extn @@ -991,9 +989,7 @@ class Column: self.warnings.append( { "col": self.column_number, - "message": ( - "The following values do not exist for {}: {}".format(self.df.options, missing_values) - ), + "message": (f"The following values do not exist for {self.df.options}: {missing_values}"), "type": "warning", } ) @@ -1023,8 +1019,8 @@ class Column: { "col": self.column_number, "message": ( - "The following values are invalid: {0}. Values must be" - " one of {1}".format(invalid_values, valid_values) + "The following values are invalid: {}. Values must be" + " one of {}".format(invalid_values, valid_values) ), } ) @@ -1110,9 +1106,9 @@ def build_fields_dict_for_column_matching(parent_doctype): ) else: name_headers = ( - "{0}.name".format(table_df.fieldname), # fieldname - "ID ({0})".format(table_df.label), # label - "{0} ({1})".format(_("ID"), translated_table_label), # translated label + f"{table_df.fieldname}.name", # fieldname + f"ID ({table_df.label})", # label + "{} ({})".format(_("ID"), translated_table_label), # translated label ) name_df.is_child_table_field = True @@ -1164,11 +1160,11 @@ def build_fields_dict_for_column_matching(parent_doctype): for header in ( # fieldname - "{0}.{1}".format(table_df.fieldname, df.fieldname), + f"{table_df.fieldname}.{df.fieldname}", # label - "{0} ({1})".format(label, table_df.label), + f"{label} ({table_df.label})", # translated label - "{0} ({1})".format(translated_label, translated_table_label), + f"{translated_label} ({translated_table_label})", ): out[header] = new_df @@ -1177,8 +1173,8 @@ def build_fields_dict_for_column_matching(parent_doctype): autoname_field = get_autoname_field(parent_doctype) if autoname_field: for header in ( - "ID ({})".format(autoname_field.label), # label - "{0} ({1})".format(_("ID"), _(autoname_field.label)), # translated label + f"ID ({autoname_field.label})", # label + "{} ({})".format(_("ID"), _(autoname_field.label)), # translated label # ID field should also map to the autoname field "ID", _("ID"), diff --git a/frappe/core/doctype/data_import/test_data_import.py b/frappe/core/doctype/data_import/test_data_import.py index fb15b3ad52..253882383c 100644 --- a/frappe/core/doctype/data_import/test_data_import.py +++ b/frappe/core/doctype/data_import/test_data_import.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/core/doctype/data_import/test_exporter.py b/frappe/core/doctype/data_import/test_exporter.py index ed01a2648c..ceeac90e36 100644 --- a/frappe/core/doctype/data_import/test_exporter.py +++ b/frappe/core/doctype/data_import/test_exporter.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/data_import/test_importer.py b/frappe/core/doctype/data_import/test_importer.py index 46b3c352ca..2c250a4e87 100644 --- a/frappe/core/doctype/data_import/test_importer.py +++ b/frappe/core/doctype/data_import/test_importer.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/deleted_document/deleted_document.py b/frappe/core/doctype/deleted_document/deleted_document.py index f2c98a41b8..14b9bb5c11 100644 --- a/frappe/core/doctype/deleted_document/deleted_document.py +++ b/frappe/core/doctype/deleted_document/deleted_document.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/deleted_document/test_deleted_document.py b/frappe/core/doctype/deleted_document/test_deleted_document.py index 8985298498..f696689664 100644 --- a/frappe/core/doctype/deleted_document/test_deleted_document.py +++ b/frappe/core/doctype/deleted_document/test_deleted_document.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index a965d9c1b2..40890e2a31 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -248,7 +248,7 @@ class DocType(Document): self.flags.update_fields_to_fetch_queries = [] - if set(old_fields_to_fetch) != set(df.fieldname for df in new_meta.get_fields_to_fetch()): + if set(old_fields_to_fetch) != {df.fieldname for df in new_meta.get_fields_to_fetch()}: for df in new_meta.get_fields_to_fetch(): if df.fieldname not in old_fields_to_fetch: link_fieldname, source_fieldname = df.fetch_from.split(".", 1) @@ -385,7 +385,7 @@ class DocType(Document): try: frappe.db.updatedb(self.name, Meta(self)) except Exception as e: - print("\n\nThere was an issue while migrating the DocType: {}\n".format(self.name)) + print(f"\n\nThere was an issue while migrating the DocType: {self.name}\n") raise e self.change_modified_of_parent() @@ -552,7 +552,7 @@ class DocType(Document): for fname in ("{}.js", "{}.py", "{}_list.js", "{}_calendar.js", "test_{}.py", "test_{}.js"): fname = os.path.join(new_path, fname.format(frappe.scrub(new))) if os.path.exists(fname): - with open(fname, "r") as f: + with open(fname) as f: code = f.read() with open(fname, "w") as f: if fname.endswith(".js"): @@ -569,7 +569,7 @@ class DocType(Document): f.write(file_content) # updating json file with new name - doctype_json_path = os.path.join(new_path, "{}.json".format(frappe.scrub(new))) + doctype_json_path = os.path.join(new_path, f"{frappe.scrub(new)}.json") current_data = frappe.get_file_json(doctype_json_path) current_data["name"] = new @@ -643,7 +643,7 @@ class DocType(Document): path = get_file_path(self.module, "DocType", self.name) if os.path.exists(path): try: - with open(path, "r") as txtfile: + with open(path) as txtfile: olddoc = json.loads(txtfile.read()) old_field_names = [f["fieldname"] for f in olddoc.get("fields", [])] @@ -804,7 +804,7 @@ class DocType(Document): {"label": "Old Parent", "fieldtype": "Link", "options": self.name, "fieldname": "old_parent"}, ) - parent_field_label = "Parent {}".format(self.name) + parent_field_label = f"Parent {self.name}" parent_field_name = frappe.scrub(parent_field_label) self.append( "fields", @@ -1417,7 +1417,7 @@ def validate_fields(meta): def check_max_height(docfield): if getattr(docfield, "max_height", None) and (docfield.max_height[-2:] not in ("px", "em")): - frappe.throw("Max for {} height must be in px, em, rem".format(frappe.bold(docfield.fieldname))) + frappe.throw(f"Max for {frappe.bold(docfield.fieldname)} height must be in px, em, rem") def check_no_of_ratings(docfield): if docfield.fieldtype == "Rating": diff --git a/frappe/core/doctype/doctype/test_doctype.py b/frappe/core/doctype/doctype/test_doctype.py index 5b0b575201..3a5ca4329f 100644 --- a/frappe/core/doctype/doctype/test_doctype.py +++ b/frappe/core/doctype/doctype/test_doctype.py @@ -1,10 +1,8 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE import random import string import unittest -from typing import Dict, List, Optional from unittest.mock import patch import frappe @@ -187,7 +185,7 @@ class TestDocType(unittest.TestCase): "module": "Core", "custom": 1, "fields": [ - {"fieldname": "{0}_field".format(field_option), "fieldtype": "Data", "options": field_option} + {"fieldname": f"{field_option}_field", "fieldtype": "Data", "options": field_option} ], } ) @@ -711,10 +709,10 @@ class TestDocType(unittest.TestCase): def new_doctype( - name: Optional[str] = None, + name: str | None = None, unique: bool = False, depends_on: str = "", - fields: Optional[List[Dict]] = None, + fields: list[dict] | None = None, **kwargs, ): if not name: diff --git a/frappe/core/doctype/doctype_action/doctype_action.py b/frappe/core/doctype/doctype_action/doctype_action.py index 49cb21f99f..1c5be9ae01 100644 --- a/frappe/core/doctype/doctype_action/doctype_action.py +++ b/frappe/core/doctype/doctype_action/doctype_action.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/doctype_link/doctype_link.py b/frappe/core/doctype/doctype_link/doctype_link.py index f534cd1780..0658b1fb28 100644 --- a/frappe/core/doctype/doctype_link/doctype_link.py +++ b/frappe/core/doctype/doctype_link/doctype_link.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/document_naming_rule/document_naming_rule.py b/frappe/core/doctype/document_naming_rule/document_naming_rule.py index 41aa3d7aff..3fecf26ade 100644 --- a/frappe/core/doctype/document_naming_rule/document_naming_rule.py +++ b/frappe/core/doctype/document_naming_rule/document_naming_rule.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/document_naming_rule/test_document_naming_rule.py b/frappe/core/doctype/document_naming_rule/test_document_naming_rule.py index 459b17da8b..cc406ed5cd 100644 --- a/frappe/core/doctype/document_naming_rule/test_document_naming_rule.py +++ b/frappe/core/doctype/document_naming_rule/test_document_naming_rule.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/document_naming_rule_condition/document_naming_rule_condition.py b/frappe/core/doctype/document_naming_rule_condition/document_naming_rule_condition.py index dc45798c34..7ecc0162a5 100644 --- a/frappe/core/doctype/document_naming_rule_condition/document_naming_rule_condition.py +++ b/frappe/core/doctype/document_naming_rule_condition/document_naming_rule_condition.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/document_naming_rule_condition/test_document_naming_rule_condition.py b/frappe/core/doctype/document_naming_rule_condition/test_document_naming_rule_condition.py index d88335758a..68f0677f2c 100644 --- a/frappe/core/doctype/document_naming_rule_condition/test_document_naming_rule_condition.py +++ b/frappe/core/doctype/document_naming_rule_condition/test_document_naming_rule_condition.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/core/doctype/document_naming_settings/document_naming_settings.py b/frappe/core/doctype/document_naming_settings/document_naming_settings.py index 46def88b65..5680b6c823 100644 --- a/frappe/core/doctype/document_naming_settings/document_naming_settings.py +++ b/frappe/core/doctype/document_naming_settings/document_naming_settings.py @@ -1,7 +1,6 @@ # Copyright (c) 2022, Frappe Technologies and contributors # For license information, please see license.txt -from typing import List, Set import frappe from frappe import _ @@ -25,7 +24,7 @@ class DocumentNamingSettings(Document): return {"transactions": transactions, "prefixes": prefixes} - def _get_transactions(self) -> List[str]: + def _get_transactions(self) -> list[str]: readable_doctypes = set(get_doctypes_with_read()) @@ -34,7 +33,7 @@ class DocumentNamingSettings(Document): return sorted(readable_doctypes.intersection(standard + custom)) - def _get_prefixes(self, doctypes) -> List[str]: + def _get_prefixes(self, doctypes) -> list[str]: """Get all prefixes for naming series. - For all templates prefix is evaluated considering today's date @@ -63,7 +62,7 @@ class DocumentNamingSettings(Document): return self._evaluate_and_clean_templates(series_templates) - def _evaluate_and_clean_templates(self, series_templates: Set[str]) -> List[str]: + def _evaluate_and_clean_templates(self, series_templates: set[str]) -> list[str]: evalauted_prefix = set() series = frappe.qb.DocType("Series") @@ -79,7 +78,7 @@ class DocumentNamingSettings(Document): return sorted(evalauted_prefix) - def get_options_list(self, options: str) -> List[str]: + def get_options_list(self, options: str) -> list[str]: return [op.strip() for op in options.split("\n") if op.strip()] @frappe.whitelist() diff --git a/frappe/core/doctype/domain/domain.py b/frappe/core/doctype/domain/domain.py index 897f7ee655..e0b0e80982 100644 --- a/frappe/core/doctype/domain/domain.py +++ b/frappe/core/doctype/domain/domain.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -113,8 +112,8 @@ class Domain(Document): # enable frappe.db.sql( """update `tabPortal Menu Item` set enabled=1 - where route in ({0})""".format( - ", ".join('"{0}"'.format(d) for d in self.data.allow_sidebar_items) + where route in ({})""".format( + ", ".join(f'"{d}"' for d in self.data.allow_sidebar_items) ) ) @@ -125,7 +124,7 @@ class Domain(Document): # enable frappe.db.sql( """update `tabPortal Menu Item` set enabled=0 - where route in ({0})""".format( - ", ".join('"{0}"'.format(d) for d in self.data.remove_sidebar_items) + where route in ({})""".format( + ", ".join(f'"{d}"' for d in self.data.remove_sidebar_items) ) ) diff --git a/frappe/core/doctype/domain/test_domain.py b/frappe/core/doctype/domain/test_domain.py index 623d80a280..32592705b4 100644 --- a/frappe/core/doctype/domain/test_domain.py +++ b/frappe/core/doctype/domain/test_domain.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/domain_settings/domain_settings.py b/frappe/core/doctype/domain_settings/domain_settings.py index ba7f397c51..85b26f53dd 100644 --- a/frappe/core/doctype/domain_settings/domain_settings.py +++ b/frappe/core/doctype/domain_settings/domain_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -32,7 +31,7 @@ class DomainSettings(Document): def restrict_roles_and_modules(self): """Disable all restricted roles and set `restrict_to_domain` property in Module Def""" active_domains = frappe.get_active_domains() - all_domains = list((frappe.get_hooks("domains") or {})) + all_domains = list(frappe.get_hooks("domains") or {}) def remove_role(role): frappe.db.delete("Has Role", {"role": role}) diff --git a/frappe/core/doctype/dynamic_link/dynamic_link.py b/frappe/core/doctype/dynamic_link/dynamic_link.py index e253147167..53eb750b5c 100644 --- a/frappe/core/doctype/dynamic_link/dynamic_link.py +++ b/frappe/core/doctype/dynamic_link/dynamic_link.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/error_log/error_log.py b/frappe/core/doctype/error_log/error_log.py index 224a5673a7..c7ab98e034 100644 --- a/frappe/core/doctype/error_log/error_log.py +++ b/frappe/core/doctype/error_log/error_log.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/error_log/test_error_log.py b/frappe/core/doctype/error_log/test_error_log.py index a8511b238e..c7cf26a0cf 100644 --- a/frappe/core/doctype/error_log/test_error_log.py +++ b/frappe/core/doctype/error_log/test_error_log.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/error_snapshot/error_snapshot.py b/frappe/core/doctype/error_snapshot/error_snapshot.py index 6e13b7a654..6966cf0aca 100644 --- a/frappe/core/doctype/error_snapshot/error_snapshot.py +++ b/frappe/core/doctype/error_snapshot/error_snapshot.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/error_snapshot/test_error_snapshot.py b/frappe/core/doctype/error_snapshot/test_error_snapshot.py index 121fe8a6f9..0c1f861b43 100644 --- a/frappe/core/doctype/error_snapshot/test_error_snapshot.py +++ b/frappe/core/doctype/error_snapshot/test_error_snapshot.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/file/file.py b/frappe/core/doctype/file/file.py index bb4b441680..7a66d45c73 100755 --- a/frappe/core/doctype/file/file.py +++ b/frappe/core/doctype/file/file.py @@ -7,7 +7,6 @@ import os import re import shutil import zipfile -from typing import List, Optional, Union from urllib.parse import quote, unquote from PIL import Image, ImageFile, ImageOps @@ -134,7 +133,7 @@ class File(Document): shutil.move(source, target) self.flags.pop("original_path") - def get_name_based_on_parent_folder(self) -> Union[str, None]: + def get_name_based_on_parent_folder(self) -> str | None: if self.folder: return os.path.join(self.folder, self.file_name) @@ -328,7 +327,7 @@ class File(Document): file_path = get_files_path(file_name, is_private=self.is_private) with open(file_path, "rb") as f: self.content_hash = get_content_hash(f.read()) - except IOError: + except OSError: frappe.throw(_("File {0} does not exist").format(file_path)) def make_thumbnail( @@ -347,7 +346,7 @@ class File(Document): image, filename, extn = get_local_image(self.file_url) else: image, filename, extn = get_web_image(self.file_url) - except (HTTPError, SSLError, IOError, TypeError): + except (HTTPError, SSLError, OSError, TypeError): return size = width, height @@ -364,7 +363,7 @@ class File(Document): if set_as_thumbnail: self.db_set("thumbnail_url", thumbnail_url) - except IOError: + except OSError: frappe.msgprint(_("Unable to write file format for {0}").format(path)) return @@ -387,7 +386,7 @@ class File(Document): else: self.delete_file_data_content(only_thumbnail=True) - def unzip(self) -> List["File"]: + def unzip(self) -> list["File"]: """Unzip current file and replace it by its children""" if not self.file_url.endswith(".zip"): frappe.throw(_("{0} is not a zip file").format(self.file_name)) @@ -506,7 +505,7 @@ class File(Document): def save_file( self, - content: Optional[Union[bytes, str]] = None, + content: bytes | str | None = None, decode=False, ignore_existing_file_check=False, overwrite=False, diff --git a/frappe/core/doctype/file/utils.py b/frappe/core/doctype/file/utils.py index 632324c9cf..e59ec2aede 100644 --- a/frappe/core/doctype/file/utils.py +++ b/frappe/core/doctype/file/utils.py @@ -4,7 +4,7 @@ import mimetypes import os import re from io import BytesIO -from typing import TYPE_CHECKING, Optional, Tuple, Union +from typing import TYPE_CHECKING, Optional from urllib.parse import unquote import requests @@ -55,8 +55,8 @@ def setup_folder_path(filename: str, new_parent: str) -> None: def get_extension( filename, - extn: Optional[str] = None, - content: Optional[bytes] = None, + extn: str | None = None, + content: bytes | None = None, response: Optional["Response"] = None, ) -> str: mimetype = None @@ -83,7 +83,7 @@ def get_extension( return extn -def get_local_image(file_url: str) -> Tuple["ImageFile", str, str]: +def get_local_image(file_url: str) -> tuple["ImageFile", str, str]: if file_url.startswith("/private"): file_url_path = (file_url.lstrip("/"),) else: @@ -93,7 +93,7 @@ def get_local_image(file_url: str) -> Tuple["ImageFile", str, str]: try: image = Image.open(file_path) - except IOError: + except OSError: frappe.throw(_("Unable to read file format for {0}").format(file_url)) content = None @@ -102,7 +102,7 @@ def get_local_image(file_url: str) -> Tuple["ImageFile", str, str]: filename, extn = file_url.rsplit(".", 1) except ValueError: # no extn - with open(file_path, "r") as f: + with open(file_path) as f: content = f.read() filename = file_url @@ -113,7 +113,7 @@ def get_local_image(file_url: str) -> Tuple["ImageFile", str, str]: return image, filename, extn -def get_web_image(file_url: str) -> Tuple["ImageFile", str, str]: +def get_web_image(file_url: str) -> tuple["ImageFile", str, str]: # download file_url = frappe.utils.get_url(file_url) r = requests.get(file_url, stream=True) @@ -179,13 +179,13 @@ def remove_file_by_url(file_url: str, doctype: str = None, name: str = None) -> return remove_file(fid=fid) -def get_content_hash(content: Union[bytes, str]) -> str: +def get_content_hash(content: bytes | str) -> str: if isinstance(content, str): content = content.encode() return hashlib.md5(content).hexdigest() # nosec -def generate_file_name(name: str, suffix: Optional[str] = None, is_private: bool = False) -> str: +def generate_file_name(name: str, suffix: str | None = None, is_private: bool = False) -> str: """Generate conflict-free file name. Suffix will be ignored if name available. If the provided suffix doesn't result in an available path, a random suffix will be picked. """ @@ -203,7 +203,7 @@ def generate_file_name(name: str, suffix: Optional[str] = None, is_private: bool return candidate_path -def get_file_name(fname: str, optional_suffix: Optional[str] = None) -> str: +def get_file_name(fname: str, optional_suffix: str | None = None) -> str: # convert to unicode fname = cstr(fname) partial, extn = os.path.splitext(fname) diff --git a/frappe/core/doctype/has_domain/has_domain.py b/frappe/core/doctype/has_domain/has_domain.py index 8ef69ef0c4..0d8257fc33 100644 --- a/frappe/core/doctype/has_domain/has_domain.py +++ b/frappe/core/doctype/has_domain/has_domain.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/has_role/has_role.py b/frappe/core/doctype/has_role/has_role.py index 83cf90aac6..8798adf031 100644 --- a/frappe/core/doctype/has_role/has_role.py +++ b/frappe/core/doctype/has_role/has_role.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/installed_application/installed_application.py b/frappe/core/doctype/installed_application/installed_application.py index 07b6c105af..0a1dab8f2e 100644 --- a/frappe/core/doctype/installed_application/installed_application.py +++ b/frappe/core/doctype/installed_application/installed_application.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/installed_applications/installed_applications.py b/frappe/core/doctype/installed_applications/installed_applications.py index d13118e169..07b20db153 100644 --- a/frappe/core/doctype/installed_applications/installed_applications.py +++ b/frappe/core/doctype/installed_applications/installed_applications.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/installed_applications/test_installed_applications.py b/frappe/core/doctype/installed_applications/test_installed_applications.py index 24d3a9a49a..b67cc4c8c7 100644 --- a/frappe/core/doctype/installed_applications/test_installed_applications.py +++ b/frappe/core/doctype/installed_applications/test_installed_applications.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/core/doctype/language/language.py b/frappe/core/doctype/language/language.py index 948810eb39..efac7b0d77 100644 --- a/frappe/core/doctype/language/language.py +++ b/frappe/core/doctype/language/language.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -42,7 +41,7 @@ def export_languages_json(): def sync_languages(): """Sync frappe/geo/languages.json with Language""" - with open(frappe.get_app_path("frappe", "geo", "languages.json"), "r") as f: + with open(frappe.get_app_path("frappe", "geo", "languages.json")) as f: data = json.loads(f.read()) for l in data: @@ -59,7 +58,7 @@ def sync_languages(): def update_language_names(): """Update frappe/geo/languages.json names (for use via patch)""" - with open(frappe.get_app_path("frappe", "geo", "languages.json"), "r") as f: + with open(frappe.get_app_path("frappe", "geo", "languages.json")) as f: data = json.loads(f.read()) for l in data: diff --git a/frappe/core/doctype/language/test_language.py b/frappe/core/doctype/language/test_language.py index 305515c191..1f9c96a5d8 100644 --- a/frappe/core/doctype/language/test_language.py +++ b/frappe/core/doctype/language/test_language.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/log_setting_user/log_setting_user.py b/frappe/core/doctype/log_setting_user/log_setting_user.py index cf66da31b1..830d29e3be 100644 --- a/frappe/core/doctype/log_setting_user/log_setting_user.py +++ b/frappe/core/doctype/log_setting_user/log_setting_user.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/log_setting_user/test_log_setting_user.py b/frappe/core/doctype/log_setting_user/test_log_setting_user.py index dc70677079..9ea56e8ec4 100644 --- a/frappe/core/doctype/log_setting_user/test_log_setting_user.py +++ b/frappe/core/doctype/log_setting_user/test_log_setting_user.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/core/doctype/log_settings/log_settings.py b/frappe/core/doctype/log_settings/log_settings.py index 1a7ce532cd..8009324e70 100644 --- a/frappe/core/doctype/log_settings/log_settings.py +++ b/frappe/core/doctype/log_settings/log_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/module_def/module_def.py b/frappe/core/doctype/module_def/module_def.py index 8f80ffd4ee..c9dac11b69 100644 --- a/frappe/core/doctype/module_def/module_def.py +++ b/frappe/core/doctype/module_def/module_def.py @@ -29,7 +29,7 @@ class ModuleDef(Document): """Adds to `[app]/modules.txt`""" modules = None if not frappe.local.module_app.get(frappe.scrub(self.name)): - with open(frappe.get_app_path(self.app_name, "modules.txt"), "r") as f: + with open(frappe.get_app_path(self.app_name, "modules.txt")) as f: content = f.read() if not self.name in content.splitlines(): modules = list(filter(None, content.splitlines())) @@ -50,7 +50,7 @@ class ModuleDef(Document): modules = None if frappe.local.module_app.get(frappe.scrub(self.name)): - with open(frappe.get_app_path(self.app_name, "modules.txt"), "r") as f: + with open(frappe.get_app_path(self.app_name, "modules.txt")) as f: content = f.read() if self.name in content.splitlines(): modules = list(filter(None, content.splitlines())) diff --git a/frappe/core/doctype/module_def/test_module_def.py b/frappe/core/doctype/module_def/test_module_def.py index 3a6da6d854..914ba07949 100644 --- a/frappe/core/doctype/module_def/test_module_def.py +++ b/frappe/core/doctype/module_def/test_module_def.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/module_profile/module_profile.py b/frappe/core/doctype/module_profile/module_profile.py index 7c5f896ba8..46c09827f3 100644 --- a/frappe/core/doctype/module_profile/module_profile.py +++ b/frappe/core/doctype/module_profile/module_profile.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/module_profile/test_module_profile.py b/frappe/core/doctype/module_profile/test_module_profile.py index e15a70d93f..099d1371fb 100644 --- a/frappe/core/doctype/module_profile/test_module_profile.py +++ b/frappe/core/doctype/module_profile/test_module_profile.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/navbar_item/navbar_item.py b/frappe/core/doctype/navbar_item/navbar_item.py index 27aa339c93..60be154e75 100644 --- a/frappe/core/doctype/navbar_item/navbar_item.py +++ b/frappe/core/doctype/navbar_item/navbar_item.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/navbar_item/test_navbar_item.py b/frappe/core/doctype/navbar_item/test_navbar_item.py index 913e84704b..7eeb4f642b 100644 --- a/frappe/core/doctype/navbar_item/test_navbar_item.py +++ b/frappe/core/doctype/navbar_item/test_navbar_item.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/core/doctype/navbar_settings/navbar_settings.py b/frappe/core/doctype/navbar_settings/navbar_settings.py index 6243107d63..1eba0f8fa7 100644 --- a/frappe/core/doctype/navbar_settings/navbar_settings.py +++ b/frappe/core/doctype/navbar_settings/navbar_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/navbar_settings/test_navbar_settings.py b/frappe/core/doctype/navbar_settings/test_navbar_settings.py index f63e361e8b..76fb3d298a 100644 --- a/frappe/core/doctype/navbar_settings/test_navbar_settings.py +++ b/frappe/core/doctype/navbar_settings/test_navbar_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/core/doctype/package/package.py b/frappe/core/doctype/package/package.py index a32f1bc534..c1cb482832 100644 --- a/frappe/core/doctype/package/package.py +++ b/frappe/core/doctype/package/package.py @@ -15,7 +15,5 @@ class Package(Document): @frappe.whitelist() def get_license_text(license_type): - with open( - os.path.join(os.path.dirname(__file__), "licenses", license_type + ".md"), "r" - ) as textfile: + with open(os.path.join(os.path.dirname(__file__), "licenses", license_type + ".md")) as textfile: return textfile.read() diff --git a/frappe/core/doctype/package_import/package_import.py b/frappe/core/doctype/package_import/package_import.py index 43a985af9b..19762eae4a 100644 --- a/frappe/core/doctype/package_import/package_import.py +++ b/frappe/core/doctype/package_import/package_import.py @@ -44,7 +44,7 @@ class PackageImport(Document): package_path = frappe.get_site_path("packages", package_name) # import Package - with open(os.path.join(package_path, package_name + ".json"), "r") as packagefile: + with open(os.path.join(package_path, package_name + ".json")) as packagefile: doc_dict = json.loads(packagefile.read()) frappe.flags.package = import_doc(doc_dict) @@ -60,6 +60,6 @@ class PackageImport(Document): # import files for file in files: import_file_by_path(file, force=self.force, ignore_version=True) - log.append("Imported {}".format(file)) + log.append(f"Imported {file}") self.log = "\n".join(log) diff --git a/frappe/core/doctype/package_release/package_release.py b/frappe/core/doctype/package_release/package_release.py index 05277dcf2e..58fdc2ab86 100644 --- a/frappe/core/doctype/package_release/package_release.py +++ b/frappe/core/doctype/package_release/package_release.py @@ -87,7 +87,7 @@ class PackageRelease(Document): def make_tarfile(self, package): # make tarfile - filename = "{}.tar.gz".format(self.name) + filename = f"{self.name}.tar.gz" subprocess.check_output( ["tar", "czf", filename, package.package_name], cwd=frappe.get_site_path("packages") ) diff --git a/frappe/core/doctype/page/page.py b/frappe/core/doctype/page/page.py index 7185a25e01..8210875b3a 100644 --- a/frappe/core/doctype/page/page.py +++ b/frappe/core/doctype/page/page.py @@ -79,7 +79,7 @@ class Page(Document): ) def as_dict(self, no_nulls=False): - d = super(Page, self).as_dict(no_nulls=no_nulls) + d = super().as_dict(no_nulls=no_nulls) for key in ("script", "style", "content"): d[key] = self.get(key) return d @@ -120,20 +120,20 @@ class Page(Document): # script fpath = os.path.join(path, page_name + ".js") if os.path.exists(fpath): - with open(fpath, "r") as f: + with open(fpath) as f: self.script = render_include(f.read()) self.script += f"\n\n//# sourceURL={page_name}.js" # css fpath = os.path.join(path, page_name + ".css") if os.path.exists(fpath): - with open(fpath, "r") as f: + with open(fpath) as f: self.style = safe_decode(f.read()) # html as js template for fname in os.listdir(path): if fname.endswith(".html"): - with open(os.path.join(path, fname), "r") as f: + with open(os.path.join(path, fname)) as f: template = f.read() if "" in template: context = frappe._dict({}) diff --git a/frappe/core/doctype/patch_log/test_patch_log.py b/frappe/core/doctype/patch_log/test_patch_log.py index 54cdc6416a..0c8a2ae4d4 100644 --- a/frappe/core/doctype/patch_log/test_patch_log.py +++ b/frappe/core/doctype/patch_log/test_patch_log.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/payment_gateway/payment_gateway.py b/frappe/core/doctype/payment_gateway/payment_gateway.py index 7eb4c5481d..74306ae4ad 100644 --- a/frappe/core/doctype/payment_gateway/payment_gateway.py +++ b/frappe/core/doctype/payment_gateway/payment_gateway.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/payment_gateway/test_payment_gateway.py b/frappe/core/doctype/payment_gateway/test_payment_gateway.py index 71766561b3..6900e79434 100644 --- a/frappe/core/doctype/payment_gateway/test_payment_gateway.py +++ b/frappe/core/doctype/payment_gateway/test_payment_gateway.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/prepared_report/prepared_report.py b/frappe/core/doctype/prepared_report/prepared_report.py index e35ec43565..0ff4ce3070 100644 --- a/frappe/core/doctype/prepared_report/prepared_report.py +++ b/frappe/core/doctype/prepared_report/prepared_report.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -103,7 +102,7 @@ def delete_prepared_reports(reports): def create_json_gz_file(data, dt, dn): # Storing data in CSV file causes information loss # Reports like P&L Statement were completely unsuable because of this - json_filename = "{0}.json.gz".format( + json_filename = "{}.json.gz".format( frappe.utils.data.format_datetime(frappe.utils.now(), "Y-m-d-H:M") ) encoded_content = frappe.safe_encode(frappe.as_json(data)) diff --git a/frappe/core/doctype/prepared_report/test_prepared_report.py b/frappe/core/doctype/prepared_report/test_prepared_report.py index 86793cb802..6d0c809a01 100644 --- a/frappe/core/doctype/prepared_report/test_prepared_report.py +++ b/frappe/core/doctype/prepared_report/test_prepared_report.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors # License: MIT. See LICENSE import json diff --git a/frappe/core/doctype/report/report.py b/frappe/core/doctype/report/report.py index efb45f41c8..7fe3cadf9c 100644 --- a/frappe/core/doctype/report/report.py +++ b/frappe/core/doctype/report/report.py @@ -243,7 +243,7 @@ class Report(Document): @staticmethod def _format(parts): # sort by is saved as DocType.fieldname, covert it to sql - return "`tab{0}`.`{1}`".format(*parts) + return "`tab{}`.`{}`".format(*parts) def get_standard_report_columns(self, params): if params.get("fields"): @@ -365,9 +365,7 @@ def get_group_by_field(args, doctype): if args["aggregate_function"] == "count": group_by_field = "count(*) as _aggregate_column" else: - group_by_field = "{0}({1}) as _aggregate_column".format( - args.aggregate_function, args.aggregate_on - ) + group_by_field = f"{args.aggregate_function}({args.aggregate_on}) as _aggregate_column" return group_by_field diff --git a/frappe/core/doctype/report/test_report.py b/frappe/core/doctype/report/test_report.py index bbae616e93..0e1ed80eda 100644 --- a/frappe/core/doctype/report/test_report.py +++ b/frappe/core/doctype/report/test_report.py @@ -22,7 +22,7 @@ class TestReport(FrappeTestCase): if frappe.db.exists("Report", "User Activity Report"): frappe.delete_doc("Report", "User Activity Report") - with open(os.path.join(os.path.dirname(__file__), "user_activity_report.json"), "r") as f: + with open(os.path.join(os.path.dirname(__file__), "user_activity_report.json")) as f: frappe.get_doc(json.loads(f.read())).insert() report = frappe.get_doc("Report", "User Activity Report") @@ -223,7 +223,7 @@ class TestReport(FrappeTestCase): if frappe.db.exists("Report", "User Activity Report Without Sort"): frappe.delete_doc("Report", "User Activity Report Without Sort") with open( - os.path.join(os.path.dirname(__file__), "user_activity_report_without_sort.json"), "r" + os.path.join(os.path.dirname(__file__), "user_activity_report_without_sort.json") ) as f: frappe.get_doc(json.loads(f.read())).insert() diff --git a/frappe/core/doctype/report_column/report_column.py b/frappe/core/doctype/report_column/report_column.py index c0984a5ca8..0d6045d121 100644 --- a/frappe/core/doctype/report_column/report_column.py +++ b/frappe/core/doctype/report_column/report_column.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/report_filter/report_filter.py b/frappe/core/doctype/report_filter/report_filter.py index e35d7064d2..f3a9607e20 100644 --- a/frappe/core/doctype/report_filter/report_filter.py +++ b/frappe/core/doctype/report_filter/report_filter.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/role/role.py b/frappe/core/doctype/role/role.py index 2119f3caa1..97a0e9b581 100644 --- a/frappe/core/doctype/role/role.py +++ b/frappe/core/doctype/role/role.py @@ -99,7 +99,7 @@ def get_users(role): @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs def role_query(doctype, txt, searchfield, start, page_len, filters): - report_filters = [["Role", "name", "like", "%{}%".format(txt)], ["Role", "is_custom", "=", 0]] + report_filters = [["Role", "name", "like", f"%{txt}%"], ["Role", "is_custom", "=", 0]] if filters and isinstance(filters, list): report_filters.extend(filters) diff --git a/frappe/core/doctype/role_permission_for_page_and_report/role_permission_for_page_and_report.py b/frappe/core/doctype/role_permission_for_page_and_report/role_permission_for_page_and_report.py index d89131b0d7..bd61995ba3 100644 --- a/frappe/core/doctype/role_permission_for_page_and_report/role_permission_for_page_and_report.py +++ b/frappe/core/doctype/role_permission_for_page_and_report/role_permission_for_page_and_report.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/role_profile/role_profile.py b/frappe/core/doctype/role_profile/role_profile.py index ab4660d7c9..a8abd6d1c1 100644 --- a/frappe/core/doctype/role_profile/role_profile.py +++ b/frappe/core/doctype/role_profile/role_profile.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/role_profile/test_role_profile.py b/frappe/core/doctype/role_profile/test_role_profile.py index 19239a81cd..726a5fc83e 100644 --- a/frappe/core/doctype/role_profile/test_role_profile.py +++ b/frappe/core/doctype/role_profile/test_role_profile.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/scheduled_job_log/scheduled_job_log.py b/frappe/core/doctype/scheduled_job_log/scheduled_job_log.py index 68541a36a0..01fa837af0 100644 --- a/frappe/core/doctype/scheduled_job_log/scheduled_job_log.py +++ b/frappe/core/doctype/scheduled_job_log/scheduled_job_log.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/scheduled_job_log/test_scheduled_job_log.py b/frappe/core/doctype/scheduled_job_log/test_scheduled_job_log.py index 3c99bb5cb8..11d60e35d8 100644 --- a/frappe/core/doctype/scheduled_job_log/test_scheduled_job_log.py +++ b/frappe/core/doctype/scheduled_job_log/test_scheduled_job_log.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/core/doctype/scheduled_job_type/scheduled_job_type.py b/frappe/core/doctype/scheduled_job_type/scheduled_job_type.py index 673805ae8b..f898311ca3 100644 --- a/frappe/core/doctype/scheduled_job_type/scheduled_job_type.py +++ b/frappe/core/doctype/scheduled_job_type/scheduled_job_type.py @@ -3,7 +3,6 @@ import json from datetime import datetime -from typing import Dict, List from croniter import croniter @@ -138,14 +137,14 @@ def run_scheduled_job(job_type: str): print(frappe.get_traceback()) -def sync_jobs(hooks: Dict = None): +def sync_jobs(hooks: dict = None): frappe.reload_doc("core", "doctype", "scheduled_job_type") scheduler_events = hooks or frappe.get_hooks("scheduler_events") all_events = insert_events(scheduler_events) clear_events(all_events) -def insert_events(scheduler_events: Dict) -> List: +def insert_events(scheduler_events: dict) -> list: cron_jobs, event_jobs = [], [] for event_type in scheduler_events: events = scheduler_events.get(event_type) @@ -157,7 +156,7 @@ def insert_events(scheduler_events: Dict) -> List: return cron_jobs + event_jobs -def insert_cron_jobs(events: Dict) -> List: +def insert_cron_jobs(events: dict) -> list: cron_jobs = [] for cron_format in events: for event in events.get(cron_format): @@ -166,7 +165,7 @@ def insert_cron_jobs(events: Dict) -> List: return cron_jobs -def insert_event_jobs(events: List, event_type: str) -> List: +def insert_event_jobs(events: list, event_type: str) -> list: event_jobs = [] for event in events: event_jobs.append(event) @@ -199,7 +198,7 @@ def insert_single_event(frequency: str, event: str, cron_format: str = None): doc.insert() -def clear_events(all_events: List): +def clear_events(all_events: list): for event in frappe.get_all("Scheduled Job Type", fields=["name", "method", "server_script"]): is_server_script = event.server_script is_defined_in_hooks = event.method in all_events diff --git a/frappe/core/doctype/scheduled_job_type/test_scheduled_job_type.py b/frappe/core/doctype/scheduled_job_type/test_scheduled_job_type.py index 3e63985692..5448bda91f 100644 --- a/frappe/core/doctype/scheduled_job_type/test_scheduled_job_type.py +++ b/frappe/core/doctype/scheduled_job_type/test_scheduled_job_type.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/server_script/server_script.py b/frappe/core/doctype/server_script/server_script.py index 5fd59e1014..fda5ca8591 100644 --- a/frappe/core/doctype/server_script/server_script.py +++ b/frappe/core/doctype/server_script/server_script.py @@ -1,9 +1,7 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE from types import FunctionType, MethodType, ModuleType -from typing import Dict, List import frappe from frappe import _ @@ -31,7 +29,7 @@ class ServerScript(Document): return {"script": "py"} @property - def scheduled_jobs(self) -> List[Dict[str, str]]: + def scheduled_jobs(self) -> list[dict[str, str]]: return frappe.get_all( "Scheduled Job Type", filters={"server_script": self.name}, @@ -69,7 +67,7 @@ class ServerScript(Document): except Exception as e: frappe.msgprint(str(e), title=_("Compilation warning")) - def execute_method(self) -> Dict: + def execute_method(self) -> dict: """Specific to API endpoint Server Scripts Raises: @@ -110,7 +108,7 @@ class ServerScript(Document): safe_exec(self.script) - def get_permission_query_conditions(self, user: str) -> List[str]: + def get_permission_query_conditions(self, user: str) -> list[str]: """Specific to Permission Query Server Scripts Args: diff --git a/frappe/core/doctype/server_script/test_server_script.py b/frappe/core/doctype/server_script/test_server_script.py index fd600b8205..4c1c12b7f2 100644 --- a/frappe/core/doctype/server_script/test_server_script.py +++ b/frappe/core/doctype/server_script/test_server_script.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/session_default/session_default.py b/frappe/core/doctype/session_default/session_default.py index df261f4a39..3fada1b5e0 100644 --- a/frappe/core/doctype/session_default/session_default.py +++ b/frappe/core/doctype/session_default/session_default.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/session_default_settings/session_default_settings.py b/frappe/core/doctype/session_default_settings/session_default_settings.py index 4ac9b61553..2b0d731920 100644 --- a/frappe/core/doctype/session_default_settings/session_default_settings.py +++ b/frappe/core/doctype/session_default_settings/session_default_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/session_default_settings/test_session_default_settings.py b/frappe/core/doctype/session_default_settings/test_session_default_settings.py index f763f90a1d..aa60085ce9 100644 --- a/frappe/core/doctype/session_default_settings/test_session_default_settings.py +++ b/frappe/core/doctype/session_default_settings/test_session_default_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/sms_parameter/__init__.py b/frappe/core/doctype/sms_parameter/__init__.py index 8b13789179..e69de29bb2 100755 --- a/frappe/core/doctype/sms_parameter/__init__.py +++ b/frappe/core/doctype/sms_parameter/__init__.py @@ -1 +0,0 @@ - diff --git a/frappe/core/doctype/sms_settings/__init__.py b/frappe/core/doctype/sms_settings/__init__.py index 8b13789179..e69de29bb2 100755 --- a/frappe/core/doctype/sms_settings/__init__.py +++ b/frappe/core/doctype/sms_settings/__init__.py @@ -1 +0,0 @@ - diff --git a/frappe/core/doctype/sms_settings/sms_settings.py b/frappe/core/doctype/sms_settings/sms_settings.py index e1da200ee5..686890514a 100644 --- a/frappe/core/doctype/sms_settings/sms_settings.py +++ b/frappe/core/doctype/sms_settings/sms_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/sms_settings/test_sms_settings.py b/frappe/core/doctype/sms_settings/test_sms_settings.py index da1b807594..61be20ff66 100644 --- a/frappe/core/doctype/sms_settings/test_sms_settings.py +++ b/frappe/core/doctype/sms_settings/test_sms_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/success_action/success_action.py b/frappe/core/doctype/success_action/success_action.py index 95a81ee0fb..e3db646a2e 100644 --- a/frappe/core/doctype/success_action/success_action.py +++ b/frappe/core/doctype/success_action/success_action.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/system_settings/test_system_settings.py b/frappe/core/doctype/system_settings/test_system_settings.py index 410762b4e7..b126976eeb 100644 --- a/frappe/core/doctype/system_settings/test_system_settings.py +++ b/frappe/core/doctype/system_settings/test_system_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/test/test.py b/frappe/core/doctype/test/test.py index 8f3cf7111d..664d06ac84 100644 --- a/frappe/core/doctype/test/test.py +++ b/frappe/core/doctype/test/test.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -15,7 +14,7 @@ class test(Document): json.dump(d, read_file) def load_from_db(self): - with open("data_file.json", "r") as read_file: + with open("data_file.json") as read_file: d = json.load(read_file) super(Document, self).__init__(d) @@ -25,20 +24,20 @@ class test(Document): json.dump(d, read_file) def get_list(self, args): - with open("data_file.json", "r") as read_file: + with open("data_file.json") as read_file: return [json.load(read_file)] def get_value(self, fields, filters, **kwargs): # return [] - with open("data_file.json", "r") as read_file: + with open("data_file.json") as read_file: return [json.load(read_file)] def get_count(self, args): # return [] - with open("data_file.json", "r") as read_file: + with open("data_file.json") as read_file: return [json.load(read_file)] def get_stats(self, args): # return [] - with open("data_file.json", "r") as read_file: + with open("data_file.json") as read_file: return [json.load(read_file)] diff --git a/frappe/core/doctype/test/test_test.py b/frappe/core/doctype/test/test_test.py index e4ee3de5dd..6080c200c1 100644 --- a/frappe/core/doctype/test/test_test.py +++ b/frappe/core/doctype/test/test_test.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/core/doctype/transaction_log/test_transaction_log.py b/frappe/core/doctype/transaction_log/test_transaction_log.py index a4bb066eea..8b179f8d85 100644 --- a/frappe/core/doctype/transaction_log/test_transaction_log.py +++ b/frappe/core/doctype/transaction_log/test_transaction_log.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors # License: MIT. See LICENSE import hashlib diff --git a/frappe/core/doctype/translation/test_translation.py b/frappe/core/doctype/translation/test_translation.py index df5ae3767a..c9f4e85086 100644 --- a/frappe/core/doctype/translation/test_translation.py +++ b/frappe/core/doctype/translation/test_translation.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/translation/translation.py b/frappe/core/doctype/translation/translation.py index 90ea4d1523..b08198eb13 100644 --- a/frappe/core/doctype/translation/translation.py +++ b/frappe/core/doctype/translation/translation.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index cfb2f4d871..bc5c20eb92 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -489,7 +489,7 @@ class User(Document): self.save() def remove_roles(self, *roles): - existing_roles = dict((d.role, d) for d in self.get("roles")) + existing_roles = {d.role: d for d in self.get("roles")} for role in roles: if role in existing_roles: self.get("roles").remove(existing_roles[role]) @@ -498,7 +498,7 @@ class User(Document): def remove_all_roles_for_guest(self): if self.name == "Guest": - self.set("roles", list(set(d for d in self.get("roles") if d.role == "Guest"))) + self.set("roles", list({d for d in self.get("roles") if d.role == "Guest"})) def remove_disabled_roles(self): disabled_roles = [d.name for d in frappe.get_all("Role", filters={"disabled": 1})] @@ -557,7 +557,7 @@ class User(Document): if not username: # @firstname_last_name username = _check_suggestion( - frappe.scrub("{0} {1}".format(self.first_name, self.last_name or "")) + frappe.scrub("{} {}".format(self.first_name, self.last_name or "")) ) if username: @@ -918,7 +918,7 @@ def user_query(doctype, txt, searchfield, start, page_len, filters): user_type_condition = "" filters.pop("ignore_user_type") - txt = "%{}%".format(txt) + txt = f"%{txt}%" return frappe.db.sql( """SELECT `name`, CONCAT_WS(' ', first_name, middle_name, last_name) FROM `tabUser` @@ -970,7 +970,7 @@ def get_system_users(exclude_users=None, limit=None): limit_cond = "" if limit: - limit_cond = "limit {0}".format(limit) + limit_cond = f"limit {limit}" exclude_users += list(STANDARD_USERS) @@ -1036,7 +1036,7 @@ def notify_admin_access_to_system_manager(login_manager=None): ): site = '{0}'.format(frappe.local.request.host_url) - date_and_time = "{0}".format(format_datetime(now_datetime(), format_string="medium")) + date_and_time = "{}".format(format_datetime(now_datetime(), format_string="medium")) ip_address = frappe.local.request_ip access_message = _("Administrator accessed {0} on {1} via IP Address {2}.").format( diff --git a/frappe/core/doctype/user_document_type/user_document_type.py b/frappe/core/doctype/user_document_type/user_document_type.py index 1e7eab4bd4..731acf582b 100644 --- a/frappe/core/doctype/user_document_type/user_document_type.py +++ b/frappe/core/doctype/user_document_type/user_document_type.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/user_email/user_email.py b/frappe/core/doctype/user_email/user_email.py index 21167ad25d..ebca480f47 100644 --- a/frappe/core/doctype/user_email/user_email.py +++ b/frappe/core/doctype/user_email/user_email.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/user_group/test_user_group.py b/frappe/core/doctype/user_group/test_user_group.py index 546d4fd54c..368f4eaef2 100644 --- a/frappe/core/doctype/user_group/test_user_group.py +++ b/frappe/core/doctype/user_group/test_user_group.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/core/doctype/user_group/user_group.py b/frappe/core/doctype/user_group/user_group.py index a59117426f..812f230f7a 100644 --- a/frappe/core/doctype/user_group/user_group.py +++ b/frappe/core/doctype/user_group/user_group.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/user_group_member/test_user_group_member.py b/frappe/core/doctype/user_group_member/test_user_group_member.py index f1bdc41cff..5d709d0bec 100644 --- a/frappe/core/doctype/user_group_member/test_user_group_member.py +++ b/frappe/core/doctype/user_group_member/test_user_group_member.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/core/doctype/user_group_member/user_group_member.py b/frappe/core/doctype/user_group_member/user_group_member.py index 6b948d797f..e9722a07ad 100644 --- a/frappe/core/doctype/user_group_member/user_group_member.py +++ b/frappe/core/doctype/user_group_member/user_group_member.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/user_select_document_type/user_select_document_type.py b/frappe/core/doctype/user_select_document_type/user_select_document_type.py index 07b8123a13..9cf2e4856d 100644 --- a/frappe/core/doctype/user_select_document_type/user_select_document_type.py +++ b/frappe/core/doctype/user_select_document_type/user_select_document_type.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/user_social_login/user_social_login.py b/frappe/core/doctype/user_social_login/user_social_login.py index d12b5823d1..4cf3f720cd 100644 --- a/frappe/core/doctype/user_social_login/user_social_login.py +++ b/frappe/core/doctype/user_social_login/user_social_login.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/user_type/test_user_type.py b/frappe/core/doctype/user_type/test_user_type.py index 53999ed3df..235881517a 100644 --- a/frappe/core/doctype/user_type/test_user_type.py +++ b/frappe/core/doctype/user_type/test_user_type.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/user_type/user_type.py b/frappe/core/doctype/user_type/user_type.py index 7efb66f569..369e70bf56 100644 --- a/frappe/core/doctype/user_type/user_type.py +++ b/frappe/core/doctype/user_type/user_type.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -211,7 +210,7 @@ def get_user_linked_doctypes(doctype, txt, searchfield, start, page_len, filters ["DocType", "issingle", "=", 0], ["DocType", "module", "not in", modules], ["DocType", "read_only", "=", 0], - ["DocType", "name", "like", "%{0}%".format(txt)], + ["DocType", "name", "like", f"%{txt}%"], ] doctypes = frappe.get_all( @@ -225,7 +224,7 @@ def get_user_linked_doctypes(doctype, txt, searchfield, start, page_len, filters ) custom_dt_filters = [ - ["Custom Field", "dt", "like", "%{0}%".format(txt)], + ["Custom Field", "dt", "like", f"%{txt}%"], ["Custom Field", "options", "=", "User"], ["Custom Field", "fieldtype", "=", "Link"], ] diff --git a/frappe/core/doctype/user_type_module/user_type_module.py b/frappe/core/doctype/user_type_module/user_type_module.py index 83662bfcaf..1dc7c849e8 100644 --- a/frappe/core/doctype/user_type_module/user_type_module.py +++ b/frappe/core/doctype/user_type_module/user_type_module.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/doctype/version/version.py b/frappe/core/doctype/version/version.py index fa6ba0a9cf..99eeb8c2b0 100644 --- a/frappe/core/doctype/version/version.py +++ b/frappe/core/doctype/version/version.py @@ -2,7 +2,6 @@ # License: MIT. See LICENSE import json -from typing import Optional import frappe from frappe.model import no_value_fields, table_fields @@ -10,7 +9,7 @@ from frappe.model.document import Document class Version(Document): - def update_version_info(self, old: Optional[Document], new: Document) -> bool: + def update_version_info(self, old: Document | None, new: Document) -> bool: """Update changed info and return true if change contains useful data.""" if not old: # Check if doc has some information about creation source like data import diff --git a/frappe/core/doctype/view_log/test_view_log.py b/frappe/core/doctype/view_log/test_view_log.py index 04a17cc526..5a88269028 100644 --- a/frappe/core/doctype/view_log/test_view_log.py +++ b/frappe/core/doctype/view_log/test_view_log.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/core/doctype/view_log/view_log.py b/frappe/core/doctype/view_log/view_log.py index 6156fb74df..8383af818e 100644 --- a/frappe/core/doctype/view_log/view_log.py +++ b/frappe/core/doctype/view_log/view_log.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/core/page/background_jobs/background_jobs.py b/frappe/core/page/background_jobs/background_jobs.py index 8c3c8ff41e..8ef15b65eb 100644 --- a/frappe/core/page/background_jobs/background_jobs.py +++ b/frappe/core/page/background_jobs/background_jobs.py @@ -1,7 +1,7 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE -from typing import TYPE_CHECKING, Dict, List +from typing import TYPE_CHECKING import frappe from frappe.utils import convert_utc_to_user_timezone @@ -15,7 +15,7 @@ JOB_COLORS = {"queued": "orange", "failed": "red", "started": "blue", "finished" @frappe.whitelist() -def get_info(view=None, queue_timeout=None, job_status=None) -> List[Dict]: +def get_info(view=None, queue_timeout=None, job_status=None) -> list[dict]: jobs = [] def add_job(job: "Job", queue: str) -> None: diff --git a/frappe/core/page/permission_manager/permission_manager.py b/frappe/core/page/permission_manager/permission_manager.py index e2d08488c0..46c9e0aca2 100644 --- a/frappe/core/page/permission_manager/permission_manager.py +++ b/frappe/core/page/permission_manager/permission_manager.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE -from typing import Optional import frappe import frappe.defaults @@ -71,7 +70,7 @@ def get_roles_and_doctypes(): @frappe.whitelist() -def get_permissions(doctype: Optional[str] = None, role: Optional[str] = None): +def get_permissions(doctype: str | None = None, role: str | None = None): frappe.only_for("System Manager") if role: diff --git a/frappe/core/report/permitted_documents_for_user/permitted_documents_for_user.py b/frappe/core/report/permitted_documents_for_user/permitted_documents_for_user.py index 6d7f394beb..362cc6b105 100644 --- a/frappe/core/report/permitted_documents_for_user/permitted_documents_for_user.py +++ b/frappe/core/report/permitted_documents_for_user/permitted_documents_for_user.py @@ -37,12 +37,12 @@ def validate(user, doctype): def get_columns_and_fields(doctype): - columns = ["Name:Link/{}:200".format(doctype)] + columns = [f"Name:Link/{doctype}:200"] fields = ["`name`"] for df in frappe.get_meta(doctype).fields: if df.in_list_view and df.fieldtype in data_fieldtypes: - fields.append("`{0}`".format(df.fieldname)) - fieldtype = "Link/{}".format(df.options) if df.fieldtype == "Link" else df.fieldtype + fields.append(f"`{df.fieldname}`") + fieldtype = f"Link/{df.options}" if df.fieldtype == "Link" else df.fieldtype columns.append( "{label}:{fieldtype}:{width}".format( label=df.label, fieldtype=fieldtype, width=df.width or 100 diff --git a/frappe/custom/doctype/client_script/test_client_script.py b/frappe/custom/doctype/client_script/test_client_script.py index 7497ab7780..c93df04c98 100644 --- a/frappe/custom/doctype/client_script/test_client_script.py +++ b/frappe/custom/doctype/client_script/test_client_script.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/custom/doctype/custom_field/test_custom_field.py b/frappe/custom/doctype/custom_field/test_custom_field.py index 519ea7f2b4..34223315c5 100644 --- a/frappe/custom/doctype/custom_field/test_custom_field.py +++ b/frappe/custom/doctype/custom_field/test_custom_field.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE diff --git a/frappe/custom/doctype/customize_form/customize_form.py b/frappe/custom/doctype/customize_form/customize_form.py index 20c3a7c025..4923bfc525 100644 --- a/frappe/custom/doctype/customize_form/customize_form.py +++ b/frappe/custom/doctype/customize_form/customize_form.py @@ -330,7 +330,7 @@ class CustomizeForm(Document): We need to maintain the order of the link/actions if the user has shuffled them. So we create a new property (ex `links_order`) to keep a list of items. """ - property_name = "{}_order".format(fieldname) + property_name = f"{fieldname}_order" if has_custom: # save the order of the actions and links self.make_property_setter( diff --git a/frappe/custom/doctype/doctype_layout/doctype_layout.py b/frappe/custom/doctype/doctype_layout/doctype_layout.py index f5d37d6f60..ea8e9acc99 100644 --- a/frappe/custom/doctype/doctype_layout/doctype_layout.py +++ b/frappe/custom/doctype/doctype_layout/doctype_layout.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/custom/doctype/doctype_layout/test_doctype_layout.py b/frappe/custom/doctype/doctype_layout/test_doctype_layout.py index 1373b4a53a..0e64a9e727 100644 --- a/frappe/custom/doctype/doctype_layout/test_doctype_layout.py +++ b/frappe/custom/doctype/doctype_layout/test_doctype_layout.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/custom/doctype/doctype_layout_field/doctype_layout_field.py b/frappe/custom/doctype/doctype_layout_field/doctype_layout_field.py index 66fc111d32..f2b8c2b40b 100644 --- a/frappe/custom/doctype/doctype_layout_field/doctype_layout_field.py +++ b/frappe/custom/doctype/doctype_layout_field/doctype_layout_field.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/custom/doctype/property_setter/test_property_setter.py b/frappe/custom/doctype/property_setter/test_property_setter.py index a1bbc69235..1fa2d2cefb 100644 --- a/frappe/custom/doctype/property_setter/test_property_setter.py +++ b/frappe/custom/doctype/property_setter/test_property_setter.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/custom/doctype/test_rename_new/test_rename_new.py b/frappe/custom/doctype/test_rename_new/test_rename_new.py index e79cb60bbe..ed89d1fad1 100644 --- a/frappe/custom/doctype/test_rename_new/test_rename_new.py +++ b/frappe/custom/doctype/test_rename_new/test_rename_new.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/custom/doctype/test_rename_new/test_test_rename_new.py b/frappe/custom/doctype/test_rename_new/test_test_rename_new.py index 513a9286a3..f1ccf42ede 100644 --- a/frappe/custom/doctype/test_rename_new/test_test_rename_new.py +++ b/frappe/custom/doctype/test_rename_new/test_test_rename_new.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/database/database.py b/frappe/database/database.py index a52264ed6d..09d3424837 100644 --- a/frappe/database/database.py +++ b/frappe/database/database.py @@ -10,7 +10,6 @@ import re import string from contextlib import contextmanager from time import time -from typing import Dict, List, Optional, Tuple, Union from pypika.terms import Criterion, NullValue, PseudoColumn @@ -31,11 +30,11 @@ SINGLE_WORD_PATTERN = re.compile(r'([`"]?)(tab([A-Z]\w+))\1') MULTI_WORD_PATTERN = re.compile(r'([`"])(tab([A-Z]\w+)( [A-Z]\w+)+)\1') -def is_query_type(query: str, query_type: Union[str, Tuple[str]]) -> bool: +def is_query_type(query: str, query_type: str | tuple[str]) -> bool: return query.lstrip().split(maxsplit=1)[0].lower().startswith(query_type) -class Database(object): +class Database: """ Open a database connection with the given parmeters, if use_default is True, use the login details from `conf.py`. This is called by the request handler and is accessible using @@ -195,7 +194,7 @@ class Database(object): if debug: time_end = time() - frappe.errprint(("Execution time: {0} sec").format(round(time_end - time_start, 2))) + frappe.errprint(("Execution time: {} sec").format(round(time_end - time_start, 2))) except Exception as e: if self.is_syntax_error(e): @@ -670,8 +669,8 @@ class Database(object): def set_single_value( self, doctype: str, - fieldname: Union[str, Dict], - value: Optional[Union[str, int]] = None, + fieldname: str | dict, + value: str | int | None = None, *args, **kwargs, ): @@ -1023,7 +1022,7 @@ class Database(object): def a_row_exists(self, doctype): """Returns True if atleast one row exists.""" - return self.sql("select name from `tab{doctype}` limit 1".format(doctype=doctype)) + return self.sql(f"select name from `tab{doctype}` limit 1") def exists(self, dt, dn=None, cache=False): """Return the document name of a matching document, or None. @@ -1063,13 +1062,13 @@ class Database(object): def count(self, dt, filters=None, debug=False, cache=False, distinct: bool = True): """Returns `COUNT(*)` for given DocType and filters.""" if cache and not filters: - cache_count = frappe.cache().get_value("doctype:count:{}".format(dt)) + cache_count = frappe.cache().get_value(f"doctype:count:{dt}") if cache_count is not None: return cache_count query = self.query.get_sql(table=dt, filters=filters, fields=Count("*"), distinct=distinct) count = self.sql(query, debug=debug)[0][0] if not filters and cache: - frappe.cache().set_value("doctype:count:{}".format(dt), count, expires_in_sec=86400) + frappe.cache().set_value(f"doctype:count:{dt}", count, expires_in_sec=86400) return count @staticmethod @@ -1103,7 +1102,7 @@ class Database(object): now_datetime() - relativedelta(minutes=minutes), )[0][0] - def get_db_table_columns(self, table) -> List[str]: + def get_db_table_columns(self, table) -> list[str]: """Returns list of column names from given table.""" columns = frappe.cache().hget("table_columns", table) if columns is None: @@ -1137,7 +1136,7 @@ class Database(object): def get_column_type(self, doctype, column): return self.sql( """SELECT column_type FROM INFORMATION_SCHEMA.COLUMNS - WHERE table_name = 'tab{0}' AND column_name = '{1}' """.format( + WHERE table_name = 'tab{}' AND column_name = '{}' """.format( doctype, column ) )[0][0] @@ -1199,7 +1198,7 @@ class Database(object): query = sql_dict.get(current_dialect) return self.sql(query, values, **kwargs) - def delete(self, doctype: str, filters: Union[Dict, List] = None, debug=False, **kwargs): + def delete(self, doctype: str, filters: dict | list = None, debug=False, **kwargs): """Delete rows from a table in site which match the passed filters. This does trigger DocType hooks. Simply runs a DELETE query in the database. @@ -1305,7 +1304,7 @@ def enqueue_jobs_after_commit(): @contextmanager -def savepoint(catch: Union[type, Tuple[type, ...]] = Exception): +def savepoint(catch: type | tuple[type, ...] = Exception): """Wrapper for wrapping blocks of DB operations in a savepoint. as contextmanager: diff --git a/frappe/database/db_manager.py b/frappe/database/db_manager.py index 8f810fe54b..796f23a054 100644 --- a/frappe/database/db_manager.py +++ b/frappe/database/db_manager.py @@ -20,15 +20,15 @@ class DbManager: host = self.get_current_host() if password: - self.db.sql("CREATE USER '%s'@'%s' IDENTIFIED BY '%s';" % (user, host, password)) + self.db.sql(f"CREATE USER '{user}'@'{host}' IDENTIFIED BY '{password}';") else: - self.db.sql("CREATE USER '%s'@'%s';" % (user, host)) + self.db.sql(f"CREATE USER '{user}'@'{host}';") def delete_user(self, target, host=None): if not host: host = self.get_current_host() try: - self.db.sql("DROP USER '%s'@'%s';" % (target, host)) + self.db.sql(f"DROP USER '{target}'@'{host}';") except Exception as e: if e.args[0] == 1396: pass @@ -54,7 +54,7 @@ class DbManager: % (target, user, host) ) else: - self.db.sql("GRANT ALL PRIVILEGES ON `%s`.* TO '%s'@'%s';" % (target, user, host)) + self.db.sql(f"GRANT ALL PRIVILEGES ON `{target}`.* TO '{user}'@'{host}';") def flush_privileges(self): self.db.sql("FLUSH PRIVILEGES") @@ -73,11 +73,11 @@ class DbManager: pv = find_executable("pv") if pv: - pipe = "{pv} {source} |".format(pv=pv, source=source) + pipe = f"{pv} {source} |" source = "" else: pipe = "" - source = "< {source}".format(source=source) + source = f"< {source}" if pipe: print("Restoring Database file...") diff --git a/frappe/database/mariadb/database.py b/frappe/database/mariadb/database.py index 7505ef3a7f..047039b0df 100644 --- a/frappe/database/mariadb/database.py +++ b/frappe/database/mariadb/database.py @@ -1,5 +1,3 @@ -from typing import List, Tuple, Union - import pymysql from pymysql.constants import ER, FIELD_TYPE from pymysql.converters import conversions, escape_string @@ -144,18 +142,18 @@ class MariaDBDatabase(Database): def is_type_datetime(code): return code in (pymysql.DATE, pymysql.DATETIME) - def rename_table(self, old_name: str, new_name: str) -> Union[List, Tuple]: + def rename_table(self, old_name: str, new_name: str) -> list | tuple: old_name = get_table_name(old_name) new_name = get_table_name(new_name) return self.sql(f"RENAME TABLE `{old_name}` TO `{new_name}`") - def describe(self, doctype: str) -> Union[List, Tuple]: + def describe(self, doctype: str) -> list | tuple: table_name = get_table_name(doctype) return self.sql(f"DESC `{table_name}`") def change_column_type( self, doctype: str, column: str, type: str, nullable: bool = False - ) -> Union[List, Tuple]: + ) -> list | tuple: table_name = get_table_name(doctype) null_constraint = "NOT NULL" if not nullable else "" return self.sql_ddl(f"ALTER TABLE `{table_name}` MODIFY `{column}` {type} {null_constraint}") @@ -303,7 +301,7 @@ class MariaDBDatabase(Database): ) ) - def add_index(self, doctype: str, fields: List, index_name: str = None): + def add_index(self, doctype: str, fields: list, index_name: str = None): """Creates an index with given fields if not already created. Index name will be `fieldname1_fieldname2_index`""" index_name = index_name or self.get_index_name(fields) @@ -343,7 +341,7 @@ class MariaDBDatabase(Database): """ res = self.sql("select issingle from `tabDocType` where name=%s", (doctype,)) if not res: - raise Exception("Wrong doctype {0} in updatedb".format(doctype)) + raise Exception(f"Wrong doctype {doctype} in updatedb") if not res[0][0]: db_table = MariaDBTable(doctype, meta) diff --git a/frappe/database/mariadb/schema.py b/frappe/database/mariadb/schema.py index f402b4ec74..24a78012e1 100644 --- a/frappe/database/mariadb/schema.py +++ b/frappe/database/mariadb/schema.py @@ -77,15 +77,15 @@ class MariaDBTable(DBTable): columns_to_modify = set(self.change_type + self.add_unique + self.set_default) for col in self.add_column: - add_column_query.append("ADD COLUMN `{}` {}".format(col.fieldname, col.get_definition())) + add_column_query.append(f"ADD COLUMN `{col.fieldname}` {col.get_definition()}") for col in columns_to_modify: - modify_column_query.append("MODIFY `{}` {}".format(col.fieldname, col.get_definition())) + modify_column_query.append(f"MODIFY `{col.fieldname}` {col.get_definition()}") for col in self.add_index: # if index key does not exists if not frappe.db.has_index(self.table_name, col.fieldname + "_index"): - add_index_query.append("ADD INDEX `{}_index`(`{}`)".format(col.fieldname, col.fieldname)) + add_index_query.append(f"ADD INDEX `{col.fieldname}_index`(`{col.fieldname}`)") for col in self.drop_index + self.drop_unique: if col.fieldname != "name": # primary key @@ -95,7 +95,7 @@ class MariaDBTable(DBTable): # nosemgrep unique_index_record = frappe.db.sql( """ - SHOW INDEX FROM `{0}` + SHOW INDEX FROM `{}` WHERE Key_name=%s AND Non_unique=0 """.format( @@ -105,14 +105,14 @@ class MariaDBTable(DBTable): as_dict=1, ) if unique_index_record: - drop_index_query.append("DROP INDEX `{}`".format(unique_index_record[0].Key_name)) + drop_index_query.append(f"DROP INDEX `{unique_index_record[0].Key_name}`") index_constraint_changed = current_column.index != col.set_index # if index key exists if index_constraint_changed and not col.set_index: # nosemgrep index_record = frappe.db.sql( """ - SHOW INDEX FROM `{0}` + SHOW INDEX FROM `{}` WHERE Key_name=%s AND Non_unique=1 """.format( @@ -122,13 +122,13 @@ class MariaDBTable(DBTable): as_dict=1, ) if index_record: - drop_index_query.append("DROP INDEX `{}`".format(index_record[0].Key_name)) + drop_index_query.append(f"DROP INDEX `{index_record[0].Key_name}`") try: for query_parts in [add_column_query, modify_column_query, add_index_query, drop_index_query]: if query_parts: query_body = ", ".join(query_parts) - query = "ALTER TABLE `{}` {}".format(self.table_name, query_body) + query = f"ALTER TABLE `{self.table_name}` {query_body}" frappe.db.sql(query) except Exception as e: diff --git a/frappe/database/mariadb/setup_db.py b/frappe/database/mariadb/setup_db.py index 4399ccfa6a..5eef0ef2c6 100644 --- a/frappe/database/mariadb/setup_db.py +++ b/frappe/database/mariadb/setup_db.py @@ -42,7 +42,7 @@ def setup_database(force, source_sql, verbose, no_mariadb_socket=False): dbman.delete_user(db_name, **dbman_kwargs) dbman.drop_database(db_name) else: - raise Exception("Database %s already exists" % (db_name,)) + raise Exception(f"Database {db_name} already exists") dbman.create_user(db_name, frappe.conf.db_password, **dbman_kwargs) if verbose: @@ -55,7 +55,7 @@ def setup_database(force, source_sql, verbose, no_mariadb_socket=False): dbman.grant_all_privileges(db_name, db_name, **dbman_kwargs) dbman.flush_privileges() if verbose: - print("Granted privileges to user %s and database %s" % (db_name, db_name)) + print(f"Granted privileges to user {db_name} and database {db_name}") # close root connection root_conn.close() diff --git a/frappe/database/postgres/database.py b/frappe/database/postgres/database.py index f9a4723d72..2553ebaa26 100644 --- a/frappe/database/postgres/database.py +++ b/frappe/database/postgres/database.py @@ -1,5 +1,4 @@ import re -from typing import List, Tuple, Union import psycopg2 import psycopg2.extensions @@ -118,9 +117,7 @@ class PostgresDatabase(Database): # pylint: disable=W0221 def sql(self, query, values=(), *args, **kwargs): - return super(PostgresDatabase, self).sql( - modify_query(query), modify_values(values), *args, **kwargs - ) + return super().sql(modify_query(query), modify_values(values), *args, **kwargs) def get_tables(self, cached=True): return [ @@ -128,9 +125,9 @@ class PostgresDatabase(Database): for d in self.sql( """select table_name from information_schema.tables - where table_catalog='{0}' + where table_catalog='{}' and table_type = 'BASE TABLE' - and table_schema='{1}'""".format( + and table_schema='{}'""".format( frappe.conf.db_name, frappe.conf.get("db_schema", "public") ) ) @@ -208,12 +205,12 @@ class PostgresDatabase(Database): def is_data_too_long(e): return e.pgcode == STRING_DATA_RIGHT_TRUNCATION - def rename_table(self, old_name: str, new_name: str) -> Union[List, Tuple]: + def rename_table(self, old_name: str, new_name: str) -> list | tuple: old_name = get_table_name(old_name) new_name = get_table_name(new_name) return self.sql(f"ALTER TABLE `{old_name}` RENAME TO `{new_name}`") - def describe(self, doctype: str) -> Union[List, Tuple]: + def describe(self, doctype: str) -> list | tuple: table_name = get_table_name(doctype) return self.sql( f"SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_NAME = '{table_name}'" @@ -221,7 +218,7 @@ class PostgresDatabase(Database): def change_column_type( self, doctype: str, column: str, type: str, nullable: bool = False, use_cast: bool = False - ) -> Union[List, Tuple]: + ) -> list | tuple: table_name = get_table_name(doctype) null_constraint = "SET NOT NULL" if not nullable else "DROP NOT NULL" using_cast = f'using "{column}"::{type}' if use_cast else "" @@ -290,9 +287,9 @@ class PostgresDatabase(Database): * updates columns * updates indices """ - res = self.sql("select issingle from `tabDocType` where name='{}'".format(doctype)) + res = self.sql(f"select issingle from `tabDocType` where name='{doctype}'") if not res: - raise Exception("Wrong doctype {0} in updatedb".format(doctype)) + raise Exception(f"Wrong doctype {doctype} in updatedb") if not res[0][0]: db_table = PostgresTable(doctype, meta) @@ -306,7 +303,7 @@ class PostgresDatabase(Database): def get_on_duplicate_update(key="name"): if isinstance(key, list): key = '", "'.join(key) - return 'ON CONFLICT ("{key}") DO UPDATE SET '.format(key=key) + return f'ON CONFLICT ("{key}") DO UPDATE SET ' def check_implicit_commit(self, query): pass # postgres can run DDL in transactions without implicit commits @@ -319,7 +316,7 @@ class PostgresDatabase(Database): ) ) - def add_index(self, doctype: str, fields: List, index_name: str = None): + def add_index(self, doctype: str, fields: list, index_name: str = None): """Creates an index with given fields if not already created. Index name will be `fieldname1_fieldname2_index`""" table_name = get_table_name(doctype) diff --git a/frappe/database/postgres/schema.py b/frappe/database/postgres/schema.py index ef7ba33e12..5e28c81455 100644 --- a/frappe/database/postgres/schema.py +++ b/frappe/database/postgres/schema.py @@ -79,7 +79,7 @@ class PostgresTable(DBTable): query = [] for col in self.add_column: - query.append("ADD COLUMN `{}` {}".format(col.fieldname, col.get_definition())) + query.append(f"ADD COLUMN `{col.fieldname}` {col.get_definition()}") for col in self.change_type: using_clause = "" @@ -87,12 +87,12 @@ class PostgresTable(DBTable): # The USING option of SET DATA TYPE can actually specify any expression # involving the old values of the row # read more https://www.postgresql.org/docs/9.1/sql-altertable.html - using_clause = "USING {}::timestamp without time zone".format(col.fieldname) + using_clause = f"USING {col.fieldname}::timestamp without time zone" elif col.fieldtype in ("Check"): - using_clause = "USING {}::smallint".format(col.fieldname) + using_clause = f"USING {col.fieldname}::smallint" query.append( - "ALTER COLUMN `{0}` TYPE {1} {2}".format( + "ALTER COLUMN `{}` TYPE {} {}".format( col.fieldname, get_definition(col.fieldtype, precision=col.precision, length=col.length), using_clause, @@ -113,9 +113,9 @@ class PostgresTable(DBTable): col_default = "NULL" else: - col_default = "{}".format(frappe.db.escape(col.default)) + col_default = f"{frappe.db.escape(col.default)}" - query.append("ALTER COLUMN `{}` SET DEFAULT {}".format(col.fieldname, col_default)) + query.append(f"ALTER COLUMN `{col.fieldname}` SET DEFAULT {col_default}") create_contraint_query = "" for col in self.add_index: @@ -139,13 +139,13 @@ class PostgresTable(DBTable): # primary key if col.fieldname != "name": # if index key exists - drop_contraint_query += 'DROP INDEX IF EXISTS "{}" ;'.format(col.fieldname) + drop_contraint_query += f'DROP INDEX IF EXISTS "{col.fieldname}" ;' for col in self.drop_unique: # primary key if col.fieldname != "name": # if index key exists - drop_contraint_query += 'DROP INDEX IF EXISTS "unique_{}" ;'.format(col.fieldname) + drop_contraint_query += f'DROP INDEX IF EXISTS "unique_{col.fieldname}" ;' try: if query: final_alter_query = "ALTER TABLE `{}` {}".format(self.table_name, ", ".join(query)) diff --git a/frappe/database/postgres/setup_db.py b/frappe/database/postgres/setup_db.py index 9a7f2b43c4..0a40e9eba7 100644 --- a/frappe/database/postgres/setup_db.py +++ b/frappe/database/postgres/setup_db.py @@ -7,12 +7,10 @@ def setup_database(force, source_sql=None, verbose=False): root_conn = get_root_connection(frappe.flags.root_login, frappe.flags.root_password) root_conn.commit() root_conn.sql("end") - root_conn.sql("DROP DATABASE IF EXISTS `{0}`".format(frappe.conf.db_name)) - root_conn.sql("DROP USER IF EXISTS {0}".format(frappe.conf.db_name)) - root_conn.sql("CREATE DATABASE `{0}`".format(frappe.conf.db_name)) - root_conn.sql( - "CREATE user {0} password '{1}'".format(frappe.conf.db_name, frappe.conf.db_password) - ) + root_conn.sql(f"DROP DATABASE IF EXISTS `{frappe.conf.db_name}`") + root_conn.sql(f"DROP USER IF EXISTS {frappe.conf.db_name}") + root_conn.sql(f"CREATE DATABASE `{frappe.conf.db_name}`") + root_conn.sql(f"CREATE user {frappe.conf.db_name} password '{frappe.conf.db_password}'") root_conn.sql("GRANT ALL PRIVILEGES ON DATABASE `{0}` TO {0}".format(frappe.conf.db_name)) root_conn.close() @@ -79,10 +77,10 @@ def import_db_from_sql(source_sql=None, verbose=False): def setup_help_database(help_db_name): root_conn = get_root_connection(frappe.flags.root_login, frappe.flags.root_password) - root_conn.sql("DROP DATABASE IF EXISTS `{0}`".format(help_db_name)) - root_conn.sql("DROP USER IF EXISTS {0}".format(help_db_name)) - root_conn.sql("CREATE DATABASE `{0}`".format(help_db_name)) - root_conn.sql("CREATE user {0} password '{1}'".format(help_db_name, help_db_name)) + root_conn.sql(f"DROP DATABASE IF EXISTS `{help_db_name}`") + root_conn.sql(f"DROP USER IF EXISTS {help_db_name}") + root_conn.sql(f"CREATE DATABASE `{help_db_name}`") + root_conn.sql(f"CREATE user {help_db_name} password '{help_db_name}'") root_conn.sql("GRANT ALL PRIVILEGES ON DATABASE `{0}` TO {0}".format(help_db_name)) diff --git a/frappe/database/query.py b/frappe/database/query.py index f7cc143cf7..c87117466b 100644 --- a/frappe/database/query.py +++ b/frappe/database/query.py @@ -1,7 +1,7 @@ import operator import re from functools import cached_property -from typing import Any, Callable, Dict, List, Tuple, Union +from typing import Any, Callable import frappe from frappe import _ @@ -26,7 +26,7 @@ def like(key: Field, value: str) -> frappe.qb: return key.like(value) -def func_in(key: Field, value: Union[List, Tuple]) -> frappe.qb: +def func_in(key: Field, value: list | tuple) -> frappe.qb: """Wrapper method for `IN` Args: @@ -52,7 +52,7 @@ def not_like(key: Field, value: str) -> frappe.qb: return key.not_like(value) -def func_not_in(key: Field, value: Union[List, Tuple]): +def func_not_in(key: Field, value: list | tuple): """Wrapper method for `NOT IN` Args: @@ -78,7 +78,7 @@ def func_regex(key: Field, value: str) -> frappe.qb: return key.regex(value) -def func_between(key: Field, value: Union[List, Tuple]) -> frappe.qb: +def func_between(key: Field, value: list | tuple) -> frappe.qb: """Wrapper method for `BETWEEN` Args: @@ -110,7 +110,7 @@ def func_timespan(key: Field, value: str) -> frappe.qb: return func_between(key, get_timespan_date_range(value)) -def make_function(key: Any, value: Union[int, str]): +def make_function(key: Any, value: int | str): """returns fucntion query Args: @@ -144,7 +144,7 @@ def change_orderby(order: str): # default operators -OPERATOR_MAP: Dict[str, Callable] = { +OPERATOR_MAP: dict[str, Callable] = { "+": operator.add, "=": operator.eq, "-": operator.sub, @@ -192,7 +192,7 @@ class Query: return all_operators - def get_condition(self, table: Union[str, Table], **kwargs) -> frappe.qb: + def get_condition(self, table: str | Table, **kwargs) -> frappe.qb: """Get initial table object Args: @@ -208,7 +208,7 @@ class Query: return frappe.qb.into(table_object) return frappe.qb.from_(table_object) - def get_table(self, table_name: Union[str, Table]) -> Table: + def get_table(self, table_name: str | Table) -> Table: if isinstance(table_name, Table): return table_name table_name = table_name.strip('"').strip("'") @@ -259,7 +259,7 @@ class Query: return conditions - def misc_query(self, table: str, filters: Union[List, Tuple] = None, **kwargs): + def misc_query(self, table: str, filters: list | tuple = None, **kwargs): """Build conditions using the given Lists or Tuple filters Args: @@ -291,9 +291,7 @@ class Query: return self.add_conditions(conditions, **kwargs) - def dict_query( - self, table: str, filters: Dict[str, Union[str, int]] = None, **kwargs - ) -> frappe.qb: + def dict_query(self, table: str, filters: dict[str, str | int] = None, **kwargs) -> frappe.qb: """Build conditions using the given dictionary filters Args: @@ -329,7 +327,7 @@ class Query: return self.add_conditions(conditions, **kwargs) def build_conditions( - self, table: str, filters: Union[Dict[str, Union[str, int]], str, int] = None, **kwargs + self, table: str, filters: dict[str, str | int] | str | int = None, **kwargs ) -> frappe.qb: """Build conditions for sql query @@ -357,8 +355,8 @@ class Query: def get_sql( self, table: str, - fields: Union[List, Tuple], - filters: Union[Dict[str, Union[str, int]], str, int, List[Union[List, str, int]]] = None, + fields: list | tuple, + filters: dict[str, str | int] | str | int | list[list | str | int] = None, **kwargs, ): # Clean up state before each query diff --git a/frappe/database/schema.py b/frappe/database/schema.py index 9a8307ddae..5920d14c3d 100644 --- a/frappe/database/schema.py +++ b/frappe/database/schema.py @@ -15,7 +15,7 @@ class InvalidColumnName(frappe.ValidationError): class DBTable: def __init__(self, doctype, meta=None): self.doctype = doctype - self.table_name = "tab{}".format(doctype) + self.table_name = f"tab{doctype}" self.meta = meta or frappe.get_meta(doctype, False) self.columns = {} self.current_columns = {} @@ -195,11 +195,11 @@ class DbColumn: if self.fieldtype in ("Check", "Int"): default_value = cint(self.default) or 0 - column_def += " not null default {0}".format(default_value) + column_def += f" not null default {default_value}" elif self.fieldtype in ("Currency", "Float", "Percent"): default_value = flt(self.default) or 0 - column_def += " not null default {0}".format(default_value) + column_def += f" not null default {default_value}" elif ( self.default @@ -207,7 +207,7 @@ class DbColumn: and not cstr(self.default).startswith(":") and column_def not in ("text", "longtext") ): - column_def += " default {}".format(frappe.db.escape(self.default)) + column_def += f" default {frappe.db.escape(self.default)}" if self.unique and (column_def not in ("text", "longtext")): column_def += " unique" @@ -308,7 +308,7 @@ class DbColumn: def validate_column_name(n): if special_characters := SPECIAL_CHAR_PATTERN.findall(n): - special_characters = ", ".join('"{0}"'.format(c) for c in special_characters) + special_characters = ", ".join(f'"{c}"' for c in special_characters) frappe.throw( _("Fieldname {0} cannot have special characters like {1}").format( frappe.bold(cstr(n)), special_characters @@ -352,7 +352,7 @@ def get_definition(fieldtype, precision=None, length=None): size = length if size is not None: - coltype = "{coltype}({size})".format(coltype=coltype, size=size) + coltype = f"{coltype}({size})" return coltype @@ -366,7 +366,7 @@ def add_column( frappe.db.commit() - query = "alter table `tab%s` add column %s %s" % ( + query = "alter table `tab{}` add column {} {}".format( doctype, column_name, get_definition(fieldtype, precision, length), diff --git a/frappe/deferred_insert.py b/frappe/deferred_insert.py index 3b47d46cdf..328d8dd555 100644 --- a/frappe/deferred_insert.py +++ b/frappe/deferred_insert.py @@ -1,5 +1,5 @@ import json -from typing import TYPE_CHECKING, Dict, List, Union +from typing import TYPE_CHECKING, Union import redis @@ -12,7 +12,7 @@ if TYPE_CHECKING: queue_prefix = "insert_queue_for_" -def deferred_insert(doctype: str, records: Union[List[Union[Dict, "Document"]], str]): +def deferred_insert(doctype: str, records: list[Union[dict, "Document"]] | str): if isinstance(records, (dict, list)): _records = json.dumps(records) else: @@ -43,7 +43,7 @@ def save_to_db(): insert_record(record, doctype) -def insert_record(record: Union[Dict, "Document"], doctype: str): +def insert_record(record: Union[dict, "Document"], doctype: str): try: record.update({"doctype": doctype}) frappe.get_doc(record).insert() diff --git a/frappe/desk/desktop.py b/frappe/desk/desktop.py index ca0d1e2353..e2be2656a9 100644 --- a/frappe/desk/desktop.py +++ b/frappe/desk/desktop.py @@ -486,9 +486,9 @@ def save_new_widget(doc, page, blocks, new_widgets): # Error log body log = """ - page: {0} - config: {1} - exception: {2} + page: {} + config: {} + exception: {} """.format( page, json_config, e ) diff --git a/frappe/desk/doctype/bulk_update/bulk_update.py b/frappe/desk/doctype/bulk_update/bulk_update.py index dc0a88178d..1e515bbc47 100644 --- a/frappe/desk/doctype/bulk_update/bulk_update.py +++ b/frappe/desk/doctype/bulk_update/bulk_update.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -24,7 +23,7 @@ def update(doctype, field, value, condition="", limit=500): frappe.throw(_("; not allowed in condition")) docnames = frappe.db.sql_list( - """select name from `tab{0}`{1} limit {2} offset 0""".format(doctype, condition, limit) + f"""select name from `tab{doctype}`{condition} limit {limit} offset 0""" ) data = {} data[field] = value diff --git a/frappe/desk/doctype/calendar_view/calendar_view.py b/frappe/desk/doctype/calendar_view/calendar_view.py index 01968e835d..1e187682ec 100644 --- a/frappe/desk/doctype/calendar_view/calendar_view.py +++ b/frappe/desk/doctype/calendar_view/calendar_view.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/desk/doctype/console_log/console_log.py b/frappe/desk/doctype/console_log/console_log.py index ebe93f535d..7e20afb22f 100644 --- a/frappe/desk/doctype/console_log/console_log.py +++ b/frappe/desk/doctype/console_log/console_log.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/desk/doctype/console_log/test_console_log.py b/frappe/desk/doctype/console_log/test_console_log.py index 409ac88299..0579098382 100644 --- a/frappe/desk/doctype/console_log/test_console_log.py +++ b/frappe/desk/doctype/console_log/test_console_log.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/desk/doctype/dashboard/dashboard.py b/frappe/desk/doctype/dashboard/dashboard.py index 61e997836c..960431d220 100644 --- a/frappe/desk/doctype/dashboard/dashboard.py +++ b/frappe/desk/doctype/dashboard/dashboard.py @@ -115,7 +115,7 @@ def get_non_standard_warning_message(non_standard_docs_map): message = _("""Please set the following documents in this Dashboard as standard first.""") def get_html(docs, doctype): - html = "

    {}

    ".format(frappe.bold(doctype)) + html = f"

    {frappe.bold(doctype)}

    " for doc in docs: html += ''.format( doctype=doctype, doc=doc diff --git a/frappe/desk/doctype/dashboard/test_dashboard.py b/frappe/desk/doctype/dashboard/test_dashboard.py index ee3d1848e2..d2ba871509 100644 --- a/frappe/desk/doctype/dashboard/test_dashboard.py +++ b/frappe/desk/doctype/dashboard/test_dashboard.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/desk/doctype/dashboard_chart/dashboard_chart.py b/frappe/desk/doctype/dashboard_chart/dashboard_chart.py index ca29bad33b..1145873a09 100644 --- a/frappe/desk/doctype/dashboard_chart/dashboard_chart.py +++ b/frappe/desk/doctype/dashboard_chart/dashboard_chart.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -212,7 +211,7 @@ def get_chart_config(chart, filters, timespan, timegrain, from_date, to_date): data = frappe.db.get_list( doctype, - fields=["{} as _unit".format(datefield), "SUM({})".format(value_field), "COUNT(*)"], + fields=[f"{datefield} as _unit", f"SUM({value_field})", "COUNT(*)"], filters=filters, group_by="_unit", order_by="_unit asc", @@ -242,13 +241,13 @@ def get_heatmap_chart_config(chart, filters, heatmap_year): year_start_date = datetime.date(year, 1, 1).strftime("%Y-%m-%d") next_year_start_date = datetime.date(year + 1, 1, 1).strftime("%Y-%m-%d") - filters.append([doctype, datefield, ">", "{date}".format(date=year_start_date), False]) - filters.append([doctype, datefield, "<", "{date}".format(date=next_year_start_date), False]) + filters.append([doctype, datefield, ">", f"{year_start_date}", False]) + filters.append([doctype, datefield, "<", f"{next_year_start_date}", False]) if frappe.db.db_type == "mariadb": - timestamp_field = "unix_timestamp({datefield})".format(datefield=datefield) + timestamp_field = f"unix_timestamp({datefield})" else: - timestamp_field = "extract(epoch from timestamp {datefield})".format(datefield=datefield) + timestamp_field = f"extract(epoch from timestamp {datefield})" data = dict( frappe.db.get_all( @@ -260,9 +259,9 @@ def get_heatmap_chart_config(chart, filters, heatmap_year): ), ], filters=filters, - group_by="date({datefield})".format(datefield=datefield), + group_by=f"date({datefield})", as_list=1, - order_by="{datefield} asc".format(datefield=datefield), + order_by=f"{datefield} asc", ignore_ifnull=True, ) ) @@ -284,7 +283,7 @@ def get_group_by_chart_config(chart, filters): data = frappe.db.get_list( doctype, fields=[ - "{} as name".format(group_by_field), + f"{group_by_field} as name", "{aggregate_function}({value_field}) as count".format( aggregate_function=aggregate_function, value_field=value_field ), @@ -351,7 +350,7 @@ def get_charts_for_user(doctype, txt, searchfield, start, page_len, filters): class DashboardChart(Document): def on_update(self): - frappe.cache().delete_key("chart-data:{}".format(self.name)) + frappe.cache().delete_key(f"chart-data:{self.name}") if frappe.conf.developer_mode and self.is_standard: export_to_files(record_list=[["Dashboard Chart", self.name]], record_module=self.module) diff --git a/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py b/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py index ca84b2c301..820f3c0555 100644 --- a/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py +++ b/frappe/desk/doctype/dashboard_chart/test_dashboard_chart.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE diff --git a/frappe/desk/doctype/dashboard_chart_field/dashboard_chart_field.py b/frappe/desk/doctype/dashboard_chart_field/dashboard_chart_field.py index 41f35d2ee4..adc03663a2 100644 --- a/frappe/desk/doctype/dashboard_chart_field/dashboard_chart_field.py +++ b/frappe/desk/doctype/dashboard_chart_field/dashboard_chart_field.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/desk/doctype/dashboard_chart_link/dashboard_chart_link.py b/frappe/desk/doctype/dashboard_chart_link/dashboard_chart_link.py index b2a7caefeb..4d98b69458 100644 --- a/frappe/desk/doctype/dashboard_chart_link/dashboard_chart_link.py +++ b/frappe/desk/doctype/dashboard_chart_link/dashboard_chart_link.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/desk/doctype/dashboard_chart_source/dashboard_chart_source.py b/frappe/desk/doctype/dashboard_chart_source/dashboard_chart_source.py index 155a71a9b4..5519ad9097 100644 --- a/frappe/desk/doctype/dashboard_chart_source/dashboard_chart_source.py +++ b/frappe/desk/doctype/dashboard_chart_source/dashboard_chart_source.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -17,7 +16,6 @@ def get_config(name): os.path.join( get_module_path(doc.module), "dashboard_chart_source", scrub(doc.name), scrub(doc.name) + ".js" ), - "r", ) as f: return f.read() diff --git a/frappe/desk/doctype/dashboard_chart_source/test_dashboard_chart_source.py b/frappe/desk/doctype/dashboard_chart_source/test_dashboard_chart_source.py index 0c219c08cc..457487bb6d 100644 --- a/frappe/desk/doctype/dashboard_chart_source/test_dashboard_chart_source.py +++ b/frappe/desk/doctype/dashboard_chart_source/test_dashboard_chart_source.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/desk/doctype/dashboard_settings/dashboard_settings.py b/frappe/desk/doctype/dashboard_settings/dashboard_settings.py index 01c3a87f20..489beda0bf 100644 --- a/frappe/desk/doctype/dashboard_settings/dashboard_settings.py +++ b/frappe/desk/doctype/dashboard_settings/dashboard_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -28,7 +27,7 @@ def get_permission_query_conditions(user): if not user: user = frappe.session.user - return """(`tabDashboard Settings`.name = {user})""".format(user=frappe.db.escape(user)) + return f"""(`tabDashboard Settings`.name = {frappe.db.escape(user)})""" @frappe.whitelist() diff --git a/frappe/desk/doctype/desktop_icon/desktop_icon.py b/frappe/desk/doctype/desktop_icon/desktop_icon.py index 29de1f56d9..5602f4da24 100644 --- a/frappe/desk/doctype/desktop_icon/desktop_icon.py +++ b/frappe/desk/doctype/desktop_icon/desktop_icon.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors # License: MIT. See LICENSE @@ -133,7 +132,7 @@ def add_user_icon(_doctype, _report=None, label=None, link=None, type="link", st if not label: label = _doctype or _report if not link: - link = "List/{0}".format(_doctype) + link = f"List/{_doctype}" # find if a standard icon exists icon_name = frappe.db.exists( diff --git a/frappe/desk/doctype/event/event.py b/frappe/desk/doctype/event/event.py index 6fdc95d3d0..e9104ef897 100644 --- a/frappe/desk/doctype/event/event.py +++ b/frappe/desk/doctype/event/event.py @@ -161,9 +161,9 @@ def delete_communication(event, reference_doctype, reference_docname): def get_permission_query_conditions(user): if not user: user = frappe.session.user - return """(`tabEvent`.`event_type`='Public' or `tabEvent`.`owner`=%(user)s)""" % { - "user": frappe.db.escape(user), - } + return """(`tabEvent`.`event_type`='Public' or `tabEvent`.`owner`={user})""".format( + user=frappe.db.escape(user), + ) def has_permission(doc, user): diff --git a/frappe/desk/doctype/event/test_event.py b/frappe/desk/doctype/event/test_event.py index 041bda643e..efbd54fb09 100644 --- a/frappe/desk/doctype/event/test_event.py +++ b/frappe/desk/doctype/event/test_event.py @@ -96,7 +96,7 @@ class TestEvent(unittest.TestCase): ev = frappe.get_doc("Event", ev.name) - self.assertEqual(set(json.loads(ev._assign)), set(["test@example.com", self.test_user])) + self.assertEqual(set(json.loads(ev._assign)), {"test@example.com", self.test_user}) # Remove an assignment todo = frappe.get_doc( diff --git a/frappe/desk/doctype/event_participants/event_participants.py b/frappe/desk/doctype/event_participants/event_participants.py index fdb834b285..869ae4092b 100644 --- a/frappe/desk/doctype/event_participants/event_participants.py +++ b/frappe/desk/doctype/event_participants/event_participants.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors # License: MIT. See LICENSE from frappe.model.document import Document diff --git a/frappe/desk/doctype/global_search_doctype/global_search_doctype.py b/frappe/desk/doctype/global_search_doctype/global_search_doctype.py index 8bdc05cd71..48fdb3d4d1 100644 --- a/frappe/desk/doctype/global_search_doctype/global_search_doctype.py +++ b/frappe/desk/doctype/global_search_doctype/global_search_doctype.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/desk/doctype/global_search_settings/global_search_settings.py b/frappe/desk/doctype/global_search_settings/global_search_settings.py index b7ffd7faf7..4e2b1e85f9 100644 --- a/frappe/desk/doctype/global_search_settings/global_search_settings.py +++ b/frappe/desk/doctype/global_search_settings/global_search_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/desk/doctype/kanban_board/kanban_board.py b/frappe/desk/doctype/kanban_board/kanban_board.py index bc47bbbaf4..83f0f46df0 100644 --- a/frappe/desk/doctype/kanban_board/kanban_board.py +++ b/frappe/desk/doctype/kanban_board/kanban_board.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -126,7 +125,7 @@ def update_order_for_single_card( if from_colname == to_colname: from_col_order = to_col_order - to_col_order.insert(new_index, from_col_order.pop((old_index))) + to_col_order.insert(new_index, from_col_order.pop(old_index)) # save updated order board.columns[from_col_idx].order = frappe.as_json(from_col_order) @@ -173,7 +172,7 @@ def quick_kanban_board(doctype, board_name, field_name, project=None): doc.field_name = field_name if project: - doc.filters = '[["Task","project","=","{0}"]]'.format(project) + doc.filters = f'[["Task","project","=","{project}"]]' options = "" for field in meta.fields: diff --git a/frappe/desk/doctype/kanban_board/test_kanban_board.py b/frappe/desk/doctype/kanban_board/test_kanban_board.py index d4504bf9d8..73f566b906 100644 --- a/frappe/desk/doctype/kanban_board/test_kanban_board.py +++ b/frappe/desk/doctype/kanban_board/test_kanban_board.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/desk/doctype/kanban_board_column/kanban_board_column.py b/frappe/desk/doctype/kanban_board_column/kanban_board_column.py index d905369a0b..e57d92857e 100644 --- a/frappe/desk/doctype/kanban_board_column/kanban_board_column.py +++ b/frappe/desk/doctype/kanban_board_column/kanban_board_column.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/desk/doctype/list_filter/list_filter.py b/frappe/desk/doctype/list_filter/list_filter.py index a5ba12df6a..e4c59ee9e4 100644 --- a/frappe/desk/doctype/list_filter/list_filter.py +++ b/frappe/desk/doctype/list_filter/list_filter.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/desk/doctype/list_view_settings/list_view_settings.py b/frappe/desk/doctype/list_view_settings/list_view_settings.py index 7d25f57acf..36ebce34d5 100644 --- a/frappe/desk/doctype/list_view_settings/list_view_settings.py +++ b/frappe/desk/doctype/list_view_settings/list_view_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/desk/doctype/list_view_settings/test_list_view_settings.py b/frappe/desk/doctype/list_view_settings/test_list_view_settings.py index 0b6a0773e3..0eab9cd7a6 100644 --- a/frappe/desk/doctype/list_view_settings/test_list_view_settings.py +++ b/frappe/desk/doctype/list_view_settings/test_list_view_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/desk/doctype/module_onboarding/module_onboarding.py b/frappe/desk/doctype/module_onboarding/module_onboarding.py index 7a12328ee0..ea02f5911d 100644 --- a/frappe/desk/doctype/module_onboarding/module_onboarding.py +++ b/frappe/desk/doctype/module_onboarding/module_onboarding.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/desk/doctype/module_onboarding/test_module_onboarding.py b/frappe/desk/doctype/module_onboarding/test_module_onboarding.py index 8def3ac40e..fa19794c1e 100644 --- a/frappe/desk/doctype/module_onboarding/test_module_onboarding.py +++ b/frappe/desk/doctype/module_onboarding/test_module_onboarding.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/desk/doctype/note/note.py b/frappe/desk/doctype/note/note.py index a709b80f1d..c0a37d5f44 100644 --- a/frappe/desk/doctype/note/note.py +++ b/frappe/desk/doctype/note/note.py @@ -40,7 +40,7 @@ def get_permission_query_conditions(user): if user == "Administrator": return "" - return """(`tabNote`.public=1 or `tabNote`.owner={user})""".format(user=frappe.db.escape(user)) + return f"""(`tabNote`.public=1 or `tabNote`.owner={frappe.db.escape(user)})""" def has_permission(doc, ptype, user): diff --git a/frappe/desk/doctype/note_seen_by/note_seen_by.py b/frappe/desk/doctype/note_seen_by/note_seen_by.py index 7dde133e6d..5acdca222e 100644 --- a/frappe/desk/doctype/note_seen_by/note_seen_by.py +++ b/frappe/desk/doctype/note_seen_by/note_seen_by.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/desk/doctype/notification_log/notification_log.py b/frappe/desk/doctype/notification_log/notification_log.py index def626513c..3d16bdf32f 100644 --- a/frappe/desk/doctype/notification_log/notification_log.py +++ b/frappe/desk/doctype/notification_log/notification_log.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -29,7 +28,7 @@ def get_permission_query_conditions(for_user): if for_user == "Administrator": return - return """(`tabNotification Log`.for_user = {user})""".format(user=frappe.db.escape(for_user)) + return f"""(`tabNotification Log`.for_user = {frappe.db.escape(for_user)})""" def get_title(doctype, docname, title_field=None): @@ -40,7 +39,7 @@ def get_title(doctype, docname, title_field=None): def get_title_html(title): - return '{0}'.format(title) + return f'{title}' def enqueue_create_notification(users, doc): diff --git a/frappe/desk/doctype/notification_log/test_notification_log.py b/frappe/desk/doctype/notification_log/test_notification_log.py index 44b1b53ead..532f05ab57 100644 --- a/frappe/desk/doctype/notification_log/test_notification_log.py +++ b/frappe/desk/doctype/notification_log/test_notification_log.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/desk/doctype/notification_settings/notification_settings.py b/frappe/desk/doctype/notification_settings/notification_settings.py index 2bf7347a4f..801d512fe7 100644 --- a/frappe/desk/doctype/notification_settings/notification_settings.py +++ b/frappe/desk/doctype/notification_settings/notification_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -88,7 +87,7 @@ def get_permission_query_conditions(user): if "System Manager" in roles: return """(`tabNotification Settings`.name != 'Administrator')""" - return """(`tabNotification Settings`.name = {user})""".format(user=frappe.db.escape(user)) + return f"""(`tabNotification Settings`.name = {frappe.db.escape(user)})""" @frappe.whitelist() diff --git a/frappe/desk/doctype/notification_subscribed_document/notification_subscribed_document.py b/frappe/desk/doctype/notification_subscribed_document/notification_subscribed_document.py index b72f827cd7..551ee6dc85 100644 --- a/frappe/desk/doctype/notification_subscribed_document/notification_subscribed_document.py +++ b/frappe/desk/doctype/notification_subscribed_document/notification_subscribed_document.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/desk/doctype/number_card/number_card.py b/frappe/desk/doctype/number_card/number_card.py index 74c8e9eb99..1bffd68940 100644 --- a/frappe/desk/doctype/number_card/number_card.py +++ b/frappe/desk/doctype/number_card/number_card.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -120,7 +119,7 @@ def get_result(doc, filters, to_date=None): function = sql_function_map[doc.function] if function == "count": - fields = ["{function}(*) as result".format(function=function)] + fields = [f"{function}(*) as result"] else: fields = [ "{function}({based_on}) as result".format( @@ -202,7 +201,7 @@ def get_cards_for_user(doctype, txt, searchfield, start, page_len, filters): numberCard = DocType("Number Card") if txt: - search_conditions = [numberCard[field].like("%{txt}%".format(txt=txt)) for field in searchfields] + search_conditions = [numberCard[field].like(f"%{txt}%") for field in searchfields] condition_query = frappe.db.query.build_conditions(doctype, filters) diff --git a/frappe/desk/doctype/number_card/test_number_card.py b/frappe/desk/doctype/number_card/test_number_card.py index 817ea2fad4..c0dda40104 100644 --- a/frappe/desk/doctype/number_card/test_number_card.py +++ b/frappe/desk/doctype/number_card/test_number_card.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/desk/doctype/number_card_link/number_card_link.py b/frappe/desk/doctype/number_card_link/number_card_link.py index b630d7caa7..16cc7ba4e3 100644 --- a/frappe/desk/doctype/number_card_link/number_card_link.py +++ b/frappe/desk/doctype/number_card_link/number_card_link.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/desk/doctype/onboarding_permission/onboarding_permission.py b/frappe/desk/doctype/onboarding_permission/onboarding_permission.py index a0e87c3067..d7db13762a 100644 --- a/frappe/desk/doctype/onboarding_permission/onboarding_permission.py +++ b/frappe/desk/doctype/onboarding_permission/onboarding_permission.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/desk/doctype/onboarding_permission/test_onboarding_permission.py b/frappe/desk/doctype/onboarding_permission/test_onboarding_permission.py index 9a12b0aab9..cdfe0d7890 100644 --- a/frappe/desk/doctype/onboarding_permission/test_onboarding_permission.py +++ b/frappe/desk/doctype/onboarding_permission/test_onboarding_permission.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/desk/doctype/onboarding_step/onboarding_step.py b/frappe/desk/doctype/onboarding_step/onboarding_step.py index 4a4d487cc8..b6807b62bd 100644 --- a/frappe/desk/doctype/onboarding_step/onboarding_step.py +++ b/frappe/desk/doctype/onboarding_step/onboarding_step.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/desk/doctype/onboarding_step/test_onboarding_step.py b/frappe/desk/doctype/onboarding_step/test_onboarding_step.py index 2342656a72..d8bf55584c 100644 --- a/frappe/desk/doctype/onboarding_step/test_onboarding_step.py +++ b/frappe/desk/doctype/onboarding_step/test_onboarding_step.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/desk/doctype/onboarding_step_map/onboarding_step_map.py b/frappe/desk/doctype/onboarding_step_map/onboarding_step_map.py index 7c20e220db..8844316e68 100644 --- a/frappe/desk/doctype/onboarding_step_map/onboarding_step_map.py +++ b/frappe/desk/doctype/onboarding_step_map/onboarding_step_map.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/desk/doctype/system_console/system_console.py b/frappe/desk/doctype/system_console/system_console.py index 063b3d37d0..993af6e753 100644 --- a/frappe/desk/doctype/system_console/system_console.py +++ b/frappe/desk/doctype/system_console/system_console.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/desk/doctype/system_console/test_system_console.py b/frappe/desk/doctype/system_console/test_system_console.py index 372cbbc1f4..96bf555f59 100644 --- a/frappe/desk/doctype/system_console/test_system_console.py +++ b/frappe/desk/doctype/system_console/test_system_console.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/desk/doctype/tag/tag.py b/frappe/desk/doctype/tag/tag.py index aabf0351a5..ca167c148e 100644 --- a/frappe/desk/doctype/tag/tag.py +++ b/frappe/desk/doctype/tag/tag.py @@ -56,7 +56,7 @@ def get_tagged_docs(doctype, tag): @frappe.whitelist() def get_tags(doctype, txt): - tag = frappe.get_list("Tag", filters=[["name", "like", "%{}%".format(txt)]]) + tag = frappe.get_list("Tag", filters=[["name", "like", f"%{txt}%"]]) tags = [t.name for t in tag] return sorted(filter(lambda t: t and txt.lower() in t.lower(), list(set(tags)))) @@ -104,7 +104,7 @@ class DocTags: tags = "," + ",".join(tl) try: frappe.db.sql( - "update `tab%s` set _user_tags=%s where name=%s" % (self.dt, "%s", "%s"), (tags, dn) + "update `tab{}` set _user_tags={} where name={}".format(self.dt, "%s", "%s"), (tags, dn) ) doc = frappe.get_doc(self.dt, dn) update_tags(doc, tags) diff --git a/frappe/desk/doctype/tag_link/tag_link.py b/frappe/desk/doctype/tag_link/tag_link.py index ec816352ca..a67e6a62d3 100644 --- a/frappe/desk/doctype/tag_link/tag_link.py +++ b/frappe/desk/doctype/tag_link/tag_link.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/desk/doctype/tag_link/test_tag_link.py b/frappe/desk/doctype/tag_link/test_tag_link.py index d4d1dd61fa..59d7bcd2bc 100644 --- a/frappe/desk/doctype/tag_link/test_tag_link.py +++ b/frappe/desk/doctype/tag_link/test_tag_link.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/desk/doctype/todo/test_todo.py b/frappe/desk/doctype/todo/test_todo.py index 5c54889e00..56ca1f30e7 100644 --- a/frappe/desk/doctype/todo/test_todo.py +++ b/frappe/desk/doctype/todo/test_todo.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/desk/doctype/workspace/test_workspace.py b/frappe/desk/doctype/workspace/test_workspace.py index 9281240e08..d0b0eba9e2 100644 --- a/frappe/desk/doctype/workspace/test_workspace.py +++ b/frappe/desk/doctype/workspace/test_workspace.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/desk/doctype/workspace/workspace.py b/frappe/desk/doctype/workspace/workspace.py index 284fecbe31..9fa99884fb 100644 --- a/frappe/desk/doctype/workspace/workspace.py +++ b/frappe/desk/doctype/workspace/workspace.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -206,7 +205,7 @@ def update_page(name, title, icon, parent, public): doc.sequence_id = frappe.db.count("Workspace", {"public": public}, cache=True) doc.public = public doc.for_user = "" if public else doc.for_user or frappe.session.user - doc.label = new_name = "{0}-{1}".format(title, doc.for_user) if doc.for_user else title + doc.label = new_name = f"{title}-{doc.for_user}" if doc.for_user else title doc.save(ignore_permissions=True) if name != new_name: @@ -221,9 +220,7 @@ def update_page(name, title, icon, parent, public): child_doc.public = public child_doc.for_user = "" if public else child_doc.for_user or frappe.session.user child_doc.label = new_child_name = ( - "{0}-{1}".format(child_doc.title, child_doc.for_user) - if child_doc.for_user - else child_doc.title + f"{child_doc.title}-{child_doc.for_user}" if child_doc.for_user else child_doc.title ) child_doc.save(ignore_permissions=True) @@ -253,7 +250,7 @@ def duplicate_page(page_name, new_page): doc.label = doc.title if not doc.public: doc.for_user = doc.for_user or frappe.session.user - doc.label = "{0}-{1}".format(doc.title, doc.for_user) + doc.label = f"{doc.title}-{doc.for_user}" doc.name = doc.label if old_doc.public == doc.public: doc.sequence_id += 0.1 diff --git a/frappe/desk/doctype/workspace_chart/workspace_chart.py b/frappe/desk/doctype/workspace_chart/workspace_chart.py index e02cf06ee0..45f4229401 100644 --- a/frappe/desk/doctype/workspace_chart/workspace_chart.py +++ b/frappe/desk/doctype/workspace_chart/workspace_chart.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/desk/doctype/workspace_link/workspace_link.py b/frappe/desk/doctype/workspace_link/workspace_link.py index 5e55a7c2bd..5756846f38 100644 --- a/frappe/desk/doctype/workspace_link/workspace_link.py +++ b/frappe/desk/doctype/workspace_link/workspace_link.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/desk/doctype/workspace_shortcut/workspace_shortcut.py b/frappe/desk/doctype/workspace_shortcut/workspace_shortcut.py index 4ca86c8146..49ba37854c 100644 --- a/frappe/desk/doctype/workspace_shortcut/workspace_shortcut.py +++ b/frappe/desk/doctype/workspace_shortcut/workspace_shortcut.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/desk/form/assign_to.py b/frappe/desk/form/assign_to.py index 4107f95827..7853e807b8 100644 --- a/frappe/desk/form/assign_to.py +++ b/frappe/desk/form/assign_to.py @@ -217,7 +217,7 @@ def notify_assignment( # Search for email address in description -- i.e. assignee user_name = frappe.get_cached_value("User", frappe.session.user, "full_name") title = get_title(doc_type, doc_name) - description_html = "
    {0}
    ".format(description) if description else None + description_html = f"
    {description}
    " if description else None if action == "CLOSE": subject = _("Your assignment on {0} {1} has been removed by {2}").format( diff --git a/frappe/desk/form/document_follow.py b/frappe/desk/form/document_follow.py index 527b9da036..86bd712926 100644 --- a/frappe/desk/form/document_follow.py +++ b/frappe/desk/form/document_follow.py @@ -192,9 +192,9 @@ def get_comments(doctype, doc_name, frequency, user): ) for comment in comments: if comment.comment_type == "Like": - by = """ By : {0}""".format(comment.modified_by) + by = f""" By : {comment.modified_by}""" elif comment.comment_type == "Comment": - by = """Commented by : {0}""".format(comment.modified_by) + by = f"""Commented by : {comment.modified_by}""" else: by = "" diff --git a/frappe/desk/form/linked_with.py b/frappe/desk/form/linked_with.py index 7a53c8b65a..b60c11774f 100644 --- a/frappe/desk/form/linked_with.py +++ b/frappe/desk/form/linked_with.py @@ -4,7 +4,6 @@ import itertools import json from collections import defaultdict -from typing import Dict, List, Optional import frappe import frappe.desk.form.load @@ -15,7 +14,7 @@ from frappe.modules import load_doctype_module @frappe.whitelist() -def get_submitted_linked_docs(doctype: str, name: str) -> List[tuple]: +def get_submitted_linked_docs(doctype: str, name: str) -> list[tuple]: """Get all the nested submitted documents those are present in referencing tables (dependent tables). :param doctype: Document type @@ -134,14 +133,14 @@ class SubmittableDocumentTree: """limit doctype links to these doctypes.""" return list(set(self.get_submittable_doctypes()) - set(get_exempted_doctypes() or [])) - def get_submittable_doctypes(self) -> List[str]: + def get_submittable_doctypes(self) -> list[str]: """Returns list of submittable doctypes.""" if not self._submittable_doctypes: self._submittable_doctypes = frappe.db.get_all("DocType", {"is_submittable": 1}, pluck="name") return self._submittable_doctypes -def get_child_tables_of_doctypes(doctypes: List[str] = None): +def get_child_tables_of_doctypes(doctypes: list[str] = None): """Returns child tables by doctype.""" filters = [["fieldtype", "=", "Table"]] filters_for_docfield = filters @@ -174,8 +173,8 @@ def get_child_tables_of_doctypes(doctypes: List[str] = None): def get_references_across_doctypes( - to_doctypes: List[str] = None, limit_link_doctypes: List[str] = None -) -> List: + to_doctypes: list[str] = None, limit_link_doctypes: list[str] = None +) -> list: """Find doctype wise foreign key references. :param to_doctypes: Get links of these doctypes. @@ -213,7 +212,7 @@ def get_references_across_doctypes( def get_references_across_doctypes_by_link_field( - to_doctypes: List[str] = None, limit_link_doctypes: List[str] = None + to_doctypes: list[str] = None, limit_link_doctypes: list[str] = None ): """Find doctype wise foreign key references based on link fields. @@ -253,7 +252,7 @@ def get_references_across_doctypes_by_link_field( def get_references_across_doctypes_by_dynamic_link_field( - to_doctypes: List[str] = None, limit_link_doctypes: List[str] = None + to_doctypes: list[str] = None, limit_link_doctypes: list[str] = None ): """Find doctype wise foreign key references based on dynamic link fields. @@ -304,10 +303,10 @@ def get_references_across_doctypes_by_dynamic_link_field( def get_referencing_documents( reference_doctype: str, - reference_names: List[str], + reference_names: list[str], link_info: dict, get_parent_if_child_table_doc: bool = True, - parent_filters: List[list] = None, + parent_filters: list[list] = None, child_filters=None, allowed_parents=None, ): @@ -340,7 +339,7 @@ def get_referencing_documents( for parent, rows in itertools.groupby(res, key=lambda row: row["parenttype"]): if allowed_parents and parent not in allowed_parents: continue - filters = (parent_filters or []) + [["name", "in", tuple([row.parent for row in rows])]] + filters = (parent_filters or []) + [["name", "in", tuple(row.parent for row in rows)]] documents[parent].extend(frappe.db.get_all(parent, filters=filters, pluck="name") or []) return documents @@ -407,7 +406,7 @@ def get_exempted_doctypes(): @frappe.whitelist() -def get_linked_docs(doctype: str, name: str, linkinfo: Optional[Dict] = None) -> Dict[str, List]: +def get_linked_docs(doctype: str, name: str, linkinfo: dict | None = None) -> dict[str, list]: if isinstance(linkinfo, str): # additional fields are added in linkinfo linkinfo = json.loads(linkinfo) @@ -447,9 +446,7 @@ def get_linked_docs(doctype: str, name: str, linkinfo: Optional[Dict] = None) -> if link.get("add_fields"): fields += link["add_fields"] - fields = [ - "`tab{dt}`.`{fn}`".format(dt=dt, fn=sf.strip()) for sf in fields if sf and "`tab" not in sf - ] + fields = [f"`tab{dt}`.`{sf.strip()}`" for sf in fields if sf and "`tab" not in sf] try: if link.get("filters"): diff --git a/frappe/desk/form/load.py b/frappe/desk/form/load.py index 5a6004652e..9e3a850bb0 100644 --- a/frappe/desk/form/load.py +++ b/frappe/desk/form/load.py @@ -2,7 +2,6 @@ # License: MIT. See LICENSE import json -from typing import List, Union from urllib.parse import quote import frappe @@ -218,8 +217,8 @@ def get_communications(doctype, name, start=0, limit=20): def get_comments( - doctype: str, name: str, comment_type: Union[str, List[str]] = "Comment" -) -> List[frappe._dict]: + doctype: str, name: str, comment_type: str | list[str] = "Comment" +) -> list[frappe._dict]: if isinstance(comment_type, list): comment_types = comment_type @@ -294,7 +293,7 @@ def get_communication_data( if after: # find after a particular date conditions += """ - AND C.creation > {0} + AND C.creation > {} """.format( after ) @@ -411,7 +410,7 @@ def get_document_email(doctype, name): return None email = email.split("@") - return "{0}+{1}+{2}@{3}".format(email[0], quote(doctype), quote(cstr(name)), email[1]) + return f"{email[0]}+{quote(doctype)}+{quote(cstr(name))}@{email[1]}" def get_automatic_email_link(): diff --git a/frappe/desk/form/meta.py b/frappe/desk/form/meta.py index dc26dfe5b0..5a426b4c63 100644 --- a/frappe/desk/form/meta.py +++ b/frappe/desk/form/meta.py @@ -52,7 +52,7 @@ def get_meta(doctype, cached=True): class FormMeta(Meta): def __init__(self, doctype): - super(FormMeta, self).__init__(doctype) + super().__init__(doctype) self.load_assets() def load_assets(self): @@ -74,7 +74,7 @@ class FormMeta(Meta): self.set("__assets_loaded", True) def as_dict(self, no_nulls=False): - d = super(FormMeta, self).as_dict(no_nulls=no_nulls) + d = super().as_dict(no_nulls=no_nulls) for k in ASSET_KEYS: d[k] = self.get(k) @@ -133,7 +133,7 @@ class FormMeta(Meta): templates = dict() for fname in os.listdir(path): if fname.endswith(".html"): - with io.open(os.path.join(path, fname), "r", encoding="utf-8") as f: + with open(os.path.join(path, fname), encoding="utf-8") as f: templates[fname.split(".")[0]] = scrub_html_template(f.read()) self.set("__templates", templates or None) diff --git a/frappe/desk/form/utils.py b/frappe/desk/form/utils.py index 573ec17979..9e10ced912 100644 --- a/frappe/desk/form/utils.py +++ b/frappe/desk/form/utils.py @@ -85,7 +85,7 @@ def get_next(doctype, value, prev, filters=None, sort_order="desc", sort_field=" doctype, fields=["name"], filters=filters, - order_by="`tab{0}`.{1}".format(doctype, sort_field) + " " + sort_order, + order_by=f"`tab{doctype}`.{sort_field}" + " " + sort_order, limit_start=0, limit_page_length=1, as_list=True, diff --git a/frappe/desk/like.py b/frappe/desk/like.py index 9e97cb269c..0f297455e7 100644 --- a/frappe/desk/like.py +++ b/frappe/desk/like.py @@ -90,7 +90,7 @@ def add_comment(doctype, name): link = get_link_to_form( doc.reference_doctype, doc.reference_name, - "{0} {1}".format(_(doc.reference_doctype), doc.reference_name), + f"{_(doc.reference_doctype)} {doc.reference_name}", ) doc.add_comment( diff --git a/frappe/desk/listview.py b/frappe/desk/listview.py index 5149f8bf86..d48a7f3de4 100644 --- a/frappe/desk/listview.py +++ b/frappe/desk/listview.py @@ -1,6 +1,5 @@ # Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE -from typing import Dict, List import frappe from frappe.query_builder import Order @@ -30,7 +29,7 @@ def set_list_settings(doctype, values): @frappe.whitelist() -def get_group_by_count(doctype: str, current_filters: str, field: str) -> List[Dict]: +def get_group_by_count(doctype: str, current_filters: str, field: str) -> list[dict]: current_filters = frappe.parse_json(current_filters) if field == "assigned_to": diff --git a/frappe/desk/moduleview.py b/frappe/desk/moduleview.py index a4fc2ccd1e..913b3406e3 100644 --- a/frappe/desk/moduleview.py +++ b/frappe/desk/moduleview.py @@ -253,13 +253,13 @@ def apply_permissions(data): def get_disabled_reports(): if not hasattr(frappe.local, "disabled_reports"): - frappe.local.disabled_reports = set(r.name for r in frappe.get_all("Report", {"disabled": 1})) + frappe.local.disabled_reports = {r.name for r in frappe.get_all("Report", {"disabled": 1})} return frappe.local.disabled_reports def get_config(app, module): """Load module info from `[app].config.[module]`.""" - config = frappe.get_module("{app}.config.{module}".format(app=app, module=module)) + config = frappe.get_module(f"{app}.config.{module}") config = config.get_data() sections = [s for s in config if s.get("condition", True)] @@ -283,7 +283,7 @@ def get_config(app, module): def config_exists(app, module): try: - frappe.get_module("{app}.config.{module}".format(app=app, module=module)) + frappe.get_module(f"{app}.config.{module}") return True except ImportError: return False diff --git a/frappe/desk/page/activity/__init__.py b/frappe/desk/page/activity/__init__.py index 8b13789179..e69de29bb2 100644 --- a/frappe/desk/page/activity/__init__.py +++ b/frappe/desk/page/activity/__init__.py @@ -1 +0,0 @@ - diff --git a/frappe/desk/page/backups/backups.py b/frappe/desk/page/backups/backups.py index ec5bea3c4b..2ef09df900 100644 --- a/frappe/desk/page/backups/backups.py +++ b/frappe/desk/page/backups/backups.py @@ -21,9 +21,9 @@ def get_context(context): def get_size(path): size = os.path.getsize(path) if size > 1048576: - return "{0:.1f}M".format(float(size) / 1048576) + return f"{float(size) / 1048576:.1f}M" else: - return "{0:.1f}K".format(float(size) / 1024) + return f"{float(size) / 1024:.1f}K" path = get_site_path("private", "backups") files = [x for x in os.listdir(path) if os.path.isfile(os.path.join(path, x))] diff --git a/frappe/desk/page/setup_wizard/setup_wizard.py b/frappe/desk/page/setup_wizard/setup_wizard.py index 8fc4b3f694..3422602720 100755 --- a/frappe/desk/page/setup_wizard/setup_wizard.py +++ b/frappe/desk/page/setup_wizard/setup_wizard.py @@ -339,11 +339,11 @@ def prettify_args(args): if isinstance(val, str) and "data:image" in val: filename = val.split("data:image", 1)[0].strip(", ") size = round((len(val) * 3 / 4) / 1048576.0, 2) - args[key] = "Image Attached: '{0}' of size {1} MB".format(filename, size) + args[key] = f"Image Attached: '{filename}' of size {size} MB" pretty_args = [] for key in sorted(args): - pretty_args.append("{} = {}".format(key, args[key])) + pretty_args.append(f"{key} = {args[key]}") return pretty_args @@ -386,7 +386,7 @@ def email_setup_wizard_exception(traceback, args): frappe.sendmail( recipients=frappe.conf.setup_wizard_exception_email, sender=frappe.session.user, - subject="Setup failed: {}".format(frappe.local.site), + subject=f"Setup failed: {frappe.local.site}", message=message, delayed=False, ) diff --git a/frappe/desk/query_report.py b/frappe/desk/query_report.py index a51fd8b1e3..29c8ed08d3 100644 --- a/frappe/desk/query_report.py +++ b/frappe/desk/query_report.py @@ -187,7 +187,7 @@ def get_script(report_name): script = None if os.path.exists(script_path): - with open(script_path, "r") as f: + with open(script_path) as f: script = f.read() script += f"\n\n//# sourceURL={scrub(report.name)}.js" diff --git a/frappe/desk/report/todo/todo.py b/frappe/desk/report/todo/todo.py index 7c566c74ea..e75b8d1900 100644 --- a/frappe/desk/report/todo/todo.py +++ b/frappe/desk/report/todo/todo.py @@ -46,7 +46,7 @@ def execute(filters=None): for todo in todo_list: if todo.owner == frappe.session.user or todo.assigned_by == frappe.session.user: if todo.reference_type: - todo.reference = """%s: %s""" % ( + todo.reference = """{}: {}""".format( todo.reference_type, todo.reference_name, todo.reference_type, diff --git a/frappe/desk/report_dump.py b/frappe/desk/report_dump.py index ac01cf892f..6650d24757 100644 --- a/frappe/desk/report_dump.py +++ b/frappe/desk/report_dump.py @@ -53,7 +53,7 @@ def get_data(doctypes, last_modified): out[dt]["data"] = [ list(t) for t in frappe.db.sql( - """select %s from %s %s %s""" % (",".join(args["columns"]), table, conditions, order_by) + """select {} from {} {} {}""".format(",".join(args["columns"]), table, conditions, order_by) ) ] diff --git a/frappe/desk/reportview.py b/frappe/desk/reportview.py index d6dce68399..caba0212b9 100644 --- a/frappe/desk/reportview.py +++ b/frappe/desk/reportview.py @@ -167,7 +167,7 @@ def setup_group_by(data): def raise_invalid_field(fieldname): - frappe.throw(_("Field not permitted in query") + ": {0}".format(fieldname), frappe.DataError) + frappe.throw(_("Field not permitted in query") + f": {fieldname}", frappe.DataError) def is_standard(fieldname): diff --git a/frappe/desk/search.py b/frappe/desk/search.py index eb1a2e82ba..8ae635093c 100644 --- a/frappe/desk/search.py +++ b/frappe/desk/search.py @@ -34,7 +34,7 @@ def sanitize_searchfield(searchfield): _raise_exception(searchfield) # to avoid and, or and like - elif any(" {0} ".format(keyword) in searchfield.split() for keyword in blacklisted_keywords): + elif any(f" {keyword} " in searchfield.split() for keyword in blacklisted_keywords): _raise_exception(searchfield) # to avoid select, delete, drop, update and case @@ -166,7 +166,7 @@ def search_widget( in ["Data", "Text", "Small Text", "Long Text", "Link", "Select", "Read Only", "Text Editor"] ) ): - or_filters.append([doctype, f.strip(), "like", "%{0}%".format(txt)]) + or_filters.append([doctype, f.strip(), "like", f"%{txt}%"]) if meta.get("fields", {"fieldname": "enabled", "fieldtype": "Check"}): filters.append([doctype, "enabled", "=", 1]) @@ -177,7 +177,7 @@ def search_widget( fields = get_std_fields_list(meta, searchfield or "name") if filter_fields: fields = list(set(fields + json.loads(filter_fields))) - formatted_fields = ["`tab%s`.`%s`" % (meta.name, f.strip()) for f in fields] + formatted_fields = [f"`tab{meta.name}`.`{f.strip()}`" for f in fields] title_field_query = get_title_field_query(meta) @@ -197,7 +197,7 @@ def search_widget( order_by_based_on_meta = get_order_by(doctype, meta) # 2 is the index of _relevance column - order_by = "_relevance, {0}, `tab{1}`.idx desc".format(order_by_based_on_meta, doctype) + order_by = f"_relevance, {order_by_based_on_meta}, `tab{doctype}`.idx desc" ptype = "select" if frappe.only_has_select_perm(doctype) else "read" ignore_permissions = ( @@ -270,7 +270,7 @@ def get_title_field_query(meta): field = None if title_field and show_title_field_in_link: - field = "`tab{0}`.{1} as `label`".format(meta.name, title_field) + field = f"`tab{meta.name}`.{title_field} as `label`" return field diff --git a/frappe/desk/treeview.py b/frappe/desk/treeview.py index d7a8db8792..f8b2a67c82 100644 --- a/frappe/desk/treeview.py +++ b/frappe/desk/treeview.py @@ -43,7 +43,7 @@ def get_children(doctype, parent="", **filters): def _get_children(doctype, parent="", ignore_permissions=False): parent_field = "parent_" + doctype.lower().replace(" ", "_") - filters = [["ifnull(`{0}`,'')".format(parent_field), "=", parent], ["docstatus", "<", 2]] + filters = [[f"ifnull(`{parent_field}`,'')", "=", parent], ["docstatus", "<", 2]] meta = frappe.get_meta(doctype) @@ -51,7 +51,7 @@ def _get_children(doctype, parent="", ignore_permissions=False): doctype, fields=[ "name as value", - "{0} as title".format(meta.get("title_field") or "name"), + "{} as title".format(meta.get("title_field") or "name"), "is_group as expandable", ], filters=filters, diff --git a/frappe/email/__init__.py b/frappe/email/__init__.py index 42fcb7b01a..0f0259653a 100644 --- a/frappe/email/__init__.py +++ b/frappe/email/__init__.py @@ -18,7 +18,7 @@ def get_contact_list(txt, page_length=20): return cached_contacts[:page_length] match_conditions = build_match_conditions("Contact") - match_conditions = "and {0}".format(match_conditions) if match_conditions else "" + match_conditions = f"and {match_conditions}" if match_conditions else "" out = frappe.db.sql( """select email_id as value, diff --git a/frappe/email/doctype/auto_email_report/auto_email_report.py b/frappe/email/doctype/auto_email_report/auto_email_report.py index 9f897a1308..b9b5e4e8d7 100644 --- a/frappe/email/doctype/auto_email_report/auto_email_report.py +++ b/frappe/email/doctype/auto_email_report/auto_email_report.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -165,7 +164,7 @@ class AutoEmailReport(Document): ) def get_file_name(self): - return "{0}.{1}".format(self.report.replace(" ", "-").replace("/", "-"), self.format.lower()) + return "{}.{}".format(self.report.replace(" ", "-").replace("/", "-"), self.format.lower()) def prepare_dynamic_filters(self): self.filters = frappe.parse_json(self.filters) @@ -260,9 +259,7 @@ def send_daily(): try: auto_email_report.send() except Exception as e: - auto_email_report.log_error( - "Failed to send {0} Auto Email Report".format(auto_email_report.name) - ) + auto_email_report.log_error(f"Failed to send {auto_email_report.name} Auto Email Report") def send_monthly(): diff --git a/frappe/email/doctype/auto_email_report/test_auto_email_report.py b/frappe/email/doctype/auto_email_report/test_auto_email_report.py index aa8dffb9e0..ee0a363bd9 100644 --- a/frappe/email/doctype/auto_email_report/test_auto_email_report.py +++ b/frappe/email/doctype/auto_email_report/test_auto_email_report.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # License: MIT. See LICENSE import json diff --git a/frappe/email/doctype/document_follow/document_follow.py b/frappe/email/doctype/document_follow/document_follow.py index 3b7d411fb5..6f9d63f3be 100644 --- a/frappe/email/doctype/document_follow/document_follow.py +++ b/frappe/email/doctype/document_follow/document_follow.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/email/doctype/document_follow/test_document_follow.py b/frappe/email/doctype/document_follow/test_document_follow.py index 1f31338351..159a399ee8 100644 --- a/frappe/email/doctype/document_follow/test_document_follow.py +++ b/frappe/email/doctype/document_follow/test_document_follow.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index a89b9a2747..02afe4f4b5 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -8,7 +8,6 @@ import socket import time from datetime import datetime, timedelta from poplib import error_proto -from typing import List import frappe from frappe import _, are_emails_muted, safe_encode @@ -259,7 +258,7 @@ class EmailAccount(Document): else: frappe.throw(cstr(e)) - except socket.error: + except OSError: if in_receive: # timeout while connecting, see receive.py connect method description = frappe.message_log.pop() if frappe.message_log else "Socket Error" @@ -444,10 +443,10 @@ class EmailAccount(Document): frappe.cache().set_value("workers:no-internet", True) def set_failed_attempts_count(self, value): - frappe.cache().set("{0}:email-account-failed-attempts".format(self.name), value) + frappe.cache().set(f"{self.name}:email-account-failed-attempts", value) def get_failed_attempts_count(self): - return cint(frappe.cache().get("{0}:email-account-failed-attempts".format(self.name))) + return cint(frappe.cache().get(f"{self.name}:email-account-failed-attempts")) def receive(self): """Called by scheduler to receive emails from this EMail account using POP3/IMAP.""" @@ -485,7 +484,7 @@ class EmailAccount(Document): if exceptions: raise Exception(frappe.as_json(exceptions)) - def get_inbound_mails(self) -> List[InboundMail]: + def get_inbound_mails(self) -> list[InboundMail]: """retrive and return inbound mails.""" mails = [] @@ -595,7 +594,7 @@ class EmailAccount(Document): if self.email_sync_option == "ALL": max_uid = get_max_email_uid(self.name) last_uid = max_uid + int(self.initial_sync_count or 100) if max_uid == 1 else "*" - return "UID {}:{}".format(max_uid, last_uid) + return f"UID {max_uid}:{last_uid}" else: return self.email_sync_option or "UNSEEN" @@ -786,7 +785,7 @@ def pull(now=False): else: # job_name is used to prevent duplicates in queue - job_name = "pull_from_email_account|{0}".format(email_account.name) + job_name = f"pull_from_email_account|{email_account.name}" if job_name not in queued_jobs: enqueue( diff --git a/frappe/email/doctype/email_account/test_email_account.py b/frappe/email/doctype/email_account/test_email_account.py index 537bf9eb7f..9ab004cdd0 100644 --- a/frappe/email/doctype/email_account/test_email_account.py +++ b/frappe/email/doctype/email_account/test_email_account.py @@ -39,7 +39,7 @@ class TestEmailAccount(unittest.TestCase): frappe.db.delete("Unhandled Email") def get_test_mail(self, fname): - with open(os.path.join(os.path.dirname(__file__), "test_mails", fname), "r") as f: + with open(os.path.join(os.path.dirname(__file__), "test_mails", fname)) as f: return f.read() def test_incoming(self): @@ -211,7 +211,7 @@ class TestEmailAccount(unittest.TestCase): sent_mail = email.message_from_string(frappe.get_last_doc("Email Queue").message) - with open(os.path.join(os.path.dirname(__file__), "test_mails", "reply-1.raw"), "r") as f: + with open(os.path.join(os.path.dirname(__file__), "test_mails", "reply-1.raw")) as f: raw = f.read() raw = raw.replace("<-- in-reply-to -->", sent_mail.get("Message-Id")) @@ -233,10 +233,10 @@ class TestEmailAccount(unittest.TestCase): def test_threading_by_subject(self): cleanup(["in", ["test_sender@example.com", "test@example.com"]]) - with open(os.path.join(os.path.dirname(__file__), "test_mails", "reply-2.raw"), "r") as f: + with open(os.path.join(os.path.dirname(__file__), "test_mails", "reply-2.raw")) as f: test_mails = [f.read()] - with open(os.path.join(os.path.dirname(__file__), "test_mails", "reply-3.raw"), "r") as f: + with open(os.path.join(os.path.dirname(__file__), "test_mails", "reply-3.raw")) as f: test_mails.append(f.read()) # parse reply @@ -280,7 +280,7 @@ class TestEmailAccount(unittest.TestCase): last_mail = frappe.get_doc("Email Queue", dict(reference_name=event.name)) # get test mail with message-id as in-reply-to - with open(os.path.join(os.path.dirname(__file__), "test_mails", "reply-4.raw"), "r") as f: + with open(os.path.join(os.path.dirname(__file__), "test_mails", "reply-4.raw")) as f: messages = { # append_to = ToDo '"INBOX"': { @@ -451,7 +451,7 @@ class TestInboundMail(unittest.TestCase): frappe.db.delete("ToDo") def get_test_mail(self, fname): - with open(os.path.join(os.path.dirname(__file__), "test_mails", fname), "r") as f: + with open(os.path.join(os.path.dirname(__file__), "test_mails", fname)) as f: return f.read() def new_doc(self, doctype, **data): diff --git a/frappe/email/doctype/email_domain/email_domain.py b/frappe/email/doctype/email_domain/email_domain.py index ff59725fd7..ab6546e4e6 100644 --- a/frappe/email/doctype/email_domain/email_domain.py +++ b/frappe/email/doctype/email_domain/email_domain.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors # License: MIT. See LICENSE @@ -53,12 +52,10 @@ class EmailDomain(Document): test = poplib.POP3(self.email_server, port=get_port(self)) except Exception as e: - logger.warn( - 'Incoming email account "{host}" not correct'.format(host=self.email_server), exc_info=e - ) + logger.warn(f'Incoming email account "{self.email_server}" not correct', exc_info=e) frappe.throw( title=_("Incoming email account not correct"), - msg='Error connecting IMAP/POP3 "{host}": {e}'.format(host=self.email_server, e=e), + msg=f'Error connecting IMAP/POP3 "{self.email_server}": {e}', ) finally: @@ -94,12 +91,10 @@ class EmailDomain(Document): sess = smtplib.SMTP(cstr(self.smtp_server or ""), cint(self.smtp_port) or None) sess.quit() except Exception as e: - logger.warn( - 'Outgoing email account "{host}" not correct'.format(host=self.smtp_server), exc_info=e - ) + logger.warn(f'Outgoing email account "{self.smtp_server}" not correct', exc_info=e) frappe.throw( title=_("Outgoing email account not correct"), - msg='Error connecting SMTP "{host}": {e}'.format(host=self.smtp_server, e=e), + msg=f'Error connecting SMTP "{self.smtp_server}": {e}', ) def on_update(self): diff --git a/frappe/email/doctype/email_domain/test_email_domain.py b/frappe/email/doctype/email_domain/test_email_domain.py index 0162e4efe0..55a8d620a8 100644 --- a/frappe/email/doctype/email_domain/test_email_domain.py +++ b/frappe/email/doctype/email_domain/test_email_domain.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/email/doctype/email_flag_queue/email_flag_queue.py b/frappe/email/doctype/email_flag_queue/email_flag_queue.py index b7ca48faf0..cf28ce0628 100644 --- a/frappe/email/doctype/email_flag_queue/email_flag_queue.py +++ b/frappe/email/doctype/email_flag_queue/email_flag_queue.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/email/doctype/email_flag_queue/test_email_flag_queue.py b/frappe/email/doctype/email_flag_queue/test_email_flag_queue.py index 11571da7d9..8bfc9230a4 100644 --- a/frappe/email/doctype/email_flag_queue/test_email_flag_queue.py +++ b/frappe/email/doctype/email_flag_queue/test_email_flag_queue.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/email/doctype/email_group/email_group.py b/frappe/email/doctype/email_group/email_group.py index 6489e82341..ea62a6e9ec 100755 --- a/frappe/email/doctype/email_group/email_group.py +++ b/frappe/email/doctype/email_group/email_group.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -12,7 +11,7 @@ class EmailGroup(Document): def onload(self): singles = [d.name for d in frappe.db.get_all("DocType", "name", {"issingle": 1})] self.get("__onload").import_types = [ - {"value": d.parent, "label": "{0} ({1})".format(d.parent, d.label)} + {"value": d.parent, "label": f"{d.parent} ({d.label})"} for d in frappe.db.get_all("DocField", ("parent", "label"), {"options": "Email"}) if d.parent not in singles ] diff --git a/frappe/email/doctype/email_group/test_email_group.py b/frappe/email/doctype/email_group/test_email_group.py index 96032d35cc..aa41285f90 100644 --- a/frappe/email/doctype/email_group/test_email_group.py +++ b/frappe/email/doctype/email_group/test_email_group.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/email/doctype/email_group_member/email_group_member.py b/frappe/email/doctype/email_group_member/email_group_member.py index 76990b18fb..c0995d393b 100644 --- a/frappe/email/doctype/email_group_member/email_group_member.py +++ b/frappe/email/doctype/email_group_member/email_group_member.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/email/doctype/email_group_member/test_email_group_member.py b/frappe/email/doctype/email_group_member/test_email_group_member.py index ae608a4e15..749792fe52 100644 --- a/frappe/email/doctype/email_group_member/test_email_group_member.py +++ b/frappe/email/doctype/email_group_member/test_email_group_member.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/email/doctype/email_queue/email_queue.py b/frappe/email/doctype/email_queue/email_queue.py index c51446947c..7b57adf6fb 100644 --- a/frappe/email/doctype/email_queue/email_queue.py +++ b/frappe/email/doctype/email_queue/email_queue.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -156,7 +155,7 @@ class EmailQueue(Document): ( frappe.qb.from_(email_queue) .delete() - .where((email_queue.modified < (Now() - Interval(days=days)))) + .where(email_queue.modified < (Now() - Interval(days=days))) ).run() # delete child tables, note that this has potential to leave some orphan @@ -165,7 +164,7 @@ class EmailQueue(Document): ( frappe.qb.from_(email_recipient) .delete() - .where((email_recipient.modified < (Now() - Interval(days=days)))) + .where(email_recipient.modified < (Now() - Interval(days=days))) ).run() @@ -244,7 +243,7 @@ class SendMailContext: self.sent_to.append(recipient.recipient) def is_mail_sent_to_all(self): - return sorted(self.sent_to) == sorted([rec.recipient for rec in self.queue_doc.recipients]) + return sorted(self.sent_to) == sorted(rec.recipient for rec in self.queue_doc.recipients) def get_message_object(self, message): return Parser(policy=SMTPUTF8).parsestr(message) @@ -660,7 +659,7 @@ class QueueBuilder: # bad Email Address - don't add to queue frappe.log_error( title="Invalid email address", - message="Invalid email address Sender: {0}, Recipients: {1}, \nTraceback: {2} ".format( + message="Invalid email address Sender: {}, Recipients: {}, \nTraceback: {} ".format( self.sender, ", ".join(self.final_recipients()), traceback.format_exc() ), reference_doctype=self.reference_doctype, diff --git a/frappe/email/doctype/email_queue/test_email_queue.py b/frappe/email/doctype/email_queue/test_email_queue.py index 435e4e691f..5a608b1b23 100644 --- a/frappe/email/doctype/email_queue/test_email_queue.py +++ b/frappe/email/doctype/email_queue/test_email_queue.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # License: MIT. See LICENSE diff --git a/frappe/email/doctype/email_queue_recipient/email_queue_recipient.py b/frappe/email/doctype/email_queue_recipient/email_queue_recipient.py index d2e4753ddf..bcb8d9b05d 100644 --- a/frappe/email/doctype/email_queue_recipient/email_queue_recipient.py +++ b/frappe/email/doctype/email_queue_recipient/email_queue_recipient.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/email/doctype/email_rule/email_rule.py b/frappe/email/doctype/email_rule/email_rule.py index 5075024b73..ab04632280 100644 --- a/frappe/email/doctype/email_rule/email_rule.py +++ b/frappe/email/doctype/email_rule/email_rule.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/email/doctype/email_rule/test_email_rule.py b/frappe/email/doctype/email_rule/test_email_rule.py index 7b7a9a5c23..1da5d34d6b 100644 --- a/frappe/email/doctype/email_rule/test_email_rule.py +++ b/frappe/email/doctype/email_rule/test_email_rule.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/email/doctype/email_template/test_email_template.py b/frappe/email/doctype/email_template/test_email_template.py index d37b5497fb..291f7e1df0 100644 --- a/frappe/email/doctype/email_template/test_email_template.py +++ b/frappe/email/doctype/email_template/test_email_template.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/email/doctype/email_unsubscribe/email_unsubscribe.py b/frappe/email/doctype/email_unsubscribe/email_unsubscribe.py index 131546a3c2..c9ab17d61d 100644 --- a/frappe/email/doctype/email_unsubscribe/email_unsubscribe.py +++ b/frappe/email/doctype/email_unsubscribe/email_unsubscribe.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors # License: MIT. See LICENSE diff --git a/frappe/email/doctype/email_unsubscribe/test_email_unsubscribe.py b/frappe/email/doctype/email_unsubscribe/test_email_unsubscribe.py index 0133c6c4b5..9ba99a6690 100644 --- a/frappe/email/doctype/email_unsubscribe/test_email_unsubscribe.py +++ b/frappe/email/doctype/email_unsubscribe/test_email_unsubscribe.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/email/doctype/newsletter/newsletter.py b/frappe/email/doctype/newsletter/newsletter.py index 6fcdce482f..757a8c875b 100644 --- a/frappe/email/doctype/newsletter/newsletter.py +++ b/frappe/email/doctype/newsletter/newsletter.py @@ -1,7 +1,6 @@ # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See LICENSE -from typing import Dict, List import frappe import frappe.utils @@ -21,7 +20,7 @@ class Newsletter(WebsiteGenerator): self.validate_publishing() @property - def newsletter_recipients(self) -> List[str]: + def newsletter_recipients(self) -> list[str]: if getattr(self, "_recipients", None) is None: self._recipients = self.get_recipients() return self._recipients @@ -112,7 +111,7 @@ class Newsletter(WebsiteGenerator): if self.send_webview_link and not self.published: frappe.throw(_("Newsletter must be published to send webview link in email")) - def get_linked_email_queue(self) -> List[str]: + def get_linked_email_queue(self) -> list[str]: """Get list of email queue linked to this newsletter.""" return frappe.get_all( "Email Queue", @@ -123,7 +122,7 @@ class Newsletter(WebsiteGenerator): pluck="name", ) - def get_success_recipients(self) -> List[str]: + def get_success_recipients(self) -> list[str]: """Recipients who have already received the newsletter. Couldn't think of a better name ;) @@ -137,7 +136,7 @@ class Newsletter(WebsiteGenerator): pluck="recipient", ) - def get_pending_recipients(self) -> List[str]: + def get_pending_recipients(self) -> list[str]: """Get list of pending recipients of the newsletter. These recipients may not have receive the newsletter in the previous iteration. """ @@ -156,11 +155,11 @@ class Newsletter(WebsiteGenerator): self.total_recipients = len(recipients) self.save() - def get_newsletter_attachments(self) -> List[Dict[str, str]]: + def get_newsletter_attachments(self) -> list[dict[str, str]]: """Get list of attachments on current Newsletter""" return [{"file_url": row.attachment} for row in self.attachments] - def send_newsletter(self, emails: List[str]): + def send_newsletter(self, emails: list[str]): """Trigger email generation for `emails` and add it in Email Queue.""" attachments = self.get_newsletter_attachments() sender = self.send_from or frappe.utils.get_formatted_email(self.owner) @@ -197,7 +196,7 @@ class Newsletter(WebsiteGenerator): return frappe.render_template(message, {"doc": self.as_dict()}) - def get_recipients(self) -> List[str]: + def get_recipients(self) -> list[str]: """Get recipients from Email Group""" emails = frappe.get_all( "Email Group Member", @@ -206,7 +205,7 @@ class Newsletter(WebsiteGenerator): ) return list(set(emails)) - def get_email_groups(self) -> List[str]: + def get_email_groups(self) -> list[str]: # wondering why the 'or'? i can't figure out why both aren't equivalent - @gavin return [x.email_group for x in self.email_group] or frappe.get_all( "Newsletter Email Group", @@ -214,7 +213,7 @@ class Newsletter(WebsiteGenerator): pluck="email_group", ) - def get_attachments(self) -> List[Dict[str, str]]: + def get_attachments(self) -> list[dict[str, str]]: return frappe.get_all( "File", fields=["name", "file_name", "file_url", "is_private"], @@ -267,8 +266,8 @@ def subscribe(email, email_group=_("Website")): # noqa _("Click here to verify"), ) content = """ -

    {0}. {1}.

    -

    {3}

    +

    {}. {}.

    +

    {}

    """.format( *translatable_content ) diff --git a/frappe/email/doctype/newsletter/test_newsletter.py b/frappe/email/doctype/newsletter/test_newsletter.py index 550ee8164b..524289db7f 100644 --- a/frappe/email/doctype/newsletter/test_newsletter.py +++ b/frappe/email/doctype/newsletter/test_newsletter.py @@ -2,7 +2,6 @@ # MIT License. See LICENSE from random import choice -from typing import Union from unittest.mock import MagicMock, PropertyMock, patch import frappe @@ -79,7 +78,7 @@ class TestNewsletterMixin: frappe.db.release_savepoint(savepoint) - def send_newsletter(self, published=0, schedule_send=None) -> Union[str, None]: + def send_newsletter(self, published=0, schedule_send=None) -> str | None: frappe.db.delete("Email Queue") frappe.db.delete("Email Queue Recipient") frappe.db.delete("Newsletter") diff --git a/frappe/email/doctype/newsletter_email_group/newsletter_email_group.py b/frappe/email/doctype/newsletter_email_group/newsletter_email_group.py index 9fe1364d11..41ada8a491 100644 --- a/frappe/email/doctype/newsletter_email_group/newsletter_email_group.py +++ b/frappe/email/doctype/newsletter_email_group/newsletter_email_group.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/email/doctype/notification/notification.py b/frappe/email/doctype/notification/notification.py index 496a05bf6a..8d0857ac60 100644 --- a/frappe/email/doctype/notification/notification.py +++ b/frappe/email/doctype/notification/notification.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -368,7 +367,7 @@ def get_context(context): template = "" template_path = os.path.join(os.path.dirname(module.__file__), frappe.scrub(self.name) + extn) if os.path.exists(template_path): - with open(template_path, "r") as f: + with open(template_path) as f: template = f.read() return template @@ -433,7 +432,7 @@ def evaluate_alert(doc: Document, alert, event): if event == "Value Change" and not doc.is_new(): if not frappe.db.has_column(doc.doctype, alert.value_changed): alert.db_set("enabled", 0) - alert.log_error("Notification {0} has been disabled due to missing field".format(alert.name)) + alert.log_error(f"Notification {alert.name} has been disabled due to missing field") return doc_before_save = doc.get_doc_before_save() diff --git a/frappe/email/doctype/notification/test_notification.py b/frappe/email/doctype/notification/test_notification.py index 7a31fc7434..4adaeae37e 100644 --- a/frappe/email/doctype/notification/test_notification.py +++ b/frappe/email/doctype/notification/test_notification.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/email/doctype/notification_recipient/notification_recipient.py b/frappe/email/doctype/notification_recipient/notification_recipient.py index 1785590e93..75bb274599 100644 --- a/frappe/email/doctype/notification_recipient/notification_recipient.py +++ b/frappe/email/doctype/notification_recipient/notification_recipient.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/email/doctype/unhandled_email/test_unhandled_email.py b/frappe/email/doctype/unhandled_email/test_unhandled_email.py index 1485f3bbaa..debc52d685 100644 --- a/frappe/email/doctype/unhandled_email/test_unhandled_email.py +++ b/frappe/email/doctype/unhandled_email/test_unhandled_email.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/email/doctype/unhandled_email/unhandled_email.py b/frappe/email/doctype/unhandled_email/unhandled_email.py index e703f1ec97..1c315e2423 100644 --- a/frappe/email/doctype/unhandled_email/unhandled_email.py +++ b/frappe/email/doctype/unhandled_email/unhandled_email.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors # License: MIT. See LICENSE diff --git a/frappe/email/email_body.py b/frappe/email/email_body.py index 3a952e1487..3288ca2148 100755 --- a/frappe/email/email_body.py +++ b/frappe/email/email_body.py @@ -7,7 +7,6 @@ import re from email import policy from email.header import Header from email.mime.multipart import MIMEMultipart -from typing import Optional import frappe from frappe.email.doctype.email_account.email_account import EmailAccount @@ -354,7 +353,7 @@ def get_formatted_html( print_html=None, email_account=None, header=None, - unsubscribe_link: Optional[frappe._dict] = None, + unsubscribe_link: frappe._dict | None = None, sender=None, with_container=False, ): @@ -454,7 +453,7 @@ def add_attachment(fname, fcontent, content_type=None, parent=None, content_id=N attachment_type = "inline" if inline else "attachment" part.add_header("Content-Disposition", attachment_type, filename=str(fname)) if content_id: - part.add_header("Content-ID", "<{0}>".format(content_id)) + part.add_header("Content-ID", f"<{content_id}>") parent.attach(part) diff --git a/frappe/email/receive.py b/frappe/email/receive.py index dd8273d778..93e1a68285 100644 --- a/frappe/email/receive.py +++ b/frappe/email/receive.py @@ -269,7 +269,7 @@ class EmailServer: 1 if uidnext < (sync_count + 1) or (uidnext - sync_count) < 1 else uidnext - sync_count ) # sync last 100 email - self.settings.email_sync_rule = "UID {}:{}".format(from_uid, uidnext) + self.settings.email_sync_rule = f"UID {from_uid}:{uidnext}" self.uid_reindexed = True elif uid_validity == current_uid_validity: @@ -534,10 +534,10 @@ class Email: for key in ("From", "To", "Subject", "Date"): value = cstr(message.get(key)) if value: - headers.append("{label}: {value}".format(label=_(key), value=escape(value))) + headers.append(f"{_(key)}: {escape(value)}") self.text_content += "\n".join(headers) - self.html_content += "
    " + "\n".join("

    {0}

    ".format(h) for h in headers) + self.html_content += "
    " + "\n".join(f"

    {h}

    " for h in headers) if not message.is_multipart() and message.get_content_type() == "text/plain": # email.parser didn't parse it! @@ -710,7 +710,7 @@ class InboundMail(Email): content = self.content for file in attachments: if file.name in self.cid_map and self.cid_map[file.name]: - content = content.replace("cid:{0}".format(self.cid_map[file.name]), file.file_url) + content = content.replace(f"cid:{self.cid_map[file.name]}", file.file_url) return content def is_notification(self): @@ -895,7 +895,7 @@ class InboundMail(Email): users = frappe.get_all( "User Email", filters={"email_account": email_account.name}, fields=["parent"] ) - return list(set([user.get("parent") for user in users])) + return list({user.get("parent") for user in users}) @staticmethod def clean_subject(subject): @@ -946,7 +946,7 @@ class InboundMail(Email): } -class TimerMixin(object): +class TimerMixin: def __init__(self, *args, **kwargs): self.timeout = kwargs.pop("timeout", 0.0) self.elapsed_time = 0.0 diff --git a/frappe/email/test_email_body.py b/frappe/email/test_email_body.py index 3de21f64ce..9f76ec6a59 100644 --- a/frappe/email/test_email_body.py +++ b/frappe/email/test_email_body.py @@ -128,7 +128,7 @@ w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> processed_message = """
    - test + test
    """.format( diff --git a/frappe/event_streaming/doctype/document_type_field_mapping/document_type_field_mapping.py b/frappe/event_streaming/doctype/document_type_field_mapping/document_type_field_mapping.py index 3019d70035..96d9e0fcb3 100644 --- a/frappe/event_streaming/doctype/document_type_field_mapping/document_type_field_mapping.py +++ b/frappe/event_streaming/doctype/document_type_field_mapping/document_type_field_mapping.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/event_streaming/doctype/document_type_mapping/document_type_mapping.py b/frappe/event_streaming/doctype/document_type_mapping/document_type_mapping.py index bcd2b275d1..04b5015296 100644 --- a/frappe/event_streaming/doctype/document_type_mapping/document_type_mapping.py +++ b/frappe/event_streaming/doctype/document_type_mapping/document_type_mapping.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE import json diff --git a/frappe/event_streaming/doctype/document_type_mapping/test_document_type_mapping.py b/frappe/event_streaming/doctype/document_type_mapping/test_document_type_mapping.py index 1d5c4862de..676d5040ff 100644 --- a/frappe/event_streaming/doctype/document_type_mapping/test_document_type_mapping.py +++ b/frappe/event_streaming/doctype/document_type_mapping/test_document_type_mapping.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/event_streaming/doctype/event_consumer/event_consumer.py b/frappe/event_streaming/doctype/event_consumer/event_consumer.py index bcd3d3be39..a2ae6f6651 100644 --- a/frappe/event_streaming/doctype/event_consumer/event_consumer.py +++ b/frappe/event_streaming/doctype/event_consumer/event_consumer.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/event_streaming/doctype/event_consumer/test_event_consumer.py b/frappe/event_streaming/doctype/event_consumer/test_event_consumer.py index 605fc7982a..6f04af643e 100644 --- a/frappe/event_streaming/doctype/event_consumer/test_event_consumer.py +++ b/frappe/event_streaming/doctype/event_consumer/test_event_consumer.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/event_streaming/doctype/event_consumer_document_type/event_consumer_document_type.py b/frappe/event_streaming/doctype/event_consumer_document_type/event_consumer_document_type.py index b33313087f..1ed15c5a75 100644 --- a/frappe/event_streaming/doctype/event_consumer_document_type/event_consumer_document_type.py +++ b/frappe/event_streaming/doctype/event_consumer_document_type/event_consumer_document_type.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/event_streaming/doctype/event_producer/event_producer.py b/frappe/event_streaming/doctype/event_producer/event_producer.py index adbb706c3d..f91c8a4fd4 100644 --- a/frappe/event_streaming/doctype/event_producer/event_producer.py +++ b/frappe/event_streaming/doctype/event_producer/event_producer.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/event_streaming/doctype/event_producer/test_event_producer.py b/frappe/event_streaming/doctype/event_producer/test_event_producer.py index eafa7a0b51..168c9a61cf 100644 --- a/frappe/event_streaming/doctype/event_producer/test_event_producer.py +++ b/frappe/event_streaming/doctype/event_producer/test_event_producer.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE import json diff --git a/frappe/event_streaming/doctype/event_producer_document_type/event_producer_document_type.py b/frappe/event_streaming/doctype/event_producer_document_type/event_producer_document_type.py index 3e9623f56f..8f4c936792 100644 --- a/frappe/event_streaming/doctype/event_producer_document_type/event_producer_document_type.py +++ b/frappe/event_streaming/doctype/event_producer_document_type/event_producer_document_type.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/event_streaming/doctype/event_producer_last_update/event_producer_last_update.py b/frappe/event_streaming/doctype/event_producer_last_update/event_producer_last_update.py index 8e32e6fe6f..ec5cee7e78 100644 --- a/frappe/event_streaming/doctype/event_producer_last_update/event_producer_last_update.py +++ b/frappe/event_streaming/doctype/event_producer_last_update/event_producer_last_update.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/event_streaming/doctype/event_producer_last_update/test_event_producer_last_update.py b/frappe/event_streaming/doctype/event_producer_last_update/test_event_producer_last_update.py index 6054ec873f..ccdea6c694 100644 --- a/frappe/event_streaming/doctype/event_producer_last_update/test_event_producer_last_update.py +++ b/frappe/event_streaming/doctype/event_producer_last_update/test_event_producer_last_update.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/event_streaming/doctype/event_sync_log/event_sync_log.py b/frappe/event_streaming/doctype/event_sync_log/event_sync_log.py index c26ca46e05..a1d82ad08f 100644 --- a/frappe/event_streaming/doctype/event_sync_log/event_sync_log.py +++ b/frappe/event_streaming/doctype/event_sync_log/event_sync_log.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/event_streaming/doctype/event_sync_log/test_event_sync_log.py b/frappe/event_streaming/doctype/event_sync_log/test_event_sync_log.py index da90c8e634..13028cbac7 100644 --- a/frappe/event_streaming/doctype/event_sync_log/test_event_sync_log.py +++ b/frappe/event_streaming/doctype/event_sync_log/test_event_sync_log.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/event_streaming/doctype/event_update_log/event_update_log.py b/frappe/event_streaming/doctype/event_update_log/event_update_log.py index 658a3b47cc..e40f600484 100644 --- a/frappe/event_streaming/doctype/event_update_log/event_update_log.py +++ b/frappe/event_streaming/doctype/event_update_log/event_update_log.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors # License: MIT. See LICENSE diff --git a/frappe/event_streaming/doctype/event_update_log/test_event_update_log.py b/frappe/event_streaming/doctype/event_update_log/test_event_update_log.py index 673164b8d7..0cbff47912 100644 --- a/frappe/event_streaming/doctype/event_update_log/test_event_update_log.py +++ b/frappe/event_streaming/doctype/event_update_log/test_event_update_log.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/event_streaming/doctype/event_update_log_consumer/event_update_log_consumer.py b/frappe/event_streaming/doctype/event_update_log_consumer/event_update_log_consumer.py index 4f00504538..69da7db92e 100644 --- a/frappe/event_streaming/doctype/event_update_log_consumer/event_update_log_consumer.py +++ b/frappe/event_streaming/doctype/event_update_log_consumer/event_update_log_consumer.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/exceptions.py b/frappe/exceptions.py index 755c21c240..c3bb45caea 100644 --- a/frappe/exceptions.py +++ b/frappe/exceptions.py @@ -76,7 +76,7 @@ class ImproperDBConfigurationError(Exception): def __init__(self, reason, msg=None): if not msg: msg = "MariaDb is not properly configured" - super(ImproperDBConfigurationError, self).__init__(msg) + super().__init__(msg) self.reason = reason diff --git a/frappe/frappeclient.py b/frappe/frappeclient.py index 04087463bc..474a5b06c4 100644 --- a/frappe/frappeclient.py +++ b/frappe/frappeclient.py @@ -26,7 +26,7 @@ class FrappeException(Exception): pass -class FrappeClient(object): +class FrappeClient: def __init__( self, url, @@ -85,11 +85,9 @@ class FrappeClient(object): def setup_key_authentication_headers(self): if self.api_key and self.api_secret: - token = base64.b64encode( - ("{}:{}".format(self.api_key, self.api_secret)).encode("utf-8") - ).decode("utf-8") + token = base64.b64encode((f"{self.api_key}:{self.api_secret}").encode()).decode("utf-8") auth_header = { - "Authorization": "Basic {}".format(token), + "Authorization": f"Basic {token}", } self.headers.update(auth_header) @@ -266,7 +264,7 @@ class FrappeClient(object): # build - attach children to parents if tables: docs = [frappe._dict(doc) for doc in docs] - docs_map = dict((doc.name, doc) for doc in docs) + docs_map = {doc.name: doc for doc in docs} for fieldname in tables: for child in tables[fieldname]: diff --git a/frappe/geo/country_info.py b/frappe/geo/country_info.py index 1de8467a6a..2aefa27170 100644 --- a/frappe/geo/country_info.py +++ b/frappe/geo/country_info.py @@ -22,7 +22,7 @@ def get_country_info(country=None): def get_all(): - with open(os.path.join(os.path.dirname(__file__), "country_info.json"), "r") as local_info: + with open(os.path.join(os.path.dirname(__file__), "country_info.json")) as local_info: all_data = json.loads(local_info.read()) return all_data @@ -59,7 +59,7 @@ def get_translated_dict(): def update(): - with open(os.path.join(os.path.dirname(__file__), "currency_info.json"), "r") as nformats: + with open(os.path.join(os.path.dirname(__file__), "currency_info.json")) as nformats: nformats = json.loads(nformats.read()) all_data = get_all() diff --git a/frappe/geo/doctype/country/__init__.py b/frappe/geo/doctype/country/__init__.py index 8b13789179..e69de29bb2 100644 --- a/frappe/geo/doctype/country/__init__.py +++ b/frappe/geo/doctype/country/__init__.py @@ -1 +0,0 @@ - diff --git a/frappe/geo/doctype/currency/__init__.py b/frappe/geo/doctype/currency/__init__.py index 8b13789179..e69de29bb2 100644 --- a/frappe/geo/doctype/currency/__init__.py +++ b/frappe/geo/doctype/currency/__init__.py @@ -1 +0,0 @@ - diff --git a/frappe/geo/utils.py b/frappe/geo/utils.py index 577c5de2ff..c8e05be357 100644 --- a/frappe/geo/utils.py +++ b/frappe/geo/utils.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -65,7 +64,7 @@ def return_location(doctype, filters_sql): if filters_sql: try: coords = frappe.db.sql( - """SELECT name, location FROM `tab{}` WHERE {}""".format(doctype, filters_sql), as_dict=True + f"""SELECT name, location FROM `tab{doctype}` WHERE {filters_sql}""", as_dict=True ) except InternalError: frappe.msgprint(frappe._("This Doctype does not contain location fields"), raise_exception=True) @@ -80,7 +79,7 @@ def return_coordinates(doctype, filters_sql): if filters_sql: try: coords = frappe.db.sql( - """SELECT name, latitude, longitude FROM `tab{}` WHERE {}""".format(doctype, filters_sql), + f"""SELECT name, latitude, longitude FROM `tab{doctype}` WHERE {filters_sql}""", as_dict=True, ) except InternalError: diff --git a/frappe/installer.py b/frappe/installer.py index 59c5dc6602..9d35f04e0d 100644 --- a/frappe/installer.py +++ b/frappe/installer.py @@ -5,7 +5,6 @@ import json import os import sys from collections import OrderedDict -from typing import Dict, List, Tuple import click @@ -38,7 +37,7 @@ def _new_site( from frappe.utils import get_site_path, scheduler, touch_file if not force and os.path.exists(site): - print("Site {0} already exists".format(site)) + print(f"Site {site} already exists") sys.exit(1) if no_mariadb_socket and not db_type == "mariadb": @@ -151,7 +150,7 @@ def install_db( frappe.flags.in_install_db = False -def find_org(org_repo: str) -> Tuple[str, str]: +def find_org(org_repo: str) -> tuple[str, str]: """find the org a repo is in find_org() @@ -179,7 +178,7 @@ def find_org(org_repo: str) -> Tuple[str, str]: raise InvalidRemoteException -def fetch_details_from_tag(_tag: str) -> Tuple[str, str, str]: +def fetch_details_from_tag(_tag: str) -> tuple[str, str, str]: """parse org, repo, tag from string fetch_details_from_tag() @@ -263,7 +262,7 @@ def install_app(name, verbose=False, set_as_patched=True, force=False): click.secho(f"App {name} already installed", fg="yellow") return - print("\nInstalling {0}...".format(name)) + print(f"\nInstalling {name}...") if name != "frappe": frappe.only_for("System Manager") @@ -371,7 +370,7 @@ def remove_app(app_name, dry_run=False, yes=False, no_backup=False, force=False) frappe.flags.in_uninstall = False -def _delete_modules(modules: List[str], dry_run: bool) -> List[str]: +def _delete_modules(modules: list[str], dry_run: bool) -> list[str]: """Delete modules belonging to the app and all related doctypes. Note: All record linked linked to Module Def are also deleted. @@ -404,7 +403,7 @@ def _delete_modules(modules: List[str], dry_run: bool) -> List[str]: def _delete_linked_documents( - module_name: str, doctype_linkfield_map: Dict[str, str], dry_run: bool + module_name: str, doctype_linkfield_map: dict[str, str], dry_run: bool ) -> None: """Deleted all records linked with module def""" @@ -415,7 +414,7 @@ def _delete_linked_documents( frappe.delete_doc(doctype, record, ignore_on_trash=True, force=True) -def _get_module_linked_doctype_field_map() -> Dict[str, str]: +def _get_module_linked_doctype_field_map() -> dict[str, str]: """Get all the doctypes which have module linked with them. returns ordered dictionary with doctype->link field mapping.""" @@ -444,7 +443,7 @@ def _get_module_linked_doctype_field_map() -> Dict[str, str]: return doctype_to_field_map -def _delete_doctypes(doctypes: List[str], dry_run: bool) -> None: +def _delete_doctypes(doctypes: list[str], dry_run: bool) -> None: for doctype in set(doctypes): print(f"* dropping Table for '{doctype}'...") if not dry_run: @@ -529,7 +528,7 @@ def update_site_config(key, value, validate=True, site_config_path=None): if not site_config_path: site_config_path = get_site_config_path() - with open(site_config_path, "r") as f: + with open(site_config_path) as f: site_config = json.loads(f.read()) # In case of non-int value @@ -664,7 +663,7 @@ def extract_sql_gzip(sql_gz_path): try: original_file = sql_gz_path decompressed_file = original_file.rstrip(".gz") - cmd = "gzip --decompress --force < {0} > {1}".format(original_file, decompressed_file) + cmd = f"gzip --decompress --force < {original_file} > {decompressed_file}" subprocess.check_call(cmd, shell=True) except Exception: raise @@ -800,7 +799,7 @@ def validate_database_sql(path, _raise=True): # dont bother checking if empty file if not empty_file: - with open(path, "r") as f: + with open(path) as f: for line in f: if "tabDefaultValue" in line: missing_table = False diff --git a/frappe/integrations/doctype/braintree_settings/braintree_settings.py b/frappe/integrations/doctype/braintree_settings/braintree_settings.py index 17330d7c84..35481c67c1 100644 --- a/frappe/integrations/doctype/braintree_settings/braintree_settings.py +++ b/frappe/integrations/doctype/braintree_settings/braintree_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -184,7 +183,7 @@ class BraintreeSettings(Document): ) def get_payment_url(self, **kwargs): - return get_url("./integrations/braintree_checkout?{0}".format(urlencode(kwargs))) + return get_url(f"./integrations/braintree_checkout?{urlencode(kwargs)}") def create_payment_request(self, data): self.data = frappe._dict(data) diff --git a/frappe/integrations/doctype/braintree_settings/test_braintree_settings.py b/frappe/integrations/doctype/braintree_settings/test_braintree_settings.py index 475a62be79..38d8909dfd 100644 --- a/frappe/integrations/doctype/braintree_settings/test_braintree_settings.py +++ b/frappe/integrations/doctype/braintree_settings/test_braintree_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/integrations/doctype/connected_app/connected_app.py b/frappe/integrations/doctype/connected_app/connected_app.py index e472193da8..308d1ca84a 100644 --- a/frappe/integrations/doctype/connected_app/connected_app.py +++ b/frappe/integrations/doctype/connected_app/connected_app.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/integrations/doctype/connected_app/test_connected_app.py b/frappe/integrations/doctype/connected_app/test_connected_app.py index 1597ec75bf..1acedff160 100644 --- a/frappe/integrations/doctype/connected_app/test_connected_app.py +++ b/frappe/integrations/doctype/connected_app/test_connected_app.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py index 8a6a7a4bfb..50c5fa8fe6 100644 --- a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py +++ b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -89,7 +88,7 @@ def take_backup_to_dropbox(retry_count=0, upload_db_backup=True): "frappe.integrations.doctype.dropbox_settings.dropbox_settings.take_backup_to_dropbox", queue="long", timeout=1500, - **args + **args, ) except Exception: if isinstance(error_log, str): @@ -212,7 +211,7 @@ def upload_file_to_dropbox(filename, folder, dropbox_client): mode = dropbox.files.WriteMode.overwrite f = open(encode(filename), "rb") - path = "{0}/{1}".format(folder, os.path.basename(filename)) + path = f"{folder}/{os.path.basename(filename)}" try: if file_size <= chunk_size: @@ -234,7 +233,7 @@ def upload_file_to_dropbox(filename, folder, dropbox_client): cursor.offset = f.tell() except dropbox.exceptions.ApiError as e: if isinstance(e.error, dropbox.files.UploadError): - error = "File Path: {path}\n".format(path=path) + error = f"File Path: {path}\n" error += frappe.get_traceback() frappe.log_error(error) else: @@ -326,7 +325,7 @@ def delete_older_backups(dropbox_client, folder_path, to_keep): def get_redirect_url(): if not frappe.conf.dropbox_broker_site: frappe.conf.dropbox_broker_site = "https://dropbox.erpnext.com" - url = "{0}/api/method/dropbox_erpnext_broker.www.setup_dropbox.get_authotize_url".format( + url = "{}/api/method/dropbox_erpnext_broker.www.setup_dropbox.get_authotize_url".format( frappe.conf.dropbox_broker_site ) diff --git a/frappe/integrations/doctype/dropbox_settings/test_dropbox_settings.py b/frappe/integrations/doctype/dropbox_settings/test_dropbox_settings.py index e73cf03268..b165e03780 100644 --- a/frappe/integrations/doctype/dropbox_settings/test_dropbox_settings.py +++ b/frappe/integrations/doctype/dropbox_settings/test_dropbox_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/integrations/doctype/google_calendar/google_calendar.py b/frappe/integrations/doctype/google_calendar/google_calendar.py index 71f0e83f80..d8dc7fab1d 100644 --- a/frappe/integrations/doctype/google_calendar/google_calendar.py +++ b/frappe/integrations/doctype/google_calendar/google_calendar.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -140,7 +139,7 @@ def authorize_access(g_calendar, reauthorize=None): frappe.db.commit() frappe.local.response["type"] = "redirect" - frappe.local.response["location"] = "/app/Form/{0}/{1}".format( + frappe.local.response["location"] = "/app/Form/{}/{}".format( quote("Google Calendar"), quote(google_calendar.name) ) diff --git a/frappe/integrations/doctype/google_contacts/google_contacts.py b/frappe/integrations/doctype/google_contacts/google_contacts.py index c26366f71a..5e4869be43 100644 --- a/frappe/integrations/doctype/google_contacts/google_contacts.py +++ b/frappe/integrations/doctype/google_contacts/google_contacts.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -91,7 +90,7 @@ def authorize_access(g_contact, reauthorize=None): frappe.db.commit() frappe.local.response["type"] = "redirect" - frappe.local.response["location"] = "/app/Form/Google%20Contacts/{}".format(google_contact.name) + frappe.local.response["location"] = f"/app/Form/Google%20Contacts/{google_contact.name}" frappe.msgprint(_("Google Contacts has been configured.")) except Exception as e: diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 347488ee44..c472cbc741 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -101,7 +100,7 @@ def authorize_access(reauthorize=None): frappe.db.commit() frappe.local.response["type"] = "redirect" - frappe.local.response["location"] = "/app/Form/{0}".format(quote("Google Drive")) + frappe.local.response["location"] = "/app/Form/{}".format(quote("Google Drive")) frappe.msgprint(_("Google Drive has been configured.")) except Exception as e: @@ -243,7 +242,7 @@ def upload_system_backup_to_google_drive(): media = MediaFileUpload( get_absolute_path(filename=fileurl), mimetype="application/gzip", resumable=True ) - except IOError as e: + except OSError as e: frappe.throw(_("Google Drive - Could not locate - {0}").format(e)) try: @@ -272,7 +271,7 @@ def weekly_backup(): def get_absolute_path(filename): file_path = os.path.join(get_backups_path()[2:], os.path.basename(filename)) - return "{0}/sites/{1}".format(get_bench_path(), file_path) + return f"{get_bench_path()}/sites/{file_path}" def set_progress(progress, message): diff --git a/frappe/integrations/doctype/google_drive/test_google_drive.py b/frappe/integrations/doctype/google_drive/test_google_drive.py index 17f5b152ca..4dcc79afd6 100644 --- a/frappe/integrations/doctype/google_drive/test_google_drive.py +++ b/frappe/integrations/doctype/google_drive/test_google_drive.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/integrations/doctype/google_settings/google_settings.py b/frappe/integrations/doctype/google_settings/google_settings.py index 0d5f9cb00d..c70a4b531f 100644 --- a/frappe/integrations/doctype/google_settings/google_settings.py +++ b/frappe/integrations/doctype/google_settings/google_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/integrations/doctype/google_settings/test_google_settings.py b/frappe/integrations/doctype/google_settings/test_google_settings.py index 53d59b1be0..8d07ffa54f 100644 --- a/frappe/integrations/doctype/google_settings/test_google_settings.py +++ b/frappe/integrations/doctype/google_settings/test_google_settings.py @@ -1,7 +1,5 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2021, Frappe Technologies and Contributors # License: MIT. See LICENSE -from __future__ import unicode_literals import unittest diff --git a/frappe/integrations/doctype/integration_request/integration_request.py b/frappe/integrations/doctype/integration_request/integration_request.py index 4c99613161..334736bc9b 100644 --- a/frappe/integrations/doctype/integration_request/integration_request.py +++ b/frappe/integrations/doctype/integration_request/integration_request.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/integrations/doctype/integration_request/test_integration_request.py b/frappe/integrations/doctype/integration_request/test_integration_request.py index d14af481e8..45963d5096 100644 --- a/frappe/integrations/doctype/integration_request/test_integration_request.py +++ b/frappe/integrations/doctype/integration_request/test_integration_request.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/integrations/doctype/ldap_group_mapping/ldap_group_mapping.py b/frappe/integrations/doctype/ldap_group_mapping/ldap_group_mapping.py index f1b242e4bb..853cfc96a1 100644 --- a/frappe/integrations/doctype/ldap_group_mapping/ldap_group_mapping.py +++ b/frappe/integrations/doctype/ldap_group_mapping/ldap_group_mapping.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/integrations/doctype/ldap_settings/ldap_settings.py b/frappe/integrations/doctype/ldap_settings/ldap_settings.py index 96007ee918..ef6493717f 100644 --- a/frappe/integrations/doctype/ldap_settings/ldap_settings.py +++ b/frappe/integrations/doctype/ldap_settings/ldap_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -137,7 +136,7 @@ class LDAPSettings(Document): def sync_roles(self, user, additional_groups=None): - current_roles = set(d.role for d in user.get("roles")) + current_roles = {d.role for d in user.get("roles")} needed_roles = set() needed_roles.add(self.default_role) @@ -209,14 +208,12 @@ class LDAPSettings(Document): if type(user) is not ldap3.abstract.entry.Entry: raise TypeError( - "Invalid type, attribute {0} must be of type '{1}'".format( - "user", "ldap3.abstract.entry.Entry" - ) + "Invalid type, attribute {} must be of type '{}'".format("user", "ldap3.abstract.entry.Entry") ) if type(conn) is not ldap3.core.connection.Connection: raise TypeError( - "Invalid type, attribute {0} must be of type '{1}'".format("conn", "ldap3.Connection") + "Invalid type, attribute {} must be of type '{}'".format("conn", "ldap3.Connection") ) fetch_ldap_groups = None @@ -254,7 +251,7 @@ class LDAPSettings(Document): if ldap_object_class is not None: conn.search( search_base=self.ldap_search_path_group, - search_filter="(&(objectClass={0})({1}={2}))".format( + search_filter="(&(objectClass={})({}={}))".format( ldap_object_class, ldap_group_members_attribute, user_search_str ), attributes=["cn"], @@ -283,7 +280,7 @@ class LDAPSettings(Document): conn.search( search_base=self.ldap_search_path_user, - search_filter="{0}".format(user_filter), + search_filter=f"{user_filter}", attributes=ldap_attributes, ) @@ -309,7 +306,7 @@ class LDAPSettings(Document): from ldap3 import HASHED_SALTED_SHA, MODIFY_REPLACE from ldap3.utils.hashed import hashed - search_filter = "({0}={1})".format(self.ldap_email_field, user) + search_filter = f"({self.ldap_email_field}={user})" conn = self.connect_to_ldap( self.base_dn, self.get_password(raise_exception=False), read_only=False diff --git a/frappe/integrations/doctype/ldap_settings/test_ldap_settings.py b/frappe/integrations/doctype/ldap_settings/test_ldap_settings.py index 0651932843..f53b5291b3 100644 --- a/frappe/integrations/doctype/ldap_settings/test_ldap_settings.py +++ b/frappe/integrations/doctype/ldap_settings/test_ldap_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE import functools @@ -204,7 +203,7 @@ class LDAP_TestCase: frappe.get_doc(localdoc).save() - self.fail("Document LDAP Settings field [{0}] is not mandatory".format(mandatory_field)) + self.fail(f"Document LDAP Settings field [{mandatory_field}] is not mandatory") except frappe.exceptions.MandatoryError: pass @@ -227,9 +226,7 @@ class LDAP_TestCase: frappe.get_doc(localdoc).save() except frappe.exceptions.MandatoryError: - self.fail( - "Document LDAP Settings field [{0}] should not be mandatory".format(non_mandatory_field) - ) + self.fail(f"Document LDAP Settings field [{non_mandatory_field}] should not be mandatory") @mock_ldap_connection def test_validation_ldap_search_string(self): @@ -252,7 +249,7 @@ class LDAP_TestCase: try: frappe.get_doc(localdoc).save() - self.fail("LDAP search string [{0}] should not validate".format(invalid_search_string)) + self.fail(f"LDAP search string [{invalid_search_string}] should not validate") except frappe.exceptions.ValidationError: pass @@ -298,7 +295,7 @@ class LDAP_TestCase: ): self.fail( - "ldap3.Connection was called with {0}, failed reason: [{1}]".format( + "ldap3.Connection was called with {}, failed reason: [{}]".format( kwargs[connection_arg], prevent_connection_parameters[connection_arg][kwargs[connection_arg]], ) @@ -475,7 +472,7 @@ class LDAP_TestCase: self.assertTrue( len(updated_user_roles) == len(test_user_data[test_user]), - "syncing of the user roles failed. {0} != {1} for user {2}".format( + "syncing of the user roles failed. {} != {} for user {}".format( len(updated_user_roles), len(test_user_data[test_user]), test_user ), ) @@ -484,7 +481,7 @@ class LDAP_TestCase: self.assertTrue( role_to_group_map[user_role] in test_user_data[test_user], - "during sync_roles(), the user was given role {0} which should not have occured".format( + "during sync_roles(), the user was given role {} which should not have occured".format( user_role ), ) @@ -609,7 +606,7 @@ class LDAP_TestCase: self.assertTrue( str(display_massage.exception).lower() == "invalid username or password", - "invalid credentials passed authentication [user: {0}, password: {1}]".format( + "invalid credentials passed authentication [user: {}, password: {}]".format( username, password ), ) diff --git a/frappe/integrations/doctype/oauth_authorization_code/oauth_authorization_code.py b/frappe/integrations/doctype/oauth_authorization_code/oauth_authorization_code.py index 4ef6f65dc7..431d27bc04 100644 --- a/frappe/integrations/doctype/oauth_authorization_code/oauth_authorization_code.py +++ b/frappe/integrations/doctype/oauth_authorization_code/oauth_authorization_code.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/integrations/doctype/oauth_authorization_code/test_oauth_authorization_code.py b/frappe/integrations/doctype/oauth_authorization_code/test_oauth_authorization_code.py index 72cb789ebb..2036a42f15 100644 --- a/frappe/integrations/doctype/oauth_authorization_code/test_oauth_authorization_code.py +++ b/frappe/integrations/doctype/oauth_authorization_code/test_oauth_authorization_code.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/integrations/doctype/oauth_bearer_token/oauth_bearer_token.py b/frappe/integrations/doctype/oauth_bearer_token/oauth_bearer_token.py index 515d3d2ba3..2a17035571 100644 --- a/frappe/integrations/doctype/oauth_bearer_token/oauth_bearer_token.py +++ b/frappe/integrations/doctype/oauth_bearer_token/oauth_bearer_token.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/integrations/doctype/oauth_bearer_token/test_oauth_bearer_token.py b/frappe/integrations/doctype/oauth_bearer_token/test_oauth_bearer_token.py index 9dea8f482a..3439096809 100644 --- a/frappe/integrations/doctype/oauth_bearer_token/test_oauth_bearer_token.py +++ b/frappe/integrations/doctype/oauth_bearer_token/test_oauth_bearer_token.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/integrations/doctype/oauth_client/oauth_client.py b/frappe/integrations/doctype/oauth_client/oauth_client.py index 09f6e3aced..ab40467751 100644 --- a/frappe/integrations/doctype/oauth_client/oauth_client.py +++ b/frappe/integrations/doctype/oauth_client/oauth_client.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/integrations/doctype/oauth_client/test_oauth_client.py b/frappe/integrations/doctype/oauth_client/test_oauth_client.py index dd1b25239a..8fd732673e 100644 --- a/frappe/integrations/doctype/oauth_client/test_oauth_client.py +++ b/frappe/integrations/doctype/oauth_client/test_oauth_client.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/integrations/doctype/oauth_provider_settings/oauth_provider_settings.py b/frappe/integrations/doctype/oauth_provider_settings/oauth_provider_settings.py index 2aefd591a1..984382df9d 100644 --- a/frappe/integrations/doctype/oauth_provider_settings/oauth_provider_settings.py +++ b/frappe/integrations/doctype/oauth_provider_settings/oauth_provider_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/integrations/doctype/oauth_scope/oauth_scope.py b/frappe/integrations/doctype/oauth_scope/oauth_scope.py index a30d087cc0..1db49a3818 100644 --- a/frappe/integrations/doctype/oauth_scope/oauth_scope.py +++ b/frappe/integrations/doctype/oauth_scope/oauth_scope.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/integrations/doctype/paypal_settings/paypal_settings.py b/frappe/integrations/doctype/paypal_settings/paypal_settings.py index 3568b77baf..99c499200b 100644 --- a/frappe/integrations/doctype/paypal_settings/paypal_settings.py +++ b/frappe/integrations/doctype/paypal_settings/paypal_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -193,7 +192,7 @@ class PayPalSettings(Document): params.update( { "METHOD": "SetExpressCheckout", - "returnUrl": get_url("{0}.get_express_checkout_details".format(api_path)), + "returnUrl": get_url(f"{api_path}.get_express_checkout_details"), "cancelUrl": get_url("/payment-cancel"), "PAYMENTREQUEST_0_PAYMENTACTION": "SALE", "PAYMENTREQUEST_0_AMT": kwargs["amount"], @@ -331,7 +330,7 @@ def confirm_payment(token): ).run_method("on_payment_authorized", "Completed") frappe.db.commit() - redirect_url = "/integrations/payment-success?doctype={0}&docname={1}".format( + redirect_url = "/integrations/payment-success?doctype={}&docname={}".format( data.get("reference_doctype"), data.get("reference_docname") ) else: @@ -404,7 +403,7 @@ def create_recurring_profile(token, payerid): ).run_method("on_payment_authorized", status_changed_to) frappe.db.commit() - redirect_url = "/integrations/payment-success?doctype={0}&docname={1}".format( + redirect_url = "/integrations/payment-success?doctype={}&docname={}".format( data.get("reference_doctype"), data.get("reference_docname") ) else: @@ -427,11 +426,9 @@ def get_redirect_uri(doc, token, payerid): data = json.loads(doc.data) if data.get("subscription_details") or data.get("subscription_id"): - return get_url( - "{0}.create_recurring_profile?token={1}&payerid={2}".format(api_path, token, payerid) - ) + return get_url(f"{api_path}.create_recurring_profile?token={token}&payerid={payerid}") else: - return get_url("{0}.confirm_payment?token={1}".format(api_path, token)) + return get_url(f"{api_path}.confirm_payment?token={token}") def manage_recurring_payment_profile_status(profile_id, action, args, url): @@ -474,7 +471,7 @@ def ipn_handler(): queue="long", timeout=600, is_async=True, - **{"doctype": "Integration Request", "docname": doc.name} + **{"doctype": "Integration Request", "docname": doc.name}, ) except frappe.InvalidStatusError: diff --git a/frappe/integrations/doctype/paytm_settings/paytm_settings.py b/frappe/integrations/doctype/paytm_settings/paytm_settings.py index d8c9159303..81a5f45f47 100644 --- a/frappe/integrations/doctype/paytm_settings/paytm_settings.py +++ b/frappe/integrations/doctype/paytm_settings/paytm_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -37,7 +36,7 @@ class PaytmSettings(Document): integration_request = create_request_log(kwargs, service_name="Paytm") kwargs.update(dict(order_id=integration_request.name)) - return get_url("./integrations/paytm_checkout?{0}".format(urlencode(kwargs))) + return get_url(f"./integrations/paytm_checkout?{urlencode(kwargs)}") def get_paytm_config(): diff --git a/frappe/integrations/doctype/paytm_settings/test_paytm_settings.py b/frappe/integrations/doctype/paytm_settings/test_paytm_settings.py index d9e72e344c..91b69d5aec 100644 --- a/frappe/integrations/doctype/paytm_settings/test_paytm_settings.py +++ b/frappe/integrations/doctype/paytm_settings/test_paytm_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/integrations/doctype/query_parameters/query_parameters.py b/frappe/integrations/doctype/query_parameters/query_parameters.py index 09f039a764..b501c0c3e8 100644 --- a/frappe/integrations/doctype/query_parameters/query_parameters.py +++ b/frappe/integrations/doctype/query_parameters/query_parameters.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py b/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py index b13319803f..a79e626b49 100644 --- a/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py +++ b/frappe/integrations/doctype/razorpay_settings/razorpay_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -124,9 +123,7 @@ class RazorpaySettings(Document): "quantity": 1 (The total amount is calculated as item.amount * quantity) } """ - url = "https://api.razorpay.com/v1/subscriptions/{0}/addons".format( - kwargs.get("subscription_id") - ) + url = "https://api.razorpay.com/v1/subscriptions/{}/addons".format(kwargs.get("subscription_id")) try: if not frappe.conf.converted_rupee_to_paisa: @@ -195,7 +192,7 @@ class RazorpaySettings(Document): def get_payment_url(self, **kwargs): integration_request = create_request_log(kwargs, service_name="Razorpay") - return get_url("./integrations/razorpay_checkout?token={0}".format(integration_request.name)) + return get_url(f"./integrations/razorpay_checkout?token={integration_request.name}") def create_order(self, **kwargs): # Creating Orders https://razorpay.com/docs/api/orders/ @@ -257,7 +254,7 @@ class RazorpaySettings(Document): try: resp = make_get_request( - "https://api.razorpay.com/v1/payments/{0}".format(self.data.razorpay_payment_id), + f"https://api.razorpay.com/v1/payments/{self.data.razorpay_payment_id}", auth=(settings.api_key, settings.api_secret), ) @@ -303,7 +300,7 @@ class RazorpaySettings(Document): if custom_redirect_to: redirect_to = custom_redirect_to - redirect_url = "payment-success?doctype={0}&docname={1}".format( + redirect_url = "payment-success?doctype={}&docname={}".format( self.data.reference_doctype, self.data.reference_docname ) else: @@ -339,7 +336,7 @@ class RazorpaySettings(Document): try: resp = make_post_request( - "https://api.razorpay.com/v1/subscriptions/{0}/cancel".format(subscription_id), + f"https://api.razorpay.com/v1/subscriptions/{subscription_id}/cancel", auth=(settings.api_key, settings.api_secret), ) except Exception: @@ -383,14 +380,14 @@ def capture_payment(is_sandbox=False, sanbox_response=None): settings = controller.get_settings(data) resp = make_get_request( - "https://api.razorpay.com/v1/payments/{0}".format(data.get("razorpay_payment_id")), + "https://api.razorpay.com/v1/payments/{}".format(data.get("razorpay_payment_id")), auth=(settings.api_key, settings.api_secret), data={"amount": data.get("amount")}, ) if resp.get("status") == "authorized": resp = make_post_request( - "https://api.razorpay.com/v1/payments/{0}/capture".format(data.get("razorpay_payment_id")), + "https://api.razorpay.com/v1/payments/{}/capture".format(data.get("razorpay_payment_id")), auth=(settings.api_key, settings.api_secret), data={"amount": data.get("amount")}, ) @@ -403,7 +400,7 @@ def capture_payment(is_sandbox=False, sanbox_response=None): doc.status = "Failed" doc.error = frappe.get_traceback() doc.save() - frappe.log_error(doc.error, "{0} Failed".format(doc.name)) + frappe.log_error(doc.error, f"{doc.name} Failed") @frappe.whitelist(allow_guest=True) @@ -498,7 +495,7 @@ def razorpay_subscription_callback(): queue="long", timeout=600, is_async=True, - **{"doctype": "Integration Request", "docname": doc.name} + **{"doctype": "Integration Request", "docname": doc.name}, ) except frappe.InvalidStatusError: @@ -521,7 +518,7 @@ def validate_payment_callback(data): settings = controller.get_settings(data) resp = make_get_request( - "https://api.razorpay.com/v1/subscriptions/{0}".format(subscription_id), + f"https://api.razorpay.com/v1/subscriptions/{subscription_id}", auth=(settings.api_key, settings.api_secret), ) diff --git a/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py b/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py index 015d4f0467..1c2d39be10 100755 --- a/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py +++ b/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors # License: MIT. See LICENSE import os diff --git a/frappe/integrations/doctype/s3_backup_settings/test_s3_backup_settings.py b/frappe/integrations/doctype/s3_backup_settings/test_s3_backup_settings.py index c6dbee2c20..48b1ccd113 100755 --- a/frappe/integrations/doctype/s3_backup_settings/test_s3_backup_settings.py +++ b/frappe/integrations/doctype/s3_backup_settings/test_s3_backup_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/integrations/doctype/slack_webhook_url/slack_webhook_url.py b/frappe/integrations/doctype/slack_webhook_url/slack_webhook_url.py index cf6a23fb34..d71d7075a6 100644 --- a/frappe/integrations/doctype/slack_webhook_url/slack_webhook_url.py +++ b/frappe/integrations/doctype/slack_webhook_url/slack_webhook_url.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/integrations/doctype/slack_webhook_url/test_slack_webhook_url.py b/frappe/integrations/doctype/slack_webhook_url/test_slack_webhook_url.py index 4bd71033bb..16b1bcd3c2 100644 --- a/frappe/integrations/doctype/slack_webhook_url/test_slack_webhook_url.py +++ b/frappe/integrations/doctype/slack_webhook_url/test_slack_webhook_url.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/integrations/doctype/social_login_key/social_login_key.py b/frappe/integrations/doctype/social_login_key/social_login_key.py index 8c19767107..e38f19bb2b 100644 --- a/frappe/integrations/doctype/social_login_key/social_login_key.py +++ b/frappe/integrations/doctype/social_login_key/social_login_key.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -69,7 +68,7 @@ class SocialLoginKey(Document): if self.provider_name in icon_map: icon_file = icon_map[self.provider_name] - self.icon = "/assets/frappe/icons/social/{0}".format(icon_file) + self.icon = f"/assets/frappe/icons/social/{icon_file}" @frappe.whitelist() def get_social_login_provider(self, provider, initialize=False): diff --git a/frappe/integrations/doctype/social_login_key/test_social_login_key.py b/frappe/integrations/doctype/social_login_key/test_social_login_key.py index be4c1f7c49..c51ccb2c0f 100644 --- a/frappe/integrations/doctype/social_login_key/test_social_login_key.py +++ b/frappe/integrations/doctype/social_login_key/test_social_login_key.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/integrations/doctype/stripe_settings/stripe_settings.py b/frappe/integrations/doctype/stripe_settings/stripe_settings.py index bc8b0dfa17..8e1d383790 100644 --- a/frappe/integrations/doctype/stripe_settings/stripe_settings.py +++ b/frappe/integrations/doctype/stripe_settings/stripe_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -163,7 +162,7 @@ class StripeSettings(Document): def validate_stripe_credentails(self): if self.publishable_key and self.secret_key: header = { - "Authorization": "Bearer {0}".format( + "Authorization": "Bearer {}".format( self.get_password(fieldname="secret_key", raise_exception=False) ) } @@ -190,7 +189,7 @@ class StripeSettings(Document): ) def get_payment_url(self, **kwargs): - return get_url("./integrations/stripe_checkout?{0}".format(urlencode(kwargs))) + return get_url(f"./integrations/stripe_checkout?{urlencode(kwargs)}") def create_request(self, data): import stripe diff --git a/frappe/integrations/doctype/stripe_settings/test_stripe_settings.py b/frappe/integrations/doctype/stripe_settings/test_stripe_settings.py index e13359fa6d..eed87bfcaf 100644 --- a/frappe/integrations/doctype/stripe_settings/test_stripe_settings.py +++ b/frappe/integrations/doctype/stripe_settings/test_stripe_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/integrations/doctype/token_cache/test_token_cache.py b/frappe/integrations/doctype/token_cache/test_token_cache.py index 6a3b16e72c..a9366d84d3 100644 --- a/frappe/integrations/doctype/token_cache/test_token_cache.py +++ b/frappe/integrations/doctype/token_cache/test_token_cache.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/integrations/doctype/token_cache/token_cache.py b/frappe/integrations/doctype/token_cache/token_cache.py index 7d961fe1cc..25f07a16ba 100644 --- a/frappe/integrations/doctype/token_cache/token_cache.py +++ b/frappe/integrations/doctype/token_cache/token_cache.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/integrations/doctype/webhook/__init__.py b/frappe/integrations/doctype/webhook/__init__.py index 915d2819ee..8e9c72c1a9 100644 --- a/frappe/integrations/doctype/webhook/__init__.py +++ b/frappe/integrations/doctype/webhook/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/integrations/doctype/webhook/test_webhook.py b/frappe/integrations/doctype/webhook/test_webhook.py index 5386a75573..5ac75f5b52 100644 --- a/frappe/integrations/doctype/webhook/test_webhook.py +++ b/frappe/integrations/doctype/webhook/test_webhook.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/integrations/doctype/webhook/webhook.py b/frappe/integrations/doctype/webhook/webhook.py index 22abcf9a99..27fdd662ed 100644 --- a/frappe/integrations/doctype/webhook/webhook.py +++ b/frappe/integrations/doctype/webhook/webhook.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -8,7 +7,6 @@ import hashlib import hmac import json from time import sleep -from typing import Dict, Optional from urllib.parse import urlparse import requests @@ -114,7 +112,7 @@ def enqueue_webhook(doc, webhook) -> None: webhook.log_error("Webhook failed") -def log_request(url: str, headers: Dict, data: Dict, res: Optional[requests.Response] = None): +def log_request(url: str, headers: dict, data: dict, res: requests.Response | None = None): request_log = frappe.get_doc( { "doctype": "Webhook Request Log", diff --git a/frappe/integrations/doctype/webhook_data/webhook_data.py b/frappe/integrations/doctype/webhook_data/webhook_data.py index 1bb0d901df..39016cb864 100644 --- a/frappe/integrations/doctype/webhook_data/webhook_data.py +++ b/frappe/integrations/doctype/webhook_data/webhook_data.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/integrations/doctype/webhook_header/webhook_header.py b/frappe/integrations/doctype/webhook_header/webhook_header.py index 9478d227e4..f5f85d1afe 100644 --- a/frappe/integrations/doctype/webhook_header/webhook_header.py +++ b/frappe/integrations/doctype/webhook_header/webhook_header.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/integrations/frappe_providers/__init__.py b/frappe/integrations/frappe_providers/__init__.py index 161937a936..630c2c08b4 100644 --- a/frappe/integrations/frappe_providers/__init__.py +++ b/frappe/integrations/frappe_providers/__init__.py @@ -9,5 +9,5 @@ def migrate_to(local_site, frappe_provider): if frappe_provider in ("frappe.cloud", "frappecloud.com"): return frappecloud_migrator(local_site) else: - print("{} is not supported yet".format(frappe_provider)) + print(f"{frappe_provider} is not supported yet") sys.exit(1) diff --git a/frappe/integrations/frappe_providers/frappecloud.py b/frappe/integrations/frappe_providers/frappecloud.py index 0a01989d5e..64aa847a0e 100644 --- a/frappe/integrations/frappe_providers/frappecloud.py +++ b/frappe/integrations/frappe_providers/frappecloud.py @@ -8,7 +8,7 @@ import frappe def frappecloud_migrator(local_site): print("Retrieving Site Migrator...") remote_site = frappe.conf.frappecloud_url or "frappecloud.com" - request_url = "https://{}/api/method/press.api.script".format(remote_site) + request_url = f"https://{remote_site}/api/method/press.api.script" request = requests.get(request_url) if request.status_code / 100 != 2: @@ -32,5 +32,5 @@ def frappecloud_migrator(local_site): py = sys.executable script = tempfile.NamedTemporaryFile(mode="w") script.write(script_contents) - print("Site Migrator stored at {}".format(script.name)) + print(f"Site Migrator stored at {script.name}") os.execv(py, [py, script.name, local_site]) diff --git a/frappe/integrations/offsite_backup_utils.py b/frappe/integrations/offsite_backup_utils.py index 307f1525fe..620f692ad0 100644 --- a/frappe/integrations/offsite_backup_utils.py +++ b/frappe/integrations/offsite_backup_utils.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -13,8 +12,8 @@ def send_email(success, service_name, doctype, email_field, error_status=None): recipients = get_recipients(doctype, email_field) if not recipients: frappe.log_error( - "No Email Recipient found for {0}".format(service_name), - "{0}: Failed to send backup status email".format(service_name), + f"No Email Recipient found for {service_name}", + f"{service_name}: Failed to send backup status email", ) return @@ -25,15 +24,15 @@ def send_email(success, service_name, doctype, email_field, error_status=None): subject = "Backup Upload Successful" message = """

    Backup Uploaded Successfully!

    -

    Hi there, this is just to inform you that your backup was successfully uploaded to your {0} bucket. So relax!

    """.format( +

    Hi there, this is just to inform you that your backup was successfully uploaded to your {} bucket. So relax!

    """.format( service_name ) else: subject = "[Warning] Backup Upload Failed" message = """

    Backup Upload Failed!

    -

    Oops, your automated backup to {0} failed.

    -

    Error message: {1}

    +

    Oops, your automated backup to {} failed.

    +

    Error message: {}

    Please contact your system manager for more information.

    """.format( service_name, error_status ) diff --git a/frappe/integrations/utils.py b/frappe/integrations/utils.py index 1440c80399..f215a73dc6 100644 --- a/frappe/integrations/utils.py +++ b/frappe/integrations/utils.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -50,7 +49,7 @@ def create_request_log( error=None, request_headers=None, output=None, - **kwargs + **kwargs, ): """ DEPRECATED: The parameter integration_type will be removed in the next major release. @@ -102,7 +101,7 @@ def get_payment_gateway_controller(payment_gateway): gateway = frappe.get_doc("Payment Gateway", payment_gateway) if gateway.gateway_controller is None: try: - return frappe.get_doc("{0} Settings".format(payment_gateway)) + return frappe.get_doc(f"{payment_gateway} Settings") except Exception: frappe.throw(_("{0} Settings not found").format(payment_gateway)) else: @@ -116,7 +115,7 @@ def get_payment_gateway_controller(payment_gateway): def get_checkout_url(**kwargs): try: if kwargs.get("payment_gateway"): - doc = frappe.get_doc("{0} Settings".format(kwargs.get("payment_gateway"))) + doc = frappe.get_doc("{} Settings".format(kwargs.get("payment_gateway"))) return doc.get_payment_url(**kwargs) else: raise Exception diff --git a/frappe/middlewares.py b/frappe/middlewares.py index cd47b7210f..168d129ebe 100644 --- a/frappe/middlewares.py +++ b/frappe/middlewares.py @@ -13,7 +13,7 @@ from frappe.utils import cstr, get_site_name class StaticDataMiddleware(SharedDataMiddleware): def __call__(self, environ, start_response): self.environ = environ - return super(StaticDataMiddleware, self).__call__(environ, start_response) + return super().__call__(environ, start_response) def get_directory_loader(self, directory): def loader(path): diff --git a/frappe/model/base_document.py b/frappe/model/base_document.py index 8e417bb45c..d3e7656d6d 100644 --- a/frappe/model/base_document.py +++ b/frappe/model/base_document.py @@ -2,7 +2,6 @@ # License: MIT. See LICENSE import datetime import json -from typing import Dict, List import frappe from frappe import _, _dict @@ -59,9 +58,7 @@ def get_controller(doctype): module_path, classname = import_path.rsplit(".", 1) module = frappe.get_module(module_path) if not hasattr(module, classname): - raise ImportError( - "{0}: {1} does not exist in module {2}".format(doctype, classname, module_path) - ) + raise ImportError(f"{doctype}: {classname} does not exist in module {module_path}") else: module = load_doctype_module(doctype, module_name) classname = doctype.replace(" ", "").replace("-", "") @@ -86,7 +83,7 @@ def get_controller(doctype): return site_controllers[doctype] -class BaseDocument(object): +class BaseDocument: _reserved_keywords = { "doctype", "meta", @@ -300,7 +297,7 @@ class BaseDocument(object): def get_valid_dict( self, sanitize=True, convert_dates_to_str=False, ignore_nulls=False, ignore_virtual=False - ) -> Dict: + ) -> dict: d = _dict() for fieldname in self.meta.get_valid_columns(): # column is valid, we can use getattr @@ -382,7 +379,7 @@ class BaseDocument(object): if key not in self.__dict__: self.__dict__[key] = None - def get_valid_columns(self) -> List[str]: + def get_valid_columns(self) -> list[str]: if self.doctype not in frappe.local.valid_columns: if self.doctype in DOCTYPES_FOR_DOCTYPE: from frappe.model.meta import get_table_columns @@ -412,7 +409,7 @@ class BaseDocument(object): no_default_fields=False, convert_dates_to_str=False, no_child_table_fields=False, - ) -> Dict: + ) -> dict: doc = self.get_valid_dict(convert_dates_to_str=convert_dates_to_str, ignore_nulls=no_nulls) doc["doctype"] = self.doctype @@ -694,7 +691,7 @@ class BaseDocument(object): if self.get("parentfield"): return "{} #{}: {}: {}".format(_("Row"), self.idx, _(df.label), docname) - return "{}: {}".format(_(df.label), docname) + return f"{_(df.label)}: {docname}" invalid_links = [] cancelled_links = [] @@ -928,7 +925,7 @@ class BaseDocument(object): if self.get("parentfield"): reference = _("{0}, Row {1}").format(_(self.doctype), self.idx) else: - reference = "{0} {1}".format(_(self.doctype), self.name) + reference = f"{_(self.doctype)} {self.name}" frappe.throw( _("{0}: '{1}' ({3}) will get truncated, as max characters allowed is {2}").format( diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 7fb38848e2..9cf831a8b9 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -6,7 +6,6 @@ import copy import json import re from datetime import datetime -from typing import List import frappe import frappe.defaults @@ -52,7 +51,7 @@ STRICT_UNION_PATTERN = re.compile(r".*\s(union).*\s") ORDER_GROUP_PATTERN = re.compile(r".*[^a-z0-9-_ ,`'\"\.\(\)].*") -class DatabaseQuery(object): +class DatabaseQuery: def __init__(self, doctype, user=None): self.doctype = doctype self.tables = [] @@ -98,7 +97,7 @@ class DatabaseQuery(object): pluck=None, ignore_ddl=False, parent_doctype=None, - ) -> List: + ) -> list: if ( not ignore_permissions @@ -926,7 +925,7 @@ class DatabaseQuery(object): def add_limit(self): if self.limit_page_length: - return "limit %s offset %s" % (self.limit_page_length, self.limit_start) + return f"limit {self.limit_page_length} offset {self.limit_start}" else: return "" @@ -1070,12 +1069,12 @@ def get_between_date_filter(value, df=None): to_date = add_to_date(to_date, days=1) if df and df.fieldtype == "Datetime": - data = "'%s' AND '%s'" % ( + data = "'{}' AND '{}'".format( frappe.db.format_datetime(from_date), frappe.db.format_datetime(to_date), ) else: - data = "'%s' AND '%s'" % (frappe.db.format_date(from_date), frappe.db.format_date(to_date)) + data = f"'{frappe.db.format_date(from_date)}' AND '{frappe.db.format_date(to_date)}'" return data diff --git a/frappe/model/delete_doc.py b/frappe/model/delete_doc.py index 606d3f89f1..b555dfc5dc 100644 --- a/frappe/model/delete_doc.py +++ b/frappe/model/delete_doc.py @@ -3,7 +3,6 @@ import os import shutil -from typing import List import frappe import frappe.defaults @@ -189,7 +188,7 @@ def update_naming_series(doc): revert_series_if_last(doc.meta.autoname, doc.name, doc) -def delete_from_table(doctype: str, name: str, ignore_doctypes: List[str], doc): +def delete_from_table(doctype: str, name: str, ignore_doctypes: list[str], doc): if doctype != "DocType" and doctype == name: frappe.db.delete("Singles", {"doctype": name}) else: @@ -339,7 +338,7 @@ def check_if_doc_is_dynamically_linked(doc, method="Delete"): reference_doctype = refdoc.parenttype if meta.istable else df.parent reference_docname = refdoc.parent if meta.istable else refdoc.name - at_position = "at Row: {0}".format(refdoc.idx) if meta.istable else "" + at_position = f"at Row: {refdoc.idx}" if meta.istable else "" raise_link_exists_exception(doc, reference_doctype, reference_docname, at_position) @@ -432,7 +431,7 @@ def insert_feed(doc): "doctype": "Comment", "comment_type": "Deleted", "reference_doctype": doc.doctype, - "subject": "{0} {1}".format(_(doc.doctype), doc.name), + "subject": f"{_(doc.doctype)} {doc.name}", "full_name": get_fullname(doc.owner), } ).insert(ignore_permissions=True) diff --git a/frappe/model/docfield.py b/frappe/model/docfield.py index 195385a2e1..c54a3855cb 100644 --- a/frappe/model/docfield.py +++ b/frappe/model/docfield.py @@ -45,7 +45,7 @@ def update_parent_field(f, new): if f["fieldtype"] in frappe.model.table_fields: frappe.db.begin() frappe.db.sql( - """update `tab%s` set parentfield=%s where parentfield=%s""" % (f["options"], "%s", "%s"), + """update `tab{}` set parentfield={} where parentfield={}""".format(f["options"], "%s", "%s"), (new, f["fieldname"]), ) frappe.db.commit() @@ -56,7 +56,7 @@ def get_change_column_query(f, new): desc = frappe.db.sql("desc `tab%s`" % f["parent"]) for d in desc: if d[0] == f["fieldname"]: - return "alter table `tab%s` change `%s` `%s` %s" % (f["parent"], f["fieldname"], new, d[1]) + return "alter table `tab{}` change `{}` `{}` {}".format(f["parent"], f["fieldname"], new, d[1]) def supports_translation(fieldtype): diff --git a/frappe/model/document.py b/frappe/model/document.py index 898c40861c..9b781b1999 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -3,7 +3,6 @@ import hashlib import json import time -from typing import List from werkzeug.exceptions import NotFound @@ -112,7 +111,7 @@ class Document(BaseDocument): if kwargs: # init base document - super(Document, self).__init__(kwargs) + super().__init__(kwargs) self.init_child_tables() self.init_valid_columns() @@ -136,7 +135,7 @@ class Document(BaseDocument): single_doc["name"] = self.doctype del single_doc["__islocal"] - super(Document, self).__init__(single_doc) + super().__init__(single_doc) self.init_valid_columns() self._fix_numeric_types() @@ -149,7 +148,7 @@ class Document(BaseDocument): _("{0} {1} not found").format(_(self.doctype), self.name), frappe.DoesNotExistError ) - super(Document, self).__init__(d) + super().__init__(d) for df in self._get_table_fields(): # Make sure not to query the DB for a child table, if it is a virtual one. @@ -401,9 +400,9 @@ class Document(BaseDocument): if rows: # select rows that do not match the ones in the document deleted_rows = frappe.db.sql( - """select name from `tab{0}` where parent=%s + """select name from `tab{}` where parent=%s and parenttype=%s and parentfield=%s - and name not in ({1})""".format( + and name not in ({})""".format( df.options, ",".join(["%s"] * len(rows)) ), [self.name, self.doctype, fieldname] + rows, @@ -756,7 +755,7 @@ class Document(BaseDocument): conflict = True else: tmp = frappe.db.sql( - """select modified, docstatus from `tab{0}` + """select modified, docstatus from `tab{}` where name = %s for update""".format( self.doctype ), @@ -779,7 +778,7 @@ class Document(BaseDocument): if conflict: frappe.msgprint( _("Error: Document has been modified after you have opened it") - + (" (%s, %s). " % (modified, self.modified)) + + (f" ({modified}, {self.modified}). ") + _("Please refresh to get the latest document."), raise_exception=frappe.TimestampMismatchError, ) @@ -874,7 +873,7 @@ class Document(BaseDocument): raise frappe.MandatoryError( "[{doctype}, {name}]: {fields}".format( - fields=", ".join((each[0] for each in missing)), doctype=self.doctype, name=self.name + fields=", ".join(each[0] for each in missing), doctype=self.doctype, name=self.name ) ) @@ -890,14 +889,14 @@ class Document(BaseDocument): cancelled_links.extend(result[1]) if invalid_links: - msg = ", ".join((each[2] for each in invalid_links)) + msg = ", ".join(each[2] for each in invalid_links) frappe.throw(_("Could not find {0}").format(msg), frappe.LinkValidationError) if cancelled_links: - msg = ", ".join((each[2] for each in cancelled_links)) + msg = ", ".join(each[2] for each in cancelled_links) frappe.throw(_("Cannot link cancelled document: {0}").format(msg), frappe.CancelledLinkError) - def get_all_children(self, parenttype=None) -> List["Document"]: + def get_all_children(self, parenttype=None) -> list["Document"]: """Returns all children documents from **Table** type fields in a list.""" children = [] @@ -1268,7 +1267,7 @@ class Document(BaseDocument): def is_whitelisted(self, method_name): method = getattr(self, method_name, None) if not method: - raise NotFound("Method {0} not found".format(method_name)) + raise NotFound(f"Method {method_name} not found") is_whitelisted(getattr(method, "__func__", method)) diff --git a/frappe/model/mapper.py b/frappe/model/mapper.py index 59f211e322..9df79ef276 100644 --- a/frappe/model/mapper.py +++ b/frappe/model/mapper.py @@ -231,7 +231,7 @@ def map_fetch_fields(target_doc, df, no_copy_fields): linked_doc = None # options should be like "link_fieldname.fieldname_in_liked_doc" - for fetch_df in target_doc.meta.get("fields", {"fetch_from": "^{0}.".format(df.fieldname)}): + for fetch_df in target_doc.meta.get("fields", {"fetch_from": f"^{df.fieldname}."}): if not (fetch_df.fieldtype == "Read Only" or fetch_df.read_only): continue diff --git a/frappe/model/meta.py b/frappe/model/meta.py index 9f5c2e7611..74b8be953b 100644 --- a/frappe/model/meta.py +++ b/frappe/model/meta.py @@ -17,7 +17,6 @@ Example: import json import os from datetime import datetime -from typing import List import click @@ -68,7 +67,7 @@ def get_table_columns(doctype): def load_doctype_from_file(doctype): fname = frappe.scrub(doctype) - with open(frappe.get_app_path("frappe", "core", "doctype", fname, fname + ".json"), "r") as f: + with open(frappe.get_app_path("frappe", "core", "doctype", fname, fname + ".json")) as f: txt = json.loads(f.read()) for d in txt.get("fields", []): @@ -104,19 +103,19 @@ class Meta(Document): def __init__(self, doctype): self._fields = {} if isinstance(doctype, dict): - super(Meta, self).__init__(doctype) + super().__init__(doctype) elif isinstance(doctype, Document): - super(Meta, self).__init__(doctype.as_dict()) + super().__init__(doctype.as_dict()) self.process() else: - super(Meta, self).__init__("DocType", doctype) + super().__init__("DocType", doctype) self.process() def load_from_db(self): try: - super(Meta, self).load_from_db() + super().load_from_db() except frappe.DoesNotExistError: if self.doctype == "DocType" and self.name in self.special_doctypes: self.__dict__.update(load_doctype_from_file(self.name)) @@ -347,7 +346,7 @@ class Meta(Document): def get_workflow(self): return get_workflow_name(self.name) - def get_naming_series_options(self) -> List[str]: + def get_naming_series_options(self) -> list[str]: """Get list naming series options.""" field = self.get_field("naming_series") @@ -434,7 +433,7 @@ class Meta(Document): # set the fields in order if specified # order is saved as `links_order` - order = json.loads(self.get("{}_order".format(fieldname)) or "[]") + order = json.loads(self.get(f"{fieldname}_order") or "[]") if order: name_map = {d.name: d for d in self.get(fieldname)} new_list = [] diff --git a/frappe/model/naming.py b/frappe/model/naming.py index b674b0cd81..bae40c68c1 100644 --- a/frappe/model/naming.py +++ b/frappe/model/naming.py @@ -2,7 +2,7 @@ # License: MIT. See LICENSE import re -from typing import TYPE_CHECKING, Callable, List, Optional, Union +from typing import TYPE_CHECKING, Callable, Optional import frappe from frappe import _ @@ -81,7 +81,7 @@ class NamingSeries: return prefix - def get_preview(self, doc=None) -> List[str]: + def get_preview(self, doc=None) -> list[str]: """Generate preview of naming series without using DB counters""" generated_names = [] for count in range(1, 4): @@ -271,10 +271,10 @@ def make_autoname(key="", doctype="", doc=""): def parse_naming_series( - parts: Union[List[str], str], + parts: list[str] | str, doctype=None, doc: Optional["Document"] = None, - number_generator: Optional[Callable[[str, int], str]] = None, + number_generator: Callable[[str, int], str] | None = None, ) -> str: """Parse the naming series and get next name. @@ -410,7 +410,7 @@ def revert_series_if_last(key, name, doc=None): frappe.db.sql("UPDATE `tabSeries` SET `current` = `current` - 1 WHERE `name`=%s", prefix) -def get_default_naming_series(doctype: str) -> Optional[str]: +def get_default_naming_series(doctype: str) -> str | None: """get default value for `naming_series` property""" naming_series_options = frappe.get_meta(doctype).get_naming_series_options() @@ -421,7 +421,7 @@ def get_default_naming_series(doctype: str) -> Optional[str]: return option -def validate_name(doctype: str, name: Union[int, str], case: Optional[str] = None): +def validate_name(doctype: str, name: int | str, case: str | None = None): if not name: frappe.throw(_("No Name Specified for {0}").format(doctype)) @@ -450,7 +450,7 @@ def validate_name(doctype: str, name: Union[int, str], case: Optional[str] = Non special_characters = "<>" if re.findall(f"[{special_characters}]+", name): - message = ", ".join("'{0}'".format(c) for c in special_characters) + message = ", ".join(f"'{c}'" for c in special_characters) frappe.throw( _("Name cannot contain special characters like {0}").format(message), frappe.NameError ) @@ -464,7 +464,7 @@ def append_number_if_name_exists(doctype, value, fieldname="name", separator="-" filters.update({fieldname: value}) exists = frappe.db.exists(doctype, filters) - regex = "^{value}{separator}\\d+$".format(value=re.escape(value), separator=separator) + regex = f"^{re.escape(value)}{separator}\\d+$" if exists: last = frappe.db.sql( @@ -482,7 +482,7 @@ def append_number_if_name_exists(doctype, value, fieldname="name", separator="-" else: count = "1" - value = "{0}{1}{2}".format(value, separator, count) + value = f"{value}{separator}{count}" return value diff --git a/frappe/model/rename_doc.py b/frappe/model/rename_doc.py index 25e471d4b0..b05df57364 100644 --- a/frappe/model/rename_doc.py +++ b/frappe/model/rename_doc.py @@ -1,6 +1,6 @@ # Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE -from typing import TYPE_CHECKING, Dict, List, Optional +from typing import TYPE_CHECKING import frappe from frappe import _, bold @@ -22,8 +22,8 @@ def update_document_title( *, doctype: str, docname: str, - title: Optional[str] = None, - name: Optional[str] = None, + title: str | None = None, + name: str | None = None, merge: bool = False, enqueue: bool = False, **kwargs, @@ -106,8 +106,8 @@ def update_document_title( def rename_doc( - doctype: Optional[str] = None, - old: Optional[str] = None, + doctype: str | None = None, + old: str | None = None, new: str = None, force: bool = False, merge: bool = False, @@ -115,7 +115,7 @@ def rename_doc( ignore_if_exists: bool = False, show_alert: bool = True, rebuild_search: bool = True, - doc: Optional[Document] = None, + doc: Document | None = None, validate: bool = True, ) -> str: """Rename a doc(dt, old) to doc(dt, new) and update all linked fields of type "Link". @@ -253,7 +253,7 @@ def update_assignments(old: str, new: str, doctype: str) -> None: frappe.db.set_value(doctype, new, "_assign", frappe.as_json(unique_assignments, indent=0)) -def update_user_settings(old: str, new: str, link_fields: List[Dict]) -> None: +def update_user_settings(old: str, new: str, link_fields: list[dict]) -> None: """ Update the user settings of all the linked doctypes while renaming. """ @@ -412,7 +412,7 @@ def update_child_docs(old: str, new: str, meta: "Meta") -> None: frappe.qb.update(df.options).set("parent", new).where(Field("parent") == old).run() -def update_link_field_values(link_fields: List[Dict], old: str, new: str, doctype: str) -> None: +def update_link_field_values(link_fields: list[dict], old: str, new: str, doctype: str) -> None: for field in link_fields: if field["issingle"]: try: @@ -448,7 +448,7 @@ def update_link_field_values(link_fields: List[Dict], old: str, new: str, doctyp field["parent"] = new -def get_link_fields(doctype: str) -> List[Dict]: +def get_link_fields(doctype: str) -> list[dict]: # get link fields from tabDocField if not frappe.flags.link_fields: frappe.flags.link_fields = {} @@ -519,7 +519,7 @@ def update_options_for_fieldtype(fieldtype: str, old: str, new: str) -> None: ).run() -def get_select_fields(old: str, new: str) -> List[Dict]: +def get_select_fields(old: str, new: str) -> list[dict]: """ get select type fields where doctype's name is hardcoded as new line separated list @@ -646,8 +646,8 @@ def rename_dynamic_links(doctype: str, old: str, new: str): def bulk_rename( - doctype: str, rows: Optional[List[List]] = None, via_console: bool = False -) -> Optional[List[str]]: + doctype: str, rows: list[list] | None = None, via_console: bool = False +) -> list[str] | None: """Bulk rename documents :param doctype: DocType to be renamed @@ -688,7 +688,7 @@ def bulk_rename( def update_linked_doctypes( - doctype: str, docname: str, linked_to: str, value: str, ignore_doctypes: Optional[List] = None + doctype: str, docname: str, linked_to: str, value: str, ignore_doctypes: list | None = None ) -> None: from frappe.model.utils.rename_doc import update_linked_doctypes @@ -704,8 +704,8 @@ def update_linked_doctypes( def get_fetch_fields( - doctype: str, linked_to: str, ignore_doctypes: Optional[List] = None -) -> List[Dict]: + doctype: str, linked_to: str, ignore_doctypes: list | None = None +) -> list[dict]: from frappe.model.utils.rename_doc import get_fetch_fields show_deprecation_warning("get_fetch_fields") diff --git a/frappe/model/sync.py b/frappe/model/sync.py index 93b883cda6..df3999054a 100644 --- a/frappe/model/sync.py +++ b/frappe/model/sync.py @@ -84,7 +84,7 @@ def sync_for(app_name, force=0, reset_permissions=False): frappe.db.commit() # show progress bar - update_progress_bar("Updating DocTypes for {0}".format(app_name), i, l) + update_progress_bar(f"Updating DocTypes for {app_name}", i, l) # print each progress bar on new line print() diff --git a/frappe/model/utils/__init__.py b/frappe/model/utils/__init__.py index 6385b61c38..351b19c8eb 100644 --- a/frappe/model/utils/__init__.py +++ b/frappe/model/utils/__init__.py @@ -47,7 +47,7 @@ def set_field_property(filters, key, value): for d in docs: d.get("fields", filters)[0].set(key, value) d.save() - print("Updated {0}".format(d.name)) + print(f"Updated {d.name}") frappe.db.commit() @@ -70,7 +70,7 @@ def render_include(content): for path in paths: app, app_path = path.split("/", 1) - with io.open(frappe.get_app_path(app, app_path), "r", encoding="utf-8") as f: + with open(frappe.get_app_path(app, app_path), encoding="utf-8") as f: include = f.read() if path.endswith(".html"): include = html_to_js_template(path, include) diff --git a/frappe/model/utils/link_count.py b/frappe/model/utils/link_count.py index 25dfe58139..9a7694b9f8 100644 --- a/frappe/model/utils/link_count.py +++ b/frappe/model/utils/link_count.py @@ -42,7 +42,7 @@ def update_link_count(): if key[0] not in ignore_doctypes: try: frappe.db.sql( - "update `tab{0}` set idx = idx + {1} where name=%s".format(key[0], count), + f"update `tab{key[0]}` set idx = idx + {count} where name=%s", key[1], auto_commit=1, ) diff --git a/frappe/model/utils/rename_doc.py b/frappe/model/utils/rename_doc.py index 00e2d78d5f..ae6649f057 100644 --- a/frappe/model/utils/rename_doc.py +++ b/frappe/model/utils/rename_doc.py @@ -2,14 +2,13 @@ # License: MIT. See LICENSE from itertools import product -from typing import Dict, List, Optional import frappe from frappe.model.rename_doc import get_link_fields def update_linked_doctypes( - doctype: str, docname: str, linked_to: str, value: str, ignore_doctypes: Optional[List] = None + doctype: str, docname: str, linked_to: str, value: str, ignore_doctypes: list | None = None ): """ linked_doctype_info_list = list formed by get_fetch_fields() function @@ -31,8 +30,8 @@ def update_linked_doctypes( def get_fetch_fields( - doctype: str, linked_to: str, ignore_doctypes: Optional[List] = None -) -> List[Dict]: + doctype: str, linked_to: str, ignore_doctypes: list | None = None +) -> list[dict]: """ doctype = Master DocType in which the changes are being made linked_to = DocType name of the field thats being updated in Master diff --git a/frappe/model/utils/rename_field.py b/frappe/model/utils/rename_field.py index 56e69455ef..9e4fc5d84a 100644 --- a/frappe/model/utils/rename_field.py +++ b/frappe/model/utils/rename_field.py @@ -40,7 +40,7 @@ def rename_field(doctype, old_fieldname, new_fieldname): ) else: # copy field value - frappe.db.sql("""update `tab%s` set `%s`=`%s`""" % (doctype, new_fieldname, old_fieldname)) + frappe.db.sql(f"""update `tab{doctype}` set `{new_fieldname}`=`{old_fieldname}`""") update_reports(doctype, old_fieldname, new_fieldname) update_users_report_view_settings(doctype, old_fieldname, new_fieldname) diff --git a/frappe/model/utils/user_settings.py b/frappe/model/utils/user_settings.py index a6ae1a818e..c12c7e27ba 100644 --- a/frappe/model/utils/user_settings.py +++ b/frappe/model/utils/user_settings.py @@ -11,9 +11,7 @@ filter_dict = {"doctype": 0, "docfield": 1, "operator": 2, "value": 3} def get_user_settings(doctype, for_update=False): - user_settings = frappe.cache().hget( - "_user_settings", "{0}::{1}".format(doctype, frappe.session.user) - ) + user_settings = frappe.cache().hget("_user_settings", f"{doctype}::{frappe.session.user}") if user_settings is None: user_settings = frappe.db.sql( @@ -43,9 +41,7 @@ def update_user_settings(doctype, user_settings, for_update=False): current.update(user_settings) - frappe.cache().hset( - "_user_settings", "{0}::{1}".format(doctype, frappe.session.user), json.dumps(current) - ) + frappe.cache().hset("_user_settings", f"{doctype}::{frappe.session.user}", json.dumps(current)) def sync_user_settings(): @@ -103,6 +99,4 @@ def update_user_settings_data( ) # clear that user settings from the redis cache - frappe.cache().hset( - "_user_settings", "{0}::{1}".format(user_setting.doctype, user_setting.user), None - ) + frappe.cache().hset("_user_settings", f"{user_setting.doctype}::{user_setting.user}", None) diff --git a/frappe/model/workflow.py b/frappe/model/workflow.py index 96fd710d91..923fbc1b3b 100644 --- a/frappe/model/workflow.py +++ b/frappe/model/workflow.py @@ -246,15 +246,15 @@ def bulk_workflow_approval(docnames, doctype, action): except Exception as e: if not frappe.message_log: # Exception is raised manually and not from msgprint or throw - message = "{0}".format(e.__class__.__name__) + message = f"{e.__class__.__name__}" if e.args: - message += " : {0}".format(e.args[0]) + message += f" : {e.args[0]}" message_dict = {"docname": docname, "message": message} failed_transactions[docname].append(message_dict) frappe.db.rollback() frappe.log_error( - title="Workflow {0} threw an error for {1} {2}".format(action, doctype, docname), + title=f"Workflow {action} threw an error for {doctype} {docname}", reference_doctype="Workflow", reference_name=action, ) @@ -286,19 +286,19 @@ def bulk_workflow_approval(docnames, doctype, action): def print_workflow_log(messages, title, doctype, indicator): if messages.keys(): - msg = "

    {0}

    ".format(title) + msg = f"

    {title}

    " for doc in messages.keys(): if len(messages[doc]): - html = "
    {0}".format(frappe.utils.get_link_to_form(doctype, doc)) + html = f"
    {frappe.utils.get_link_to_form(doctype, doc)}" for log in messages[doc]: if log.get("message"): - html += "
    {0}
    ".format( + html += "
    {}
    ".format( log.get("message") ) html += "
    " else: - html = "
    {0}
    ".format(doc) + html = f"
    {doc}
    " msg += html frappe.msgprint(msg, title=_("Workflow Status"), indicator=indicator, is_minimizable=True) diff --git a/frappe/modules/export_file.py b/frappe/modules/export_file.py index 8eac7a9229..e3a80d6679 100644 --- a/frappe/modules/export_file.py +++ b/frappe/modules/export_file.py @@ -113,7 +113,7 @@ def create_folder(module, dt, dn, create_init): def get_custom_module_path(module): package = frappe.db.get_value("Module Def", module, "package") if not package: - frappe.throw("Package must be set for custom Module {module}".format(module=module)) + frappe.throw(f"Package must be set for custom Module {module}") path = os.path.join(get_package_path(package), scrub(module)) if not os.path.exists(path): diff --git a/frappe/modules/import_file.py b/frappe/modules/import_file.py index d39f98f966..3690da0657 100644 --- a/frappe/modules/import_file.py +++ b/frappe/modules/import_file.py @@ -109,7 +109,7 @@ def import_file_by_path( """ try: docs = read_doc_from_file(path) - except IOError: + except OSError: print(f"{path} missing") return @@ -172,14 +172,14 @@ def import_file_by_path( def read_doc_from_file(path): doc = None if os.path.exists(path): - with open(path, "r") as f: + with open(path) as f: try: doc = json.loads(f.read()) except ValueError: - print("bad json: {0}".format(path)) + print(f"bad json: {path}") raise else: - raise IOError("%s missing" % path) + raise OSError("%s missing" % path) return doc @@ -254,7 +254,7 @@ def load_code_properties(doc, path): for key, extn in doc.get_code_fields().items(): codefile = os.path.join(dirname, filename.split(".")[0] + "." + extn) if os.path.exists(codefile): - with open(codefile, "r") as txtfile: + with open(codefile) as txtfile: doc.set(key, txtfile.read()) @@ -285,6 +285,6 @@ def reset_tree_properties(doc): # "rgt". They are automatically set and kept up-to-date. Importing them # would destroy any existing tree structure. if getattr(doc.meta, "is_tree", None) and any([doc.lft, doc.rgt]): - print('Ignoring values of `lft` and `rgt` for {} "{}"'.format(doc.doctype, doc.name)) + print(f'Ignoring values of `lft` and `rgt` for {doc.doctype} "{doc.name}"') doc.lft = None doc.rgt = None diff --git a/frappe/modules/patch_handler.py b/frappe/modules/patch_handler.py index ae6d9a6de2..f389312a4f 100644 --- a/frappe/modules/patch_handler.py +++ b/frappe/modules/patch_handler.py @@ -38,7 +38,6 @@ import configparser import time from enum import Enum from textwrap import dedent, indent -from typing import List, Optional import frappe @@ -52,7 +51,7 @@ class PatchType(Enum): post_model_sync = "post_model_sync" -def run_all(skip_failing: bool = False, patch_type: Optional[PatchType] = None) -> None: +def run_all(skip_failing: bool = False, patch_type: PatchType | None = None) -> None: """run all pending patches""" executed = set(frappe.get_all("Patch Log", fields="patch", pluck="patch")) @@ -81,7 +80,7 @@ def run_all(skip_failing: bool = False, patch_type: Optional[PatchType] = None) run_patch(patch) -def get_all_patches(patch_type: Optional[PatchType] = None) -> List[str]: +def get_all_patches(patch_type: PatchType | None = None) -> list[str]: if patch_type and not isinstance(patch_type, PatchType): frappe.throw(f"Unsupported patch type specified: {patch_type}") @@ -93,7 +92,7 @@ def get_all_patches(patch_type: Optional[PatchType] = None) -> List[str]: return patches -def get_patches_from_app(app: str, patch_type: Optional[PatchType] = None) -> List[str]: +def get_patches_from_app(app: str, patch_type: PatchType | None = None) -> list[str]: """Get patches from an app's patches.txt patches.txt can be: diff --git a/frappe/modules/utils.py b/frappe/modules/utils.py index ad6a75e900..f4a386cfc9 100644 --- a/frappe/modules/utils.py +++ b/frappe/modules/utils.py @@ -105,7 +105,7 @@ def sync_customizations(app=None): if os.path.exists(folder): for fname in os.listdir(folder): if fname.endswith(".json"): - with open(os.path.join(folder, fname), "r") as f: + with open(os.path.join(folder, fname)) as f: data = json.loads(f.read()) if data.get("sync_on_migrate"): sync_customizations_for_doctype(data, folder) @@ -164,7 +164,7 @@ def sync_customizations_for_doctype(data, folder): if data.get("custom_perms"): sync("custom_perms", "Custom DocPerm", "parent") - print("Updating customizations for {0}".format(doctype)) + print(f"Updating customizations for {doctype}") validate_fields_for_doctype(doctype) if update_schema and not frappe.db.get_value("DocType", doctype, "issingle"): @@ -317,7 +317,6 @@ def make_boilerplate(template, doc, opts=None): with open(target_file_path, "w") as target: with open( os.path.join(get_module_path("core"), "doctype", scrub(doc.doctype), "boilerplate", template), - "r", ) as source: target.write( frappe.as_unicode( diff --git a/frappe/monitor.py b/frappe/monitor.py index 74f9e06ef3..e151944b1f 100644 --- a/frappe/monitor.py +++ b/frappe/monitor.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE diff --git a/frappe/parallel_test_runner.py b/frappe/parallel_test_runner.py index 4fd03773ef..39a00235cb 100644 --- a/frappe/parallel_test_runner.py +++ b/frappe/parallel_test_runner.py @@ -83,7 +83,7 @@ class ParallelTestRunner: test_record_filename = re.sub("^test_", "", filename).replace(".py", ".json") test_record_file_path = os.path.join(path, test_record_filename) if os.path.exists(test_record_file_path): - with open(test_record_file_path, "r") as f: + with open(test_record_file_path) as f: doc = json.loads(f.read()) doctype = doc["name"] make_test_records(doctype, commit=True) diff --git a/frappe/patches/v10_0/increase_single_table_column_length.py b/frappe/patches/v10_0/increase_single_table_column_length.py index 21b5a790ab..0b8e94a3f7 100644 --- a/frappe/patches/v10_0/increase_single_table_column_length.py +++ b/frappe/patches/v10_0/increase_single_table_column_length.py @@ -6,4 +6,4 @@ import frappe def execute(): for col in ("field", "doctype"): - frappe.db.sql_ddl("alter table `tabSingles` modify column `{0}` varchar(255)".format(col)) + frappe.db.sql_ddl(f"alter table `tabSingles` modify column `{col}` varchar(255)") diff --git a/frappe/patches/v11_0/delete_duplicate_user_permissions.py b/frappe/patches/v11_0/delete_duplicate_user_permissions.py index b986c6f825..f2ca6d51fe 100644 --- a/frappe/patches/v11_0/delete_duplicate_user_permissions.py +++ b/frappe/patches/v11_0/delete_duplicate_user_permissions.py @@ -13,7 +13,7 @@ def execute(): for record in duplicateRecords: frappe.db.sql( """delete from `tabUser Permission` - where allow=%s and user=%s and for_value=%s limit {0}""".format( + where allow=%s and user=%s and for_value=%s limit {}""".format( record.count - 1 ), (record.allow, record.user, record.for_value), diff --git a/frappe/patches/v11_0/drop_column_apply_user_permissions.py b/frappe/patches/v11_0/drop_column_apply_user_permissions.py index bfc4aee72c..0a0091624e 100644 --- a/frappe/patches/v11_0/drop_column_apply_user_permissions.py +++ b/frappe/patches/v11_0/drop_column_apply_user_permissions.py @@ -8,7 +8,7 @@ def execute(): for doctype in to_remove: if frappe.db.table_exists(doctype): if column in frappe.db.get_table_columns(doctype): - frappe.db.sql("alter table `tab{0}` drop column {1}".format(doctype, column)) + frappe.db.sql(f"alter table `tab{doctype}` drop column {column}") frappe.reload_doc("core", "doctype", "docperm", force=True) frappe.reload_doc("core", "doctype", "custom_docperm", force=True) diff --git a/frappe/patches/v11_0/fix_order_by_in_reports_json.py b/frappe/patches/v11_0/fix_order_by_in_reports_json.py index 3dfec0954f..4e955a338b 100644 --- a/frappe/patches/v11_0/fix_order_by_in_reports_json.py +++ b/frappe/patches/v11_0/fix_order_by_in_reports_json.py @@ -28,8 +28,8 @@ def execute(): sort_by = parts[1].split(" ") - json_data["order_by"] = "`tab{0}`.`{1}`".format(doc.ref_doctype, sort_by[0]) - json_data["order_by"] += " {0}".format(sort_by[1]) if len(sort_by) > 1 else "" + json_data["order_by"] = f"`tab{doc.ref_doctype}`.`{sort_by[0]}`" + json_data["order_by"] += f" {sort_by[1]}" if len(sort_by) > 1 else "" doc.json = json.dumps(json_data) doc.save() diff --git a/frappe/patches/v11_0/update_list_user_settings.py b/frappe/patches/v11_0/update_list_user_settings.py index 146b29346c..5209b9e384 100644 --- a/frappe/patches/v11_0/update_list_user_settings.py +++ b/frappe/patches/v11_0/update_list_user_settings.py @@ -13,7 +13,7 @@ def execute(): # get user_settings for each user settings = frappe.db.sql( "select * from `__UserSettings` \ - where user={0}".format( + where user={}".format( frappe.db.escape(user.user) ), as_dict=True, diff --git a/frappe/patches/v12_0/delete_duplicate_indexes.py b/frappe/patches/v12_0/delete_duplicate_indexes.py index 6a6b0b3204..f1def21f7f 100644 --- a/frappe/patches/v12_0/delete_duplicate_indexes.py +++ b/frappe/patches/v12_0/delete_duplicate_indexes.py @@ -43,10 +43,10 @@ def execute(): # build drop index query for (table_name, index_list) in final_deletion_map.items(): query_list = [] - alter_query = "ALTER TABLE `{}`".format(table_name) + alter_query = f"ALTER TABLE `{table_name}`" for index in index_list: - query_list.append("{} DROP INDEX `{}`".format(alter_query, index)) + query_list.append(f"{alter_query} DROP INDEX `{index}`") for query in query_list: try: diff --git a/frappe/patches/v12_0/fix_public_private_files.py b/frappe/patches/v12_0/fix_public_private_files.py index e1ad2f1862..382e3c2db1 100644 --- a/frappe/patches/v12_0/fix_public_private_files.py +++ b/frappe/patches/v12_0/fix_public_private_files.py @@ -30,7 +30,7 @@ def generate_file(file_name): file_doc.file_url = new_doc.file_url file_doc.save() - except IOError: + except OSError: pass except Exception as e: print(e) diff --git a/frappe/patches/v12_0/move_timeline_links_to_dynamic_links.py b/frappe/patches/v12_0/move_timeline_links_to_dynamic_links.py index 2207edd958..4d2061c5ac 100644 --- a/frappe/patches/v12_0/move_timeline_links_to_dynamic_links.py +++ b/frappe/patches/v12_0/move_timeline_links_to_dynamic_links.py @@ -22,7 +22,7 @@ def execute(): if communication.timeline_doctype and communication.timeline_name: name += 1 values.append( - """({0}, "{1}", "timeline_links", "Communication", "{2}", "{3}", "{4}", "{5}", "{6}", "{7}")""".format( + """({}, "{}", "timeline_links", "Communication", "{}", "{}", "{}", "{}", "{}", "{}")""".format( counter, str(name), frappe.db.escape(communication.name), @@ -37,7 +37,7 @@ def execute(): if communication.link_doctype and communication.link_name: name += 1 values.append( - """({0}, "{1}", "timeline_links", "Communication", "{2}", "{3}", "{4}", "{5}", "{6}", "{7}")""".format( + """({}, "{}", "timeline_links", "Communication", "{}", "{}", "{}", "{}", "{}", "{}")""".format( counter, str(name), frappe.db.escape(communication.name), @@ -55,7 +55,7 @@ def execute(): INSERT INTO `tabCommunication Link` (`idx`, `name`, `parentfield`, `parenttype`, `parent`, `link_doctype`, `link_name`, `creation`, `modified`, `modified_by`) - VALUES {0} + VALUES {} """.format( ", ".join([d for d in values]) ) diff --git a/frappe/patches/v12_0/set_correct_url_in_files.py b/frappe/patches/v12_0/set_correct_url_in_files.py index dca42a3c04..fee0b5d6fc 100644 --- a/frappe/patches/v12_0/set_correct_url_in_files.py +++ b/frappe/patches/v12_0/set_correct_url_in_files.py @@ -30,12 +30,10 @@ def execute(): if file_is_private: public_file_url = os.path.join(public_file_path, file_name) if os.path.exists(public_file_url): - frappe.db.set_value( - "File", file.name, {"file_url": "/files/{0}".format(file_name), "is_private": 0} - ) + frappe.db.set_value("File", file.name, {"file_url": f"/files/{file_name}", "is_private": 0}) else: private_file_url = os.path.join(private_file_path, file_name) if os.path.exists(private_file_url): frappe.db.set_value( - "File", file.name, {"file_url": "/private/files/{0}".format(file_name), "is_private": 1} + "File", file.name, {"file_url": f"/private/files/{file_name}", "is_private": 1} ) diff --git a/frappe/patches/v12_0/setup_tags.py b/frappe/patches/v12_0/setup_tags.py index 46482a102b..6bff8d3dac 100644 --- a/frappe/patches/v12_0/setup_tags.py +++ b/frappe/patches/v12_0/setup_tags.py @@ -17,7 +17,7 @@ def execute(): continue for _user_tags in frappe.db.sql( - "select `name`, `_user_tags` from `tab{0}`".format(doctype.name), as_dict=True + f"select `name`, `_user_tags` from `tab{doctype.name}`", as_dict=True ): if not _user_tags.get("_user_tags"): continue diff --git a/frappe/patches/v13_0/set_unique_for_page_view.py b/frappe/patches/v13_0/set_unique_for_page_view.py index 1a674f6697..45351afdde 100644 --- a/frappe/patches/v13_0/set_unique_for_page_view.py +++ b/frappe/patches/v13_0/set_unique_for_page_view.py @@ -4,6 +4,4 @@ import frappe def execute(): frappe.reload_doc("website", "doctype", "web_page_view", force=True) site_url = frappe.utils.get_site_url(frappe.local.site) - frappe.db.sql( - """UPDATE `tabWeb Page View` set is_unique=1 where referrer LIKE '%{0}%'""".format(site_url) - ) + frappe.db.sql(f"""UPDATE `tabWeb Page View` set is_unique=1 where referrer LIKE '%{site_url}%'""") diff --git a/frappe/patches/v14_0/copy_mail_data.py b/frappe/patches/v14_0/copy_mail_data.py index 6b976ba6fb..c44b7c9e92 100644 --- a/frappe/patches/v14_0/copy_mail_data.py +++ b/frappe/patches/v14_0/copy_mail_data.py @@ -1,5 +1,3 @@ -from __future__ import unicode_literals - import frappe diff --git a/frappe/patches/v14_0/update_color_names_in_kanban_board_column.py b/frappe/patches/v14_0/update_color_names_in_kanban_board_column.py index f8d6f236cd..b568151273 100644 --- a/frappe/patches/v14_0/update_color_names_in_kanban_board_column.py +++ b/frappe/patches/v14_0/update_color_names_in_kanban_board_column.py @@ -1,7 +1,6 @@ # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import frappe diff --git a/frappe/permissions.py b/frappe/permissions.py index 55a7c0e5f3..25d054f2e3 100644 --- a/frappe/permissions.py +++ b/frappe/permissions.py @@ -1,7 +1,6 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE import copy -from typing import List import frappe import frappe.share @@ -516,7 +515,7 @@ def clear_user_permissions_for_doctype(doctype, user=None): def can_import(doctype, raise_exception=False): if not ("System Manager" in frappe.get_roles() or has_permission(doctype, "import")): if raise_exception: - raise frappe.PermissionError("You are not allowed to import: {doctype}".format(doctype=doctype)) + raise frappe.PermissionError(f"You are not allowed to import: {doctype}") else: return False return True @@ -606,7 +605,7 @@ def reset_perms(doctype): frappe.db.delete("Custom DocPerm", {"parent": doctype}) -def get_linked_doctypes(dt: str) -> List: +def get_linked_doctypes(dt: str) -> list: meta = frappe.get_meta(dt) linked_doctypes = [dt] + [ d.options diff --git a/frappe/printing/doctype/letter_head/test_letter_head.py b/frappe/printing/doctype/letter_head/test_letter_head.py index 9357d15315..75019ce275 100644 --- a/frappe/printing/doctype/letter_head/test_letter_head.py +++ b/frappe/printing/doctype/letter_head/test_letter_head.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/printing/doctype/print_format/print_format.py b/frappe/printing/doctype/print_format/print_format.py index 2e12fdb8d8..e49db67512 100644 --- a/frappe/printing/doctype/print_format/print_format.py +++ b/frappe/printing/doctype/print_format/print_format.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/printing/doctype/print_heading/print_heading.py b/frappe/printing/doctype/print_heading/print_heading.py index c905e68d47..9daee06f03 100644 --- a/frappe/printing/doctype/print_heading/print_heading.py +++ b/frappe/printing/doctype/print_heading/print_heading.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/printing/doctype/print_heading/test_print_heading.py b/frappe/printing/doctype/print_heading/test_print_heading.py index 02eddb072f..74ff7ce74f 100644 --- a/frappe/printing/doctype/print_heading/test_print_heading.py +++ b/frappe/printing/doctype/print_heading/test_print_heading.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/printing/doctype/print_settings/print_settings.py b/frappe/printing/doctype/print_settings/print_settings.py index f52d08e6ec..36eaac2e68 100644 --- a/frappe/printing/doctype/print_settings/print_settings.py +++ b/frappe/printing/doctype/print_settings/print_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/printing/doctype/print_settings/test_print_settings.py b/frappe/printing/doctype/print_settings/test_print_settings.py index ba22df4438..6a6437bf97 100644 --- a/frappe/printing/doctype/print_settings/test_print_settings.py +++ b/frappe/printing/doctype/print_settings/test_print_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/printing/doctype/print_style/print_style.py b/frappe/printing/doctype/print_style/print_style.py index 00de829deb..2b0fbfe929 100644 --- a/frappe/printing/doctype/print_style/print_style.py +++ b/frappe/printing/doctype/print_style/print_style.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/printing/doctype/print_style/test_print_style.py b/frappe/printing/doctype/print_style/test_print_style.py index ad2b61cc87..f8ce54b9bb 100644 --- a/frappe/printing/doctype/print_style/test_print_style.py +++ b/frappe/printing/doctype/print_style/test_print_style.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2017, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/printing/page/print_format_builder_beta/print_format_builder_beta.py b/frappe/printing/page/print_format_builder_beta/print_format_builder_beta.py index 668be8d05a..d54624aaef 100644 --- a/frappe/printing/page/print_format_builder_beta/print_format_builder_beta.py +++ b/frappe/printing/page/print_format_builder_beta/print_format_builder_beta.py @@ -1,7 +1,6 @@ # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals import functools @@ -13,7 +12,7 @@ def get_google_fonts(): return _get_google_fonts() -@functools.lru_cache() +@functools.lru_cache def _get_google_fonts(): file_path = frappe.get_app_path("frappe", "data", "google_fonts.json") return frappe.parse_json(frappe.read_file(file_path)) diff --git a/frappe/query_builder/custom.py b/frappe/query_builder/custom.py index 20827df190..3203c72b8d 100644 --- a/frappe/query_builder/custom.py +++ b/frappe/query_builder/custom.py @@ -1,4 +1,4 @@ -from typing import Any, Optional +from typing import Any from pypika.functions import DistinctOptionFunction from pypika.terms import Term @@ -8,17 +8,17 @@ import frappe class GROUP_CONCAT(DistinctOptionFunction): - def __init__(self, column: str, alias: Optional[str] = None): + def __init__(self, column: str, alias: str | None = None): """[ Implements the group concat function read more about it at https://www.geeksforgeeks.org/mysql-group_concat-function ] Args: column (str): [ name of the column you want to concat] alias (Optional[str], optional): [ is this an alias? ]. Defaults to None. """ - super(GROUP_CONCAT, self).__init__("GROUP_CONCAT", column, alias=alias) + super().__init__("GROUP_CONCAT", column, alias=alias) class STRING_AGG(DistinctOptionFunction): - def __init__(self, column: str, separator: str = ",", alias: Optional[str] = None): + def __init__(self, column: str, separator: str = ",", alias: str | None = None): """[ Implements the group concat function read more about it at https://docs.microsoft.com/en-us/sql/t-sql/functions/string-agg-transact-sql?view=sql-server-ver15 ] Args: @@ -26,7 +26,7 @@ class STRING_AGG(DistinctOptionFunction): separator (str, optional): [separator to be used]. Defaults to ",". alias (Optional[str], optional): [description]. Defaults to None. """ - super(STRING_AGG, self).__init__("STRING_AGG", column, separator, alias=alias) + super().__init__("STRING_AGG", column, separator, alias=alias) class MATCH(DistinctOptionFunction): @@ -37,7 +37,7 @@ class MATCH(DistinctOptionFunction): column (str):[ column to search in ] """ alias = kwargs.get("alias") - super(MATCH, self).__init__(" MATCH", column, *args, alias=alias) + super().__init__(" MATCH", column, *args, alias=alias) self._Against = False def get_function_sql(self, **kwargs): @@ -65,7 +65,7 @@ class TO_TSVECTOR(DistinctOptionFunction): column (str): [ column to search in ] """ alias = kwargs.get("alias") - super(TO_TSVECTOR, self).__init__("TO_TSVECTOR", column, *args, alias=alias) + super().__init__("TO_TSVECTOR", column, *args, alias=alias) self._PLAINTO_TSQUERY = False def get_function_sql(self, **kwargs): @@ -95,7 +95,7 @@ class ConstantColumn(Term): """ self.value = value - def get_sql(self, quote_char: Optional[str] = None, **kwargs: Any) -> str: + def get_sql(self, quote_char: str | None = None, **kwargs: Any) -> str: return format_alias_sql( format_quotes(self.value, kwargs.get("secondary_quote_char") or ""), self.alias or self.value, diff --git a/frappe/query_builder/functions.py b/frappe/query_builder/functions.py index f03c139f57..9e49756340 100644 --- a/frappe/query_builder/functions.py +++ b/frappe/query_builder/functions.py @@ -11,7 +11,7 @@ from .utils import PseudoColumn class Concat_ws(Function): def __init__(self, *terms, **kwargs): - super(Concat_ws, self).__init__("CONCAT_WS", *terms, **kwargs) + super().__init__("CONCAT_WS", *terms, **kwargs) GroupConcat = ImportMapper({db_type_is.MARIADB: GROUP_CONCAT, db_type_is.POSTGRES: STRING_AGG}) @@ -68,7 +68,7 @@ class Cast_(Function): if hasattr(self.as_type, "get_sql") else str(self.as_type).upper() ) - return "AS {type}".format(type=type_sql) + return f"AS {type_sql}" def _aggregate(function, dt, fieldname, filters, **kwargs): diff --git a/frappe/query_builder/terms.py b/frappe/query_builder/terms.py index 64a4707983..4d3c98b6a3 100644 --- a/frappe/query_builder/terms.py +++ b/frappe/query_builder/terms.py @@ -1,5 +1,5 @@ from datetime import timedelta -from typing import Any, Dict, Optional +from typing import Any from pypika.queries import QueryBuilder from pypika.terms import Criterion, Function, ValueWrapper @@ -27,7 +27,7 @@ class NamedParameterWrapper: self.parameters[param_key[2:-2]] = param_value return param_key - def get_parameters(self) -> Dict[str, Any]: + def get_parameters(self) -> dict[str, Any]: """get dict with parameters and values Returns: @@ -45,9 +45,9 @@ class ParameterizedValueWrapper(ValueWrapper): def get_sql( self, - quote_char: Optional[str] = None, + quote_char: str | None = None, secondary_quote_char: str = "'", - param_wrapper: Optional[NamedParameterWrapper] = None, + param_wrapper: NamedParameterWrapper | None = None, **kwargs: Any, ) -> str: if param_wrapper and isinstance(self.value, str): @@ -104,7 +104,7 @@ class SubQuery(Criterion): def __init__( self, subq: QueryBuilder, - alias: Optional[str] = None, + alias: str | None = None, ) -> None: super().__init__(alias) self.subq = subq diff --git a/frappe/query_builder/utils.py b/frappe/query_builder/utils.py index 10bab38a63..ad8ff4b0df 100644 --- a/frappe/query_builder/utils.py +++ b/frappe/query_builder/utils.py @@ -1,6 +1,6 @@ from enum import Enum from importlib import import_module -from typing import Any, Callable, Dict, Union, get_type_hints +from typing import Any, Callable, get_type_hints from pypika import Query from pypika.queries import Column @@ -18,7 +18,7 @@ class db_type_is(Enum): class ImportMapper: - def __init__(self, func_map: Dict[db_type_is, Callable]) -> None: + def __init__(self, func_map: dict[db_type_is, Callable]) -> None: self.func_map = func_map def __call__(self, *args: Any, **kwds: Any) -> Callable: @@ -31,7 +31,7 @@ class BuilderIdentificationFailed(Exception): super().__init__("Couldn't guess builder") -def get_query_builder(type_of_db: str) -> Union[Postgres, MariaDB]: +def get_query_builder(type_of_db: str) -> Postgres | MariaDB: """[return the query builder object] Args: diff --git a/frappe/rate_limiter.py b/frappe/rate_limiter.py index 6693f8abaf..0717124ba9 100644 --- a/frappe/rate_limiter.py +++ b/frappe/rate_limiter.py @@ -1,10 +1,9 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE from datetime import datetime from functools import wraps -from typing import Callable, Union +from typing import Callable from werkzeug.wrappers import Response @@ -85,9 +84,9 @@ class RateLimiter: def rate_limit( key: str = None, - limit: Union[int, Callable] = 5, + limit: int | Callable = 5, seconds: int = 24 * 60 * 60, - methods: Union[str, list] = "ALL", + methods: str | list = "ALL", ip_based: bool = True, ): """Decorator to rate limit an endpoint. diff --git a/frappe/recorder.py b/frappe/recorder.py index 87e001fe31..0262f4cbce 100644 --- a/frappe/recorder.py +++ b/frappe/recorder.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE import datetime @@ -36,7 +35,7 @@ def sql(*args, **kwargs): # Collect EXPLAIN for executed query if query.lower().strip().split()[0] in ("select", "update", "delete"): # Only SELECT/UPDATE/DELETE queries can be "EXPLAIN"ed - explain_result = frappe.db._sql("EXPLAIN {}".format(query), as_dict=True) + explain_result = frappe.db._sql(f"EXPLAIN {query}", as_dict=True) else: explain_result = [] @@ -45,7 +44,7 @@ def sql(*args, **kwargs): "stack": stack, "explain_result": explain_result, "time": start_time, - "duration": float("{:.3f}".format((end_time - start_time) * 1000)), + "duration": float(f"{(end_time - start_time) * 1000:.3f}"), } frappe.local._recorder.register(data) @@ -102,9 +101,7 @@ class Recorder: "time": self.time, "queries": len(self.calls), "time_queries": float("{:0.3f}".format(sum(call["duration"] for call in self.calls))), - "duration": float( - "{:0.3f}".format((datetime.datetime.now() - self.time).total_seconds() * 1000) - ), + "duration": float(f"{(datetime.datetime.now() - self.time).total_seconds() * 1000:0.3f}"), "method": self.method, } frappe.cache().hset(RECORDER_REQUEST_SPARSE_HASH, self.uuid, request_data) diff --git a/frappe/social/doctype/energy_point_log/energy_point_log.py b/frappe/social/doctype/energy_point_log/energy_point_log.py index a0c5120fa7..e888e9b53f 100644 --- a/frappe/social/doctype/energy_point_log/energy_point_log.py +++ b/frappe/social/doctype/energy_point_log/energy_point_log.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -51,7 +50,7 @@ class EnergyPointLog(Document): "document_name": self.reference_name, "subject": get_notification_message(self), "from_user": reference_user, - "email_content": "
    {}
    ".format(self.reason) if self.reason else None, + "email_content": f"
    {self.reason}
    " if self.reason else None, } enqueue_create_notification(self.user, notification_doc) @@ -360,7 +359,7 @@ def send_summary(timespan): ] frappe.sendmail( - subject="{} energy points summary".format(timespan), + subject=f"{timespan} energy points summary", recipients=all_users, template="energy_points_summary", args={ diff --git a/frappe/social/doctype/energy_point_log/test_energy_point_log.py b/frappe/social/doctype/energy_point_log/test_energy_point_log.py index 9a244a0a2c..3830f0505b 100644 --- a/frappe/social/doctype/energy_point_log/test_energy_point_log.py +++ b/frappe/social/doctype/energy_point_log/test_energy_point_log.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE import frappe diff --git a/frappe/social/doctype/energy_point_rule/energy_point_rule.py b/frappe/social/doctype/energy_point_rule/energy_point_rule.py index 9d393dde48..1057ac2749 100644 --- a/frappe/social/doctype/energy_point_rule/energy_point_rule.py +++ b/frappe/social/doctype/energy_point_rule/energy_point_rule.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/social/doctype/energy_point_settings/energy_point_settings.py b/frappe/social/doctype/energy_point_settings/energy_point_settings.py index c1ff2707af..4156aa0094 100644 --- a/frappe/social/doctype/energy_point_settings/energy_point_settings.py +++ b/frappe/social/doctype/energy_point_settings/energy_point_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/social/doctype/review_level/review_level.py b/frappe/social/doctype/review_level/review_level.py index b3418e913e..9734d45118 100644 --- a/frappe/social/doctype/review_level/review_level.py +++ b/frappe/social/doctype/review_level/review_level.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/templates/includes/comments/comments.py b/frappe/templates/includes/comments/comments.py index b98106c0dc..c90c07c776 100644 --- a/frappe/templates/includes/comments/comments.py +++ b/frappe/templates/includes/comments/comments.py @@ -44,7 +44,7 @@ def add_comment(comment, comment_email, comment_by, reference_doctype, reference content = ( comment.content - + "

    {2}

    ".format( + + "

    {}

    ".format( frappe.utils.get_request_site_address(), comment.name, _("View Comment") ) ) diff --git a/frappe/templates/includes/feedback/feedback.py b/frappe/templates/includes/feedback/feedback.py index 4c6a0588f5..16ebdaf741 100644 --- a/frappe/templates/includes/feedback/feedback.py +++ b/frappe/templates/includes/feedback/feedback.py @@ -1,6 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE -from __future__ import unicode_literals import frappe from frappe import _ @@ -40,7 +39,7 @@ def give_feedback(reference_doctype, reference_name, like): def send_mail(feedback, subject): doc = frappe.get_doc(feedback.reference_doctype, feedback.reference_name) if feedback.like: - message = "

    Hey,

    You have received a ❤️ heart on your blog post {0}

    ".format( + message = "

    Hey,

    You have received a ❤️ heart on your blog post {}

    ".format( feedback.reference_name ) else: diff --git a/frappe/test_runner.py b/frappe/test_runner.py index 82179d8fac..e8c1656ca8 100644 --- a/frappe/test_runner.py +++ b/frappe/test_runner.py @@ -57,7 +57,7 @@ def main( if doctype_list_path: app, doctype_list_path = doctype_list_path.split(os.path.sep, 1) - with open(frappe.get_app_path(app, doctype_list_path), "r") as f: + with open(frappe.get_app_path(app, doctype_list_path)) as f: doctype = f.read().strip().splitlines() if ui_tests: @@ -151,14 +151,14 @@ def set_test_email_config(): class TimeLoggingTestResult(unittest.TextTestResult): def startTest(self, test): self._started_at = time.time() - super(TimeLoggingTestResult, self).startTest(test) + super().startTest(test) def addSuccess(self, test): elapsed = time.time() - self._started_at name = self.getDescription(test) if elapsed >= SLOW_TEST_THRESHOLD: - self.stream.write("\n{} ({:.03}s)\n".format(name, elapsed)) - super(TimeLoggingTestResult, self).addSuccess(test) + self.stream.write(f"\n{name} ({elapsed:.03}s)\n") + super().addSuccess(test) def run_all_tests( @@ -227,7 +227,7 @@ def run_tests_for_doctype( for doctype in doctypes: module = frappe.db.get_value("DocType", doctype, "module") if not module: - print("Invalid doctype {0}".format(doctype)) + print(f"Invalid doctype {doctype}") sys.exit(1) test_module = get_module_name(doctype, module, "test_") @@ -351,7 +351,7 @@ def _add_test(app, path, filename, verbose, test_suite=None, ui_tests=False): if os.path.basename(os.path.dirname(path)) == "doctype": txt_file = os.path.join(path, filename[5:].replace(".py", ".json")) if os.path.exists(txt_file): - with open(txt_file, "r") as f: + with open(txt_file) as f: doc = json.loads(f.read()) doctype = doc["name"] make_test_records(doctype, verbose, commit=True) @@ -535,7 +535,7 @@ def get_test_record_log(): """Return the list of doctypes for which test records have been created""" if "test_record_log" not in frappe.flags: if os.path.exists(frappe.get_site_path(".test_log")): - with open(frappe.get_site_path(".test_log"), "r") as f: + with open(frappe.get_site_path(".test_log")) as f: frappe.flags.test_record_log = f.read().splitlines() else: frappe.flags.test_record_log = [] diff --git a/frappe/tests/test_api.py b/frappe/tests/test_api.py index bbb2280578..0464f54530 100644 --- a/frappe/tests/test_api.py +++ b/frappe/tests/test_api.py @@ -3,7 +3,6 @@ import unittest from contextlib import contextmanager from random import choice from threading import Thread -from typing import Dict, Optional, Tuple from unittest.mock import patch import requests @@ -33,7 +32,7 @@ def suppress_stdout(): def make_request( - target: str, args: Optional[Tuple] = None, kwargs: Optional[Dict] = None + target: str, args: tuple | None = None, kwargs: dict | None = None ) -> TestResponse: t = ThreadWithReturnValue(target=target, args=args, kwargs=kwargs) t.start() @@ -86,7 +85,7 @@ class FrappeAPITestCase(unittest.TestCase): return self._sid - def get(self, path: str, params: Optional[Dict] = None, **kwargs) -> TestResponse: + def get(self, path: str, params: dict | None = None, **kwargs) -> TestResponse: return make_request(target=self.TEST_CLIENT.get, args=(path,), kwargs={"data": params, **kwargs}) def post(self, path, data, **kwargs) -> TestResponse: diff --git a/frappe/tests/test_bot.py b/frappe/tests/test_bot.py index 222f35b99b..ffc3513619 100644 --- a/frappe/tests/test_bot.py +++ b/frappe/tests/test_bot.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE diff --git a/frappe/tests/test_caching.py b/frappe/tests/test_caching.py index 6a1390f10c..66b47b6e31 100644 --- a/frappe/tests/test_caching.py +++ b/frappe/tests/test_caching.py @@ -1,6 +1,5 @@ import time import unittest -from typing import Dict, List, Tuple, Union from unittest.mock import MagicMock import frappe @@ -13,7 +12,7 @@ register_with_external_service = MagicMock(return_value=True) @request_cache -def request_specific_api(a: Union[List, Tuple, Dict, int], b: int) -> int: +def request_specific_api(a: list | tuple | dict | int, b: int) -> int: # API that takes very long to return a result todays_value = external_service() if not isinstance(a, (int, float)): diff --git a/frappe/tests/test_client.py b/frappe/tests/test_client.py index b5a1771800..1a1c4f3232 100644 --- a/frappe/tests/test_client.py +++ b/frappe/tests/test_client.py @@ -146,7 +146,7 @@ class TestClient(unittest.TestCase): from frappe.client import insert def get_random_title(): - return "test-{0}".format(frappe.generate_hash()) + return f"test-{frappe.generate_hash()}" # test insert dict doc = {"doctype": "Note", "title": get_random_title(), "content": "test"} @@ -183,7 +183,7 @@ class TestClient(unittest.TestCase): from frappe.client import insert, insert_many def get_random_title(): - return "test-{0}".format(frappe.generate_hash(length=5)) + return f"test-{frappe.generate_hash(length=5)}" # insert a (parent) doc note1 = {"doctype": "Note", "title": get_random_title(), "content": "test"} diff --git a/frappe/tests/test_commands.py b/frappe/tests/test_commands.py index aa00a884e1..cb8c3d266b 100644 --- a/frappe/tests/test_commands.py +++ b/frappe/tests/test_commands.py @@ -13,7 +13,6 @@ from contextlib import contextmanager from functools import wraps from glob import glob from pathlib import Path -from typing import List, Optional from unittest.case import skipIf from unittest.mock import patch @@ -34,7 +33,7 @@ from frappe.utils import add_to_date, get_bench_path, get_bench_relative_path, n from frappe.utils.backups import fetch_latest_backups from frappe.utils.jinja_globals import bundled_asset -_result: Optional[Result] = None +_result: Result | None = None TEST_SITE = "commands-site-O4PN2QKA.test" # added random string tag to avoid collisions CLI_CONTEXT = frappe._dict(sites=[TEST_SITE]) @@ -55,7 +54,7 @@ def clean(value) -> str: return value -def missing_in_backup(doctypes: List, file: os.PathLike) -> List: +def missing_in_backup(doctypes: list, file: os.PathLike) -> list: """Returns list of missing doctypes in the backup. Args: @@ -72,7 +71,7 @@ def missing_in_backup(doctypes: List, file: os.PathLike) -> List: return [doctype for doctype in doctypes if predicate.format(doctype).lower() not in content] -def exists_in_backup(doctypes: List, file: os.PathLike) -> bool: +def exists_in_backup(doctypes: list, file: os.PathLike) -> bool: """Checks if the list of doctypes exist in the database.sql.gz file supplied Args: @@ -111,7 +110,7 @@ def pass_test_context(f): @contextmanager -def cli(cmd: Command, args: Optional[List] = None): +def cli(cmd: Command, args: list | None = None): with maintain_locals(): global _result @@ -160,9 +159,7 @@ class BaseTestCommands(unittest.TestCase): click.secho(self.command, fg="bright_black") command = shlex.split(self.command) - self._proc = subprocess.run( - command, input=cmd_input, stdout=subprocess.PIPE, stderr=subprocess.PIPE - ) + self._proc = subprocess.run(command, input=cmd_input, capture_output=True) self.stdout = clean(self._proc.stdout) self.stderr = clean(self._proc.stderr) self.returncode = clean(self._proc.returncode) @@ -184,7 +181,7 @@ class BaseTestCommands(unittest.TestCase): ) def _formatMessage(self, msg, standardMsg): - output = super(BaseTestCommands, self)._formatMessage(msg, standardMsg) + output = super()._formatMessage(msg, standardMsg) if not hasattr(self, "command") and _result: command = _result.command @@ -201,14 +198,14 @@ class BaseTestCommands(unittest.TestCase): [ "-" * 70, "Last Command Execution Summary:", - "Command: {}".format(command) if command else "", - "Standard Output: {}".format(stdout) if stdout else "", - "Standard Error: {}".format(stderr) if stderr else "", - "Return Code: {}".format(returncode) if returncode else "", + f"Command: {command}" if command else "", + f"Standard Output: {stdout}" if stdout else "", + f"Standard Error: {stderr}" if stderr else "", + f"Return Code: {returncode}" if returncode else "", ] ).strip() - return "{}\n\n{}".format(output, cmd_execution_summary) + return f"{output}\n\n{cmd_execution_summary}" class TestCommands(BaseTestCommands): @@ -325,10 +322,10 @@ class TestCommands(BaseTestCommands): # test 2: bare functionality for single site self.execute("bench --site {site} list-apps") self.assertEqual(self.returncode, 0) - list_apps = set(_x.split()[0] for _x in self.stdout.split("\n")) + list_apps = {_x.split()[0] for _x in self.stdout.split("\n")} doctype = frappe.get_single("Installed Applications").installed_applications if doctype: - installed_apps = set(x.app_name for x in doctype) + installed_apps = {x.app_name for x in doctype} else: installed_apps = set(frappe.get_installed_apps()) self.assertSetEqual(list_apps, installed_apps) diff --git a/frappe/tests/test_db.py b/frappe/tests/test_db.py index 69f7a7d5aa..2ec1dd7fb2 100644 --- a/frappe/tests/test_db.py +++ b/frappe/tests/test_db.py @@ -119,7 +119,7 @@ class TestDB(unittest.TestCase): self.assertGreaterEqual(1, cint(frappe.db._cursor.rowcount)) def test_escape(self): - frappe.db.escape("香港濟生堂製藥有限公司 - IT".encode("utf-8")) + frappe.db.escape("香港濟生堂製藥有限公司 - IT".encode()) def test_get_single_value(self): # setup @@ -491,15 +491,15 @@ class TestDB(unittest.TestCase): frappe.get_doc(doctype="Note", title="note2", content="someting else").insert() # Count with no filtes - self.assertEquals((frappe.db.count("Note")), 2) + self.assertEqual((frappe.db.count("Note")), 2) # simple filters - self.assertEquals((frappe.db.count("Note", ["title", "=", "note1"])), 1) + self.assertEqual((frappe.db.count("Note", ["title", "=", "note1"])), 1) frappe.get_doc(doctype="Note", title="note3", content="something other").insert() # List of list filters with tables - self.assertEquals( + self.assertEqual( ( frappe.db.count( "Note", diff --git a/frappe/tests/test_db_update.py b/frappe/tests/test_db_update.py index 7c615f2df5..38cc8af2f3 100644 --- a/frappe/tests/test_db_update.py +++ b/frappe/tests/test_db_update.py @@ -18,7 +18,7 @@ class TestDBUpdate(unittest.TestCase): frappe.db.updatedb(doctype) field_defs = get_field_defs(doctype) - table_columns = frappe.db.get_table_columns_description("tab{}".format(doctype)) + table_columns = frappe.db.get_table_columns_description(f"tab{doctype}") self.assertEqual(len(field_defs), len(table_columns)) @@ -34,7 +34,7 @@ class TestDBUpdate(unittest.TestCase): default = field_def.default if field_def.default is not None else fallback_default self.assertEqual(fieldtype, table_column.type) - self.assertIn(cstr(table_column.default) or "NULL", [cstr(default), "'{}'".format(default)]) + self.assertIn(cstr(table_column.default) or "NULL", [cstr(default), f"'{default}'"]) def test_index_and_unique_constraints(self): doctype = "User" @@ -93,7 +93,7 @@ def get_fieldtype_from_def(field_def): fieldtuple = frappe.db.type_map.get(field_def.fieldtype, ("", 0)) fieldtype = fieldtuple[0] if fieldtype in ("varchar", "datetime", "int"): - fieldtype += "({})".format(field_def.length or fieldtuple[1]) + fieldtype += f"({field_def.length or fieldtuple[1]})" return fieldtype @@ -134,5 +134,5 @@ def get_other_fields_meta(meta): def get_table_column(doctype, fieldname): - table_columns = frappe.db.get_table_columns_description("tab{}".format(doctype)) + table_columns = frappe.db.get_table_columns_description(f"tab{doctype}") return find(table_columns, lambda d: d.get("name") == fieldname) diff --git a/frappe/tests/test_email.py b/frappe/tests/test_email.py index 3d6773044f..71886bb625 100644 --- a/frappe/tests/test_email.py +++ b/frappe/tests/test_email.py @@ -281,7 +281,7 @@ class TestEmail(unittest.TestCase): frappe.db.delete("Communication", {"sender": "sukh@yyy.com"}) - with open(frappe.get_app_path("frappe", "tests", "data", "email_with_image.txt"), "r") as raw: + with open(frappe.get_app_path("frappe", "tests", "data", "email_with_image.txt")) as raw: messages = { '"INBOX"': {"latest_messages": [raw.read()], "seen_status": {2: "UNSEEN"}, "uid_list": [2]} } diff --git a/frappe/tests/test_fixture_import.py b/frappe/tests/test_fixture_import.py index 5b776c0392..3113812fa6 100644 --- a/frappe/tests/test_fixture_import.py +++ b/frappe/tests/test_fixture_import.py @@ -1,6 +1,5 @@ import os import unittest -from typing import List import frappe from frappe.core.doctype.data_import.data_import import export_json, import_doc @@ -12,13 +11,13 @@ class TestFixtureImport(unittest.TestCase): def create_new_doctype(self, DocType: str) -> None: file = frappe.get_app_path("frappe", "custom", "fixtures", f"{DocType}.json") - file = open(file, "r") + file = open(file) doc = file.read() file.close() savedocs(doc, "Save") - def insert_dummy_data_and_export(self, DocType: str, dummy_name_list: List[str]) -> str: + def insert_dummy_data_and_export(self, DocType: str, dummy_name_list: list[str]) -> str: for name in dummy_name_list: doc = frappe.get_doc({"doctype": DocType, "member_name": name}) doc.insert() diff --git a/frappe/tests/test_form_load.py b/frappe/tests/test_form_load.py index 22db56eeef..83baf94b1c 100644 --- a/frappe/tests/test_form_load.py +++ b/frappe/tests/test_form_load.py @@ -31,7 +31,7 @@ class TestFormLoad(unittest.TestCase): "blog_intro": "Test Blog Intro", "blogger": "_Test Blogger 1", "content": "Test Blog Content", - "title": "_Test Blog Post {}".format(frappe.utils.now()), + "title": f"_Test Blog Post {frappe.utils.now()}", "published": 0, } ) diff --git a/frappe/tests/test_formatter.py b/frappe/tests/test_formatter.py index 1a195f9218..b34aa40e77 100644 --- a/frappe/tests/test_formatter.py +++ b/frappe/tests/test_formatter.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import unittest import frappe diff --git a/frappe/tests/test_frappe_client.py b/frappe/tests/test_frappe_client.py index 2cca251718..facb0b3b72 100644 --- a/frappe/tests/test_frappe_client.py +++ b/frappe/tests/test_frappe_client.py @@ -193,7 +193,7 @@ class TestFrappeClient(unittest.TestCase): ) api_key = frappe.db.get_value("User", "Administrator", "api_key") - header = {"Authorization": "token {}:{}".format(api_key, generated_secret)} + header = {"Authorization": f"token {api_key}:{generated_secret}"} res = requests.post(get_url() + "/api/method/frappe.auth.get_logged_user", headers=header) self.assertEqual(res.status_code, 200) @@ -202,7 +202,7 @@ class TestFrappeClient(unittest.TestCase): header = { "Authorization": "Basic {}".format( - base64.b64encode(frappe.safe_encode("{}:{}".format(api_key, generated_secret))).decode() + base64.b64encode(frappe.safe_encode(f"{api_key}:{generated_secret}")).decode() ) } res = requests.post(get_url() + "/api/method/frappe.auth.get_logged_user", headers=header) @@ -211,13 +211,13 @@ class TestFrappeClient(unittest.TestCase): # Valid api key, invalid api secret api_secret = "ksk&93nxoe3os" - header = {"Authorization": "token {}:{}".format(api_key, api_secret)} + header = {"Authorization": f"token {api_key}:{api_secret}"} res = requests.post(get_url() + "/api/method/frappe.auth.get_logged_user", headers=header) self.assertEqual(res.status_code, 403) # random api key and api secret api_key = "@3djdk3kld" api_secret = "ksk&93nxoe3os" - header = {"Authorization": "token {}:{}".format(api_key, api_secret)} + header = {"Authorization": f"token {api_key}:{api_secret}"} res = requests.post(get_url() + "/api/method/frappe.auth.get_logged_user", headers=header) self.assertEqual(res.status_code, 401) diff --git a/frappe/tests/test_monitor.py b/frappe/tests/test_monitor.py index 0c26ec0e28..48de913241 100644 --- a/frappe/tests/test_monitor.py +++ b/frappe/tests/test_monitor.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE diff --git a/frappe/tests/test_naming.py b/frappe/tests/test_naming.py index 305df66209..5feaad6f9b 100644 --- a/frappe/tests/test_naming.py +++ b/frappe/tests/test_naming.py @@ -139,16 +139,16 @@ class TestNaming(FrappeTestCase): week = determine_consecutive_week_number(now_datetime()) - self.assertEqual(todo.name, "TODO-{week}-{series}".format(week=week, series=series)) + self.assertEqual(todo.name, f"TODO-{week}-{series}") def test_revert_series(self): from datetime import datetime year = datetime.now().year - series = "TEST-{}-".format(year) + series = f"TEST-{year}-" key = "TEST-.YYYY.-" - name = "TEST-{}-00001".format(year) + name = f"TEST-{year}-00001" frappe.db.sql("""INSERT INTO `tabSeries` (name, current) values (%s, 1)""", (series,)) revert_series_if_last(key, name) current_index = frappe.db.sql( @@ -158,9 +158,9 @@ class TestNaming(FrappeTestCase): self.assertEqual(current_index.get("current"), 0) frappe.db.delete("Series", {"name": series}) - series = "TEST-{}-".format(year) + series = f"TEST-{year}-" key = "TEST-.YYYY.-.#####" - name = "TEST-{}-00002".format(year) + name = f"TEST-{year}-00002" frappe.db.sql("""INSERT INTO `tabSeries` (name, current) values (%s, 2)""", (series,)) revert_series_if_last(key, name) current_index = frappe.db.sql( @@ -235,11 +235,11 @@ class TestNaming(FrappeTestCase): amended_doc.docstatus = 0 amended_doc.amended_from = doc.name amended_doc.save() - self.assertEqual(amended_doc.name, "{}-1".format(original_name)) + self.assertEqual(amended_doc.name, f"{original_name}-1") amended_doc.submit() amended_doc.cancel() - self.assertEqual(amended_doc.name, "{}-1".format(original_name)) + self.assertEqual(amended_doc.name, f"{original_name}-1") submittable_doctype.delete() diff --git a/frappe/tests/test_permissions.py b/frappe/tests/test_permissions.py index 26d5c714ef..b4f0402a16 100644 --- a/frappe/tests/test_permissions.py +++ b/frappe/tests/test_permissions.py @@ -461,7 +461,7 @@ class TestPermissions(FrappeTestCase): self.assertIn( post.blogger, ["_Test Blogger", "_Test Blogger 1"], - "A post from {} is not expected.".format(post.blogger), + f"A post from {post.blogger} is not expected.", ) def test_if_owner_permission_overrides_properly(self): diff --git a/frappe/tests/test_query_builder.py b/frappe/tests/test_query_builder.py index 926bdedfbd..929a0ac451 100644 --- a/frappe/tests/test_query_builder.py +++ b/frappe/tests/test_query_builder.py @@ -1,5 +1,5 @@ import unittest -from typing import Callable +from collections.abc import Callable import frappe from frappe.query_builder import Case @@ -150,7 +150,7 @@ class TestCustomFunctionsPostgres(unittest.TestCase): ) -class TestBuilderBase(object): +class TestBuilderBase: def test_adding_tabs(self): self.assertEqual("tabNotes", frappe.qb.DocType("Notes").get_sql()) self.assertEqual("__Auth", frappe.qb.DocType("__Auth").get_sql()) @@ -186,9 +186,7 @@ class TestBuilderBase(object): class TestParameterization(unittest.TestCase): def test_where_conditions(self): DocType = frappe.qb.DocType("DocType") - query = ( - frappe.qb.from_(DocType).select(DocType.name).where((DocType.owner == "Administrator' --")) - ) + query = frappe.qb.from_(DocType).select(DocType.name).where(DocType.owner == "Administrator' --") self.assertTrue("walk" in dir(query)) query, params = query.walk() diff --git a/frappe/tests/test_rate_limiter.py b/frappe/tests/test_rate_limiter.py index 5cfe2694f6..90f69c502a 100644 --- a/frappe/tests/test_rate_limiter.py +++ b/frappe/tests/test_rate_limiter.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE diff --git a/frappe/tests/test_recorder.py b/frappe/tests/test_recorder.py index 94b97cb3a6..78ef49062b 100644 --- a/frappe/tests/test_recorder.py +++ b/frappe/tests/test_recorder.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - # Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE diff --git a/frappe/tests/test_rename_doc.py b/frappe/tests/test_rename_doc.py index 928953fe1c..f712965d67 100644 --- a/frappe/tests/test_rename_doc.py +++ b/frappe/tests/test_rename_doc.py @@ -6,7 +6,6 @@ import unittest from contextlib import contextmanager, redirect_stdout from io import StringIO from random import choice, sample -from typing import List from unittest.mock import patch import frappe @@ -23,7 +22,7 @@ from frappe.utils import add_to_date, now @contextmanager -def patch_db(endpoints: List[str] = None): +def patch_db(endpoints: list[str] = None): patched_endpoints = [] for point in endpoints: @@ -59,7 +58,7 @@ class TestRenameDoc(unittest.TestCase): { "doctype": self.test_doctype, "date": add_to_date(now(), days=num), - "description": "this is todo #{}".format(num), + "description": f"this is todo #{num}", } ).insert() self.available_documents.append(doc.name) diff --git a/frappe/tests/test_twofactor.py b/frappe/tests/test_twofactor.py index 82d39f40bb..d9bf982cd2 100644 --- a/frappe/tests/test_twofactor.py +++ b/frappe/tests/test_twofactor.py @@ -24,7 +24,7 @@ from . import get_system_setting, update_system_settings class TestTwoFactor(unittest.TestCase): def __init__(self, *args, **kwargs): - super(TestTwoFactor, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.default_allowed_login_attempts = get_system_setting("allow_consecutive_login_attempts") def setUp(self): @@ -60,7 +60,7 @@ class TestTwoFactor(unittest.TestCase): self.assertTrue(verification_obj) self.assertTrue(tmp_id) for k in ["_usr", "_pwd", "_otp_secret"]: - self.assertTrue(frappe.cache().get("{0}{1}".format(tmp_id, k)), "{} not available".format(k)) + self.assertTrue(frappe.cache().get(f"{tmp_id}{k}"), f"{k} not available") def test_two_factor_is_enabled(self): """ diff --git a/frappe/tests/test_utils.py b/frappe/tests/test_utils.py index 2a8d27cd19..e903c655b0 100644 --- a/frappe/tests/test_utils.py +++ b/frappe/tests/test_utils.py @@ -126,14 +126,14 @@ class TestMoney(unittest.TestCase): self.assertEqual( money_in_words(num[0], "BHD"), num[1], - "{0} is not the same as {1}".format(money_in_words(num[0], "BHD"), num[1]), + "{} is not the same as {}".format(money_in_words(num[0], "BHD"), num[1]), ) for num in nums_ngn: self.assertEqual( money_in_words(num[0], "NGN"), num[1], - "{0} is not the same as {1}".format(money_in_words(num[0], "NGN"), num[1]), + "{} is not the same as {}".format(money_in_words(num[0], "NGN"), num[1]), ) @@ -157,11 +157,11 @@ class TestDataManipulation(unittest.TestCase): url = get_url() self.assertTrue('Test link 1' in html) - self.assertTrue('Test link 2'.format(url) in html) - self.assertTrue('Test link 3'.format(url) in html) - self.assertTrue(''.format(url) in html) + self.assertTrue(f'Test link 2' in html) + self.assertTrue(f'Test link 3' in html) + self.assertTrue(f'' in html) self.assertTrue( - "style=\"background-image: url('{0}/assets/frappe/bg.jpg') !important\"".format(url) in html + f"style=\"background-image: url('{url}/assets/frappe/bg.jpg') !important\"" in html ) self.assertTrue('email' in html) @@ -304,7 +304,7 @@ class TestValidationUtils(unittest.TestCase): class TestImage(unittest.TestCase): def test_strip_exif_data(self): original_image = Image.open("../apps/frappe/frappe/tests/data/exif_sample_image.jpg") - original_image_content = io.open( + original_image_content = open( "../apps/frappe/frappe/tests/data/exif_sample_image.jpg", mode="rb" ).read() @@ -317,7 +317,7 @@ class TestImage(unittest.TestCase): def test_optimize_image(self): image_file_path = "../apps/frappe/frappe/tests/data/sample_image_for_optimization.jpg" content_type = guess_type(image_file_path)[0] - original_content = io.open(image_file_path, mode="rb").read() + original_content = open(image_file_path, mode="rb").read() optimized_content = optimize_image(original_content, content_type, max_width=500, max_height=500) optimized_image = Image.open(io.BytesIO(optimized_content)) diff --git a/frappe/tests/tests_geo_utils.py b/frappe/tests/tests_geo_utils.py index 2ac03e67e0..22ef74f721 100644 --- a/frappe/tests/tests_geo_utils.py +++ b/frappe/tests/tests_geo_utils.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/tests/ui_test_helpers.py b/frappe/tests/ui_test_helpers.py index 494ba8872d..92f4ca7eaf 100644 --- a/frappe/tests/ui_test_helpers.py +++ b/frappe/tests/ui_test_helpers.py @@ -86,7 +86,7 @@ def create_contact_phone_nos_records(): doc = frappe.new_doc("Contact") doc.first_name = "Test Contact" for index in range(1000): - doc.append("phone_nos", {"phone": "123456{}".format(index)}) + doc.append("phone_nos", {"phone": f"123456{index}"}) doc.insert() @@ -140,7 +140,7 @@ def create_multiple_todo_records(): if frappe.db.get_all("ToDo", {"description": "Multiple ToDo 1"}): return - values = [("100{}".format(i), "Multiple ToDo {}".format(i)) for i in range(1, 1002)] + values = [(f"100{i}", f"Multiple ToDo {i}") for i in range(1, 1002)] frappe.db.bulk_insert("ToDo", fields=["name", "description"], values=set(values)) diff --git a/frappe/translate.py b/frappe/translate.py index 5dbbbd31f2..dc1407cfdb 100644 --- a/frappe/translate.py +++ b/frappe/translate.py @@ -15,7 +15,6 @@ import operator import os import re from csv import reader -from typing import Dict, List, Optional, Tuple, Union from pypika.terms import PseudoColumn @@ -52,7 +51,7 @@ REPORT_TRANSLATE_PATTERN = re.compile('"([^:,^"]*):') CSV_STRIP_WHITESPACE_PATTERN = re.compile(r"{\s?([0-9]+)\s?}") -def get_language(lang_list: List = None) -> str: +def get_language(lang_list: list = None) -> str: """Set `frappe.local.lang` from HTTP headers at beginning of request Order of priority for setting language: @@ -102,7 +101,7 @@ def get_language(lang_list: List = None) -> str: return frappe.local.lang -@functools.lru_cache() +@functools.lru_cache def get_parent_language(lang: str) -> str: """If the passed language is a variant, return its parent @@ -134,7 +133,7 @@ def get_user_lang(user: str = None) -> str: return lang -def get_lang_code(lang: str) -> Union[str, None]: +def get_lang_code(lang: str) -> str | None: return frappe.db.get_value("Language", {"name": lang}) or frappe.db.get_value( "Language", {"language_name": lang} ) @@ -154,7 +153,7 @@ def get_lang_dict(): ) -def get_dict(fortype: str, name: Optional[str] = None) -> Dict: +def get_dict(fortype: str, name: str | None = None) -> dict: """Returns translation dict for a type of object. :param fortype: must be one of `doctype`, `page`, `report`, `include`, `jsfile`, `boot` @@ -205,7 +204,7 @@ def get_dict(fortype: str, name: Optional[str] = None) -> Dict: translation_assets[asset_key] = message_dict cache.hset("translation_assets", frappe.local.lang, translation_assets, shared=True) - translation_map: Dict = translation_assets[asset_key] + translation_map: dict = translation_assets[asset_key] translation_map.update(get_user_translations(frappe.local.lang)) @@ -680,7 +679,7 @@ def get_all_messages_from_js_files(app_name=None): return messages -def get_messages_from_file(path: str) -> List[Tuple[str, str, str, str]]: +def get_messages_from_file(path: str) -> list[tuple[str, str, str, str]]: """Returns a list of transatable strings from a code file :param path: path of the code file @@ -695,11 +694,11 @@ def get_messages_from_file(path: str) -> List[Tuple[str, str, str, str]]: bench_path = get_bench_path() if os.path.exists(path): - with open(path, "r") as sourcefile: + with open(path) as sourcefile: try: file_contents = sourcefile.read() except Exception: - print("Could not scan file for translation: {0}".format(path)) + print(f"Could not scan file for translation: {path}") return [] return [ @@ -722,7 +721,7 @@ def extract_messages_from_code(code): code = frappe.as_unicode(render_include(code)) # Exception will occur when it encounters John Resig's microtemplating code - except (TemplateError, ImportError, InvalidIncludePath, IOError) as e: + except (TemplateError, ImportError, InvalidIncludePath, OSError) as e: if isinstance(e, InvalidIncludePath): frappe.clear_last_message() @@ -769,7 +768,7 @@ def read_csv_file(path): :param path: File path""" - with io.open(path, mode="r", encoding="utf-8", newline="") as msgfile: + with open(path, encoding="utf-8", newline="") as msgfile: data = reader(msgfile) newdata = [[val for val in row] for row in data] diff --git a/frappe/twofactor.py b/frappe/twofactor.py index c803a5ff87..55c27e2bac 100644 --- a/frappe/twofactor.py +++ b/frappe/twofactor.py @@ -90,8 +90,8 @@ def cache_2fa_data(user, token, otp_secret, tmp_id): else: expiry_time = frappe.flags.otp_expiry or 180 for k, v in {"_usr": user, "_pwd": pwd, "_otp_secret": otp_secret}.items(): - frappe.cache().set("{0}{1}".format(tmp_id, k), v) - frappe.cache().expire("{0}{1}".format(tmp_id, k), expiry_time) + frappe.cache().set(f"{tmp_id}{k}", v) + frappe.cache().expire(f"{tmp_id}{k}", expiry_time) def two_factor_is_enabled_for_(user): @@ -287,14 +287,14 @@ def get_email_body_for_qr_code(kwargs_dict): def get_link_for_qrcode(user, totp_uri): """Get link to temporary page showing QRCode.""" key = frappe.generate_hash(length=20) - key_user = "{}_user".format(key) - key_uri = "{}_uri".format(key) + key_user = f"{key}_user" + key_uri = f"{key}_uri" lifespan = ( int(frappe.db.get_value("System Settings", "System Settings", "lifespan_qrcode_image")) or 240 ) frappe.cache().set_value(key_uri, totp_uri, expires_in_sec=lifespan) frappe.cache().set_value(key_user, user, expires_in_sec=lifespan) - return get_url("/qrcode?k={}".format(key)) + return get_url(f"/qrcode?k={key}") def send_token_via_sms(otpsecret, token=None, phone_no=None): @@ -312,7 +312,7 @@ def send_token_via_sms(otpsecret, token=None, phone_no=None): return False hotp = pyotp.HOTP(otpsecret) - args = {ss.message_parameter: "Your verification code is {}".format(hotp.at(int(token)))} + args = {ss.message_parameter: f"Your verification code is {hotp.at(int(token))}"} for d in ss.get("parameters"): args[d.parameter] = d.value @@ -328,7 +328,7 @@ def send_token_via_sms(otpsecret, token=None, phone_no=None): is_async=True, job_name=None, now=False, - **sms_args + **sms_args, ) return True @@ -364,7 +364,7 @@ def send_token_via_email(user, token, otp_secret, otp_issuer, subject=None, mess is_async=True, job_name=None, now=False, - **email_args + **email_args, ) return True @@ -386,7 +386,7 @@ def get_qr_svg_code(totp_uri): def qrcode_as_png(user, totp_uri): """Save temporary Qrcode to server.""" folder = create_barcode_folder() - png_file_name = "{}.png".format(frappe.generate_hash(length=20)) + png_file_name = f"{frappe.generate_hash(length=20)}.png" _file = frappe.get_doc( { "doctype": "File", @@ -484,7 +484,7 @@ def reset_otp_secret(user): is_async=True, job_name=None, now=False, - **email_args + **email_args, ) return frappe.msgprint( _("OTP Secret has been reset. Re-registration will be required on next login.") diff --git a/frappe/utils/__init__.py b/frappe/utils/__init__.py index 6872ace7d8..82e1cb3510 100644 --- a/frappe/utils/__init__.py +++ b/frappe/utils/__init__.py @@ -9,12 +9,10 @@ import os import re import sys import traceback -import typing -from collections.abc import MutableMapping, MutableSequence, Sequence +from collections.abc import Generator, Iterable, MutableMapping, MutableSequence, Sequence from email.header import decode_header, make_header from email.utils import formataddr, parseaddr from gzip import GzipFile -from typing import Generator, Iterable from urllib.parse import quote, urlparse from redis.exceptions import ConnectionError @@ -265,7 +263,7 @@ def has_gravatar(email): hexdigest = hashlib.md5(frappe.as_unicode(email).encode("utf-8")).hexdigest() - gravatar_url = "https://secure.gravatar.com/avatar/{hash}?d=404&s=200".format(hash=hexdigest) + gravatar_url = f"https://secure.gravatar.com/avatar/{hexdigest}?d=404&s=200" try: res = requests.get(gravatar_url) if res.status_code == 200: @@ -489,7 +487,7 @@ def get_request_site_address(full_address=False): def get_site_url(site): - return "http://{site}:{port}".format(site=site, port=frappe.get_conf(site).webserver_port) + return f"http://{site}:{frappe.get_conf(site).webserver_port}" def encode_dict(d, encoding="utf-8"): @@ -507,7 +505,7 @@ def decode_dict(d, encoding="utf-8"): return d -@functools.lru_cache() +@functools.lru_cache def get_site_name(hostname): return hostname.split(":")[0] @@ -517,7 +515,7 @@ def get_disk_usage(): files_path = get_files_path() if not os.path.exists(files_path): return 0 - err, out = execute_in_shell("du -hsm {files_path}".format(files_path=files_path)) + err, out = execute_in_shell(f"du -hsm {files_path}") return cint(out.split("\n")[-2].split("\t")[0]) @@ -584,21 +582,21 @@ def update_progress_bar(txt, i, l): complete = int(float(i + 1) / l * col) completion_bar = ("=" * complete).ljust(col, " ") percent_complete = str(int(float(i + 1) / l * 100)) - sys.stdout.write("\r{0}: [{1}] {2}%".format(txt, completion_bar, percent_complete)) + sys.stdout.write(f"\r{txt}: [{completion_bar}] {percent_complete}%") sys.stdout.flush() def get_html_format(print_path): html_format = None if os.path.exists(print_path): - with open(print_path, "r") as f: + with open(print_path) as f: html_format = f.read() for include_directive, path in INCLUDE_DIRECTIVE_PATTERN.findall(html_format): for app_name in frappe.get_installed_apps(): include_path = frappe.get_app_path(app_name, *path.split(os.path.sep)) if os.path.exists(include_path): - with open(include_path, "r") as f: + with open(include_path) as f: html_format = html_format.replace(include_directive, f.read()) break @@ -904,10 +902,10 @@ def get_file_size(path, format=False): for unit in ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"]: if abs(num) < 1024: - return "{0:3.1f}{1}{2}".format(num, unit, suffix) + return f"{num:3.1f}{unit}{suffix}" num /= 1024 - return "{0:.1f}{1}{2}".format(num, "Yi", suffix) + return "{:.1f}{}{}".format(num, "Yi", suffix) def get_build_version(): @@ -962,13 +960,13 @@ def get_bench_relative_path(file_path): file_path = os.path.join(base_path, file_path) if not os.path.exists(file_path): - print("Invalid path {0}".format(file_path[3:])) + print(f"Invalid path {file_path[3:]}") sys.exit(1) return os.path.abspath(file_path) -def groupby_metric(iterable: typing.Dict[str, list], key: str): +def groupby_metric(iterable: dict[str, list], key: str): """Group records by a metric. Usecase: Lets assume we got country wise players list with the ranking given for each player(multiple players in a country can have same ranking aswell). diff --git a/frappe/utils/background_jobs.py b/frappe/utils/background_jobs.py index a7956717d4..3d3df3504d 100755 --- a/frappe/utils/background_jobs.py +++ b/frappe/utils/background_jobs.py @@ -3,7 +3,7 @@ import socket import time from collections import defaultdict from functools import lru_cache -from typing import TYPE_CHECKING, List +from typing import TYPE_CHECKING from uuid import uuid4 import redis @@ -23,7 +23,7 @@ if TYPE_CHECKING: from rq.job import Job -@lru_cache() +@lru_cache def get_queues_timeout(): common_site_config = frappe.get_conf() custom_workers_config = common_site_config.get("workers", {}) @@ -333,7 +333,7 @@ def get_redis_conn(username=None, password=None): return redis_connection -def get_queues() -> List[Queue]: +def get_queues() -> list[Queue]: """Get all the queues linked to the current bench.""" queues = Queue.all(connection=get_redis_conn()) return [q for q in queues if is_queue_accessible(q)] diff --git a/frappe/utils/backups.py b/frappe/utils/backups.py index 85826b4ce7..e6068fd299 100644 --- a/frappe/utils/backups.py +++ b/frappe/utils/backups.py @@ -103,14 +103,12 @@ class BackupGenerator: if self.backup_path: os.makedirs(self.backup_path, exist_ok=True) - for file_path in set( - [ - self.backup_path_files, - self.backup_path_db, - self.backup_path_private_files, - self.backup_path_conf, - ] - ): + for file_path in { + self.backup_path_files, + self.backup_path_db, + self.backup_path_private_files, + self.backup_path_conf, + }: if file_path: dir = os.path.dirname(file_path) os.makedirs(dir, exist_ok=True) @@ -337,13 +335,13 @@ class BackupGenerator: def print_summary(self): backup_summary = self.get_summary() - print("Backup Summary for {0} at {1}".format(frappe.local.site, now())) + print(f"Backup Summary for {frappe.local.site} at {now()}") title = max(len(x) for x in backup_summary) path = max(len(x["path"]) for x in backup_summary.values()) for _type, info in backup_summary.items(): - template = "{{0:{0}}}: {{1:{1}}} {{2}}".format(title, path) + template = f"{{0:{title}}}: {{1:{path}}} {{2}}" print(template.format(_type.title(), info["path"], info["size"])) def backup_files(self): @@ -417,12 +415,10 @@ class BackupGenerator: if self.db_type == "postgres": if self.backup_includes: - args["include"] = " ".join( - ["--table='public.\"{0}\"'".format(table) for table in self.backup_includes] - ) + args["include"] = " ".join([f"--table='public.\"{table}\"'" for table in self.backup_includes]) elif self.backup_excludes: args["exclude"] = " ".join( - ["--exclude-table-data='public.\"{0}\"'".format(table) for table in self.backup_excludes] + [f"--exclude-table-data='public.\"{table}\"'" for table in self.backup_excludes] ) cmd_string = ( @@ -432,13 +428,10 @@ class BackupGenerator: else: if self.backup_includes: - args["include"] = " ".join(["'{0}'".format(x) for x in self.backup_includes]) + args["include"] = " ".join([f"'{x}'" for x in self.backup_includes]) elif self.backup_excludes: args["exclude"] = " ".join( - [ - "--ignore-table='{0}.{1}'".format(frappe.conf.db_name, table) - for table in self.backup_excludes - ] + [f"--ignore-table='{frappe.conf.db_name}.{table}'" for table in self.backup_excludes] ) cmd_string = ( @@ -479,14 +472,14 @@ class BackupGenerator: Your backups are ready to be downloaded. -1. [Click here to download the database backup](%(db_backup_url)s) -2. [Click here to download the files backup](%(files_backup_url)s) +1. [Click here to download the database backup]({db_backup_url}) +2. [Click here to download the files backup]({files_backup_url}) This link will be valid for 24 hours. A new backup will be available for -download only after 24 hours.""" % { - "db_backup_url": db_backup_url, - "files_backup_url": files_backup_url, - } +download only after 24 hours.""".format( + db_backup_url=db_backup_url, + files_backup_url=files_backup_url, + ) datetime_str = datetime.fromtimestamp(os.stat(self.backup_path_db).st_ctime) subject = datetime_str.strftime("%d/%m/%Y %H:%M:%S") + """ - Backup ready to be downloaded""" diff --git a/frappe/utils/boilerplate.py b/frappe/utils/boilerplate.py index bd4cff9ef9..503ee6d338 100644 --- a/frappe/utils/boilerplate.py +++ b/frappe/utils/boilerplate.py @@ -110,7 +110,7 @@ def _create_app_boilerplate(dest, hooks, no_git=False): with open(os.path.join(dest, hooks.app_name, "README.md"), "w") as f: f.write( frappe.as_unicode( - "## {0}\n\n{1}\n\n#### License\n\n{2}".format( + "## {}\n\n{}\n\n#### License\n\n{}".format( hooks.app_title, hooks.app_description, hooks.app_license ) ) diff --git a/frappe/utils/caching.py b/frappe/utils/caching.py index 326dacfd5a..a2c9496098 100644 --- a/frappe/utils/caching.py +++ b/frappe/utils/caching.py @@ -5,14 +5,14 @@ import json from collections import defaultdict from datetime import datetime, timedelta from functools import wraps -from typing import Callable, Dict, Optional, Tuple +from typing import Callable import frappe _SITE_CACHE = defaultdict(lambda: defaultdict(dict)) -def __generate_request_cache_key(args: Tuple, kwargs: Dict): +def __generate_request_cache_key(args: tuple, kwargs: dict): """Generate a key for the cache.""" if not kwargs: return hash(args) @@ -61,7 +61,7 @@ def request_cache(func: Callable) -> Callable: return wrapper -def site_cache(ttl: Optional[int] = None, maxsize: Optional[int] = None) -> Callable: +def site_cache(ttl: int | None = None, maxsize: int | None = None) -> Callable: """Decorator to cache method calls across requests. The cache is stored in frappe.utils.caching._SITE_CACHE. The cache persists on the parent process. It offers a light-weight cache for the current process without the additional diff --git a/frappe/utils/change_log.py b/frappe/utils/change_log.py index 95a17f9dc1..12069cce09 100644 --- a/frappe/utils/change_log.py +++ b/frappe/utils/change_log.py @@ -65,9 +65,7 @@ def get_change_log_for_app(app, from_version, to_version): # remove pre-release part to_version.prerelease = None - major_version_folders = [ - "v{0}".format(i) for i in range(from_version.major, to_version.major + 1) - ] + major_version_folders = [f"v{i}" for i in range(from_version.major, to_version.major + 1)] app_change_log = [] for folder in os.listdir(change_log_folder): @@ -119,9 +117,9 @@ def get_versions(): } if versions[app]["branch"] != "master": - branch_version = app_hooks.get("{0}_version".format(versions[app]["branch"])) + branch_version = app_hooks.get("{}_version".format(versions[app]["branch"])) if branch_version: - versions[app]["branch_version"] = branch_version[0] + " ({0})".format( + versions[app]["branch_version"] = branch_version[0] + " ({})".format( get_app_last_commit_ref(app) ) @@ -238,9 +236,7 @@ def check_release_on_github(app: str): try: # Check if repo remote is on github - remote_url = subprocess.check_output( - "cd ../apps/{} && git ls-remote --get-url".format(app), shell=True - ) + remote_url = subprocess.check_output(f"cd ../apps/{app} && git ls-remote --get-url", shell=True) except subprocess.CalledProcessError: # Passing this since some apps may not have git initialized in them return @@ -305,7 +301,7 @@ def show_update_popup(): if release_links: message = _("New {} releases for the following apps are available").format(_(update_type)) update_message += ( - "
    {0}
    ".format( + "
    {}
    ".format( message, release_links ) ) diff --git a/frappe/utils/connections.py b/frappe/utils/connections.py index bf0a338681..6660e6ce19 100644 --- a/frappe/utils/connections.py +++ b/frappe/utils/connections.py @@ -13,7 +13,7 @@ def is_open(ip, port, timeout=10): s.connect((ip, int(port))) s.shutdown(socket.SHUT_RDWR) return True - except socket.error: + except OSError: return False finally: s.close() diff --git a/frappe/utils/csvutils.py b/frappe/utils/csvutils.py index 9d32712454..4840c806bb 100644 --- a/frappe/utils/csvutils.py +++ b/frappe/utils/csvutils.py @@ -188,7 +188,7 @@ def get_csv_content_from_google_sheets(url): # remove /edit path url = url.rsplit("/edit", 1)[0] # add /export path, - url = url + "/export?format=csv&gid={0}".format(gid) + url = url + f"/export?format=csv&gid={gid}" headers = {"Accept": "text/csv"} response = requests.get(url, headers=headers) diff --git a/frappe/utils/dashboard.py b/frappe/utils/dashboard.py index ad1f391831..6acd63274e 100644 --- a/frappe/utils/dashboard.py +++ b/frappe/utils/dashboard.py @@ -21,7 +21,7 @@ def cache_source(function): if no_cache: return function(chart=chart, no_cache=no_cache) chart_name = frappe.parse_json(chart).name - cache_key = "chart-data:{}".format(chart_name) + cache_key = f"chart-data:{chart_name}" if int(kwargs.get("refresh") or 0): results = generate_and_cache_results(kwargs, function, cache_key, chart) else: @@ -93,7 +93,7 @@ def sync_dashboards(app=None): apps = frappe.get_installed_apps() for app_name in apps: - print("Updating Dashboard for {app}".format(app=app_name)) + print(f"Updating Dashboard for {app_name}") for module_name in frappe.local.app_modules.get(app_name) or []: frappe.flags.in_import = True make_records_in_module(app_name, module_name) @@ -101,7 +101,7 @@ def sync_dashboards(app=None): def make_records_in_module(app, module): - dashboards_path = frappe.get_module_path(module, "{module}_dashboard".format(module=module)) + dashboards_path = frappe.get_module_path(module, f"{module}_dashboard") charts_path = frappe.get_module_path(module, "dashboard chart") cards_path = frappe.get_module_path(module, "number card") diff --git a/frappe/utils/data.py b/frappe/utils/data.py index 20c9dabfbf..7f590ed5e6 100644 --- a/frappe/utils/data.py +++ b/frappe/utils/data.py @@ -11,7 +11,7 @@ import time import typing from code import compile_command from enum import Enum -from typing import Any, Dict, List, Literal, Optional, Tuple, TypeVar, Union +from typing import Any, Literal, Optional, TypeVar, Union from urllib.parse import quote, urljoin from click import secho @@ -72,7 +72,7 @@ def is_invalid_date_string(date_string: str) -> bool: ) -def getdate(string_date: Optional["DateTimeLikeObject"] = None) -> Optional[datetime.date]: +def getdate(string_date: Optional["DateTimeLikeObject"] = None) -> datetime.date | None: """ Converts string date (yyyy-mm-dd) to datetime.date object. If no input is provided, current date is returned. @@ -101,7 +101,7 @@ def getdate(string_date: Optional["DateTimeLikeObject"] = None) -> Optional[date def get_datetime( datetime_str: Optional["DateTimeLikeObject"] = None, -) -> Optional[datetime.datetime]: +) -> datetime.datetime | None: from dateutil import parser if datetime_str is None: @@ -125,7 +125,7 @@ def get_datetime( return parser.parse(datetime_str) -def get_timedelta(time: Optional[str] = None) -> Optional[datetime.timedelta]: +def get_timedelta(time: str | None = None) -> datetime.timedelta | None: """Return `datetime.timedelta` object from string value of a valid time format. Returns None if `time` is not a valid format @@ -157,7 +157,7 @@ def get_timedelta(time: Optional[str] = None) -> Optional[datetime.timedelta]: return None -def to_timedelta(time_str: Union[str, datetime.time]) -> datetime.timedelta: +def to_timedelta(time_str: str | datetime.time) -> datetime.timedelta: from dateutil import parser if isinstance(time_str, datetime.time): @@ -393,7 +393,7 @@ def get_first_day(dt, d_years=0, d_months=0, as_str: Literal[True] = False) -> s # TODO: first arg def get_first_day( dt, d_years: int = 0, d_months: int = 0, as_str: bool = False -) -> Union[str, datetime.date]: +) -> str | datetime.date: """ Returns the first day of the month for the date specified by date object Also adds `d_years` and `d_months` if specified @@ -421,7 +421,7 @@ def get_quarter_start(dt, as_str: Literal[True] = False) -> str: ... -def get_quarter_start(dt, as_str: bool = False) -> Union[str, datetime.date]: +def get_quarter_start(dt, as_str: bool = False) -> str | datetime.date: date = getdate(dt) quarter = (date.month - 1) // 3 + 1 first_date_of_quarter = datetime.date(date.year, ((quarter - 1) * 3) + 1, 1) @@ -474,7 +474,7 @@ def get_quarter_ending(date): # find the earliest quarter ending date that is after # the given date for month in (3, 6, 9, 12): - quarter_end_month = getdate("{}-{}-01".format(date.year, month)) + quarter_end_month = getdate(f"{date.year}-{month}-01") quarter_end_date = getdate(get_last_day(quarter_end_month)) if date <= quarter_end_date: date = quarter_end_date @@ -487,7 +487,7 @@ def get_year_ending(date): """returns year ending of the given date""" date = getdate(date) # first day of next year (note year starts from 1) - date = add_to_date("{}-01-01".format(date.year), months=12) + date = add_to_date(f"{date.year}-01-01", months=12) # last day of this month return add_to_date(date, days=-1) @@ -528,7 +528,7 @@ def get_time_str(timedelta_obj) -> str: hours, remainder = divmod(timedelta_obj.seconds, 3600) minutes, seconds = divmod(remainder, 60) - return "{0}:{1}:{2}".format(hours, minutes, seconds) + return f"{hours}:{minutes}:{seconds}" def get_user_date_format() -> str: @@ -550,7 +550,7 @@ def get_user_time_format() -> str: return frappe.local.user_time_format or "HH:mm:ss" -def format_date(string_date=None, format_string: Optional[str] = None) -> str: +def format_date(string_date=None, format_string: str | None = None) -> str: """Converts the given string date to :data:`user_date_format` User format specified in defaults @@ -583,7 +583,7 @@ def format_date(string_date=None, format_string: Optional[str] = None) -> str: formatdate = format_date # For backwards compatibility -def format_time(time_string=None, format_string: Optional[str] = None) -> str: +def format_time(time_string=None, format_string: str | None = None) -> str: """Converts the given string time to :data:`user_time_format` User format specified in defaults @@ -610,9 +610,7 @@ def format_time(time_string=None, format_string: Optional[str] = None) -> str: return formatted_time -def format_datetime( - datetime_string: DateTimeLikeObject, format_string: Optional[str] = None -) -> str: +def format_datetime(datetime_string: DateTimeLikeObject, format_string: str | None = None) -> str: """Converts the given string time to :data:`user_datetime_format` User format specified in defaults @@ -719,14 +717,14 @@ def get_weekdays(): return ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] -def get_weekday(datetime: Optional[datetime.datetime] = None) -> str: +def get_weekday(datetime: datetime.datetime | None = None) -> str: if not datetime: datetime = now_datetime() weekdays = get_weekdays() return weekdays[datetime.weekday()] -def get_timespan_date_range(timespan: str) -> Tuple[datetime.datetime, datetime.datetime]: +def get_timespan_date_range(timespan: str) -> tuple[datetime.datetime, datetime.datetime]: today = nowdate() date_range_map = { "last week": lambda: ( @@ -886,16 +884,16 @@ def cast(fieldtype, value=None): @typing.overload -def flt(s: Union[NumericType, str], precision: Literal[0]) -> int: +def flt(s: NumericType | str, precision: Literal[0]) -> int: ... @typing.overload -def flt(s: Union[NumericType, str], precision: Optional[int] = None) -> float: +def flt(s: NumericType | str, precision: int | None = None) -> float: ... -def flt(s: Union[NumericType, str], precision: Optional[int] = None) -> float: +def flt(s: NumericType | str, precision: int | None = None) -> float: """Convert to float (ignoring commas in string) :param s: Number in string or other numeric format. @@ -928,7 +926,7 @@ def flt(s: Union[NumericType, str], precision: Optional[int] = None) -> float: return num -def cint(s: Union[NumericType, str], default: int = 0) -> int: +def cint(s: NumericType | str, default: int = 0) -> int: """Convert to integer :param s: Number in string or other numeric format. @@ -997,7 +995,7 @@ def cstr(s, encoding="utf-8"): return frappe.as_unicode(s, encoding) -def sbool(x: str) -> Union[bool, Any]: +def sbool(x: str) -> bool | Any: """Converts str object to Boolean if possible. Example: "true" becomes True @@ -1113,10 +1111,10 @@ def parse_val(v): def fmt_money( - amount: Union[str, float, int], - precision: Optional[int] = None, - currency: Optional[str] = None, - format: Optional[str] = None, + amount: str | float | int, + precision: int | None = None, + currency: str | None = None, + format: str | None = None, ) -> str: """ Convert to string with commas for thousands, millions etc @@ -1206,7 +1204,7 @@ number_format_info = { } -def get_number_format_info(format: str) -> Tuple[str, str, int]: +def get_number_format_info(format: str) -> tuple[str, str, int]: return number_format_info.get(format) or (".", ",", 2) @@ -1214,9 +1212,9 @@ def get_number_format_info(format: str) -> Tuple[str, str, int]: # convert currency to words # def money_in_words( - number: Union[str, float, int], - main_currency: Optional[str] = None, - fraction_currency: Optional[str] = None, + number: str | float | int, + main_currency: str | None = None, + fraction_currency: str | None = None, ): """ Returns string in words with currency and fraction currency. @@ -1251,7 +1249,7 @@ def money_in_words( fraction_length = get_number_format_info(number_format)[2] - n = "%.{0}f".format(fraction_length) % number + n = f"%.{fraction_length}f" % number numbers = n.split(".") main, fraction = numbers if len(numbers) > 1 else [n, "00"] @@ -1266,7 +1264,7 @@ def money_in_words( # 0.00 if main == "0" and fraction in ["00", "000"]: - out = "{0} {1}".format(main_currency, _("Zero")) + out = "{} {}".format(main_currency, _("Zero")) # 0.XX elif main == "0": out = _(in_words(fraction, in_million).title()) + " " + fraction_currency @@ -1329,7 +1327,7 @@ def get_thumbnail_base64_for_image(src): from frappe.core.doctype.file.utils import get_local_image if not src: - frappe.throw("Invalid source for image: {0}".format(src)) + frappe.throw(f"Invalid source for image: {src}") if not src.startswith("/files") or ".." in src: return @@ -1344,7 +1342,7 @@ def get_thumbnail_base64_for_image(src): try: image, unused_filename, extn = get_local_image(src) - except IOError: + except OSError: return original_size = image.size @@ -1353,7 +1351,7 @@ def get_thumbnail_base64_for_image(src): base64_string = image_to_base64(image, extn) return { - "base64": "data:image/{0};base64,{1}".format(extn, safe_decode(base64_string)), + "base64": f"data:image/{extn};base64,{safe_decode(base64_string)}", "width": original_size[0], "height": original_size[1], } @@ -1372,7 +1370,7 @@ def image_to_base64(image, extn: str) -> bytes: return img_str -def pdf_to_base64(filename: str) -> Optional[bytes]: +def pdf_to_base64(filename: str) -> bytes | None: from frappe.utils.file_manager import get_file_path if "../" in filename or filename.rsplit(".")[-1] not in ["pdf", "PDF"]: @@ -1412,7 +1410,7 @@ def escape_html(text: str) -> str: return "".join(html_escape_table.get(c, c) for c in text) -def pretty_date(iso_datetime: Union[datetime.datetime, str]) -> str: +def pretty_date(iso_datetime: datetime.datetime | str) -> str: """ Takes an ISO time and returns a string representing how long ago the date represents. @@ -1462,7 +1460,7 @@ def pretty_date(iso_datetime: Union[datetime.datetime, str]) -> str: elif dt_diff_days < 550.0: return _("1 year ago") else: - return "{0} years ago".format(cint(math.floor(dt_diff_days / 365.0))) + return f"{cint(math.floor(dt_diff_days / 365.0))} years ago" def comma_or(some_list, add_quotes=True): @@ -1503,12 +1501,12 @@ def new_line_sep(some_list): return some_list -def filter_strip_join(some_list: List[str], sep: str) -> List[str]: +def filter_strip_join(some_list: list[str], sep: str) -> list[str]: """given a list, filter None values, strip spaces and join""" - return (cstr(sep)).join((cstr(a).strip() for a in filter(None, some_list))) + return (cstr(sep)).join(cstr(a).strip() for a in filter(None, some_list)) -def get_url(uri: Optional[str] = None, full_address: bool = False) -> str: +def get_url(uri: str | None = None, full_address: bool = False) -> str: """get app url from request""" host_name = frappe.local.conf.host_name or frappe.local.conf.hostname @@ -1582,19 +1580,19 @@ def get_host_name() -> str: return get_url().rsplit("//", 1)[-1] -def get_link_to_form(doctype: str, name: str, label: Optional[str] = None) -> str: +def get_link_to_form(doctype: str, name: str, label: str | None = None) -> str: if not label: label = name - return """{1}""".format(get_url_to_form(doctype, name), label) + return f"""{label}""" def get_link_to_report( name: str, - label: Optional[str] = None, - report_type: Optional[str] = None, - doctype: Optional[str] = None, - filters: Optional[Dict] = None, + label: str | None = None, + report_type: str | None = None, + doctype: str | None = None, + filters: dict | None = None, ) -> str: if not label: label = name @@ -1612,39 +1610,37 @@ def get_link_to_report( filters = "&".join(conditions) - return """{1}""".format( + return """{}""".format( get_url_to_report_with_filters(name, filters, report_type, doctype), label ) else: - return """{1}""".format(get_url_to_report(name, report_type, doctype), label) + return f"""{label}""" def get_absolute_url(doctype: str, name: str) -> str: - return "/app/{0}/{1}".format(quoted(slug(doctype)), quoted(name)) + return f"/app/{quoted(slug(doctype))}/{quoted(name)}" def get_url_to_form(doctype: str, name: str) -> str: - return get_url(uri="/app/{0}/{1}".format(quoted(slug(doctype)), quoted(name))) + return get_url(uri=f"/app/{quoted(slug(doctype))}/{quoted(name)}") def get_url_to_list(doctype: str) -> str: - return get_url(uri="/app/{0}".format(quoted(slug(doctype)))) + return get_url(uri=f"/app/{quoted(slug(doctype))}") -def get_url_to_report( - name, report_type: Optional[str] = None, doctype: Optional[str] = None -) -> str: +def get_url_to_report(name, report_type: str | None = None, doctype: str | None = None) -> str: if report_type == "Report Builder": - return get_url(uri="/app/{0}/view/report/{1}".format(quoted(slug(doctype)), quoted(name))) + return get_url(uri=f"/app/{quoted(slug(doctype))}/view/report/{quoted(name)}") else: - return get_url(uri="/app/query-report/{0}".format(quoted(name))) + return get_url(uri=f"/app/query-report/{quoted(name)}") def get_url_to_report_with_filters(name, filters, report_type=None, doctype=None): if report_type == "Report Builder": - return get_url(uri="/app/{0}/view/report?{1}".format(quoted(doctype), filters)) + return get_url(uri=f"/app/{quoted(doctype)}/view/report?{filters}") else: - return get_url(uri="/app/query-report/{0}?{1}".format(quoted(name), filters)) + return get_url(uri=f"/app/query-report/{quoted(name)}?{filters}") operator_map = { @@ -1665,7 +1661,7 @@ operator_map = { } -def evaluate_filters(doc, filters: Union[Dict, List, Tuple]): +def evaluate_filters(doc, filters: dict | list | tuple): """Returns true if doc matches filters""" if isinstance(filters, dict): for key, value in filters.items(): @@ -1682,7 +1678,7 @@ def evaluate_filters(doc, filters: Union[Dict, List, Tuple]): return True -def compare(val1: Any, condition: str, val2: Any, fieldtype: Optional[str] = None): +def compare(val1: Any, condition: str, val2: Any, fieldtype: str | None = None): ret = False if fieldtype: val2 = cast(fieldtype, val2) @@ -1692,7 +1688,7 @@ def compare(val1: Any, condition: str, val2: Any, fieldtype: Optional[str] = Non return ret -def get_filter(doctype: str, f: Union[Dict, List, Tuple], filters_config=None) -> "frappe._dict": +def get_filter(doctype: str, f: dict | list | tuple, filters_config=None) -> "frappe._dict": """Returns a _dict like { @@ -1825,7 +1821,7 @@ def sanitize_column(column_name: str) -> None: if "ifnull" in column_name: if regex.match(column_name): # to avoid and, or - if any(" {0} ".format(keyword) in column_name.split() for keyword in blacklisted_keywords): + if any(f" {keyword} " in column_name.split() for keyword in blacklisted_keywords): _raise_exception() # to avoid select, delete, drop, update and case @@ -1881,7 +1877,7 @@ def quote_urls(html: str) -> str: return URLS_HTTP_TAG_PATTERN.sub(_quote_url, html) -def unique(seq: typing.Sequence["T"]) -> List["T"]: +def unique(seq: typing.Sequence["T"]) -> list["T"]: """use this instead of list(set()) to preserve order of the original list. Thanks to Stackoverflow: http://stackoverflow.com/questions/480214/how-do-you-remove-duplicates-from-a-list-in-python-whilst-preserving-order""" @@ -1890,7 +1886,7 @@ def unique(seq: typing.Sequence["T"]) -> List["T"]: return [x for x in seq if not (x in seen or seen_add(x))] -def strip(val: str, chars: Optional[str] = None) -> str: +def strip(val: str, chars: str | None = None) -> str: # \ufeff is no-width-break, \u200b is no-width-space return (val or "").replace("\ufeff", "").replace("\u200b", "").strip(chars) @@ -1938,7 +1934,7 @@ def markdown(markdown_text): return md_to_html(markdown_text) -def is_subset(list_a: List, list_b: List) -> bool: +def is_subset(list_a: list, list_b: list) -> bool: """Returns whether list_a is a subset of list_b""" return len(list(set(list_a) & set(list_b))) == len(list_a) @@ -2032,7 +2028,7 @@ def validate_json_string(string: str) -> None: class _UserInfo(typing.TypedDict): email: str - image: Optional[str] + image: str | None name: str @@ -2047,7 +2043,7 @@ def get_user_info_for_avatar(user_id: str) -> _UserInfo: def validate_python_code( - string: str, fieldname: Optional[str] = None, is_expression: bool = True + string: str, fieldname: str | None = None, is_expression: bool = True ) -> None: """Validate python code fields by using compile_command to ensure that expression is valid python. @@ -2099,7 +2095,7 @@ def format_timedelta(o: datetime.timedelta) -> str: else: seconds = rounded_seconds - return "{:01}:{:02}:{:02}".format(int(hours), int(minutes), seconds) + return f"{int(hours):01}:{int(minutes):02}:{seconds:02}" def parse_timedelta(s: str) -> datetime.timedelta: diff --git a/frappe/utils/dateutils.py b/frappe/utils/dateutils.py index d7412a444f..ca147744d4 100644 --- a/frappe/utils/dateutils.py +++ b/frappe/utils/dateutils.py @@ -42,7 +42,7 @@ def user_to_str(date, date_format=None): try: return datetime.datetime.strptime(date, dateformats[date_format]).strftime("%Y-%m-%d") except ValueError: - raise ValueError("Date %s must be in format %s" % (date, date_format)) + raise ValueError(f"Date {date} must be in format {date_format}") def parse_date(date): diff --git a/frappe/utils/diff.py b/frappe/utils/diff.py index 02fa1ef4c7..2fbe555e12 100644 --- a/frappe/utils/diff.py +++ b/frappe/utils/diff.py @@ -1,6 +1,5 @@ import json from difflib import unified_diff -from typing import List, Union import frappe from frappe.utils import pretty_date @@ -9,8 +8,8 @@ from frappe.utils.data import cstr @frappe.whitelist() def get_version_diff( - from_version: Union[int, str], to_version: Union[int, str], fieldname: str = "script" -) -> List[str]: + from_version: int | str, to_version: int | str, fieldname: str = "script" +) -> list[str]: before, before_timestamp = _get_value_from_version(from_version, fieldname) after, after_timestamp = _get_value_from_version(to_version, fieldname) @@ -32,7 +31,7 @@ def get_version_diff( return list(diff) -def _get_value_from_version(version_name: Union[int, str], fieldname: str): +def _get_value_from_version(version_name: int | str, fieldname: str): version = frappe.get_list("Version", fields=["data", "modified"], filters={"name": version_name}) if version: data = json.loads(version[0].data) diff --git a/frappe/utils/doctor.py b/frappe/utils/doctor.py index a474ffc612..5b12a01990 100644 --- a/frappe/utils/doctor.py +++ b/frappe/utils/doctor.py @@ -74,7 +74,7 @@ def get_pending_jobs(site=None): for job in q.jobs: method_kwargs = job.kwargs["kwargs"] if job.kwargs["kwargs"] else "" if job.kwargs["site"] == site: - jobs_per_queue[queue].append("{0} {1}".format(job.kwargs["method"], method_kwargs)) + jobs_per_queue[queue].append("{} {}".format(job.kwargs["method"], method_kwargs)) return jobs_per_queue @@ -122,14 +122,14 @@ def doctor(site=None): # TODO improve this print("Workers online:", workers_online) - print("-----{0} Jobs-----".format(site)) + print(f"-----{site} Jobs-----") for queue in get_queue_list(): if jobs_per_queue[queue]: print("Queue:", queue) print("Number of Jobs: ", job_count[queue]) print("Methods:") for method, count in jobs_per_queue[queue].items(): - print("{0} : {1}".format(method, count)) + print(f"{method} : {count}") print("------------") return True @@ -140,5 +140,5 @@ def pending_jobs(site=None): pending_jobs = get_pending_jobs(site) for queue in get_queue_list(): if pending_jobs[queue]: - print("-----Queue :{0}-----".format(queue)) + print(f"-----Queue :{queue}-----") print("\n".join(pending_jobs[queue])) diff --git a/frappe/utils/error.py b/frappe/utils/error.py index bc369eccad..94b3cf3b2c 100644 --- a/frappe/utils/error.py +++ b/frappe/utils/error.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Maxwell Morais and contributors # License: MIT. See LICENSE @@ -32,16 +31,16 @@ def make_error_snapshot(exception): snapshot_folder = get_error_snapshot_path() frappe.create_folder(snapshot_folder) - snapshot_file_path = os.path.join(snapshot_folder, "{0}.json".format(error_id)) + snapshot_file_path = os.path.join(snapshot_folder, f"{error_id}.json") snapshot = get_snapshot(exception) with open(encode(snapshot_file_path), "wb") as error_file: error_file.write(encode(frappe.as_json(snapshot))) - logger.error("New Exception collected with id: {}".format(error_id)) + logger.error(f"New Exception collected with id: {error_id}") except Exception as e: - logger.error("Could not take error snapshot: {0}".format(e), exc_info=True) + logger.error(f"Could not take error snapshot: {e}", exc_info=True) def get_snapshot(exception, context=10): @@ -78,7 +77,7 @@ def get_snapshot(exception, context=10): if func != "?": call = inspect.formatargvalues( - args, varargs, varkw, locals, formatvalue=lambda value: "={}".format(pydoc.text.repr(value)) + args, varargs, varkw, locals, formatvalue=lambda value: f"={pydoc.text.repr(value)}" ) # basic frame information @@ -112,7 +111,7 @@ def get_snapshot(exception, context=10): continue if value is not cgitb.__UNDEF__: if where == "global": - name = "global {name:s}".format(name=name) + name = f"global {name:s}" elif where != "local": name = where + " " + name.split(".")[-1] f["dump"][name] = pydoc.text.repr(value) @@ -149,7 +148,7 @@ def collect_error_snapshots(): fullpath = os.path.join(path, fname) try: - with open(fullpath, "r") as filedata: + with open(fullpath) as filedata: data = json.load(filedata) except ValueError: diff --git a/frappe/utils/file_manager.py b/frappe/utils/file_manager.py index 620962004a..875ca10c63 100644 --- a/frappe/utils/file_manager.py +++ b/frappe/utils/file_manager.py @@ -209,9 +209,9 @@ def save_file_on_filesystem(fname, content, content_type=None, is_private=0): fpath = write_file(content, fname, is_private) if is_private: - file_url = "/private/files/{0}".format(fname) + file_url = f"/private/files/{fname}" else: - file_url = "/files/{0}".format(fname) + file_url = f"/files/{fname}" return {"file_name": os.path.basename(fpath), "file_url": file_url} @@ -342,7 +342,7 @@ def get_file(fname): file_path = get_file_path(fname) # read the file - with io.open(encode(file_path), mode="rb") as f: + with open(encode(file_path), mode="rb") as f: content = f.read() try: # for plain text files @@ -405,7 +405,7 @@ def get_file_name(fname, optional_suffix): partial, extn = f[0], "" else: partial, extn = f[0], "." + f[1] - return "{partial}{suffix}{extn}".format(partial=partial, extn=extn, suffix=optional_suffix) + return f"{partial}{optional_suffix}{extn}" return fname diff --git a/frappe/utils/fixtures.py b/frappe/utils/fixtures.py index 42e86e9f11..6b3166bfe6 100644 --- a/frappe/utils/fixtures.py +++ b/frappe/utils/fixtures.py @@ -58,9 +58,7 @@ def export_fixtures(app=None): filters = fixture.get("filters") or_filters = fixture.get("or_filters") fixture = fixture.get("doctype") or fixture.get("dt") - print( - "Exporting {0} app {1} filters {2}".format(fixture, app, (filters if filters else or_filters)) - ) + print(f"Exporting {fixture} app {app} filters {(filters if filters else or_filters)}") if not os.path.exists(frappe.get_app_path(app, "fixtures")): os.mkdir(frappe.get_app_path(app, "fixtures")) diff --git a/frappe/utils/formatters.py b/frappe/utils/formatters.py index 575a05a5c2..12b3ee11be 100644 --- a/frappe/utils/formatters.py +++ b/frappe/utils/formatters.py @@ -96,7 +96,7 @@ def format_value(value, df=None, doc=None, currency=None, translated=False, form return fmt_money(value, precision=precision, currency=currency) elif df.get("fieldtype") == "Percent": - return "{}%".format(flt(value, 2)) + return f"{flt(value, 2)}%" elif df.get("fieldtype") in ("Text", "Small Text"): if not BLOCK_TAGS_PATTERN.search(value): @@ -121,7 +121,7 @@ def format_value(value, df=None, doc=None, currency=None, translated=False, form return format_duration(value, hide_days) elif df.get("fieldtype") == "Text Editor": - return "
    {}
    ".format(value) + return f"
    {value}
    " elif df.get("fieldtype") in ["Link", "Dynamic Link"]: if not doc or not doc.get("__link_titles") or not df.options: @@ -136,6 +136,6 @@ def format_value(value, df=None, doc=None, currency=None, translated=False, form _field = meta.get_field(df.options) doctype = _field.options - return doc.__link_titles.get("{0}::{1}".format(doctype, value), value) + return doc.__link_titles.get(f"{doctype}::{value}", value) return value diff --git a/frappe/utils/global_search.py b/frappe/utils/global_search.py index af6d9a3c28..14dcc0fdda 100644 --- a/frappe/utils/global_search.py +++ b/frappe/utils/global_search.py @@ -223,12 +223,12 @@ def insert_values_for_multiple_docs(all_contents): { "mariadb": """INSERT IGNORE INTO `__global_search` (doctype, name, content, published, title, route) - VALUES {0} """.format( + VALUES {} """.format( ", ".join(batch_values) ), "postgres": """INSERT INTO `__global_search` (doctype, name, content, published, title, route) - VALUES {0} + VALUES {} ON CONFLICT("name", "doctype") DO NOTHING""".format( ", ".join(batch_values) ), diff --git a/frappe/utils/goal.py b/frappe/utils/goal.py index fb348496da..fe8c2399a4 100644 --- a/frappe/utils/goal.py +++ b/frappe/utils/goal.py @@ -2,7 +2,6 @@ # License: MIT. See LICENSE from contextlib import suppress -from typing import Dict, Optional import frappe from frappe import _ @@ -16,9 +15,9 @@ def get_monthly_results( goal_doctype: str, goal_field: str, date_col: str, - filters: Dict, + filters: dict, aggregation: str = "sum", -) -> Dict: +) -> dict: """Get monthly aggregation values for given field of doctype""" Table = DocType(goal_doctype) @@ -49,8 +48,8 @@ def get_monthly_goal_graph_data( date_field: str, filter_str: str = None, aggregation: str = "sum", - filters: Optional[Dict] = None, -) -> Dict: + filters: dict | None = None, +) -> dict: """ Get month-wise graph data for a doctype based on aggregation values of a field in the goal doctype diff --git a/frappe/utils/identicon.py b/frappe/utils/identicon.py index 448f24657c..1267b8f9c3 100644 --- a/frappe/utils/identicon.py +++ b/frappe/utils/identicon.py @@ -10,7 +10,7 @@ BORDER_SIZE = 20 SQUARE_SIZE = 40 -class Identicon(object): +class Identicon: def __init__(self, str_, background="#fafbfc"): """ `str_` is the string used to generate the identicon. @@ -104,4 +104,4 @@ class Identicon(object): save_handler(self.image, fp, "") finally: fp.seek(0) - return "data:image/png;base64,{0}".format(base64.b64encode(fp.read())) # noqa + return f"data:image/png;base64,{base64.b64encode(fp.read())}" # noqa diff --git a/frappe/utils/image.py b/frappe/utils/image.py index 8823ea3dfe..11d9a86c4f 100644 --- a/frappe/utils/image.py +++ b/frappe/utils/image.py @@ -17,7 +17,7 @@ def resize_images(path, maxdim=700): im.thumbnail(size, Image.Resampling.LANCZOS) im.save(os.path.join(basepath, fname)) - print("resized {0}".format(os.path.join(basepath, fname))) + print(f"resized {os.path.join(basepath, fname)}") def strip_exif_data(content, content_type): diff --git a/frappe/utils/jinja.py b/frappe/utils/jinja.py index c7902e7096..5e3a70554d 100644 --- a/frappe/utils/jinja.py +++ b/frappe/utils/jinja.py @@ -56,7 +56,7 @@ def validate_template(html): try: jenv.from_string(html) except TemplateSyntaxError as e: - frappe.msgprint("Line {}: {}".format(e.lineno, e.message)) + frappe.msgprint(f"Line {e.lineno}: {e.message}") frappe.throw(frappe._("Syntax error in template")) @@ -86,7 +86,7 @@ def render_template(template, context, is_path=None, safe_render=True): except TemplateError: throw( title="Jinja Template Error", - msg="
    {template}
    {tb}
    ".format(template=template, tb=get_traceback()), + msg=f"
    {template}
    {get_traceback()}
    ", ) @@ -117,7 +117,7 @@ def get_jloader(): frappe.local.jloader = ChoiceLoader( # search for something like app/templates/... - [PrefixLoader(dict((app, PackageLoader(app, ".")) for app in apps))] + [PrefixLoader({app: PackageLoader(app, ".") for app in apps})] # search for something like templates/... + [PackageLoader(app, ".") for app in apps] ) diff --git a/frappe/utils/logger.py b/frappe/utils/logger.py index f2ce8a14c3..461204371e 100755 --- a/frappe/utils/logger.py +++ b/frappe/utils/logger.py @@ -41,7 +41,7 @@ def get_logger( else: site = False - logger_name = "{0}-{1}".format(module, site or "all") + logger_name = "{}-{}".format(module, site or "all") try: return frappe.loggers[logger_name] @@ -59,7 +59,7 @@ def get_logger( logger.setLevel(frappe.log_level or default_log_level) logger.propagate = False - formatter = logging.Formatter("%(asctime)s %(levelname)s {0} %(message)s".format(module)) + formatter = logging.Formatter(f"%(asctime)s %(levelname)s {module} %(message)s") if stream_only: handler = logging.StreamHandler() else: @@ -91,7 +91,7 @@ class SiteContextFilter(logging.Filter): if "Form Dict" not in str(record.msg): site = getattr(frappe.local, "site", None) form_dict = getattr(frappe.local, "form_dict", None) - record.msg = str(record.msg) + "\nSite: {0}\nForm Dict: {1}".format(site, form_dict) + record.msg = str(record.msg) + f"\nSite: {site}\nForm Dict: {form_dict}" return True diff --git a/frappe/utils/make_random.py b/frappe/utils/make_random.py index 41d6f89d72..1915cbb620 100644 --- a/frappe/utils/make_random.py +++ b/frappe/utils/make_random.py @@ -33,7 +33,7 @@ def get_random(doctype, filters=None, doc=False): condition = [] if filters: for key, val in filters.items(): - condition.append("%s='%s'" % (key, str(val).replace("'", "'"))) + condition.append("{}='{}'".format(key, str(val).replace("'", "'"))) if condition: condition = " where " + " and ".join(condition) else: diff --git a/frappe/utils/nestedset.py b/frappe/utils/nestedset.py index 681cd6439d..222f670e0f 100644 --- a/frappe/utils/nestedset.py +++ b/frappe/utils/nestedset.py @@ -10,7 +10,7 @@ # 3. call update_nsm(doc_obj) in the on_upate method # ------------------------------------------ -from typing import Iterator +from collections.abc import Iterator import frappe from frappe import _ diff --git a/frappe/utils/oauth.py b/frappe/utils/oauth.py index 9e7138cbbd..042fa24a8b 100644 --- a/frappe/utils/oauth.py +++ b/frappe/utils/oauth.py @@ -47,7 +47,7 @@ def get_oauth_keys(provider): """get client_id and client_secret from database or conf""" # try conf - keys = frappe.conf.get("{provider}_login".format(provider=provider)) + keys = frappe.conf.get(f"{provider}_login") if not keys: # try database @@ -100,7 +100,7 @@ def get_oauth2_flow(provider): def get_redirect_uri(provider): - keys = frappe.conf.get("{provider}_login".format(provider=provider)) + keys = frappe.conf.get(f"{provider}_login") if keys and keys.get("redirect_uri"): # this should be a fully qualified redirect uri @@ -223,7 +223,7 @@ def login_oauth_user( if frappe.utils.cint(generate_login_token): login_token = frappe.generate_hash(length=32) frappe.cache().set_value( - "login_token:{0}".format(login_token), frappe.local.session.sid, expires_in_sec=120 + f"login_token:{login_token}", frappe.local.session.sid, expires_in_sec=120 ) frappe.response["login_token"] = login_token diff --git a/frappe/utils/password.py b/frappe/utils/password.py index c539891ac7..9a2aa04bf7 100644 --- a/frappe/utils/password.py +++ b/frappe/utils/password.py @@ -29,7 +29,7 @@ class LegacyPassword(pbkdf2_sha256): secret[0] == "*" and len(secret) == 41 and all(c in string.hexdigits for c in secret[1:]) ): secret = mysql41.hash(secret + self.salt.decode("utf-8")) - return super(LegacyPassword, self)._calc_checksum(secret) + return super()._calc_checksum(secret) register_crypt_handler(LegacyPassword, force=True) diff --git a/frappe/utils/pdf.py b/frappe/utils/pdf.py index ddab2f2b18..678671bce2 100644 --- a/frappe/utils/pdf.py +++ b/frappe/utils/pdf.py @@ -5,7 +5,6 @@ import os import re import subprocess from distutils.version import LooseVersion -from typing import Optional import pdfkit from bs4 import BeautifulSoup @@ -24,7 +23,7 @@ PDF_CONTENT_ERRORS = [ ] -def get_pdf(html, options=None, output: Optional[PdfWriter] = None): +def get_pdf(html, options=None, output: PdfWriter | None = None): html = scrub_urls(html) html, options = prepare_options(html, options) @@ -135,13 +134,13 @@ def get_cookie_options(): options = {} if frappe.session and frappe.session.sid and hasattr(frappe.local, "request"): # Use wkhtmltopdf's cookie-jar feature to set cookies and restrict them to host domain - cookiejar = "/tmp/{}.jar".format(frappe.generate_hash()) + cookiejar = f"/tmp/{frappe.generate_hash()}.jar" # Remove port from request.host # https://werkzeug.palletsprojects.com/en/0.16.x/wrappers/#werkzeug.wrappers.BaseRequest.host domain = frappe.utils.get_host_name().split(":", 1)[0] with open(cookiejar, "w") as f: - f.write("sid={}; Domain={};\n".format(frappe.session.sid, domain)) + f.write(f"sid={frappe.session.sid}; Domain={domain};\n") options["cookie-jar"] = cookiejar @@ -211,7 +210,7 @@ def prepare_header_footer(soup): ) # create temp file - fname = os.path.join("/tmp", "frappe-pdf-{0}.html".format(frappe.generate_hash())) + fname = os.path.join("/tmp", f"frappe-pdf-{frappe.generate_hash()}.html") with open(fname, "wb") as f: f.write(html.encode("utf-8")) diff --git a/frappe/utils/print_format.py b/frappe/utils/print_format.py index a48d7ab84f..03d564b16c 100644 --- a/frappe/utils/print_format.py +++ b/frappe/utils/print_format.py @@ -96,11 +96,11 @@ def download_multi_pdf(doctype, name, format=None, no_letterhead=False, options= except Exception: frappe.log_error( title="Error in Multi PDF download", - message="Permission Error on doc {} of doctype {}".format(doc_name, doctype_name), + message=f"Permission Error on doc {doc_name} of doctype {doctype_name}", reference_doctype=doctype_name, reference_name=doc_name, ) - frappe.local.response.filename = "{}.pdf".format(name) + frappe.local.response.filename = f"{name}.pdf" frappe.local.response.filecontent = read_multi_pdf(output) frappe.local.response.type = "download" @@ -108,7 +108,7 @@ def download_multi_pdf(doctype, name, format=None, no_letterhead=False, options= def read_multi_pdf(output): # Get the content of the merged pdf files - fname = os.path.join("/tmp", "frappe-pdf-{0}.pdf".format(frappe.generate_hash())) + fname = os.path.join("/tmp", f"frappe-pdf-{frappe.generate_hash()}.pdf") output.write(open(fname, "wb")) with open(fname, "rb") as fileobj: @@ -157,10 +157,10 @@ def print_by_server( doctype, name, print_format, doc=doc, no_letterhead=no_letterhead, as_pdf=True, output=output ) if not file_path: - file_path = os.path.join("/", "tmp", "frappe-pdf-{0}.pdf".format(frappe.generate_hash())) + file_path = os.path.join("/", "tmp", f"frappe-pdf-{frappe.generate_hash()}.pdf") output.write(open(file_path, "wb")) conn.printFile(print_settings.printer_name, file_path, name, {}) - except IOError as e: + except OSError as e: if ( "ContentNotFoundError" in e.message or "ContentOperationNotPermittedError" in e.message diff --git a/frappe/utils/redis_wrapper.py b/frappe/utils/redis_wrapper.py index c29836af32..a41e47b0c6 100644 --- a/frappe/utils/redis_wrapper.py +++ b/frappe/utils/redis_wrapper.py @@ -26,9 +26,9 @@ class RedisWrapper(redis.Redis): if user is True: user = frappe.session.user - key = "user:{0}:{1}".format(user, key) + key = f"user:{user}:{key}" - return "{0}|{1}".format(frappe.conf.db_name, key).encode("utf-8") + return f"{frappe.conf.db_name}|{key}".encode() def set_value(self, key, val, user=None, expires_in_sec=None, shared=False, cache_locally=True): """Sets cache value. @@ -128,25 +128,25 @@ class RedisWrapper(redis.Redis): pass def lpush(self, key, value): - super(RedisWrapper, self).lpush(self.make_key(key), value) + super().lpush(self.make_key(key), value) def rpush(self, key, value): - super(RedisWrapper, self).rpush(self.make_key(key), value) + super().rpush(self.make_key(key), value) def lpop(self, key): - return super(RedisWrapper, self).lpop(self.make_key(key)) + return super().lpop(self.make_key(key)) def rpop(self, key): - return super(RedisWrapper, self).rpop(self.make_key(key)) + return super().rpop(self.make_key(key)) def llen(self, key): - return super(RedisWrapper, self).llen(self.make_key(key)) + return super().llen(self.make_key(key)) def lrange(self, key, start, stop): - return super(RedisWrapper, self).lrange(self.make_key(key), start, stop) + return super().lrange(self.make_key(key), start, stop) def ltrim(self, key, start, stop): - return super(RedisWrapper, self).ltrim(self.make_key(key), start, stop) + return super().ltrim(self.make_key(key), start, stop) def hset(self, name: str, key: str, value, shared: bool = False, cache_locally: bool = True): if key is None: @@ -160,7 +160,7 @@ class RedisWrapper(redis.Redis): # set in redis try: - super(RedisWrapper, self).hset(_name, key, pickle.dumps(value)) + super().hset(_name, key, pickle.dumps(value)) except redis.exceptions.ConnectionError: pass @@ -169,12 +169,12 @@ class RedisWrapper(redis.Redis): return False _name = self.make_key(name, shared=shared) try: - return super(RedisWrapper, self).hexists(_name, key) + return super().hexists(_name, key) except redis.exceptions.ConnectionError: return False def hgetall(self, name): - value = super(RedisWrapper, self).hgetall(self.make_key(name)) + value = super().hgetall(self.make_key(name)) return {key: pickle.loads(value) for key, value in value.items()} def hget(self, name, key, generator=None, shared=False): @@ -190,7 +190,7 @@ class RedisWrapper(redis.Redis): value = None try: - value = super(RedisWrapper, self).hget(_name, key) + value = super().hget(_name, key) except redis.exceptions.ConnectionError: pass @@ -209,7 +209,7 @@ class RedisWrapper(redis.Redis): if key in frappe.local.cache[_name]: del frappe.local.cache[_name][key] try: - super(RedisWrapper, self).hdel(_name, key) + super().hdel(_name, key) except redis.exceptions.ConnectionError: pass @@ -221,30 +221,30 @@ class RedisWrapper(redis.Redis): def hkeys(self, name): try: - return super(RedisWrapper, self).hkeys(self.make_key(name)) + return super().hkeys(self.make_key(name)) except redis.exceptions.ConnectionError: return [] def sadd(self, name, *values): """Add a member/members to a given set""" - super(RedisWrapper, self).sadd(self.make_key(name), *values) + super().sadd(self.make_key(name), *values) def srem(self, name, *values): """Remove a specific member/list of members from the set""" - super(RedisWrapper, self).srem(self.make_key(name), *values) + super().srem(self.make_key(name), *values) def sismember(self, name, value): """Returns True or False based on if a given value is present in the set""" - return super(RedisWrapper, self).sismember(self.make_key(name), value) + return super().sismember(self.make_key(name), value) def spop(self, name): """Removes and returns a random member from the set""" - return super(RedisWrapper, self).spop(self.make_key(name)) + return super().spop(self.make_key(name)) def srandmember(self, name, count=None): """Returns a random member from the set""" - return super(RedisWrapper, self).srandmember(self.make_key(name)) + return super().srandmember(self.make_key(name)) def smembers(self, name): """Return all members of the set""" - return super(RedisWrapper, self).smembers(self.make_key(name)) + return super().smembers(self.make_key(name)) diff --git a/frappe/utils/response.py b/frappe/utils/response.py index 80aeaa2ad0..ed2cee6208 100644 --- a/frappe/utils/response.py +++ b/frappe/utils/response.py @@ -96,7 +96,7 @@ def as_raw(): ) response.headers["Content-Disposition"] = ( f'{frappe.response.get("display_content_as","attachment")}; filename="{frappe.response["filename"].replace(" ", "_")}"' - ).encode("utf-8") + ).encode() response.data = frappe.response["filecontent"] return response @@ -184,7 +184,7 @@ def json_handler(obj): else: raise TypeError( - """Object of type %s with value of %s is not JSON serializable""" % (type(obj), repr(obj)) + f"""Object of type {type(obj)} with value of {repr(obj)} is not JSON serializable""" ) @@ -246,7 +246,7 @@ def send_private_file(path: str) -> Response: filepath = frappe.utils.get_site_path(path) try: f = open(filepath, "rb") - except IOError: + except OSError: raise NotFound response = Response(wrap_file(frappe.local.request.environ, f), direct_passthrough=True) diff --git a/frappe/utils/safe_exec.py b/frappe/utils/safe_exec.py index b29ae848aa..9136df1062 100644 --- a/frappe/utils/safe_exec.py +++ b/frappe/utils/safe_exec.py @@ -347,7 +347,7 @@ def _getattr(object, name, default=None): } if isinstance(name, str) and (name in UNSAFE_ATTRIBUTES): - raise SyntaxError("{name} is an unsafe attribute".format(name=name)) + raise SyntaxError(f"{name} is an unsafe attribute") return RestrictedPython.Guards.safer_getattr(object, name, default=default) diff --git a/frappe/utils/scheduler.py b/frappe/utils/scheduler.py index 48826b13c6..23b4949c38 100755 --- a/frappe/utils/scheduler.py +++ b/frappe/utils/scheduler.py @@ -60,12 +60,12 @@ def enqueue_events_for_all_sites(): try: enqueue_events_for_site(site=site) except Exception as e: - print(e.__class__, "Failed to enqueue events for site: {}".format(site)) + print(e.__class__, f"Failed to enqueue events for site: {site}") def enqueue_events_for_site(site): def log_and_raise(): - error_message = "Exception in Enqueue Events for Site {0}\n{1}".format( + error_message = "Exception in Enqueue Events for Site {}\n{}".format( site, frappe.get_traceback() ) frappe.logger("scheduler").error(error_message) @@ -78,10 +78,10 @@ def enqueue_events_for_site(site): enqueue_events(site=site) - frappe.logger("scheduler").debug("Queued events for site {0}".format(site)) + frappe.logger("scheduler").debug(f"Queued events for site {site}") except frappe.db.OperationalError as e: if frappe.db.is_access_denied(e): - frappe.logger("scheduler").debug("Access denied for site {0}".format(site)) + frappe.logger("scheduler").debug(f"Access denied for site {site}") else: log_and_raise() except Exception: diff --git a/frappe/utils/user.py b/frappe/utils/user.py index 308ab85f05..a9bec0affa 100644 --- a/frappe/utils/user.py +++ b/frappe/utils/user.py @@ -2,7 +2,7 @@ # License: MIT. See LICENSE from email.utils import formataddr -from typing import TYPE_CHECKING, Dict, List, Optional +from typing import TYPE_CHECKING import frappe import frappe.share @@ -284,7 +284,7 @@ def get_fullname_and_avatar(user: str) -> _dict: ) -def get_system_managers(only_name: bool = False) -> List[str]: +def get_system_managers(only_name: bool = False) -> list[str]: """returns all system manager's user details""" HasRole = DocType("Has Role") User = DocType("User") @@ -297,7 +297,7 @@ def get_system_managers(only_name: bool = False) -> List[str]: system_managers = ( frappe.qb.from_(User) .join(HasRole) - .on((HasRole.parent == User.name)) + .on(HasRole.parent == User.name) .where( (HasRole.parenttype == "User") & (User.enabled == 1) @@ -322,8 +322,8 @@ def add_role(user: str, role: str) -> None: def add_system_manager( email: str, - first_name: Optional[str] = None, - last_name: Optional[str] = None, + first_name: str | None = None, + last_name: str | None = None, send_welcome_email: bool = False, password: str = None, ) -> "User": @@ -359,7 +359,7 @@ def add_system_manager( return user -def get_enabled_system_users() -> List[Dict]: +def get_enabled_system_users() -> list[dict]: return frappe.get_all( "User", fields=["email", "language", "name"], @@ -371,11 +371,11 @@ def get_enabled_system_users() -> List[Dict]: ) -def is_website_user(username: Optional[str] = None) -> Optional[str]: +def is_website_user(username: str | None = None) -> str | None: return frappe.db.get_value("User", username or frappe.session.user, "user_type") == "Website User" -def is_system_user(username: Optional[str] = None) -> Optional[str]: +def is_system_user(username: str | None = None) -> str | None: return frappe.db.get_value( "User", { @@ -386,7 +386,7 @@ def is_system_user(username: Optional[str] = None) -> Optional[str]: ) -def get_users() -> List[Dict]: +def get_users() -> list[dict]: from frappe.core.doctype.user.user import get_system_users users = [] @@ -404,7 +404,7 @@ def get_users() -> List[Dict]: return users -def get_users_with_role(role: str) -> List[str]: +def get_users_with_role(role: str) -> list[str]: User = DocType("User") HasRole = DocType("Has Role") diff --git a/frappe/utils/verified_command.py b/frappe/utils/verified_command.py index e342ef1810..f46c8a8e73 100644 --- a/frappe/utils/verified_command.py +++ b/frappe/utils/verified_command.py @@ -62,7 +62,7 @@ def get_url(cmd, params, nonce=None, secret=None): def get_signature(params, nonce, secret=None): - params = "".join((frappe.utils.cstr(p) for p in params.values())) + params = "".join(frappe.utils.cstr(p) for p in params.values()) if not secret: secret = frappe.local.conf.get("secret") or "secret" diff --git a/frappe/website/doctype/__init__.py b/frappe/website/doctype/__init__.py index 8b13789179..e69de29bb2 100644 --- a/frappe/website/doctype/__init__.py +++ b/frappe/website/doctype/__init__.py @@ -1 +0,0 @@ - diff --git a/frappe/website/doctype/about_us_settings/test_about_us_settings.py b/frappe/website/doctype/about_us_settings/test_about_us_settings.py index a4b2da7718..6477d7fcf7 100644 --- a/frappe/website/doctype/about_us_settings/test_about_us_settings.py +++ b/frappe/website/doctype/about_us_settings/test_about_us_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/website/doctype/blog_post/blog_post.py b/frappe/website/doctype/blog_post/blog_post.py index 2f5d8e4ace..e411931694 100644 --- a/frappe/website/doctype/blog_post/blog_post.py +++ b/frappe/website/doctype/blog_post/blog_post.py @@ -37,7 +37,7 @@ class BlogPost(WebsiteGenerator): return self.title def validate(self): - super(BlogPost, self).validate() + super().validate() if not self.blog_intro: content = get_html_content_based_on_type(self, "content", self.content_type) @@ -73,11 +73,11 @@ class BlogPost(WebsiteGenerator): frappe.db.set_value("Blog Post", post.name, "featured", 0) def on_update(self): - super(BlogPost, self).on_update() + super().on_update() clear_cache("writers") def on_trash(self): - super(BlogPost, self).on_trash() + super().on_trash() def get_context(self, context): # this is for double precaution. usually it wont reach this code if not published @@ -317,13 +317,13 @@ def get_blog_list( from `tabBlog Post` t1, `tabBlogger` t2 where ifnull(t1.published,0)=1 and t1.blogger = t2.name - %(condition)s + {condition} order by featured desc, published_on desc, name asc - limit %(page_len)s OFFSET %(start)s""" % { - "start": limit_start, - "page_len": limit_page_length, - "condition": (" and " + " and ".join(conditions)) if conditions else "", - } + limit {page_len} OFFSET {start}""".format( + start=limit_start, + page_len=limit_page_length, + condition=(" and " + " and ".join(conditions)) if conditions else "", + ) posts = frappe.db.sql(query, as_dict=1) diff --git a/frappe/website/doctype/blog_settings/test_blog_settings.py b/frappe/website/doctype/blog_settings/test_blog_settings.py index 23607812fb..c4be6e270e 100644 --- a/frappe/website/doctype/blog_settings/test_blog_settings.py +++ b/frappe/website/doctype/blog_settings/test_blog_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/website/doctype/color/color.py b/frappe/website/doctype/color/color.py index 4d822d6b69..f720e86314 100644 --- a/frappe/website/doctype/color/color.py +++ b/frappe/website/doctype/color/color.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/website/doctype/color/test_color.py b/frappe/website/doctype/color/test_color.py index 2fd1cf1ba8..1b1e8c0774 100644 --- a/frappe/website/doctype/color/test_color.py +++ b/frappe/website/doctype/color/test_color.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/website/doctype/help_article/test_help_article.py b/frappe/website/doctype/help_article/test_help_article.py index e7dec4080c..3cbd5ceb22 100644 --- a/frappe/website/doctype/help_article/test_help_article.py +++ b/frappe/website/doctype/help_article/test_help_article.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/website/doctype/help_category/test_help_category.py b/frappe/website/doctype/help_category/test_help_category.py index de7d288555..443cacfd3b 100644 --- a/frappe/website/doctype/help_category/test_help_category.py +++ b/frappe/website/doctype/help_category/test_help_category.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/website/doctype/personal_data_deletion_request/personal_data_deletion_request.py b/frappe/website/doctype/personal_data_deletion_request/personal_data_deletion_request.py index 45c1a5ad38..edeb44f015 100644 --- a/frappe/website/doctype/personal_data_deletion_request/personal_data_deletion_request.py +++ b/frappe/website/doctype/personal_data_deletion_request/personal_data_deletion_request.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -392,4 +391,4 @@ def confirm_deletion(email, name, host_name): def get_pattern(full_match): - return re.compile(r"(?
    " - + "
    ".join("{0} ({1})".format(d.label, d.fieldtype) for d in missing) + + "
    ".join(f"{d.label} ({d.fieldtype})" for d in missing) ) def allow_website_search_indexing(self): @@ -671,4 +671,4 @@ def get_link_options(web_form_name, doctype, allow_read_on_all_link_options=Fals return "\n".join([doc.value for doc in link_options]) else: - raise frappe.PermissionError("Not Allowed, {0}".format(doctype)) + raise frappe.PermissionError(f"Not Allowed, {doctype}") diff --git a/frappe/website/doctype/web_page/__init__.py b/frappe/website/doctype/web_page/__init__.py index 8b13789179..e69de29bb2 100644 --- a/frappe/website/doctype/web_page/__init__.py +++ b/frappe/website/doctype/web_page/__init__.py @@ -1 +0,0 @@ - diff --git a/frappe/website/doctype/web_page/web_page.py b/frappe/website/doctype/web_page/web_page.py index fb94dc9165..a94838baed 100644 --- a/frappe/website/doctype/web_page/web_page.py +++ b/frappe/website/doctype/web_page/web_page.py @@ -33,10 +33,10 @@ class WebPage(WebsiteGenerator): return self.title def on_update(self): - super(WebPage, self).on_update() + super().on_update() def on_trash(self): - super(WebPage, self).on_trash() + super().on_trash() def get_context(self, context): context.main_section = get_html_content_based_on_type(self, "main_section", self.content_type) diff --git a/frappe/website/doctype/web_page_block/web_page_block.py b/frappe/website/doctype/web_page_block/web_page_block.py index 790ab98b6a..e700986739 100644 --- a/frappe/website/doctype/web_page_block/web_page_block.py +++ b/frappe/website/doctype/web_page_block/web_page_block.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/website/doctype/web_page_view/test_web_page_view.py b/frappe/website/doctype/web_page_view/test_web_page_view.py index 3f1d86ada4..d573402a08 100644 --- a/frappe/website/doctype/web_page_view/test_web_page_view.py +++ b/frappe/website/doctype/web_page_view/test_web_page_view.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/website/doctype/web_page_view/web_page_view.py b/frappe/website/doctype/web_page_view/web_page_view.py index b1e64980d9..7417f2d290 100644 --- a/frappe/website/doctype/web_page_view/web_page_view.py +++ b/frappe/website/doctype/web_page_view/web_page_view.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/website/doctype/web_template/test_web_template.py b/frappe/website/doctype/web_template/test_web_template.py index 2d2d7faf36..b31d11e01f 100644 --- a/frappe/website/doctype/web_template/test_web_template.py +++ b/frappe/website/doctype/web_template/test_web_template.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/website/doctype/web_template/web_template.py b/frappe/website/doctype/web_template/web_template.py index 93b469fe96..a21affafc9 100644 --- a/frappe/website/doctype/web_template/web_template.py +++ b/frappe/website/doctype/web_template/web_template.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -97,7 +96,7 @@ class WebTemplate(Document): """ if standard: template = self.get_template_path() - with open(template, "r") as template_file: + with open(template) as template_file: template = template_file.read() else: template = self.template diff --git a/frappe/website/doctype/web_template_field/test_web_template_field.py b/frappe/website/doctype/web_template_field/test_web_template_field.py index 3f9160edb9..0a5b74c1ad 100644 --- a/frappe/website/doctype/web_template_field/test_web_template_field.py +++ b/frappe/website/doctype/web_template_field/test_web_template_field.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/website/doctype/web_template_field/web_template_field.py b/frappe/website/doctype/web_template_field/web_template_field.py index 082bde41f3..e86e630e81 100644 --- a/frappe/website/doctype/web_template_field/web_template_field.py +++ b/frappe/website/doctype/web_template_field/web_template_field.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/website/doctype/website_meta_tag/website_meta_tag.py b/frappe/website/doctype/website_meta_tag/website_meta_tag.py index 0ac84a632e..56b5f4f37b 100644 --- a/frappe/website/doctype/website_meta_tag/website_meta_tag.py +++ b/frappe/website/doctype/website_meta_tag/website_meta_tag.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/website/doctype/website_route_meta/test_website_route_meta.py b/frappe/website/doctype/website_route_meta/test_website_route_meta.py index 0a04207cea..55c95cdb9f 100644 --- a/frappe/website/doctype/website_route_meta/test_website_route_meta.py +++ b/frappe/website/doctype/website_route_meta/test_website_route_meta.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/website/doctype/website_route_meta/website_route_meta.py b/frappe/website/doctype/website_route_meta/website_route_meta.py index 0c12b10583..12ae682a48 100644 --- a/frappe/website/doctype/website_route_meta/website_route_meta.py +++ b/frappe/website/doctype/website_route_meta/website_route_meta.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/website/doctype/website_route_redirect/website_route_redirect.py b/frappe/website/doctype/website_route_redirect/website_route_redirect.py index 29bcd82094..f84e68d2b2 100644 --- a/frappe/website/doctype/website_route_redirect/website_route_redirect.py +++ b/frappe/website/doctype/website_route_redirect/website_route_redirect.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2019, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/website/doctype/website_settings/__init__.py b/frappe/website/doctype/website_settings/__init__.py index 8b13789179..e69de29bb2 100644 --- a/frappe/website/doctype/website_settings/__init__.py +++ b/frappe/website/doctype/website_settings/__init__.py @@ -1 +0,0 @@ - diff --git a/frappe/website/doctype/website_settings/google_indexing.py b/frappe/website/doctype/website_settings/google_indexing.py index 6585642fe7..d0657a1928 100644 --- a/frappe/website/doctype/website_settings/google_indexing.py +++ b/frappe/website/doctype/website_settings/google_indexing.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE @@ -52,7 +51,7 @@ def authorize_access(reauthorize=None): frappe.db.commit() frappe.local.response["type"] = "redirect" - frappe.local.response["location"] = "/app/Form/{0}".format(quote("Website Settings")) + frappe.local.response["location"] = "/app/Form/{}".format(quote("Website Settings")) frappe.msgprint(_("Google Indexing has been configured.")) except Exception as e: diff --git a/frappe/website/doctype/website_settings/test_website_settings.py b/frappe/website/doctype/website_settings/test_website_settings.py index c204bd7aea..40ca87efc9 100644 --- a/frappe/website/doctype/website_settings/test_website_settings.py +++ b/frappe/website/doctype/website_settings/test_website_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and Contributors # License: MIT. See LICENSE # import frappe diff --git a/frappe/website/doctype/website_settings/website_settings.py b/frappe/website/doctype/website_settings/website_settings.py index f249778c58..4088be88c2 100644 --- a/frappe/website/doctype/website_settings/website_settings.py +++ b/frappe/website/doctype/website_settings/website_settings.py @@ -1,6 +1,5 @@ # Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE -from typing import Dict, List from urllib.parse import quote import frappe @@ -180,7 +179,7 @@ def get_website_settings(context=None): if frappe.request: context.url = quote(str(get_request_site_address(full_address=True)), safe="/:") - context.encoded_title = quote(encode(context.title or ""), str("")) + context.encoded_title = quote(encode(context.title or ""), "") context.web_include_js = hooks.web_include_js or [] @@ -216,7 +215,7 @@ def get_website_settings(context=None): return context -def get_items(parentfield: str) -> List[Dict]: +def get_items(parentfield: str) -> list[dict]: _items = frappe.get_all( "Top Bar Item", filters={"parent": "Website Settings", "parentfield": parentfield}, diff --git a/frappe/website/doctype/website_sidebar/test_website_sidebar.py b/frappe/website/doctype/website_sidebar/test_website_sidebar.py index 5e92de0f6d..78c51546b7 100644 --- a/frappe/website/doctype/website_sidebar/test_website_sidebar.py +++ b/frappe/website/doctype/website_sidebar/test_website_sidebar.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/website/doctype/website_sidebar/website_sidebar.py b/frappe/website/doctype/website_sidebar/website_sidebar.py index 151446bac3..f120db1e87 100644 --- a/frappe/website/doctype/website_sidebar/website_sidebar.py +++ b/frappe/website/doctype/website_sidebar/website_sidebar.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/website/doctype/website_sidebar_item/website_sidebar_item.py b/frappe/website/doctype/website_sidebar_item/website_sidebar_item.py index e839de6d2b..febbafcaf7 100644 --- a/frappe/website/doctype/website_sidebar_item/website_sidebar_item.py +++ b/frappe/website/doctype/website_sidebar_item/website_sidebar_item.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/website/doctype/website_slideshow/test_website_slideshow.py b/frappe/website/doctype/website_slideshow/test_website_slideshow.py index c18835bdc1..45fe200949 100644 --- a/frappe/website/doctype/website_slideshow/test_website_slideshow.py +++ b/frappe/website/doctype/website_slideshow/test_website_slideshow.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE import unittest diff --git a/frappe/website/doctype/website_theme/website_theme.py b/frappe/website/doctype/website_theme/website_theme.py index 9cb7095f40..442ebe284b 100644 --- a/frappe/website/doctype/website_theme/website_theme.py +++ b/frappe/website/doctype/website_theme/website_theme.py @@ -90,7 +90,7 @@ class WebsiteTheme(Document): if stderr: stderr = frappe.safe_decode(stderr) stderr = stderr.replace("\n", "
    ") - frappe.throw('
    {stderr}
    '.format(stderr=stderr)) + frappe.throw(f'
    {stderr}
    ') else: self.theme_url = "/files/website_theme/" + file_name diff --git a/frappe/website/doctype/website_theme_ignore_app/website_theme_ignore_app.py b/frappe/website/doctype/website_theme_ignore_app/website_theme_ignore_app.py index 72652805ec..8c3f962b91 100644 --- a/frappe/website/doctype/website_theme_ignore_app/website_theme_ignore_app.py +++ b/frappe/website/doctype/website_theme_ignore_app/website_theme_ignore_app.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/website/page_renderers/base_renderer.py b/frappe/website/page_renderers/base_renderer.py index c8b4ac7344..e8421d17ab 100644 --- a/frappe/website/page_renderers/base_renderer.py +++ b/frappe/website/page_renderers/base_renderer.py @@ -2,7 +2,7 @@ import frappe from frappe.website.utils import build_response -class BaseRenderer(object): +class BaseRenderer: def __init__(self, path=None, http_status_code=None): self.headers = None self.http_status_code = http_status_code or 200 diff --git a/frappe/website/page_renderers/base_template_page.py b/frappe/website/page_renderers/base_template_page.py index f35a7e64f7..8163f113fa 100644 --- a/frappe/website/page_renderers/base_template_page.py +++ b/frappe/website/page_renderers/base_template_page.py @@ -46,7 +46,7 @@ class BaseTemplatePage(BaseRenderer): and self.context.title and not self.context.title.startswith(self.context.title_prefix) ): - self.context.title = "{0} - {1}".format(self.context.title_prefix, self.context.title) + self.context.title = f"{self.context.title_prefix} - {self.context.title}" def set_missing_values(self): # set using frappe.respond_as_web_page diff --git a/frappe/website/page_renderers/redirect_page.py b/frappe/website/page_renderers/redirect_page.py index b673fce3bb..be4a7bdf45 100644 --- a/frappe/website/page_renderers/redirect_page.py +++ b/frappe/website/page_renderers/redirect_page.py @@ -2,7 +2,7 @@ import frappe from frappe.website.utils import build_response -class RedirectPage(object): +class RedirectPage: def __init__(self, path, http_status_code=301): self.path = path self.http_status_code = http_status_code diff --git a/frappe/website/page_renderers/template_page.py b/frappe/website/page_renderers/template_page.py index 83f68d3716..daa4d54cc5 100644 --- a/frappe/website/page_renderers/template_page.py +++ b/frappe/website/page_renderers/template_page.py @@ -100,7 +100,7 @@ class TemplatePage(BaseTemplatePage): def post_process_context(self): self.set_user_info() self.add_sidebar_and_breadcrumbs() - super(TemplatePage, self).post_process_context() + super().post_process_context() def add_sidebar_and_breadcrumbs(self): if self.basepath: @@ -252,7 +252,7 @@ class TemplatePage(BaseTemplatePage): self.context.colocated_css = self.get_colocated_file(css_path) def get_colocated_file(self, path): - with io.open(path, "r", encoding="utf-8") as f: + with open(path, encoding="utf-8") as f: return f.read() def extract_frontmatter(self): @@ -289,7 +289,7 @@ class TemplatePage(BaseTemplatePage): self.app = "frappe" self.app_path = frappe.get_app_path("frappe") self.path = path - self.template_path = "www/{path}.html".format(path=path) + self.template_path = f"www/{path}.html" def set_missing_values(self): super().set_missing_values() diff --git a/frappe/website/report/website_analytics/website_analytics.py b/frappe/website/report/website_analytics/website_analytics.py index fd9bcc01ba..7e2e891081 100644 --- a/frappe/website/report/website_analytics/website_analytics.py +++ b/frappe/website/report/website_analytics/website_analytics.py @@ -13,7 +13,7 @@ def execute(filters=None): return WebsiteAnalytics(filters).run() -class WebsiteAnalytics(object): +class WebsiteAnalytics: def __init__(self, filters=None): self.filters = frappe._dict(filters or {}) diff --git a/frappe/website/router.py b/frappe/website/router.py index 8c21501a4e..24a085224b 100644 --- a/frappe/website/router.py +++ b/frappe/website/router.py @@ -204,13 +204,13 @@ def setup_source(page_info): # load css/js files js_path = os.path.join(page_info.basepath, (page_info.basename or "index") + ".js") if os.path.exists(js_path) and "{% block script %}" not in html: - with io.open(js_path, "r", encoding="utf-8") as f: + with open(js_path, encoding="utf-8") as f: js = f.read() page_info.colocated_js = js css_path = os.path.join(page_info.basepath, (page_info.basename or "index") + ".css") if os.path.exists(css_path) and "{% block style %}" not in html: - with io.open(css_path, "r", encoding="utf-8") as f: + with open(css_path, encoding="utf-8") as f: css = f.read() page_info.colocated_css = css @@ -249,7 +249,7 @@ def setup_index(page_info): # load index.txt if loading all pages index_txt_path = os.path.join(page_info.basepath, "index.txt") if os.path.exists(index_txt_path): - with open(index_txt_path, "r") as f: + with open(index_txt_path) as f: page_info.index = f.read().splitlines() diff --git a/frappe/website/utils.py b/frappe/website/utils.py index 6e34c05d40..cc39f11893 100644 --- a/frappe/website/utils.py +++ b/frappe/website/utils.py @@ -5,7 +5,6 @@ import mimetypes import os import re from functools import lru_cache, wraps -from typing import Dict, Optional import yaml from werkzeug.wrappers import Response @@ -81,9 +80,9 @@ def get_comment_list(doctype, name): reference_name=name, ), or_filters=[ - ["recipients", "like", "%{0}%".format(frappe.session.user)], - ["cc", "like", "%{0}%".format(frappe.session.user)], - ["bcc", "like", "%{0}%".format(frappe.session.user)], + ["recipients", "like", f"%{frappe.session.user}%"], + ["cc", "like", f"%{frappe.session.user}%"], + ["bcc", "like", f"%{frappe.session.user}%"], ], ) @@ -454,7 +453,7 @@ def get_sidebar_items_from_sidebar_file(basepath, look_for_sidebar_json): if not sidebar_json_path: return sidebar_items - with open(sidebar_json_path, "r") as sidebarfile: + with open(sidebar_json_path) as sidebarfile: try: sidebar_json = sidebarfile.read() sidebar_items = json.loads(sidebar_json) @@ -506,7 +505,7 @@ def cache_html(func): return cache_html_decorator -def build_response(path, data, http_status_code, headers: Optional[Dict] = None): +def build_response(path, data, http_status_code, headers: dict | None = None): # build response response = Response() response.data = set_content_type(response, data, path) @@ -559,7 +558,7 @@ def add_preload_headers(response): links = [] for _type, link in preload: - links.append("<{}>; rel=preload; as={}".format(link, _type)) + links.append(f"<{link}>; rel=preload; as={_type}") if links: response.headers["Link"] = ",".join(links) @@ -569,7 +568,7 @@ def add_preload_headers(response): traceback.print_exc() -@lru_cache() +@lru_cache def is_binary_file(path): # ref: https://stackoverflow.com/a/7392391/10309266 textchars = bytearray({7, 8, 9, 10, 12, 13, 27} | set(range(0x20, 0x100)) - {0x7F}) diff --git a/frappe/website/website_generator.py b/frappe/website/website_generator.py index 9d9fbd30e5..759b83d2e8 100644 --- a/frappe/website/website_generator.py +++ b/frappe/website/website_generator.py @@ -13,7 +13,7 @@ class WebsiteGenerator(Document): def __init__(self, *args, **kwargs): self.route = None - super(WebsiteGenerator, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def get_website_properties(self, key=None, default=None): out = getattr(self, "_website", None) or getattr(self, "website", None) or {} @@ -70,7 +70,7 @@ class WebsiteGenerator(Document): return title_field def clear_cache(self): - super(WebsiteGenerator, self).clear_cache() + super().clear_cache() clear_cache(self.route) def scrub(self, text): diff --git a/frappe/workflow/doctype/workflow/test_workflow.py b/frappe/workflow/doctype/workflow/test_workflow.py index 0fb4eca232..be4708ee12 100644 --- a/frappe/workflow/doctype/workflow/test_workflow.py +++ b/frappe/workflow/doctype/workflow/test_workflow.py @@ -96,7 +96,7 @@ class TestWorkflow(unittest.TestCase): todo4 = create_new_todo() actions = get_common_transition_actions([todo1, todo2, todo3, todo4], "ToDo") - self.assertSetEqual(set(actions), set(["Approve", "Reject"])) + self.assertSetEqual(set(actions), {"Approve", "Reject"}) apply_workflow(todo1, "Reject") apply_workflow(todo2, "Reject") diff --git a/frappe/workflow/doctype/workflow_action_master/workflow_action_master.py b/frappe/workflow/doctype/workflow_action_master/workflow_action_master.py index eb227b6125..95c7aa7cee 100644 --- a/frappe/workflow/doctype/workflow_action_master/workflow_action_master.py +++ b/frappe/workflow/doctype/workflow_action_master/workflow_action_master.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2018, Frappe Technologies and contributors # License: MIT. See LICENSE diff --git a/frappe/www/__init__.py b/frappe/www/__init__.py index 8b13789179..e69de29bb2 100644 --- a/frappe/www/__init__.py +++ b/frappe/www/__init__.py @@ -1 +0,0 @@ - diff --git a/frappe/www/_test/_test_metatags.py b/frappe/www/_test/_test_metatags.py index b5b504a246..717b89e985 100644 --- a/frappe/www/_test/_test_metatags.py +++ b/frappe/www/_test/_test_metatags.py @@ -1,8 +1,6 @@ # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors # MIT License. See license.txt -from __future__ import unicode_literals - def get_context(): return {"title": "Test Title Metatag", "description": "Test Description for Metatag"} diff --git a/frappe/www/app.py b/frappe/www/app.py index 0447d00f89..f75fe05c03 100644 --- a/frappe/www/app.py +++ b/frappe/www/app.py @@ -77,18 +77,18 @@ def get_desk_assets(build_version): if path.startswith("/assets/"): path = path.replace("/assets/", "assets/") try: - with open(os.path.join(frappe.local.sites_path, path), "r") as f: + with open(os.path.join(frappe.local.sites_path, path)) as f: assets[0]["data"] = assets[0]["data"] + "\n" + frappe.safe_decode(f.read(), "utf-8") - except IOError: + except OSError: pass for path in data["include_css"]: if path.startswith("/assets/"): path = path.replace("/assets/", "assets/") try: - with open(os.path.join(frappe.local.sites_path, path), "r") as f: + with open(os.path.join(frappe.local.sites_path, path)) as f: assets[1]["data"] = assets[1]["data"] + "\n" + frappe.safe_decode(f.read(), "utf-8") - except IOError: + except OSError: pass return {"build_version": data["build_version"], "boot": data["boot"], "assets": assets} diff --git a/frappe/www/list.py b/frappe/www/list.py index 2048f1223e..06a2ea48aa 100644 --- a/frappe/www/list.py +++ b/frappe/www/list.py @@ -125,11 +125,11 @@ def get_list_data( def set_route(context): """Set link for the list item""" if context.web_form_name: - context.route = "{0}?name={1}".format(context.pathname, quoted(context.doc.name)) + context.route = f"{context.pathname}?name={quoted(context.doc.name)}" elif context.doc and getattr(context.doc, "route", None): context.route = context.doc.route else: - context.route = "{0}/{1}".format( + context.route = "{}/{}".format( context.pathname or quoted(context.doc.doctype), quoted(context.doc.name) ) diff --git a/frappe/www/login.py b/frappe/www/login.py index 119dfefcd7..c29fdce9ce 100644 --- a/frappe/www/login.py +++ b/frappe/www/login.py @@ -129,7 +129,7 @@ def login_via_office365(code, state): @frappe.whitelist(allow_guest=True) def login_via_token(login_token): - sid = frappe.cache().get_value("login_token:{0}".format(login_token), expires=True) + sid = frappe.cache().get_value(f"login_token:{login_token}", expires=True) if not sid: frappe.respond_as_web_page(_("Invalid Request"), _("Invalid Login Token"), http_status_code=417) return diff --git a/frappe/www/message.py b/frappe/www/message.py index fa13f3ab75..b5035de20f 100644 --- a/frappe/www/message.py +++ b/frappe/www/message.py @@ -18,7 +18,7 @@ def get_context(context): elif frappe.local.form_dict.id: message_id = frappe.local.form_dict.id - key = "message_id:{0}".format(message_id) + key = f"message_id:{message_id}" message = frappe.cache().get_value(key, expires=True) if message: message_context.update(message.get("context", {})) diff --git a/frappe/www/printview.py b/frappe/www/printview.py index c8595a6f2c..3ba73fe348 100644 --- a/frappe/www/printview.py +++ b/frappe/www/printview.py @@ -242,9 +242,9 @@ def set_title_values_for_link_and_dynamic_link_fields(meta, doc, parent_doc=None link_title = frappe.get_cached_value(doctype, doc.get(field.fieldname), meta.title_field) if parent_doc: - parent_doc.__link_titles["{0}::{1}".format(doctype, doc.get(field.fieldname))] = link_title + parent_doc.__link_titles[f"{doctype}::{doc.get(field.fieldname)}"] = link_title elif doc: - doc.__link_titles["{0}::{1}".format(doctype, doc.get(field.fieldname))] = link_title + doc.__link_titles[f"{doctype}::{doc.get(field.fieldname)}"] = link_title def set_title_values_for_table_and_multiselect_fields(meta, doc): @@ -388,7 +388,7 @@ def get_print_format(doctype, print_format): ) if os.path.exists(path): - with open(path, "r") as pffile: + with open(path) as pffile: return pffile.read() else: if print_format.raw_printing: @@ -557,11 +557,11 @@ def get_font(print_settings, print_format=None, for_legacy=False): font = None if print_format: if print_format.font and print_format.font != "Default": - font = "{0}, sans-serif".format(print_format.font) + font = f"{print_format.font}, sans-serif" if not font: if print_settings.font and print_settings.font != "Default": - font = "{0}, sans-serif".format(print_settings.font) + font = f"{print_settings.font}, sans-serif" else: font = default diff --git a/frappe/www/qrcode.py b/frappe/www/qrcode.py index 7adde40fde..e76dc65540 100644 --- a/frappe/www/qrcode.py +++ b/frappe/www/qrcode.py @@ -29,8 +29,8 @@ def get_query_key(): def get_user_svg_from_cache(): """Get User and SVG code from cache.""" key = get_query_key() - totp_uri = frappe.cache().get_value("{}_uri".format(key)) - user = frappe.cache().get_value("{}_user".format(key)) + totp_uri = frappe.cache().get_value(f"{key}_uri") + user = frappe.cache().get_value(f"{key}_user") if not totp_uri or not user: frappe.throw(_("Page has expired!"), frappe.PermissionError) if not frappe.db.exists("User", user): diff --git a/frappe/www/rss.py b/frappe/www/rss.py index 1ebfb61482..dbd2aac9e9 100644 --- a/frappe/www/rss.py +++ b/frappe/www/rss.py @@ -29,7 +29,7 @@ def get_context(context): blog.content = escape_html(blog.content or "") if blog_list: - modified = max((blog["modified"] for blog in blog_list)) + modified = max(blog["modified"] for blog in blog_list) else: modified = now() From d614bad6677d0fe48457a8d44282302e39031640 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Fri, 1 Jul 2022 12:09:27 +0530 Subject: [PATCH 099/101] ci: force modern python with pyupgrade (#17370) also add previous bulk change to git-blame-ignore-revs --- .git-blame-ignore-revs | 3 +++ .pre-commit-config.yaml | 16 ++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index a49668a5f4..c3ad43c5be 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -22,3 +22,6 @@ b2fc959307c7c79f5584625569d5aed04133ba13 # Format codebase and sort imports c0c5b2ebdddbe8898ce2d5e5365f4931ff73b6bf + +# update python code to use 3.10 supported features +81b37cb7d2160866afa2496873656afe53f0c145 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e8a44f0d1e..b231221517 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ fail_fast: false repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.0.1 + rev: v4.3.0 hooks: - id: trailing-whitespace files: "frappe.*" @@ -15,6 +15,16 @@ repos: args: ['--branch', 'develop'] - id: check-merge-conflict - id: check-ast + - id: check-json + - id: check-toml + - id: check-yaml + - id: debug-statements + + - repo: https://github.com/asottile/pyupgrade + rev: v2.34.0 + hooks: + - id: pyupgrade + args: ['--py310-plus'] - repo: https://github.com/adityahase/black rev: 9cb0a69f4d0030cdf687eddf314468b39ed54119 @@ -31,9 +41,7 @@ repos: rev: 3.9.2 hooks: - id: flake8 - additional_dependencies: [ - 'flake8-bugbear', - ] + additional_dependencies: ['flake8-bugbear',] args: ['--config', '.github/helper/flake8.conf'] ci: From 3287bce2137e40294499523d7daad00ca6676759 Mon Sep 17 00:00:00 2001 From: "Nihantra C. Patel" <99652762+nihantra@users.noreply.github.com> Date: Fri, 1 Jul 2022 13:46:33 +0530 Subject: [PATCH 100/101] fix: calendar view set in assign time --- .../public/js/frappe/form/sidebar/assign_to.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/frappe/public/js/frappe/form/sidebar/assign_to.js b/frappe/public/js/frappe/form/sidebar/assign_to.js index 71ad5b4cb2..befd5bc572 100644 --- a/frappe/public/js/frappe/form/sidebar/assign_to.js +++ b/frappe/public/js/frappe/form/sidebar/assign_to.js @@ -164,17 +164,9 @@ frappe.ui.form.AssignToDialog = class AssignToDialog { return frappe.db.get_link_options("User", txt, {user_type: "System User", enabled: 1}); } }, - { - label: __("Comment"), - fieldtype: 'Small Text', - fieldname: 'description' - }, { fieldtype: 'Section Break' }, - { - fieldtype: 'Column Break' - }, { label: __("Complete By"), fieldtype: 'Date', @@ -203,6 +195,14 @@ frappe.ui.form.AssignToDialog = class AssignToDialog { ], // Pick up priority from the source document, if it exists and is available in ToDo default: ["Low", "Medium", "High"].includes(me.frm && me.frm.doc.priority ? me.frm.doc.priority : 'Medium') + }, + { + fieldtype: 'Section Break' + }, + { + label: __("Comment"), + fieldtype: 'Small Text', + fieldname: 'description' } ]; } From cc15cc73eb1cce1f5ace76e25f8fefc8ab6e1ae6 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Fri, 1 Jul 2022 18:15:42 +0530 Subject: [PATCH 101/101] chore: delete old conf files We dont use pylint and it's not even valid pylint config. [skip ci] --- .pylintrc | 2 -- Makefile | 4 ---- 2 files changed, 6 deletions(-) delete mode 100644 .pylintrc delete mode 100644 Makefile diff --git a/.pylintrc b/.pylintrc deleted file mode 100644 index c11c0ab6a3..0000000000 --- a/.pylintrc +++ /dev/null @@ -1,2 +0,0 @@ -disable=access-member-before-definition -disable=no-member \ No newline at end of file diff --git a/Makefile b/Makefile deleted file mode 100644 index 44a7d2fd59..0000000000 --- a/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -BASEDIR := $(realpath .) - -clean: - find $(BASEDIR) | grep -E "__pycache__|\.pyc" | xargs rm -rf \ No newline at end of file