Metadata-Version: 2.1
Name: lbxtoolkit
Version: 2.1.2
Summary: 
Author: Cristiano P. Ferrari
Author-email: cristiano.ferrari@lbx.com.br
Requires-Python: >=3.12,<4.0
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Requires-Dist: msal (>=1.30.0,<2.0.0)
Requires-Dist: numpy (>=2.0.1,<3.0.0)
Requires-Dist: pandas (>=2.2.2,<3.0.0)
Requires-Dist: psutil (>=6.0.0,<7.0.0)
Requires-Dist: psycopg2 (>=2.9.9,<3.0.0)
Requires-Dist: pygetwindow (>=0.0.9,<0.0.10)
Requires-Dist: pywin32 (>=306,<307)
Requires-Dist: requests (>=2.32.3,<3.0.0)
Requires-Dist: selenium (>=4.23.1,<5.0.0)
Requires-Dist: validators (>=0.33.0,<0.34.0)
Requires-Dist: webdriver-manager (>=4.0.2,<5.0.0)
Description-Content-Type: text/plain


<!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">&quot;&quot;&quot;</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">    &quot;&quot;&quot;</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">&quot;&quot;&quot;</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">    &quot;&quot;&quot;</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">&#39;log&#39;</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">&#39;argparse_cfg&#39;</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">&#39;argparse_opt&#39;</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">&#39;ambiente&#39;</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">&#39;Argumento &quot;log&quot; é mandatório e deve ser uma instância de &quot;lbxtoolkit.lbx_logger&quot;&#39;</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">&#39;Argumento &quot;argparse_cfg&quot; é 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&#39;</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">&#39;Argumento &quot;argparse_opt&quot; é 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&#39;</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">&#39;Linux&#39;</span><span class="p">,</span> <span class="s1">&#39;Windows&#39;</span><span class="p">,</span> <span class="s1">&#39;Serviço&#39;</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">&#39;Argumento &quot;ambiente&quot; é mandatório e deve ser uma string com um dos seguintes valores: [Linux, Windows, Serviço]&#39;</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">&#39;.&#39;</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">&#39;.daemon&#39;</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">&#39;Windows&#39;</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">&#39;~&#39;</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">&#39;/&#39;</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">&#39;.&#39;</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">&#39;[DAEMON (console)]&#39;</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(&#39;argparse_cfg&#39;)</span>
        <span class="c1">#kwopts = ConfigManager.get(&#39;argparse_opt&#39;)                </span>
        <span class="c1">#ambiente = ConfigManager.get(&#39;ambiente&#39;)                </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">&#39;Serviço&#39;</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">&gt;</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">&#39;install&#39;</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">&gt;</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">&#39;remove&#39;</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">&gt;</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">&#39;start&#39;</span><span class="p">,</span> <span class="s1">&#39;stop&#39;</span><span class="p">,</span> <span class="s1">&#39;restart&#39;</span><span class="p">,</span> <span class="s1">&#39;debug&#39;</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">&#39;short&#39;</span><span class="p">],</span> <span class="n">opt</span><span class="p">[</span><span class="s1">&#39;long&#39;</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">&#39;action&#39;</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">&#39;help&#39;</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">&quot;&quot;&quot;Inicia a execução do do serviço&quot;&quot;&quot;</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">&#39;START&#39;</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">&#39;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">... &#39;</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">&#39;w&#39;</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s1">&#39;utf-8&#39;</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">&#39;;&#39;</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">&#39;CRASH&#39;</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">&#39;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">&#39;</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">&#39;Ok!&#39;</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">&#39;STOP&#39;</span><span class="p">):</span>
