No project description provided
Project description
<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="icon" href="assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.6.0, mkdocs-material-9.5.31">
<title>lbxtoolkit</title>
<link rel="stylesheet" href="assets/stylesheets/main.3cba04c6.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<link rel="stylesheet" href="assets/_mkdocstrings.css">
<script>__md_scope=new URL(".",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
</head>
<body dir="ltr">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#lbxtoolkit" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header md-header--shadow" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href="." title="lbxtoolkit" class="md-header__button md-logo" aria-label="lbxtoolkit" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"/></svg>
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
lbxtoolkit
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Home
</span>
</div>
</div>
</div>
<script>var media,input,key,value,palette=__md_get("__palette");if(palette&&palette.color){"(prefers-color-scheme)"===palette.color.media&&(media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']"),palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent"));for([key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
</label>
<nav class="md-search__options" aria-label="Search">
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"/></svg>
</button>
</nav>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="." title="lbxtoolkit" class="md-nav__button md-logo" aria-label="lbxtoolkit" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"/></svg>
</a>
lbxtoolkit
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
Home
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="." class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Home
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#lbxtoolkit" class="md-nav__link">
<span class="md-ellipsis">
lbxtoolkit
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit--biblioteca-de-ferramentas-lbx-sa" class="md-nav__link">
<span class="md-ellipsis">
Biblioteca de ferramentas LBX S/A
</span>
</a>
<nav class="md-nav" aria-label="Biblioteca de ferramentas LBX S/A">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#lbxtoolkit--classe-e-funcoes" class="md-nav__link">
<span class="md-ellipsis">
Classe e funções
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit--instalacao-e-uso" class="md-nav__link">
<span class="md-ellipsis">
Instalação e uso:
</span>
</a>
<nav class="md-nav" aria-label="Instalação e uso:">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#lbxtoolkit--instalacao" class="md-nav__link">
<span class="md-ellipsis">
Instalação
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit--uso" class="md-nav__link">
<span class="md-ellipsis">
Uso
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit.ConfigManager" class="md-nav__link">
<span class="md-ellipsis">
ConfigManager
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit.Servicer" class="md-nav__link">
<span class="md-ellipsis">
Servicer
</span>
</a>
<nav class="md-nav" aria-label="Servicer">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#lbxtoolkit.Servicer.cleanup" class="md-nav__link">
<span class="md-ellipsis">
cleanup
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit.Servicer.daemon_log" class="md-nav__link">
<span class="md-ellipsis">
daemon_log
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit.Servicer.run" class="md-nav__link">
<span class="md-ellipsis">
run
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit.Servicer.stop" class="md-nav__link">
<span class="md-ellipsis">
stop
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit.api_rest" class="md-nav__link">
<span class="md-ellipsis">
api_rest
</span>
</a>
<nav class="md-nav" aria-label="api_rest">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#lbxtoolkit.api_rest--classe-api_rest" class="md-nav__link">
<span class="md-ellipsis">
Classe api_rest
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit.auth_EntraID" class="md-nav__link">
<span class="md-ellipsis">
auth_EntraID
</span>
</a>
<nav class="md-nav" aria-label="auth_EntraID">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#lbxtoolkit.auth_EntraID--classe-auth_entraid" class="md-nav__link">
<span class="md-ellipsis">
Classe auth_EntraID
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit.lbx_logger" class="md-nav__link">
<span class="md-ellipsis">
lbx_logger
</span>
</a>
<nav class="md-nav" aria-label="lbx_logger">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#lbxtoolkit.lbx_logger--classe-lbx_logger" class="md-nav__link">
<span class="md-ellipsis">
Classe lbx_logger
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit.misc" class="md-nav__link">
<span class="md-ellipsis">
misc
</span>
</a>
<nav class="md-nav" aria-label="misc">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#lbxtoolkit.misc--classe-misc" class="md-nav__link">
<span class="md-ellipsis">
Classe misc
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit.postgreSQL" class="md-nav__link">
<span class="md-ellipsis">
postgreSQL
</span>
</a>
<nav class="md-nav" aria-label="postgreSQL">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#lbxtoolkit.postgreSQL--classe-postgresql" class="md-nav__link">
<span class="md-ellipsis">
Classe postgreSQL
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#lbxtoolkit" class="md-nav__link">
<span class="md-ellipsis">
lbxtoolkit
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit--biblioteca-de-ferramentas-lbx-sa" class="md-nav__link">
<span class="md-ellipsis">
Biblioteca de ferramentas LBX S/A
</span>
</a>
<nav class="md-nav" aria-label="Biblioteca de ferramentas LBX S/A">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#lbxtoolkit--classe-e-funcoes" class="md-nav__link">
<span class="md-ellipsis">
Classe e funções
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit--instalacao-e-uso" class="md-nav__link">
<span class="md-ellipsis">
Instalação e uso:
</span>
</a>
<nav class="md-nav" aria-label="Instalação e uso:">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#lbxtoolkit--instalacao" class="md-nav__link">
<span class="md-ellipsis">
Instalação
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit--uso" class="md-nav__link">
<span class="md-ellipsis">
Uso
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit.ConfigManager" class="md-nav__link">
<span class="md-ellipsis">
ConfigManager
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit.Servicer" class="md-nav__link">
<span class="md-ellipsis">
Servicer
</span>
</a>
<nav class="md-nav" aria-label="Servicer">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#lbxtoolkit.Servicer.cleanup" class="md-nav__link">
<span class="md-ellipsis">
cleanup
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit.Servicer.daemon_log" class="md-nav__link">
<span class="md-ellipsis">
daemon_log
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit.Servicer.run" class="md-nav__link">
<span class="md-ellipsis">
run
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit.Servicer.stop" class="md-nav__link">
<span class="md-ellipsis">
stop
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit.api_rest" class="md-nav__link">
<span class="md-ellipsis">
api_rest
</span>
</a>
<nav class="md-nav" aria-label="api_rest">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#lbxtoolkit.api_rest--classe-api_rest" class="md-nav__link">
<span class="md-ellipsis">
Classe api_rest
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit.auth_EntraID" class="md-nav__link">
<span class="md-ellipsis">
auth_EntraID
</span>
</a>
<nav class="md-nav" aria-label="auth_EntraID">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#lbxtoolkit.auth_EntraID--classe-auth_entraid" class="md-nav__link">
<span class="md-ellipsis">
Classe auth_EntraID
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit.lbx_logger" class="md-nav__link">
<span class="md-ellipsis">
lbx_logger
</span>
</a>
<nav class="md-nav" aria-label="lbx_logger">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#lbxtoolkit.lbx_logger--classe-lbx_logger" class="md-nav__link">
<span class="md-ellipsis">
Classe lbx_logger
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit.misc" class="md-nav__link">
<span class="md-ellipsis">
misc
</span>
</a>
<nav class="md-nav" aria-label="misc">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#lbxtoolkit.misc--classe-misc" class="md-nav__link">
<span class="md-ellipsis">
Classe misc
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#lbxtoolkit.postgreSQL" class="md-nav__link">
<span class="md-ellipsis">
postgreSQL
</span>
</a>
<nav class="md-nav" aria-label="postgreSQL">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#lbxtoolkit.postgreSQL--classe-postgresql" class="md-nav__link">
<span class="md-ellipsis">
Classe postgreSQL
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1>Home</h1>
<div class="doc doc-object doc-module">
<a id="lbxtoolkit"></a>
<div class="doc doc-contents first">
<h2 id="lbxtoolkit--biblioteca-de-ferramentas-lbx-sa"><strong>Biblioteca de ferramentas LBX S/A</strong></h2>
<p>Esta biblioteca possui um ferramentas utilitárias de uso recorrente para aplicações de RPA em python.</p>
<h3 id="lbxtoolkit--classe-e-funcoes"><strong>Classe e funções</strong></h3>
<p><strong>auth_EntraID</strong> <br />
Usa o Microsoft Entra ID (antiga Azure AD) para evitar execução não autorizada
disclaimer : Mensagem sobre a necessidade de autenticação
valida_grupo : Autentica o usuário e aborta se checa não pertencer ao grupo de segurança</p>
<p><strong>postgreSQL</strong>
Interage com o banco de dados PostgreSQL
- <em>.db</em>: Inicia sessão com o banco
- <em>.csv_df</em>: Lê arquivo CSV e gera Dataframe (pandas) a partir dele
- <em>.db_insert_df</em>: Insere informações de Dataframe em tabela do banco com estrutura equivalente
- <em>.db_select</em>: Retorna um cursor a partir de uma query
- <em>.db_update</em>: Executa update em tabelas</p>
<p><strong>api_rest</strong>
Interage com APIs RESTfull, especialmente providas para a plataforma Sienge
- <em>.auth_base</em>: Autentica (HTTPBasicAuth) sessão na API
- <em>.auth_bearer</em>: Autentica sessão na API pelos métodos: OAuth, JWT, Bearer<br />
- <em>.endpoint_json</em>: Realizad chama ao endpoint. Payload em formato <code>json</code> opcional.
- <em>.trata_erro_sienge</em>: Retorna a mensagem de erro do Sienge caso código de retorno seja diferente de 200.
- <em>.close</em>: Encerra a sessão autenticada</p>
<p><strong>lbx_logger</strong>
Manipula e formata as mensagens de saída do script para direcioná-las para tela (stdout) e/ou arquivo de log
- <em>.add</em>: Adiciona a mensagem a um <em>buffer</em> sem exibir, acumulando até a próxima chamada em algum dos níveis abaixo.
- <em>.print</em>: Contorna o manipulador de log e imprime diretamente na tela (stdout), sem formatar a mensagem nem registrar no arquivo
- <em>.debug, .info, .aviso, .erro, .critico</em>: Classifica as mensagens por nível de severidade/relevância e rediciona a saída (arquivo, tela, tela+arquivo) conforme a configuração do nível
- <em>.stop_logging</em>: Interrompe a manipulação das saídas pelo logger e restaura as saídas padrão (stdout/stderr) para a tela
- <em>.filtra</em>: Filtra os eventos do arquivo de log registrados em um intervalo de tempo específico</p>
<p><strong>misc</strong>
Classe de miscelâneas/diversos
- <em>.seleciona_arquivo</em>: Abre um picker do sistema operacionar para selecionar um <em>arquivo</em> e retorna seu path
- <em>.seleciona_dir</em>: Abre um picker do sistema operacionar para selecionar um <em>diretório</em> e retorna seu path
- <em>.normaliza</em>: Limpa caracteres especiais e espaços de strings e retorna tudo em minúsculo
- <em>.get_cmd_window</em>: Captura a referencia da janela atual (cmd.exe) para retornar o foco à ela depois de chamar os pickers
- <em>.maximize_console</em>: Maxima a janela do console (cmd.exe)</p>
<h3 id="lbxtoolkit--instalacao-e-uso">Instalação e uso:</h3>
<h4 id="lbxtoolkit--instalacao">Instalação</h4>
<pre><code>pip install lbx_toolkit
</code></pre>
<h4 id="lbxtoolkit--uso">Uso</h4>
<pre><code>from lbx_toolkit import auth_EntraID, PostgreSQL, api_rest, lbx_logger
</code></pre>
<div class="doc doc-children">
<div class="doc doc-object doc-class">
<h2 id="lbxtoolkit.ConfigManager" class="doc doc-heading">
<code>ConfigManager</code>
</h2>
<div class="doc doc-contents ">
<p>Como Funciona
Singleton Pattern: ConfigManager é um singleton que garante que todas as partes do código usem a mesma instância e, portanto, compartilhem a mesma configuração.
Inicialização com Argumentos Dinâmicos: O método initialize usa **kwargs para aceitar qualquer número de pares chave-valor, armazenando-os no dicionário _config da instância.
Método Genérico get: O método get aceita uma chave como argumento e retorna o valor correspondente do dicionário _config.
Método set: O método set permite adicionar ou atualizar dinamicamente valores no dicionário _config.
Método reset: O método reset limpa todas as configurações armazenadas, permitindo uma nova inicialização do ConfigManager com novos valores</p>
<details class="quote">
<summary>Source code in <code>lbxtoolkit\__init__.py</code></summary>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">1336</span>
<span class="normal">1337</span>
<span class="normal">1338</span>
<span class="normal">1339</span>
<span class="normal">1340</span>
<span class="normal">1341</span>
<span class="normal">1342</span>
<span class="normal">1343</span>
<span class="normal">1344</span>
<span class="normal">1345</span>
<span class="normal">1346</span>
<span class="normal">1347</span>
<span class="normal">1348</span>
<span class="normal">1349</span>
<span class="normal">1350</span>
<span class="normal">1351</span>
<span class="normal">1352</span>
<span class="normal">1353</span>
<span class="normal">1354</span>
<span class="normal">1355</span>
<span class="normal">1356</span>
<span class="normal">1357</span>
<span class="normal">1358</span>
<span class="normal">1359</span>
<span class="normal">1360</span>
<span class="normal">1361</span>
<span class="normal">1362</span>
<span class="normal">1363</span>
<span class="normal">1364</span>
<span class="normal">1365</span>
<span class="normal">1366</span>
<span class="normal">1367</span>
<span class="normal">1368</span>
<span class="normal">1369</span>
<span class="normal">1370</span>
<span class="normal">1371</span>
<span class="normal">1372</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">class</span> <span class="nc">ConfigManager</span><span class="p">:</span> <span class="c1"># Inicializa e recupera variáveis em ambiente de intercâmbio entre classes</span>
<span class="w"> </span><span class="sd">"""</span>
<span class="sd"> Como Funciona</span>
<span class="sd"> Singleton Pattern: ConfigManager é um singleton que garante que todas as partes do código usem a mesma instância e, portanto, compartilhem a mesma configuração.</span>
<span class="sd"> Inicialização com Argumentos Dinâmicos: O método initialize usa **kwargs para aceitar qualquer número de pares chave-valor, armazenando-os no dicionário _config da instância.</span>
<span class="sd"> Método Genérico get: O método get aceita uma chave como argumento e retorna o valor correspondente do dicionário _config.</span>
<span class="sd"> Método set: O método set permite adicionar ou atualizar dinamicamente valores no dicionário _config.</span>
<span class="sd"> Método reset: O método reset limpa todas as configurações armazenadas, permitindo uma nova inicialização do ConfigManager com novos valores </span>
<span class="sd"> """</span>
<span class="n">_instance</span> <span class="o">=</span> <span class="kc">None</span>
<span class="k">def</span> <span class="fm">__new__</span><span class="p">(</span><span class="bp">cls</span><span class="p">):</span>
<span class="k">if</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_instance</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="bp">cls</span><span class="o">.</span><span class="n">_instance</span> <span class="o">=</span> <span class="nb">super</span><span class="p">(</span><span class="n">ConfigManager</span><span class="p">,</span> <span class="bp">cls</span><span class="p">)</span><span class="o">.</span><span class="fm">__new__</span><span class="p">(</span><span class="bp">cls</span><span class="p">)</span>
<span class="bp">cls</span><span class="o">.</span><span class="n">_instance</span><span class="o">.</span><span class="n">_config</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">return</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_instance</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="nd">@classmethod</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="n">instance</span> <span class="o">=</span> <span class="bp">cls</span><span class="p">()</span>
<span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
<span class="n">instance</span><span class="o">.</span><span class="n">_config</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="nd">@classmethod</span>
<span class="k">def</span> <span class="nf">get</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_instance</span><span class="o">.</span><span class="n">_config</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="nd">@classmethod</span>
<span class="k">def</span> <span class="nf">set</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
<span class="bp">cls</span><span class="o">.</span><span class="n">_instance</span><span class="o">.</span><span class="n">_config</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="nd">@classmethod</span>
<span class="k">def</span> <span class="nf">reset</span><span class="p">(</span><span class="bp">cls</span><span class="p">):</span>
<span class="bp">cls</span><span class="o">.</span><span class="n">_instance</span><span class="o">.</span><span class="n">_config</span> <span class="o">=</span> <span class="p">{}</span>
</code></pre></div></td></tr></table></div>
</details>
<div class="doc doc-children">
</div>
</div>
</div>
<div class="doc doc-object doc-class">
<h2 id="lbxtoolkit.Servicer" class="doc doc-heading">
<code>Servicer</code>
</h2>
<div class="doc doc-contents ">
<p>Classe base que implementa as rotinas padrão para a criação dameons/serviços do windows.
Além de iniciar e interromper o daemon/serviço, a classe implementar os métodos daemon_logs() e cleanup(), dependencias de run() e stop() que criam um arquivo de log do serviço/daemon (não do script em si) e um arquivo PID para o monitor de serviços.
Os métodos padrão são init(), run() e stop() e não devem ser redefinidos/sobrecarregados.
Para ser funcional, é necessária a criação de uma classe local que herde essa classe e redefina (por sobrecarga) ao menos os métodos on_run, on_start e args_parser(). on_init é opcional.
Outros métodos complementares são oferidos para init, run e stop, permitindo injetar código no ínicio (pre) e fim (pós) os respectivos métodos (on_init_pre(), on_init_pos(), on_run_pre(), on_run_pos(), on_stop_pre(), on_stop_pos())</p>
<details class="quote">
<summary>Source code in <code>lbxtoolkit\__init__.py</code></summary>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">1377</span>
<span class="normal">1378</span>
<span class="normal">1379</span>
<span class="normal">1380</span>
<span class="normal">1381</span>
<span class="normal">1382</span>
<span class="normal">1383</span>
<span class="normal">1384</span>
<span class="normal">1385</span>
<span class="normal">1386</span>
<span class="normal">1387</span>
<span class="normal">1388</span>
<span class="normal">1389</span>
<span class="normal">1390</span>
<span class="normal">1391</span>
<span class="normal">1392</span>
<span class="normal">1393</span>
<span class="normal">1394</span>
<span class="normal">1395</span>
<span class="normal">1396</span>
<span class="normal">1397</span>
<span class="normal">1398</span>
<span class="normal">1399</span>
<span class="normal">1400</span>
<span class="normal">1401</span>
<span class="normal">1402</span>
<span class="normal">1403</span>
<span class="normal">1404</span>
<span class="normal">1405</span>
<span class="normal">1406</span>
<span class="normal">1407</span>
<span class="normal">1408</span>
<span class="normal">1409</span>
<span class="normal">1410</span>
<span class="normal">1411</span>
<span class="normal">1412</span>
<span class="normal">1413</span>
<span class="normal">1414</span>
<span class="normal">1415</span>
<span class="normal">1416</span>
<span class="normal">1417</span>
<span class="normal">1418</span>
<span class="normal">1419</span>
<span class="normal">1420</span>
<span class="normal">1421</span>
<span class="normal">1422</span>
<span class="normal">1423</span>
<span class="normal">1424</span>
<span class="normal">1425</span>
<span class="normal">1426</span>
<span class="normal">1427</span>
<span class="normal">1428</span>
<span class="normal">1429</span>
<span class="normal">1430</span>
<span class="normal">1431</span>
<span class="normal">1432</span>
<span class="normal">1433</span>
<span class="normal">1434</span>
<span class="normal">1435</span>
<span class="normal">1436</span>
<span class="normal">1437</span>
<span class="normal">1438</span>
<span class="normal">1439</span>
<span class="normal">1440</span>
<span class="normal">1441</span>
<span class="normal">1442</span>
<span class="normal">1443</span>
<span class="normal">1444</span>
<span class="normal">1445</span>
<span class="normal">1446</span>
<span class="normal">1447</span>
<span class="normal">1448</span>
<span class="normal">1449</span>
<span class="normal">1450</span>
<span class="normal">1451</span>
<span class="normal">1452</span>
<span class="normal">1453</span>
<span class="normal">1454</span>
<span class="normal">1455</span>
<span class="normal">1456</span>
<span class="normal">1457</span>
<span class="normal">1458</span>
<span class="normal">1459</span>
<span class="normal">1460</span>
<span class="normal">1461</span>
<span class="normal">1462</span>
<span class="normal">1463</span>
<span class="normal">1464</span>
<span class="normal">1465</span>
<span class="normal">1466</span>
<span class="normal">1467</span>
<span class="normal">1468</span>
<span class="normal">1469</span>
<span class="normal">1470</span>
<span class="normal">1471</span>
<span class="normal">1472</span>
<span class="normal">1473</span>
<span class="normal">1474</span>
<span class="normal">1475</span>
<span class="normal">1476</span>
<span class="normal">1477</span>
<span class="normal">1478</span>
<span class="normal">1479</span>
<span class="normal">1480</span>
<span class="normal">1481</span>
<span class="normal">1482</span>
<span class="normal">1483</span>
<span class="normal">1484</span>
<span class="normal">1485</span>
<span class="normal">1486</span>
<span class="normal">1487</span>
<span class="normal">1488</span>
<span class="normal">1489</span>
<span class="normal">1490</span>
<span class="normal">1491</span>
<span class="normal">1492</span>
<span class="normal">1493</span>
<span class="normal">1494</span>
<span class="normal">1495</span>
<span class="normal">1496</span>
<span class="normal">1497</span>
<span class="normal">1498</span>
<span class="normal">1499</span>
<span class="normal">1500</span>
<span class="normal">1501</span>
<span class="normal">1502</span>
<span class="normal">1503</span>
<span class="normal">1504</span>
<span class="normal">1505</span>
<span class="normal">1506</span>
<span class="normal">1507</span>
<span class="normal">1508</span>
<span class="normal">1509</span>
<span class="normal">1510</span>
<span class="normal">1511</span>
<span class="normal">1512</span>
<span class="normal">1513</span>
<span class="normal">1514</span>
<span class="normal">1515</span>
<span class="normal">1516</span>
<span class="normal">1517</span>
<span class="normal">1518</span>
<span class="normal">1519</span>
<span class="normal">1520</span>
<span class="normal">1521</span>
<span class="normal">1522</span>
<span class="normal">1523</span>
<span class="normal">1524</span>
<span class="normal">1525</span>
<span class="normal">1526</span>
<span class="normal">1527</span>
<span class="normal">1528</span>
<span class="normal">1529</span>
<span class="normal">1530</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">class</span> <span class="nc">Servicer</span><span class="p">():</span> <span class="c1"># Cria um daemon para rodar como serviço</span>
<span class="w"> </span><span class="sd">"""</span>
<span class="sd"> Classe base que implementa as rotinas padrão para a criação dameons/serviços do windows.</span>
<span class="sd"> Além de iniciar e interromper o daemon/serviço, a classe implementar os métodos daemon_logs() e cleanup(), dependencias de run() e stop() que criam um arquivo de log do serviço/daemon (não do script em si) e um arquivo PID para o monitor de serviços.</span>
<span class="sd"> Os métodos padrão são init(), run() e stop() e não devem ser redefinidos/sobrecarregados.</span>
<span class="sd"> Para ser funcional, é necessária a criação de uma classe local que herde essa classe e redefina (por sobrecarga) ao menos os métodos on_run, on_start e args_parser(). on_init é opcional.</span>
<span class="sd"> Outros métodos complementares são oferidos para init, run e stop, permitindo injetar código no ínicio (pre) e fim (pós) os respectivos métodos (on_init_pre(), on_init_pos(), on_run_pre(), on_run_pos(), on_stop_pre(), on_stop_pos())</span>
<span class="sd"> """</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">Log</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">piddir</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span><span class="c1">#TODO: ao criar uma classe padrão usar args/kwargs para lidar como parametros variáveis no instanciamento</span>
<span class="c1"># PRE-REQUISITOS/DEPENDÊNCIAS: </span>
<span class="bp">self</span><span class="o">.</span><span class="n">log</span> <span class="o">=</span> <span class="n">ConfigManager</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'log'</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">kwargs</span> <span class="o">=</span> <span class="n">ConfigManager</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'argparse_cfg'</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">kwopts</span> <span class="o">=</span> <span class="n">ConfigManager</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'argparse_opt'</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">ambiente</span> <span class="o">=</span> <span class="n">ConfigManager</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'ambiente'</span><span class="p">)</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">log</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="p">,</span> <span class="n">lbx_logger</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Argumento "log" é mandatório e deve ser uma instância de "lbxtoolkit.lbx_logger"'</span><span class="p">)</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">kwargs</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Argumento "argparse_cfg" é mandatório e deve ser um dicionário com ao mínimo as chaves: [description, usage, usage, add_help, formatter_class] para configuração do módulo argpase'</span><span class="p">)</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">kwopts</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Argumento "argparse_opt" é mandatório e deve ser uma lista de dicionários ao mínimo as chaves: [short, long, action, help] para tratamento dos argumentos recebidos da linha de comando'</span><span class="p">)</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">ambiente</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">ambiente</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="s1">'Linux'</span><span class="p">,</span> <span class="s1">'Windows'</span><span class="p">,</span> <span class="s1">'Serviço'</span><span class="p">]:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Argumento "ambiente" é mandatório e deve ser uma string com um dos seguintes valores: [Linux, Windows, Serviço]'</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_init_pre</span><span class="p">()</span> <span class="c1">## método opcional a ser definito por sobrecarga na função local</span>
<span class="c1"># Argumentos padrão obrigatórios </span>
<span class="bp">self</span><span class="o">.</span><span class="n">LogFile</span> <span class="o">=</span> <span class="n">Path</span><span class="p">(</span><span class="s1">'.'</span><span class="p">,</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">splitext</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">basename</span><span class="p">(</span><span class="vm">__file__</span><span class="p">))[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'.daemon'</span><span class="p">)</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">Log</span> <span class="k">else</span> <span class="n">Log</span>
<span class="bp">self</span><span class="o">.</span><span class="n">OS</span> <span class="o">=</span> <span class="n">platform</span><span class="o">.</span><span class="n">system</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">PID</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">getppid</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">IP</span> <span class="o">=</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostbyname</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">())</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Host</span> <span class="o">=</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Usuario</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">getlogin</span><span class="p">()</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">OS</span> <span class="o">==</span> <span class="s1">'Windows'</span> <span class="k">else</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">expanduser</span><span class="p">(</span><span class="s1">'~'</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="sa">r</span><span class="s1">'/'</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Me</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">abspath</span><span class="p">(</span><span class="vm">__file__</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">PIDDir</span> <span class="o">=</span> <span class="n">Path</span><span class="p">(</span><span class="s1">'.'</span><span class="p">)</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">piddir</span> <span class="k">else</span> <span class="n">piddir</span>
<span class="bp">self</span><span class="o">.</span><span class="n">PIDFile</span> <span class="o">=</span> <span class="n">Path</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">PIDDir</span><span class="p">,</span><span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">PID</span><span class="p">))</span>
<span class="bp">self</span><span class="o">.</span><span class="n">exit</span> <span class="o">=</span> <span class="kc">False</span>
<span class="bp">self</span><span class="o">.</span><span class="n">mode</span> <span class="o">=</span> <span class="s1">'[DAEMON (console)]'</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_init</span><span class="p">()</span> <span class="c1">## método opcional a ser definito por sobrecarga na função local</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_init_pos</span><span class="p">()</span> <span class="c1">## método opcional a ser definito por sobrecarga na função local </span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="c1">#kwargs = ConfigManager.get('argparse_cfg')</span>
<span class="c1">#kwopts = ConfigManager.get('argparse_opt') </span>
<span class="c1">#ambiente = ConfigManager.get('ambiente') </span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">ambiente</span> <span class="o">==</span> <span class="s1">'Serviço'</span><span class="p">:</span> <span class="c1">## VEM DAQUI https://gist.github.com/drmalex07/10554232?permalink_comment_id=2555358#gistcomment-2555358 </span>
<span class="n">servicemanager</span><span class="o">.</span><span class="n">Initialize</span><span class="p">()</span>
<span class="n">servicemanager</span><span class="o">.</span><span class="n">PrepareToHostSingle</span><span class="p">(</span><span class="n">ServicoWindows</span><span class="p">)</span>
<span class="n">servicemanager</span><span class="o">.</span><span class="n">StartServiceCtrlDispatcher</span><span class="p">()</span>
<span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span> <span class="o">></span> <span class="mi">1</span> <span class="ow">and</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'install'</span><span class="p">:</span>
<span class="n">ServicoWindows</span><span class="o">.</span><span class="n">SvcInstall</span><span class="p">()</span>
<span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span> <span class="o">></span> <span class="mi">1</span> <span class="ow">and</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'remove'</span><span class="p">:</span>
<span class="n">ServicoWindows</span><span class="o">.</span><span class="n">SvcRemove</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span> <span class="o">></span> <span class="mi">1</span> <span class="ow">and</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="ow">in</span> <span class="p">[</span><span class="s1">'start'</span><span class="p">,</span> <span class="s1">'stop'</span><span class="p">,</span> <span class="s1">'restart'</span><span class="p">,</span> <span class="s1">'debug'</span><span class="p">]:</span>
<span class="n">win32serviceutil</span><span class="o">.</span><span class="n">HandleCommandLine</span><span class="p">(</span><span class="n">ServicoWindows</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">parser</span> <span class="o">=</span> <span class="n">argparse</span><span class="o">.</span><span class="n">ArgumentParser</span><span class="p">(</span><span class="o">**</span><span class="bp">self</span><span class="o">.</span><span class="n">kwargs</span><span class="p">)</span>
<span class="k">for</span> <span class="n">opt</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">kwopts</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="n">opt</span><span class="p">[</span><span class="s1">'short'</span><span class="p">],</span> <span class="n">opt</span><span class="p">[</span><span class="s1">'long'</span><span class="p">],</span> <span class="n">action</span><span class="o">=</span><span class="n">opt</span><span class="p">[</span><span class="s1">'action'</span><span class="p">],</span> <span class="n">help</span><span class="o">=</span><span class="n">opt</span><span class="p">[</span><span class="s1">'help'</span><span class="p">])</span>
<span class="bp">self</span><span class="o">.</span><span class="n">args</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">parser</span><span class="o">.</span><span class="n">parse_args</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">args_paser</span><span class="p">()</span> <span class="c1">## tratamento dos arguemntos deve ser redefindo por sobrecarga no na função local</span>
<span class="c1">#</span>
<span class="c1"># </span>
<span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">"""Inicia a execução do do serviço"""</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_run_pre</span><span class="p">()</span> <span class="c1">## método opcional a ser definito por sobrecarga na função local </span>
<span class="bp">self</span><span class="o">.</span><span class="n">daemon_log</span><span class="p">(</span><span class="s1">'START'</span><span class="p">)</span>
<span class="c1">## Gera o PIDFile</span>
<span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Iniciando daemon [PID: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">PID</span><span class="si">}</span><span class="s1">] para monitorar os processos que rodam como serviço/daemon monitorados em: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">PIDDir</span><span class="si">}</span><span class="s1">... '</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">PIDFile</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s1">'utf-8'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">Me</span> <span class="o">+</span> <span class="s1">';'</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">LogFile</span><span class="p">))</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">Err</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">stop</span><span class="p">(</span><span class="s1">'CRASH'</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">erro</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Erro [</span><span class="si">{</span><span class="n">Err</span><span class="si">}</span><span class="s1">] ao salvar PIDFile: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">PIDFile</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Ok!'</span><span class="p">)</span> <span class="c1">## trocar para debug em prd ??</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_run</span><span class="p">()</span> <span class="c1"># função principal para interreper o daemon/serviço, definir localmente por sobrecarga (criar classe que herde essa classe e defina essa função) </span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_run_pos</span><span class="p">()</span> <span class="c1">## método opcional a ser definito por sobrecarga na função local </span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">stop</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">evento</span><span class="o">=</span><span class="s1">'STOP'</span><span class="p">):</span>
<span class="w"> </span><span class="sd">"""Interrompe o daemon/serviço"""</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_stop_pre</span><span class="p">()</span> <span class="c1">## método opcional a ser definito por sobrecarga na função local </span>
<span class="bp">self</span><span class="o">.</span><span class="n">daemon_log</span><span class="p">(</span><span class="n">evento</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_stop</span><span class="p">()</span> <span class="c1"># função principal para interreper o daemon/serviço, definir localmente por sobrecarga (criar classe que herde essa classe e defina essa função)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">cleanup</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">exit</span><span class="o">=</span><span class="kc">True</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_stop_pos</span><span class="p">()</span> <span class="c1">## método opcional a ser definito por sobrecarga na função local </span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">cleanup</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="c1">## Elimina o arquivo PID do processo se estiver rodando como daemon</span>
<span class="w"> </span><span class="sd">"""Método auxiliar utilizado no stop() para limpar o o PID file na interrupção"""</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_cleanup_pre</span><span class="p">()</span> <span class="c1">## método opcional a ser definito por sobrecarga na função local </span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">PIDFile</span><span class="p">:</span> <span class="c1">## verifica se está rodando como daemon</span>
<span class="k">if</span> <span class="n">Path</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">PIDFile</span><span class="p">)</span><span class="o">.</span><span class="n">exists</span><span class="p">():</span>
<span class="n">Path</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">PIDFile</span><span class="p">)</span><span class="o">.</span><span class="n">unlink</span><span class="p">()</span> <span class="c1">##exclui o pidfile do daemon se o arquivo existir </span>
<span class="bp">self</span><span class="o">.</span><span class="n">PIDFile</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_cleanup_pos</span><span class="p">()</span> <span class="c1">## método opcional a ser definito por sobrecarga na função local </span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">daemon_log</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">evento</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span> <span class="c1">## Gerar log de início/interrupção do serviço</span>
<span class="w"> </span><span class="sd">"""Método auxiliar utilizado alimentar log do histórico de inicialização/interrupção do serviço/daemon"""</span>
<span class="n">evento</span> <span class="o">=</span> <span class="s1">'CHECK'</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">evento</span> <span class="k">else</span> <span class="n">evento</span>
<span class="n">evento</span> <span class="o">=</span> <span class="n">evento</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span>
<span class="n">TimeStamp</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1"> %H:%M:%S'</span><span class="p">)</span>
<span class="n">Message</span> <span class="o">=</span> <span class="sa">f</span><span class="s1">'</span><span class="si">{</span><span class="n">TimeStamp</span><span class="si">}</span><span class="s1"> - </span><span class="si">{</span><span class="n">evento</span><span class="si">}</span><span class="s1"> - </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">OS</span><span class="si">}</span><span class="s1"> - </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">Host</span><span class="si">}</span><span class="s1">/</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">IP</span><span class="si">}</span><span class="s1"> - PID: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">PID</span><span class="si">}</span><span class="s1"> - </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">Usuario</span><span class="si">}</span><span class="s1"> - </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">Me</span><span class="si">}</span><span class="s1">'</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">LogFile</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
<span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">Message</span> <span class="o">+</span> <span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">Err</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">erro</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Erro [</span><span class="si">{</span><span class="n">Err</span><span class="si">}</span><span class="s1">] ao gravar status do daemon em </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">LogFile</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">on_init_pre</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">on_init_pos</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">on_init</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">on_cleanup_pre</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">on_cleanup_pos</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">on_cleanup</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">on_run_pre</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">on_run_pos</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">on_run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">on_stop_pre</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">on_stop_pos</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">on_stop</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">args_paser</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">pass</span>
</code></pre></div></td></tr></table></div>
</details>
<div class="doc doc-children">
<div class="doc doc-object doc-function">
<h3 id="lbxtoolkit.Servicer.cleanup" class="doc doc-heading">
<code class="highlight language-python"><span class="n">cleanup</span><span class="p">()</span></code>
</h3>
<div class="doc doc-contents ">
<p>Método auxiliar utilizado no stop() para limpar o o PID file na interrupção</p>
<details class="quote">
<summary>Source code in <code>lbxtoolkit\__init__.py</code></summary>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">1478</span>
<span class="normal">1479</span>
<span class="normal">1480</span>
<span class="normal">1481</span>
<span class="normal">1482</span>
<span class="normal">1483</span>
<span class="normal">1484</span>
<span class="normal">1485</span>
<span class="normal">1486</span>
<span class="normal">1487</span>
<span class="normal">1488</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="nf">cleanup</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="c1">## Elimina o arquivo PID do processo se estiver rodando como daemon</span>
<span class="w"> </span><span class="sd">"""Método auxiliar utilizado no stop() para limpar o o PID file na interrupção"""</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_cleanup_pre</span><span class="p">()</span> <span class="c1">## método opcional a ser definito por sobrecarga na função local </span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">PIDFile</span><span class="p">:</span> <span class="c1">## verifica se está rodando como daemon</span>
<span class="k">if</span> <span class="n">Path</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">PIDFile</span><span class="p">)</span><span class="o">.</span><span class="n">exists</span><span class="p">():</span>
<span class="n">Path</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">PIDFile</span><span class="p">)</span><span class="o">.</span><span class="n">unlink</span><span class="p">()</span> <span class="c1">##exclui o pidfile do daemon se o arquivo existir </span>
<span class="bp">self</span><span class="o">.</span><span class="n">PIDFile</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_cleanup_pos</span><span class="p">()</span> <span class="c1">## método opcional a ser definito por sobrecarga na função local </span>
</code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="lbxtoolkit.Servicer.daemon_log" class="doc doc-heading">
<code class="highlight language-python"><span class="n">daemon_log</span><span class="p">(</span><span class="n">evento</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span></code>
</h3>
<div class="doc doc-contents ">
<p>Método auxiliar utilizado alimentar log do histórico de inicialização/interrupção do serviço/daemon</p>
<details class="quote">
<summary>Source code in <code>lbxtoolkit\__init__.py</code></summary>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">1491</span>
<span class="normal">1492</span>
<span class="normal">1493</span>
<span class="normal">1494</span>
<span class="normal">1495</span>
<span class="normal">1496</span>
<span class="normal">1497</span>
<span class="normal">1498</span>
<span class="normal">1499</span>
<span class="normal">1500</span>
<span class="normal">1501</span>
<span class="normal">1502</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="nf">daemon_log</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">evento</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span> <span class="c1">## Gerar log de início/interrupção do serviço</span>
<span class="w"> </span><span class="sd">"""Método auxiliar utilizado alimentar log do histórico de inicialização/interrupção do serviço/daemon"""</span>
<span class="n">evento</span> <span class="o">=</span> <span class="s1">'CHECK'</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">evento</span> <span class="k">else</span> <span class="n">evento</span>
<span class="n">evento</span> <span class="o">=</span> <span class="n">evento</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span>
<span class="n">TimeStamp</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1"> %H:%M:%S'</span><span class="p">)</span>
<span class="n">Message</span> <span class="o">=</span> <span class="sa">f</span><span class="s1">'</span><span class="si">{</span><span class="n">TimeStamp</span><span class="si">}</span><span class="s1"> - </span><span class="si">{</span><span class="n">evento</span><span class="si">}</span><span class="s1"> - </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">OS</span><span class="si">}</span><span class="s1"> - </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">Host</span><span class="si">}</span><span class="s1">/</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">IP</span><span class="si">}</span><span class="s1"> - PID: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">PID</span><span class="si">}</span><span class="s1"> - </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">Usuario</span><span class="si">}</span><span class="s1"> - </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">Me</span><span class="si">}</span><span class="s1">'</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">LogFile</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
<span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">Message</span> <span class="o">+</span> <span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">Err</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">erro</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Erro [</span><span class="si">{</span><span class="n">Err</span><span class="si">}</span><span class="s1">] ao gravar status do daemon em </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">LogFile</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
</code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="lbxtoolkit.Servicer.run" class="doc doc-heading">
<code class="highlight language-python"><span class="n">run</span><span class="p">()</span></code>
</h3>
<div class="doc doc-contents ">
<p>Inicia a execução do do serviço</p>
<details class="quote">
<summary>Source code in <code>lbxtoolkit\__init__.py</code></summary>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">1444</span>
<span class="normal">1445</span>
<span class="normal">1446</span>
<span class="normal">1447</span>
<span class="normal">1448</span>
<span class="normal">1449</span>
<span class="normal">1450</span>
<span class="normal">1451</span>
<span class="normal">1452</span>
<span class="normal">1453</span>
<span class="normal">1454</span>
<span class="normal">1455</span>
<span class="normal">1456</span>
<span class="normal">1457</span>
<span class="normal">1458</span>
<span class="normal">1459</span>
<span class="normal">1460</span>
<span class="normal">1461</span>
<span class="normal">1462</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">"""Inicia a execução do do serviço"""</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_run_pre</span><span class="p">()</span> <span class="c1">## método opcional a ser definito por sobrecarga na função local </span>
<span class="bp">self</span><span class="o">.</span><span class="n">daemon_log</span><span class="p">(</span><span class="s1">'START'</span><span class="p">)</span>
<span class="c1">## Gera o PIDFile</span>
<span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Iniciando daemon [PID: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">PID</span><span class="si">}</span><span class="s1">] para monitorar os processos que rodam como serviço/daemon monitorados em: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">PIDDir</span><span class="si">}</span><span class="s1">... '</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">PIDFile</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s1">'utf-8'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">Me</span> <span class="o">+</span> <span class="s1">';'</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">LogFile</span><span class="p">))</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">Err</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">stop</span><span class="p">(</span><span class="s1">'CRASH'</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">erro</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Erro [</span><span class="si">{</span><span class="n">Err</span><span class="si">}</span><span class="s1">] ao salvar PIDFile: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">PIDFile</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Ok!'</span><span class="p">)</span> <span class="c1">## trocar para debug em prd ??</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_run</span><span class="p">()</span> <span class="c1"># função principal para interreper o daemon/serviço, definir localmente por sobrecarga (criar classe que herde essa classe e defina essa função) </span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_run_pos</span><span class="p">()</span> <span class="c1">## método opcional a ser definito por sobrecarga na função local </span>
</code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="lbxtoolkit.Servicer.stop" class="doc doc-heading">
<code class="highlight language-python"><span class="n">stop</span><span class="p">(</span><span class="n">evento</span><span class="o">=</span><span class="s1">'STOP'</span><span class="p">)</span></code>
</h3>
<div class="doc doc-contents ">
<p>Interrompe o daemon/serviço</p>
<details class="quote">
<summary>Source code in <code>lbxtoolkit\__init__.py</code></summary>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">1465</span>
<span class="normal">1466</span>
<span class="normal">1467</span>
<span class="normal">1468</span>
<span class="normal">1469</span>
<span class="normal">1470</span>
<span class="normal">1471</span>
<span class="normal">1472</span>
<span class="normal">1473</span>
<span class="normal">1474</span>
<span class="normal">1475</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="nf">stop</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">evento</span><span class="o">=</span><span class="s1">'STOP'</span><span class="p">):</span>
<span class="w"> </span><span class="sd">"""Interrompe o daemon/serviço"""</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_stop_pre</span><span class="p">()</span> <span class="c1">## método opcional a ser definito por sobrecarga na função local </span>
<span class="bp">self</span><span class="o">.</span><span class="n">daemon_log</span><span class="p">(</span><span class="n">evento</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_stop</span><span class="p">()</span> <span class="c1"># função principal para interreper o daemon/serviço, definir localmente por sobrecarga (criar classe que herde essa classe e defina essa função)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">cleanup</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">exit</span><span class="o">=</span><span class="kc">True</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_stop_pos</span><span class="p">()</span> <span class="c1">## método opcional a ser definito por sobrecarga na função local </span>
</code></pre></div></td></tr></table></div>
</details>
</div>
</div>
</div>
</div>
</div>
<div class="doc doc-object doc-class">
<h2 id="lbxtoolkit.api_rest" class="doc doc-heading">
<code>api_rest</code>
</h2>
<div class="doc doc-contents ">
<h6 id="lbxtoolkit.api_rest--classe-api_rest">Classe <strong>api_rest</strong></h6>
<p>Destina-se a interatir com APIs RESTfull, em especial as publicadas pela SoftPlan para a <a href="https://api.sienge.com.br/docs/">Plataforma Sienge</a>.</p>
<p>A classe deve ser instanciada conforme sintaxe abaixo:</p>
<p><code>api_rest(url, credenciais, cadencia, timeout=6, logger=None, headers={"Content-Type": "application/json"}, verify=True)</code></p>
<p>São nessários 2 parâmetros posicionais obrigatórios, e 5 parametros nominais facultativos (valor padrão, se omisso, indicado na sintaxe acima):
- <code>url</code>: o endereço da URL de autenticação da API
- <code>crednciais</code>: Dicionário com credenciais de autenticação.
- <code>cadencia</code> Número máximo de chamadas <em>por segudo</em> à API
- <code>timeout</code> Tempo máximo (segundos) para aguardar retorno à chamada. Padrão 6s, se omisso.
- <code>logger</code> O objeto <em>log handler</em> para lidar com as informações de saída. Se não informado, todas as saídas serão direcionadas para a stdout.
- <code>headers</code> Cabeçalhos <em>http</em> para a requisição à API.
- <code>verify</code> Verifica a validade do certificado SSL do servidor de destino da requisição.</p>
<p>Quanto às credenciais de autenticação, assim como a classe de interação com o PostgreSQL, elas precisam ser fornecidas na forma de um <em>dicionário</em>.
Para o método <code>api_rest.aut_basic()</code>, o formato deve ser: </p>
<pre><code>credenciais = {
'user': 'USUARIO_API',
'password': 'TOKEN_USUARIO'
}
</code></pre>
<p>Caso a autenticação seja pelo método <code>api_rest.aut_bearer()</code>, o dicionário deve corresponder ao formato previsto pelo endpoint e seu conteúdo será enviado como um JSON ao endereço indicado no parametro <code>url</code></p>
<p>A classe possui 3 métodos:
- <code>api_rest.auth_basic()</code>: instanciamento da sessão autenticando pelo método HTTPBasicAuth
- <code>api_rest.auth_bearer()</code>: instanciamento da sessão autenticando pelos métodos OAuth, JWT, Bearer <br />
- <code>api_rest.endpoint_json([endereço], [método], payload=None)</code>: para a chamada ao endpoint
- <code>close()</code> para encerra a instância/sessão</p>
<p>O consumo é feito pelo método <code>api_rest.endpoint_json</code> que suporta apenas APIs cujo payload (opcional) seja aceito no formato JSON. </p>
<p>Esse método espera 2 parametros posicionais obrigatórios: o endereço do endpoint e o verbo (get, post, patch ou put), tendo parametro opcional o objeto de 'payload' (json).
Note que o endereço do endpoint deve ser informado completo. A URL informada no instanciamento da classe corresponde apenas ao endereço de autenticação. </p>
<p>O tempo, em segundos, transcorrido entre a chamada a atual e a chamada anterior ao endpoint pode ser consultado pelo argumento <code>.Intervalo</code> no objeto recebido do retorno à chamada ao método <code>.endpoint_json</code>. </p>
<p>Da mesma forma, o tempo de espera imposto para respeitar a cadência do webservcie também pode ser consultado pelo argumento <code>.Espera</code>.</p>
<p>Exemplo de uso:</p>
<pre><code>from lbx_toolkit import api_rest
UrlBase=r'https://api.sienge.com.br/lbx/public/api/v1'
Credenciais = {
'user': 'USUARIO_API',
'password': 'TOKEN_USUARIO'
}
ApiSienge = api_rest(UrlBase,Credenciais,2.5) # limite de 2 requisições/segundo para cadência de chamada ao endpoint
Auth = ApiSienge.auth_basic()
Nutitulo=input('Numero do título:')
Nuparcela=input('Numero da parcela:')
Vencimento=input('Vencimento [AAAA-MM-DD]:')
Payload = {
"dueDate": f"{Vencimento}"
}
EndPoint = f'{UrlBase}/bills/{Nutitulo}/installments/{Nuparcela}'
#chama o endpoint e recebe o retorno no objeto AlteraVcto
AlteraVcto = ApiSienge.endpoint_json(EndPoint, 'patch', Payload)
</code></pre>
<p>No exemplo acima não é esperado que o endpoint retorne nenhum dado (<code>patch</code>).</p>
<p>Quando se usa o verbo <code>get</code> e se espera o retorno de algum dado, use o método <code>.json</code> do pacote <code>request</code> para acessar o objeto recebido.</p>
<p>Para uso em APIs com autenticação JWT (JSON Web Token), OAuth, Bearer Token Authentication, a construção é a mesma indicada acima, bastando-se usar <code>.auth_bearer()</code> ao invés de <em>.auth_basic()</em>, e ajustar o dicionário <code>credenciais</code> informado no instanciamento da classe, que deve ser estruturado conforme o padrão fornecido peo mantendor da API e será enviado como payload ao endpoint (<code>json=credenciais</code>).</p>
<details class="quote">
<summary>Source code in <code>lbxtoolkit\__init__.py</code></summary>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">709</span>
<span class="normal">710</span>
<span class="normal">711</span>
<span class="normal">712</span>
<span class="normal">713</span>
<span class="normal">714</span>
<span class="normal">715</span>
<span class="normal">716</span>
<span class="normal">717</span>
<span class="normal">718</span>
<span class="normal">719</span>
<span class="normal">720</span>
<span class="normal">721</span>
<span class="normal">722</span>
<span class="normal">723</span>
<span class="normal">724</span>
<span class="normal">725</span>
<span class="normal">726</span>
<span class="normal">727</span>
<span class="normal">728</span>
<span class="normal">729</span>
<span class="normal">730</span>
<span class="normal">731</span>
<span class="normal">732</span>
<span class="normal">733</span>
<span class="normal">734</span>
<span class="normal">735</span>
<span class="normal">736</span>
<span class="normal">737</span>
<span class="normal">738</span>
<span class="normal">739</span>
<span class="normal">740</span>
<span class="normal">741</span>
<span class="normal">742</span>
<span class="normal">743</span>
<span class="normal">744</span>
<span class="normal">745</span>
<span class="normal">746</span>
<span class="normal">747</span>
<span class="normal">748</span>
<span class="normal">749</span>
<span class="normal">750</span>
<span class="normal">751</span>
<span class="normal">752</span>
<span class="normal">753</span>
<span class="normal">754</span>
<span class="normal">755</span>
<span class="normal">756</span>
<span class="normal">757</span>
<span class="normal">758</span>
<span class="normal">759</span>
<span class="normal">760</span>
<span class="normal">761</span>
<span class="normal">762</span>
<span class="normal">763</span>
<span class="normal">764</span>
<span class="normal">765</span>
<span class="normal">766</span>
<span class="normal">767</span>
<span class="normal">768</span>
<span class="normal">769</span>
<span class="normal">770</span>
<span class="normal">771</span>
<span class="normal">772</span>
<span class="normal">773</span>
<span class="normal">774</span>
<span class="normal">775</span>
<span class="normal">776</span>
<span class="normal">777</span>
<span class="normal">778</span>
<span class="normal">779</span>
<span class="normal">780</span>
<span class="normal">781</span>
<span class="normal">782</span>
<span class="normal">783</span>
<span class="normal">784</span>
<span class="normal">785</span>
<span class="normal">786</span>
<span class="normal">787</span>
<span class="normal">788</span>
<span class="normal">789</span>
<span class="normal">790</span>
<span class="normal">791</span>
<span class="normal">792</span>
<span class="normal">793</span>
<span class="normal">794</span>
<span class="normal">795</span>
<span class="normal">796</span>
<span class="normal">797</span>
<span class="normal">798</span>
<span class="normal">799</span>
<span class="normal">800</span>
<span class="normal">801</span>
<span class="normal">802</span>
<span class="normal">803</span>
<span class="normal">804</span>
<span class="normal">805</span>
<span class="normal">806</span>
<span class="normal">807</span>
<span class="normal">808</span>
<span class="normal">809</span>
<span class="normal">810</span>
<span class="normal">811</span>
<span class="normal">812</span>
<span class="normal">813</span>
<span class="normal">814</span>
<span class="normal">815</span>
<span class="normal">816</span>
<span class="normal">817</span>
<span class="normal">818</span>
<span class="normal">819</span>
<span class="normal">820</span>
<span class="normal">821</span>
<span class="normal">822</span>
<span class="normal">823</span>
<span class="normal">824</span>
<span class="normal">825</span>
<span class="normal">826</span>
<span class="normal">827</span>
<span class="normal">828</span>
<span class="normal">829</span>
<span class="normal">830</span>
<span class="normal">831</span>
<span class="normal">832</span>
<span class="normal">833</span>
<span class="normal">834</span>
<span class="normal">835</span>
<span class="normal">836</span>
<span class="normal">837</span>
<span class="normal">838</span>
<span class="normal">839</span>
<span class="normal">840</span>
<span class="normal">841</span>
<span class="normal">842</span>
<span class="normal">843</span>
<span class="normal">844</span>
<span class="normal">845</span>
<span class="normal">846</span>
<span class="normal">847</span>
<span class="normal">848</span>
<span class="normal">849</span>
<span class="normal">850</span>
<span class="normal">851</span>
<span class="normal">852</span>
<span class="normal">853</span>
<span class="normal">854</span>
<span class="normal">855</span>
<span class="normal">856</span>
<span class="normal">857</span>
<span class="normal">858</span>
<span class="normal">859</span>
<span class="normal">860</span>
<span class="normal">861</span>
<span class="normal">862</span>
<span class="normal">863</span>
<span class="normal">864</span>
<span class="normal">865</span>
<span class="normal">866</span>
<span class="normal">867</span>
<span class="normal">868</span>
<span class="normal">869</span>
<span class="normal">870</span>
<span class="normal">871</span>
<span class="normal">872</span>
<span class="normal">873</span>
<span class="normal">874</span>
<span class="normal">875</span>
<span class="normal">876</span>
<span class="normal">877</span>
<span class="normal">878</span>
<span class="normal">879</span>
<span class="normal">880</span>
<span class="normal">881</span>
<span class="normal">882</span>
<span class="normal">883</span>
<span class="normal">884</span>
<span class="normal">885</span>
<span class="normal">886</span>
<span class="normal">887</span>
<span class="normal">888</span>
<span class="normal">889</span>
<span class="normal">890</span>
<span class="normal">891</span>
<span class="normal">892</span>
<span class="normal">893</span>
<span class="normal">894</span>
<span class="normal">895</span>
<span class="normal">896</span>
<span class="normal">897</span>
<span class="normal">898</span>
<span class="normal">899</span>
<span class="normal">900</span>
<span class="normal">901</span>
<span class="normal">902</span>
<span class="normal">903</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">class</span> <span class="nc">api_rest</span><span class="p">:</span> <span class="c1"># Classe para interação com APIs Rest (especialmente Sienge)</span>
<span class="w"> </span><span class="sd">"""</span>
<span class="sd"> #### Classe **api_rest**</span>
<span class="sd"> Destina-se a interatir com APIs RESTfull, em especial as publicadas pela SoftPlan para a [Plataforma Sienge](https://api.sienge.com.br/docs/).</span>
<span class="sd"> A classe deve ser instanciada conforme sintaxe abaixo:</span>
<span class="sd"> `api_rest(url, credenciais, cadencia, timeout=6, logger=None, headers={"Content-Type": "application/json"}, verify=True)`</span>
<span class="sd"> São nessários 2 parâmetros posicionais obrigatórios, e 5 parametros nominais facultativos (valor padrão, se omisso, indicado na sintaxe acima):</span>
<span class="sd"> - `url`: o endereço da URL de autenticação da API</span>
<span class="sd"> - `crednciais`: Dicionário com credenciais de autenticação. </span>
<span class="sd"> - `cadencia` Número máximo de chamadas *por segudo* à API </span>
<span class="sd"> - `timeout` Tempo máximo (segundos) para aguardar retorno à chamada. Padrão 6s, se omisso.</span>
<span class="sd"> - `logger` O objeto _log handler_ para lidar com as informações de saída. Se não informado, todas as saídas serão direcionadas para a stdout.</span>
<span class="sd"> - `headers` Cabeçalhos _http_ para a requisição à API.</span>
<span class="sd"> - `verify` Verifica a validade do certificado SSL do servidor de destino da requisição.</span>
<span class="sd"> Quanto às credenciais de autenticação, assim como a classe de interação com o PostgreSQL, elas precisam ser fornecidas na forma de um *dicionário*. </span>
<span class="sd"> Para o método `api_rest.aut_basic()`, o formato deve ser: </span>
<span class="sd"> ```</span>
<span class="sd"> credenciais = {</span>
<span class="sd"> 'user': 'USUARIO_API',</span>
<span class="sd"> 'password': 'TOKEN_USUARIO'</span>
<span class="sd"> }</span>
<span class="sd"> ```</span>
<span class="sd"> Caso a autenticação seja pelo método `api_rest.aut_bearer()`, o dicionário deve corresponder ao formato previsto pelo endpoint e seu conteúdo será enviado como um JSON ao endereço indicado no parametro `url`</span>
<span class="sd"> A classe possui 3 métodos: </span>
<span class="sd"> - `api_rest.auth_basic()`: instanciamento da sessão autenticando pelo método HTTPBasicAuth</span>
<span class="sd"> - `api_rest.auth_bearer()`: instanciamento da sessão autenticando pelos métodos OAuth, JWT, Bearer </span>
<span class="sd"> - `api_rest.endpoint_json([endereço], [método], payload=None)`: para a chamada ao endpoint</span>
<span class="sd"> - `close()` para encerra a instância/sessão</span>
<span class="sd"> O consumo é feito pelo método `api_rest.endpoint_json` que suporta apenas APIs cujo payload (opcional) seja aceito no formato JSON. </span>
<span class="sd"> Esse método espera 2 parametros posicionais obrigatórios: o endereço do endpoint e o verbo (get, post, patch ou put), tendo parametro opcional o objeto de 'payload' (json). </span>
<span class="sd"> Note que o endereço do endpoint deve ser informado completo. A URL informada no instanciamento da classe corresponde apenas ao endereço de autenticação. </span>
<span class="sd"> O tempo, em segundos, transcorrido entre a chamada a atual e a chamada anterior ao endpoint pode ser consultado pelo argumento `.Intervalo` no objeto recebido do retorno à chamada ao método `.endpoint_json`. </span>
<span class="sd"> Da mesma forma, o tempo de espera imposto para respeitar a cadência do webservcie também pode ser consultado pelo argumento `.Espera`.</span>
<span class="sd"> Exemplo de uso:</span>
<span class="sd"> ```</span>
<span class="sd"> from lbx_toolkit import api_rest</span>
<span class="sd"> UrlBase=r'https://api.sienge.com.br/lbx/public/api/v1'</span>
<span class="sd"> Credenciais = {</span>
<span class="sd"> 'user': 'USUARIO_API',</span>
<span class="sd"> 'password': 'TOKEN_USUARIO'</span>
<span class="sd"> }</span>
<span class="sd"> ApiSienge = api_rest(UrlBase,Credenciais,2.5) # limite de 2 requisições/segundo para cadência de chamada ao endpoint</span>
<span class="sd"> Auth = ApiSienge.auth_basic()</span>
<span class="sd"> Nutitulo=input('Numero do título:')</span>
<span class="sd"> Nuparcela=input('Numero da parcela:')</span>
<span class="sd"> Vencimento=input('Vencimento [AAAA-MM-DD]:')</span>
<span class="sd"> Payload = {</span>
<span class="sd"> "dueDate": f"{Vencimento}"</span>
<span class="sd"> }</span>
<span class="sd"> EndPoint = f'{UrlBase}/bills/{Nutitulo}/installments/{Nuparcela}'</span>
<span class="sd"> #chama o endpoint e recebe o retorno no objeto AlteraVcto</span>
<span class="sd"> AlteraVcto = ApiSienge.endpoint_json(EndPoint, 'patch', Payload)</span>
<span class="sd"> ```</span>
<span class="sd"> No exemplo acima não é esperado que o endpoint retorne nenhum dado (`patch`).</span>
<span class="sd"> Quando se usa o verbo `get` e se espera o retorno de algum dado, use o método `.json` do pacote `request` para acessar o objeto recebido.</span>
<span class="sd"> Para uso em APIs com autenticação JWT (JSON Web Token), OAuth, Bearer Token Authentication, a construção é a mesma indicada acima, bastando-se usar `.auth_bearer()` ao invés de _.auth_basic()_, e ajustar o dicionário `credenciais` informado no instanciamento da classe, que deve ser estruturado conforme o padrão fornecido peo mantendor da API e será enviado como payload ao endpoint (`json=credenciais`). </span>
<span class="sd"> """</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">credenciais</span><span class="p">,</span> <span class="n">cadencia</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="mi">6</span><span class="p">,</span> <span class="n">logger</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="p">{</span><span class="s2">"Content-Type"</span><span class="p">:</span> <span class="s2">"application/json"</span><span class="p">},</span> <span class="n">verify</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span> <span class="o">=</span> <span class="n">logger</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">logger</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">lbx_logger</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="n">logging</span><span class="o">.</span><span class="n">DEBUG</span><span class="p">,</span> <span class="s1">'</span><span class="si">%(levelname)s</span><span class="s1">: </span><span class="si">%(message)s</span><span class="s1">'</span><span class="p">)</span> <span class="c1"># se não fornecer o logger, vai tudo para o console</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">validators</span><span class="o">.</span><span class="n">url</span><span class="p">(</span><span class="n">url</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">critico</span><span class="p">(</span><span class="s1">'URL inválida: </span><span class="si">{url}</span><span class="s1">. Primeiro parametro precisar uma URL válida. Script abortado'</span><span class="p">,</span> <span class="n">exit</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">credenciais</span><span class="p">,</span> <span class="nb">dict</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">critico</span><span class="p">(</span><span class="s1">'O segundo parametro posicional precisa ser um dicionário. Script abortado'</span><span class="p">,</span> <span class="n">exit</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">RetEndPoint</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># Inicializa self.RetEndPoint como None </span>
<span class="bp">self</span><span class="o">.</span><span class="n">Headers</span> <span class="o">=</span> <span class="n">headers</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Verify</span> <span class="o">=</span> <span class="n">verify</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Url</span> <span class="o">=</span> <span class="n">url</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Timeout</span> <span class="o">=</span> <span class="n">timeout</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Credenciais</span> <span class="o">=</span> <span class="n">credenciais</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Cadencia</span> <span class="o">=</span> <span class="mi">1</span><span class="o">/</span><span class="n">cadencia</span> <span class="c1">## candencia corresponde a chamadas por segundo, não minuto</span>
<span class="bp">self</span><span class="o">.</span><span class="n">TempoUltReq</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Intervalo</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">Cadencia</span> <span class="o">+</span> <span class="mi">1</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">controla_cadencia</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="c1">## para controle apenas, não deve ser chamada fora da classe</span>
<span class="c1"># Verificar o tempo atual</span>
<span class="n">Agora</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>
<span class="c1"># Calcular intervalo entre requisições</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">TempoUltReq</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Intervalo</span> <span class="o">=</span> <span class="n">Agora</span> <span class="o">-</span> <span class="bp">self</span><span class="o">.</span><span class="n">TempoUltReq</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Intervalo</span> <span class="o">=</span> <span class="nb">float</span><span class="p">(</span><span class="s1">'inf'</span><span class="p">)</span> <span class="c1"># Primeira requisição não espera</span>
<span class="c1"># Calcular o tempo de espera necessário para respeitar o limite</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">Intervalo</span> <span class="o"><</span> <span class="bp">self</span><span class="o">.</span><span class="n">Cadencia</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Espera</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">Cadencia</span> <span class="o">-</span> <span class="bp">self</span><span class="o">.</span><span class="n">Intervalo</span>
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">Espera</span><span class="p">)</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">Espera</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Espera</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">Espera</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">Intervalo</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">auth_basic</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="c1"># Autentica e abre sessão na API </span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">Credenciais</span><span class="p">[</span><span class="s1">'user'</span><span class="p">]</span> <span class="ow">or</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">Credenciais</span><span class="p">[</span><span class="s1">'password'</span><span class="p">]:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">critico</span><span class="p">(</span><span class="s1">'Dicionário de credenciais não possui chaves "user" e/ou "password". Script abortado'</span><span class="p">,</span> <span class="n">exit</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Sessao</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">Session</span><span class="p">()</span>
<span class="c1">#Sessao.auth = (ApiUser, ApiPass)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Sessao</span><span class="o">.</span><span class="n">auth</span> <span class="o">=</span> <span class="n">HTTPBasicAuth</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">Credenciais</span><span class="p">[</span><span class="s1">'user'</span><span class="p">],</span> <span class="bp">self</span><span class="o">.</span><span class="n">Credenciais</span><span class="p">[</span><span class="s1">'password'</span><span class="p">])</span>
<span class="n">Auth</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">Sessao</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">Url</span><span class="p">)</span>
<span class="c1">#print(f'Status: {Auth.status_code}')</span>
<span class="c1">#print(f'Retorno: {Auth.text}')</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">Sessao</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">Err</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">critico</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Falha ao autenticar API: </span><span class="si">{</span><span class="n">Err</span><span class="si">}</span><span class="s2">. URL: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">Url</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span> <span class="n">exit</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">auth_bearer</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="c1"># Autentica e abre sessão na API</span>
<span class="c1">#self.UrlLogin = UrlLogin if UrlLogin is not None else self.Url</span>
<span class="k">try</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Sessao</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">Session</span><span class="p">()</span>
<span class="n">Token</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">Sessao</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">Url</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">Headers</span><span class="p">,</span> <span class="n">json</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">Credenciais</span><span class="p">,</span> <span class="n">verify</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">Verify</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Headers</span><span class="o">.</span><span class="n">update</span><span class="p">({</span><span class="s2">"Authorization"</span><span class="p">:</span> <span class="sa">f</span><span class="s2">"Bearer </span><span class="si">{</span><span class="n">Token</span><span class="o">.</span><span class="n">text</span><span class="si">}</span><span class="s2">"</span><span class="p">})</span>
<span class="k">if</span> <span class="mi">200</span> <span class="o"><=</span> <span class="n">Token</span><span class="o">.</span><span class="n">status_code</span> <span class="o"><=</span> <span class="mi">299</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Sessao</span><span class="o">.</span><span class="n">status_code</span> <span class="o">=</span> <span class="n">Token</span><span class="o">.</span><span class="n">status_code</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Sessao</span><span class="o">.</span><span class="n">token</span> <span class="o">=</span> <span class="n">Token</span><span class="o">.</span><span class="n">text</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">Sessao</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">critico</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Erro ao autenticar API: </span><span class="si">{</span><span class="n">Token</span><span class="o">.</span><span class="n">status_code</span><span class="si">}</span><span class="s2"> - </span><span class="si">{</span><span class="n">Token</span><span class="o">.</span><span class="n">text</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span> <span class="n">exit</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">Err</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">critico</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Falha ao autenticar API: </span><span class="si">{</span><span class="n">Err</span><span class="si">}</span><span class="s2">. URL: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">Url</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span> <span class="n">exit</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">endpoint_json</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">endpoint</span><span class="p">,</span> <span class="n">metodo</span><span class="p">,</span> <span class="n">payload</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span> <span class="c1"># Interage com End Point</span>
<span class="bp">self</span><span class="o">.</span><span class="n">ult_tempo_req</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Metodo</span> <span class="o">=</span> <span class="n">metodo</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
<span class="c1">#self.EndPoint = self.Url + endpoint</span>
<span class="bp">self</span><span class="o">.</span><span class="n">EndPoint</span> <span class="o">=</span> <span class="n">endpoint</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Payload</span> <span class="o">=</span> <span class="n">payload</span>
<span class="n">MetodosAceitos</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'post'</span><span class="p">,</span> <span class="s1">'get'</span><span class="p">,</span> <span class="s1">'patch'</span><span class="p">,</span> <span class="s1">'put'</span><span class="p">]</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">any</span><span class="p">(</span><span class="n">element</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">Metodo</span> <span class="k">for</span> <span class="n">element</span> <span class="ow">in</span> <span class="n">MetodosAceitos</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">critico</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Método </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">Metodo</span><span class="si">}</span><span class="s1"> não previsto. Abortando chamada!'</span><span class="p">,</span> <span class="n">exit</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">ChamadaApi</span> <span class="o">=</span> <span class="sa">f</span><span class="s1">'self.Sessao.</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">Metodo</span><span class="si">}</span><span class="s1">(self.EndPoint, timeout=self.Timeout, headers=self.Headers, verify=self.Verify)'</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">Payload</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="sa">f</span><span class="s1">'self.Sessao.</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">Metodo</span><span class="si">}</span><span class="s1">(self.EndPoint, timeout=self.Timeout, headers=self.Headers, verify=self.Verify, json=self.Payload)'</span>
<span class="bp">self</span><span class="o">.</span><span class="n">controla_cadencia</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">TempoUltReq</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">RetEndPoint</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="n">ChamadaApi</span><span class="p">)</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">RetEndPoint</span><span class="o">.</span><span class="n">status_code</span> <span class="o">>=</span> <span class="mi">500</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">critico</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Erro </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">RetEndPoint</span><span class="o">.</span><span class="n">status_code</span><span class="si">}</span><span class="s1"> na chamada do endpoint: </span><span class="si">{</span><span class="n">Err</span><span class="si">}</span><span class="se">\n</span><span class="s1">Endpoint: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">EndPoint</span><span class="si">}</span><span class="se">\n</span><span class="s1">Resposta: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">RetEndPoint</span><span class="o">.</span><span class="n">text</span><span class="si">}</span><span class="s1">'</span><span class="p">,</span> <span class="n">exit</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">RetEndPoint</span><span class="o">.</span><span class="n">Espera</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">Espera</span> <span class="c1">## adiona o tempo de espera ao retorno da API</span>
<span class="bp">self</span><span class="o">.</span><span class="n">RetEndPoint</span><span class="o">.</span><span class="n">Intervalo</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">Intervalo</span> <span class="c1">## adiciona o intervalo entre chamada ao retorno da API </span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">RetEndPoint</span>
<span class="k">except</span> <span class="n">requests</span><span class="o">.</span><span class="n">exceptions</span><span class="o">.</span><span class="n">ReadTimeout</span> <span class="k">as</span> <span class="n">Err</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">critico</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Excedido tempo limite </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">Timeout</span><span class="si">}</span><span class="s1"> para retorno do endpoint: </span><span class="si">{</span><span class="n">Err</span><span class="si">}</span><span class="se">\n</span><span class="s1">Endpoint: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">EndPoint</span><span class="si">}</span><span class="s1">'</span><span class="p">,</span> <span class="n">exit</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">Err</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">critico</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Falha na chamada do endpoint: </span><span class="si">{</span><span class="n">Err</span><span class="si">}</span><span class="se">\n</span><span class="s1">Endpoint: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">EndPoint</span><span class="si">}</span><span class="se">\n</span><span class="s1">Codigo retorno: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">RetEndPoint</span><span class="o">.</span><span class="n">status_code</span><span class="si">}</span><span class="se">\n</span><span class="s1">Resposta:</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">RetEndPoint</span><span class="o">.</span><span class="n">text</span><span class="si">}</span><span class="s1">'</span><span class="p">,</span> <span class="n">exit</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">trata_erro_sienge</span><span class="p">(</span><span class="n">CodRet</span><span class="p">,</span> <span class="n">Retorno</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="mi">200</span> <span class="o"><=</span> <span class="n">CodRet</span> <span class="o"><=</span> <span class="mi">299</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">DicRetorno</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="n">Retorno</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'null'</span><span class="p">,</span><span class="s1">'None'</span><span class="p">)</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="sa">r</span><span class="s1">'\n\t'</span><span class="p">,</span><span class="s1">' '</span><span class="p">))</span>
<span class="k">if</span> <span class="s1">'clientMessage'</span> <span class="ow">in</span> <span class="n">DicRetorno</span> <span class="ow">and</span> <span class="n">DicRetorno</span><span class="p">[</span><span class="s1">'clientMessage'</span><span class="p">]</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="s1">'None'</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="s1">''</span><span class="p">,</span> <span class="s1">' '</span><span class="p">,</span> <span class="s1">'null'</span><span class="p">]:</span>
<span class="n">MsgErro</span> <span class="o">=</span> <span class="n">DicRetorno</span><span class="p">[</span><span class="s1">'clientMessage'</span><span class="p">]</span>
<span class="k">elif</span> <span class="s1">'developerMessage'</span> <span class="ow">in</span> <span class="n">DicRetorno</span> <span class="ow">and</span> <span class="n">DicRetorno</span><span class="p">[</span><span class="s1">'developerMessage'</span><span class="p">]</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="s1">'None'</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="s1">''</span><span class="p">,</span> <span class="s1">' '</span><span class="p">,</span> <span class="s1">'null'</span><span class="p">]:</span>
<span class="n">MsgErro</span> <span class="o">=</span> <span class="n">DicRetorno</span><span class="p">[</span><span class="s1">'developerMessage'</span><span class="p">]</span>
<span class="k">elif</span> <span class="s1">'message'</span> <span class="ow">in</span> <span class="n">DicRetorno</span> <span class="ow">and</span> <span class="n">DicRetorno</span><span class="p">[</span><span class="s1">'message'</span><span class="p">]</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="s1">'None'</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="s1">''</span><span class="p">,</span> <span class="s1">' '</span><span class="p">,</span> <span class="s1">'null'</span><span class="p">]:</span>
<span class="n">MsgErro</span> <span class="o">=</span> <span class="n">DicRetorno</span><span class="p">[</span><span class="s1">'message'</span><span class="p">]</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">MsgErro</span> <span class="o">=</span> <span class="n">Retorno</span>
<span class="k">except</span><span class="p">:</span>
<span class="n">MsgErro</span> <span class="o">=</span> <span class="n">Retorno</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="sa">r</span><span class="s1">'\n\t'</span><span class="p">,</span><span class="s1">' '</span><span class="p">)</span>
<span class="k">finally</span><span class="p">:</span>
<span class="k">return</span> <span class="n">MsgErro</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="n">Retorno</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="c1"># Encerra a cessão</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Sessao</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</code></pre></div></td></tr></table></div>
</details>
<div class="doc doc-children">
</div>
</div>
</div>
<div class="doc doc-object doc-class">
<h2 id="lbxtoolkit.auth_EntraID" class="doc doc-heading">
<code>auth_EntraID</code>
</h2>
<div class="doc doc-contents ">
<h6 id="lbxtoolkit.auth_EntraID--classe-auth_entraid">Classe <strong>auth_EntraID</strong></h6>
<p>Este recurso tem o propósito de controlar as permissões de execução do script usando as credencias do ambiente AD em nuvem da Microsoft (Azure AD >> Microsoft Entra ID), abortando se a autentição falhar ou o usuário não pertencer ao grupo.</p>
<p>Essa classe possui apenas dois métodos:</p>
<ul>
<li>
<p><code>auth_EntraID.disclaimer()</code>: apenas exibe uma tela de informações/instruções ao usuário.</p>
</li>
<li>
<p><code>auth_EntraID.valida_grupo([client_id], [client_secret], [tenant_id], timeout=60, log_file='auth_EntraID.log')</code>: efetua a autenticação do usuário e verifica se ele pertence ao grupo informado, abortando a execução caso não pertença ao grupo ou a autenticação não seja validada no tempo estabelecido. Os argumentos <code>timeout</code> e <code>log_file</code> são opcionais e, se omitidos, os valores aqui atribuídos serão adotados como padrão.</p>
</li>
</ul>
<p>É necessário obter parametros da plataforma de identidade da Microsoft (AD Azure, agora Microsoft Entra ID), no <a href="https://entra.microsoft.com"><em>Centro de administração do Microsoft Entra</em></a>.
Sugerimos não armazenar estas ou outras informações sensíveis no script. Considere usar o pacote <code>dotenv</code> para isso.</p>
<p>Os argumentos obrigatórios (posicionais) são:</p>
<p>1) <code>tenant_id</code> corresponde ao campo <em>ID do Locatário</em>, que pode ser obtido na página <a href="https://entra.microsoft.com/#blade/Microsoft_AAD_IAM/TenantOverview.ReactView">visão geral de identidade do domínio</a></p>
<p>2) <code>client_id</code> corresponde ao <em>ID do aplicativo (cliente)</em>, obtido na secção <a href="https://entra.microsoft.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade/quickStartType~/null/sourceType/Microsoft_AAD_IAM"><em>Identidade > Aplicativos > Registros de Aplicativo</em></a>. Considere não reaproveitar aplicativos e criar um específico para essa finalidade.</p>
<p>3) <code>secret_id</code> corresponde ao <em>Valor</em> do <em>ID secreto</em> (não ao próprio ID Secreto) do aplicativo. Este token não é passivel de consulta após gerado e para obtê-lo, é necessário criar um novo segredo para o aplicativo na subsecção <em>"Certificados e Segredos"</em>, após clicar no nome do aplicativo exibo na indicada no item (2). O token (<em>Valor do segredo</em>) deve ser copiado e anotado no ato da criação, pois <em>não é possível consultá-lo posteriormente</em>.</p>
<pre><code>from lbx_toolkit import auth_EntraID
client_id = 'SEU_CLIENT_ID'
client_secret = 'SEU_CLIENT_SECRET'
tenant_id = 'SEU_TENANT_ID'
# inicializa instância
auth = auth_EntraID(client_id, client_secret, tenant_id, timeout=60, log_file='auth_EntraID.log')
# exibe a mensagem padrão de aviso
auth.disclaimer()
auth.valida_grupo('Nome do Grupo de Distribuição')
# se usuário não pertencer a grupo informado, a execução do script é abortada.
</code></pre>
<details class="quote">
<summary>Source code in <code>lbxtoolkit\__init__.py</code></summary>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">100</span>
<span class="normal">101</span>
<span class="normal">102</span>
<span class="normal">103</span>
<span class="normal">104</span>
<span class="normal">105</span>
<span class="normal">106</span>
<span class="normal">107</span>
<span class="normal">108</span>
<span class="normal">109</span>
<span class="normal">110</span>
<span class="normal">111</span>
<span class="normal">112</span>
<span class="normal">113</span>
<span class="normal">114</span>
<span class="normal">115</span>
<span class="normal">116</span>
<span class="normal">117</span>
<span class="normal">118</span>
<span class="normal">119</span>
<span class="normal">120</span>
<span class="normal">121</span>
<span class="normal">122</span>
<span class="normal">123</span>
<span class="normal">124</span>
<span class="normal">125</span>
<span class="normal">126</span>
<span class="normal">127</span>
<span class="normal">128</span>
<span class="normal">129</span>
<span class="normal">130</span>
<span class="normal">131</span>
<span class="normal">132</span>
<span class="normal">133</span>
<span class="normal">134</span>
<span class="normal">135</span>
<span class="normal">136</span>
<span class="normal">137</span>
<span class="normal">138</span>
<span class="normal">139</span>
<span class="normal">140</span>
<span class="normal">141</span>
<span class="normal">142</span>
<span class="normal">143</span>
<span class="normal">144</span>
<span class="normal">145</span>
<span class="normal">146</span>
<span class="normal">147</span>
<span class="normal">148</span>
<span class="normal">149</span>
<span class="normal">150</span>
<span class="normal">151</span>
<span class="normal">152</span>
<span class="normal">153</span>
<span class="normal">154</span>
<span class="normal">155</span>
<span class="normal">156</span>
<span class="normal">157</span>
<span class="normal">158</span>
<span class="normal">159</span>
<span class="normal">160</span>
<span class="normal">161</span>
<span class="normal">162</span>
<span class="normal">163</span>
<span class="normal">164</span>
<span class="normal">165</span>
<span class="normal">166</span>
<span class="normal">167</span>
<span class="normal">168</span>
<span class="normal">169</span>
<span class="normal">170</span>
<span class="normal">171</span>
<span class="normal">172</span>
<span class="normal">173</span>
<span class="normal">174</span>
<span class="normal">175</span>
<span class="normal">176</span>
<span class="normal">177</span>
<span class="normal">178</span>
<span class="normal">179</span>
<span class="normal">180</span>
<span class="normal">181</span>
<span class="normal">182</span>
<span class="normal">183</span>
<span class="normal">184</span>
<span class="normal">185</span>
<span class="normal">186</span>
<span class="normal">187</span>
<span class="normal">188</span>
<span class="normal">189</span>
<span class="normal">190</span>
<span class="normal">191</span>
<span class="normal">192</span>
<span class="normal">193</span>
<span class="normal">194</span>
<span class="normal">195</span>
<span class="normal">196</span>
<span class="normal">197</span>
<span class="normal">198</span>
<span class="normal">199</span>
<span class="normal">200</span>
<span class="normal">201</span>
<span class="normal">202</span>
<span class="normal">203</span>
<span class="normal">204</span>
<span class="normal">205</span>
<span class="normal">206</span>
<span class="normal">207</span>
<span class="normal">208</span>
<span class="normal">209</span>
<span class="normal">210</span>
<span class="normal">211</span>
<span class="normal">212</span>
<span class="normal">213</span>
<span class="normal">214</span>
<span class="normal">215</span>
<span class="normal">216</span>
<span class="normal">217</span>
<span class="normal">218</span>
<span class="normal">219</span>
<span class="normal">220</span>
<span class="normal">221</span>
<span class="normal">222</span>
<span class="normal">223</span>
<span class="normal">224</span>
<span class="normal">225</span>
<span class="normal">226</span>
<span class="normal">227</span>
<span class="normal">228</span>
<span class="normal">229</span>
<span class="normal">230</span>
<span class="normal">231</span>
<span class="normal">232</span>
<span class="normal">233</span>
<span class="normal">234</span>
<span class="normal">235</span>
<span class="normal">236</span>
<span class="normal">237</span>
<span class="normal">238</span>
<span class="normal">239</span>
<span class="normal">240</span>
<span class="normal">241</span>
<span class="normal">242</span>
<span class="normal">243</span>
<span class="normal">244</span>
<span class="normal">245</span>
<span class="normal">246</span>
<span class="normal">247</span>
<span class="normal">248</span>
<span class="normal">249</span>
<span class="normal">250</span>
<span class="normal">251</span>
<span class="normal">252</span>
<span class="normal">253</span>
<span class="normal">254</span>
<span class="normal">255</span>
<span class="normal">256</span>
<span class="normal">257</span>
<span class="normal">258</span>
<span class="normal">259</span>
<span class="normal">260</span>
<span class="normal">261</span>
<span class="normal">262</span>
<span class="normal">263</span>
<span class="normal">264</span>
<span class="normal">265</span>
<span class="normal">266</span>
<span class="normal">267</span>
<span class="normal">268</span>
<span class="normal">269</span>
<span class="normal">270</span>
<span class="normal">271</span>
<span class="normal">272</span>
<span class="normal">273</span>
<span class="normal">274</span>
<span class="normal">275</span>
<span class="normal">276</span>
<span class="normal">277</span>
<span class="normal">278</span>
<span class="normal">279</span>
<span class="normal">280</span>
<span class="normal">281</span>
<span class="normal">282</span>
<span class="normal">283</span>
<span class="normal">284</span>
<span class="normal">285</span>
<span class="normal">286</span>
<span class="normal">287</span>
<span class="normal">288</span>
<span class="normal">289</span>
<span class="normal">290</span>
<span class="normal">291</span>
<span class="normal">292</span>
<span class="normal">293</span>
<span class="normal">294</span>
<span class="normal">295</span>
<span class="normal">296</span>
<span class="normal">297</span>
<span class="normal">298</span>
<span class="normal">299</span>
<span class="normal">300</span>
<span class="normal">301</span>
<span class="normal">302</span>
<span class="normal">303</span>
<span class="normal">304</span>
<span class="normal">305</span>
<span class="normal">306</span>
<span class="normal">307</span>
<span class="normal">308</span>
<span class="normal">309</span>
<span class="normal">310</span>
<span class="normal">311</span>
<span class="normal">312</span>
<span class="normal">313</span>
<span class="normal">314</span>
<span class="normal">315</span>
<span class="normal">316</span>
<span class="normal">317</span>
<span class="normal">318</span>
<span class="normal">319</span>
<span class="normal">320</span>
<span class="normal">321</span>
<span class="normal">322</span>
<span class="normal">323</span>
<span class="normal">324</span>
<span class="normal">325</span>
<span class="normal">326</span>
<span class="normal">327</span>
<span class="normal">328</span>
<span class="normal">329</span>
<span class="normal">330</span>
<span class="normal">331</span>
<span class="normal">332</span>
<span class="normal">333</span>
<span class="normal">334</span>
<span class="normal">335</span>
<span class="normal">336</span>
<span class="normal">337</span>
<span class="normal">338</span>
<span class="normal">339</span>
<span class="normal">340</span>
<span class="normal">341</span>
<span class="normal">342</span>
<span class="normal">343</span>
<span class="normal">344</span>
<span class="normal">345</span>
<span class="normal">346</span>
<span class="normal">347</span>
<span class="normal">348</span>
<span class="normal">349</span>
<span class="normal">350</span>
<span class="normal">351</span>
<span class="normal">352</span>
<span class="normal">353</span>
<span class="normal">354</span>
<span class="normal">355</span>
<span class="normal">356</span>
<span class="normal">357</span>
<span class="normal">358</span>
<span class="normal">359</span>
<span class="normal">360</span>
<span class="normal">361</span>
<span class="normal">362</span>
<span class="normal">363</span>
<span class="normal">364</span>
<span class="normal">365</span>
<span class="normal">366</span>
<span class="normal">367</span>
<span class="normal">368</span>
<span class="normal">369</span>
<span class="normal">370</span>
<span class="normal">371</span>
<span class="normal">372</span>
<span class="normal">373</span>
<span class="normal">374</span>
<span class="normal">375</span>
<span class="normal">376</span>
<span class="normal">377</span>
<span class="normal">378</span>
<span class="normal">379</span>
<span class="normal">380</span>
<span class="normal">381</span>
<span class="normal">382</span>
<span class="normal">383</span>
<span class="normal">384</span>
<span class="normal">385</span>
<span class="normal">386</span>
<span class="normal">387</span>
<span class="normal">388</span>
<span class="normal">389</span>
<span class="normal">390</span>
<span class="normal">391</span>
<span class="normal">392</span>
<span class="normal">393</span>
<span class="normal">394</span>
<span class="normal">395</span>
<span class="normal">396</span>
<span class="normal">397</span>
<span class="normal">398</span>
<span class="normal">399</span>
<span class="normal">400</span>
<span class="normal">401</span>
<span class="normal">402</span>
<span class="normal">403</span>
<span class="normal">404</span>
<span class="normal">405</span>
<span class="normal">406</span>
<span class="normal">407</span>
<span class="normal">408</span>
<span class="normal">409</span>
<span class="normal">410</span>
<span class="normal">411</span>
<span class="normal">412</span>
<span class="normal">413</span>
<span class="normal">414</span>
<span class="normal">415</span>
<span class="normal">416</span>
<span class="normal">417</span>
<span class="normal">418</span>
<span class="normal">419</span>
<span class="normal">420</span>
<span class="normal">421</span>
<span class="normal">422</span>
<span class="normal">423</span>
<span class="normal">424</span>
<span class="normal">425</span>
<span class="normal">426</span>
<span class="normal">427</span>
<span class="normal">428</span>
<span class="normal">429</span>
<span class="normal">430</span>
<span class="normal">431</span>
<span class="normal">432</span>
<span class="normal">433</span>
<span class="normal">434</span>
<span class="normal">435</span>
<span class="normal">436</span>
<span class="normal">437</span>
<span class="normal">438</span>
<span class="normal">439</span>
<span class="normal">440</span>
<span class="normal">441</span>
<span class="normal">442</span>
<span class="normal">443</span>
<span class="normal">444</span>
<span class="normal">445</span>
<span class="normal">446</span>
<span class="normal">447</span>
<span class="normal">448</span>
<span class="normal">449</span>
<span class="normal">450</span>
<span class="normal">451</span>
<span class="normal">452</span>
<span class="normal">453</span>
<span class="normal">454</span>
<span class="normal">455</span>
<span class="normal">456</span>
<span class="normal">457</span>
<span class="normal">458</span>
<span class="normal">459</span>
<span class="normal">460</span>
<span class="normal">461</span>
<span class="normal">462</span>
<span class="normal">463</span>
<span class="normal">464</span>
<span class="normal">465</span>
<span class="normal">466</span>
<span class="normal">467</span>
<span class="normal">468</span>
<span class="normal">469</span>
<span class="normal">470</span>
<span class="normal">471</span>
<span class="normal">472</span>
<span class="normal">473</span>
<span class="normal">474</span>
<span class="normal">475</span>
<span class="normal">476</span>
<span class="normal">477</span>
<span class="normal">478</span>
<span class="normal">479</span>
<span class="normal">480</span>
<span class="normal">481</span>
<span class="normal">482</span>
<span class="normal">483</span>
<span class="normal">484</span>
<span class="normal">485</span>
<span class="normal">486</span>
<span class="normal">487</span>
<span class="normal">488</span>
<span class="normal">489</span>
<span class="normal">490</span>
<span class="normal">491</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">class</span> <span class="nc">auth_EntraID</span><span class="p">:</span> <span class="c1"># Classe de autenticação de usuários no Microsoft Entra ID (antiga Azure AD)</span>
<span class="w"> </span><span class="sd">"""</span>
<span class="sd"> #### Classe **auth_EntraID**</span>
<span class="sd"> Este recurso tem o propósito de controlar as permissões de execução do script usando as credencias do ambiente AD em nuvem da Microsoft (Azure AD >> Microsoft Entra ID), abortando se a autentição falhar ou o usuário não pertencer ao grupo.</span>
<span class="sd"> Essa classe possui apenas dois métodos:</span>
<span class="sd"> - `auth_EntraID.disclaimer()`: apenas exibe uma tela de informações/instruções ao usuário.</span>
<span class="sd"> - `auth_EntraID.valida_grupo([client_id], [client_secret], [tenant_id], timeout=60, log_file='auth_EntraID.log')`: efetua a autenticação do usuário e verifica se ele pertence ao grupo informado, abortando a execução caso não pertença ao grupo ou a autenticação não seja validada no tempo estabelecido. Os argumentos `timeout` e `log_file` são opcionais e, se omitidos, os valores aqui atribuídos serão adotados como padrão.</span>
<span class="sd"> É necessário obter parametros da plataforma de identidade da Microsoft (AD Azure, agora Microsoft Entra ID), no [*Centro de administração do Microsoft Entra*](https://entra.microsoft.com).</span>
<span class="sd"> Sugerimos não armazenar estas ou outras informações sensíveis no script. Considere usar o pacote `dotenv` para isso.</span>
<span class="sd"> Os argumentos obrigatórios (posicionais) são:</span>
<span class="sd"> 1) `tenant_id` corresponde ao campo *ID do Locatário*, que pode ser obtido na página [visão geral de identidade do domínio](https://entra.microsoft.com/#blade/Microsoft_AAD_IAM/TenantOverview.ReactView)</span>
<span class="sd"> 2) `client_id` corresponde ao *ID do aplicativo (cliente)*, obtido na secção [_Identidade > Aplicativos > Registros de Aplicativo_](https://entra.microsoft.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade/quickStartType~/null/sourceType/Microsoft_AAD_IAM). Considere não reaproveitar aplicativos e criar um específico para essa finalidade.</span>
<span class="sd"> 3) `secret_id` corresponde ao *Valor* do _ID secreto_ (não ao próprio ID Secreto) do aplicativo. Este token não é passivel de consulta após gerado e para obtê-lo, é necessário criar um novo segredo para o aplicativo na subsecção _"Certificados e Segredos"_, após clicar no nome do aplicativo exibo na indicada no item (2). O token (_Valor do segredo_) deve ser copiado e anotado no ato da criação, pois *não é possível consultá-lo posteriormente*.</span>
<span class="sd"> ```</span>
<span class="sd"> from lbx_toolkit import auth_EntraID</span>
<span class="sd"> client_id = 'SEU_CLIENT_ID'</span>
<span class="sd"> client_secret = 'SEU_CLIENT_SECRET'</span>
<span class="sd"> tenant_id = 'SEU_TENANT_ID'</span>
<span class="sd"> # inicializa instância</span>
<span class="sd"> auth = auth_EntraID(client_id, client_secret, tenant_id, timeout=60, log_file='auth_EntraID.log') </span>
<span class="sd"> # exibe a mensagem padrão de aviso</span>
<span class="sd"> auth.disclaimer()</span>
<span class="sd"> auth.valida_grupo('Nome do Grupo de Distribuição') </span>
<span class="sd"> # se usuário não pertencer a grupo informado, a execução do script é abortada.</span>
<span class="sd"> ```</span>
<span class="sd"> """</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">client_id</span><span class="p">,</span> <span class="n">client_secret</span><span class="p">,</span> <span class="n">tenant_id</span><span class="p">,</span> <span class="n">grupo</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="mi">60</span><span class="p">,</span> <span class="n">log_file</span><span class="o">=</span><span class="s1">'auth_EntraID.log'</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">client_id</span> <span class="o">=</span> <span class="n">client_id</span>
<span class="bp">self</span><span class="o">.</span><span class="n">client_secret</span> <span class="o">=</span> <span class="n">client_secret</span>
<span class="bp">self</span><span class="o">.</span><span class="n">tenant_id</span> <span class="o">=</span> <span class="n">tenant_id</span>
<span class="bp">self</span><span class="o">.</span><span class="n">timeout</span> <span class="o">=</span> <span class="n">timeout</span>
<span class="bp">self</span><span class="o">.</span><span class="n">grupo</span> <span class="o">=</span> <span class="n">grupo</span>
<span class="bp">self</span><span class="o">.</span><span class="n">authority</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"https://login.microsoftonline.com/</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">tenant_id</span><span class="si">}</span><span class="s2">"</span>
<span class="bp">self</span><span class="o">.</span><span class="n">scope</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"https://graph.microsoft.com/.default"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">redirect_uri</span> <span class="o">=</span> <span class="s2">"http://localhost:8000"</span>
<span class="bp">self</span><span class="o">.</span><span class="n">response</span> <span class="o">=</span> <span class="s2">""</span>
<span class="bp">self</span><span class="o">.</span><span class="n">status_code</span> <span class="o">=</span> <span class="mi">0</span>
<span class="bp">self</span><span class="o">.</span><span class="n">server</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">log_file</span> <span class="o">=</span> <span class="n">log_file</span>
<span class="c1"># Configura o logger</span>
<span class="n">logging</span><span class="o">.</span><span class="n">basicConfig</span><span class="p">(</span><span class="n">filename</span><span class="o">=</span><span class="n">log_file</span><span class="p">,</span> <span class="n">level</span><span class="o">=</span><span class="n">logging</span><span class="o">.</span><span class="n">INFO</span><span class="p">,</span>
<span class="nb">format</span><span class="o">=</span><span class="s1">'</span><span class="si">%(asctime)s</span><span class="s1"> - </span><span class="si">%(name)s</span><span class="s1"> - </span><span class="si">%(levelname)s</span><span class="s1"> - </span><span class="si">%(message)s</span><span class="s1">'</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="vm">__name__</span><span class="p">)</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">valida_grupo</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="c1"># Valida se o usuário autenticado pertence a grupo de segurança informado</span>
<span class="c1"># Redireciona stdout e stderr para arquivos de log</span>
<span class="n">original_stdout</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span>
<span class="n">original_stderr</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">stderr</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'stdout.log'</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stderr</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'stderr.log'</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span>
<span class="c1"># Configurações do Selenium</span>
<span class="n">chrome_options</span> <span class="o">=</span> <span class="n">Options</span><span class="p">()</span>
<span class="n">chrome_options</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s2">"--incognito"</span><span class="p">)</span>
<span class="c1"># Inicializa a aplicação MSAL</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">msal</span><span class="o">.</span><span class="n">ConfidentialClientApplication</span><span class="p">(</span>
<span class="bp">self</span><span class="o">.</span><span class="n">client_id</span><span class="p">,</span>
<span class="n">authority</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">authority</span><span class="p">,</span>
<span class="n">client_credential</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">client_secret</span><span class="p">,</span>
<span class="p">)</span>
<span class="k">except</span> <span class="ne">BaseException</span> <span class="k">as</span> <span class="n">err</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Falha ao iniciar aplicação MSAL: </span><span class="si">{</span><span class="n">err</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
<span class="c1"># Restaura saída padrão</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span> <span class="o">=</span> <span class="n">original_stdout</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stderr</span> <span class="o">=</span> <span class="n">original_stderr</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Script abortado por falha aplicação MSAL. Verifque logs: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">log_file</span><span class="si">}</span><span class="s1">, stdout.log e sterr.log'</span><span class="p">)</span>
<span class="n">os</span><span class="o">.</span><span class="n">_exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="c1"># Inicia o fluxo de código de autorização</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">flow</span> <span class="o">=</span> <span class="n">app</span><span class="o">.</span><span class="n">initiate_auth_code_flow</span><span class="p">(</span><span class="n">scopes</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">scope</span><span class="p">,</span> <span class="n">redirect_uri</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">redirect_uri</span><span class="p">)</span>
<span class="n">auth_url</span> <span class="o">=</span> <span class="n">flow</span><span class="p">[</span><span class="s2">"auth_uri"</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">response</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"Acessando a URL de autenticação Microsoft Entra ID (antiga Azure AD): </span><span class="si">{</span><span class="n">auth_url</span><span class="si">}</span><span class="s2">"</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">response</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">BaseException</span> <span class="k">as</span> <span class="n">err</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Falha no fluxo de autorização Microsoft Entra ID (antiga Azure AD): </span><span class="si">{</span><span class="n">err</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
<span class="c1"># Restaura saída padrão</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span> <span class="o">=</span> <span class="n">original_stdout</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stderr</span> <span class="o">=</span> <span class="n">original_stderr</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Script abortado por falha no fluxo de autorização Microsoft Entra ID (antiga Azure AD). Verifque logs: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">log_file</span><span class="si">}</span><span class="s1">, stdout.log e sterr.log'</span><span class="p">)</span>
<span class="n">os</span><span class="o">.</span><span class="n">_exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="c1"># Inicializa o ChromeDriver com redirecionamento de saída</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">service</span> <span class="o">=</span> <span class="n">Service</span><span class="p">(</span><span class="n">ChromeDriverManager</span><span class="p">()</span><span class="o">.</span><span class="n">install</span><span class="p">())</span>
<span class="n">service</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
<span class="n">driver</span> <span class="o">=</span> <span class="n">webdriver</span><span class="o">.</span><span class="n">Chrome</span><span class="p">(</span><span class="n">service</span><span class="o">=</span><span class="n">service</span><span class="p">,</span> <span class="n">options</span><span class="o">=</span><span class="n">chrome_options</span><span class="p">)</span>
<span class="n">driver</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">auth_url</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">BaseException</span> <span class="k">as</span> <span class="n">err</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Falha na inicialização do Chrome: </span><span class="si">{</span><span class="n">err</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
<span class="c1"># Restaura saída padrão</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span> <span class="o">=</span> <span class="n">original_stdout</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stderr</span> <span class="o">=</span> <span class="n">original_stderr</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Script abortado na inicialização do Chrome. Verifque logs: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">log_file</span><span class="si">}</span><span class="s1">, stdout.log e sterr.log'</span><span class="p">)</span>
<span class="n">os</span><span class="o">.</span><span class="n">_exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">class</span> <span class="nc">AuthHandler</span><span class="p">(</span><span class="n">BaseHTTPRequestHandler</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">log_message</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">format</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">server</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">"</span><span class="si">%s</span><span class="s2"> - - [</span><span class="si">%s</span><span class="s2">] </span><span class="si">%s</span><span class="se">\n</span><span class="s2">"</span> <span class="o">%</span>
<span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">client_address</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span>
<span class="bp">self</span><span class="o">.</span><span class="n">log_date_time_string</span><span class="p">(),</span>
<span class="nb">format</span> <span class="o">%</span> <span class="n">args</span><span class="p">))</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">do_GET</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">parsed_path</span> <span class="o">=</span> <span class="n">urlparse</span><span class="o">.</span><span class="n">urlparse</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">path</span><span class="p">)</span>
<span class="n">query_params</span> <span class="o">=</span> <span class="n">urlparse</span><span class="o">.</span><span class="n">parse_qs</span><span class="p">(</span><span class="n">parsed_path</span><span class="o">.</span><span class="n">query</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">send_response</span><span class="p">(</span><span class="mi">200</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">send_header</span><span class="p">(</span><span class="s1">'Content-type'</span><span class="p">,</span> <span class="s1">'text/html'</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">end_headers</span><span class="p">()</span>
<span class="c1"># Captura o código de autorização e o estado</span>
<span class="k">if</span> <span class="s1">'code'</span> <span class="ow">in</span> <span class="n">query_params</span> <span class="ow">and</span> <span class="s1">'state'</span> <span class="ow">in</span> <span class="n">query_params</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">server</span><span class="o">.</span><span class="n">auth_code</span> <span class="o">=</span> <span class="n">query_params</span><span class="p">[</span><span class="s1">'code'</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">server</span><span class="o">.</span><span class="n">state</span> <span class="o">=</span> <span class="n">query_params</span><span class="p">[</span><span class="s1">'state'</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">wfile</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="sa">b</span><span class="s2">"""</span>
<span class="s2"> <!DOCTYPE html></span>
<span class="s2"> <html lang="pt_BR"></span>
<span class="s2"> <head></span>
<span class="s2"> <meta charset="UTF-8"></span>
<span class="s2"> <meta name="viewport" content="width=device-width, initial-scale=1.0"></span>
<span class="s2"> <style></span>
<span class="s2"> body {</span>
<span class="s2"> font-family: 'Arial', sans-serif;</span>
<span class="s2"> background-color: #f8f9fa;</span>
<span class="s2"> margin: 0;</span>
<span class="s2"> font-size: 16px;</span>
<span class="s2"> padding: 30px;</span>
<span class="s2"> display: flex; *</span>
<span class="s2"> }</span>
<span class="s2"> .container { </span>
<span class="s2"> width: 100%;</span>
<span class="s2"> margin: auto;</span>
<span class="s2"> background-color: #ffffff;</span>
<span class="s2"> box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);</span>
<span class="s2"> padding: 16px;</span>
<span class="s2"> text-align: center;</span>
<span class="s2"> font-size: 16px;</span>
<span class="s2"> border-radius: 8px;</span>
<span class="s2"> }</span>
<span class="s2"> h1 { </span>
<span class="s2"> font-size: 18px;</span>
<span class="s2"> text-align: center;</span>
<span class="s2"> color: #007bff;</span>
<span class="s2"> }</span>
<span class="s2"> </style></span>
<span class="s2"> </head></span>
<span class="s2"> <div class="container"></span>
<span class="s2"> <h1>Autentica&#231;&#227;o realizada com sucesso!</h1></span>
<span class="s2"> Aguarde que esta p&#225;gina ser&#225; fechada automaticamente.<br></span>
<span class="s2"> Se isto n&#227;o acontecer, pode fech&#225;-la manualmente.</span>
<span class="s2"> </div></span>
<span class="s2"> </body></html></span>
<span class="s2"> """</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">wfile</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="sa">b</span><span class="s2">"""</span>
<span class="s2"> <!DOCTYPE html></span>
<span class="s2"> <html lang="pt_BR"></span>
<span class="s2"> <head></span>
<span class="s2"> <meta charset="UTF-8"></span>
<span class="s2"> <meta name="viewport" content="width=device-width, initial-scale=1.0"></span>
<span class="s2"> <style></span>
<span class="s2"> body {</span>
<span class="s2"> font-family: 'Arial', sans-serif;</span>
<span class="s2"> background-color: #f8f9fa;</span>
<span class="s2"> margin: 0;</span>
<span class="s2"> font-size: 16px;</span>
<span class="s2"> padding: 30px;</span>
<span class="s2"> display: flex; *</span>
<span class="s2"> }</span>
<span class="s2"> .container { </span>
<span class="s2"> width: 100%;</span>
<span class="s2"> margin: auto;</span>
<span class="s2"> background-color: #ffffff;</span>
<span class="s2"> box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);</span>
<span class="s2"> padding: 16px;</span>
<span class="s2"> text-align: center;</span>
<span class="s2"> font-size: 16px;</span>
<span class="s2"> border-radius: 8px;</span>
<span class="s2"> }</span>
<span class="s2"> h1 { </span>
<span class="s2"> font-size: 18px;</span>
<span class="s2"> text-align: center;</span>
<span class="s2"> color: red;</span>
<span class="s2"> }</span>
<span class="s2"> </style></span>
<span class="s2"> </head></span>
<span class="s2"> <div class="container"></span>
<span class="s2"> <h1>Falha na autentica&#231;&#227;o!</h1></span>
<span class="s2"> Esta p&#225;gina ser&#225; fechada automaticamente.<br></span>
<span class="s2"> Se isto n&#227;o acontecer, pode fech&#225;-la manualmente.</span>
<span class="s2"> </div></span>
<span class="s2"> </body></html></span>
<span class="s2"> """</span><span class="p">)</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="c1"># Inicializa o servidor HTTP</span>
<span class="bp">self</span><span class="o">.</span><span class="n">server</span> <span class="o">=</span> <span class="n">HTTPServer</span><span class="p">((</span><span class="s1">'localhost'</span><span class="p">,</span> <span class="mi">8000</span><span class="p">),</span> <span class="n">AuthHandler</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">server</span><span class="o">.</span><span class="n">logger</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span> <span class="c1"># Passa o logger para o servidor</span>
<span class="c1"># Função para monitorar o tempo limite</span>
<span class="k">def</span> <span class="nf">monitor_timeout</span><span class="p">():</span>
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">timeout</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">server</span><span class="p">,</span> <span class="s1">'auth_code'</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">response</span> <span class="o">=</span> <span class="s2">"tempo limite para autenticação foi excedido"</span>
<span class="bp">self</span><span class="o">.</span><span class="n">status_code</span> <span class="o">=</span> <span class="mi">490</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">response</span><span class="p">)</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span> <span class="o">=</span> <span class="n">original_stdout</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stderr</span> <span class="o">=</span> <span class="n">original_stderr</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Código retorno: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">status_code</span><span class="si">}</span><span class="s1"> '</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s1">''</span><span class="p">)</span> <span class="c1">## self.status_code = 200, usuário pertence ao grupo informado. self.status_code = 299, grupo existe mas usuário NÃO pertence à ele. Erros retornam 4xx.</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Resposta: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">response</span><span class="si">}</span><span class="s1">'</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s1">'</span><span class="se">\n\n</span><span class="s1">'</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'Falha na autenticação! Execução abortada!'</span><span class="p">)</span>
<span class="n">driver</span><span class="o">.</span><span class="n">quit</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">server</span><span class="o">.</span><span class="n">server_close</span><span class="p">()</span>
<span class="n">os</span><span class="o">.</span><span class="n">_exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="c1"># Inicia a thread para monitorar o tempo limite</span>
<span class="n">timeout_thread</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">monitor_timeout</span><span class="p">)</span>
<span class="n">timeout_thread</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
<span class="c1"># Espera pelo código de autorização</span>
<span class="bp">self</span><span class="o">.</span><span class="n">response</span> <span class="o">=</span> <span class="s2">"Esperando pela autenticação..."</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">response</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">server</span><span class="o">.</span><span class="n">handle_request</span><span class="p">()</span>
<span class="c1"># Restaura stdout e stderr</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span> <span class="o">=</span> <span class="n">original_stdout</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stderr</span> <span class="o">=</span> <span class="n">original_stderr</span>
<span class="c1"># Verifica se o código de autorização foi obtido dentro do tempo limite</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">server</span><span class="p">,</span> <span class="s1">'auth_code'</span><span class="p">):</span>
<span class="k">return</span>
<span class="c1"># Obtém o código de autorização e o estado capturados pelo servidor HTTP</span>
<span class="n">auth_code</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">server</span><span class="o">.</span><span class="n">auth_code</span>
<span class="n">state</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">server</span><span class="o">.</span><span class="n">state</span>
<span class="c1"># Adquire o token usando o código de autorização, verificando o estado</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">app</span><span class="o">.</span><span class="n">acquire_token_by_auth_code_flow</span><span class="p">(</span><span class="n">flow</span><span class="p">,</span> <span class="p">{</span><span class="s2">"code"</span><span class="p">:</span> <span class="n">auth_code</span><span class="p">,</span> <span class="s2">"state"</span><span class="p">:</span> <span class="n">state</span><span class="p">})</span>
<span class="k">except</span> <span class="ne">ValueError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">response</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"Erro ao obter o token de acesso: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">"</span>
<span class="bp">self</span><span class="o">.</span><span class="n">status_code</span> <span class="o">=</span> <span class="mi">401</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">response</span><span class="p">)</span>
<span class="n">driver</span><span class="o">.</span><span class="n">quit</span><span class="p">()</span>
<span class="k">return</span>
<span class="k">if</span> <span class="s2">"access_token"</span> <span class="ow">in</span> <span class="n">result</span><span class="p">:</span>
<span class="n">access_token</span> <span class="o">=</span> <span class="n">result</span><span class="p">[</span><span class="s1">'access_token'</span><span class="p">]</span>
<span class="n">headers</span> <span class="o">=</span> <span class="p">{</span>
<span class="s1">'Authorization'</span><span class="p">:</span> <span class="s1">'Bearer '</span> <span class="o">+</span> <span class="n">access_token</span>
<span class="p">}</span>
<span class="c1"># Obtém o email do usuário autenticado</span>
<span class="n">me_response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span>
<span class="s1">'https://graph.microsoft.com/v1.0/me'</span><span class="p">,</span>
<span class="n">headers</span><span class="o">=</span><span class="n">headers</span>
<span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">status_code</span> <span class="o">=</span> <span class="n">me_response</span><span class="o">.</span><span class="n">status_code</span>
<span class="k">if</span> <span class="n">me_response</span><span class="o">.</span><span class="n">status_code</span> <span class="o">==</span> <span class="mi">200</span><span class="p">:</span>
<span class="n">me_data</span> <span class="o">=</span> <span class="n">me_response</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
<span class="n">user_email</span> <span class="o">=</span> <span class="n">me_data</span><span class="p">[</span><span class="s1">'userPrincipalName'</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">response</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"Email do usuário autenticado: </span><span class="si">{</span><span class="n">user_email</span><span class="si">}</span><span class="s2">"</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">response</span><span class="p">)</span>
<span class="c1"># Verifica se o usuário pertence ao grupo</span>
<span class="n">group_name</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">grupo</span>
<span class="c1"># Obtém o ID do usuário</span>
<span class="n">user_response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span>
<span class="sa">f</span><span class="s1">'https://graph.microsoft.com/v1.0/users/</span><span class="si">{</span><span class="n">user_email</span><span class="si">}</span><span class="s1">'</span><span class="p">,</span>
<span class="n">headers</span><span class="o">=</span><span class="n">headers</span>
<span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">status_code</span> <span class="o">=</span> <span class="n">user_response</span><span class="o">.</span><span class="n">status_code</span>
<span class="k">if</span> <span class="n">user_response</span><span class="o">.</span><span class="n">status_code</span> <span class="o">==</span> <span class="mi">200</span><span class="p">:</span>
<span class="n">user_data</span> <span class="o">=</span> <span class="n">user_response</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
<span class="n">user_id</span> <span class="o">=</span> <span class="n">user_data</span><span class="p">[</span><span class="s1">'id'</span><span class="p">]</span>
<span class="c1"># Pesquisa o grupo pelo nome</span>
<span class="n">group_response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span>
<span class="sa">f</span><span class="s2">"https://graph.microsoft.com/v1.0/groups?$filter=displayName eq '</span><span class="si">{</span><span class="n">group_name</span><span class="si">}</span><span class="s2">'"</span><span class="p">,</span>
<span class="n">headers</span><span class="o">=</span><span class="n">headers</span>
<span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">status_code</span> <span class="o">=</span> <span class="n">group_response</span><span class="o">.</span><span class="n">status_code</span>
<span class="k">if</span> <span class="n">group_response</span><span class="o">.</span><span class="n">status_code</span> <span class="o">==</span> <span class="mi">200</span><span class="p">:</span>
<span class="n">group_data</span> <span class="o">=</span> <span class="n">group_response</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
<span class="k">if</span> <span class="s1">'value'</span> <span class="ow">in</span> <span class="n">group_data</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">group_data</span><span class="p">[</span><span class="s1">'value'</span><span class="p">])</span> <span class="o">></span> <span class="mi">0</span><span class="p">:</span>
<span class="n">group_id</span> <span class="o">=</span> <span class="n">group_data</span><span class="p">[</span><span class="s1">'value'</span><span class="p">][</span><span class="mi">0</span><span class="p">][</span><span class="s1">'id'</span><span class="p">]</span>
<span class="c1"># Verifica se o usuário está no grupo</span>
<span class="n">members_response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span>
<span class="sa">f</span><span class="s1">'https://graph.microsoft.com/v1.0/groups/</span><span class="si">{</span><span class="n">group_id</span><span class="si">}</span><span class="s1">/members'</span><span class="p">,</span>
<span class="n">headers</span><span class="o">=</span><span class="n">headers</span>
<span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">status_code</span> <span class="o">=</span> <span class="n">members_response</span><span class="o">.</span><span class="n">status_code</span>
<span class="k">if</span> <span class="n">members_response</span><span class="o">.</span><span class="n">status_code</span> <span class="o">==</span> <span class="mi">200</span><span class="p">:</span>
<span class="n">members_data</span> <span class="o">=</span> <span class="n">members_response</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
<span class="k">if</span> <span class="s1">'value'</span> <span class="ow">in</span> <span class="n">members_data</span><span class="p">:</span>
<span class="n">user_in_group</span> <span class="o">=</span> <span class="nb">any</span><span class="p">(</span><span class="n">member</span><span class="p">[</span><span class="s1">'id'</span><span class="p">]</span> <span class="o">==</span> <span class="n">user_id</span> <span class="k">for</span> <span class="n">member</span> <span class="ow">in</span> <span class="n">members_data</span><span class="p">[</span><span class="s1">'value'</span><span class="p">])</span>
<span class="k">if</span> <span class="n">user_in_group</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">response</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"O usuário </span><span class="si">{</span><span class="n">user_email</span><span class="si">}</span><span class="s2"> liberado para uso desta aplicação."</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">response</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"O usuário </span><span class="si">{</span><span class="n">user_email</span><span class="si">}</span><span class="s2"> NÃO liberado para uso desta aplicação. Solicite acesso à TI."</span>
<span class="bp">self</span><span class="o">.</span><span class="n">status_code</span> <span class="o">=</span> <span class="mi">299</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">response</span> <span class="o">=</span> <span class="s2">"Resposta da API de membros não contém a chave 'value'."</span>
<span class="bp">self</span><span class="o">.</span><span class="n">status_code</span> <span class="o">=</span> <span class="mi">460</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">response</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"Erro na resposta da API de membros: </span><span class="si">{</span><span class="n">members_response</span><span class="o">.</span><span class="n">status_code</span><span class="si">}</span><span class="s2">"</span>
<span class="bp">self</span><span class="o">.</span><span class="n">response</span> <span class="o">+=</span> <span class="sa">f</span><span class="s2">"</span><span class="se">\n</span><span class="si">{</span><span class="n">members_response</span><span class="o">.</span><span class="n">json</span><span class="p">()</span><span class="si">}</span><span class="s2">"</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">response</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"Grupo '</span><span class="si">{</span><span class="n">group_name</span><span class="si">}</span><span class="s2">' não encontrado."</span>
<span class="bp">self</span><span class="o">.</span><span class="n">status_code</span> <span class="o">=</span> <span class="mi">470</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">response</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"Erro na resposta da API de grupos: </span><span class="si">{</span><span class="n">group_response</span><span class="o">.</span><span class="n">status_code</span><span class="si">}</span><span class="s2">"</span>
<span class="bp">self</span><span class="o">.</span><span class="n">response</span> <span class="o">+=</span> <span class="sa">f</span><span class="s2">"</span><span class="se">\n</span><span class="si">{</span><span class="n">group_response</span><span class="o">.</span><span class="n">json</span><span class="p">()</span><span class="si">}</span><span class="s2">"</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">response</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"Erro na resposta da API de usuário: </span><span class="si">{</span><span class="n">user_response</span><span class="o">.</span><span class="n">status_code</span><span class="si">}</span><span class="s2">"</span>
<span class="bp">self</span><span class="o">.</span><span class="n">response</span> <span class="o">+=</span> <span class="sa">f</span><span class="s2">"</span><span class="se">\n</span><span class="si">{</span><span class="n">user_response</span><span class="o">.</span><span class="n">json</span><span class="p">()</span><span class="si">}</span><span class="s2">"</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">response</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"Erro ao obter informações do usuário: </span><span class="si">{</span><span class="n">me_response</span><span class="o">.</span><span class="n">status_code</span><span class="si">}</span><span class="s2">"</span>
<span class="bp">self</span><span class="o">.</span><span class="n">response</span> <span class="o">+=</span> <span class="sa">f</span><span class="s2">"</span><span class="se">\n</span><span class="si">{</span><span class="n">me_response</span><span class="o">.</span><span class="n">json</span><span class="p">()</span><span class="si">}</span><span class="s2">"</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">response</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"Erro ao obter o token de acesso: </span><span class="si">{</span><span class="n">result</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'error'</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span>
<span class="bp">self</span><span class="o">.</span><span class="n">response</span> <span class="o">+=</span> <span class="sa">f</span><span class="s2">"</span><span class="se">\n</span><span class="si">{</span><span class="n">result</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'error_description'</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span>
<span class="bp">self</span><span class="o">.</span><span class="n">status_code</span> <span class="o">=</span> <span class="mi">480</span>
<span class="c1"># Fecha o navegador</span>
<span class="n">driver</span><span class="o">.</span><span class="n">quit</span><span class="p">()</span>
<span class="n">service</span><span class="o">.</span><span class="n">stop</span><span class="p">()</span>
<span class="c1"># Define o retorno</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'</span><span class="se">\n</span><span class="s1">Código retorno: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">status_code</span><span class="si">}</span><span class="s1"> '</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s1">''</span><span class="p">)</span> <span class="c1">## self.status_code = 200, usuário pertence ao grupo informado. self.status_code = 299, grupo existe mas usuário NÃO pertence à ele. Erros retornam 4xx.</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Resposta: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">response</span><span class="si">}</span><span class="s1">'</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s1">'</span><span class="se">\n\n</span><span class="s1">'</span><span class="p">)</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">status_code</span> <span class="o">==</span> <span class="mi">200</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'Acesso autorizado!'</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'Permissões inválidas! Execução abortada!'</span><span class="p">)</span>
<span class="n">os</span><span class="o">.</span><span class="n">_exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">disclaimer</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="c1"># Mostra o aviso do funcionamento e necessidade de autenticação</span>
<span class="nb">input</span><span class="p">(</span><span class="sa">f</span><span class="s2">"""</span>
<span class="s2"> Para ser utilizado de forma adequada e segura, este script requer autenticação no Microsoft Entra ID (antiga Azure AD).</span>
<span class="s2"> Também requer que seu usuário pertença a um grupo de segurança específico. Se você não tem a segurança que tem permissão de uso, solicite previamente à TI.</span>
<span class="s2"> Para continuar, é necessário fornecer suas credenciais, aquelas que costumeiramente utiliza para acessar os serviços de e-mail corporativo.</span>
<span class="s2"> Uma janela de navegador será aberta e você será direcionado à tela de Logon do Microsoft Entra ID.</span>
<span class="s2"> Faça o Logon fornecendo usuário, senha e validação de duplo fator (no autenticador da Microsoft, instalado em seu celular). </span>
<span class="s2"> Após a autenticação, a janela do navegador será fechada e o script iniciará o processo de execução.</span>
<span class="s2"> Você tem </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">timeout</span><span class="si">}</span><span class="s2"> segundos para realizar a autenticação ou a execução será abortada.</span>
<span class="s2"> Tecle [ENTER] para continuar ...</span>
<span class="s2"> """</span><span class="p">)</span>
</code></pre></div></td></tr></table></div>
</details>
<div class="doc doc-children">
</div>
</div>
</div>
<div class="doc doc-object doc-class">
<h2 id="lbxtoolkit.lbx_logger" class="doc doc-heading">
<code>lbx_logger</code>
</h2>
<div class="doc doc-contents ">
<h6 id="lbxtoolkit.lbx_logger--classe-lbx_logger">Classe <strong>lbx_logger</strong></h6>
<p>Essa classe requer a importação do módulo <code>logging</code> no script em que for instanciada e tem o propósito de manipular/formatar as mensagens de saída do script, alterando o formato e redirecionando destino padrão (stdout e stderr) para uma combinação de tela e/ou arquivo.</p>
<p>O comportamento padrão é registrar todas as saídas <em>simultaneamente</em> em tela e no arquivo com endereço informado no parâmetro <code>log_file_path</code>. Se este parametro for omisso no instanciamento da classe, as mensagens serão exibidas apenas na tela.</p>
<p>A mensagens devem ser classificadas por grau de severidade/relevância, da menor para a maior, na seguinte ordem: <em>debug, info, warning (aviso), error (erro), critical (critico)</em></p>
<p>A classificação do nível de serveridade da mensagem se dá pelo método escolhido para invocar a mensagem, correspondente aos níveis de severidade equivalentes.</p>
<p>A classe deve ser instanciada conforme sintaxe abaixo:</p>
<p><code>lbx_logger(log_file_path=None, log_level=logging.DEBUG, formato_log='%(asctime)s - %(levelname)s - %(message)s', modulo=None, ignore_console=None, ignore_file=None):</code></p>
<p>Todos os parametros são nominativos e facultativos. Em caso de omissão, os valores padrão são assumidos conforme o exemplo acima.</p>
<p>Os parametros para o instanciamento da classe são:</p>
<ul>
<li><code>log_file_path</code> Define o caminho e o nome do arquivo de log. Se omisso, as mensagens serão todas direcionadas apenas para a tela.</li>
<li><code>log_level</code> Define o nível mínimo de severidade das mensagens a serem manipuladas pelo logger. Se omisso, será assumido o nível mais baixo (<em>debug</em>). As mensagens com nível abaixo do especificado são descartadas. Os níveis devem ser informados de acordo com a sintaxe acima (prefixados com <em>logging.</em> e com o nome do nível em inglês e maiúsculas). Exemplo: </li>
<li><code>logging.DEBUG</code> para manipular chamadas do método <em>.debug()</em> e acima.</li>
<li><code>logging.INFO</code> para manipular chamadas do método <em>.info()</em> e acima.</li>
<li><code>logging.WARNING</code> para manipular chamadas do método <em>.aviso()</em> e acima.</li>
<li><code>logging.ERROR</code> para manipular chamadas do método <em>.erro()</em> e acima.</li>
<li><code>logging.CRITICAL</code> para manipular chamadas do método <em>.critico()</em> e acima. </li>
<li><code>formato_log</code> Define o formato em que a mensagem será apresentada. Se omisso, o padrá é <em>DATA_HORA - NIVEL - MENSAGEM</em>. Para maiores opções veja: <a href="https://docs.python.org/3/library/logging.html#logrecord-attributes">Atributos de log</a></li>
<li><code>modulo</code> Nome do módulo para o qual os logs serão monitorados. Permite instanciar várias vezes a classe para criar manipuladores diferentes para módulos diferente. Informe o nome do módulo para criar um log específico para ele ou simplesmente omita o parametro para criar um log para o script em geral.</li>
<li><code>ignore_console</code> Lista com os níveis de severidade a serem ignorados para <em>apresentação na tela</em>, registrando <em>apenas no arquivo</em> (quando informado no parametro <code>log_file_path</code>) e obedecendo ao nível mínimo estabelecido no parametro <code>log_level</code>. Note que omitir o parametro <code>log_file_path</code> e incluir um nível na lsita <code>ignore_console</code> implica em ignorar/suprimir esse nível de mensagem de qualquer apresentação.</li>
<li><code>ignore_file</code> Mesma lógica do parametro <code>ignore_console</code>, mas com lógica invertida: suprime o registro do nível do arquivo e demonstra <em>apenas na tela</em>.</li>
</ul>
<p>1) As mensagem são manipuladas substituindo-se o comando <code>print()</code> pela chamada a um dos 5 métodos acima (<em>.add(), .debug(), .info(), .aviso(), .erro(), .critico()</em>). Exceto o método <code>.add()</code>, qualquer um dos demais métodos pode interromper a execução do script, através da passagem do parâmetro <code>exit</code>. Ao informar esse parametro na chamadada do método, atribua a ele o código de saída desejado (0 para normal, qualquer outro número para saída com erro). Exemplo:</p>
<pre><code>log.erro('Essa mensagem apenas resulta em uma mensagem de nível ERROR')
log.erro('Essa mensagem resulta em uma mensagem de nível ERRO e encerra o script com código de retorno -1', exit=-1)
</code></pre>
<p>Qualquer chamada ao comando <code>print()</code>, uma vez instanciado manipulador de log, será registada como uma chamada ao método <em>.info()</em> e registrada com este nível de severidade.
Para retornar ao comportamente padrão do comando print, ou interromper o manipulador, faça chamada ao método <code>.stop_logging()</code></p>
<p>2) O método <em>.add()</em> não exibe/grava imediatamente a mensagem, mas apenas a diciona a <em>buffer</em>. Todas as chamas a <em>.add()</em> irão concatenar a mensagem recebida até a próxima chamada em algum dos níveis <em>.debug(), .info(), .aviso(), .erro(), .critico()</em>. Na primeira chama de um destes níveis após uma (ou mais) chamada(s) ao método <em>.add()</em> o <em>buffer</em> será concatenado à mensagem recebida por um destes métodos e o resultado será manipulado pelo log conforme os parametros definidos no intanciamento da classe e o método chamado. Essa função é útil para tratar mensagens com retorno condicional. Exemplo:</p>
<pre><code>log.add('Mensagem 1# ') ## não será exibida/registrada
log.add('Mensagem 2# ') ## não será exibida/registrada
log.info('Mensagem 3) ## será exibida/registrada como nível "info" e com texto: "Mensagem 1# Mensagem 2# Mensagem 3"
</code></pre>
<p>3) Os métodos que exibem as mensagens (<code>.debug()</code>,<code>.info()</code>,<code>.aviso()</code>, <code>.erro()</code>, <code>.critico()</code>) possuem 3 parametros: <code>message</code>, <code>corte=None</code>, <code>exit=None</code>.</p>
<ul>
<li><code>message</code>: posicional e obrigatório. corresponde à mensagem a ser exibida</li>
<li><code>corte</code>: o tamanho máximo da mensagem a ser exibida. opcional e se omitido, exibe a mensagem inteira. se fornecido, corta a mensagem no comprimento informado</li>
<li><code>exit</code>: opcional. se informado (requer um código de retorno), aborta o script com o código informado. se omisso (padrão) a mensagem apenas é minutada pelo log, sem interferir no funcionamento do script</li>
</ul>
<p>4) O método <code>.filtra()</code> possui 3 parametros posicionais, todos opcionais: <code>log_file</code>, <code>dh_ini</code>, <code>dh_fim</code>.</p>
<p>Se os 3 forem omitidos, serão exibidas as entradas de log do arquivo corrente, definido no instanciamento da classe <code>lbx_logger</code>, registradas na última hora. Deste modo, o valor padrão para <code>dh_fim</code> é <code>now()</code> e para <code>dh_ini</code> é <code>now()</code> menos 1 hora.</p>
<p>Caso queira filtrar os registro de outro arquivo de log, que não seja o do script corrente, informe o endereço do arquivo no primeiro parametro.</p>
<p>E caso queira alterar alterar o período de filtragem, informe nos parametros 2 e 3 a data/hora de início e fim do período. Estes dois parametros aceitam tanto um objeto do tipo <code>datetime</code> como uma string (que será convertida para datetime), desde que ela esteja no formato <code>dd/mm/aaaa hh:mm:[ss]</code> (segundos são opcionais).</p>
<p>Considerando que os parametros são posicionais, caso queira omitir apenas um dos parametros, preencha a posição do parametro a ser omitido com <code>None</code>.</p>
<p>A saída dessa função retorna um objeto, que pode ser salvo em disco ou impresso na tela.</p>
<p>5) Exemplos de uso:</p>
<pre><code>from lbx_toolkit import lbx_logger
import logging
import os
from pathlib import Path
DirBase = Path('./') # diretório corrente do script
BaseName = os.path.splitext(os.path.basename(__file__))[0] # nome do script sem extensão
LogFile = Path(DirBase, BaseName + '.log') # salva logs no diretório corrente, em um arquivo nomeado com nome do script + extensão ".log"
### instancia o manipulador para tratar todas as mensagens (nível DEBUG acima),
# mas suprime a apresentação em tela das mensagens de nível "DEBUG" na tela,
# apenas registrando-as somente no arquivo
# e sumprime o registro no arquivo das mensagens de nível "ERROR",
# mostrando-as apenas na tela
log = lbx_logger(LogFile, logging.DEBUG, ignore_console=[logging.DEBUG], ignore_file=[logging.ERROR])
# Exemplo de mensagens de log
log.debug('Esta é uma mensagem de debug')
log.info('Esta é uma mensagem informativa')
log.add('Esta mensagem não será exibida agora, mas acumulada no buffer# ')
log.aviso('Esta é uma mensagem de aviso')
log.erro('Esta é uma mensagem de erro')
log.erro('Esta é uma mensagem erro muito comprida e será limitada a 40 caracteres, o restante será cortado e ingorado ao ser manipulado', 40)
log.critico('Esta é uma mensagem crítica')
# Exemplo de função que gera uma exceção
def funcao_com_erro():
raise ValueError('Este é um erro de exemplo')
# Testando redirecionamento de print e captura de exceção
print('Mensagem de teste via print')
try:
funcao_com_erro()
except Exception as e:
print(f'Capturado um erro: {e}')
log.erro('Essa é uma mensagem de erro e abortará a execução do script', exit=1)
log.info('Essa mensagem não será exibida pois o script foi abortado na mensagem anterior')
# obtem os registros de log da última hora (comportamento padrão)
filtra_log = log.search()
# obtem os registros das últimas 6 horas
ultimas_6h = datetime.datetime.now() - datetime.timedelta(hours=6) ## carimbo de tempo de 6 horas atrás !!! requer>> import datetime
filtra_log = log.search(None, ultimas_6h) # None no 1º parametro impõe o log do arquivo corrente como padrão (definido em 'LogFile' e apontado no instanciamento da classe)
# obtem os registros do dia 14/01/2020 até 3h atrás
ultimas_3h = datetime.datetime.now() - datetime.timedelta(hours=3) ## carimbo de tempo de 6 horas atrás !!! requer>> import datetime
filtra_log = log.search(None, '14/01/2020 00:00', ultimas_3h) #
# obtem os registros do horário comercial do dia 23/12/2023 do arquivo salvo em C:\temp\outro_arquivo.log
Outro_Log = Path(r'c:\temp\outro_arquivo.log')
filtra_log = log.search(Outro_Log, '23/12/2023 08:00', '23/12/2023 18:00') #
# salva conteúdo filtrado em um arquivo:
filtrado = 'filtered_log.txt'
with open(filtado, 'w', encoding='ISO-8859-1') as output_file: # indique o enconding conforme salvo (UTF-8 ou ISO-8859-1)
output_file.writelines(filta_log)
# mostra o conteúdo filtrado na tela
print(''.join(filtra_log))
# mostra o conteúdo filtrado na tela, listando apenas as os registros do nível "DEBUG"
for line in filtered_lines:
if "DEBUG" in line:
print(line, end='')
</code></pre>
<details class="quote">
<summary>Source code in <code>lbxtoolkit\__init__.py</code></summary>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"> 906</span>
<span class="normal"> 907</span>
<span class="normal"> 908</span>
<span class="normal"> 909</span>
<span class="normal"> 910</span>
<span class="normal"> 911</span>
<span class="normal"> 912</span>
<span class="normal"> 913</span>
<span class="normal"> 914</span>
<span class="normal"> 915</span>
<span class="normal"> 916</span>
<span class="normal"> 917</span>
<span class="normal"> 918</span>
<span class="normal"> 919</span>
<span class="normal"> 920</span>
<span class="normal"> 921</span>
<span class="normal"> 922</span>
<span class="normal"> 923</span>
<span class="normal"> 924</span>
<span class="normal"> 925</span>
<span class="normal"> 926</span>
<span class="normal"> 927</span>
<span class="normal"> 928</span>
<span class="normal"> 929</span>
<span class="normal"> 930</span>
<span class="normal"> 931</span>
<span class="normal"> 932</span>
<span class="normal"> 933</span>
<span class="normal"> 934</span>
<span class="normal"> 935</span>
<span class="normal"> 936</span>
<span class="normal"> 937</span>
<span class="normal"> 938</span>
<span class="normal"> 939</span>
<span class="normal"> 940</span>
<span class="normal"> 941</span>
<span class="normal"> 942</span>
<span class="normal"> 943</span>
<span class="normal"> 944</span>
<span class="normal"> 945</span>
<span class="normal"> 946</span>
<span class="normal"> 947</span>
<span class="normal"> 948</span>
<span class="normal"> 949</span>
<span class="normal"> 950</span>
<span class="normal"> 951</span>
<span class="normal"> 952</span>
<span class="normal"> 953</span>
<span class="normal"> 954</span>
<span class="normal"> 955</span>
<span class="normal"> 956</span>
<span class="normal"> 957</span>
<span class="normal"> 958</span>
<span class="normal"> 959</span>
<span class="normal"> 960</span>
<span class="normal"> 961</span>
<span class="normal"> 962</span>
<span class="normal"> 963</span>
<span class="normal"> 964</span>
<span class="normal"> 965</span>
<span class="normal"> 966</span>
<span class="normal"> 967</span>
<span class="normal"> 968</span>
<span class="normal"> 969</span>
<span class="normal"> 970</span>
<span class="normal"> 971</span>
<span class="normal"> 972</span>
<span class="normal"> 973</span>
<span class="normal"> 974</span>
<span class="normal"> 975</span>
<span class="normal"> 976</span>
<span class="normal"> 977</span>
<span class="normal"> 978</span>
<span class="normal"> 979</span>
<span class="normal"> 980</span>
<span class="normal"> 981</span>
<span class="normal"> 982</span>
<span class="normal"> 983</span>
<span class="normal"> 984</span>
<span class="normal"> 985</span>
<span class="normal"> 986</span>
<span class="normal"> 987</span>
<span class="normal"> 988</span>
<span class="normal"> 989</span>
<span class="normal"> 990</span>
<span class="normal"> 991</span>
<span class="normal"> 992</span>
<span class="normal"> 993</span>
<span class="normal"> 994</span>
<span class="normal"> 995</span>
<span class="normal"> 996</span>
<span class="normal"> 997</span>
<span class="normal"> 998</span>
<span class="normal"> 999</span>
<span class="normal">1000</span>
<span class="normal">1001</span>
<span class="normal">1002</span>
<span class="normal">1003</span>
<span class="normal">1004</span>
<span class="normal">1005</span>
<span class="normal">1006</span>
<span class="normal">1007</span>
<span class="normal">1008</span>
<span class="normal">1009</span>
<span class="normal">1010</span>
<span class="normal">1011</span>
<span class="normal">1012</span>
<span class="normal">1013</span>
<span class="normal">1014</span>
<span class="normal">1015</span>
<span class="normal">1016</span>
<span class="normal">1017</span>
<span class="normal">1018</span>
<span class="normal">1019</span>
<span class="normal">1020</span>
<span class="normal">1021</span>
<span class="normal">1022</span>
<span class="normal">1023</span>
<span class="normal">1024</span>
<span class="normal">1025</span>
<span class="normal">1026</span>
<span class="normal">1027</span>
<span class="normal">1028</span>
<span class="normal">1029</span>
<span class="normal">1030</span>
<span class="normal">1031</span>
<span class="normal">1032</span>
<span class="normal">1033</span>
<span class="normal">1034</span>
<span class="normal">1035</span>
<span class="normal">1036</span>
<span class="normal">1037</span>
<span class="normal">1038</span>
<span class="normal">1039</span>
<span class="normal">1040</span>
<span class="normal">1041</span>
<span class="normal">1042</span>
<span class="normal">1043</span>
<span class="normal">1044</span>
<span class="normal">1045</span>
<span class="normal">1046</span>
<span class="normal">1047</span>
<span class="normal">1048</span>
<span class="normal">1049</span>
<span class="normal">1050</span>
<span class="normal">1051</span>
<span class="normal">1052</span>
<span class="normal">1053</span>
<span class="normal">1054</span>
<span class="normal">1055</span>
<span class="normal">1056</span>
<span class="normal">1057</span>
<span class="normal">1058</span>
<span class="normal">1059</span>
<span class="normal">1060</span>
<span class="normal">1061</span>
<span class="normal">1062</span>
<span class="normal">1063</span>
<span class="normal">1064</span>
<span class="normal">1065</span>
<span class="normal">1066</span>
<span class="normal">1067</span>
<span class="normal">1068</span>
<span class="normal">1069</span>
<span class="normal">1070</span>
<span class="normal">1071</span>
<span class="normal">1072</span>
<span class="normal">1073</span>
<span class="normal">1074</span>
<span class="normal">1075</span>
<span class="normal">1076</span>
<span class="normal">1077</span>
<span class="normal">1078</span>
<span class="normal">1079</span>
<span class="normal">1080</span>
<span class="normal">1081</span>
<span class="normal">1082</span>
<span class="normal">1083</span>
<span class="normal">1084</span>
<span class="normal">1085</span>
<span class="normal">1086</span>
<span class="normal">1087</span>
<span class="normal">1088</span>
<span class="normal">1089</span>
<span class="normal">1090</span>
<span class="normal">1091</span>
<span class="normal">1092</span>
<span class="normal">1093</span>
<span class="normal">1094</span>
<span class="normal">1095</span>
<span class="normal">1096</span>
<span class="normal">1097</span>
<span class="normal">1098</span>
<span class="normal">1099</span>
<span class="normal">1100</span>
<span class="normal">1101</span>
<span class="normal">1102</span>
<span class="normal">1103</span>
<span class="normal">1104</span>
<span class="normal">1105</span>
<span class="normal">1106</span>
<span class="normal">1107</span>
<span class="normal">1108</span>
<span class="normal">1109</span>
<span class="normal">1110</span>
<span class="normal">1111</span>
<span class="normal">1112</span>
<span class="normal">1113</span>
<span class="normal">1114</span>
<span class="normal">1115</span>
<span class="normal">1116</span>
<span class="normal">1117</span>
<span class="normal">1118</span>
<span class="normal">1119</span>
<span class="normal">1120</span>
<span class="normal">1121</span>
<span class="normal">1122</span>
<span class="normal">1123</span>
<span class="normal">1124</span>
<span class="normal">1125</span>
<span class="normal">1126</span>
<span class="normal">1127</span>
<span class="normal">1128</span>
<span class="normal">1129</span>
<span class="normal">1130</span>
<span class="normal">1131</span>
<span class="normal">1132</span>
<span class="normal">1133</span>
<span class="normal">1134</span>
<span class="normal">1135</span>
<span class="normal">1136</span>
<span class="normal">1137</span>
<span class="normal">1138</span>
<span class="normal">1139</span>
<span class="normal">1140</span>
<span class="normal">1141</span>
<span class="normal">1142</span>
<span class="normal">1143</span>
<span class="normal">1144</span>
<span class="normal">1145</span>
<span class="normal">1146</span>
<span class="normal">1147</span>
<span class="normal">1148</span>
<span class="normal">1149</span>
<span class="normal">1150</span>
<span class="normal">1151</span>
<span class="normal">1152</span>
<span class="normal">1153</span>
<span class="normal">1154</span>
<span class="normal">1155</span>
<span class="normal">1156</span>
<span class="normal">1157</span>
<span class="normal">1158</span>
<span class="normal">1159</span>
<span class="normal">1160</span>
<span class="normal">1161</span>
<span class="normal">1162</span>
<span class="normal">1163</span>
<span class="normal">1164</span>
<span class="normal">1165</span>
<span class="normal">1166</span>
<span class="normal">1167</span>
<span class="normal">1168</span>
<span class="normal">1169</span>
<span class="normal">1170</span>
<span class="normal">1171</span>
<span class="normal">1172</span>
<span class="normal">1173</span>
<span class="normal">1174</span>
<span class="normal">1175</span>
<span class="normal">1176</span>
<span class="normal">1177</span>
<span class="normal">1178</span>
<span class="normal">1179</span>
<span class="normal">1180</span>
<span class="normal">1181</span>
<span class="normal">1182</span>
<span class="normal">1183</span>
<span class="normal">1184</span>
<span class="normal">1185</span>
<span class="normal">1186</span>
<span class="normal">1187</span>
<span class="normal">1188</span>
<span class="normal">1189</span>
<span class="normal">1190</span>
<span class="normal">1191</span>
<span class="normal">1192</span>
<span class="normal">1193</span>
<span class="normal">1194</span>
<span class="normal">1195</span>
<span class="normal">1196</span>
<span class="normal">1197</span>
<span class="normal">1198</span>
<span class="normal">1199</span>
<span class="normal">1200</span>
<span class="normal">1201</span>
<span class="normal">1202</span>
<span class="normal">1203</span>
<span class="normal">1204</span>
<span class="normal">1205</span>
<span class="normal">1206</span>
<span class="normal">1207</span>
<span class="normal">1208</span>
<span class="normal">1209</span>
<span class="normal">1210</span>
<span class="normal">1211</span>
<span class="normal">1212</span>
<span class="normal">1213</span>
<span class="normal">1214</span>
<span class="normal">1215</span>
<span class="normal">1216</span>
<span class="normal">1217</span>
<span class="normal">1218</span>
<span class="normal">1219</span>
<span class="normal">1220</span>
<span class="normal">1221</span>
<span class="normal">1222</span>
<span class="normal">1223</span>
<span class="normal">1224</span>
<span class="normal">1225</span>
<span class="normal">1226</span>
<span class="normal">1227</span>
<span class="normal">1228</span>
<span class="normal">1229</span>
<span class="normal">1230</span>
<span class="normal">1231</span>
<span class="normal">1232</span>
<span class="normal">1233</span>
<span class="normal">1234</span>
<span class="normal">1235</span>
<span class="normal">1236</span>
<span class="normal">1237</span>
<span class="normal">1238</span>
<span class="normal">1239</span>
<span class="normal">1240</span>
<span class="normal">1241</span>
<span class="normal">1242</span>
<span class="normal">1243</span>
<span class="normal">1244</span>
<span class="normal">1245</span>
<span class="normal">1246</span>
<span class="normal">1247</span>
<span class="normal">1248</span>
<span class="normal">1249</span>
<span class="normal">1250</span>
<span class="normal">1251</span>
<span class="normal">1252</span>
<span class="normal">1253</span>
<span class="normal">1254</span>
<span class="normal">1255</span>
<span class="normal">1256</span>
<span class="normal">1257</span>
<span class="normal">1258</span>
<span class="normal">1259</span>
<span class="normal">1260</span>
<span class="normal">1261</span>
<span class="normal">1262</span>
<span class="normal">1263</span>
<span class="normal">1264</span>
<span class="normal">1265</span>
<span class="normal">1266</span>
<span class="normal">1267</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">class</span> <span class="nc">lbx_logger</span><span class="p">:</span> <span class="c1"># Classe para gerenciar a saída para log</span>
<span class="w"> </span><span class="sa">r</span><span class="sd">"""</span>
<span class="sd"> #### Classe **lbx_logger**</span>
<span class="sd"> Essa classe requer a importação do módulo `logging` no script em que for instanciada e tem o propósito de manipular/formatar as mensagens de saída do script, alterando o formato e redirecionando destino padrão (stdout e stderr) para uma combinação de tela e/ou arquivo.</span>
<span class="sd"> O comportamento padrão é registrar todas as saídas *simultaneamente* em tela e no arquivo com endereço informado no parâmetro `log_file_path`. Se este parametro for omisso no instanciamento da classe, as mensagens serão exibidas apenas na tela.</span>
<span class="sd"> A mensagens devem ser classificadas por grau de severidade/relevância, da menor para a maior, na seguinte ordem: *debug, info, warning (aviso), error (erro), critical (critico)*</span>
<span class="sd"> A classificação do nível de serveridade da mensagem se dá pelo método escolhido para invocar a mensagem, correspondente aos níveis de severidade equivalentes.</span>
<span class="sd"> A classe deve ser instanciada conforme sintaxe abaixo:</span>
<span class="sd"> `lbx_logger(log_file_path=None, log_level=logging.DEBUG, formato_log='%(asctime)s - %(levelname)s - %(message)s', modulo=None, ignore_console=None, ignore_file=None):`</span>
<span class="sd"> Todos os parametros são nominativos e facultativos. Em caso de omissão, os valores padrão são assumidos conforme o exemplo acima.</span>
<span class="sd"> Os parametros para o instanciamento da classe são:</span>
<span class="sd"> - `log_file_path` Define o caminho e o nome do arquivo de log. Se omisso, as mensagens serão todas direcionadas apenas para a tela.</span>
<span class="sd"> - `log_level` Define o nível mínimo de severidade das mensagens a serem manipuladas pelo logger. Se omisso, será assumido o nível mais baixo (_debug_). As mensagens com nível abaixo do especificado são descartadas. Os níveis devem ser informados de acordo com a sintaxe acima (prefixados com _logging._ e com o nome do nível em inglês e maiúsculas). Exemplo: </span>
<span class="sd"> - `logging.DEBUG` para manipular chamadas do método *.debug()* e acima.</span>
<span class="sd"> - `logging.INFO` para manipular chamadas do método *.info()* e acima.</span>
<span class="sd"> - `logging.WARNING` para manipular chamadas do método *.aviso()* e acima.</span>
<span class="sd"> - `logging.ERROR` para manipular chamadas do método *.erro()* e acima.</span>
<span class="sd"> - `logging.CRITICAL` para manipular chamadas do método *.critico()* e acima. </span>
<span class="sd"> - `formato_log` Define o formato em que a mensagem será apresentada. Se omisso, o padrá é *DATA_HORA - NIVEL - MENSAGEM*. Para maiores opções veja: [Atributos de log](https://docs.python.org/3/library/logging.html#logrecord-attributes)</span>
<span class="sd"> - `modulo` Nome do módulo para o qual os logs serão monitorados. Permite instanciar várias vezes a classe para criar manipuladores diferentes para módulos diferente. Informe o nome do módulo para criar um log específico para ele ou simplesmente omita o parametro para criar um log para o script em geral.</span>
<span class="sd"> - `ignore_console` Lista com os níveis de severidade a serem ignorados para *apresentação na tela*, registrando *apenas no arquivo* (quando informado no parametro `log_file_path`) e obedecendo ao nível mínimo estabelecido no parametro `log_level`. Note que omitir o parametro `log_file_path` e incluir um nível na lsita `ignore_console` implica em ignorar/suprimir esse nível de mensagem de qualquer apresentação.</span>
<span class="sd"> - `ignore_file` Mesma lógica do parametro `ignore_console`, mas com lógica invertida: suprime o registro do nível do arquivo e demonstra *apenas na tela*.</span>
<span class="sd"> 1) As mensagem são manipuladas substituindo-se o comando `print()` pela chamada a um dos 5 métodos acima (_.add(), .debug(), .info(), .aviso(), .erro(), .critico()_). Exceto o método `.add()`, qualquer um dos demais métodos pode interromper a execução do script, através da passagem do parâmetro `exit`. Ao informar esse parametro na chamadada do método, atribua a ele o código de saída desejado (0 para normal, qualquer outro número para saída com erro). Exemplo:</span>
<span class="sd"> ```</span>
<span class="sd"> log.erro('Essa mensagem apenas resulta em uma mensagem de nível ERROR')</span>
<span class="sd"> log.erro('Essa mensagem resulta em uma mensagem de nível ERRO e encerra o script com código de retorno -1', exit=-1)</span>
<span class="sd"> ```</span>
<span class="sd"> Qualquer chamada ao comando `print()`, uma vez instanciado manipulador de log, será registada como uma chamada ao método _.info()_ e registrada com este nível de severidade. </span>
<span class="sd"> Para retornar ao comportamente padrão do comando print, ou interromper o manipulador, faça chamada ao método `.stop_logging()`</span>
<span class="sd"> 2) O método _.add()_ não exibe/grava imediatamente a mensagem, mas apenas a diciona a _buffer_. Todas as chamas a _.add()_ irão concatenar a mensagem recebida até a próxima chamada em algum dos níveis _.debug(), .info(), .aviso(), .erro(), .critico()_. Na primeira chama de um destes níveis após uma (ou mais) chamada(s) ao método _.add()_ o *buffer* será concatenado à mensagem recebida por um destes métodos e o resultado será manipulado pelo log conforme os parametros definidos no intanciamento da classe e o método chamado. Essa função é útil para tratar mensagens com retorno condicional. Exemplo:</span>
<span class="sd"> ```</span>
<span class="sd"> log.add('Mensagem 1# ') ## não será exibida/registrada</span>
<span class="sd"> log.add('Mensagem 2# ') ## não será exibida/registrada</span>
<span class="sd"> log.info('Mensagem 3) ## será exibida/registrada como nível "info" e com texto: "Mensagem 1# Mensagem 2# Mensagem 3"</span>
<span class="sd"> ```</span>
<span class="sd"> 3) Os métodos que exibem as mensagens (`.debug()`,`.info()`,`.aviso()`, `.erro()`, `.critico()`) possuem 3 parametros: `message`, `corte=None`, `exit=None`.</span>
<span class="sd"> - `message`: posicional e obrigatório. corresponde à mensagem a ser exibida</span>
<span class="sd"> - `corte`: o tamanho máximo da mensagem a ser exibida. opcional e se omitido, exibe a mensagem inteira. se fornecido, corta a mensagem no comprimento informado</span>
<span class="sd"> - `exit`: opcional. se informado (requer um código de retorno), aborta o script com o código informado. se omisso (padrão) a mensagem apenas é minutada pelo log, sem interferir no funcionamento do script</span>
<span class="sd"> 4) O método `.filtra()` possui 3 parametros posicionais, todos opcionais: `log_file`, `dh_ini`, `dh_fim`.</span>
<span class="sd"> Se os 3 forem omitidos, serão exibidas as entradas de log do arquivo corrente, definido no instanciamento da classe `lbx_logger`, registradas na última hora. Deste modo, o valor padrão para `dh_fim` é `now()` e para `dh_ini` é `now()` menos 1 hora.</span>
<span class="sd"> Caso queira filtrar os registro de outro arquivo de log, que não seja o do script corrente, informe o endereço do arquivo no primeiro parametro.</span>
<span class="sd"> E caso queira alterar alterar o período de filtragem, informe nos parametros 2 e 3 a data/hora de início e fim do período. Estes dois parametros aceitam tanto um objeto do tipo `datetime` como uma string (que será convertida para datetime), desde que ela esteja no formato `dd/mm/aaaa hh:mm:[ss]` (segundos são opcionais).</span>
<span class="sd"> Considerando que os parametros são posicionais, caso queira omitir apenas um dos parametros, preencha a posição do parametro a ser omitido com `None`.</span>
<span class="sd"> A saída dessa função retorna um objeto, que pode ser salvo em disco ou impresso na tela.</span>
<span class="sd"> 5) Exemplos de uso:</span>
<span class="sd"> ```</span>
<span class="sd"> from lbx_toolkit import lbx_logger </span>
<span class="sd"> import logging</span>
<span class="sd"> import os</span>
<span class="sd"> from pathlib import Path</span>
<span class="sd"> DirBase = Path('./') # diretório corrente do script</span>
<span class="sd"> BaseName = os.path.splitext(os.path.basename(__file__))[0] # nome do script sem extensão</span>
<span class="sd"> LogFile = Path(DirBase, BaseName + '.log') # salva logs no diretório corrente, em um arquivo nomeado com nome do script + extensão ".log"</span>
<span class="sd"> ### instancia o manipulador para tratar todas as mensagens (nível DEBUG acima), </span>
<span class="sd"> # mas suprime a apresentação em tela das mensagens de nível "DEBUG" na tela, </span>
<span class="sd"> # apenas registrando-as somente no arquivo</span>
<span class="sd"> # e sumprime o registro no arquivo das mensagens de nível "ERROR", </span>
<span class="sd"> # mostrando-as apenas na tela</span>
<span class="sd"> log = lbx_logger(LogFile, logging.DEBUG, ignore_console=[logging.DEBUG], ignore_file=[logging.ERROR]) </span>
<span class="sd"> # Exemplo de mensagens de log</span>
<span class="sd"> log.debug('Esta é uma mensagem de debug') </span>
<span class="sd"> log.info('Esta é uma mensagem informativa')</span>
<span class="sd"> log.add('Esta mensagem não será exibida agora, mas acumulada no buffer# ')</span>
<span class="sd"> log.aviso('Esta é uma mensagem de aviso')</span>
<span class="sd"> log.erro('Esta é uma mensagem de erro')</span>
<span class="sd"> log.erro('Esta é uma mensagem erro muito comprida e será limitada a 40 caracteres, o restante será cortado e ingorado ao ser manipulado', 40)</span>
<span class="sd"> log.critico('Esta é uma mensagem crítica')</span>
<span class="sd"> # Exemplo de função que gera uma exceção</span>
<span class="sd"> def funcao_com_erro():</span>
<span class="sd"> raise ValueError('Este é um erro de exemplo')</span>
<span class="sd"> # Testando redirecionamento de print e captura de exceção</span>
<span class="sd"> print('Mensagem de teste via print')</span>
<span class="sd"> try:</span>
<span class="sd"> funcao_com_erro()</span>
<span class="sd"> except Exception as e:</span>
<span class="sd"> print(f'Capturado um erro: {e}')</span>
<span class="sd"> log.erro('Essa é uma mensagem de erro e abortará a execução do script', exit=1)</span>
<span class="sd"> log.info('Essa mensagem não será exibida pois o script foi abortado na mensagem anterior')</span>
<span class="sd"> # obtem os registros de log da última hora (comportamento padrão)</span>
<span class="sd"> filtra_log = log.search() </span>
<span class="sd"> # obtem os registros das últimas 6 horas</span>
<span class="sd"> ultimas_6h = datetime.datetime.now() - datetime.timedelta(hours=6) ## carimbo de tempo de 6 horas atrás !!! requer>> import datetime</span>
<span class="sd"> filtra_log = log.search(None, ultimas_6h) # None no 1º parametro impõe o log do arquivo corrente como padrão (definido em 'LogFile' e apontado no instanciamento da classe)</span>
<span class="sd"> # obtem os registros do dia 14/01/2020 até 3h atrás</span>
<span class="sd"> ultimas_3h = datetime.datetime.now() - datetime.timedelta(hours=3) ## carimbo de tempo de 6 horas atrás !!! requer>> import datetime</span>
<span class="sd"> filtra_log = log.search(None, '14/01/2020 00:00', ultimas_3h) # </span>
<span class="sd"> # obtem os registros do horário comercial do dia 23/12/2023 do arquivo salvo em C:\temp\outro_arquivo.log</span>
<span class="sd"> Outro_Log = Path(r'c:\temp\outro_arquivo.log')</span>
<span class="sd"> filtra_log = log.search(Outro_Log, '23/12/2023 08:00', '23/12/2023 18:00') # </span>
<span class="sd"> # salva conteúdo filtrado em um arquivo:</span>
<span class="sd"> filtrado = 'filtered_log.txt'</span>
<span class="sd"> with open(filtado, 'w', encoding='ISO-8859-1') as output_file: # indique o enconding conforme salvo (UTF-8 ou ISO-8859-1)</span>
<span class="sd"> output_file.writelines(filta_log) </span>
<span class="sd"> # mostra o conteúdo filtrado na tela</span>
<span class="sd"> print(''.join(filtra_log))</span>
<span class="sd"> # mostra o conteúdo filtrado na tela, listando apenas as os registros do nível "DEBUG"</span>
<span class="sd"> for line in filtered_lines:</span>
<span class="sd"> if "DEBUG" in line:</span>
<span class="sd"> print(line, end='')</span>
<span class="sd"> ```</span>
<span class="sd"> """</span>
<span class="k">class</span> <span class="nc">LevelFilter</span><span class="p">(</span><span class="n">logging</span><span class="o">.</span><span class="n">Filter</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">levels_to_ignore</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">levels_to_ignore</span> <span class="o">=</span> <span class="n">levels_to_ignore</span>
<span class="c1">#</span>
<span class="c1"># </span>
<span class="k">def</span> <span class="nf">filter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">record</span><span class="p">):</span>
<span class="k">return</span> <span class="n">record</span><span class="o">.</span><span class="n">levelno</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">levels_to_ignore</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">log_file_path</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">log_level</span><span class="o">=</span><span class="n">logging</span><span class="o">.</span><span class="n">DEBUG</span><span class="p">,</span> <span class="n">formato_log</span><span class="o">=</span><span class="s1">'</span><span class="si">%(asctime)s</span><span class="s1"> - </span><span class="si">%(levelname)s</span><span class="s1"> - </span><span class="si">%(message)s</span><span class="s1">'</span><span class="p">,</span> <span class="n">modulo</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">ignore_console</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">ignore_file</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">ignore_file</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">if</span> <span class="n">ignore_file</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">ignore_file</span>
<span class="bp">self</span><span class="o">.</span><span class="n">ignore_console</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">if</span> <span class="n">ignore_console</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">ignore_console</span>
<span class="bp">self</span><span class="o">.</span><span class="n">modulo</span> <span class="o">=</span> <span class="vm">__name__</span> <span class="k">if</span> <span class="n">modulo</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">modulo</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">modulo</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">setLevel</span><span class="p">(</span><span class="n">log_level</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span> <span class="o">=</span> <span class="s1">''</span>
<span class="bp">self</span><span class="o">.</span><span class="n">log_file_path</span> <span class="o">=</span> <span class="n">log_file_path</span>
<span class="k">if</span> <span class="n">log_file_path</span><span class="p">:</span>
<span class="c1"># Criando um handler para escrever em um arquivo de log</span>
<span class="n">file_handler</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">FileHandler</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">log_file_path</span><span class="p">)</span>
<span class="n">file_handler</span><span class="o">.</span><span class="n">setLevel</span><span class="p">(</span><span class="n">log_level</span><span class="p">)</span> <span class="c1"># Sempre registrar tudo no arquivo</span>
<span class="c1"># Criando um handler para exibir no console</span>
<span class="n">console_handler</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">StreamHandler</span><span class="p">()</span>
<span class="n">console_handler</span><span class="o">.</span><span class="n">setLevel</span><span class="p">(</span><span class="n">log_level</span><span class="p">)</span> <span class="c1"># Registrar DEBUG e acima no console</span>
<span class="c1"># Adicionando filtro para ignorar certos níveis no console e no arquivo</span>
<span class="n">file_handler</span><span class="o">.</span><span class="n">addFilter</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">LevelFilter</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ignore_file</span><span class="p">))</span>
<span class="n">console_handler</span><span class="o">.</span><span class="n">addFilter</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">LevelFilter</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ignore_console</span><span class="p">))</span>
<span class="c1"># Definindo o formato das mensagens de log</span>
<span class="n">formatter</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">Formatter</span><span class="p">(</span><span class="n">formato_log</span><span class="p">)</span>
<span class="n">file_handler</span><span class="o">.</span><span class="n">setFormatter</span><span class="p">(</span><span class="n">formatter</span><span class="p">)</span>
<span class="n">console_handler</span><span class="o">.</span><span class="n">setFormatter</span><span class="p">(</span><span class="n">formatter</span><span class="p">)</span>
<span class="c1"># Adicionando os handlers ao logger</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">addHandler</span><span class="p">(</span><span class="n">file_handler</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">addHandler</span><span class="p">(</span><span class="n">console_handler</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># Tudo direcionado para o console</span>
<span class="n">console_handler</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">StreamHandler</span><span class="p">()</span>
<span class="n">console_handler</span><span class="o">.</span><span class="n">setLevel</span><span class="p">(</span><span class="n">log_level</span><span class="p">)</span> <span class="c1"># Registrar no console</span>
<span class="c1"># Adicionando filtro para ignorar certos níveis no console e no arquivo</span>
<span class="n">console_handler</span><span class="o">.</span><span class="n">addFilter</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">LevelFilter</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ignore_console</span><span class="p">))</span>
<span class="c1"># Definindo o formato das mensagens de log</span>
<span class="n">formatter</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">Formatter</span><span class="p">(</span><span class="n">formato_log</span><span class="p">)</span>
<span class="n">console_handler</span><span class="o">.</span><span class="n">setFormatter</span><span class="p">(</span><span class="n">formatter</span><span class="p">)</span>
<span class="c1"># Adicionando o handler ao logger</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">addHandler</span><span class="p">(</span><span class="n">console_handler</span><span class="p">)</span>
<span class="c1"># Redirecionando exceções para o logger</span>
<span class="n">sys</span><span class="o">.</span><span class="n">excepthook</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">handle_exception</span>
<span class="c1"># Redirecionando saída padrão</span>
<span class="bp">self</span><span class="o">.</span><span class="n">original_stdout</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span> <span class="o">=</span> <span class="bp">self</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">handle_exception</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exc_type</span><span class="p">,</span> <span class="n">exc_value</span><span class="p">,</span> <span class="n">exc_traceback</span><span class="p">):</span>
<span class="k">if</span> <span class="nb">issubclass</span><span class="p">(</span><span class="n">exc_type</span><span class="p">,</span> <span class="ne">KeyboardInterrupt</span><span class="p">):</span>
<span class="n">sys</span><span class="o">.</span><span class="n">__excepthook__</span><span class="p">(</span><span class="n">exc_type</span><span class="p">,</span> <span class="n">exc_value</span><span class="p">,</span> <span class="n">exc_traceback</span><span class="p">)</span>
<span class="k">return</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s2">"Exceção não prevista"</span><span class="p">,</span> <span class="n">exc_info</span><span class="o">=</span><span class="p">(</span><span class="n">exc_type</span><span class="p">,</span> <span class="n">exc_value</span><span class="p">,</span> <span class="n">exc_traceback</span><span class="p">))</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">print</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="c1"># Imprime diretamente na saída padrão</span>
<span class="nb">print</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">,</span> <span class="n">file</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">original_stdout</span><span class="p">)</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">corte</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="n">message</span> <span class="o">=</span> <span class="n">message</span><span class="p">[:</span><span class="n">corte</span><span class="p">]</span> <span class="k">if</span> <span class="n">corte</span> <span class="k">else</span> <span class="n">message</span>
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span> <span class="o">+</span> <span class="n">message</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">message</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span>
<span class="c1">#</span>
<span class="c1"># </span>
<span class="k">def</span> <span class="nf">write</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">):</span>
<span class="k">if</span> <span class="n">message</span><span class="o">.</span><span class="n">strip</span><span class="p">():</span> <span class="c1"># Ignorar mensagens vazias</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="n">message</span><span class="o">.</span><span class="n">strip</span><span class="p">())</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">flush</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">pass</span> <span class="c1"># Método necessário para compatibilidade com sys.stdout</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">debug</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">corte</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">exit</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span> <span class="o">+</span> <span class="n">message</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">message</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span>
<span class="n">msg</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">[:</span><span class="n">corte</span><span class="p">]</span> <span class="k">if</span> <span class="n">corte</span> <span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span> <span class="o">=</span> <span class="s1">''</span>
<span class="k">if</span> <span class="n">exit</span><span class="p">:</span>
<span class="n">os</span><span class="o">.</span><span class="n">_exit</span><span class="p">(</span><span class="n">exit</span><span class="p">)</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">info</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">corte</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">exit</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span> <span class="o">+</span> <span class="n">message</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">message</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span>
<span class="n">msg</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">[:</span><span class="n">corte</span><span class="p">]</span> <span class="k">if</span> <span class="n">corte</span> <span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span> <span class="o">=</span> <span class="s1">''</span>
<span class="k">if</span> <span class="n">exit</span><span class="p">:</span>
<span class="n">os</span><span class="o">.</span><span class="n">_exit</span><span class="p">(</span><span class="n">exit</span><span class="p">)</span>
<span class="c1">#</span>
<span class="c1"># </span>
<span class="k">def</span> <span class="nf">aviso</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">corte</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">exit</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span> <span class="o">+</span> <span class="n">message</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">message</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span>
<span class="n">msg</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">[:</span><span class="n">corte</span><span class="p">]</span> <span class="k">if</span> <span class="n">corte</span> <span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span> <span class="o">=</span> <span class="s1">''</span>
<span class="k">if</span> <span class="n">exit</span><span class="p">:</span>
<span class="n">os</span><span class="o">.</span><span class="n">_exit</span><span class="p">(</span><span class="n">exit</span><span class="p">)</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">erro</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">corte</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">exit</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span> <span class="o">+</span> <span class="n">message</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">message</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span>
<span class="n">msg</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">[:</span><span class="n">corte</span><span class="p">]</span> <span class="k">if</span> <span class="n">corte</span> <span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span> <span class="o">=</span> <span class="s1">''</span>
<span class="k">if</span> <span class="n">exit</span><span class="p">:</span>
<span class="n">os</span><span class="o">.</span><span class="n">_exit</span><span class="p">(</span><span class="n">exit</span><span class="p">)</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">critico</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">corte</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">exit</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span> <span class="o">+</span> <span class="n">message</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">message</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span>
<span class="n">msg</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">[:</span><span class="n">corte</span><span class="p">]</span> <span class="k">if</span> <span class="n">corte</span> <span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">critical</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span> <span class="o">=</span> <span class="s1">''</span>
<span class="k">if</span> <span class="n">exit</span><span class="p">:</span>
<span class="n">os</span><span class="o">.</span><span class="n">_exit</span><span class="p">(</span><span class="n">exit</span><span class="p">)</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">stop_logging</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="c1"># Restaurar o stdout original</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">original_stdout</span>
<span class="c1"># Remover handlers do logger</span>
<span class="n">handlers</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">handlers</span><span class="p">[:]</span>
<span class="k">for</span> <span class="n">handler</span> <span class="ow">in</span> <span class="n">handlers</span><span class="p">:</span>
<span class="n">handler</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">removeHandler</span><span class="p">(</span><span class="n">handler</span><span class="p">)</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">filtra</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">log_file</span><span class="p">,</span> <span class="n">dh_ini</span><span class="p">,</span> <span class="n">dh_fim</span><span class="p">):</span>
<span class="c1"># Validar parametros de entrada</span>
<span class="k">if</span> <span class="n">dh_ini</span><span class="p">:</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">dh_ini</span><span class="p">,</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">re</span><span class="o">.</span><span class="n">fullmatch</span><span class="p">(</span><span class="sa">r</span><span class="s1">'([0-3][0-9]/[0-1][0-2]/[1-2][0-9]</span><span class="si">{3}</span><span class="s1"> [0-2][0-9]\:[0-6][0-9])(\:[0-6][0-9]){0,1}'</span><span class="p">,</span> <span class="n">dh_ini</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Data/Hora início </span><span class="si">{</span><span class="n">dh_ini</span><span class="si">}</span><span class="s1"> em formato inválido. Informe um objeto do tipo "datetime" ou uma string no formato "dd/mm/aaaa hh:mm:[ss]"'</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">None</span>
<span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">dh_ini</span><span class="p">)</span> <span class="o">==</span> <span class="mi">16</span><span class="p">:</span> <span class="c1"># Formato 'dd/mm/yyyy hh:mm'</span>
<span class="n">dh_ini</span> <span class="o">+=</span> <span class="s2">":00"</span>
<span class="k">try</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">inicio</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">dh_ini</span><span class="p">,</span> <span class="s1">'</span><span class="si">%d</span><span class="s1">/%m/%Y %H:%M:%S'</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Data/Hora início </span><span class="si">{</span><span class="n">dh_ini</span><span class="si">}</span><span class="s1"> em formato inválido. Informe um objeto do tipo "datetime" ou uma string no formato "dd/mm/aaaa hh:mm:[ss]"'</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">None</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">inicio</span> <span class="o">=</span> <span class="n">dh_ini</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">inicio</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span> <span class="o">-</span> <span class="n">datetime</span><span class="o">.</span><span class="n">timedelta</span><span class="p">(</span><span class="n">hours</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span> <span class="c1">## assume a última hora como intervalo, se omisso</span>
<span class="k">if</span> <span class="n">dh_fim</span><span class="p">:</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">dh_fim</span><span class="p">,</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">re</span><span class="o">.</span><span class="n">fullmatch</span><span class="p">(</span><span class="sa">r</span><span class="s1">'([0-3][0-9]/[0-1][0-2]/[1-2][0-9]</span><span class="si">{3}</span><span class="s1"> [0-2][0-9]\:[0-6][0-9])(\:[0-6][0-9]){0,1}'</span><span class="p">,</span> <span class="n">dh_ini</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Data/Hora fim </span><span class="si">{</span><span class="n">dh_fim</span><span class="si">}</span><span class="s1"> em formato inválido. Informe um objeto do tipo "datetime" ou uma string no formato "dd/mm/aaaa hh:mm:[ss]"'</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">None</span>
<span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">dh_fim</span><span class="p">)</span> <span class="o">==</span> <span class="mi">16</span><span class="p">:</span> <span class="c1"># Formato 'dd/mm/yyyy hh:mm'</span>
<span class="n">dh_fim</span> <span class="o">+=</span> <span class="s2">":00"</span>
<span class="k">try</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">fim</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">dh_fim</span><span class="p">,</span> <span class="s1">'</span><span class="si">%d</span><span class="s1">/%m/%Y %H:%M:%S'</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Data/Hora fim </span><span class="si">{</span><span class="n">dh_fim</span><span class="si">}</span><span class="s1"> em formato inválido. Informe um objeto do tipo "datetime" ou uma string no formato "dd/mm/aaaa hh:mm:[ss]"'</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">None</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">fim</span> <span class="o">=</span> <span class="n">dh_fim</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">fim</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span> <span class="c1">## assume a última hora como intervalo, se omisso</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">log_file</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">log_file_path</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">critical</span><span class="p">(</span><span class="s1">'Nenhum arquivo de log disponível. Log desta instância configurado apenas para exibição em tela, sem registro em arquivo'</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">None</span>
<span class="k">elif</span> <span class="ow">not</span> <span class="n">log_file</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">log_file_path</span><span class="p">:</span>
<span class="n">log_file_path</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">log_file_path</span>
<span class="k">elif</span> <span class="n">log_file</span><span class="p">:</span>
<span class="k">if</span> <span class="n">Path</span><span class="p">(</span><span class="n">log_file</span><span class="p">)</span><span class="o">.</span><span class="n">is_file</span><span class="p">():</span>
<span class="n">log_file_path</span> <span class="o">=</span> <span class="n">log_file</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">critical</span><span class="p">(</span><span class="sa">f</span><span class="s1">'Arquivo de log </span><span class="si">{</span><span class="n">log_file</span><span class="si">}</span><span class="s1"> não existe!'</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">None</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">critical</span><span class="p">(</span><span class="s1">'Erro validação arquivo de entrada. Abortando!'</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">None</span>
<span class="c1"># Função para verificar se a linha está dentro do intervalo de tempo</span>
<span class="k">def</span> <span class="nf">is_within_time_range</span><span class="p">(</span><span class="n">timestamp</span><span class="p">,</span> <span class="n">dh_inicio</span><span class="p">,</span> <span class="n">dh_fim</span><span class="p">):</span>
<span class="k">return</span> <span class="n">dh_inicio</span> <span class="o"><=</span> <span class="n">timestamp</span> <span class="o"><=</span> <span class="n">dh_fim</span>
<span class="c1"># Ler e filtrar o arquivo de log com a codificação ISO-8859-1</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">log_file_path</span><span class="p">,</span> <span class="s1">'r'</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s1">'ISO-8859-1'</span><span class="p">)</span> <span class="k">as</span> <span class="n">log_file</span><span class="p">:</span>
<span class="n">log_lines</span> <span class="o">=</span> <span class="n">log_file</span><span class="o">.</span><span class="n">readlines</span><span class="p">()</span>
<span class="c1"># Variável para armazenar o último timestamp válido</span>
<span class="n">last_valid_timestamp</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">filtered_lines</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">log_lines</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="c1"># Extraia a data e a hora da linha</span>
<span class="n">timestamp_str</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">split</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s2">" "</span> <span class="o">+</span> <span class="n">line</span><span class="o">.</span><span class="n">split</span><span class="p">()[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">timestamp</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">timestamp_str</span><span class="p">,</span> <span class="s1">'%Y-%m-</span><span class="si">%d</span><span class="s1"> %H:%M:%S,</span><span class="si">%f</span><span class="s1">'</span><span class="p">)</span>
<span class="n">last_valid_timestamp</span> <span class="o">=</span> <span class="n">timestamp</span>
<span class="k">if</span> <span class="n">is_within_time_range</span><span class="p">(</span><span class="n">timestamp</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">inicio</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">fim</span><span class="p">):</span>
<span class="n">filtered_lines</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">line</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="c1"># Caso a linha não tenha um carimbo de tempo, use o último timestamp válido</span>
<span class="k">if</span> <span class="n">last_valid_timestamp</span> <span class="ow">and</span> <span class="n">is_within_time_range</span><span class="p">(</span><span class="n">last_valid_timestamp</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">inicio</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">fim</span><span class="p">):</span>
<span class="n">filtered_lines</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">line</span><span class="p">)</span>
<span class="c1"># Retornar o objeto contendo as linhas filtradas</span>
<span class="k">return</span> <span class="n">filtered_lines</span>
</code></pre></div></td></tr></table></div>
</details>
<div class="doc doc-children">
</div>
</div>
</div>
<div class="doc doc-object doc-class">
<h2 id="lbxtoolkit.misc" class="doc doc-heading">
<code>misc</code>
</h2>
<div class="doc doc-contents ">
<h6 id="lbxtoolkit.misc--classe-misc">Classe <strong>misc</strong></h6>
<p>Classe que reune pequenas funções uteis para agilizar tarefas comuns.</p>
<p>Sintaxe e exemplos de uso. Parametros omissos assume os valores padrão indicados abaixo:</p>
<ul>
<li><code>Arquivo = seleciona_arquivo(DirBase, TiposArquivo=[('Todos os arquivos', '*.*')], Titulo='Selecionar arquivo')</code></li>
<li><code>Diretório = seleciona_dir(DirBase=Path(r'./'), Titulo='Selecionar diretório'):</code></li>
<li><code>NomeLimpo = normaliza('String # SEM Noção!') #>>> string_sem_nocao</code></li>
<li><code>cmd_window = get_cmd_window()</code></li>
<li><code>maximize_console()</code></li>
</ul>
<details class="quote">
<summary>Source code in <code>lbxtoolkit\__init__.py</code></summary>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">1270</span>
<span class="normal">1271</span>
<span class="normal">1272</span>
<span class="normal">1273</span>
<span class="normal">1274</span>
<span class="normal">1275</span>
<span class="normal">1276</span>
<span class="normal">1277</span>
<span class="normal">1278</span>
<span class="normal">1279</span>
<span class="normal">1280</span>
<span class="normal">1281</span>
<span class="normal">1282</span>
<span class="normal">1283</span>
<span class="normal">1284</span>
<span class="normal">1285</span>
<span class="normal">1286</span>
<span class="normal">1287</span>
<span class="normal">1288</span>
<span class="normal">1289</span>
<span class="normal">1290</span>
<span class="normal">1291</span>
<span class="normal">1292</span>
<span class="normal">1293</span>
<span class="normal">1294</span>
<span class="normal">1295</span>
<span class="normal">1296</span>
<span class="normal">1297</span>
<span class="normal">1298</span>
<span class="normal">1299</span>
<span class="normal">1300</span>
<span class="normal">1301</span>
<span class="normal">1302</span>
<span class="normal">1303</span>
<span class="normal">1304</span>
<span class="normal">1305</span>
<span class="normal">1306</span>
<span class="normal">1307</span>
<span class="normal">1308</span>
<span class="normal">1309</span>
<span class="normal">1310</span>
<span class="normal">1311</span>
<span class="normal">1312</span>
<span class="normal">1313</span>
<span class="normal">1314</span>
<span class="normal">1315</span>
<span class="normal">1316</span>
<span class="normal">1317</span>
<span class="normal">1318</span>
<span class="normal">1319</span>
<span class="normal">1320</span>
<span class="normal">1321</span>
<span class="normal">1322</span>
<span class="normal">1323</span>
<span class="normal">1324</span>
<span class="normal">1325</span>
<span class="normal">1326</span>
<span class="normal">1327</span>
<span class="normal">1328</span>
<span class="normal">1329</span>
<span class="normal">1330</span>
<span class="normal">1331</span>
<span class="normal">1332</span>
<span class="normal">1333</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">class</span> <span class="nc">misc</span><span class="p">:</span> <span class="c1"># Classe de miscelâneas</span>
<span class="w"> </span><span class="sd">"""</span>
<span class="sd"> #### Classe **misc**</span>
<span class="sd"> Classe que reune pequenas funções uteis para agilizar tarefas comuns.</span>
<span class="sd"> Sintaxe e exemplos de uso. Parametros omissos assume os valores padrão indicados abaixo:</span>
<span class="sd"> - `Arquivo = seleciona_arquivo(DirBase, TiposArquivo=[('Todos os arquivos', '*.*')], Titulo='Selecionar arquivo')`</span>
<span class="sd"> - `Diretório = seleciona_dir(DirBase=Path(r'./'), Titulo='Selecionar diretório'):`</span>
<span class="sd"> - `NomeLimpo = normaliza('String # SEM Noção!') #>>> string_sem_nocao`</span>
<span class="sd"> - `cmd_window = get_cmd_window()`</span>
<span class="sd"> - `maximize_console()` </span>
<span class="sd"> """</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">pass</span>
<span class="c1">#</span>
<span class="c1"># </span>
<span class="k">def</span> <span class="nf">seleciona_arquivo</span><span class="p">(</span><span class="n">DirBase</span><span class="p">,</span> <span class="n">TiposArquivo</span><span class="o">=</span><span class="p">[(</span><span class="s1">'Todos os arquivos'</span><span class="p">,</span> <span class="s1">'*.*'</span><span class="p">)],</span> <span class="n">Titulo</span><span class="o">=</span><span class="s1">'Selecionar arquivo'</span><span class="p">):</span> <span class="c1"># Picker para selecionar arquivo</span>
<span class="n">root</span> <span class="o">=</span> <span class="n">tk</span><span class="o">.</span><span class="n">Tk</span><span class="p">()</span>
<span class="n">root</span><span class="o">.</span><span class="n">withdraw</span><span class="p">()</span> <span class="c1"># Esconde a janela principal do Tkinter</span>
<span class="n">Arquivo</span> <span class="o">=</span> <span class="n">filedialog</span><span class="o">.</span><span class="n">askopenfilename</span><span class="p">(</span><span class="n">initialdir</span><span class="o">=</span><span class="n">DirBase</span><span class="p">,</span> <span class="n">filetypes</span><span class="o">=</span><span class="n">TiposArquivo</span><span class="p">,</span> <span class="n">title</span><span class="o">=</span><span class="n">Titulo</span><span class="p">)</span>
<span class="n">Arquivo</span> <span class="o">=</span> <span class="n">Path</span><span class="p">(</span><span class="n">Arquivo</span><span class="p">)</span>
<span class="n">root</span><span class="o">.</span><span class="n">destroy</span><span class="p">()</span>
<span class="k">return</span> <span class="n">Arquivo</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">seleciona_dir</span><span class="p">(</span><span class="n">DirBase</span><span class="o">=</span><span class="n">Path</span><span class="p">(</span><span class="sa">r</span><span class="s1">'./'</span><span class="p">),</span> <span class="n">Titulo</span><span class="o">=</span><span class="s1">'Selecionar diretório'</span><span class="p">):</span> <span class="c1"># Picker para selecionar diretório</span>
<span class="n">root</span> <span class="o">=</span> <span class="n">tk</span><span class="o">.</span><span class="n">Tk</span><span class="p">()</span> <span class="c1"># objeto picker (Tkinter)para selecionar arquivos e diretórios</span>
<span class="n">root</span><span class="o">.</span><span class="n">withdraw</span><span class="p">()</span> <span class="c1"># Esconde a janela principal do Tkinter</span>
<span class="n">Diretorio</span> <span class="o">=</span> <span class="n">filedialog</span><span class="o">.</span><span class="n">askdirectory</span><span class="p">(</span><span class="n">initialdir</span><span class="o">=</span><span class="n">DirBase</span><span class="p">,</span> <span class="n">title</span><span class="o">=</span><span class="n">Titulo</span><span class="p">)</span>
<span class="n">Diretorio</span> <span class="o">=</span> <span class="n">Path</span><span class="p">(</span><span class="n">Diretorio</span><span class="p">)</span>
<span class="n">root</span><span class="o">.</span><span class="n">destroy</span><span class="p">()</span>
<span class="k">return</span> <span class="n">Diretorio</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">normaliza</span><span class="p">(</span><span class="n">Original</span><span class="p">):</span> <span class="c1"># Limpa e padroniza nomes</span>
<span class="n">Lixo</span> <span class="o">=</span> <span class="sa">r</span><span class="s1">'/</span><span class="se">\\</span><span class="s1">?%§ªº°`´^~*:|"<>!@#$%¨&*()_+=-[]</span><span class="si">{}</span><span class="s1">"</span><span class="se">\'</span><span class="s1"> '</span>
<span class="n">Normalizar</span> <span class="o">=</span> <span class="n">normalize</span><span class="p">(</span><span class="s1">'NFKD'</span><span class="p">,</span> <span class="n">Original</span><span class="p">)</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">'ASCII'</span><span class="p">,</span> <span class="s1">'ignore'</span><span class="p">)</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">'ASCII'</span><span class="p">)</span>
<span class="n">RemoverLixo</span> <span class="o">=</span> <span class="p">[</span><span class="n">c</span> <span class="k">if</span> <span class="n">c</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">Lixo</span> <span class="k">else</span> <span class="s1">'_'</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">Normalizar</span><span class="p">]</span>
<span class="n">Limpo</span> <span class="o">=</span> <span class="s2">""</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">RemoverLixo</span><span class="p">)</span>
<span class="n">Limpo</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="sa">r</span><span class="s1">'\.(?=.*\.)'</span><span class="p">,</span> <span class="s1">'_'</span><span class="p">,</span> <span class="n">Limpo</span><span class="p">)</span> <span class="c1"># troca todos os pontos por underline</span>
<span class="n">Limpo</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="sa">r</span><span class="s1">'_+'</span><span class="p">,</span> <span class="s1">'_'</span><span class="p">,</span> <span class="n">Limpo</span><span class="p">)</span> <span class="c1"># limpa as reptições do underline</span>
<span class="k">return</span> <span class="n">Limpo</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">get_cmd_window</span><span class="p">():</span> <span class="c1"># Captura a referencia da janela atual para retornar o foco à ela depois de chamar os pickers</span>
<span class="n">pid</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">getpid</span><span class="p">()</span>
<span class="n">windows</span> <span class="o">=</span> <span class="n">gw</span><span class="o">.</span><span class="n">getWindowsWithTitle</span><span class="p">(</span><span class="s2">""</span><span class="p">)</span>
<span class="k">for</span> <span class="n">window</span> <span class="ow">in</span> <span class="n">windows</span><span class="p">:</span>
<span class="k">if</span> <span class="n">window</span><span class="o">.</span><span class="n">title</span> <span class="ow">and</span> <span class="n">window</span><span class="o">.</span><span class="n">visible</span> <span class="ow">and</span> <span class="n">window</span><span class="o">.</span><span class="n">topleft</span><span class="p">:</span>
<span class="k">return</span> <span class="n">window</span>
<span class="k">return</span> <span class="kc">None</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">maximize_console</span><span class="p">():</span> <span class="c1"># Ajustar o buffer de console</span>
<span class="c1"># os.system('mode con: cols=500 lines=100')</span>
<span class="c1"># Obter o handle da janela do console</span>
<span class="n">kernel32</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">WinDLL</span><span class="p">(</span><span class="s1">'kernel32'</span><span class="p">)</span>
<span class="n">user32</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">WinDLL</span><span class="p">(</span><span class="s1">'user32'</span><span class="p">)</span>
<span class="n">hWnd</span> <span class="o">=</span> <span class="n">kernel32</span><span class="o">.</span><span class="n">GetConsoleWindow</span><span class="p">()</span>
<span class="k">if</span> <span class="n">hWnd</span><span class="p">:</span>
<span class="c1"># Definir as dimensões da tela</span>
<span class="n">user32</span><span class="o">.</span><span class="n">ShowWindow</span><span class="p">(</span><span class="n">hWnd</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span> <span class="c1"># 3 = SW_MAXIMIZE </span>
</code></pre></div></td></tr></table></div>
</details>
<div class="doc doc-children">
</div>
</div>
</div>
<div class="doc doc-object doc-class">
<h2 id="lbxtoolkit.postgreSQL" class="doc doc-heading">
<code>postgreSQL</code>
</h2>
<div class="doc doc-contents ">
<h6 id="lbxtoolkit.postgreSQL--classe-postgresql">Classe <strong>postgreSQL</strong></h6>
<p>Recursos de interação com o banco de dados relacional PostgreSQL</p>
<p>1) O método <code>postgreSQl.db()</code> exige que as credenciais e parametros de acesso sejam fornecidas em um <em>dicionário</em> com, ao mínimo, o seguinte formato:</p>
<pre><code>credenciais = {
'dbname': 'NOME_BANCO',
'user': 'USUARIO'',
'password': 'SENHA',
'host': 'IP_OU_DNS_SERVIDOR',
'port': 'PORTA_POSTGRESQL', ## padrão = 5432
}
conexao = postgreSQL.db(credenciais)
</code></pre>
<p>O nome do schema é ser declarado no contexto da query, mas se desejar alterar o schema padrão, adicione <em><code>'options' : '-c search_path=[NOME_SCHEMA]',</code></em> ao dicionário.</p>
<p>Qualquer argumento de conexão previsto no pacote <em>psycopg2</em> são aceitos como entrada no dicionário acima.</p>
<p>2) O método <code>postgreSQl.csv_df()</code> lê arquivo texto do tipo CSV e o converte para o objeto Dataframe do <code>pandas</code>. A assinatura da função exige que se forneça o caminho do arquivo CSV e, opcionalmente o caracter delimitador. Se o caracter demilitador não for informado, será assumido <code>;</code>. Considere usar a função <code>Path</code> para tratar o caminho do arquivo de origem.</p>
<pre><code>from pathlib import Path
arquivo_csv = Path('./diretorio/arquivo_exemplo.csv')
dados = postgreSQL.csv_df(arquivo_csv, CsvDelim=',') # usando vírgula como separador. se omisso, assume ";'
</code></pre>
<p>3) O método <code>postgreSQl.db_insert_df()</code> insere dados a partir de um Dataframe (pandas) em uma tabela do banco com estrutura de colunas equivalente.</p>
<p>A assinatura da função é <code>postgreSQL.db_insert_df([conexao], [dataframe_origem], [tabela_destino], Schema=None, Colunas=None, OnConflict=None)</code></p>
<p>É necessário que os nomes das colunas do dataframe coincidam com o nome das colunas da tabela.
Não há como traduzir/compatibilizar (de-para) nomes de colunas entre o dataframe e a tabela.</p>
<p>Os três primeiros parametros são posicionais e correspondem, respectivamente, (1) ao objeto da conexão com o banco, (2) ao objeto que contém o dataframe e (3) ao nome da tabela de destino.
Assume-se que a tabela pertença ao schema padrão (definido na variável <em>search_path</em> do servidor). Caso a tabela de destino esteja em um <em>schema</em> diferente do padrão, deve-se informar seu nome no parâmetro opcional <code>Schema</code>.</p>
<p>O parametro opcional <code>Colunas</code> espera um objeto do tipo <em>lista</em> que contenha a relação das colunas a serem importadas.
As colunas listadas neste objeto precisam existir nas duas pontas (dataframe e tabela).
Caso seja omisso, todas as colunas do dataframe serão inseridas na tabela. Neste caso, admite-se que haja colunas na tabela que não exitam no dataframe (serão gravadas como NULL), mas o contrário provocará erro. </p>
<p>O último parametro opcional <code>OnConflict</code> espera uma declaração para tratar o que fazer caso o dado a ser inserido já exista na tabela, baseado na cláusula <a href="https://www.postgresql.org/docs/current/sql-insert.html#SQL-ON-CONFLICT"><em>ON CONFLICT</em></a> do comando INSERT. A claúsula deve ser declarada explicita e integralmente nessa variável (clausula, <em>target</em> e <em>action</em>) e não há crítica/validação desse argumento, podendo gerar erros se declarado inconforme com o padrão SQL.</p>
<p>Exemplo de uso:</p>
<pre><code>from lbx_toolkit import postgreSQL
from pathlib import Path
credenciais = {
'dbname': 'NOME_BANCO',
'user': 'USUARIO'',
'password': 'SENHA',
'host': 'IP_OU_DNS_SERVIDOR',
'port': 'PORTA_POSTGRESQL', ## padrão = 5432
}
conexao = postgreSQL.db(credenciais)
arquivo_csv = Path('./diretorio/arquivo_exemplo.csv')
dados = postgreSQL.csv_df(arquivo_csv, CsvDelim=',') # usando vírgula como separador. se omisso, assume ";'
postgreSQL.db_insert_df(conexao, dados, 'teste_table', Schema='meu_esquema', OnConflict='on conflict (coluna_chave_primaria) do nothing')
# conexão com o banco precisa ser fechada explicitamente após a chamada do método, caso não seja mais utilizada:
conexao.close()
</code></pre>
<p>4) O método <code>postgreSQl.db_select()</code> executa consultas no banco de dados e retorna um <code>cursor</code> com o resultado.</p>
<p>A assinatura da função é <code>postgreSQL.db_select([conexao], [query])</code></p>
<p>São permitidas apenas instruções de consulta (podendo serem complexas, por exemplo, com uso de <a href="https://www.postgresql.org/docs/current/queries-with.html">CTE</a>). A presença de outras instruções SQL de manipulação de dados e metadados não são permitidas e abortarão a execução da query, se presentes.</p>
<p>O <code>cursor</code> é fechado no contexto do método, antes do retorno, <em>não podendo</em> ser manipulado após recebido como retorno da função.</p>
<p>A função retorna <em>dois objetos</em>, o primeiro contendo os dados do cursor, o segundo, contendo os nomes das respectivas colunas.</p>
<p>Exemplo de uso:</p>
<pre><code>from lbx_toolkit import postgreSQL
from pathlib import Path
credenciais = {
'dbname': 'NOME_BANCO',
'user': 'USUARIO'',
'password': 'SENHA',
'host': 'IP_OU_DNS_SERVIDOR',
'port': 'PORTA_POSTGRESQL', ## padrão = 5432
}
conexao = postgreSQL.db(credenciais)
query = 'select * from meu_esquema.teste_table'
dados, colunas = postgreSQL.db_select(conexao, query)
conexao.close()
</code></pre>
<p>5) O método <code>postgreSQl.db_update()</code> executa updates no banco</p>
<p>A assinatura da função é <code>postgreSQL.db_update([conexao], [query])</code></p>
<p>São permitidas apenas instruções de update. A presença de outras instruções SQL de manipulação de dados e metadados não são permitidas e abortarão a execução da query.</p>
<p>A função retorna <em>a quantidade de linhas alteradas</em>.</p>
<p>Exemplo de uso:</p>
<pre><code>from lbx_toolkit import postgreSQL
from pathlib import Path
credenciais = {
'dbname': 'NOME_BANCO',
'user': 'USUARIO'',
'password': 'SENHA',
'host': 'IP_OU_DNS_SERVIDOR',
'port': 'PORTA_POSTGRESQL', ## padrão = 5432
}
conexao = postgreSQL.db(credenciais)
query = "update meu_esquema.teste_table set coluna='novo_valor' where pk='chave'"
result = postgreSQL.db_update(conexao, query)
conexao.close()
</code></pre>
<details class="quote">
<summary>Source code in <code>lbxtoolkit\__init__.py</code></summary>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">494</span>
<span class="normal">495</span>
<span class="normal">496</span>
<span class="normal">497</span>
<span class="normal">498</span>
<span class="normal">499</span>
<span class="normal">500</span>
<span class="normal">501</span>
<span class="normal">502</span>
<span class="normal">503</span>
<span class="normal">504</span>
<span class="normal">505</span>
<span class="normal">506</span>
<span class="normal">507</span>
<span class="normal">508</span>
<span class="normal">509</span>
<span class="normal">510</span>
<span class="normal">511</span>
<span class="normal">512</span>
<span class="normal">513</span>
<span class="normal">514</span>
<span class="normal">515</span>
<span class="normal">516</span>
<span class="normal">517</span>
<span class="normal">518</span>
<span class="normal">519</span>
<span class="normal">520</span>
<span class="normal">521</span>
<span class="normal">522</span>
<span class="normal">523</span>
<span class="normal">524</span>
<span class="normal">525</span>
<span class="normal">526</span>
<span class="normal">527</span>
<span class="normal">528</span>
<span class="normal">529</span>
<span class="normal">530</span>
<span class="normal">531</span>
<span class="normal">532</span>
<span class="normal">533</span>
<span class="normal">534</span>
<span class="normal">535</span>
<span class="normal">536</span>
<span class="normal">537</span>
<span class="normal">538</span>
<span class="normal">539</span>
<span class="normal">540</span>
<span class="normal">541</span>
<span class="normal">542</span>
<span class="normal">543</span>
<span class="normal">544</span>
<span class="normal">545</span>
<span class="normal">546</span>
<span class="normal">547</span>
<span class="normal">548</span>
<span class="normal">549</span>
<span class="normal">550</span>
<span class="normal">551</span>
<span class="normal">552</span>
<span class="normal">553</span>
<span class="normal">554</span>
<span class="normal">555</span>
<span class="normal">556</span>
<span class="normal">557</span>
<span class="normal">558</span>
<span class="normal">559</span>
<span class="normal">560</span>
<span class="normal">561</span>
<span class="normal">562</span>
<span class="normal">563</span>
<span class="normal">564</span>
<span class="normal">565</span>
<span class="normal">566</span>
<span class="normal">567</span>
<span class="normal">568</span>
<span class="normal">569</span>
<span class="normal">570</span>
<span class="normal">571</span>
<span class="normal">572</span>
<span class="normal">573</span>
<span class="normal">574</span>
<span class="normal">575</span>
<span class="normal">576</span>
<span class="normal">577</span>
<span class="normal">578</span>
<span class="normal">579</span>
<span class="normal">580</span>
<span class="normal">581</span>
<span class="normal">582</span>
<span class="normal">583</span>
<span class="normal">584</span>
<span class="normal">585</span>
<span class="normal">586</span>
<span class="normal">587</span>
<span class="normal">588</span>
<span class="normal">589</span>
<span class="normal">590</span>
<span class="normal">591</span>
<span class="normal">592</span>
<span class="normal">593</span>
<span class="normal">594</span>
<span class="normal">595</span>
<span class="normal">596</span>
<span class="normal">597</span>
<span class="normal">598</span>
<span class="normal">599</span>
<span class="normal">600</span>
<span class="normal">601</span>
<span class="normal">602</span>
<span class="normal">603</span>
<span class="normal">604</span>
<span class="normal">605</span>
<span class="normal">606</span>
<span class="normal">607</span>
<span class="normal">608</span>
<span class="normal">609</span>
<span class="normal">610</span>
<span class="normal">611</span>
<span class="normal">612</span>
<span class="normal">613</span>
<span class="normal">614</span>
<span class="normal">615</span>
<span class="normal">616</span>
<span class="normal">617</span>
<span class="normal">618</span>
<span class="normal">619</span>
<span class="normal">620</span>
<span class="normal">621</span>
<span class="normal">622</span>
<span class="normal">623</span>
<span class="normal">624</span>
<span class="normal">625</span>
<span class="normal">626</span>
<span class="normal">627</span>
<span class="normal">628</span>
<span class="normal">629</span>
<span class="normal">630</span>
<span class="normal">631</span>
<span class="normal">632</span>
<span class="normal">633</span>
<span class="normal">634</span>
<span class="normal">635</span>
<span class="normal">636</span>
<span class="normal">637</span>
<span class="normal">638</span>
<span class="normal">639</span>
<span class="normal">640</span>
<span class="normal">641</span>
<span class="normal">642</span>
<span class="normal">643</span>
<span class="normal">644</span>
<span class="normal">645</span>
<span class="normal">646</span>
<span class="normal">647</span>
<span class="normal">648</span>
<span class="normal">649</span>
<span class="normal">650</span>
<span class="normal">651</span>
<span class="normal">652</span>
<span class="normal">653</span>
<span class="normal">654</span>
<span class="normal">655</span>
<span class="normal">656</span>
<span class="normal">657</span>
<span class="normal">658</span>
<span class="normal">659</span>
<span class="normal">660</span>
<span class="normal">661</span>
<span class="normal">662</span>
<span class="normal">663</span>
<span class="normal">664</span>
<span class="normal">665</span>
<span class="normal">666</span>
<span class="normal">667</span>
<span class="normal">668</span>
<span class="normal">669</span>
<span class="normal">670</span>
<span class="normal">671</span>
<span class="normal">672</span>
<span class="normal">673</span>
<span class="normal">674</span>
<span class="normal">675</span>
<span class="normal">676</span>
<span class="normal">677</span>
<span class="normal">678</span>
<span class="normal">679</span>
<span class="normal">680</span>
<span class="normal">681</span>
<span class="normal">682</span>
<span class="normal">683</span>
<span class="normal">684</span>
<span class="normal">685</span>
<span class="normal">686</span>
<span class="normal">687</span>
<span class="normal">688</span>
<span class="normal">689</span>
<span class="normal">690</span>
<span class="normal">691</span>
<span class="normal">692</span>
<span class="normal">693</span>
<span class="normal">694</span>
<span class="normal">695</span>
<span class="normal">696</span>
<span class="normal">697</span>
<span class="normal">698</span>
<span class="normal">699</span>
<span class="normal">700</span>
<span class="normal">701</span>
<span class="normal">702</span>
<span class="normal">703</span>
<span class="normal">704</span>
<span class="normal">705</span>
<span class="normal">706</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">class</span> <span class="nc">postgreSQL</span><span class="p">:</span> <span class="c1"># Classe de acesso e interação com banco PostgreSQL</span>
<span class="w"> </span><span class="sd">"""</span>
<span class="sd"> #### Classe **postgreSQL**</span>
<span class="sd"> Recursos de interação com o banco de dados relacional PostgreSQL</span>
<span class="sd"> 1) O método `postgreSQl.db()` exige que as credenciais e parametros de acesso sejam fornecidas em um *dicionário* com, ao mínimo, o seguinte formato:</span>
<span class="sd"> ```</span>
<span class="sd"> credenciais = {</span>
<span class="sd"> 'dbname': 'NOME_BANCO',</span>
<span class="sd"> 'user': 'USUARIO'', </span>
<span class="sd"> 'password': 'SENHA', </span>
<span class="sd"> 'host': 'IP_OU_DNS_SERVIDOR',</span>
<span class="sd"> 'port': 'PORTA_POSTGRESQL', ## padrão = 5432</span>
<span class="sd"> }</span>
<span class="sd"> conexao = postgreSQL.db(credenciais)</span>
<span class="sd"> ```</span>
<span class="sd"> O nome do schema é ser declarado no contexto da query, mas se desejar alterar o schema padrão, adicione *`'options' : '-c search_path=[NOME_SCHEMA]',`* ao dicionário.</span>
<span class="sd"> Qualquer argumento de conexão previsto no pacote *psycopg2* são aceitos como entrada no dicionário acima.</span>
<span class="sd"> 2) O método `postgreSQl.csv_df()` lê arquivo texto do tipo CSV e o converte para o objeto Dataframe do `pandas`. A assinatura da função exige que se forneça o caminho do arquivo CSV e, opcionalmente o caracter delimitador. Se o caracter demilitador não for informado, será assumido `;`. Considere usar a função `Path` para tratar o caminho do arquivo de origem.</span>
<span class="sd"> ```</span>
<span class="sd"> from pathlib import Path</span>
<span class="sd"> arquivo_csv = Path('./diretorio/arquivo_exemplo.csv')</span>
<span class="sd"> dados = postgreSQL.csv_df(arquivo_csv, CsvDelim=',') # usando vírgula como separador. se omisso, assume ";'</span>
<span class="sd"> ```</span>
<span class="sd"> 3) O método `postgreSQl.db_insert_df()` insere dados a partir de um Dataframe (pandas) em uma tabela do banco com estrutura de colunas equivalente.</span>
<span class="sd"> A assinatura da função é `postgreSQL.db_insert_df([conexao], [dataframe_origem], [tabela_destino], Schema=None, Colunas=None, OnConflict=None)`</span>
<span class="sd"> É necessário que os nomes das colunas do dataframe coincidam com o nome das colunas da tabela. </span>
<span class="sd"> Não há como traduzir/compatibilizar (de-para) nomes de colunas entre o dataframe e a tabela.</span>
<span class="sd"> Os três primeiros parametros são posicionais e correspondem, respectivamente, (1) ao objeto da conexão com o banco, (2) ao objeto que contém o dataframe e (3) ao nome da tabela de destino.</span>
<span class="sd"> Assume-se que a tabela pertença ao schema padrão (definido na variável _search_path_ do servidor). Caso a tabela de destino esteja em um _schema_ diferente do padrão, deve-se informar seu nome no parâmetro opcional `Schema`.</span>
<span class="sd"> O parametro opcional `Colunas` espera um objeto do tipo _lista_ que contenha a relação das colunas a serem importadas. </span>
<span class="sd"> As colunas listadas neste objeto precisam existir nas duas pontas (dataframe e tabela).</span>
<span class="sd"> Caso seja omisso, todas as colunas do dataframe serão inseridas na tabela. Neste caso, admite-se que haja colunas na tabela que não exitam no dataframe (serão gravadas como NULL), mas o contrário provocará erro. </span>
<span class="sd"> O último parametro opcional `OnConflict` espera uma declaração para tratar o que fazer caso o dado a ser inserido já exista na tabela, baseado na cláusula [*ON CONFLICT*](https://www.postgresql.org/docs/current/sql-insert.html#SQL-ON-CONFLICT) do comando INSERT. A claúsula deve ser declarada explicita e integralmente nessa variável (clausula, _target_ e _action_) e não há crítica/validação desse argumento, podendo gerar erros se declarado inconforme com o padrão SQL.</span>
<span class="sd"> Exemplo de uso:</span>
<span class="sd"> ```</span>
<span class="sd"> from lbx_toolkit import postgreSQL</span>
<span class="sd"> from pathlib import Path</span>
<span class="sd"> credenciais = {</span>
<span class="sd"> 'dbname': 'NOME_BANCO',</span>
<span class="sd"> 'user': 'USUARIO'', </span>
<span class="sd"> 'password': 'SENHA', </span>
<span class="sd"> 'host': 'IP_OU_DNS_SERVIDOR',</span>
<span class="sd"> 'port': 'PORTA_POSTGRESQL', ## padrão = 5432</span>
<span class="sd"> }</span>
<span class="sd"> conexao = postgreSQL.db(credenciais)</span>
<span class="sd"> arquivo_csv = Path('./diretorio/arquivo_exemplo.csv')</span>
<span class="sd"> dados = postgreSQL.csv_df(arquivo_csv, CsvDelim=',') # usando vírgula como separador. se omisso, assume ";'</span>
<span class="sd"> postgreSQL.db_insert_df(conexao, dados, 'teste_table', Schema='meu_esquema', OnConflict='on conflict (coluna_chave_primaria) do nothing')</span>
<span class="sd"> # conexão com o banco precisa ser fechada explicitamente após a chamada do método, caso não seja mais utilizada:</span>
<span class="sd"> conexao.close()</span>
<span class="sd"> ```</span>
<span class="sd"> 4) O método `postgreSQl.db_select()` executa consultas no banco de dados e retorna um `cursor` com o resultado.</span>
<span class="sd"> A assinatura da função é `postgreSQL.db_select([conexao], [query])`</span>
<span class="sd"> São permitidas apenas instruções de consulta (podendo serem complexas, por exemplo, com uso de [CTE](https://www.postgresql.org/docs/current/queries-with.html)). A presença de outras instruções SQL de manipulação de dados e metadados não são permitidas e abortarão a execução da query, se presentes.</span>
<span class="sd"> O `cursor` é fechado no contexto do método, antes do retorno, *não podendo* ser manipulado após recebido como retorno da função.</span>
<span class="sd"> A função retorna *dois objetos*, o primeiro contendo os dados do cursor, o segundo, contendo os nomes das respectivas colunas.</span>
<span class="sd"> Exemplo de uso:</span>
<span class="sd"> ```</span>
<span class="sd"> from lbx_toolkit import postgreSQL</span>
<span class="sd"> from pathlib import Path</span>
<span class="sd"> credenciais = {</span>
<span class="sd"> 'dbname': 'NOME_BANCO',</span>
<span class="sd"> 'user': 'USUARIO'', </span>
<span class="sd"> 'password': 'SENHA', </span>
<span class="sd"> 'host': 'IP_OU_DNS_SERVIDOR',</span>
<span class="sd"> 'port': 'PORTA_POSTGRESQL', ## padrão = 5432</span>
<span class="sd"> }</span>
<span class="sd"> conexao = postgreSQL.db(credenciais)</span>
<span class="sd"> query = 'select * from meu_esquema.teste_table'</span>
<span class="sd"> dados, colunas = postgreSQL.db_select(conexao, query)</span>
<span class="sd"> conexao.close()</span>
<span class="sd"> ```</span>
<span class="sd"> 5) O método `postgreSQl.db_update()` executa updates no banco</span>
<span class="sd"> A assinatura da função é `postgreSQL.db_update([conexao], [query])`</span>
<span class="sd"> São permitidas apenas instruções de update. A presença de outras instruções SQL de manipulação de dados e metadados não são permitidas e abortarão a execução da query.</span>
<span class="sd"> A função retorna *a quantidade de linhas alteradas*.</span>
<span class="sd"> Exemplo de uso:</span>
<span class="sd"> ```</span>
<span class="sd"> from lbx_toolkit import postgreSQL</span>
<span class="sd"> from pathlib import Path</span>
<span class="sd"> credenciais = {</span>
<span class="sd"> 'dbname': 'NOME_BANCO',</span>
<span class="sd"> 'user': 'USUARIO'', </span>
<span class="sd"> 'password': 'SENHA', </span>
<span class="sd"> 'host': 'IP_OU_DNS_SERVIDOR',</span>
<span class="sd"> 'port': 'PORTA_POSTGRESQL', ## padrão = 5432</span>
<span class="sd"> }</span>
<span class="sd"> conexao = postgreSQL.db(credenciais)</span>
<span class="sd"> query = "update meu_esquema.teste_table set coluna='novo_valor' where pk='chave'"</span>
<span class="sd"> result = postgreSQL.db_update(conexao, query)</span>
<span class="sd"> conexao.close()</span>
<span class="sd"> ```</span>
<span class="sd"> """</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">config</span><span class="p">,</span> <span class="n">logger</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span> <span class="o">=</span> <span class="n">logger</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">logger</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="n">lbx_logger</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="n">logging</span><span class="o">.</span><span class="n">DEBUG</span><span class="p">,</span> <span class="s1">'</span><span class="si">%(levelname)s</span><span class="s1">: </span><span class="si">%(message)s</span><span class="s1">'</span><span class="p">)</span> <span class="c1"># se não fornecer o logger, vai tudo para o console</span>
<span class="k">try</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Conexao</span> <span class="o">=</span> <span class="n">psycopg2</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="o">**</span><span class="n">config</span><span class="p">)</span> <span class="c1">## na chamada de uma função/método, o * explode os valores de um dicionário em argumentos posicionais (só valores) e ** explode discionário em argumentos nominais (nome=valor)</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">Err</span><span class="p">:</span>
<span class="k">raise</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">csv_df</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">CsvPath</span><span class="p">,</span> <span class="n">CsvDelim</span><span class="o">=</span><span class="s1">';'</span><span class="p">):</span> <span class="c1"># Le arquivo CSV e gera Dataframe do Pandas</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">DataFrame</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">read_csv</span><span class="p">(</span><span class="n">CsvPath</span><span class="p">,</span> <span class="n">delimiter</span><span class="o">=</span><span class="n">CsvDelim</span><span class="p">)</span> <span class="c1"># Verifique se o delimitador é ';'</span>
<span class="n">DataFrame</span><span class="o">.</span><span class="n">replace</span><span class="p">({</span><span class="n">np</span><span class="o">.</span><span class="n">nan</span><span class="p">:</span> <span class="kc">None</span><span class="p">},</span> <span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> <span class="c1">## troca 'NaN' por None (null no postgresql)</span>
<span class="k">return</span> <span class="n">DataFrame</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">Err</span><span class="p">:</span>
<span class="k">raise</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">db_insert_df</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">DataFrame</span><span class="p">,</span> <span class="n">Tabela</span><span class="p">,</span> <span class="n">Schema</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">Colunas</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">OnConflict</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span> <span class="c1"># Insere os dados de um dataframe em uma tabela equivalente no banco (exige mesma estrutura de colunas)</span>
<span class="c1"># Essa função exige que os nomes dos cabeçalhos das colunas do CSV sejam os mesmos das colunas da tabela de destino</span>
<span class="n">Colunas</span> <span class="o">=</span> <span class="n">Colunas</span> <span class="ow">or</span> <span class="n">DataFrame</span><span class="o">.</span><span class="n">columns</span><span class="o">.</span><span class="n">tolist</span><span class="p">()</span> <span class="c1"># Caso não seja fornecida a lista de colunas, assume as colunas do DataFrame</span>
<span class="n">Valores</span> <span class="o">=</span> <span class="p">[</span><span class="nb">tuple</span><span class="p">(</span><span class="n">Linha</span><span class="p">)</span> <span class="k">for</span> <span class="n">Linha</span> <span class="ow">in</span> <span class="n">DataFrame</span><span class="p">[</span><span class="n">Colunas</span><span class="p">]</span><span class="o">.</span><span class="n">values</span><span class="p">]</span>
<span class="n">Schema</span> <span class="o">=</span> <span class="n">Schema</span> <span class="ow">or</span> <span class="s1">'public'</span>
<span class="n">Query</span> <span class="o">=</span> <span class="sa">f</span><span class="s1">'insert into </span><span class="si">{</span><span class="n">Schema</span><span class="si">}</span><span class="s1">.</span><span class="si">{</span><span class="n">Tabela</span><span class="si">}</span><span class="s1"> (</span><span class="si">{</span><span class="s1">', '</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">Colunas</span><span class="p">)</span><span class="si">}</span><span class="s1">) values %s '</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">OnConflict</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">Query</span> <span class="o">=</span> <span class="n">Query</span> <span class="o">+</span> <span class="n">OnConflict</span>
<span class="k">try</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Cursor</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">Conexao</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span>
<span class="n">execute_values</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">Cursor</span><span class="p">,</span> <span class="n">Query</span><span class="p">,</span> <span class="n">Valores</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Conexao</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">Err</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Conexao</span><span class="o">.</span><span class="n">rollback</span><span class="p">()</span>
<span class="k">raise</span>
<span class="k">finally</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Cursor</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="c1">#Conexao.close() ## conexão precisa ser fechada explicitamente fora da classe</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">db_select</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">Query</span><span class="p">):</span> <span class="c1"># Retorna um cursor à partir de um select</span>
<span class="n">BlackList</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'INSERT '</span><span class="p">,</span> <span class="s1">'DELETE '</span><span class="p">,</span> <span class="s1">'UPDATE '</span><span class="p">,</span> <span class="s1">'CREATE '</span><span class="p">,</span> <span class="s1">'DROP '</span><span class="p">,</span> <span class="s1">'MERGE '</span><span class="p">,</span> <span class="s1">'REPLACE '</span><span class="p">,</span> <span class="s1">'CALL '</span><span class="p">,</span> <span class="s1">'EXECUTE '</span><span class="p">]</span>
<span class="k">if</span> <span class="nb">any</span><span class="p">(</span><span class="n">element</span> <span class="ow">in</span> <span class="n">Query</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span> <span class="k">for</span> <span class="n">element</span> <span class="ow">in</span> <span class="n">BlackList</span><span class="p">):</span>
<span class="n">BlackListed</span> <span class="o">=</span> <span class="p">[</span><span class="n">element</span> <span class="k">for</span> <span class="n">element</span> <span class="ow">in</span> <span class="n">BlackList</span> <span class="k">if</span> <span class="n">element</span> <span class="ow">in</span> <span class="n">Query</span><span class="o">.</span><span class="n">upper</span><span class="p">()]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">erro</span><span class="p">(</span><span class="sa">f</span><span class="s1">'</span><span class="si">{</span><span class="vm">__name__</span><span class="si">}</span><span class="s1">: Este método permite apenas consultas. A query informada possui as seguintes palavras reservadas não aceitas: </span><span class="si">{</span><span class="n">BlackListed</span><span class="si">}</span><span class="s1"> e não foi executada!'</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">None</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Cursor</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">Conexao</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Cursor</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">Query</span><span class="p">)</span>
<span class="n">Dados</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">Cursor</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
<span class="n">Colunas</span> <span class="o">=</span> <span class="p">[</span><span class="n">Col</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">Col</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">Cursor</span><span class="o">.</span><span class="n">description</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Conexao</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Cursor</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">return</span> <span class="n">Dados</span><span class="p">,</span> <span class="n">Colunas</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">Err</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Conexao</span><span class="o">.</span><span class="n">rollback</span><span class="p">()</span>
<span class="k">raise</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">db_update</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">Query</span><span class="p">):</span> <span class="c1"># Retorna um cursor à partir de um select</span>
<span class="n">UpdRows</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">BlackList</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'INSERT '</span><span class="p">,</span> <span class="s1">'DELETE '</span><span class="p">,</span> <span class="s1">'SELECT '</span><span class="p">,</span> <span class="s1">'CREATE '</span><span class="p">,</span> <span class="s1">'DROP '</span><span class="p">,</span> <span class="s1">'MERGE '</span><span class="p">,</span> <span class="s1">'REPLACE '</span><span class="p">,</span> <span class="s1">'CALL '</span><span class="p">,</span> <span class="s1">'EXECUTE '</span><span class="p">]</span>
<span class="k">if</span> <span class="nb">any</span><span class="p">(</span><span class="n">element</span> <span class="ow">in</span> <span class="n">Query</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span> <span class="k">for</span> <span class="n">element</span> <span class="ow">in</span> <span class="n">BlackList</span><span class="p">):</span>
<span class="n">BlackListed</span> <span class="o">=</span> <span class="p">[</span><span class="n">element</span> <span class="k">for</span> <span class="n">element</span> <span class="ow">in</span> <span class="n">BlackList</span> <span class="k">if</span> <span class="n">element</span> <span class="ow">in</span> <span class="n">Query</span><span class="o">.</span><span class="n">upper</span><span class="p">()]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">erro</span><span class="p">(</span><span class="sa">f</span><span class="s1">'</span><span class="si">{</span><span class="vm">__name__</span><span class="si">}</span><span class="s1">: Este método permite apenas updates. A query informada possui as seguintes palavras reservadas não aceitas: </span><span class="si">{</span><span class="n">BlackListed</span><span class="si">}</span><span class="s1"> e não foi executada!'</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">None</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Cursor</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">Conexao</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Cursor</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">Query</span><span class="p">)</span>
<span class="n">UpdRows</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">Cursor</span><span class="o">.</span><span class="n">rowcount</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Conexao</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Cursor</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">return</span> <span class="n">UpdRows</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">Err</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Conexao</span><span class="o">.</span><span class="n">rollback</span><span class="p">()</span>
<span class="k">raise</span>
</code></pre></div></td></tr></table></div>
</details>
<div class="doc doc-children">
</div>
</div>
</div>
</div>
</div>
</div>
</article>
</div>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": ".", "features": [], "search": "assets/javascripts/workers/search.b8dbb3d2.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
<script src="assets/javascripts/bundle.fe8b6f2b.min.js"></script>
</body>
</html>
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
lbxtoolkit-2.1.3.tar.gz
(104.3 kB
view details)
Built Distribution
File details
Details for the file lbxtoolkit-2.1.3.tar.gz
.
File metadata
- Download URL: lbxtoolkit-2.1.3.tar.gz
- Upload date:
- Size: 104.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.12.2
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 893519e9ab6a70a3527ace8462f9a5d8e6639236c28a772750e53c912a81796d |
|
MD5 | badc9b613facc1086b8baa171fdecce9 |
|
BLAKE2b-256 | 6cc86c79c8f25fcbf0472f6d634875f2e4d2cc8b1fb60cdb1bfe6a7ad7a071ae |
File details
Details for the file lbxtoolkit-2.1.3-py3-none-any.whl
.
File metadata
- Download URL: lbxtoolkit-2.1.3-py3-none-any.whl
- Upload date:
- Size: 65.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.12.2
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | f13570bdd92ccb5f26448a14d2a1c3ce61225a13fce3d1fca4804ee823a964ce |
|
MD5 | 566a4c431c84d77a0caea3abcf87015f |
|
BLAKE2b-256 | e663b87941a6700bfddcf84f944472b74a63b8ce238ac908deb7ed330aea370d |