Заработок на Apptools — Заработок в интернете
Как заработать в современном прогрессивном мире
Заработать в современном прогрессивном мире в интернете или на приложениях в сети – давно не проблема, проблема только в том,
чтобы найти свое направление и начать работать. Сегодня, чтобы получать прибыль, не обязательно ходить на работу,
даже за компьютером находиться давно не обязательно, ведь даже со своего смартфона можно делать первые шаги для заработка в интернете.
Если поначалу прибыль будет слабенькой, то со временем и опытом она будет расти.
Как пройти регистрацию на Apptools
Первым делом, чтобы начать работу с платформой для заработка на своем мобильном, посещаем их официальный сайт, а именно:
apptools.ru, переходим к скачиванию приложения. После того, как приложение оказалось на вашем смартфоне, установите его и перейдите к разделу «регистрация».
Пройдя все пункты регистрации успешно, Вам откроется раздел заданий, за выполнение которых на Вашем счету начнут копиться деньги сразу же.
Что предлагает платформа для заработка с телефона Апптулс ру
Если брать в сравнении, то сервис предлагает достаточно хорошие и выгодные условия для исполнителей и заказчиков.
При помощи приложения люди, которые хотят выполнить то или иное задание с легкостью выполняют их и получают за это вознаграждение.
Предложенный проект предлагает заказчику раскрутить свой проект и увеличить его популярность за счет реальных пользователей интернета.
Сервис работает с двумя крупнейшими магазинами, а именно: Google Play и App Store от Apple.
Преимущества Apptools
Неплохой, удачный интерфейс приложения, интуитивно понятный для заказчика и исполнителя.
Единственный подобный сервис в настоящее время, который честно оплачивает задания и исполняет заказы заинтересованных лиц.
Заработок на апптулс возможен не только пользователям iOS, но и Android. Понятная инструкция по работе с приложениями и выполнением заданий.
Недостатки Apptools
Никаких серьезных недостатков, по сути, нет, кроме того, что заработать действительно много денег здесь однозначно не выйдет,
но в качестве «стартовой» площадки, вполне подойдет.
Вывод денег из Apptools
Зачисление финансов производится изначально внутри приложения практически мгновенно после выполнения задания.
Принимаются платежи и переводы через WebMoney без комиссии. Вывод доступен также на электронные кошельки и даже мобильный телефон.
Перевод осуществляется в течение нескольких минут.
Отзывы об Apptools
Пользователи, которые сталкивались и работали с этим сервисом положительно отзываются о нём, чаще всего.
Чаще всего сервис хвалят за простоту работы в нем, интуитивную понятность самого приложения и креативное оформление,
а также за выплаты денег за задания и на электронные кошельки. Минимальных сумм для вывода здесь нет, как и комиссий.
Спасибо за прочтение статьи! Надеюсь информация была полезной. Обязательно поделитесь с друзьями!
Реально зароботать в приложении на андроид AppTools?
Если вы имеете в виду редактор html и прочих тектовых файлов на андроид-устройствах, то для этого есть несколько приложений, тут уже выбираете то, которое вам нужнее и удобнее.
Я например пользуюсь программой Total Commander, а вот для того, чтобы выгрузить готовую страницу назад, необходимо еще приложение для работы с ФТП-сервером, впрочем и для Тотал Коммандера такой плагин есть, но мне удобнее все-таки программа AndFTP.
В чем и дело , что каждое последующее обновление приложения делает его шире , больше по объёму. Причина простая. В каких то приложениях старые компоненты не заменяются к ним просто присоединяются новые , если же заменяются то обновление на то и было, чтоб расширить работу приложения и сделать его лучше, по логике и должно обновление быть мощнее , следовательно и больше по памяти.
Скорей всего, не настроены уведомления самого приложения. Включить уведомления можно в самом Ватсаппе. Зайти в программу, дальше в её Настройки => Уведомления => Всплывающее уведомление и выбрать Всегда показывать. Можно выбрать и другие пункты, для своего удобства.
Либо через настройки приложений самого Андройда: Настройки => Приложения => WhatsApp => Уведомления. Дальше смотреть, что включено и что выключено, а должно быть так: выключить Блокировать все, а включить Краткие уведомления.
Нажмите кнопку меню (справа от кнопки home), выберите пункт меню «Настройка темы» и среди списка появившихся тем выбираете ту, которая была у вас стандартной.
По мне приложение youtube дети,очень полезно,если у вас есть дети младше чем 18 лет. в этом приложении можно устанавливать родительский контроль,который не маловажен тем родителям,которые следят за своими детьми.в этом приложении нельзя смотреть видио с возрастными ограничениями 16+ 18+
Как заработать на AppTools?
Заработок на AppTools
Многие пользователи сети уже не раз слышали об уникальной возможности зарабатывать при помощи интернета. Подобный способ пополнить бюджет действительно выгодный, вы можете, не выходя из дома получать хорошую прибыль.
На сегодняшний день, заработок в сети, как и множество других технологий, динамично совершенствуется. Теперь фрилансеры смогут воспользоваться еще более выгодным приложением – получать реальные деньги при помощи мобильного телефона. Как же работает данная методика?
Существует несколько проектов, предлагающих пользователям такой вид работы. Среди них стоит выделить apptools. По сути, это специализированное приложение, которое каждый владелец устройства с системами IOS и Android может загрузить при помощи Play Market или AppStore.
Принцип работы прост. Вы скачиваете доступные в главном меню проекта приложения и получаете за это реальные деньги. При этом у вас есть возможность выбрать форму получения прибыли. Вы можете вывести денежные средства на банковский счет или пополнить ваш мобильный счет.
Способы заработка на AppTools
AppTools – одно из наиболее выгодных приложений, которое позволяет каждому пользователю, обладающему мобильным устройством с системами IOS и Android, получать прибыль, не прилагая к трудовому процессу никаких усилий. При этом временные затраты на выполнение заданий сведены к минимуму.
Проект готов предложить своим пользователям три альтернативных способа заработка:
- скачивания приложений;
- проставление оценок и написание отзывов;
- реферальные ссылки.
Первые два способа схожи между собой. Принцип выполнения задания более чем прост. В случае возникновения вопросов каждый пользователь может ознакомиться с обучающими заметками, которые помогут найти ответы на возникшие вопросы.
Как в первом, так и во втором случае, задача пользователей заключается в скачивании приложений. Для выполнения заданий, в главном меню сервиса вы сможете увидеть список доступных заданий. Вам достаточно выбрать одно из них и после этого скачать его на свой мобильный телефон. Для того чтобы задание было засчитано нужно запустить приложение, в противном случае вы потеряете потенциальную прибыль.
Стоит отметить, что перечень приложений для скачивания постоянно пополняется, что позволяет исполнителям иметь стабильный доход. Помимо прочего, для удобства работников, на адрес вашей электронной почты на постоянной основе будут приходить оповещения о том, что список программ для загрузки пополнен. Благодаря этому вы всегда будете в курсе актуальных рабочих предложений.
Последний вид заработка на проекте apptools можно обозначить как пассивный. Вы с легкостью сможете его совмещать с основными заданиями на проекте. Для того чтобы получить прибыль вам нужно привлечь новых работников.
Задача предельно проста, рассказав друзьям и знакомым о сервисе для заработка, вы сможете получать на постоянной основе до 10 % от дохода приведенных вами пользователей. Для этого им достаточно пройти процедуру регистрации. Регистрация ✓
Ни один ученик не останется равнодушным / Newtonew: новости сетевого образования
Pear Deck: простое и «вовлекательное» приложение для интерактивных презентаций
Это приложение синхронизируется с Google Диском и позволяет присоединяться к работе с презентацией через аккаунты Google. Pear Deck служит для создания интерактивных презентаций, слайды которых могут содержать изображения, текст, видеоконтент. Приложение позволяет учителю во время активной сессии взаимодействовать с аудиторией, создавая вопросы и задания в реальном времени по ходу демонстрации презентации. Если обычно во время урока учитель может ориентироваться на реакцию тех, кто не стесняется и не ленится высказаться в слух, то с Pear Deck каждый ученик будет услышан, реагируя на слова учителя на своём компьютере.
Nearpod: урок в мобильном телефоне
Онлайн-платформа Nearpod позволяет создавать презентации к занятиям и делиться ими с детьми с помощью мобильных. Вы просто высылаете ученикам код презентации, а они подключаются к общему действу через мобильные телефоны. Как отмечают некоторые учителя, дети могут забыть дома что угодно, только не свой смартфон.
Примечательно, что с помощью этого приложения ученики могут выполнять ваши задания, дополняя презентацию своим контентом прямо во время урока. Например, вы можете попросить их написать эссе о картине художника, творчество которого изучаете в классе. В режиме домашнего задания ученики могут работать с презентациями, не подключаясь к общей сессии.
Истории успешного использования Nearpod от преподавателей
Socrative: викторины для студентов
Мобильное приложение Socrative специализируется на викторинах. С его помощью учитель может создавать опросники с открытыми вопросами и тесты с вариантами ответов. Ученики присоединяются к викторине по ссылке, а результаты их ответов обрабатываются программой. Учитель получает в результате статистику по каждому ученику и сводную таблицу результатов.
Socrative сразу показывает статистику ответов преподавателю
Источник: socrative.com
Викторина за пять минут с Kahoot!
Kahoot! — бесплатный сервис, полный достоинств. Яркий, очень социальный, чрезвычайно простой для учителя, а уж дети от 5 до 16 от него в восторге. Kahoot разрабатывался как инструмент для быстрого создания всего интерактивного, что можно представить: викторин, опросов и обсуждений. Всё, что создаётся на платформе, так и называется — «кахуты». В эти мини-игры можно вставлять видео и изображения, а процесс создания (если есть, конечно, уже готовый опросник) занимает от силы минут пять. Для добавления соревновательного эффекта к вопросам добавляется таймер. Чтобы начать игру в классе, учителю нужно предоставить группе учеников сгенерированный системой код, который они потом вводят на своих устройствах (планшет, смартфон, десктоп) — и да начнётся веселье! Система поддерживает русский язык, доступна на любом устройстве (работает в браузере, есть адаптированная мобильная версия, поэтому даже приложений устанавливать не нужно).
Вот скриншот мини-игры, проверяющей элементарные знания условных операторов в программировании на Scratch.
Источник: kahoot
Интерактивная мультимедийная стена
Padlet — инструмент, который позволяет разместить свои идеи не на чередующихся слайдах, а на виртуальной плоскости. К созданию стены можно приглашать других пользователей и использовать её так же, как интерактивные карты: ученики или другие учителя будут добавлять на вашу общую стену свои материалы, в результате получается совместный творческий продукт. Стена имеет постоянный адрес веб-страницы, и вы можете делиться результатом в социальных сетях, вставлять её в блоги и на другие сайты.
Коллекция дизайнерских объектов на одной мультимедийной стене
Источник: padlet.com
На стене можно размещать текстовые блоки, фотографии, видео с YouTube. Все изменения сохраняются онлайн автоматически. Приватность стены гибко настраивается: вы можете пригласить в соавторы несколько человек, а можете сделать её открытой для изменений всему миру.
История Одиссея, рассказанная с помощью Padlet
Источник: padlet.com
Учителя, которые давно полюбили этот инструмент, делятся идеями, как можно его использовать. Вот только некоторые варианты: создать общую стену для размещения отзывов на книги; сделать стену благодарностей или поздравлений; приспособить виртуальную плоскость для форума. Можно использовать стену и для менее глобальных задач. Например, пригласить ребят к обсуждению плей-листа следующей школьной дискотеки.
Гладкий графический дизайн с Canva
Сервис Canva нужно рекомендовать всем от мала до велика. Он поможет и учителям соорудить наглядную инфографику, которая выглядит не хуже, чем профессиональные, и ученикам приятнее будет открыть не опостылевший PowerPoint, а очень дружелюбный веб-сайт с готовыми шаблонами, симпатичными иллюстрациями, набором визуальных элементов и фотографий. Сделать что-то уродливое в Canva возможно только если выбирать элементы с закрытыми глазами. Сервис бесплатный, но есть платные коллекции и элементы (без которых, к слову, вполне можно обойтись благодаря возможности загружать собственные изображения).
Плакат даже информационный можно на коленке сделать из готовых шаблонов.
Vialogues — бесплатный сервис, который позволяет вести онлайн-дискуссии вокруг видео
Работать с Vialogues просто. Загружаете видео на сайт (или выбираете ролик с YouTube), дополняете описанием самого ролика, обозначаете вопросы для обсуждения, настраиваете приватность — и делитесь своим «виалогом» с теми, кого хотите втянуть в дискуссию. У модератора обсуждения есть возможность оставлять комментарии и вопросы к конкретным участкам видео.
Оставляйте комментарии и вопросы к конкретным участкам видео
Создание образовательных видео с Zaption и Adobe Voice
Adobe Voice созвучен философии Apple: чем меньше у пользователя выбор, тем меньше возможность ошибиться
Эти два инструмента помогут создать урок для размещения онлайн на основе видео и фотоматериалов. С Zaption можно работать онлайн с любого устройства, в бесплатном режиме или с аккаунтом PRO с расширенным функционалом. Adobe Voice разработан для iPad и принципиально бесплатен (кроме того, предлагает ещё для оформления тысячи вариантов бесплатных иконок и изображений). «Изюминка» Zaption — в возможности использовать интерактивные элементы (онлайн-опросы, викторины и т.д.). Adobe Voice делает ставку на простоту использования и предсказуемо красивый с точки зрения дизайна результат. И главное — вы с лёгкостью можете записать голосовой комментарий к видео или фоторяду.
Рисуйте комиксы
Можно поспорить на что угодно: предложение нарисовать комикс на уроке истории взбодрит самые дальние парты. Pixton — инструмент для создания комиксов «на коленке». В базовой бесплатной версии здесь предлагается выбрать уже готовые локации и использовать до трёх персонажей. Нужно учесть, что сервис не поддерживает кириллицу, поэтому на чистом русском ваши персонажи не заговорят. Вы можете сами иллюстрировать уроки комиксами, а можете давать ребятам такие оригинальные задания.
Пример изучения русской культуры англоязычными студентами с помощью Pixtone
Источник: pixton.com
Создавайте хроники
В этой подборке представлены 9 сервисов для создания хроник. Создание хроники — это не только расстановка исторических событий во временной последовательности. Это способ организовать самую разнообразную информацию. Современные сервисы позволяют расположить в хронологическом порядке видео, фотографии, тексты. Некоторые из них можно использовать для создания целых репортажей. Хороший способ оригинально и наглядно представить учебный материал или поделиться ценным навыком упорядочивания со студентами.
Нашли опечатку? Выделите фрагмент и нажмите Ctrl+Enter.
Служба выбора — Документация Apptools
В приложениях с графическим интерфейсом довольно часто присутствует элемент пользовательского интерфейса, отображающий
набор элементов, которые может выбрать пользователь («поставщики выбора»), а
другие части приложения должны реагировать на изменения в выборе
(«Отбор слушателей»).
В идеале слушатели не должны иметь прямой зависимости от объекта UI.
Это особенно важно в расширяемых приложениях Envisage, где
плагину может потребоваться отреагировать на изменение выбора, но мы не хотим
показать внутреннюю организацию приложения внешним разработчикам.
Этот пакет определяет службу выбора, которая управляет связью
между провайдерами и слушателем.
Объект SelectionService
— это центральный менеджер, который обрабатывает
общение между поставщиками выбора и слушателем.
Провайдеры выбора — это компоненты, которые хотят
публиковать информацию об их текущем выборе для общественного потребления.
Они регистрируются на выбор
экземпляр службы, когда у них впервые доступен выбор (например,г., когда
Пользовательский интерфейс, показывающий список выбираемых элементов, инициализирован), и отмените регистрацию, как только
поскольку выбор больше не доступен (например, пользовательский интерфейс уничтожается, когда
окна закрыты).
Слушатели выбора могут запрашивать выбор
сервис, чтобы получить текущий выбор, опубликованный поставщиком, используя
уникальный идентификатор провайдера.
Сервис действует как посредник между провайдерами и слушателями, гарантируя, что
они получают уведомление, когда
выбор
событие запущено.
Провайдеры отбора
Любой объект может стать поставщиком выбора, реализовав
ISelectionProvider
интерфейс и регистрация в службе выбора.
Провайдеры выбора должны предоставить уникальный идентификатор
provider_id
,
который используется слушателями для запроса текущего выбора.
При изменении выбора провайдеры запускают
выбор
мероприятие. Содержимое мероприятия — это экземпляр, реализующий
ISelection
, который содержит информацию о выбранных элементах.
Например, объект ListSelection
содержит список выбранных
предметы и их индексы.
Провайдеры выбора также могут быть напрямую запрошены об их текущем выборе
с использованием
get_selection
метод, и может быть предложено изменить их выбор на новый с
set_selection
метод.
Регистрация
Поставщики селекции публикуют свой выбор, регистрируясь в выборке
сервис с использованием
add_selection_provider
метод. Когда выбор больше не доступен, поставщики выбора
следует отменить регистрацию через
remove_selection_provider
.
Обычно провайдеры выбора — это объекты пользовательского интерфейса, показывающие список или дерево элементов,
они регистрируются, как только компонент пользовательского интерфейса инициализируется, и отменяют регистрацию
когда компонент пользовательского интерфейса исчезает (например,г., потому что их окно было закрыто).
В более сложных приложениях регистрация может выполняться контроллером.
объект вместо этого.
Подбор слушателей
Слушатели выбора запрашивают информацию о текущем выборе
поставщика выбора с учетом его идентификатора поставщика. SelectionService
поддерживает два различных варианта использования:
Пассивное прослушивание изменений выбора: слушатель подключается к определенному
провайдера и получают уведомление при изменении выбора провайдера.Активно запрашивает у поставщика текущий выбор: выбор
service может использоваться для запроса поставщика, используя его уникальный идентификатор.
Пассивное прослушивание
Слушатели подключаются к событиям выбора для данного провайдера с помощью
connect_selection_listener
метод. Им необходимо предоставить уникальный идентификатор поставщика и функцию
(или вызываемый), который вызывается для отправки события. Эта функция обратного вызова принимает
один аргумент, реализация ISelection
, которая представляет
выбор.
Слушатель может подключиться к идентификатору поставщика до того, как он
зарегистрирован. Как только провайдер будет зарегистрирован, слушатель получит
уведомление, содержащее первоначальный выбор поставщика.
Для отключения слушателя используйте методы
Disconnect_selection_listener
.
Активные запросы
В других случаях элементу приложения требуется только текущий
выбор в определенное время. Например, кнопка на панели инструментов может открывать диалог
представляет действие пользователя на основе того, что в данный момент выбрано в активном
редактор.
get_selection
метод вызывает соответствующий метод поставщика с данным идентификатором и
возвращает экземпляр ISelection
.
Установка выделения
Наконец, можно запросить у провайдера установку для его выбора заданного
набор объектов с
set_selection
.
Основной вариант использования этого метода — несколько представлений одного и того же списка
объекты, выбор которых должен синхронизироваться.
Если элементы, указанные в аргументах, недоступны в поставщике,
возникает ProviderNotRegisteredError
,
если для необязательного аргумента ключевого слова ignore_missing
установлено значение True
.
# (C) Copyright 2005-2021 Enthought, Inc. , Остин, Техас | |
# Все права защищены. | |
# | |
# Это программное обеспечение предоставляется без гарантии в соответствии с условиями BSD | |
# лицензия включена в ЛИЦЕНЗИЮ.txt и может распространяться только под номером | |
# условия, описанные в вышеупомянутой лицензии. Лицензия | |
# также доступен в Интернете по адресу http://www.enoughtt.com/licenses/BSD.txt | |
# | |
# Спасибо за использование открытого исходного кода Enthought! | |
«» « | |
Код для поддержки записи в читаемый и исполняемый скрипт Python. | |
FIXME: | |
— Поддержка словарей? | |
«» « | |
импорт встроенных модулей | |
предупреждений об импорте | |
из черт.импорт API ( | |
HasTraits, | |
Список, | |
ул., | |
Dict, | |
Bool, | |
недвижимость, | |
Инт, | |
Экземпляр, | |
) | |
из черт. util.camel_case импорт camel_case_to_python | |
############################################## ############################# | |
# Класс `_RegistryData`. | |
############################################## ############################# | |
класс _RegistryData (HasTraits): | |
# ID скрипта объекта | |
script_id = Свойство (Str) | |
# Путь к объекту в иерархии объектов. | |
путь = Свойство (Str) | |
# Родительские данные для этого объекта, если есть. | |
parent_data = Экземпляр («_ RegistryData», allow_none = True) | |
# Имя трейта родительского объекта, которым является этот объект. | |
trait_name_on_parent = Str («») | |
# Список трейтов, которые мы слушаем для этого объекта. | |
names = Список (Str) | |
# Вложенные записываемые экземпляры объекта. | |
sub_recordables = Список (Str) | |
# Список признаков, которые являются списками. | |
list_names = Список (Str) | |
_script_id = Str («») | |
############################################## ######################### | |
# Непубличный интерфейс. | |
############################################## ######################### | |
def _get_path (сам): | |
pdata = self. parent_data | |
путь = «» | |
, если pdata не равно None: | |
pid = pdata.script_id | |
ppath = pdata.path | |
tnop = self.trait_name_on_parent | |
, если «[» в tnop: | |
# Если объект является вложенным через итератор, | |
# мы создаем его экземпляр и не обращаемся к нему через | |
# путь, это упрощает создание сценариев. | |
, если len (ppath) == 0: | |
путь = pid + «. » + тноп | |
еще: | |
путь = ppath + «.» + тноп | |
еще: | |
путь = ppath + «.» + тноп | |
обратный путь | |
def _get_script_id (сам): | |
sid = self._script_id | |
, если len (sid) == 0: | |
pdata = self.parent_data | |
sid = pdata.script_id + «.» + self. trait_name_on_parent | |
возврат sid | |
def _set_script_id (self, id): | |
сам._script_id = id | |
############################################## ############################# | |
# Класс RecorderError. | |
############################################## ############################# | |
класс RecorderError (исключение): | |
пасс | |
############################################## ############################# | |
# Класс Recorder. | |
############################################## ############################# | |
Регистратор класса (HasTraits): | |
# Строки записанного кода. | |
строк = Список (Str) | |
# Мы записываем или нет? | |
record = Bool (False, desc = «если запись сценария включена или нет») | |
# Скрипт Python, который мы записали.Это просто | |
# удобство для метода get_code (). | |
скрипт = Свойство (Str) | |
###################################### | |
# Личные черты. | |
# Dict используется для хранения информации о зарегистрированных объектах.В нем хранится | |
# уникальное имя объекта и его путь в иерархии объектов | |
# пройден. | |
_registry = Dict | |
# Обратный реестр с ключами как script_id и object как значение. | |
_reverse_registry = Dict | |
# Отображение для создания уникальных имен для объектов.Ключ | |
# name used (которое является производным от имени класса | |
# объект), а значение — целое число, описывающее, сколько раз | |
# это имя переменной использовалось ранее. | |
_name_map = Dict (Str, Int) | |
# Список специальных зарезервированных идентификаторов скриптов.Это удобно, когда вы | |
# хотите, чтобы у конкретного объекта был легко читаемый идентификатор скрипта, а не | |
# значение по умолчанию, основанное на имени класса. Это приводит к немного | |
# скрипты легче читать. | |
_special_ids = Список | |
# Какие известные имена в скрипте? Под известными именами мы подразумеваем | |
# имена, которые фактически привязаны к объектам. | |
_known_ids = Список (Str) | |
# Известные типы в пространстве имен. | |
_known_types = Список (Str) | |
# Страж, проверяющий, находимся ли мы сейчас в записанном вызове функции, | |
#, в этом случае мы не хотим делать никаких записей. | |
_in_function = Bool (Ложь) | |
############################################## ######################### | |
# Интерфейс `Recorder`. | |
############################################## ######################### | |
def запись (сам, код): | |
«» «Записать строку для сохранения в выходной файл. | |
Параметры | |
———- | |
код: str | |
Строка текста. | |
«» « | |
, если сам.запись, а не себя ._в_функции: | |
строк = self.lines | |
# Проанализируйте код и при необходимости добавьте дополнительный код. | |
self._analyze_code (код) | |
# Добавьте код. | |
lines.append (код) | |
регистр def ( | |
я, | |
объект, | |
родитель = Нет, | |
trait_name_on_parent = «», | |
игнорировать = Нет, | |
known = False, | |
script_id = Нет, | |
): | |
«» «Зарегистрируйте объект в регистраторе. Это настраивает | |
объект для записи. | |
По умолчанию все черты (кроме тех, которые начинаются и заканчиваются на | |
‘_’) записаны. Для самих атрибутов | |
записываемый, можно пометить признаки с метаданными «записи» как | |
следует: | |
— Если метаданные `record = False` установлены, вложенный объект не будет | |
записано. | |
— Если record = True, то этот объект также записывается, если он равен | |
не `None`. | |
Если объект представляет собой список или словарь, помеченный цифрой | |
`record = True`, сам список не прослушивается на предмет изменений | |
, но все его содержимое зарегистрировано. | |
Если у `объекта` есть признак с именем` рекордер`, то этот рекордер | |
По возможности будет установлен экземпляр | . |
Параметры | |
———- | |
объект: Экземпляр (HasTraits) | |
Объект для регистрации в реестре. | |
родитель: Экземпляр (HasTraits) | |
Необязательный родительский объект, в котором содержится `объект` | |
trait_name_on_parent: str | |
Необязательное имя признака объекта в родительском элементе. | |
игнорировать: список (str) | |
Необязательный список имён свойств объекта, который должен быть | |
игнорируется. | |
известно: bool | |
Необязательная спецификация, если идентификатор объекта известен на | |
переводчик. Это необходимо, если вы вручную вводите | |
код для определения / создания объекта. | |
script_id: str | |
Необязательно укажите script_id для использования для этого объекта. Это | |
не гарантируется, что этот идентификатор будет использован, так как он может | |
уже используется. | |
«» « | |
registry = self._registry | |
# Ничего не делать, если объект уже зарегистрирован. | |
, если объект в реестре: | |
возврат | |
# Когда указан родительский признак, также должно быть указано trait_name_on_parent. | |
, если родитель не None: | |
assert len (trait_name_on_parent)> 0 | |
, если игнорировать Нет: | |
игнорировать = [] | |
, если isinstance (объект, HasTraits): | |
# Всегда игнорируйте это. | |
ignore.extend ([«trait_added», «trait_modified»]) | |
sub_recordables = список (object.traits (record = True) .keys ()) | |
# Найдите все имена черт, которые мы должны игнорировать. | |
ignore.extend (object.traits (record = False) .keys ()) | |
# Черты характера, к которым нужно прислушиваться. | |
tnames = [ | |
т | |
для t в object.trait_names () | |
, если не t. startswith («_») | |
, а не t.endswith («_») | |
и т не в игнор | |
] | |
# Найти все черты списка. | |
trts = object.traits () | |
list_names = [] | |
для т в именах: | |
tt = trts [t] .trait_type | |
, если ( | |
hasattr (tt, «default_value_type») | |
и тт.default_value_type == 5 | |
): | |
list_names. append (t) | |
еще: | |
# Никаких черт, так что мы мало что можем сделать. | |
sub_recordables = [] | |
tnames = [] | |
list_names = [] | |
# Настроить данные реестра. | |
# Если указан идентификатор сценария, попробуйте его использовать. | |
sid = «» | |
, если script_id не None: | |
r_registry = self. _reverse_registry | |
, в то время как script_id в r_registry: | |
script_id = «% s1″% script_id | |
sid = script_id | |
# Добавить выбранный id в список special_id. | |
self._special_ids.append (sid) | |
, если родитель Нет: | |
pdata = Нет | |
, если len (sid) == 0: | |
sid = self._get_unique_name (объект) | |
еще: | |
pdata = self. _get_registry_data (родительский) | |
tnop = trait_name_on_parent | |
, если «[» в tnop: | |
# Если объект является вложенным через итератор, | |
# мы создаем его экземпляр и не обращаемся к нему через | |
# путь, это упрощает создание сценариев. | |
sid = self._get_unique_name (объект) | |
# Зарегистрируйте объект с данными. | |
data = _RegistryData ( | |
script_id = sid, | |
parent_data = pdata, | |
trait_name_on_parent = trait_name_on_parent, | |
имена = tnames, | |
sub_recordables = sub_recordables, | |
list_names = list_names, | |
) | |
реестр [объект] = данные | |
# Теперь получаем идентификатор скрипта объекта — обратите внимание, что если sid » | |
# выше, тогда script_id вычисляется из родительского. | |
sid = data.script_id | |
# Настроить обратный реестр, чтобы мы могли получить объект из | |
# script_id. | |
self._reverse_registry [sid] = объект | |
# Записать script_id, если известный аргумент явно установлен на | |
# Верно. | |
, если известно: | |
self._known_ids.append (sid) | |
# Попытайтесь установить атрибут рекордера, если необходимо. | |
, если hasattr (объект, «регистратор»): | |
попытка: | |
объект.рекордер = сам | |
кроме исключения как e: | |
msg = «Невозможно установить свойство» рекордер «объекта% r:» «% s»% ( | |
объект, | |
е, | |
) | |
предупреждений.warn (msg, warnings.RuntimeWarning) | |
, если isinstance (объект, HasTraits): | |
# Добавить обработчик для списков. | |
для имени в list_names: | |
объект.on_trait_change ( | |
сам._list_items_listner, «% s_items»% name | |
) | |
# Зарегистрируйте все дополнительные записи. | |
для имени в sub_recordables: | |
obj = getattr (объект, имя) | |
, если isinstance (объект, список): | |
# Не регистрировать сам объект, а регистрировать его | |
# дети. | |
для i, дочерний элемент в enumerate (obj): | |
attr = «% s [% d]»% (name, i) | |
саморегистратор ( | |
ребенок, родитель = объект, trait_name_on_parent = attr | |
) | |
elif obj is not None: | |
сам.регистр ( | |
obj, parent = объект, trait_name_on_parent = name | |
) | |
# Слушайте изменения в самой характеристике, чтобы новый | |
# назначенный объект также можно прослушивать. | |
объект.on_trait_change (self._object_changed_handler, имя) | |
# Теперь добавим список для самого объекта. | |
object.on_trait_change (self._listner, tnames) | |
def unregister (self, object): | |
«» «Отменить регистрацию данного объекта в регистраторе.Это инвертирует | |
логика метода `register (…)`. | |
«» « | |
registry = self._registry | |
# Ничего не делать, если объект не зарегистрирован. | |
, если объекта нет в реестре: | |
возврат | |
данные = реестр [объект] | |
# Попытайтесь сбросить атрибут рекордера, если необходимо. | |
, если hasattr (объект, «регистратор»): | |
попытка: | |
object.recorder = Нет | |
кроме исключения как e: | |
msg = «Невозможно отменить настройку» рекордера «объекта% r:» «% s»% ( | |
объект, | |
е, | |
) | |
предупреждений. warn (msg, warnings.RuntimeWarning) | |
, если isinstance (объект, HasTraits): | |
# Удалить все обработчики list_items. | |
для имени в data.list_names: | |
объект.on_trait_change ( | |
сам._list_items_listner, «% s_items»% name, remove = True | |
) | |
# Отменить регистрацию всех дополнительных записей. | |
для имени в data.sub_recordables: | |
obj = getattr (объект, имя) | |
, если isinstance (объект, список): | |
# Отменить регистрацию детей. | |
для i, дочерний элемент в enumerate (obj): | |
самостоятельная незарегистрированная (ребенок) | |
elif obj is not None: | |
саморегистратор (obj) | |
# Удалите обработчик признаков для присвоения признаков. | |
объект.on_trait_change ( | |
self._object_changed_handler, name, remove = True | |
) | |
# Теперь удалим список для самого объекта. | |
object.on_trait_change (self. _listner, data.names, remove = True) | |
# Удалить данные объекта из реестра и т. Д. | |
, если data.script_id в self._known_ids: | |
self._known_ids.remove (data.script_id) | |
del self._reverse_registry [data.script_id] | |
del registry [объект] | |
def сохранить (себя, файл): | |
«» «Сохранить записанные строки в данный файл.Не закрывается | |
файл. | |
«» « | |
file. write (self.get_code ()) | |
file.flush () | |
def record_function (self, func, args, kw): | |
«» «Записать вызов функции для данной функции и ее | |
аргументов.»» « | |
, если самозапись, а не самозапись ._в_функции: | |
# Запишите имя функции и аргументы. | |
call_str = self._function_as_string (func, args, kw) | |
# Вызов функции. | |
попытка: | |
сам. _in_function = Истина | |
результат = func (* args, ** kw) | |
наконец: | |
self._in_function = Ложь | |
# Зарегистрируйте результат, если он не равен None. | |
, если func.__name__ == «__init__»: | |
f_self = args [0] | |
код = self._import_class_string (f_self .__ class__) | |
self.lines.append (код) | |
return_str = self._registry.get (f_self) .script_id | |
еще: | |
return_str = self. _return_as_string (результат) | |
, если len (return_str)> 0: | |
self.lines.append («% s =% s»% (return_str, call_str)) | |
еще: | |
self.lines.append («% s»% (call_str)) | |
еще: | |
результат = func (* args, ** kw) | |
вернуть результат | |
по умолчанию ui_save (сам): | |
«» «Сохранить запись в файл, откройте диалоговое окно пользовательского интерфейса, чтобы узнать, где именно | |
и закройте файл, когда закончите. | |
«» « | |
из pyface.api import FileDialog, OK | |
wildcard = «Файлы Python (* .py) | * .py |» + FileDialog.WILDCARD_ALL | |
dialog = FileDialog ( | |
title = «Сохранить сценарий», действие = «сохранить как», подстановочный знак = подстановочный знак | |
) | |
, если диалог.open () == ОК: | |
fname = dialog.path | |
f = open (fname, «w») | |
self. save (f) | |
f.close () | |
def ясно (сам): | |
«» «Очищает все предыдущие записанные состояния и отменяет регистрацию всех | |
зарегистрированных объектов.»» « | |
# Сначала отмените регистрацию любых зарегистрированных объектов. | |
registry = self._registry | |
, а len (реестр)> 0: | |
self.unregister (list (registry.keys ()) [0]) | |
# Очистить различные списки. | |
сам.строки [:] = [] | |
self._registry.clear () | |
self._known_ids [:] = [] | |
self._name_map.clear () | |
self._reverse_registry.clear () | |
self._known_types [:] = [] | |
self._special_ids [:] = [] | |
по умолчанию get_code (сам): | |
«» «Возвращает записанные строки как строку печатаемого кода.»» « | |
return «\ n» . join (self.lines) + «\ n» | |
def is_registered (я, объект): | |
«» «Возвращает True, если данный объект зарегистрирован в | |
регистратор. «» « | |
вернуть объект в себя._registry | |
def get_script_id (сам, объект): | |
«» «Возвращает script_id зарегистрированного объекта. Полезно, когда | |
, вы хотите вручную добавить оператор записи. «» « | |
вернуть self._get_registry_data (объект) . script_id | |
def get_object_path (сам, объект): | |
«» «Возвращает путь в иерархии объектов зарегистрированного | |
объект.Полезно для отладки. «» « | |
вернуть self._get_registry_data (объект) .path | |
def write_script_id_in_namespace (self, script_id): | |
«» «Если script_id не известен в пространстве имен текущего сценария, | |
это устанавливает его, используя путь объекта или фактически | |
, создающий его экземпляр. Если это невозможно (так как script_id | |
не соответствует ни одному существующему объекту), ничего не записывается, кроме | |
Платформа | уведомляется о том, что доступен конкретный script_id |
в пространстве имен. Это полезно, если вы хотите ввести код | |
в пространстве имен для создания конкретного объекта. | |
«» « | |
, если не самозапись: | |
возврат | |
known_ids = self._known_ids | |
, если script_id отсутствует в known_ids: | |
obj = self. _reverse_registry.get (script_id) | |
# Добавить ID к известным_ID. | |
known_ids.append (script_id) | |
, если объект не равен None: | |
data = self._registry.get (obj) | |
результат = «» | |
, если len (data.path)> 0: | |
# Код записи для создания экземпляра объекта. | |
result = «% s =% s»% (script_id, data.path) | |
еще: | |
# Это не лучший вариант, но лучше, чем | |
# ничего. | |
результат = self._import_class_string (obj .__ class__) | |
cls = объект.__класс __.__ имя__ | |
результат + = «\ n% s =% s ()»% (script_id, cls) | |
, если len (результат)> 0: | |
self.lines.extend (result.split («\ n»)) | |
############################################## ######################### | |
# Непубличный интерфейс. | |
############################################## ######################### | |
def _get_unique_name (self, obj): | |
«» «Возвращает уникальное имя объекта (строку). Обратите внимание, что это | |
не кэширует объект, поэтому при вызове с одним и тем же объектом 3 раза | |
вы получите три разных имени. | |
«» « | |
cname = объект .__ класс __.__ имя__ | |
нм = self._name_map | |
результат = «» | |
builtin = False | |
, если cname во встроенных .__ dict__: | |
builtin = True | |
, если hasattr (obj, «__name__»): | |
cname = obj. __name__ | |
еще: | |
cname = camel_case_to_python (cname) | |
special_ids = self._special_ids | |
, а len (результат) == 0 или результат special_ids: | |
, если имя в нм: | |
id = nm [cname] + 1 | |
нм [cname] = id | |
result = «% s% d»% (cname, id) | |
еще: | |
нм [cname] = 0 | |
# Первый идентификатор не нуждается в числе, если он не является встроенным. | |
, если встроенный: | |
result = «% s0″% (cname) | |
еще: | |
результат = cname | |
вернуть результат | |
def _get_registry_data (сам, объект): | |
«» «Получить данные для объекта из реестра.»» « | |
data = self._registry.get (объект) | |
, если данных нет: | |
сообщение = ( | |
«Рекордер: невозможно получить script_id, поскольку объект% s не зарегистрирован» | |
) | |
поднять ошибку RecorderError (сообщение% (объект)) | |
вернуть данные | |
def _listner (я, объект, имя, старый, новый): | |
«» «Список изменений характеристик объекта. | |
Это вызывается дочерними списками или когда любой из записываемых | |
Свойства объекта | изменяются при включении записи в скрипт. |
Параметры: | |
———— | |
объект: Объект, который был изменен. | |
name: расширенное имя измененного атрибута. | |
old: старое значение. | |
new: Новое значение. | |
«» « | |
, если сам.запись, а не себя ._в_функции: | |
new_repr = repr (новый) | |
sid = self._get_registry_data (объект) .script_id | |
, если len (sid) == 0: | |
msg = «% s =% r»% (имя, новое) | |
еще: | |
msg = «% s.% s =% r «% (sid, name, new) | |
, если new_repr. startswith («<") и new_repr.endswith (">«): | |
self.record («#» + msg) | |
еще: | |
самозапись (сообщение) | |
def _list_items_listner (я, объект, имя, старый, событие): | |
«» «Составитель списка * _items в списке характеристик объекта.»» « | |
# Установить путь к зарегистрированным объектам в модифицированном списке и | |
# все их дети. Это делается путем отмены регистрации объекта | |
# и перерегистрировать их. Это медленно, но. | |
registry = self._registry | |
sid = реестр.получить (объект) .script_id | |
trait_name = name [: — 6] | |
items = getattr (объект, trait_name) | |
для (i, item) в enumerate (items): | |
, если элемент в реестре: | |
data = registry.get (элемент) | |
tnop = данные.trait_name_on_parent | |
, если len (tnop)> 0: | |
data.trait_name_on_parent = «% s [% d]»% (trait_name, i) | |
# Запишите изменение. | |
, если самозапись, а не самозапись ._в_функции: | |
индекс = событие.индекс | |
удалено = событие удалено | |
добавлено = событие добавлено | |
nr = len (удалено) | |
slice = «[% d:% d]»% (index, index + nr) | |
rhs = [self._object_as_string (элемент) для элемента в добавленном] | |
rhs = «,».присоединиться (RHS) | |
obj = «% s.% S»% (sid, name [: — 6]) | |
msg = «% s% s = [% s]»% (obj, slice, rhs) | |
самозапись (сообщение) | |
def _object_changed_handler (я, объект, имя, старый, новый): | |
«» «Вызывается при переназначении записываемого дочернего объекта. «» « | |
registry = self._registry | |
, если старый — нет Нет: | |
, если старый в реестре: | |
саморегистратор (старый) | |
, если новых нет Нет: | |
, если нового нет в реестре: | |
сам.register (новый, родительский = объект, trait_name_on_parent = name) | |
def _get_script (сам): | |
возврат self.get_code () | |
def _analyze_code (сам, код): | |
«» «Проанализировать код и при необходимости вернуть дополнительный код. «» « | |
lhs = «» | |
попытка: | |
lhs = code.split () [0] | |
, кроме IndexError: | |
пасс | |
, если «.» в лш: | |
ob_name = lhs.split («.») [0] | |
self.write_script_id_in_namespace (ob_name) | |
def _function_as_string (self, func, args, kw): | |
«» «Вернуть строку, представляющую вызов функции. » «» | |
func_name = func .__ name__ | |
func_code = func.__code__ | |
# Даже если func действительно декорированный метод, он никогда не отображается как | |
# здесь связанный или несвязанный метод, поэтому мы должны проверить | |
# имена аргументов, чтобы выяснить, является ли это методом или функцией. | |
, если func_code.co_argcount> 0 и func_code.co_varnames [0] == «self»: | |
# Это метод, первый аргумент привязан к self. | |
f_self = args [0] | |
# Преобразуйте остальные аргументы в строки. | |
argl = [self._object_as_string (arg) для аргумента в args [1:]] | |
# Если это __init__, мы делаем его особенным. | |
, если func_name == «__init__»: | |
# Зарегистрируйте объект. | |
self.register (f_self, known = True) | |
func_name = f_self .__ class __.__ name__ | |
еще: | |
sid = self._object_as_string (f_self) | |
func_name = «% s.% S»% (sid, func_name) | |
еще: | |
argl = [self. _object_as_string (arg) для аргумента в args] | |
# Преобразовать ключевое слово args. | |
кВт / л = [ | |
«% s =% s»% (ключ, self._object_as_string (значение)) | |
для ключа, значение в kw.items () | |
] | |
argl.удлинить (кВт) | |
# Создайте строковое представление аргументов, кВт. | |
argstr = «,» .join (argl) | |
вернуть «% s (% s)»% (func_name, argstr) | |
def _is_arbitrary_object (сам, объект): | |
«» «Вернуть True, если объект является произвольным, не примитивным объектом. | |
Мы предполагаем, что если шестнадцатеричный идентификатор объекта находится в его строке | |
, то это произвольный объект. | |
«» « | |
ob_id = id (объект) | |
orepr = repr (объект) | |
hex_id = «% x»% ob_id | |
вернуть hex_id.верхний () в ореп. верхний () | |
def _object_as_string (я, объект): | |
«» «Вернуть строку, представляющую объект. » «» | |
registry = self._registry | |
, если объект в реестре: | |
# Вернуть id скрипта, если объект известен; создать скрипт | |
# id в пространстве имен, если нужно перед этим. | |
sid = registry.get (объект) .script_id | |
base_id = sid.split («.») [0] | |
self.write_script_id_in_namespace (base_id) | |
возврат sid | |
еще: | |
, если не сам._is_arbitrary_object (объект): | |
return repr (объект) | |
# Если мы попали сюда, мы просто зарегистрируем объект и назовем себя | |
# снова, чтобы сделать необходимое. | |
самореестр (объект) | |
возврат сам._object_as_string (объект) | |
def _return_as_string (я, объект): | |
«» «Возвращает строку, заданную возвращенным объектом из функции.» «» | |
результат = «» | |
ignore = (float, complex, bool, int, str) | |
, если объект не равен None и тип (объект) не игнорируется: | |
# Если объект не известен, зарегистрируйте его. | |
registry = self. _registry | |
, если объекта нет в реестре: | |
самореестр (объект) | |
результат = registry.get (объект) .script_id | |
# Поскольку он возвращается, он известен в пространстве имен. | |
known_ids = self._known_ids | |
, если результат не в known_ids: | |
known_ids.append (результат) | |
вернуть результат | |
def _import_class_string (self, cls): | |
«» «При необходимости импортируйте класс. » «» | |
cname = cls.__name__ | |
результат = «» | |
, если cname не во встроенных .__ dict__: | |
мод = cls .__ модуль__ | |
typename = «% s.% S»% (mod, cname) | |
, если typename не в self._known_types: | |
result = «from% s import% s»% (mod, cname) | |
сам._known_types.append (имя_типа) | |
вернуть результат |
# (C) Copyright 2005-2021 Enthought, Inc. , Остин, Техас | |
# Все права защищены. | |
# | |
# Это программное обеспечение предоставляется без гарантии в соответствии с условиями BSD | |
# лицензия включена в ЛИЦЕНЗИЮ.txt и может распространяться только под номером | |
# условия, описанные в вышеупомянутой лицензии. Лицензия | |
# также доступен в Интернете по адресу http://www.enoughtt.com/licenses/BSD.txt | |
# | |
# Спасибо за использование открытого исходного кода Enthought! | |
«» «Этот модуль предоставляет код, который позволяет выбрать состояние | |
объект Python в словарь. | |
Мотивация для этого проста. Стандартный Python | |
Машина для травления / разборки | лучше всего подходит для маринования простых предметов, а не |
слишком хорошо работает со сложным кодом. В частности, есть два основных | |
проблемы (1) формат файла pickle не просто редактировать с текстом | |
и (2) когда маринованный огурчик, он создает все | |
необходимых объектов и задает состояние этих объектов. | |
Проблема (2) может не показаться проблемой. Однако часто | |
для определения всего «состояния» приложения требуется | |
знание состояния многих объектов, которых на самом деле нет в | |
Касаются | пользователей. Пользователь в идеале хотел бы мариновать именно то, что он |
считает актуальным.Теперь, учитывая, что пользователь не собирается сохранять | |
полное состояние приложения, использование рассола недостаточно | |
, поскольку состояние больше не полностью известно (или его стоит знать). Модель | |
по умолчанию `Unpickler` воссоздает объекты и типичный | |
Реализация | `__setstate__` обычно просто обновляет |
атрибут объекта `__dict__`. Этого недостаточно, потому что маринованный | |
информация вырвана из реального контекста при сохранении. | |
StatePickler в основном собирает «состояние» объекта в | |
большой словарь. Эти маринованные данные могут быть легко извлечены и | |
изменено в интерпретаторе или отредактировано в текстовом редакторе | |
(`pprint.saferepr` — друг). Вторая проблема тоже | |
исключено. Когда это состояние не выбирается с помощью StateUnpickler, что | |
— это специальный словарь (экземпляр State). Это позволяет одному | |
для навигации по состоянию, как и для исходного объекта. Его до | |
пользователь может создавать любые новые объекты и устанавливать их состояния с помощью этого | |
информация.Это обеспечивает большую гибкость при одновременном использовании одного | |
, чтобы сохранить и установить состояние (почти) любого объекта Python. | |
Класс StateSetter помогает установить состояние известного экземпляра. Когда | |
устанавливает состояние экземпляра, который он проверяет, чтобы увидеть, есть ли | |
метод `__set_pure_state__`, который, в свою очередь, вызывает` StateSetter.набор` | |
соответственно. | |
Дополнительно есть поддержка управления версиями. Версия класса | |
получить из атрибута класса __version__. Эта версия по | |
с версиями баз класса встроен в | |
метаданных состояния и сохранены.Используя `version_registry.py` | |
пользователь может зарегистрировать обработчик для определенного класса и модуля. Когда | |
состояние объекта устанавливается с помощью StateSetter.set_state, затем | |
, эти обработчики вызываются в обратном порядке их MRO. Это дает | |
обработчик имеет возможность модернизировать состояние в зависимости от его | |
версия. Встроенные классы не сканируются на наличие версий. Если класс | |
не имеет версии, тогда по умолчанию предполагается -1. | |
Пример :: | |
>>> класс A: | |
… def __init __ (сам): | |
… self.a = ‘а’ | |
… | |
>>> а = А () | |
>>> а.а = 100 | |
>>> импорт state_pickler | |
>>> s = state_pickler. dumps (a) # Дамп состояния `a`. | |
>>> state = state_pickler.loads_state (s) # Вернуть состояние. | |
>>> b = state_pickler.create_instance (state) # Создаем объект. | |
>>> state_pickler.set_state (b, state) # Устанавливаем состояние объекта. | |
>>> assert b.a == 100 | |
Характеристики | |
——— | |
— На выходе получается простой старый словарь, поэтому его легко анализировать, редактировать и т. Д. | |
— Обрабатывает ссылки, чтобы избежать дублирования. | |
— Gzips Числовые массивы при их сбросе. | |
— Поддержка управления версиями. | |
Предупреждения | |
——- | |
— не обрабатывает целую кучу вещей, включая объекты кода и | |
функций. | |
— Вывод представляет собой чистый словарь и не содержит экземпляров. Итак, | |
, используя это * как есть * в `__setstate__`, работать не будет. Вместо | |
определите __set_pure_state__ и используйте класс StateSetter или | |
функция `set_state`, предоставляемая этим модулем. | |
Банкноты | |
—— | |
Просмотр кода из XMarshaL_ и pickle.ру оказался полезным для | |
идей. Однако ни один код не взят оттуда. | |
. . _XMarshaL: http://www.dezentral.de/soft/XMarshaL | |
«» « | |
# Автор: Прабху Рамачандран | |
# Авторские права (c) 2005-2015, Enthought, Inc. | |
# Лицензия: BSD Style. | |
# Импорт стандартной библиотеки. | |
импортная база64 | |
импортная система | |
маринад импортный | |
импорт gzip | |
из io импорт BytesIO, StringIO | |
импортный номер | |
# Местный импорт. | |
с. import version_registry | |
из .file_path import FilePath | |
NumpyArrayType = тип (numpy.array ([])) | |
def gzip_string (данные): | |
«» «Данная строка (` data`) архивирует строку и возвращает ее.»» « | |
с = BytesIO () | |
writer = gzip.GzipFile (mode = «wb», fileobj = s) | |
writer. write (данные) | |
writer.close () | |
s.seek (0) | |
возврат s.read () | |
def gunzip_string (данные): | |
«» «Учитывая сжатую строку (` data`), она распаковывает строку и | |
возвращает его. | |
«» « | |
, если тип (данные) байты: | |
с = BytesIO (данные) | |
еще: | |
с = StringIO (данные) | |
writer = gzip. GzipFile (mode = «rb», fileobj = s) | |
данные = писатель.читать () | |
writer.close () | |
вернуть данные | |
класс StatePicklerError (исключение): | |
пасс | |
класс StateUnpicklerError (исключение): | |
пасс | |
класс StateSetterError (исключение): | |
пасс | |
############################################## #################### | |
# `State` класс | |
############################################## #################### | |
класс State (дикт): | |
«» «Используется для инкапсуляции состояния экземпляра в очень | |
удобная форма. Атрибут / ключ __metadata__ — это словарь | |
, который имеет специфические для класса детали, такие как имя класса, имя модуля | |
и т. Д. | |
«» « | |
def __init __ (self, ** кВт): | |
dict .__ init __ (сам, ** кВт) | |
сам.__dict__ = сам | |
############################################## #################### | |
# класс StateDict | |
############################################## #################### | |
класс StateDict (диктат): | |
«» «Используется для инкапсуляции словаря, хранящегося в экземпляре` State`. | |
Атрибут has_instance указывает, есть ли у dict экземпляр | |
В него встроено | . |
«» « | |
def __init __ (self, ** кВт): | |
dict .__ init __ (сам, ** кВт) | |
сам.has_instance = Ложь | |
############################################## #################### | |
# класс StateList | |
############################################## #################### | |
класс StateList (список): | |
«» «Используется для инкапсуляции списка, хранящегося в экземпляре` State`. Модель | |
Атрибут | has_instance указывает, есть ли в списке экземпляр |
В него встроено | . |
«» « | |
def __init __ (self, seq = None): | |
, если seq: | |
лист.__init __ (self, seq) | |
еще: | |
list .__ init __ (сам) | |
self.has_instance = Ложь | |
############################################## #################### | |
# класс StateTuple | |
############################################## #################### | |
класс StateTuple (кортеж): | |
«» «Используется для инкапсуляции кортежа, хранящегося в экземпляре` State`. Модель | |
Атрибут | has_instance указывает, есть ли в кортеже экземпляр |
В него встроено | . |
«» « | |
def __new __ (cls, seq = None): | |
, если seq: | |
объект = супер (StateTuple, cls).__new __ (cls, кортеж (seq)) | |
еще: | |
obj = super (StateTuple, cls) .__ новый __ (cls) | |
obj.has_instance = Ложь | |
возврат obj | |
############################################## #################### | |
# класс StatePickler | |
############################################## #################### | |
класс StatePickler: | |
«» «Сохраняет состояние объекта в словарь. Модель | |
Сам словарь | либо сохраняется в виде файла (`dump`), либо |
маринованная струна («отвалы»). В качестве альтернативы, метод `dump_state` | |
вернет маринованный словарь. | |
Формат государственного дикта достаточно строгий. Основные типы | |
(bool, int, long, float, complex, None, string) равно | |
представлены как есть.Все остальное хранится как | |
словарь, содержащий информацию метаданных о типе объекта | |
и т. Д. , А также фактический объект в ключе «данные». Например :: | |
>>> p = StatePickler () | |
>>> p.dump_state (1) | |
1 | |
>>> l = [1,2.0, Нет, [1,2,3]] | |
>>> p.dump_state (l) | |
{‘данные’: [1, 2.0, Нет, {‘данные’: [1, 2, 3], ‘тип’: ‘список’, ‘идентификатор’: 1}], | |
‘id’: 0, | |
‘тип’: ‘список’} | |
Классы также представлены аналогично. Состояние в данном случае — | |
, полученный из метода __getstate__ или из __dict__. | |
Вот пример :: | |
>>> класс A: | |
… __version__ = 1 # Версия состояния | |
… def __init __ (сам): | |
… self.attribute = 1 | |
… | |
>>> а = А () | |
>>> p = StatePickler () | |
>>> p.dump_state (a) | |
{‘имя_класса’: ‘А’, | |
‘data’: {‘data’: {‘attribute’: 1}, ‘type’: ‘dict’, ‘id’: 2}, | |
‘id’: 0, | |
‘initargs’: {‘данные’: (), ‘тип’: ‘кортеж’, ‘идентификатор’: 1}, | |
‘модуль’: ‘__main__’, | |
‘тип’: ‘экземпляр’, | |
‘версия’: [((‘A’, ‘__main__’), 1)]} | |
При травлении данных учитываются ссылки. Числовые массивы | |
могут быть обработаны и сохранены в виде строки, закодированной в формате gzip base64. | |
«» « | |
def __init __ (сам): | |
self._clear () | |
type_map = { | |
bool: self._do_basic_type, | |
комплекс: self._do_basic_type, | |
с плавающей точкой: self._do_basic_type, | |
интервал: self. _do_basic_type, | |
тип (Нет): self._do_basic_type, | |
ул.: Self._do_basic_type, | |
байт: сам._do_basic_type, | |
кортеж: self._do_tuple, | |
список: self._do_list, | |
dict: self._do_dict, | |
NumpyArrayType: self._do_numeric, | |
Состояние: self._do_state, | |
} | |
сам.type_map = type_map | |
def дамп (собственное, значение, файл): | |
«» «Выбирает состояние объекта (` value`) в переданный | |
файл. | |
«» « | |
попытка: | |
# Сохраните имя файла, в который мы пишем, чтобы мы могли изменить | |
# подходящие пути к файлам. | |
self.file_name = file.name | |
, кроме AttributeError: | |
пасс | |
pickle.dump (self._do (значение), файл) | |
def dumps (self, value): | |
«» «Выбирает состояние объекта (` value`) и возвращает | |
строка. | |
«» « | |
вернуть pickle.dumps (self._do (значение)) | |
def dump_state (self, value): | |
«» «Возвращает словарь или базовый тип, представляющий | |
полное состояние объекта («значение»). | |
Это значение подбирается методами dump и dumps. | |
«» « | |
вернуть self._do (значение) | |
############################################## #################### | |
# Непубличные методы | |
############################################## #################### | |
def _clear (сам): | |
# Сохраняет имя файла, используемого для дампа | |
# состояние. Это используется для изменения любых встроенных путей относительно | |
# в сохраненный файл. | |
self.file_name = «» | |
# Кеширует идентификаторы для обработки ссылок. | |
self.obj_cache = {} | |
# Разный кеш для кеширования нестабильных вещей. Для | |
# пример, объект.__getstate __ () / __ getinitargs __ () обычно | |
# возвращает копию словаря / кортежа, который может быть использован повторно | |
# на __getstate__ другого объекта. Кэширование этих препятствий | |
# некоторые странные проблемы с `id` объекта. | |
self._misc_cache = [] | |
def _flush_traits (себя, объект): | |
«» «Проверяет, есть ли у объекта признаки, и гарантирует, что признаки | |
установлены в `__dict__`, поэтому мы можем его засолить. | |
«» « | |
# Не требуется с Traits3. | |
def _do (self, obj): | |
obj_type = тип (объект) | |
ключ = self. _get_id (obj) | |
, если ввести self.obj_cache: | |
вернуть self._do_reference (obj) | |
elif obj_type в self.type_map: | |
return self.type_map [obj_type] (obj) | |
elif isinstance (объект, кортеж): | |
# Заботится о StateTuples. | |
возврат сам._do_tuple (объект) | |
elif isinstance (объект, список): | |
# Заботится о TraitListObjects. | |
вернуть self._do_list (obj) | |
elif isinstance (obj, dict): | |
# Заботится о TraitDictObjects. | |
возврат сам._do_dict (obj) | |
elif hasattr (obj, «__dict__»): | |
вернуть self._do_instance (obj) | |
def _get_id (self, value): | |
попытка: | |
ключ = хэш (значение) | |
, кроме TypeError: | |
ключ = id (значение) | |
ключ возврата | |
def _register (self, value): | |
ключ = сам. _get_id (значение) | |
кеш = self.obj_cache | |
idx = len (кеш) | |
cache [ключ] = idx | |
возврат idx | |
def _do_basic_type (self, value): | |
возвращаемое значение | |
def _do_reference (себя, значение): | |
ключ = сам._get_id (значение) | |
idx = self.obj_cache [ключ] | |
return dict (type = «reference», id = idx, data = None) | |
def _do_instance (self, value): | |
# Вычеркните черты характера. | |
self._flush_traits (значение) | |
# Настроить относительные пути к FilePaths перед сбросом. | |
, если self.file_name и isinstance (значение, FilePath): | |
value.set_relative (собственное имя_файла) | |
# Получаем аргументы инициализации. | |
аргументов = () | |
, если hasattr (значение, «__getinitargs__») и значение.__getinitargs__: | |
args = значение .__ getinitargs __ () | |
# Получить состояние объекта. | |
, если hasattr (значение, «__get_pure_state__»): | |
состояние = значение .__ get_pure_state __ () | |
elif hasattr (значение, «__getstate__»): | |
состояние = значение.__getstate __ () | |
еще: | |
состояние = значение .__ dict__ | |
state.pop («__ traits_version__», Нет) | |
# Кэшируйте аргументы и состояние, так как они могут быть gc’d. | |
сам. _misc_cache.extend ([аргументы, состояние]) | |
# Зарегистрируйтесь и обработайте. | |
idx = self._register (значение) | |
args_data = self._do (аргументы) | |
data = self._do (состояние) | |
# Получить версию объекта. | |
version = version_registry.get_version (значение) | |
модуль = значение .__ класс __.__ модуль__ | |
имя_класса = значение .__ класс __.__ имя__ | |
return dict ( | |
type = «instance», | |
модуль = модуль, | |
имя_класса = имя_класса, | |
версия = версия, | |
id = idx, | |
initargs = args_data, | |
данные = данные, | |
) | |
def _do_state (self, value): | |
метаданные = значение. __metadata__ | |
args = metadata.get («initargs») | |
состояние = dict (значение) | |
state.pop («__ метаданные__») | |
self._misc_cache.extend ([аргументы, состояние]) | |
idx = сам._register (значение) | |
args_data = self._do (аргументы) | |
data = self._do (состояние) | |
return dict ( | |
type = «instance», | |
модуль = метаданные [«модуль»], | |
имя_класса = метаданные [«имя_класса»], | |
версия = метаданные [«версия»], | |
id = idx, | |
initargs = args_data, | |
данные = данные, | |
) | |
def _do_tuple (self, value): | |
idx = сам. _register (значение) | |
data = tuple ([self._do (x) for x in value]) | |
return dict (type = «tuple», id = idx, data = data) | |
def _do_list (себя, значение): | |
idx = self._register (значение) | |
data = [self._do (x) вместо x в значении] | |
return dict (type = «list», id = idx, data = data) | |
def _do_dict (себя, значение): | |
idx = self._register (значение) | |
vals = [self. _do (x) for x in value.values ()] | |
data = dict (zip (value.ключи (), валс)) | |
return dict (type = «dict», id = idx, data = data) | |
def _do_numeric (self, value): | |
idx = self._register (значение) | |
данные = base64.encodebytes (gzip_string (numpy.ndarray.dumps (значение))) | |
return dict (type = «numeric», id = idx, data = data) | |
############################################## #################### | |
# класс StateUnpickler | |
############################################## #################### | |
класс StateUnpickler: | |
«» «Распаковывает состояние объекта, сохраненного с помощью StatePickler. | |
Обратите внимание, что в отличие от стандартного Unpickler, экземпляры | |
созданы какие-то пользовательские классы. Данные по состоянию получены | |
из файла или строки, ссылочные объекты настраиваются для ссылки на | |
то же значение состояния, и это состояние возвращается в форме | |
обычно в виде словаря.Например :: | |
>>> класс A: | |
… def __init __ (сам): | |
. .. self.attribute = 1 | |
… | |
>>> а = А () | |
>>> p = StatePickler () | |
>>> s = п.отвалы (а) | |
>>> вверх = StateUnpickler () | |
>>> состояние = up.loads_state (s) | |
>>> состояние .__ класс __.__ имя__ | |
«Государство» | |
>>> state.attribute | |
1 | |
>>> гос.__metadata__ | |
{‘имя_класса’: ‘А’, | |
‘has_instance’: Верно, | |
‘id’: 0, | |
‘initargs’: (), | |
‘модуль’: ‘__main__’, | |
‘тип’: ‘экземпляр’, | |
‘версия’: [((‘A’, ‘__main__’), -1)]} | |
Обратите внимание, что состояние на самом деле является экземпляром State и равно | |
навигация, как и исходный объект. Детали | |
хранятся в атрибуте `__metadata__`. Это | |
очень удобен, так как его можно просмотреть, а | |
очень легко изменить состояние. | |
«» « | |
def __init __ (сам): | |
сам._clear () | |
self.type_map = { | |
«ссылка»: self._do_reference, | |
«экземпляр»: self._do_instance, | |
«кортеж»: self._do_tuple, | |
«список»: self. _do_list, | |
«дикт»: сам._do_dict, | |
«числовой»: self._do_numeric, | |
} | |
def load_state (сам, файл): | |
«» «Возвращает состояние объекта, загруженного из обработанных данных | |
в данном файле. | |
«» « | |
попытка: | |
сам.имя_файла = имя_файла | |
, кроме AttributeError: | |
пасс | |
data = pickle. load (файл) | |
результат = self._process (данные) | |
вернуть результат | |
def load_state (self, строка): | |
«» «Возвращает состояние объекта, загруженного из обработанных данных | |
в данной строке. | |
«» « | |
data = pickle.loads (строка) | |
результат = self._process (данные) | |
вернуть результат | |
############################################## #################### | |
# Непубличные методы | |
############################################## #################### | |
def _clear (сам): | |
# Файл, из которого мы загружаемся. | |
self.file_name = «» | |
# Кэш объектов. | |
self._obj_cache = {} | |
# Пути к экземплярам. | |
self._instances = [] | |
# Кэширует ссылки. | |
сам._refs = {} | |
# Числовые массивы. | |
self._numeric = {} | |
def _set_has_instance (self, obj, value): | |
, если isinstance (объект, состояние): | |
obj . __ metadata __ [«has_instance»] = значение | |
elif isinstance (объект, (StateDict, StateList, StateTuple)): | |
obj.has_instance = значение | |
def _process (self, data): | |
результат = self._do (данные) | |
# Настроить все числовые массивы. Сделайте это сначала с | |
# ссылки используют это. | |
для ключа (path, val) в self._numeric.items (): | |
, если isinstance (результат, StateTuple): | |
результат = список (результат) | |
exec («результат% s = val»% путь) | |
результат = StateTuple (результат) | |
еще: | |
exec («результат% s = val»% путь) | |
# Установите ссылки, чтобы они действительно были ссылками. | |
для ключа, пути в self._refs.items (): | |
для пути в путях: | |
x = self._obj_cache [ключ] | |
, если isinstance (результат, StateTuple): | |
результат = список (результат) | |
exec («результат% s = x»% путь) | |
результат = StateTuple (результат) | |
еще: | |
exec («результат% s = x»% путь) | |
# если ссылка на экземпляр, добавьте его путь. | |
, если isinstance (x, State): | |
self. _instances.append (путь) | |
# Теперь настройте атрибут has_instance. Если has_instance | |
# True, тогда объект содержит где-то экземпляр | |
# внутри. | |
для пути в self._instances: | |
pth = путь | |
, а pth: | |
нс = {«результат»: результат} | |
exec («val = result% s»% pth, ns, ns) | |
self._set_has_instance (ns [«val»], True) | |
конец = пт. rfind («[«) | |
pth = pth [: конец] | |
# Теперь убедитесь, что первый элемент также has_instance. | |
self._set_has_instance (результат, True) | |
вернуть результат | |
def _do (self, data, path = «»): | |
, если тип (данные) dict: | |
возврат сам.type_map [данные [«тип»]] (данные, путь) | |
еще: | |
вернуть данные | |
def _do_reference (self, value, path): | |
id = значение [«id»] | |
, если идентификатор в self. _refs: | |
сам._refs [id] .append (путь) | |
еще: | |
self._refs [id] = [путь] | |
вернуть состояние (__ метаданные __ = значение) | |
def _handle_file_path (self, value): | |
, если ( | |
(значение [«class_name»] == «FilePath») | |
и («file_path» в значении [«module»]) | |
и сам.имя_файла | |
): | |
данные = значение [«данные»] [«данные»] | |
fp = FilePath (данные [«rel_pth»]) | |
fp. set_absolute (собственное имя_файла) | |
данные [«abs_pth»] = fp.abs_pth | |
def _do_instance (self, value, path): | |
сам._instances.append (путь) | |
initargs = self._do ( | |
значение [«initargs»], путь + ‘.__ метаданные __ [«initargs»]’ | |
) | |
# Обработка файловых путей. | |
self._handle_file_path (значение) | |
d = сам. _do (значение [«данные»], путь) | |
md = dict ( | |
type = «instance», | |
модуль = значение [«модуль»], | |
имя_класса = значение [«имя_класса»], | |
версия = значение [«версия»], | |
id = значение [«id»], | |
initargs = initargs, | |
has_instance = True, | |
) | |
результат = Состояние (** d) | |
результат. __metadata__ = md | |
self._obj_cache [значение [«id»]] = результат | |
вернуть результат | |
def _do_tuple (себя, значение, путь): | |
res = [] | |
для i, x в перечислении (значение [«данные»]): | |
рез.append (self._do (x, path + «[% d]»% i)) | |
результат = StateTuple (res) | |
self._obj_cache [значение [«id»]] = результат | |
вернуть результат | |
def _do_list (self, value, path): | |
результат = StateList () | |
для i, x в перечислении (значение [«данные»]): | |
результат. append (self._do (x, path + «[% d]»% i)) | |
self._obj_cache [значение [«id»]] = результат | |
вернуть результат | |
def _do_dict (self, value, path): | |
результат = StateDict () | |
для ключа, значение в значении [«данные»].пунктов (): | |
результат [ключ] = self._do (val, path + ‘[«% s»]’% ключ) | |
self._obj_cache [значение [«id»]] = результат | |
вернуть результат | |
def _do_numeric (self, value, path): | |
данные = значение [«данные»] | |
, если isinstance (data, str): | |
данные = значение [«данные»]. кодировать («utf-8») | |
мусор = gunzip_string (base64.decodebytes (данные)) | |
результат = pickle.loads (junk, encoding = «bytes») | |
self._numeric [значение [«id»]] = (путь, результат) | |
self._obj_cache [значение [«id»]] = результат | |
вернуть результат | |
############################################## #################### | |
# класс StateSetter | |
############################################## #################### | |
класс StateSetter: | |
«» «Это удобный класс, который помогает пользователю настроить | |
атрибутов объекта с учетом его сохраненного состояния. Например, это | |
проверяет, существует ли метод __set_pure_state__, и вызывает | |
, что когда он устанавливает состояние. | |
«» « | |
def __init __ (сам): | |
# Сохраняет идентификаторы уже выполненных экземпляров. | |
self._instance_ids = [] | |
self.type_map = { | |
Состояние: self._do_instance, | |
StateTuple: self.do_tuple, | |
StateList: self. _do_list, | |
StateDict: сам._do_dict, | |
} | |
def set (self, obj, state, ignore = None, first = None, last = None): | |
«» «Устанавливает состояние объекта. | |
Это должно использоваться как средство для упрощения загрузки состояния | |
объект из его метода `__setstate__` с использованием словаря | |
, описывающий его состояние.Обратите внимание, что до установки состояния | |
зарегистрированных обработчиков для определенного класса вызываются в | |
приказ обновить гос версию до последней | |
версия. | |
Параметры | |
———- | |
— объект: `объект` | |
Объект, состояние которого должно быть установлено.Если это `None` | |
(по умолчанию), то объект создается. | |
— состояние: `dict` | |
Словарь, представляющий состояние объекта. | |
— игнорировать: `list (str)` | |
Список атрибутов, указанных в этом списке, игнорируется | |
, и состояние этих атрибутов не задано (исключая | |
те, которые указаны в `first` и` last`).Если указать | |
a ‘*’, тогда все атрибуты игнорируются, кроме | |
указан в `first` и` last`. | |
— первый: `list (str)` | |
Список атрибутов, указанных в этом списке, устанавливается первым (в | |
) перед установкой любых других атрибутов. | |
— последняя: `list (str)` | |
Список атрибутов, указанных в этом списке, устанавливается последним (в | |
) после установки всех остальных атрибутов. | |
«» « | |
если (не isinstance (состояние, состояние)), а состояние.__метаданные __ [ | |
«тип» | |
]! = «Instance»: | |
поднять StateSetterError ( | |
«Можно устанавливать только атрибуты экземпляра». | |
) | |
# Обновите состояние до последнего с помощью реестра. | |
self._update_and_check_state (объект, состояние) | |
self.register (obj) | |
# Эта странность необходима, поскольку собственные `ключи` государства могут | |
# установить на другое значение. | |
state_keys = список (дикт.ключи (гос.)) | |
state_keys. remove («__ метаданные__») | |
, если первый — Нет: | |
первый = [] | |
, если последний — Нет: | |
последняя = [] | |
# Убрать все игнорируемые ключи. | |
, если игнорировать: | |
если «*» в игнорировании: | |
state_keys = первый + последний | |
еще: | |
для имени в игноре: | |
попытка: | |
state_keys. удалить (имя) | |
, кроме KeyError: | |
пасс | |
# Выполните атрибуты `first`. | |
для первого ввода: | |
state_keys.remove (ключ) | |
сам._do (объект, ключ, состояние [ключ]) | |
# Удаляем атрибуты `last`. | |
для ввода последнего: | |
state_keys.remove (ключ) | |
# Установите остальные атрибуты. | |
для ключа в state_keys: | |
сам._do (объект, ключ, состояние [ключ]) | |
# Последние выполняйте по порядку. | |
для ввода последнего: | |
self._do (объект, ключ, состояние [ключ]) | |
############################################## #################### | |
# Непубличные методы. | |
############################################## #################### | |
def _register (self, obj): | |
idx = id (объект) | |
, если idx отсутствует в self. _instance_ids: | |
self._instance_ids.append (idx) | |
def _is_registered (self, obj): | |
вернуть id (obj) в self._instance_ids | |
def _has_instance (self, value): | |
«» «Учитывая что-то (` value`), которое является частью состояния, это | |
возвращает значение, если в значение встроен экземпляр или нет. | |
«» « | |
, если isinstance (значение, состояние): | |
возврат Истина | |
elif isinstance (значение, (StateDict, StateList, StateTuple)): | |
возвращаемое значение. has_instance | |
возврат Ложь | |
def _get_pure (себя, значение): | |
«» «Возвращает представление объекта Python (обычно | |
list, tuple или dict), в который не встроены экземпляры. | |
«» « | |
результат = значение | |
, если сам._has_instance (значение): | |
поднять StateSetterError («Значение имеет экземпляр:% s»% значение) | |
, если isinstance (значение, (StateList, StateTuple)): | |
результат = [self. _get_pure (x) для x в значении] | |
, если isinstance (значение, StateTuple): | |
результат = кортеж (результат) | |
elif isinstance (значение, StateDict): | |
результат = {} | |
для значения k, v.пунктов (): | |
результат [k] = self._get_pure (v) | |
вернуть результат | |
def _update_and_check_state (self, obj, state): | |
«» «Обновляет состояние из реестра, а затем проверяет, | |
объект и состояние имеют один и тот же класс. | |
«» « | |
# Обновите этот объект состояния до последней версии с помощью реестра. | |
# Это делается перед тестированием, потому что обновление может изменить | |
# имя класса / модуль. | |
version_registry.registry.update (состояние) | |
# Убедитесь, что объект и состояние имеют одинаковые имена классов и модулей. | |
метаданные = состояние .__ метаданные__ | |
cls = объект__ класс__ | |
, если метаданные [«имя_класса»]! = Cls . __ name__: | |
поднять StateSetterError ( | |
«Экземпляр (% s) и состояние (% s) не имеют одного и того же класса» | |
«имя!» % (cls.__name__, метаданные [«имя_класса»]) | |
) | |
, если метаданные [«модуль»]! = Cls .__ module__: | |
поднять StateSetterError ( | |
«Экземпляр (% s) и состояние (% s) не имеют одного и того же модуля» | |
«имя!» % (cls .__ module__, метаданные [«модуль»]) | |
) | |
def _do (self, obj, key, value): | |
попытка: | |
getattr (объект, ключ) | |
, кроме AttributeError: | |
поднять StateSetterError ( | |
«Объект% s не имеет атрибута с именем:% s»% (obj, key) | |
) | |
, если isinstance (значение, (State, StateDict, StateList, StateTuple)): | |
# Нужны специальные обработчики. | |
, если не self._has_instance (значение): | |
результат = self._get_pure (значение) | |
setattr (объект, ключ, результат) | |
elif isinstance (значение, StateTuple): | |
setattr (объект, ключ, self._do_tuple (getattr (объект, ключ), значение)) | |
еще: | |
сам._do_object (getattr (объект, ключ), значение) | |
еще: | |
setattr (объект, ключ, значение) | |
def _do_object (сам, объект, состояние): | |
self. type_map [состояние .__ класс __] (объект, состояние) | |
def _do_instance (self, obj, state): | |
, если сам._is_registered (obj): | |
возврат | |
еще: | |
self.register (obj) | |
метаданные = состояние .__ метаданные__ | |
, если hasattr (obj, «__set_pure_state__»): | |
сам._update_and_check_state (объект, состояние) | |
объект__ set_pure_state __ (состояние) | |
elif «tvtk_classes» в метаданных [«модуль»]: | |
self. _update_and_check_state (объект, состояние) | |
tmp = self._get_pure (StateDict (** состояние)) | |
del tmp [«__ metadata__»] | |
obj.__setstate __ (tmp) | |
еще: | |
# Нет необходимости обновлять или проверять, поскольку `set` делает это за нас. | |
self.set (объект, состояние) | |
def _do_tuple (сам, объект, состояние): | |
, если не self._has_instance (состояние): | |
возврат сам. _get_pure (состояние) | |
еще: | |
результат = список (объект) | |
self._do_list (результат, состояние) | |
вернуть кортеж (результат) | |
def _do_list (сам, объект, состояние): | |
, если len (obj) == len (состояние): | |
для i в диапазоне (len (obj)): | |
, если не сам._has_instance (состояние [i]): | |
obj [i] = self._get_pure (state [i]) | |
elif isinstance (состояние [i], кортеж): | |
obj [i] = self._do_tuple (состояние [i]) | |
еще: | |
self._do_object (объект [i], состояние [i]) | |
еще: | |
поднять StateSetterError ( | |
«Невозможно установить состояние списка неправильного размера.« | |
) | |
def _do_dict (сам, объект, состояние): | |
для ключа, значение в state.items (): | |
, если не self._has_instance (значение): | |
obj [ключ] = self._get_pure (значение) | |
elif isinstance (значение, кортеж): | |
obj [ключ] = self._do_tuple (значение) | |
еще: | |
self._do_object (объект [ключ], значение) | |
############################################## #################### | |
# Внутренние служебные функции. | |
############################################## #################### | |
def _get_file_read (f): | |
, если hasattr (f, «читать»): | |
возврат | |
еще: | |
возврат открытый (f, «rb») | |
def _get_file_write (f): | |
, если hasattr (f, «написать»): | |
возврат | |
еще: | |
возвратное открытое (f, «wb») | |
############################################## #################### | |
# Служебные функции. | |
############################################## #################### | |
def dump (значение, файл): | |
«» «Закрепляет состояние объекта (` value`) в переданном файле | |
(или имя файла). | |
«» « | |
f = _get_file_write (файл) | |
попытка: | |
StatePickler ().дамп (значение, ф) | |
наконец: | |
ф. Промывка () | |
, если f не файл: | |
f.close () | |
def dumps (значение): | |
«» «Выбирает состояние объекта (` значение`) и возвращает строку.»» « | |
вернуть StatePickler (). Dumps (значение) | |
def load_state (файл): | |
«» «Возвращает состояние объекта, загруженного из обработанных данных в | |
указанный файл (или имя файла). | |
«» « | |
f = _get_file_read (файл) | |
попытка: | |
состояние = StateUnpickler ().load_state (f) | |
наконец: | |
, если f не файл: | |
f.close () | |
возврат состояния | |
def load_state (строка): | |
«» «Возвращает состояние объекта, загруженного из обработанных данных | |
в данной строке. | |
«» « | |
вернуть StateUnpickler (). Load_state (строка) | |
по умолчанию get_state (объект): | |
«» «Возвращает состояние объекта (обычно в виде словаря). | |
Возвращенное состояние | может использоваться непосредственно для установки состояния объекта |
через `set_state`. | |
«» « | |
s = дамп (obj) | |
возврат load_state (s) | |
def set_state (obj, state, ignore = None, first = None, last = None): | |
StateSetter (). Set (объект, состояние, игнорировать, первый, последний) | |
set_state.__doc__ = StateSetter.set .__ doc__ | |
def update_state (состояние): | |
«» «Учитывая состояние объекта, это обновляет состояние до | |
последней версии с использованием обработчиков, указанных в реестре версий. | |
Состояние изменено на месте. | |
«» « | |
version_registry.registry.update (состояние) | |
def create_instance (состояние): | |
«» «Если возможно, создать экземпляр из состояния.» «» | |
if (not isinstance (state, State)) и ( | |
«имя_класса» не в состоянии.__metadata__ | |
): | |
поднять StateSetterError («Нет информации о классе в состоянии») | |
метаданные = состояние .__ метаданные__ | |
имя_класса = metadata.get («имя_класса») | |
mod_name = metadata.get («модуль») | |
, если «tvtk_classes» в имени модуля: | |
# FIXME: Этот особый случай, вероятно, указывает на что-то | |
# над которым нужно подумать, плюс он заставляет решить, стоит ли | |
# этот компонент зависит от tvtk! | |
от ТВТК.API импорт ТВТК | |
вернуть getattr (tvtk, имя_класса) () | |
initargs = метаданные [«initargs»] | |
, если initargs.has_instance: | |
поднять StateUnpicklerError («Невозможно распаковать нетривиальные исходные аргументы») | |
__import __ (имя_модуля, globals (), locals (), имя_класса) | |
мод = sys.модули [mod_name] | |
cls = getattr (мод, имя_класса) | |
return cls (* initargs) |
cozTools for IBM i by Bob Cozzi (COZTOOLS)
Горячий список
Самые популярные CL-команды Cozzi Tools:
- Получить атрибуты файла SPOOL (RTVSPLFA)
- Копирование из PDF в принтер IBM i (CPYFRMPDF)
- Копирование файла DB2 в формат CSV (CPYTOCSV)
- Копировать OUTQ (CPYOUTQ)
- Копировать буферный файл (CPYPRTF)
- Создать файл IFS (CRTSTMF)
- Получить расширенную дату (RTVDATE)
Cozzi cozTools Цены на продукцию | Инструменты приложений | Разработчик AppTools | AppTools Enterprise |
Лицензионный сбор | $ 195 | $ 999 | $ 5999 |
Включено неограниченное время бесплатного использования | Есть | Есть | Есть |
Включает первый год обслуживания программного обеспечения и Опора | Есть | Есть | Есть |
Создавайте программы CL с помощью команд CL Cozzi AppTools | Есть | Есть | Есть |
75+ команд CL и рост (учить более…) | Есть | Есть | Есть |
150+ улучшений RPG | Да (только во время выполнения) | Есть | Есть |
/ COPY или / INCLUDE предоставлено участниками-источниками | № | Есть | Есть |
Включает полный исходный код продукта (на момент лицензия) | № | № | Есть |
Текст подсказки для команд / документация | Есть | Есть | Есть |
(до) Включена поддержка 3 инцидентов | Есть | Есть | Есть |
Поддерживаемая самая ранняя версия IBM i (i5 / OS) * | v5.4 | v5.4 | v5.4 |
Где заказать: | Закажите и скачайте | Закажите и скачайте | Закажите и скачайте |
Используется всеми основными компаниями и организациями на всей территории
Северная Америка. Не пора ли воспользоваться Cozzi Tools в
твоя компания?
Доступно в 3 редакциях для любого магазина и любого бюджета:
- cozTools Enterprise — включает полный исходный код
код для Cozzi App Tools вместе с AppTools Developer. - cozTools Developer — включает инструменты приложения и
исходный прототип прототипа для использования в ваших собственных программах RPG IV.
Включает бесплатную библиотеку времени выполнения, которая позволяет вам скомпилировать RPG IV.
приложений для использования Cozzi App Tools в любой другой системе IBM i без
оплата дополнительного лицензионного сбора. Это действительно «бесплатная среда выполнения»
библиотека. - cozTools — Когда ты
нужна производительность команд CL Application Tools.(См. Наш
растущий список CL
команды включены).
Купить Cozzi AppTools
посетите нашу страницу регистрации. После регистрации
вы будете перенаправлены на страницу подтверждения, где наш « Готов к
Купить «Виджет доступен.
Чтобы узнать о последних обновлениях, посетите нашу страницу «Что нового»
(обновляется еженедельно).
Copyright © 2012 Cozzi Productions, Inc. Все права защищены.
ПРИМЕЧАНИЕ. * Текущая версия поддерживает IBM i v5r4 и более поздние версии (также известные как i5 / OS).Следующий крупный
Выпуск должен работать на IBM i v7.1 и более поздних версиях, хотя он также может работать на v6.1, но текущие планы проектирования предусматривают только v7.1 и более поздние версии. В это время текущая версия среды выполнения будет «заморожена» и по-прежнему будет доступна для клиентов v5r4.
Справочная страница Ubuntu: apptools — apptools 4.4.0
Предоставлено: python-apptools-doc_4.4.0-3ubuntu1_all
ИМЯ
apptools - apptools 4.4.0
ПРИЛОЖЕНИЕ СКРИПТИРОВАНИЕ РАМКА
Framework Application Scripting Framework - это компонент Enthought Tool Suite, который предоставляет разработчикам API, который позволяет создавать сценарии для объектов на основе признаков.Операции над объектом, допускающим сценарий, можно записать в сценарий и впоследствии воспроизвести. Фреймворк полностью настраивается. Альтернативные реализации всех основных компоненты могут быть предоставлены при необходимости. Структура Концепции Следующие концепции поддерживаются фреймворком. · Скриптовый тип Тип, поддерживающий скрипты, - это подтип HasTraits , который имеет скриптовые методы и скриптовые методы. черты.Если вызывается скриптовый метод или задана скриптовая черта, то это действие может быть записано в сценарий и впоследствии воспроизведено. Если метод __init __ () поддерживает сценарий, то создание объекта из этого типа может быть записанным. Скриптируемые типы могут быть явно определены или созданы динамически из любого подтипа HasTraits . · Скриптовый API Набор скриптовых методов и свойств скриптируемого типа составляет скриптовый API.API может быть определен явно с помощью сценария декоратора (для методов) или Сценарий обертка (для трейтов). Для динамически создаваемых типов со сценариями API можно определить в терминах одного или нескольких типов или интерфейсов или явного списка имен методов и признаков. К по умолчанию, все общедоступные методы и свойства (т. е. те, чье имя не начинается с подчеркивание) являются частью API.Также можно явно исключить список методов и названий признаков. · Скриптуемый объект Объект, поддерживающий скрипт, является экземпляром скриптового типа. Сценарийные объекты могут быть явно созданы, вызывая скриптовый тип. В качестве альтернативы объект, не поддерживающий сценарии, можно сделать динамически доступным для сценариев. · Скрипт Скрипт - это скрипт Python, который может быть записью или написан с нуля. Если создание скриптовых объектов может быть записано, то это может быть возможным для запись должна выполняться непосредственно интерпретатором Python и независимо от приложение, сделавшее запись.В противном случае приложение должно запустить сценарий и сначала создайте любые скриптовые объекты, упомянутые в скрипте. · Переплет Сценарий выполняется в пространстве имен, которое по умолчанию пусто. Если скриптовые объекты упомянутые в сценарии, не создаются сценарием (потому что их тип __init __ () метод не поддерживает скрипт), то они должны быть созданы приложением и добавлены в пространство имен. Добавление объекта в пространство имен называется привязкой.Сценарийные объекты, создание которых может быть записано, автоматически связываются когда они созданы. Также возможно привязать фабрику объектов, а не сам объект. Фабрика будет вызван, и объект будет создан, только если объект нужен скрипту, когда он запущен. Обычно это используется плагинами. Имя, которое обязательно понадобится объекту, не имеет отношения к имени объекта внутри приложение.Имена могут быть разделены точками (например, aaa.bbb.ccc ) и соответствующими объектами. представляющие промежуточные части такого имени будут созданы автоматически. Событие запускается всякий раз, когда объект привязан (или когда вызывается привязанная фабрика). Это позволяет другим объектам (например, встроенной оболочке Python) предоставлять доступ к объектам с возможностью сценария в другие способы. · Менеджер скриптов Менеджер скриптов отвечает за запись и последующее воспроизведение скриптов.В приложении есть один экземпляр диспетчера сценариев, который можно задать явно или создается автоматически. Ограничения В текущей реализации скриптовые типы контейнеров Trait (например, List, Dict) могут только содержат объекты, соответствующие фундаментальным типам Python (например, int, bool, str). API Обзор В этом разделе дается обзор API, реализованного фреймворком. Полный API документация доступна в виде HTML, созданного эндо.Приложение example демонстрирует некоторые возможности фреймворка. Модуль Уровень Объекты get_script_manager () Менеджер скриптов приложения возвращается. Один будет создан автоматически, если нужный. set_script_manager (script_manager) Менеджер скриптов приложения будет установлен на script_manager , заменив любые существующий менеджер скриптов. скриптов Это декоратор, используемый для явной пометки методов как доступных для сценариев. Любой звонок к скриптовому методу записывается. Если метод __init __ () типа оформлен тогда создание объекта будет записано. Скрипт Это оболочка для признака, чтобы явно пометить его как доступный для сценариев. Любой изменение значения признака будет записано.Простое прочтение признака будет не записываться, если только прочитанное значение не привязано к другому признаку, допускающему скрипт или передается как аргумент методу с поддержкой сценариев. Передача has_side_effects = True при переносе признака всегда будет записано чтение. create_scriptable_type (тип_скрипта, name = None, bind_policy = 'auto', api = None, includes = None, excludes = None, script_init = True) Это создает новый тип на основе существующего типа, но с определенными методами и черты, отмеченные как подлежащие сценарию.Затем можно создать объекты с возможностью сценария вызывая тип. тип_сценария - существующий тип, не поддерживающий сценарии. Новый тип будет подтипом этого. API , включает , а исключает аргументов, определяющих, какие методы и характеристики сделаны сценариями. По умолчанию все общедоступные методы и трейты (т. Е. Те, чьи имя не начинается с символа подчеркивания) становятся доступными для сценариев.Аргументы name и bind_policy определяют, как связываются объекты сценария, когда они созданы. имя - это имя, к которому будет привязан объект. По умолчанию к имени script_type с переводом первого символа в нижний регистр. название май быть пунктирным именем, например. aaa.bb.c . bind_policy определяет, что произойдет, если объект уже привязан к имени.Если это авто , тогда к имени нового объекта будет добавлен числовой суффикс. Если это уникальный , тогда будет возбуждено исключение. Если это , повторная привязка , то объект привязанный в настоящее время к имени будет освобожден. api - это класс или интерфейс (или список классов или интерфейсов), который используется для укажите имена методов и черт, которые нужно сделать скриптовыми. Класс или интерфейс эффективно определяет скриптовый API.Если api не указан, тогда включает - это список имен методов и свойств, которые сделан скрипт. Если api и включает не указаны, тогда исключает - это список метода и признака имена, которые являются , а не , сделаны сценариями. Если установлено script_init , тогда метод __init __ () становится скриптовым независимо от api , включает , а исключает аргументов.Если script_init не задан, то объекты должны быть явно привязаны и должны иметь имя и bind_policy игнорируются. make_object_scriptable (obj, api = None, includes = None, excludes = None) Это берет существующий объект, не допускающий сценариев, и делает его доступным для сценариев. Это работает вызов create_scriptable_type () для существующего типа объектов и замена этот существующий тип с новым скриптовым типом.См. Описание create_scriptable_type () для объяснения api , включает , а исключает аргументов. ScriptManager Класс ScriptManager является реализацией по умолчанию интерфейса IScriptManager . bind_event Это событие запускается всякий раз, когда объект привязан или не привязан. Аргумент события реализует интерфейс IBindEvent . запись Этот признак устанавливается, если скрипт в данный момент записывается. Это обновлено автоматически менеджером скриптов. скрипт Эта черта содержит текст записываемого в данный момент скрипта (или последнего записанный сценарий, если он в настоящее время не записывается). Это обновлено автоматически менеджером скриптов. script_updated Это событие запускается всякий раз, когда обновляется характеристика скрипта .Аргумент события менеджер скриптов. bind (self, obj, name = None, bind_policy = 'unique', api = None, includes = None, excludes = None) Этот метод делает объект доступным для сценариев и привязывает его к имени. Смотрите описание из create_scriptable_type () для объяснения API , включает , исключает , name и аргумента bind_policy, аргументов. bind_factory (self, factory, name, bind_policy = 'unique', api = None, includes = None, исключает = Нет) Этот метод связывает фабрику объектов с именем. Фабрика призвана создавать объект (и сделать его доступным для сценариев) только тогда, когда объект нужен для запущенного сценария. См. Описание create_scriptable_type () для объяснения имени и bind_policy аргументов. запустить (самостоятельно, скрипт) Этот метод запускает сценарий в пространстве имен, содержащем все связанные в данный момент объекты. сценарий - это любой объект, который может использоваться оператором Python exec , включая строку или файловый объект. run_file (сам, имя_файла) Этот метод запускает сценарий в пространстве имен, содержащем все связанные в данный момент объекты. имя_файла - это имя файла, содержащего сценарий. start_recording (сам) Этот метод запускает запись сценария. stop_recording (сам) Этот метод останавливает запись текущего скрипта. IBindEvent Интерфейс IBindEvent определяет интерфейс, который реализуется переданным объектом. когда запускается bind_event диспетчера сценариев. name Эта черта - привязанное или несвязанное имя. obj Эта черта - объект привязан к name или None, если name не привязан. Начать запись действия Класс StartRecordingAction - это стандартное действие PyFace, которое запускает запись изменяет объекты сценария в сценарий. Действие StopRecording StopRecordingAction Класс - это стандартное действие PyFace, которое завершает запись изменений. в скриптовые объекты в скрипт. Реализация Приложение Сценарии Ключевой частью поддержки сценариев приложений является разработка соответствующего API сценариев. и чтобы убедиться, что само приложение использует API, чтобы изменения данных могли быть записано. Платформа предоставляет множество способов указать API сценариев. Какой подход уместно в конкретном случае, будет зависеть от того, когда это новое приложение, или добавляются ли скрипты в существующее приложение и насколько сложны модель данных приложения. Статический Спецификация API сценариев задается статически с помощью явного использования сценария декоратора . и оболочку трейта Scriptable . Например: из apptools.appscripting.api импортировать скрипт, скрипт из traits.api импортировать HasTraits, Int, Str класс DataModel (HasTraits): foo = Сценарий (Str) bar = Сценарий (Int, has_side_effects = True) @scriptable def baz (сам): проходить Def Weble (сам) проходить # Создайте объект со сценарием.Это создание не будет записано, потому что # __init __ () не оформляется. obj = DataModel () # Они будут записаны. obj.foo = '' obj.bar = 10 obj.baz () # Это не будет записано. obj.weeble () # Это не будет записано, если 'f' не будет передано чему-то # записано. f = obj.foo # Это будет записано, потому что мы установили has_side_effects. b = obj.bar Dynamic Спецификация API сценариев также можно указать динамически.В следующем примере создается объект со сценариями с тем же API с поддержкой сценариев, что и выше (за исключением has_side_effects нельзя указывать динамически): из apptools.appscripting.api import create_scriptable_type из traits.api импортировать HasTraits, Int, Str класс DataModel (HasTraits): foo = Str bar = Int def baz (сам): проходить Def Weble (сам) проходить # Создайте скриптовый тип на основе вышеизложенного.ScriptableDataModel = create_scriptable_type (DataModel, excludes = ['weeble']) # Теперь создайте скриптобъекты из скриптового типа. Обратите внимание, что каждый # объект такого же типа. obj1 = ScriptableDataModel () obj2 = ScriptableDataModel () Вместо этого мы могли бы обойти тип и сделать сами объекты сценариями следующим образом: из apptools.appscripting.api импортировать make_object_scriptable из traits.api импортировать HasTraits, Int, Str класс DataModel (HasTraits): foo = Str bar = Int def baz (сам): проходить Def Weble (сам) проходить # Создавать неподписываемые объекты.obj1 = DataModel () obj2 = DataModel () # Теперь сделайте объекты доступными для сценариев. Обратите внимание, что у каждого объекта свой # тип, каждый из которых является подтипом DataModel. make_object_scriptable (obj1, excludes = ['weeble']) make_object_scriptable (obj2, excludes = ['weeble']) При более сложном дизайне мы можем указать скриптовый API как интерфейс следующим образом: из apptools.appscripting.api импортировать make_object_scriptable от черт.api import HasTraits, Int, Interface, Str класс DataModel (HasTraits): foo = Str bar = Int def baz (сам): проходить Def Weble (сам) проходить класс IScriptableDataModel (Интерфейс): foo = Str bar = Int def baz (сам): проходить # Создать объект, неподдающийся написанию. obj = DataModel () # Теперь сделайте объект доступным для сценариев.make_object_scriptable (объект, api = IScriptableDataModel) Создание сценариев __init __ () Создание метода типа __init __ () имеет свои преимущества и недостатки. Это означает, что создание скриптовых объектов будет записано в скрипт (вместе с необходимыми импортировать операторов). Это означает, что сценарий можно запускать независимо от вашего приложение стандартным интерпретатором Python. Недостатком является то, что если у вас сложная модель данных с множеством взаимозависимостей, затем определение полного и согласованного API сценариев, который позволяет запускать сценарий самостоятельно может оказаться трудным.В таких случаях лучше иметь приложение создавать и связывать сами скриптовые объекты.
РАЗРЕШЕНИЯ РАМКИ — ВВЕДЕНИЕ
Структура разрешений - это компонент Enthought Tool Suite, который обеспечивает разработчикам с возможностью ограничить доступ к частям приложения, если пользователь не надлежащим образом уполномочен. Другими словами, он включает и отключает различные части GUI согласно личности пользователя.Фреймворк включает API, позволяющий интегрировать его с существующими организациями. инфраструктура безопасности, например, для поиска пользователей в корпоративном каталоге LDAP. Фреймворк полностью настраивается. Альтернативные реализации всех основных компоненты могут быть предоставлены при необходимости. Реализации по умолчанию обеспечивают простой база данных пользователей локальной файловой системы и позволяет определять роли и назначать их пользователям. Структура не , а не предоставляет никаких средств для защиты доступа к данным.Это не так можно реализовать такую защиту в Python и использовать файловую безопасность, обеспечиваемую типичная операционная система. Структура Концепции Следующие концепции поддерживаются фреймворком. · Разрешение Разрешение - это основной инструмент, который разработчик использует для указания доступа к части приложение должно быть ограничено. Если у текущего пользователя есть разрешение, тогда доступ предоставляется.Разрешение может быть прикреплено к действию PyFace, к элементу Представление TraitsUI или виджет определенного набора инструментов GUI. Когда пользователю отказано в доступе, соответствующий элемент управления GUI отключен или полностью скрыт. · Пользователь У каждого приложения есть текущий пользователь: авторизованный или неавторизованный . Чтобы для авторизации пользователь должен идентифицировать себя и подтвердить свою личность. Произвольный фрагмент данных (называемый blob) может быть связан с авторизованным пользователем. которые (при поддержке менеджера пользователей) можно безопасно хранить.Это может быть использовано для Например, для хранения конфиденциальных пользовательских настроек или для реализации перемещаемого профиля. · Менеджер пользователей Диспетчер пользователей отвечает за авторизацию текущего пользователя и, следовательно, определяет как это делается. Он также предоставляет информацию о группе пользователей для политики. управляющий делами. Он также может, опционально, предоставлять возможность управлять популяцией пользователей (например, добавить или удалить пользователей). Менеджер пользователей должен либо поддерживать постоянную запись совокупность пользователей или интерфейс с внешней базой данных пользователей или службой каталогов.Менеджер пользователей по умолчанию использует авторизацию на основе пароля. Менеджер пользователей сохраняет свои данные в базе данных пользователей. Диспетчер пользователей по умолчанию предоставляет API, позволяющий использовать различные реализации базы данных пользователей (для пример для хранения данных в СУБД или интеграции с существующим каталогом служба). Предоставляется база данных пользователей по умолчанию, которая собирает данные в локальном файле. · Менеджер по политике Диспетчер политик отвечает за назначение разрешений пользователям и определение разрешения, назначенные текущему пользователю.Для этого он должен поддерживать постоянный запись этих заданий. Менеджер политик по умолчанию, поставляемый с платформой, использует роли, чтобы упростить администратор для управления отношениями между разрешениями и пользователями. Роль определяется как именованный набор разрешений, и пользователю может быть назначена одна или несколько ролей их. Менеджер политик сохраняет свои данные в базе данных политик. Диспетчер политик по умолчанию предоставляет API, чтобы можно было использовать различные реализации базы данных политик (например, для хранения данных в СУБД).Предоставляется база данных политик по умолчанию, копирует данные в локальном файле. · Диспетчер разрешений Диспетчер разрешений - это одноэлементный объект, используемый для получения и установки текущей политики и менеджеры пользователей. Framework API API-интерфейсы, предоставляемые платформой разрешений, можно разделить на следующие группы. · Приложение API Эта часть API используется разработчиками приложений.· Политика Менеджер API Это интерфейс, который должен реализовать альтернативный менеджер политик. Нужно реализация альтернативы ожидается очень редко, поэтому API не распространяется дальше. Подробности см. В определении интерфейса IPolicyManager. · По умолчанию Политика Менеджер Данные API Эта часть API используется разработчиками для хранения постоянных данных политики в более безопасное место (например,на удаленном сервере), чем предусмотрено по умолчанию выполнение. · Пользователь Менеджер API Это интерфейс, который должен реализовать альтернативный пользовательский менеджер. Нужно реализация альтернативы ожидается очень редко, поэтому API не распространяется дальше. Подробнее см. Определение интерфейса IUserManager. · По умолчанию Пользователь Менеджер Данные API Эта часть API используется разработчиками для хранения пользовательской базы данных в более безопасном местоположение (например,на удаленном сервере), чем предусмотрено реализацией по умолчанию. Полная документация API доступна в виде HTML-кода, сгенерированного эндо. Что Сделать Я Нужна повторная реализация с до ? Архитектура структуры разрешений состоит из нескольких уровней, каждый из которых может переопределен для удовлетворения требований конкретной среды. Надеюсь, следующие вопросы и ответы прояснят, что необходимо повторно реализовать в зависимости от ваше окружение.В: Хотите ли вы использовать роли для группировки разрешений и назначения их пользователям? A: Если да , тогда используйте предоставленный PolicyManager, в противном случае предоставьте ваш собственный Реализация IPolicyManager. В: Вы хотите, чтобы пользователи аутентифицировались с помощью пароля? A: Если да , тогда используйте , предоставленный UserManager, в противном случае предоставит ваш собственный Реализация IUserManager. Q: Разрешает ли интерфейс IUser вы до хранить все пользователь специфический информация вам нужна? A: Если да , то используйте предоставленный UserDatabase, в противном случае предоставьте ваш собственный Реализация IUserDatabase.В: Вы хотите сохранить свои учетные записи пользователей в виде консервированных данных в локальном файле? A: Если да , то использовать предоставлено по умолчанию, в противном случае предоставит UserDatabase с ваша собственная реализация IUserStorage. Q: Сделайте вы хотите до сохраните свою политику данные (т.е. роли и роли назначения) как маринованные данные в локальном файле? A: Если да , тогда используйте , предоставлено по умолчанию, в противном случае предоставит PolicyManager с ваша собственная реализация IPolicyStorage. Развертывание Альтернатива Менеджеры Структура разрешений сначала попытается импортировать различных менеджеров из apptools.permissions.external пространство имен. Менеджеры по умолчанию используются, только если нет альтернатива была найдена. Следовательно, альтернативных менеджеров следует использовать как яйцо. содержащее это пространство имен. В частности, фреймворк ищет следующие классы: PolicyManager из apptools.permissions.external.policy_manager PolicyStorage из apptools.permissions.external.policy_storage UserDatabase из apptools.permissions.external.user_database UserManager из apptools.permissions.external.user_manager UserStorage из apptools.permissions.external.user_storage Примером сервера является такой пакет, который предоставляет PolicyStorage и UserStorage. реализации, которые используют сервер на основе XML-RPC для предоставления удаленных (и, следовательно, более secure) политики и пользовательских баз данных. Использование По умолчанию Хранилище Реализации И политика по умолчанию, и менеджеры пользователей (опять же по умолчанию) сохраняют свои данные в виде солений. в локальных файлах с именами ets_perms_policydb и ets_perms_userdb соответственно.По умолчанию они хранятся в домашнем каталоге приложения (т. е. возвращенном ETSConfig.application_home ). Обратите внимание, что этот каталог обычно находится в собственной структуре каталогов пользователя, тогда как он должен быть доступен всем пользователям приложения. Если установлена переменная среды ETS_PERMS_DATA_DIR , то вместо нее используется ее значение. Каталог должен быть доступен для записи всем пользователям приложения.Следует повторить, что реализации по умолчанию , а не , обеспечивают безопасный доступ к разрешения и пользовательские данные. Они полезны в совместной среде и как рабочие Примеры.
ПРИМЕНЕНИЕ API
В этом разделе представлен обзор части API-интерфейса ETS Permissions Framework, используемой разработчики приложений. Пример Permissions Framework демонстрирует используемый API.Приложение обычно использует API для следующих действий: · Определить разрешения · Применить разрешения · Аутентификация пользователя · Получение и установка пользовательских данных · Интегрировать управленческие действия. Определение Разрешения Разрешение - это объект, который определяет доступ пользователя к части приложения. Хотя можно применить одно и то же разрешение к нескольким частям приложения, как правило, это плохая идея, так как это затрудняет их последующее разделение. Дата.Разрешение имеет идентификатор и удобочитаемое описание. Идентификаторы разрешений должны быть уникальными. По соглашению для идентификаторов используется точечная нотация, придающая им структуру. Идентификаторы должны быть на как минимум иметь префикс, специфичный для приложения или плагина, чтобы гарантировать их уникальность. Обычно все разрешения для приложений определяются в одном permissions.py модуль. Ниже приводится отрывок из примера модуля permissions.py : из apptools.permissions.api разрешение на импорт # Добавить нового человека. NewPersonPerm = Permission (id = 'ets.permissions.example.person.new', description = u «Добавить нового человека») # Обновить возраст человека. UpdatePersonAgePerm = Permission (id = 'ets.permissions.example.person.age.update', description = u «Обновить возраст человека») # Просмотр или обновление зарплаты человека. PersonSalaryPerm = Permission (id = 'ets.permissions.example.person.salary', description = u "Просмотреть или обновить зарплату человека") Применение разрешений Разрешения применяются к различным частям графического интерфейса приложения.Когда пользователь был Если вы получили разрешение, соответствующая часть графического интерфейса отображается нормально. Когда пользователю отказано в разрешении, тогда соответствующая часть графического интерфейса отключена или полностью скрыт. Разрешения могут применяться к элементам представления TraitsUI и к любому объекту, который можно обернуть. в SecureProxy . TraitsUI Просмотреть элементов Элементы в представлениях TraitsUI имеют включенных_ когда и видимых_ когда черт, которые оцениваются как определить, должен ли элемент быть включен или видим соответственно.Они используются для применения разрешения, сохраняя соответствующие разрешения в модели, чтобы они были доступны для вид. Признаки enabled_when и visible_when просто ссылаются на права доступа. предоставил черту. предоставил черту автоматически отражает, действительно ли пользователь имеет соответствующее разрешение. Чтобы представление правильно обновлялось при изменении прав пользователя (т.е.когда они проходят аутентификацию) представление должно использовать обработчик SecureHandler . Этот обработчик простой подкласс стандартного класса Traits Handler . В следующем отрывке из примера показано представление по умолчанию для объекта Person , который включает элемент age , когда у пользователя есть разрешение UpdatePersonAgePerm , и показывает salary item, когда у пользователя есть разрешение PersonSalaryPerm : из apptools.permissions.api импорт SecureHandler из traits.api импортировать HasTraits, Int, Unicode из traitsui.api импортировать элемент, просмотр из разрешений импорт UpdatePersonAgePerm, PersonSalaryPerm класс Person (HasTraits): "" "Простой пример объектной модели" "" # Имя. name = Unicode # Возраст в годах. age = Int # Зарплата. зарплата = Инт # Определите вид по умолчанию с прикрепленными разрешениями.age_perm = UpdatePersonAgePerm salary_perm = PersonSalaryPerm traits_view = Просмотр ( Предмет (name = 'name'), Предмет (name = 'age', enabled_when = 'object.age_perm.granted'), Item (name = 'salary', visible_when = 'object.salary_perm.granted'), обработчик = SecureHandler) Упаковка в на SecureProxy К любому объекту можно применить разрешения, заключив его в объект SecureProxy .An используется адаптер, который управляет включенным и видимым состояниями проксируемого объекта в соответствии с разрешениями текущего пользователя. В противном случае прокси ведет себя так же, как проксируемый объект. В комплект входят адаптеры для следующих типов объектов: · Действия PyFace · Виджеты PyFace FIXME: TODO · Виджеты Qt · Виджеты wx См. Запись SecureProxy Адаптеры для описания того, как писать адаптеры для других типы объектов.Следующий отрывок из примера показывает упаковку стандартного действия PyFace и применение разрешения NewPersonPerm : из apptools.permissions.api импортировать SecureProxy из импорта разрешений NewPersonPerm ... def _new_person_action_default (self): "" "Инициализатор свойства." "" # Создайте действие и защитите его с помощью соответствующего разрешения. act = Action (name = 'New Person', on_perform = self._новый человек) act = SecureProxy (act, permissions = [NewPersonPerm]) ответный акт SecureProxy также принимает аргумент show , который, если установлен в False , скрывает объект, когда он становится отключенным. Аутентификация Пользователь Менеджер пользователей поддерживает концепцию текущего пользователя и отвечает за аутентификация пользователя (и, при необходимости, отмена авторизации пользователя).Фрагмент кода для аутентификации текущего пользователя: из apptools.permissions.api import get_permissions_manager get_permissions_Manager (). user_manager.authenticate_user () Отказ от авторизации текущего пользователя осуществляется с помощью метода unauthenticate_user () . Для удобства предусмотрены два действия PyFace, которые называются LoginAction и LogoutAction . которые обертывают эти два метода. Для дополнительного удобства предусмотрен менеджер меню PyFace, называемый UserMenuManager , который содержит все действия пользователя и управления (см. ниже) в структуре разрешений.Это используется в примере. Меню пользователя, действия входа и выхода могут быть импортированы из apptools.permissions.action.api . Получение и Настройка Пользователь Данные Менеджер пользователей имеет черту user , которая представляет собой объект, реализующий интерфейс IUser . Он действителен только после аутентификации пользователя. Интерфейс IUser имеет черту blob , которая содержит любые двоичные данные (в виде строки Python).В данные будут прочитаны, когда пользователь будет аутентифицирован. Данные будут записаны всякий раз, когда измененный. Интеграция Управление Действия И политики, и менеджеры пользователей могут предоставлять действия, обеспечивающие доступ к различным функции управления. Оба имеют черту management_actions , которая представляет собой список PyFace. действия, которые вызывают соответствующие диалоги, которые позволяют пользователю управлять политикой и количество пользователей соответственно.У менеджеров пользователей также есть черта user_actions , которая представляет собой список действий PyFace, которые вызывают соответствующие диалоги, которые позволяют пользователю управлять собой. Например, по умолчанию диспетчер пользователей предоставляет действие, позволяющее пользователю изменить свой пароль. Менеджер политик по умолчанию предоставляет действия, которые позволяют определять роли в терминах наборы разрешений и позволяют назначать пользователям одну или несколько ролей. Менеджер пользователей по умолчанию предоставляет действия, которые позволяют добавлять, изменять и удалено.Менеджер пользователей, который интегрируется со службой безопасного каталога предприятия, может не предусматривать никаких управленческих действий. Все действия управления имеют соответствующие разрешения. Запись SecureProxy Адаптеры SecureProxy автоматически обрабатывает большинство типов объектов, которые вы хотите применить. разрешения на. Однако можно реализовать дополнительные адаптеры для поддержки других типы объектов.Для этого вам необходимо реализовать подкласс AdapterBase и зарегистрировать Это. Адаптеры, как правило, представляют собой один из двух стилей в зависимости от того, как объект включен и виден. состояния изменены. Если состояния изменены с помощью атрибутов (обычно на основе признаков objects), то адаптер вызовет создание прокси для объекта. Если государства изменяются с помощью методов (обычно виджетов инструментария), тогда адаптер, вероятно, изменит сам объект.Мы будем называть эти два стиля адаптерами упаковки и исправлением переходники соответственно. Ниже приводится краткий обзор класса AdapterBase : проксировано Этот атрибут экземпляра является ссылкой на исходный объект. register_adapter (адаптер, тип, тип, ...) Это метод класса, который используется для регистрации вашего адаптера и одного или нескольких объектов. типы, которые он обрабатывает. адаптировать () Это метод, который следует повторно реализовать, установив исправления для адаптеров. (По умолчанию реализация приведет к созданию прокси-сервера для упаковки адаптеров.) Это где выполняется любое исправление проксированного атрибута . Возвращенный объект будет возвращается SecureProxy () и обычно является исправленным объектом, но может быть любым объект. setattr (имя, значение) Этот метод следует повторно реализовать, обернув адаптеры, чтобы перехватить настройку. соответствующих атрибутов проксированного объекта .Реализация по умолчанию должна быть используется как резерв для нерелевантных атрибутов. get_enabled () Этот метод необходимо повторно реализовать, чтобы вернуть текущее включенное состояние. set_enabled (значение) Этот метод необходимо повторно реализовать, чтобы установить для включенного состояния заданное значение. update_enabled (значение) Этот метод вызывается вашим адаптером для установки желаемого значения включенного государственный.Фактический набор состояния будет зависеть от прав текущего пользователя. get_visible () Этот метод необходимо реализовать повторно, чтобы вернуть текущее видимое состояние. set_visible (значение) Этот метод необходимо повторно реализовать, чтобы установить для видимого состояния заданное значение. update_visible (значение) Этот метод вызывается вашим адаптером для установки желаемого значения видимого государственный. Фактический набор состояния будет зависеть от прав текущего пользователя.Класс AdapterBase определен в файле adapter_base.py . Адаптер PyFace action адаптер является примером адаптера упаковки. PyQt виджет адаптер является примером адаптера исправления.
ПО УМОЛЧАНИЮ ПОЛИТИКА МЕНЕДЖЕР ДАННЫЕ API
В этом разделе представлен обзор части API-интерфейса ETS Permissions Framework, используемой разработчики, которые хотят хранить постоянные данные диспетчера политик в более безопасном месте (например.удаленный сервер), чем предусмотрено реализацией по умолчанию. API определяется менеджером политик по умолчанию, который использует роли, чтобы упростить назначать разрешения пользователям. Если этот API недостаточно гибкий или если роли неприемлемо, тогда следует внедрить альтернативный менеджер политики. API полностью определяется интерфейсом IPolicyStorage . Реализация по умолчанию этот интерфейс хранит базу данных политик как рассол в локальном файле. Обзор из IPolicyStorage Интерфейс IPolicyStorage определяет ряд методов, которые должны быть реализованы для чтения и напишите в базу данных политик. Эти методы предназначены для реализации с использованием простых Операторы SQL. В случае ошибки метод должен вызвать исключение PolicyStorageError . Струна представление исключения используется как сообщение об ошибке, которое отображается пользователю.
ПО УМОЛЧАНИЮ ПОЛЬЗОВАТЕЛЬ МЕНЕДЖЕР ДАННЫЕ API
В этом разделе представлен обзор части API-интерфейса ETS Permissions Framework, используемой разработчикам, которые хотят хранить базу данных пользователей в более безопасном месте (например, удаленное server), чем предусмотрено реализацией по умолчанию. API определяется менеджером пользователей по умолчанию, который использует авторизацию на основе пароля. Если этот API недостаточно гибкий или используется другой метод авторизации (например, биометрия), тогда следует внедрить альтернативный менеджер пользователей.API полностью определяется интерфейсом IUserDatabase . Это позволяет пользовательским базам данных быть реализованы, которые расширяют интерфейс IUser и хранят дополнительные данные, связанные с пользователем. Если база данных пользователей сохраняется в безопасном хранилище (например, удаленной СУБД), тогда это могут использоваться для хранения конфиденциальных данных (например, паролей для внешних систем), которые не должны храниться как обычные настройки. В большинстве случаев не требуется хранить дополнительные данные, связанные с пользователем, кроме этих. определяется IUser , поэтому предоставленная UserDatabase реализация (которая предоставляет весь графический интерфейс код, необходимый для реализации интерфейса IUserDatabase () ).База данных пользователей Реализация делегирует доступ к базе данных пользователей объекту, реализующему IUserStorage интерфейс . Реализация по умолчанию этого интерфейса хранит пользователя базу данных как рассол в локальном файле. Обзор из IUserStorage Интерфейс IUserStorage определяет ряд методов, которые должны быть реализованы для чтения и пишем в базу пользователей.Эти методы предназначены для реализации с использованием простых Операторы SQL. В случае ошибки метод должен вызвать исключение UserStorageError . Струна представление исключения используется как сообщение об ошибке, которое отображается пользователю. Обзор из IUserDatabase Интерфейс IUserDatabase определяет набор черт Bool , все начинающиеся с can_ , которые описать возможности конкретной реализации.Например, can_add_user trait устанавливается реализацией, если она поддерживает возможность добавления нового пользователя в база данных. Каждой из этих черт возможностей соответствует метод с тем же именем, за исключением для префикса can_ . Метод необходимо реализовать, только если соответствующие черты Истинно . Метод, например add_user () , вызывается менеджером пользователей для реализации возможность.В интерфейсе есть еще два метода. Диспетчер пользователей вызывает метод bootstrapping () , чтобы определить, является ли база данных самозагрузка. Обычно это происходит, когда база данных пуста, а пользователи еще не были определенный. Платформа разрешений рассматривает эту ситуацию как особый случай и может ослабить принудительное применение разрешений, чтобы пользователи и разрешения были изначально определенный. Менеджер пользователей вызывает метод user_factory () для создания нового объекта пользователя, т.е.объект, реализующий интерфейс IUser . Это позволяет реализации расширить IUser интерфейс и хранить дополнительные данные, связанные с пользователем, в объекте, если черта blob оказывается недостаточным.
ПРЕДПОЧТЕНИЯ
Пакет настроек предоставляет простой API для управления настройками приложения. В классы в пакете реализуются с использованием многоуровневого подхода, когда самый нижний уровень обеспечивает доступ к механизму необработанных настроек, и каждый слой наверху предоставляет больше удобные способы получения и установки значений предпочтений.
THE BASIC ПРЕДПОЧТЕНИЯ МЕХАНИЗМ
Давайте начнем с самого нижнего уровня, который состоит из IP-ссылок интерфейс и его реализация по умолчанию в классе Preferences . Этот слой реализует базовая система предпочтений, которая представляет собой иерархическое расположение узлов предпочтений (где каждый узел - это просто объект, реализующий интерфейс IPreferences ).Узлы в иерархия может содержать настройки предпочтений и / или дочерние узлы. Этот слой также обеспечивает способ по умолчанию для чтения и записи настроек из файловой системы с использованием отличного ConfigObj пакет. Все это звучит немного сложно, но, поверьте, это не так! Чтобы доказать это (надеюсь), давайте посмотрите на пример. Скажем, у меня есть следующие настройки в файле example.ini: [acme.ui] bgcolor = синий ширина = 50 коэффициент = 1.0 visible = True [acme.ui.splash_screen] изображение = всплеск fgcolor = красный Я могу создать иерархию предпочтений из этого файла: >>> из apptools.preferences.api import Preferences >>> предпочтения = Предпочтения (filename = 'example.ini') >>> preferences.dump () Узел () {} Узел (acme) {} Узел (ui) {'bgcolor': 'blue', 'ratio': '1.0', 'width': '50', 'visible': 'True'} Узел (splash_screen) {'изображение': 'всплеск', 'fgcolor': 'красный'} Метод 'dump' (полезен для отладки и т. Д.) Просто красиво печатает настройки иерархия.Словарь рядом с каждым узлом содержит фактические предпочтения узла. В В этом случае корневой узел (узел без имени) - это объект настроек, который мы созданный. У этого узла теперь есть один дочерний узел acme, который не содержит предпочтений. В Узел acme имеет один дочерний элемент, ui, который содержит некоторые настройки (например, bgcolor), а также дочерний узел splash_screen, который также содержит настройки (например, изображение). Чтобы найти предпочтение, мы используем: >>> предпочтения.получить ('acme.ui.bgcolor') 'синий' Если таких настроек нет, по умолчанию возвращается None: >>> preferences.get ('acme.ui.bogus') - Нет Истинный Вы также можете указать явное значение по умолчанию: >>> preferences.get ('acme.ui.bogus', 'фред') 'Фред' Чтобы установить предпочтение, мы используем: >>> preferences.set ('acme.ui.bgcolor', 'красный') >>> preferences.get ('acme.ui.bgcolor') 'красный' И чтобы убедиться, что настройки сохранены обратно на диск: >>> предпочтения.румянец() Чтобы добавить новое значение предпочтения, мы просто устанавливаем его: >>> preferences.set ('acme.ui.fgcolor', 'черный') >>> preferences.get ('acme.ui.fgcolor') 'чернить' Любые отсутствующие узлы при вызове set создаются автоматически, следовательно: >>> preferences.set ('acme.ui.button.fgcolor', 'белый') >>> preferences.get ('acme.ui.button.fgcolor') 'белый' Предпочтения также могут быть «унаследованы». например Обратите внимание, что узел 'splash_screen' не содержат предпочтение 'bgcolor' и, следовательно: >>> предпочтения.get ('acme.ui.splash_screen.bgcolor') - Нет Истинный Но если мы допустим «наследование» значений предпочтений, тогда: >>> preferences.get ('acme.ui.splash_screen.bgcolor', наследовать = True) 'красный' Используя здесь «наследование», система предпочтений будет пробовать следующие предпочтения: 'acme.ui.splash_screen.bgcolor' 'acme.ui.bgcolor' 'acme.bgcolor' 'bgcolor' струны, великолепные струны Здесь стоит упомянуть, что всегда сохраняются и возвращаются как струны.Это связано с ограничениями традиционного формата файлов .ini, т.е. они не содержат никакой информации о типе! Прежде чем вы начнете паниковать, это не значит что все ваши предпочтения должны быть струнными! В настоящее время система предпочтений позволяет, строки (!), логические, целые, длинные, числа с плавающей запятой и комплексные числа. Когда вы храните нестроковый значение он преобразуется в строку для вас, но вы всегда получаете строку обратно: >>> предпочтения.получить ('acme.ui.width') '50' >>> preferences.set ('acme.ui.width', 100) >>> preferences.get ('acme.ui.width') «100» >>> preferences.get ('acme.ui.visible') 'Истинный' >>> preferences.set ('acme.ui.visible', ложь) >>> preferences.get ('acme.ui.visible') 'Ложь' Очевидно, что это не очень удобно, поэтому в следующем разделе обсуждается, как мы связать информацию о типе с нашими предпочтениями, чтобы получить и настроить их больше естественный.
ПРЕДПОЧТЕНИЯ И ТИПЫ
Как упоминалось ранее, мы хотели бы иметь возможность получать и устанавливать нестроковые предпочтения в более удобный способ. Здесь на помощь приходит класс PreferencesHelper . Давайте еще раз посмотрим на example.ini: [acme.ui] bgcolor = синий ширина = 50 коэффициент = 1.0 visible = True [acme.ui.splash_screen] изображение = всплеск fgcolor = красный Скажем, меня интересуют предпочтения в 'acme.ui 'раздел. Я могу использовать настройки помощник в следующем виде: из apptools.preferences.api import PreferencesHelper класс SplashScreenPreferences (PreferencesHelper): "" "Помощник настроек для заставки." "" PREFERENCES_PATH = 'acme.ui' bgcolor = Str width = Int ratio = Float visible = Bool >>> предпочтения = Предпочтения (filename = 'example.ini') >>> helper = SplashScreenPreferences (предпочтения = предпочтения) >>> помощник.bgcolor 'синий' >>> helper.width 100 >>> helper.ratio 1.0 >>> helper.visible Истинный И, очевидно, я могу также установить значение предпочтений через помощник: >>> helper.ratio = 0,5 И если вы хотите доказать себе, что предпочтение действительно установлено: >>> preferences.get ('acme.ui.ratio') '0,5' Используя помощник по настройкам, вы также получаете уведомление через обычный механизм черт, когда предпочтения изменяются (либо через помощник, либо через узел предпочтений напрямую: def listener (obj, trait_name, old, new): напечатать trait_name, old, new >>> помощник.on_trait_change (слушатель) >>> helper.ratio = 0,75 коэффициент 0,5 0,75 >>> preferences.set ('acme.ui.ratio', 0,33) коэффициент 0,75 0,33 Если вы всегда используете тот же узел предпочтений в качестве корня ваших предпочтений, вы также можете установите атрибут класса PreferencesHelper.preferences как этот узел и с этого момента in вам не нужно передавать коллекцию настроек каждый раз, когда вы создаете помощник: >>> PreferencesHelper.предпочтения = Предпочтения (имя файла = 'example.ini') >>> helper = SplashScreenPreferences () >>> helper.bgcolor 'синий' >>> helper.width 100 >>> helper.ratio 1.0 >>> helper.visible Истинный
ОПИСАНИЕ ПРЕДПОЧТЕНИЯ
Во многих приложениях полезна идея области предпочтений. В ограниченной системе фактическое значение предпочтения может быть сохранено в любой области, и при вызове метода get поиск областей в порядке приоритета.Реализация по умолчанию (в классе ScopedPreferences ) предоставляет две области действия дефолт: 1. Область применения Эта область хранится в каталоге ETSConfig.application_home. Этот объем обычно используется, когда задает какие-либо пользовательские настройки. 2. Объем по умолчанию Эта область видимости временна (т.е. она нигде не хранится). Этот объем обычно используется для загрузки любых предопределенных значений по умолчанию в систему настроек.Если вас устраивает расположение по умолчанию, то использовать настройки с ограниченным объемом например, используя простую старую версию без области видимости: >>> из apptools.preferences.api импортировать ScopedPreferences >>> предпочтения = ScopedPreferences (filename = 'example.ini') >>> preferences.load ('example.ini') >>> p.dump () Узел () {} Узел (приложение) {} Узел (acme) {} Узел (ui) {'bgcolor': 'blue', 'ratio': '1.0 ',' width ':' 50 ',' visible ':' True '} Узел (splash_screen) {'изображение': 'всплеск', 'fgcolor': 'красный'} Узел (по умолчанию) {} Здесь вы можете видеть, что у корневого узла теперь есть дочерний узел, представляющий каждую область. Когда мы получаем и устанавливаем предпочтения с помощью областей видимости, нам обычно нужны следующие поведение: а) Когда мы получаем предпочтение, мы хотим просмотреть его по порядку в каждой области. Первый размах который содержит значение «выигрывает». б) Когда мы устанавливаем предпочтение, мы хотим установить его в первой области.По умолчанию это означает что когда мы устанавливаем предпочтение, оно будет установлено в области приложения. Это точно что мы хотим, поскольку область приложения - это постоянная область действия. Поэтому обычно мы просто используем настройки с ограниченной областью действия, как и раньше: >>> preferences.get ('acme.ui.bgcolor') 'синий' >>> preferences.set ('acme.ui.bgcolor', 'красный') >>> preferences.dump () Узел () {} Узел (приложение) {} Узел (acme) {} Узел (ui) {'bgcolor': 'красный', 'ratio': '1.0 ',' width ':' 50 ',' visible ':' True '} Узел (splash_screen) {'изображение': 'всплеск', 'fgcolor': 'красный'} Узел (по умолчанию) {} И, что удобно, хелперы предпочтений работают точно так же и с ограниченными предпочтениями: >>> PreferencesHelper.preferences = ScopedPreferences (filename = 'example.ini') >>> helper = SplashScreenPreferences () >>> helper.bgcolor 'синий' >>> helper.width 100 >>> помощник.соотношение 1.0 >>> helper.visible Истинный Доступ к в частности область Если вы хотите получить или установить предпочтение в определенной области, вы используете следующий синтаксис: >>> preferences.set ('default / acme.ui.bgcolor', 'красный') >>> preferences.get ('default / acme.ui.bgcolor') 'красный' >>> preferences.dump () Узел () {} Узел (приложение) {} Узел (acme) {} Узел (ui) {'bgcolor': 'красный', 'ratio': '1.0 ',' width ':' 50 ',' visible ':' True '} Узел (splash_screen) {'изображение': 'всплеск', 'fgcolor': 'красный'} Узел (по умолчанию) {} Узел (acme) {} Узел (ui) {'bgcolor': 'красный'} Вы также можете получить прицел через: >>> default = preferences.get_scope ('по умолчанию') А затем проделать с ним любую из обычных операций.
ДАЛЬНЕЙШИЕ ЧТЕНИЕ
Итак, это краткий обзор базового использования API настроек.Для большего Информацию о том, что предоставляется, см. в документации API . Если вы используете Envisage для создания своих приложений, вас также может заинтересовать Preferences in Envisage section.
ПРЕДПОЧТЕНИЯ IN ENVISAGE
В этом разделе обсуждается, как приложение Envisage использует механизм предпочтений. Envisage старается не диктовать слишком много, поэтому здесь описывается поведение по умолчанию, но вы можете изменить его по своему усмотрению.Envisage использует реализацию по умолчанию класса ScopedPreferences , которая сделана доступно через черту приложения "настройки": >>> приложение = Приложение (id = 'myapplication') >>> application.preferences.set ('acme.ui.bgcolor', 'желтый') >>> application.preferences.get ('acme.ui.bgcolor') 'желтый' Следовательно, вы используете предпочтения Envisage так же, как и любые другие предпочтения с ограниченным объемом.Он также регистрируется как узел предпочтений по умолчанию, используемый PreferencesHelper учебный класс. Следовательно, вам не нужно явно указывать узел предпочтений своему помощнику: >>> helper = SplashScreenPreferences () >>> helper.bgcolor 'синий' >>> helper.width 100 >>> helper.ratio 1.0 >>> helper.visible Истинный Единственное, что делает для вас Envisage - это точка расширения, которая позволяет вносить любое количество файлов.ini ', которые загружаются в область по умолчанию при запуске приложения. например Чтобы добавить файл настроек для моего плагина, я могу использовать: класс MyPlugin (Плагин): ... @contributes_to ('envisage.preferences') def get_preferences (себя, приложение): return ['pkgfile: // mypackage: preferences.ini']
АВТОМАТИЧЕСКИЙ СКРИПТ ЗАПИСЬ
Этот пакет предоставляет очень удобное и мощное средство записи скриптов Python.Этот можно использовать для: · Записывать все действия, выполняемые в пользовательском интерфейсе на основе характеристик, в человек читаемый , Python скрипт, который должен иметь возможность воссоздавать ваши действия пользовательского интерфейса. · Легко изучить скриптовый API приложения. Этот пакет - не просто игрушечный фреймворк, он достаточно мощный, чтобы предоставить полный сценарий. запись в приложение Mayavi . Mayavi - это мощный инструмент 3D-визуализации, который часть ETS . сценарии API API сценариев в первую очередь позволяет записывать действия пользовательского интерфейса для объектов, имеющих свойства. Технически фреймворк отслеживает все изменения характеристик, поэтому будет работать вне пользовательского интерфейса. Мы делаем не документируйте полный API здесь, лучшее место для поиска - это apptools.scripting.recorder модуль, который достаточно хорошо документирован. Мы обеспечиваем высокий обзор уровня библиотеки.Самый быстрый способ начать - это рассмотреть небольшой пример. A тур по пример Следующий пример взят из набора тестов. Рассмотрим набор простых предметов организованы в иерархию: из импорта traits.api (HasTraits, Float, Instance, Str, List, Bool, HasStrictTraits, Tuple, Range, TraitPrefixMap, Черта) из импорта apptools.scripting.api (Рекордер, записываемый, set_recorder) Свойство класса (HasStrictTraits): цвет = Кортеж (Диапазон (0.0, 1,0), диапазон (0,0, 1,0), диапазон (0,0, 1,0)) непрозрачность = Диапазон (0,0; 1,0; 1,0) представление = Trait ('поверхность', TraitPrefixMap ({'поверхность': 2, 'каркас': 1, 'points': 0})) класс Игрушка (HasTraits): color = Str type = Str # Обратите внимание на использование метаданных признака, чтобы игнорировать этот признак. ignore = Bool (Ложь, запись = Ложь) класс Child (HasTraits): name = Str ('ребенок') age = Float (10.0) # Регистратор проходит через суб-экземпляры, если они отмечены # с record = True свойство = Экземпляр (Свойство, (), запись = Истина) игрушка = Экземпляр (Игрушка, запись = Истина) друзья = Список (Str) # Декоратор записывает метод. @recordable def grow (self, x): "" "Увеличить возраст на x лет." "" self.age + = x Родитель класса (HasTraits): children = Список (Дочерний, запись = True) рекордер = Экземпляр (Рекордер, запись = Ложь) Используя эти простые классы, мы сначала создаем простую иерархию объектов следующим образом: p = Родитель () c = Ребенок () t = Игрушка () c.игрушка = т p.children.append (c) Учитывая эту иерархию, мы хотели бы иметь возможность записывать сценарий. Для этого мы настраиваем инфраструктура записи: из mayavi.core.recorder import Recorder, set_recorder # Создать рекордер. r = Регистратор () # Установите глобальный рекордер, чтобы декоратор работал. set_recorder (r) r.register (p) r.recording = Истина Ключевым методом здесь является вызов r.register (p) выше.Он смотрит на черты p и находит все признаки и вложенные объекты, которые указывают запись = True в их метаданных признака (все методы, начинающиеся и заканчивающиеся на _ , игнорируются). Все подобъекты по очереди зарегистрирован на диктофоне и так далее. Обратные вызовы привязаны к изменениям характеристик и они подключены для создания читаемого и исполняемого кода. Вызов set_recorder (r) является также очень важно и устанавливает глобальный регистратор, чтобы фреймворк слушал любые функции которые украшены записываемым декоратором .Теперь давайте проверим это так: # Будет записано следующее. c.name = 'Шива' c.property.presentation = 'ш' c.property.opacity = 0,4 c.grow (1) Чтобы увидеть, что было записано, сделайте следующее: напечатать r.script Это печатает: child = parent.children [0] child.name = 'Шива' child.property.presentation = 'каркас' child.property.opacity = 0,40000000000000002 child.grow (1) Регистратор внутренне поддерживает сопоставление между объектами и уникальными именами для каждого объект.Он также хранит информацию о местоположении конкретного объекта в иерархия объектов. Например, путь к экземпляру Toy в иерархии выше: parent.children [0] .toy . Поскольку создание сценариев со списками таким способом может быть утомительным, диктофон сначала создает экземпляр ребенка : child = parent.children [0] В последующих строках используется дочерний атрибут . Регистратор всегда пытается создать экземпляр объект упоминается с использованием информации о своем пути таким образом.Чтобы записать вызов функции или метода, нужно просто украсить функцию / метод символом записываемый декоратор. Вложенные записываемые функции не записываются, а изменения признаков также не записывается, если выполняется внутри записываемой функции. ПРИМЕЧАНИЕ: 1. Очень важно отметить, что глобальный регистратор должен быть установлен через set_recorder метод. Декоратор с возможностью записи полагается на это, чтобы он работал.2. Записываемый декоратор будет работать как с простыми классами Python, так и с функциями. Чтобы остановить запись, сделайте следующее: r.unregister (p) r.recording = Ложь r.unregister (p) отменяет вызов r.register (p) и отменяет регистрацию всех вложенных объектов как Что ж. Продвинутый использовать ящика Вот несколько сложных вариантов использования. · API также предоставляет класс RecorderWithUI , который обеспечивает простой пользовательский интерфейс. который печатает записанный сценарий и позволяет пользователю сохранить сценарий.· Иногда недостаточно просто фиксировать изменения черт, можно сдать произвольная строка или команда при записи. Чтобы учесть это, если определяет признак рекордера на объекте, он устанавливается на текущий рекордер. Можно затем используйте этот диктофон, чтобы делать все, что угодно. Это очень удобно. · Чтобы игнорировать определенные черты, необходимо указать метаданные record = False для определение признака или укажите список строк в регистре метод в игнорировать аргумент ключевого слова.· Если вы хотите использовать конкретное имя для объекта в сценарии, вы можете передать script_id параметр функции регистра. Более подробно о самом регистраторе предлагаем прочитать исходный код модуля. это достаточно хорошо задокументирован и с приведенной выше предысторией должно быть достаточно, чтобы вы начали.
UNDO РАМКА
Undo Framework - это компонент Enthought Tool Suite, который предоставляет разработчикам с API, реализующим стандартный шаблон для команд do / undo / redo.Фреймворк полностью настраивается. Альтернативные реализации всех основных компоненты могут быть предоставлены при необходимости. Структура Концепции Следующие концепции поддерживаются фреймворком. · Команда Команда - это определенная приложением операция, которую можно выполнить (т.е. выполнить), отменить (т.е. возвращено) и переделано (т.е. повторено). Команда работает с некоторыми данными и поддерживает достаточное состояние, чтобы позволить ей вернуться или повторить изменение данных.Команды могут быть объединены, так что потенциально длинные последовательности похожих команд (например, добавить символ к тексту) можно свернуть в одну команду (например, добавить слово к какому-то тексту). · Макро Макрос - это последовательность команд, которая при отмене обрабатывается как одна команда. или переделан. · Стек команд Команда выполняется путем помещения ее в стек команд. Последнюю команду можно отменить и повторить, вызвав соответствующие методы стека команд.Также можно переехать положение стека в любую точку, и стек команд гарантирует, что команды отменено или переделано по мере необходимости. Стек команд поддерживает чистое состояние , которое обновляется по мере выполнения команд и отменено. Он может быть установлен явно, например, когда данные обрабатываются команды сохраняются на диск. Стандартные действия PyFace предоставляются как оболочки для методов стека команд для реализации общие пункты меню.· Менеджер отмены Диспетчер отмены отвечает за один или несколько стеков команд и поддерживает ссылку в текущий активный стек. Он предоставляет удобные методы отмены и повтора, которые работают с текущим активным стеком. Менеджер отмены гарантирует, что каждому выполнению команды назначена уникальная последовательность число, независимо от того, в какой стек команд он помещен. Используя это возможно для синхронизации нескольких стеков команд и восстановления их на определенный момент времени.Менеджер отмены будет генерировать событие всякий раз, когда чистое состояние активного стека изменения. Это можно использовать для поддержки своего рода индикатора состояния графического интерфейса пользователя, чтобы сообщить пользователь, что его данные были изменены с момента последнего сохранения. Обычно в приложении есть один менеджер отмены и один стек отмены для каждого типа данных. которые можно редактировать. Однако это не требование: как стек команд в конкретные организованы и связаны (с порядковым номером менеджера пользователей) могут потребоваться тщательно продумать, чтобы не запутать пользователя - особенно в приложении на основе плагинов у этого может быть много редакторов.Для поддержки этого типичного использования класс PyFace Workbench имеет черту undo_manager и Класс PyFace Editor имеет черту command_stack . Оба загружаются лениво, поэтому могут быть полностью игнорируются, если они не используются. API Обзор В этом разделе дается краткий обзор различных классов, реализованных во фреймворке. Полная документация API доступна в виде HTML-кода, сгенерированного эндо.Приложение example демонстрирует все основные функции фреймворка. UndoManager Класс UndoManager является реализацией по умолчанию интерфейса IUndoManager . active_stack Эта черта является ссылкой на текущий активный стек команд и может иметь значение None. Обычно он устанавливается, когда становится активным какой-то редактор. active_stack_clean Этот логический признак отражает чистое состояние текущего активного стека команд.Он предназначен для поддержки индикатора «документ изменен» в графическом интерфейсе пользователя. Это поддерживается менеджером отмены. stack_updated Это событие вызывается при изменении индекса стека команд. Ссылка на стек передается как аргумент событию и может не быть активным в данный момент куча. undo_name Эта черта Unicode - это имя команды, которую можно отменить, и она будет пустой. если такой команды нет.Он поддерживается менеджером отмены. redo_name Эта черта Unicode - это имя команды, которую можно повторить, и она будет пустой. если такой команды нет. Он поддерживается менеджером отмены. sequence_nr Эта целочисленная характеристика - порядковый номер следующей команды, которая должна быть выполнена. Это увеличивается непосредственно перед вызовом метода do () команды. Особый порядковый номер определяет состояние всех стеков команд, обрабатываемых отменой менеджер и позволяет установить эти стеки в точку, в которой они находились в конкретном момент времени.Другими словами, порядковый номер позволяет стеки команд для синхронизации. undo () Этот метод вызывает метод undo () последней команды активной команды. куча. redo () Этот метод вызывает метод redo () последней отмененной команды на активном стек команд. CommandStack Класс CommandStack является реализацией по умолчанию интерфейса ICommandStack . clean Эта логическая характеристика отражает чистое состояние стека команд. Его ценность изменяется по мере выполнения, отмены и повторного выполнения команд. Также можно явно указать чтобы отметить текущую позицию стека как чистую (когда данные сохраняются на диск для пример). undo_name Эта черта Unicode - это имя команды, которую можно отменить, и она будет пустой. если такой команды нет.Он поддерживается стеком команд. redo_name Эта черта Unicode - это имя команды, которую можно повторить, и она будет пустой. если такой команды нет. Он поддерживается стеком команд. undo_manager Эта черта является ссылкой на диспетчер отмены, который управляет стеком команд. push (команда) Этот метод выполняет заданную команду, вызывая ее метод do () .Любое значение возвращается do () возвращается push () . Если команду не удалось объединить с предыдущий, то он сохраняется в стеке команд. отменить (sequence_nr = 0) Этот метод отменяет последнюю команду. Если указан порядковый номер, то все команды отменяются до включенного порядкового номера. повторить (sequence_nr = 0) Этот метод повторяет последнюю команду и возвращает любой результат.Если порядковый номер дается, то все команды переделываются, включая порядковый номер и возвращается любой результат последнего из них. прозрачный () Этот метод очищает стек команд без отмены или повторения каких-либо команд, и оставляет стек в чистом состоянии. Обычно он используется, когда все изменения данные были заброшены. begin_macro (имя) Этот метод начинает макрос с создания пустой команды с заданным именем.В команды, переданные всем последующим вызовам push () , будут содержаться в макросе до следующего вызова end_macro () . Макросы могут быть вложенными. Стек команд отключено (т.е. ничего нельзя отменить или повторить) во время создания макроса (т.е. пока есть невыполненный вызов end_macro () ). end_macro () Этот метод завершает текущий макрос. ICкоманда Интерфейс ICommand определяет интерфейс, который должен быть реализован любым команда отмены / повторения. данные Эта необязательная черта является ссылкой на объект данных, с которым работает команда. Самым фреймворком он не используется. name Эта черта Unicode - это имя команды, которое будет отображаться в любом элементе графического интерфейса. (например, в тексте пункта меню отмены и повтора). Он может включать и для обозначения сочетание клавиш, которое будет автоматически удаляться, если оно неуместно. __init __ (* аргументы) Если команда принимает аргументы, то она должна гарантировать, что глубокие копии должны при необходимости. do () Этот метод вызывается стеком команд для выполнения команды и возврата любого результат. Команда должна сохранять любое состояние, необходимое для undo () и redo () методы работы. Гарантируется, что это будет вызвано только один раз и что он будет вызываться перед любым вызовом undo () или redo () . undo () Этот метод вызывается стеком команд для отмены команды. redo () Этот метод вызывается стеком команд для повторения команды и возврата любого результат. объединить (другое) Этот метод вызывается стеком команд, чтобы попытаться объединить другую команду с Вот этот. Значение true должно быть возвращено, если команды были объединены. Если команды объединяются, тогда , остальные не будут помещены в стек команд. Последующая отмена или повтор этой измененной команды должен иметь тот же эффект, что и два исходных команды. АннотацияCommand AbstractCommand - абстрактный базовый класс, реализующий интерфейс ICommand . Это предоставляет реализацию по умолчанию для метода merge () . CommandAction Класс CommandAction является подклассом класса PyFace Action , который используется для переноса команды. команда Эта вызываемая черта должна быть установлена на фабрику, которая будет возвращать объект, который реализует ICommand .Он будет вызываться при вызове действия и объекта created помещается в стек команд. command_stack Этот признак экземпляра должен быть установлен в стек команд, которые вызываются действие перенесено на. данные Эта необязательная характеристика является ссылкой на объект данных, который будет передан в команда factory при ее вызове. Отменить действие Класс UndoAction - это стандартное действие PyFace, которое отменяет последнюю команду активного стек команд. Повторить действие Класс RedoAction - это стандартное действие PyFace, которое повторяет последнюю команду, отмененную из активный стек команд.
ВЫБОР СЕРВИС
В приложениях с графическим интерфейсом довольно часто встречается элемент пользовательского интерфейса, отображающий набор элементы, которые пользователь может выбрать («поставщики выбора»), в то время как другие части приложения должен реагировать на изменения в выборе («слушатели выбора»).В идеале слушатели не должны иметь прямой зависимости от объекта пользовательского интерфейса. Это особенно важно в расширяемых , предусмотренных приложениях, где плагину может потребоваться реагировать на изменение выбора, но мы не хотим раскрывать внутреннюю организацию приложение для внешних разработчиков. Этот пакет определяет службу выбора, которая управляет связью между поставщиками. и слушатель. Объект SelectionService объект Объект SelectionService - это центральный менеджер, который управляет обменом данными между выбор провайдеров и слушателей. Выбор провайдеров - это компоненты, которые хотят опубликовать информацию о своих текущих выбор для общественного потребления. Они регистрируются в экземпляре службы выбора, когда сначала иметь доступный выбор (например, когда пользовательский интерфейс, показывающий список выбираемых элементов, инициализировано) и отмените регистрацию, как только выбор станет недоступен (например, UI разрушается при закрытии окон). Выбор слушателей могут запросить службу выбора, чтобы опубликовать текущий выбор поставщиком, используя уникальный идентификатор поставщика.Сервис действует как посредник между провайдерами и слушателями, обеспечивая их уведомляется, когда запускается событие selection . Выбор провайдеров Любой объект может стать поставщиком выбора, реализовав ISelectionProvider интерфейс и регистрация в службе выбора. Поставщики выбора должны предоставить уникальный идентификатор provider_id , который используется слушателями для запросить текущий выбор.Каждый раз, когда его выбор изменяется, провайдеры запускают событие selection . Содержание мероприятия - это экземпляр, реализующий ISelection , который содержит информацию о выбранных элементах. Например, объект ListSelection содержит список выбранных элементов и их индексы. У поставщиков выбора также можно напрямую запросить их текущий выбор с помощью get_selection , и может быть предложено изменить их выбор на новый с помощью set_selection метод. Регистрация Поставщики услуг отбора публикуют свой выбор, регистрируясь в службе отбора с помощью метод add_selection_provider . Когда выбор больше не доступен, выбор провайдеры должны отменить регистрацию через remove_selection_provider . Обычно провайдеры выбора - это объекты пользовательского интерфейса, показывающие список или дерево элементов, они зарегистрируйтесь, как только компонент пользовательского интерфейса будет инициализирован, и отмените регистрацию, когда компонент пользовательского интерфейса исчезает (e.г., потому что их окно было закрыто). В более сложных приложениях вместо этого регистрация может быть выполнена с помощью объекта контроллера. Selection слушателя Слушатели выбора запрашивают информацию о текущем выборе выбора поставщик, учитывая их идентификатор поставщика. SelectionService поддерживает два различных варианта использования: 1. Пассивное прослушивание изменений выбора: слушатель подключается к определенному провайдеру. и получают уведомление при изменении выбора поставщика.2. Активно запрашивает у поставщика текущий выбор: услуга выбора может быть используется для запроса поставщика с использованием его уникального идентификатора. Пассивный слушающий Слушатели подключаются к событиям выбора для данного поставщика с помощью connect_selection_listener метод. Им необходимо предоставить уникальный идентификатор поставщика, и функция (или вызываемая), которая вызывается для отправки события. Эта функция обратного вызова принимает один аргумент, реализация ISelection , которая представляет выбор.Слушатель может подключиться к идентификатору поставщика до того, как он будет зарегистрирован. Как только как только провайдер зарегистрирован, слушатель получит уведомление, содержащее первоначальный выбор провайдера. Чтобы отключить слушателя, используйте методы disconnect_selection_listener . Активный запрос В других случаях элементу приложения требуется только текущий выбор в конкретное время. Например, кнопка на панели инструментов может открывать диалог, представляющий действие пользователя. на основе того, что в данный момент выбрано в активном редакторе.Метод get_selection вызывает соответствующий метод поставщика с заданным идентификатором и возвращает экземпляр ISelection . Настройка a выбор Наконец, можно попросить поставщика установить его выбор на заданный набор объекты с set_selection . Основной вариант использования этого метода - несколько представлений тот же список объектов, выбор которых должен синхронизироваться.Если элементы, указанные в аргументах, недоступны в поставщике, ProviderNotRegisteredError возникает, если только необязательный аргумент ключевого слова ignore_missing установлено значение True . API Ссылка apptools.selection Пакет Пользователи пакета apptools.selection могут получить доступ к объектам, которые являются частью общего доступа. API через удобство apptools.selection.api . selection_service Модуль класс apptools.selection.selection_service.SelectionService Базы: traits.has_traits.HasTraits Служба выбора соединяет провайдеров выбора и слушателей. Сервис выбора - это реестр поставщиков выбора, то есть объектов, которые опубликовать свой текущий выбор. Выборы можно запрашивать активно, явно запрашивая текущий выбор в провайдере ( get_selection (id) () ) или пассивно путем подключения выбора слушатели. add_selection_provider (поставщик) Добавьте поставщика выбора. Провайдер идентифицируется по его ID. Если у провайдера с таким же ID есть был уже зарегистрирован, возникает ошибка IDConflictError . Аргументы: провайдер - ISelectionProvider Поставщик выбора добавлен во внутренний реестр. connect_selection_listener (provider_id, func) Подключите слушателя к событиям выбора от определенного провайдера. Подпись, если обратный вызов слушателя - func (i_selection) . Слушатель называется: 1. Когда провайдер с данным идентификатором зарегистрирован, с его начальным выбор в качестве аргумента, или 2. всякий раз, когда провайдер запускает событие выбора.Совершенно верно подключить слушателя до провайдера с данным ID зарегистрирован. Слушатель останется подключенным, даже если провайдер неоднократно подключались и отключались. Аргументы: provider_id - str ID поставщика выбора. func - вызываемый (i_selection) Вызываемый объект, который уведомляется при изменении выбора. Disconnect_selection_listener (provider_id, func) Отключите слушателя от определенного провайдера. Аргументы: provider_id - str ID поставщика выбора. func - вызываемый (provider_id, i_selection) Вызываемый объект, который уведомляется при изменении выбора. get_selection (provider_id) Вернуть текущий выбор поставщика с заданным идентификатором. Если провайдер с таким идентификатором не был зарегистрирован, Возникла ошибка ProviderNotRegisteredError . Аргументы: provider_id - str ID поставщика выбора. Возвраты: выбор - ISelection Текущий выбор провайдера. has_selection_provider (provider_id) Зарегистрирован ли провайдер с данным идентификатором? remove_selection_provider (поставщик) Удалить поставщика выбора. Если провайдер не зарегистрирован, ProviderNotRegisteredError поднятый. Аргументы: провайдер - ISelectionProvider Поставщик выбора добавлен во внутренний реестр. set_selection (provider_id, элементов, ignore_missing = False) Установите текущий выбор в поставщике для данных элементов. Если провайдер с данным идентификатором не зарегистрирован, Возникла ошибка ProviderNotRegisteredError .Если ignore_missing равно True , элементы, недоступные в выборе провайдера молча игнорируются. Если False (по умолчанию), ValueError должен быть поднятым. Аргументы: provider_id - str ID поставщика выбора. позиции - список Список элементов для выбора. ignore_missing - bool Если Ложь (по умолчанию), провайдер вызывает исключение, если любое из элементы в элементы недоступны для выбора. В противном случае отсутствующие элементы игнорируются, а остальные выбрано. i_selection_provider Модуль класс apptools.selection.i_selection_provider.ISelectionProvider Базы: traits.has_traits.Interface Источник выборки. get_selection () Вернуть текущий выбор. Возвраты: выбор - ISelection Объект, представляющий текущий выбор. provider_id = Str () Уникальный идентификатор, идентифицирующий поставщика. выбор = Событие Событие срабатывает при изменении выбора. Содержание мероприятия - ISelection экземпляр. set_selection (items, ignore_missing = False) Установите текущий выбор для данных элементов. Если ignore_missing равно True , элементы, недоступные в выборе провайдера молча игнорируются.Если False (по умолчанию), ValueError должен быть поднят. Аргументы: позиции - список Список элементов для выбора. ignore_missing - bool Если Ложь (по умолчанию), провайдер вызывает исключение, если любое из элементы в элементы недоступны для выбора.В противном случае отсутствующие элементы игнорируются, а остальные выбрано. is_selection Модуль класс apptools.selection.i_selection.IListSelection Базы: apptools.selection.i_selection.ISelection Выбор для упорядоченных последовательностей элементов. индексов = Список Индексы выбранных объектов в поставщике выбора. позиции = Список Выбранные объекты. класс apptools.selection.i_selection.ISelection Базы: traits.has_traits.Interface Сбор избранных предметов. is_empty () Выбор пуст? provider_id = Str ID поставщика выбора, создавшего этот объект выбора. list_selection Модуль класс apptools.selection.list_selection.ListSelection Базы: traits.has_traits.HasTraits Выбор для упорядоченных последовательностей элементов. Это реализация по умолчанию интерфейса IListSelection . classmethod from_available_items (provider_id, selected, all_items) Создайте выборку из списка всех доступных элементов.Заполняет необходимую информацию (в частности, индексы) на основании список выбранных элементов и список всех доступных элементов. ПРИМЕЧАНИЕ: · Список доступных элементов не должен содержать повторяющихся элементов. · Ожидается, что выбранных заполнены элементами в all_items . индексов = Список Индексы выбранных объектов в поставщике выбора. is_empty () Выбор пуст? позиции = Список Выбранные объекты. provider_id = Str ID поставщика выбора, создавшего этот объект выбора. ошибок Модуль исключение apptools.selection.errors.IDConflictError (provider_id) Базы: Исключение Возникает, когда провайдер добавлен и его идентификатор уже зарегистрирован. исключение apptools.selection.errors.ListenerNotConnectedError (provider_id, listener) Базы: Исключение Возникает, когда слушатель, который никогда не был подключен, отключается. исключение apptools.selection.errors.ProviderNotRegisteredError (provider_id) Базы: Исключение Возникает, когда провайдер запрашивается по ID и не найден. · поиск
АВТОР
Задумался
АВТОРСКИЕ ПРАВА
2008-2019, Придумал
Snapchat сообщает, что 400 тыс. Человек уже зарегистрировались для голосования через его инструменты в приложении
В прошлом месяце Snapchat представил новый набор инструментов для поощрения пользователей Snapchat к голосованию на предстоящих президентских выборах в США, в том числе подсказки для регистрации и руководства, которые помогут голосующим впервые высказать свое мнение.
И эти инициативы уже оказывают влияние — согласно новому отчету Axios, более 407 000 человек уже зарегистрировались для голосования в Snapchat, и в ближайшие недели приложение планирует запустить еще больше инструментов и уведомлений для избирателей.
Данные особенно важны, учитывая прошлые усилия Snapchat по поощрению участия избирателей. Еще в 2018 году в рамках аналогичной кампании по поощрению голосования в среднесрочной перспективе в США около 450 000 пользователей Snapchat зарегистрировались для голосования, и около 57% из них фактически проголосовали на выборах.
Это равняется примерно 260 000 дополнительных голосов, поданных как прямой результат толчка через приложение.
Конечно, 260 тысяч — это лишь небольшая часть от общего числа голосующих в США — например, на президентских выборах в США в 2016 году проголосовали около 138 миллионов человек, в результате чего Дональд Трамп одержал победу над Хилари Клинтон. Но границы победы на ключевых местах были очень малы — на большинстве мест, где Трамп победил Клинтона, их разделяло менее 200 тысяч голосов.
Это говорит о том, что поощрение к участию еще 260 тыс. Людей может иметь значительное влияние — и, учитывая, что до фактического голосования остались недели, первые цифры последней инициативы Snapchat для избирателей обнадеживают.
Может ли Snapchat быть приложением, которое решает результат?
Определенно, ожидается, что молодые избиратели будут иметь гораздо большее влияние в 2020 году, и Snapchat явно имеет сильную связь с молодой аудиторией.
И, как уже отмечалось, Snapchat все еще разрабатывает и другие планы поощрения избирателей.Согласно Axios, бывший президент Барак Обама скоро будет показан в новом Snapchat PSA, чтобы побудить впервые и молодых избирателей зарегистрироваться для голосования через приложение. К Обаме также присоединятся такие знаменитости, как Арнольд Шварценеггер, Снуп Догг, Кэтрин МакБрум. , и Куинси Браун, в рамках различных программ, направленных на дальнейшее расширение участия.
В более широком плане охват аудитории Snapchat очень мал — Snapchat в настоящее время видит 238 миллионов активных пользователей в день, в отличие от 1 у Facebook.79 миллиардов DAU. Но это все равно может иметь большое влияние — если Snapchat сможет привлечь к опросам больше молодых людей, когорту с исторически низким уровнем участия, это определенно может повлиять на конечный результат.
Snapchat стремится сыграть большую роль в увеличении этой цифры, и, исходя из этих ранних цифр, она, вероятно, сыграет некоторую роль в максимальном увеличении участия.
isc-apptools-lockdown
Программа для повышения безопасности и создания пользователей и добавления привилегий SQL.
Установка с ZPM
zpm: ПОЛЬЗОВАТЕЛЬ> установить isc-apptools-lockdown
Установка с Docker
Предварительные требования
Убедитесь, что у вас установлены git и рабочий стол Docker.
Установка
Clone / git перетащить репо в любой локальный каталог
$ git clone https://github.com/SergeyMi37/isc-apptools-lockdown.git
Откройте терминал в этом каталоге и запустите:
$ сборка docker-compose
- Запустите контейнер IRIS с вашим проектом:
$ docker-compose up -d
Как это проверить
Откройте терминал IRIS:
$ docker-compose exec iris iris сеанс iris
Повышение настроек безопасности
Вы можете заменить общий пароль, если пароль предопределенных пользователей системы был скомпрометирован
IRISAPP> do ## class (Прил.LockDown) .ChangePassword ("NewPass231", ## class (App.LockDown) .GetPreparedUsers ())
Приложение к системе LockedDown, если оно было установлено с исходными настройками безопасности, минимальными или нормальными.
Вы можете получить и изучить описание параметров метода с помощью такой команды, как и любой другой элемент любого другого класса.
IRISAPP> write ## class (App.msg) .man ("App.LockDown) .Apply")
Повышение безопасности системы до LockDown
Метод отключает службы и приложения как в LockDown.Удаляет пространства имен "DOCBOOK", "ENSDEMO", "SAMPLES".
Метод включает аудит и настраивает регистрацию всех событий на портале, кроме переключения журнала.
и изменение свойств системы
Для всех предопределенных пользователей измените пароль и измените свойства, как в LockDown.
newPassword - новый пароль вместо SYS. Для уровня безопасности LockDown он имеет шаблон 8.32ANP.
sBindings = 1 Сервис% service_bindings enable
sCachedirect = 1 Service% service_cachedirect включить
InactiveLimit = 90
DemoDelete = 0 Demoens, пространства имен Samples удаляются
AuditOn = 1
sECP = 1 Service% service_ecp enable
sBindingsIP - список IP-адресов через точку с запятой, для которых разрешено соединение CacheStudio.Для конфигураций ECP вам необходимо добавить адреса всех серверов и клиентов, чтобы разрешить подключение к% Net.RemoteConnection, чтобы удалить «брошенные» задачи.
sCachedirectIP - список IP-адресов с точкой с запятой, для которых разрешено подключение устаревших приложений.
sECPIP - список IP-адресов через точку с запятой, для которых разрешено соединение с ECP-сервером.
AuthLDAP = 1 В дополнение к паролю также включить аутентификацию LDAP
...
Применить настройки безопасности к «LockDown»
IRISAPP> do ## class (Прил.LockDown) .Apply ("NewPassword123",. Msg, 1,1,0,0)
Приложения и сервисы будут аутентифицироваться по паролю
Пароль сброшен для предопределенных пользователей
Модификация свойств сервиса:
% service_cachedirect: ошибка = ОШИБКА № 787: служба% Service_CacheDirect не разрешена лицензией
Пароли создаются для всех приложений CSP.
Есть модификация основных настроек системы
Настройка события AUDIT:
% System /% DirectMode / DirectMode изменено
% System /% Login / Login изменен
% System /% Login / Logout изменено
% System /% Login / Terminate изменено
% System /% Security / Protect изменено
% System /% System / JournalChange изменено
% System /% System / RoutineChange изменено
% System /% System / SuspendResume изменено
Все остальные возможности интерфейсной части программного решения можно найти в
документ
или в статье российского ресурса
.
Добавить комментарий