<span class="w">        </span><span class="sd">&quot;&quot;&quot;Interrompe o daemon/serviço&quot;&quot;&quot;</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">&quot;&quot;&quot;Método auxiliar utilizado no stop() para limpar o o PID file na interrupção&quot;&quot;&quot;</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">&quot;&quot;&quot;Método auxiliar utilizado alimentar log do histórico de inicialização/interrupção do serviço/daemon&quot;&quot;&quot;</span>

        <span class="n">evento</span> <span class="o">=</span> <span class="s1">&#39;CHECK&#39;</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">&#39;%Y-%m-</span><span class="si">%d</span><span class="s1"> %H:%M:%S&#39;</span><span class="p">)</span>
        <span class="n">Message</span>  <span class="o">=</span> <span class="sa">f</span><span class="s1">&#39;</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">&#39;</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">&#39;a&#39;</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">&#39;</span><span class="se">\n</span><span class="s1">&#39;</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">&#39;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">&#39;</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">&quot;&quot;&quot;Método auxiliar utilizado no stop() para limpar o o PID file na interrupção&quot;&quot;&quot;</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">&quot;&quot;&quot;Método auxiliar utilizado alimentar log do histórico de inicialização/interrupção do serviço/daemon&quot;&quot;&quot;</span>

    <span class="n">evento</span> <span class="o">=</span> <span class="s1">&#39;CHECK&#39;</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">&#39;%Y-%m-</span><span class="si">%d</span><span class="s1"> %H:%M:%S&#39;</span><span class="p">)</span>
    <span class="n">Message</span>  <span class="o">=</span> <span class="sa">f</span><span class="s1">&#39;</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">&#39;</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">&#39;a&#39;</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">&#39;</span><span class="se">\n</span><span class="s1">&#39;</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">&#39;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">&#39;</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">&quot;&quot;&quot;Inicia a execução do do serviço&quot;&quot;&quot;</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">&#39;START&#39;</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">&#39;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">... &#39;</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">&#39;w&#39;</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s1">&#39;utf-8&#39;</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">&#39;;&#39;</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">&#39;CRASH&#39;</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">&#39;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">&#39;</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">&#39;Ok!&#39;</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">&#39;STOP&#39;</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">&#39;STOP&#39;</span><span class="p">):</span>
<span class="w">    </span><span class="sd">&quot;&quot;&quot;Interrompe o daemon/serviço&quot;&quot;&quot;</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 = {
                &quot;dueDate&quot;: f&quot;{Vencimento}&quot;
            }
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">&quot;&quot;&quot;</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={&quot;Content-Type&quot;: &quot;application/json&quot;}, 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">                    &#39;user&#39;: &#39;USUARIO_API&#39;,</span>
<span class="sd">                    &#39;password&#39;: &#39;TOKEN_USUARIO&#39;</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 &#39;payload&#39; (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&#39;https://api.sienge.com.br/lbx/public/api/v1&#39;</span>
<span class="sd">    Credenciais = {</span>
<span class="sd">                    &#39;user&#39;: &#39;USUARIO_API&#39;,</span>
<span class="sd">                    &#39;password&#39;: &#39;TOKEN_USUARIO&#39;</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(&#39;Numero do título:&#39;)</span>
<span class="sd">    Nuparcela=input(&#39;Numero da parcela:&#39;)</span>
<span class="sd">    Vencimento=input(&#39;Vencimento [AAAA-MM-DD]:&#39;)</span>
<span class="sd">    Payload = {</span>
<span class="sd">                    &quot;dueDate&quot;: f&quot;{Vencimento}&quot;</span>
<span class="sd">                }</span>
<span class="sd">    EndPoint = f&#39;{UrlBase}/bills/{Nutitulo}/installments/{Nuparcela}&#39;</span>

<span class="sd">    #chama o endpoint e recebe o retorno no objeto AlteraVcto</span>
<span class="sd">    AlteraVcto = ApiSienge.endpoint_json(EndPoint, &#39;patch&#39;, 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">    &quot;&quot;&quot;</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">&quot;Content-Type&quot;</span><span class="p">:</span> <span class="s2">&quot;application/json&quot;</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">&#39;</span><span class="si">%(levelname)s</span><span class="s1">: </span><span class="si">%(message)s</span><span class="s1">&#39;</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">&#39;URL inválida: </span><span class="si">{url}</span><span class="s1">. Primeiro parametro precisar uma URL válida. Script abortado&#39;</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">&#39;O segundo parametro posicional precisa ser um dicionário. Script abortado&#39;</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">&#39;inf&#39;</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">&lt;</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">&#39;user&#39;</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">&#39;password&#39;</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">&#39;Dicionário de credenciais não possui chaves &quot;user&quot; e/ou &quot;password&quot;. Script abortado&#39;</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">&#39;user&#39;</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">&#39;password&#39;</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&#39;Status: {Auth.status_code}&#39;)</span>
            <span class="c1">#print(f&#39;Retorno: {Auth.text}&#39;)</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">&quot;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">&quot;</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">&quot;Authorization&quot;</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&quot;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">&quot;</span><span class="p">})</span>
            <span class="k">if</span> <span class="mi">200</span> <span class="o">&lt;=</span> <span class="n">Token</span><span class="o">.</span><span class="n">status_code</span> <span class="o">&lt;=</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">&quot;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">&quot;</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">&quot;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">&quot;</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">&#39;post&#39;</span><span class="p">,</span> <span class="s1">&#39;get&#39;</span><span class="p">,</span> <span class="s1">&#39;patch&#39;</span><span class="p">,</span> <span class="s1">&#39;put&#39;</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">&#39;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!&#39;</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">&#39;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)&#39;</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">&#39;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)&#39;</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">&gt;=</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">&#39;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">&#39;</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">&#39;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">&#39;</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">&#39;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">&#39;</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">&lt;=</span> <span class="n">CodRet</span> <span class="o">&lt;=</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">&#39;null&#39;</span><span class="p">,</span><span class="s1">&#39;None&#39;</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">&#39;\n\t&#39;</span><span class="p">,</span><span class="s1">&#39; &#39;</span><span class="p">))</span>
                <span class="k">if</span> <span class="s1">&#39;clientMessage&#39;</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">&#39;clientMessage&#39;</span><span class="p">]</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="s1">&#39;None&#39;</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="s1">&#39; &#39;</span><span class="p">,</span> <span class="s1">&#39;null&#39;</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">&#39;clientMessage&#39;</span><span class="p">]</span>
                <span class="k">elif</span> <span class="s1">&#39;developerMessage&#39;</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">&#39;developerMessage&#39;</span><span class="p">]</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="s1">&#39;None&#39;</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="s1">&#39; &#39;</span><span class="p">,</span> <span class="s1">&#39;null&#39;</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">&#39;developerMessage&#39;</span><span class="p">]</span>
                <span class="k">elif</span> <span class="s1">&#39;message&#39;</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">&#39;message&#39;</span><span class="p">]</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="s1">&#39;None&#39;</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="s1">&#39; &#39;</span><span class="p">,</span> <span class="s1">&#39;null&#39;</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">&#39;message&#39;</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">&#39;\n\t&#39;</span><span class="p">,</span><span class="s1">&#39; &#39;</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 &gt;&gt; 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 &gt; Aplicativos &gt; 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">&quot;&quot;&quot;</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 &gt;&gt; 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=&#39;auth_EntraID.log&#39;)`: 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 &gt; Aplicativos &gt; 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 _&quot;Certificados e Segredos&quot;_, 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 = &#39;SEU_CLIENT_ID&#39;</span>
<span class="sd">    client_secret = &#39;SEU_CLIENT_SECRET&#39;</span>
<span class="sd">    tenant_id = &#39;SEU_TENANT_ID&#39;</span>

<span class="sd">    # inicializa instância</span>
<span class="sd">    auth = auth_EntraID(client_id, client_secret, tenant_id, timeout=60, log_file=&#39;auth_EntraID.log&#39;)  </span>

<span class="sd">    # exibe a mensagem padrão de aviso</span>
<span class="sd">    auth.disclaimer()</span>

<span class="sd">    auth.valida_grupo(&#39;Nome do Grupo de Distribuição&#39;) </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">    &quot;&quot;&quot;</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">&#39;auth_EntraID.log&#39;</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">&quot;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">&quot;</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">&quot;https://graph.microsoft.com/.default&quot;</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">&quot;http://localhost:8000&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">response</span> <span class="o">=</span> <span class="s2">&quot;&quot;</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">&#39;</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">&#39;</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">&#39;stdout.log&#39;</span><span class="p">,</span> <span class="s1">&#39;a&#39;</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">&#39;stderr.log&#39;</span><span class="p">,</span> <span class="s1">&#39;a&#39;</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">&quot;--incognito&quot;</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">&#39;Falha ao iniciar aplicação MSAL: </span><span class="si">{</span><span class="n">err</span><span class="si">}</span><span class="s1">&#39;</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">&#39;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&#39;</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">&quot;auth_uri&quot;</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">&quot;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">&quot;</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">&#39;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">&#39;</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">&#39;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&#39;</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">&#39;Falha na inicialização do Chrome: </span><span class="si">{</span><span class="n">err</span><span class="si">}</span><span class="s1">&#39;</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">&#39;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&#39;</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">&quot;</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">&quot;</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">&#39;Content-type&#39;</span><span class="p">,</span> <span class="s1">&#39;text/html&#39;</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">&#39;code&#39;</span> <span class="ow">in</span> <span class="n">query_params</span> <span class="ow">and</span> <span class="s1">&#39;state&#39;</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">&#39;code&#39;</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">&#39;state&#39;</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">&quot;&quot;&quot;</span>
<span class="s2">                                    &lt;!DOCTYPE html&gt;</span>
<span class="s2">                                    &lt;html lang=&quot;pt_BR&quot;&gt;</span>
<span class="s2">                                    &lt;head&gt;</span>
<span class="s2">                                        &lt;meta charset=&quot;UTF-8&quot;&gt;</span>
<span class="s2">                                        &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;</span>
<span class="s2">                                        &lt;style&gt;</span>
<span class="s2">                                                body {</span>
<span class="s2">                                                    font-family: &#39;Arial&#39;, 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">                                        &lt;/style&gt;</span>
<span class="s2">                                     &lt;/head&gt;</span>
<span class="s2">                                        &lt;div class=&quot;container&quot;&gt;</span>
<span class="s2">                                            &lt;h1&gt;Autentica&amp;#231;&amp;#227;o realizada com sucesso!&lt;/h1&gt;</span>
<span class="s2">                                            Aguarde que esta p&amp;#225;gina ser&amp;#225; fechada automaticamente.&lt;br&gt;</span>
<span class="s2">                                            Se isto n&amp;#227;o acontecer, pode fech&amp;#225;-la manualmente.</span>
<span class="s2">                                        &lt;/div&gt;</span>
<span class="s2">                                     &lt;/body&gt;&lt;/html&gt;</span>
<span class="s2">                                     &quot;&quot;&quot;</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">&quot;&quot;&quot;</span>
<span class="s2">                                    &lt;!DOCTYPE html&gt;</span>
<span class="s2">                                    &lt;html lang=&quot;pt_BR&quot;&gt;</span>
<span class="s2">                                    &lt;head&gt;</span>
<span class="s2">                                        &lt;meta charset=&quot;UTF-8&quot;&gt;</span>
<span class="s2">                                        &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;</span>
<span class="s2">                                        &lt;style&gt;</span>
<span class="s2">                                                body {</span>
<span class="s2">                                                    font-family: &#39;Arial&#39;, 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">                                        &lt;/style&gt;</span>
<span class="s2">                                     &lt;/head&gt;</span>
<span class="s2">                                        &lt;div class=&quot;container&quot;&gt;</span>
<span class="s2">                                            &lt;h1&gt;Falha na autentica&amp;#231;&amp;#227;o!&lt;/h1&gt;</span>
<span class="s2">                                            Esta p&amp;#225;gina ser&amp;#225; fechada automaticamente.&lt;br&gt;</span>
<span class="s2">                                            Se isto n&amp;#227;o acontecer, pode fech&amp;#225;-la manualmente.</span>
<span class="s2">                                        &lt;/div&gt;</span>
<span class="s2">                                     &lt;/body&gt;&lt;/html&gt;</span>
<span class="s2">                                     &quot;&quot;&quot;</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">&#39;localhost&#39;</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">&#39;auth_code&#39;</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">&quot;tempo limite para autenticação foi excedido&quot;</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">&#39;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"> &#39;</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s1">&#39;&#39;</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">&#39;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">&#39;</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s1">&#39;</span><span class="se">\n\n</span><span class="s1">&#39;</span><span class="p">)</span>  
                <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;Falha na autenticação! Execução abortada!&#39;</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">&quot;Esperando pela autenticação...&quot;</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">&#39;auth_code&#39;</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">&quot;code&quot;</span><span class="p">:</span> <span class="n">auth_code</span><span class="p">,</span> <span class="s2">&quot;state&quot;</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">&quot;Erro ao obter o token de acesso: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">&quot;</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">&quot;access_token&quot;</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">&#39;access_token&#39;</span><span class="p">]</span>
            <span class="n">headers</span> <span class="o">=</span> <span class="p">{</span>
                <span class="s1">&#39;Authorization&#39;</span><span class="p">:</span> <span class="s1">&#39;Bearer &#39;</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">&#39;https://graph.microsoft.com/v1.0/me&#39;</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">&#39;userPrincipalName&#39;</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">&quot;Email do usuário autenticado: </span><span class="si">{</span><span class="n">user_email</span><span class="si">}</span><span class="s2">&quot;</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">&#39;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">&#39;</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">&#39;id&#39;</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">&quot;https://graph.microsoft.com/v1.0/groups?$filter=displayName eq &#39;</span><span class="si">{</span><span class="n">group_name</span><span class="si">}</span><span class="s2">&#39;&quot;</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">&#39;value&#39;</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">&#39;value&#39;</span><span class="p">])</span> <span class="o">&gt;</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">&#39;value&#39;</span><span class="p">][</span><span class="mi">0</span><span class="p">][</span><span class="s1">&#39;id&#39;</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">&#39;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&#39;</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">&#39;value&#39;</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">&#39;id&#39;</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">&#39;value&#39;</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">&quot;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.&quot;</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">&quot;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.&quot;</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">&quot;Resposta da API de membros não contém a chave &#39;value&#39;.&quot;</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">&quot;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">&quot;</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">&quot;</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">&quot;</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">&quot;Grupo &#39;</span><span class="si">{</span><span class="n">group_name</span><span class="si">}</span><span class="s2">&#39; não encontrado.&quot;</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">&quot;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">&quot;</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">&quot;</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">&quot;</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">&quot;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">&quot;</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">&quot;</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">&quot;</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">&quot;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">&quot;</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">&quot;</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">&quot;</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">&quot;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">&#39;error&#39;</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</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">&quot;</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">&#39;error_description&#39;</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</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">&#39;</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"> &#39;</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s1">&#39;&#39;</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">&#39;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">&#39;</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s1">&#39;</span><span class="se">\n\n</span><span class="s1">&#39;</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">&#39;Acesso autorizado!&#39;</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">&#39;Permissões inválidas! Execução abortada!&#39;</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">&quot;&quot;&quot;</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">        &quot;&quot;&quot;</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 &quot;info&quot; e com texto: &quot;Mensagem 1# Mensagem 2# Mensagem 3&quot;
</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 &quot;.log&quot;

### instancia o manipulador para tratar todas as mensagens (nível DEBUG acima), 
#   mas suprime a apresentação em tela das mensagens de nível &quot;DEBUG&quot; na tela, 
#   apenas registrando-as somente no arquivo
#   e sumprime o registro no arquivo das mensagens de nível &quot;ERROR&quot;, 
#   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&gt;&gt; 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&gt;&gt; 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 &quot;DEBUG&quot;
for line in filtered_lines:
    if &quot;DEBUG&quot; 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">&quot;&quot;&quot;</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=&#39;%(asctime)s - %(levelname)s - %(message)s&#39;, 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(&#39;Essa mensagem apenas resulta em uma mensagem de nível ERROR&#39;)</span>
<span class="sd">    log.erro(&#39;Essa mensagem resulta em uma mensagem de nível ERRO e encerra o script com código de retorno -1&#39;, 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(&#39;Mensagem 1# &#39;) ## não será exibida/registrada</span>
<span class="sd">    log.add(&#39;Mensagem 2# &#39;) ## não será exibida/registrada</span>
<span class="sd">    log.info(&#39;Mensagem 3) ## será exibida/registrada como nível &quot;info&quot; e com texto: &quot;Mensagem 1# Mensagem 2# Mensagem 3&quot;</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(&#39;./&#39;)  # 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 + &#39;.log&#39;) # salva logs no diretório corrente, em um arquivo nomeado com nome do script + extensão &quot;.log&quot;</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 &quot;DEBUG&quot; 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 &quot;ERROR&quot;, </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(&#39;Esta é uma mensagem de debug&#39;) </span>
<span class="sd">    log.info(&#39;Esta é uma mensagem informativa&#39;)</span>
<span class="sd">    log.add(&#39;Esta mensagem não será exibida agora, mas acumulada no buffer# &#39;)</span>
<span class="sd">    log.aviso(&#39;Esta é uma mensagem de aviso&#39;)</span>
<span class="sd">    log.erro(&#39;Esta é uma mensagem de erro&#39;)</span>
<span class="sd">    log.erro(&#39;Esta é uma mensagem erro muito comprida e será limitada a 40 caracteres, o restante será cortado e ingorado ao ser manipulado&#39;, 40)</span>
<span class="sd">    log.critico(&#39;Esta é uma mensagem crítica&#39;)</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(&#39;Este é um erro de exemplo&#39;)</span>

<span class="sd">    # Testando redirecionamento de print e captura de exceção</span>
<span class="sd">    print(&#39;Mensagem de teste via print&#39;)</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&#39;Capturado um erro: {e}&#39;)</span>

<span class="sd">    log.erro(&#39;Essa é uma mensagem de erro e abortará a execução do script&#39;, exit=1)</span>

<span class="sd">    log.info(&#39;Essa mensagem não será exibida pois o script foi abortado na mensagem anterior&#39;)</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&gt;&gt; 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 &#39;LogFile&#39; 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&gt;&gt; import datetime</span>
<span class="sd">    filtra_log = log.search(None, &#39;14/01/2020 00:00&#39;, 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&#39;c:\temp\outro_arquivo.log&#39;)</span>
<span class="sd">    filtra_log = log.search(Outro_Log, &#39;23/12/2023 08:00&#39;, &#39;23/12/2023 18:00&#39;) # </span>

<span class="sd">    # salva conteúdo filtrado em um arquivo:</span>
<span class="sd">    filtrado = &#39;filtered_log.txt&#39;</span>
<span class="sd">    with open(filtado, &#39;w&#39;, encoding=&#39;ISO-8859-1&#39;) 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(&#39;&#39;.join(filtra_log))</span>

<span class="sd">    # mostra o conteúdo filtrado na tela, listando apenas as os registros do nível &quot;DEBUG&quot;</span>
<span class="sd">    for line in filtered_lines:</span>
<span class="sd">        if &quot;DEBUG&quot; in line:</span>
<span class="sd">            print(line, end=&#39;&#39;)</span>
<span class="sd">    ```</span>
<span class="sd">    &quot;&quot;&quot;</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">&#39;</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">&#39;</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">&#39;&#39;</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">&quot;Exceção não prevista&quot;</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">&#39;&#39;</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">&#39;&#39;</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">&#39;&#39;</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">&#39;&#39;</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">&#39;&#39;</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">&#39;([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}&#39;</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">&#39;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 &quot;datetime&quot; ou uma string no formato &quot;dd/mm/aaaa hh:mm:[ss]&quot;&#39;</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 &#39;dd/mm/yyyy hh:mm&#39;</span>
                    <span class="n">dh_ini</span> <span class="o">+=</span> <span class="s2">&quot;:00&quot;</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">&#39;</span><span class="si">%d</span><span class="s1">/%m/%Y %H:%M:%S&#39;</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">&#39;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 &quot;datetime&quot; ou uma string no formato &quot;dd/mm/aaaa hh:mm:[ss]&quot;&#39;</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">&#39;([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}&#39;</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">&#39;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 &quot;datetime&quot; ou uma string no formato &quot;dd/mm/aaaa hh:mm:[ss]&quot;&#39;</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 &#39;dd/mm/yyyy hh:mm&#39;</span>
                    <span class="n">dh_fim</span> <span class="o">+=</span> <span class="s2">&quot;:00&quot;</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">&#39;</span><span class="si">%d</span><span class="s1">/%m/%Y %H:%M:%S&#39;</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">&#39;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 &quot;datetime&quot; ou uma string no formato &quot;dd/mm/aaaa hh:mm:[ss]&quot;&#39;</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">&#39;Nenhum arquivo de log disponível. Log desta instância configurado apenas para exibição em tela, sem registro em arquivo&#39;</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">&#39;Arquivo de log </span><span class="si">{</span><span class="n">log_file</span><span class="si">}</span><span class="s1"> não existe!&#39;</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">&#39;Erro validação arquivo de entrada. Abortando!&#39;</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">&lt;=</span> <span class="n">timestamp</span> <span class="o">&lt;=</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">&#39;r&#39;</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s1">&#39;ISO-8859-1&#39;</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">&quot; &quot;</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">&#39;%Y-%m-</span><span class="si">%d</span><span class="s1"> %H:%M:%S,</span><span class="si">%f</span><span class="s1">&#39;</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!') #&gt;&gt;&gt; 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">&quot;&quot;&quot;</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=[(&#39;Todos os arquivos&#39;, &#39;*.*&#39;)], Titulo=&#39;Selecionar arquivo&#39;)`</span>
<span class="sd">    - `Diretório = seleciona_dir(DirBase=Path(r&#39;./&#39;), Titulo=&#39;Selecionar diretório&#39;):`</span>
<span class="sd">    - `NomeLimpo = normaliza(&#39;String # SEM Noção!&#39;) #&gt;&gt;&gt; string_sem_nocao`</span>
<span class="sd">    - `cmd_window = get_cmd_window()`</span>
<span class="sd">    - `maximize_console()`    </span>
<span class="sd">    &quot;&quot;&quot;</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">&#39;Todos os arquivos&#39;</span><span class="p">,</span> <span class="s1">&#39;*.*&#39;</span><span class="p">)],</span> <span class="n">Titulo</span><span class="o">=</span><span class="s1">&#39;Selecionar arquivo&#39;</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">&#39;./&#39;</span><span class="p">),</span> <span class="n">Titulo</span><span class="o">=</span><span class="s1">&#39;Selecionar diretório&#39;</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">&#39;/</span><span class="se">\\</span><span class="s1">?%§ªº°`´^~*:|&quot;&lt;&gt;!@#$%¨&amp;*()_+=-[]</span><span class="si">{}</span><span class="s1">&quot;</span><span class="se">\&#39;</span><span class="s1"> &#39;</span> 
        <span class="n">Normalizar</span> <span class="o">=</span> <span class="n">normalize</span><span class="p">(</span><span class="s1">&#39;NFKD&#39;</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">&#39;ASCII&#39;</span><span class="p">,</span> <span class="s1">&#39;ignore&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">&#39;ASCII&#39;</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">&#39;_&#39;</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">&quot;&quot;</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">&#39;\.(?=.*\.)&#39;</span><span class="p">,</span> <span class="s1">&#39;_&#39;</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">&#39;_+&#39;</span><span class="p">,</span> <span class="s1">&#39;_&#39;</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">&quot;&quot;</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(&#39;mode con: cols=500 lines=100&#39;)</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">&#39;kernel32&#39;</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">&#39;user32&#39;</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 &quot;;'
</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 &quot;;'

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 = &quot;update meu_esquema.teste_table set coluna='novo_valor' where pk='chave'&quot;

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">&quot;&quot;&quot;</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">                    &#39;dbname&#39;: &#39;NOME_BANCO&#39;,</span>
<span class="sd">                    &#39;user&#39;: &#39;USUARIO&#39;&#39;,        </span>
<span class="sd">                    &#39;password&#39;: &#39;SENHA&#39;,     </span>
<span class="sd">                    &#39;host&#39;: &#39;IP_OU_DNS_SERVIDOR&#39;,</span>
<span class="sd">                    &#39;port&#39;: &#39;PORTA_POSTGRESQL&#39;,  ## 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 *`&#39;options&#39; : &#39;-c search_path=[NOME_SCHEMA]&#39;,`* 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(&#39;./diretorio/arquivo_exemplo.csv&#39;)</span>
<span class="sd">    dados = postgreSQL.csv_df(arquivo_csv, CsvDelim=&#39;,&#39;) # usando vírgula como separador. se omisso, assume &quot;;&#39;</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">                    &#39;dbname&#39;: &#39;NOME_BANCO&#39;,</span>
<span class="sd">                    &#39;user&#39;: &#39;USUARIO&#39;&#39;,        </span>
<span class="sd">                    &#39;password&#39;: &#39;SENHA&#39;,     </span>
<span class="sd">                    &#39;host&#39;: &#39;IP_OU_DNS_SERVIDOR&#39;,</span>
<span class="sd">                    &#39;port&#39;: &#39;PORTA_POSTGRESQL&#39;,  ## padrão = 5432</span>
<span class="sd">                }</span>

<span class="sd">    conexao = postgreSQL.db(credenciais)</span>

<span class="sd">    arquivo_csv = Path(&#39;./diretorio/arquivo_exemplo.csv&#39;)</span>
<span class="sd">    dados = postgreSQL.csv_df(arquivo_csv, CsvDelim=&#39;,&#39;) # usando vírgula como separador. se omisso, assume &quot;;&#39;</span>

<span class="sd">    postgreSQL.db_insert_df(conexao, dados, &#39;teste_table&#39;, Schema=&#39;meu_esquema&#39;, OnConflict=&#39;on conflict (coluna_chave_primaria) do nothing&#39;)</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">                    &#39;dbname&#39;: &#39;NOME_BANCO&#39;,</span>
<span class="sd">                    &#39;user&#39;: &#39;USUARIO&#39;&#39;,        </span>
<span class="sd">                    &#39;password&#39;: &#39;SENHA&#39;,     </span>
<span class="sd">                    &#39;host&#39;: &#39;IP_OU_DNS_SERVIDOR&#39;,</span>
<span class="sd">                    &#39;port&#39;: &#39;PORTA_POSTGRESQL&#39;,  ## padrão = 5432</span>
<span class="sd">                }</span>

<span class="sd">    conexao = postgreSQL.db(credenciais)</span>

<span class="sd">    query = &#39;select * from meu_esquema.teste_table&#39;</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">                    &#39;dbname&#39;: &#39;NOME_BANCO&#39;,</span>
<span class="sd">                    &#39;user&#39;: &#39;USUARIO&#39;&#39;,        </span>
<span class="sd">                    &#39;password&#39;: &#39;SENHA&#39;,     </span>
<span class="sd">                    &#39;host&#39;: &#39;IP_OU_DNS_SERVIDOR&#39;,</span>
<span class="sd">                    &#39;port&#39;: &#39;PORTA_POSTGRESQL&#39;,  ## padrão = 5432</span>
<span class="sd">                }</span>

<span class="sd">    conexao = postgreSQL.db(credenciais)</span>

<span class="sd">    query = &quot;update meu_esquema.teste_table set coluna=&#39;novo_valor&#39; where pk=&#39;chave&#39;&quot;</span>

<span class="sd">    result = postgreSQL.db_update(conexao, query)</span>
<span class="sd">    conexao.close()</span>
<span class="sd">    ```</span>

<span class="sd">    &quot;&quot;&quot;</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">&#39;</span><span class="si">%(levelname)s</span><span class="s1">: </span><span class="si">%(message)s</span><span class="s1">&#39;</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">&#39;;&#39;</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 é &#39;;&#39;</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 &#39;NaN&#39; 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">&#39;public&#39;</span>
        <span class="n">Query</span> <span class="o">=</span> <span class="sa">f</span><span class="s1">&#39;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">&#39;, &#39;</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 &#39;</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">&#39;INSERT &#39;</span><span class="p">,</span> <span class="s1">&#39;DELETE &#39;</span><span class="p">,</span> <span class="s1">&#39;UPDATE &#39;</span><span class="p">,</span> <span class="s1">&#39;CREATE &#39;</span><span class="p">,</span> <span class="s1">&#39;DROP &#39;</span><span class="p">,</span> <span class="s1">&#39;MERGE &#39;</span><span class="p">,</span> <span class="s1">&#39;REPLACE &#39;</span><span class="p">,</span> <span class="s1">&#39;CALL &#39;</span><span class="p">,</span> <span class="s1">&#39;EXECUTE &#39;</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">&#39;</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!&#39;</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">&#39;INSERT &#39;</span><span class="p">,</span> <span class="s1">&#39;DELETE &#39;</span><span class="p">,</span> <span class="s1">&#39;SELECT &#39;</span><span class="p">,</span> <span class="s1">&#39;CREATE &#39;</span><span class="p">,</span> <span class="s1">&#39;DROP &#39;</span><span class="p">,</span> <span class="s1">&#39;MERGE &#39;</span><span class="p">,</span> <span class="s1">&#39;REPLACE &#39;</span><span class="p">,</span> <span class="s1">&#39;CALL &#39;</span><span class="p">,</span> <span class="s1">&#39;EXECUTE &#39;</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">&#39;</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!&#39;</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>
