Files
connpy/docs/connpy/services/config_service.html
T
fluzzi32 12543c683e 1. Persistence Setup: Optimized the dockerfile to manually create the /root/.config/conn/.folder file
pointing to /config. This avoids running the conn command during the build process and ensures a
      cleaner setup.
   2. Copilot UI Fix: Resolved a double-escaping bug in the terminal bottom bar. Device prompts (like
      6WIND-PE1>) will now render correctly instead of showing HTML entities like >.
   3. AI Model Update: Updated the default engineer model in connpy/ai.py to
      gemini/gemini-3.1-flash-lite, removing the deprecated -preview suffix.
   4. Standardized Timeouts: Unified all default timeouts to 20 seconds across the board. This includes
      direct execution (run/test), modern playbooks (v2), and classic task-based playbooks (v1).
   5. Documentation Update: Regenerated the full documentation site in the docs/ directory using pdoc to
      reflect the latest changes.
   6. Cleanup: Removed all debug prints from connpy/core.py and restored the docker/logs/.gitignore
      file.
2026-05-13 14:16:14 -03:00

326 lines
18 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta name="generator" content="pdoc3 0.11.5">
<title>connpy.services.config_service API documentation</title>
<meta name="description" content="">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/sanitize.min.css" integrity="sha512-y1dtMcuvtTMJc1yPgEqF0ZjQbhnc/bFhyvIyVNb9Zk5mIGtqVaAB1Ttl28su8AvFMOY0EwRbAe+HCLqj6W7/KA==" crossorigin>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/13.0.0/typography.min.css" integrity="sha512-Y1DYSb995BAfxobCkKepB1BqJJTPrOp3zPL74AWFugHHmmdcvO+C48WLrUOlhGMc0QG7AE3f7gmvvcrmX2fDoA==" crossorigin>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:1.5em;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:2em 0 .50em 0}h3{font-size:1.4em;margin:1.6em 0 .7em 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .2s ease-in-out}a:visited{color:#503}a:hover{color:#b62}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900;font-weight:bold}pre code{font-size:.8em;line-height:1.4em;padding:1em;display:block}code{background:#f3f3f3;font-family:"DejaVu Sans Mono",monospace;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source > summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible;min-width:max-content}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em 1em;margin:1em 0}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul ul{padding-left:1em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" integrity="sha512-D9gUyxqja7hBtkWpPWGt9wfbfaMGVt9gnyCvYa+jojwwPHLCzUm5i8rpk7vD7wNee9bA35eYIjobYPaQuKS1MQ==" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => {
hljs.configure({languages: ['bash', 'css', 'diff', 'graphql', 'ini', 'javascript', 'json', 'plaintext', 'python', 'python-repl', 'rust', 'shell', 'sql', 'typescript', 'xml', 'yaml']});
hljs.highlightAll();
/* Collapse source docstrings */
setTimeout(() => {
[...document.querySelectorAll('.hljs.language-python > .hljs-string')]
.filter(el => el.innerHTML.length > 200 && ['"""', "'''"].includes(el.innerHTML.substring(0, 3)))
.forEach(el => {
let d = document.createElement('details');
d.classList.add('hljs-string');
d.innerHTML = '<summary>"""</summary>' + el.innerHTML.substring(3);
el.replaceWith(d);
});
}, 100);
})</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>connpy.services.config_service</code></h1>
</header>
<section id="section-intro">
</section>
<section>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="connpy.services.config_service.ConfigService"><code class="flex name class">
<span>class <span class="ident">ConfigService</span></span>
<span>(</span><span>config=None)</span>
</code></dt>
<dd>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class ConfigService(BaseService):
&#34;&#34;&#34;Business logic for general application settings and state configuration.&#34;&#34;&#34;
def get_settings(self) -&gt; Dict[str, Any]:
&#34;&#34;&#34;Get the global configuration settings block.&#34;&#34;&#34;
settings = self.config.config.copy()
settings[&#34;configfolder&#34;] = self.config.defaultdir
return settings
def get_default_dir(self) -&gt; str:
&#34;&#34;&#34;Get the default configuration directory.&#34;&#34;&#34;
return self.config.defaultdir
def set_config_folder(self, folder_path: str):
&#34;&#34;&#34;Set the default location for config file by writing to ~/.config/conn/.folder&#34;&#34;&#34;
if not os.path.isdir(folder_path):
raise ConnpyError(f&#34;readable_dir:{folder_path} is not a valid path&#34;)
pathfile = os.path.join(self.config.anchor_path, &#34;.folder&#34;)
folder = os.path.abspath(folder_path).rstrip(&#39;/&#39;)
try:
with open(pathfile, &#34;w&#34;) as f:
f.write(str(folder))
except Exception as e:
raise ConnpyError(f&#34;Failed to save config folder: {e}&#34;)
def update_setting(self, key, value):
&#34;&#34;&#34;Update a setting in the configuration file.&#34;&#34;&#34;
self.config.config[key] = value
self.config._saveconfig(self.config.file)
def encrypt_password(self, password):
&#34;&#34;&#34;Encrypt a password using the application&#39;s configuration encryption key.&#34;&#34;&#34;
return self.config.encrypt(password)
def apply_theme_from_file(self, theme_input):
&#34;&#34;&#34;Apply &#39;dark&#39;, &#39;light&#39; theme or load a YAML theme file and save it to the configuration.&#34;&#34;&#34;
import yaml
from ..printer import STYLES, LIGHT_THEME
if theme_input == &#34;dark&#34;:
valid_styles = {}
self.update_setting(&#34;theme&#34;, valid_styles)
return valid_styles
elif theme_input == &#34;light&#34;:
valid_styles = LIGHT_THEME.copy()
self.update_setting(&#34;theme&#34;, valid_styles)
return valid_styles
if not os.path.exists(theme_input):
raise InvalidConfigurationError(f&#34;Theme file &#39;{theme_input}&#39; not found.&#34;)
try:
with open(theme_input, &#39;r&#39;) as f:
user_styles = yaml.safe_load(f)
except Exception as e:
raise InvalidConfigurationError(f&#34;Failed to parse theme file: {e}&#34;)
if not isinstance(user_styles, dict):
raise InvalidConfigurationError(&#34;Theme file must be a YAML dictionary.&#34;)
# Support both direct styles and nested under &#39;theme&#39; key
if &#34;theme&#34; in user_styles and isinstance(user_styles[&#34;theme&#34;], dict):
user_styles = user_styles[&#34;theme&#34;]
# Filter for valid styles only (prevent junk in config)
valid_styles = {k: v for k, v in user_styles.items() if k in STYLES}
if not valid_styles:
raise InvalidConfigurationError(&#34;No valid style keys found in theme file.&#34;)
# Persist and return merged styles
self.update_setting(&#34;theme&#34;, valid_styles)
return valid_styles</code></pre>
</details>
<div class="desc"><p>Business logic for general application settings and state configuration.</p>
<p>Initialize the service.</p>
<h2 id="args">Args</h2>
<dl>
<dt><strong><code>config</code></strong></dt>
<dd>An instance of configfile (or None to instantiate a new one/use global context).</dd>
</dl></div>
<h3>Ancestors</h3>
<ul class="hlist">
<li><a title="connpy.services.base.BaseService" href="base.html#connpy.services.base.BaseService">BaseService</a></li>
</ul>
<h3>Methods</h3>
<dl>
<dt id="connpy.services.config_service.ConfigService.apply_theme_from_file"><code class="name flex">
<span>def <span class="ident">apply_theme_from_file</span></span>(<span>self, theme_input)</span>
</code></dt>
<dd>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def apply_theme_from_file(self, theme_input):
&#34;&#34;&#34;Apply &#39;dark&#39;, &#39;light&#39; theme or load a YAML theme file and save it to the configuration.&#34;&#34;&#34;
import yaml
from ..printer import STYLES, LIGHT_THEME
if theme_input == &#34;dark&#34;:
valid_styles = {}
self.update_setting(&#34;theme&#34;, valid_styles)
return valid_styles
elif theme_input == &#34;light&#34;:
valid_styles = LIGHT_THEME.copy()
self.update_setting(&#34;theme&#34;, valid_styles)
return valid_styles
if not os.path.exists(theme_input):
raise InvalidConfigurationError(f&#34;Theme file &#39;{theme_input}&#39; not found.&#34;)
try:
with open(theme_input, &#39;r&#39;) as f:
user_styles = yaml.safe_load(f)
except Exception as e:
raise InvalidConfigurationError(f&#34;Failed to parse theme file: {e}&#34;)
if not isinstance(user_styles, dict):
raise InvalidConfigurationError(&#34;Theme file must be a YAML dictionary.&#34;)
# Support both direct styles and nested under &#39;theme&#39; key
if &#34;theme&#34; in user_styles and isinstance(user_styles[&#34;theme&#34;], dict):
user_styles = user_styles[&#34;theme&#34;]
# Filter for valid styles only (prevent junk in config)
valid_styles = {k: v for k, v in user_styles.items() if k in STYLES}
if not valid_styles:
raise InvalidConfigurationError(&#34;No valid style keys found in theme file.&#34;)
# Persist and return merged styles
self.update_setting(&#34;theme&#34;, valid_styles)
return valid_styles</code></pre>
</details>
<div class="desc"><p>Apply 'dark', 'light' theme or load a YAML theme file and save it to the configuration.</p></div>
</dd>
<dt id="connpy.services.config_service.ConfigService.encrypt_password"><code class="name flex">
<span>def <span class="ident">encrypt_password</span></span>(<span>self, password)</span>
</code></dt>
<dd>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def encrypt_password(self, password):
&#34;&#34;&#34;Encrypt a password using the application&#39;s configuration encryption key.&#34;&#34;&#34;
return self.config.encrypt(password)</code></pre>
</details>
<div class="desc"><p>Encrypt a password using the application's configuration encryption key.</p></div>
</dd>
<dt id="connpy.services.config_service.ConfigService.get_default_dir"><code class="name flex">
<span>def <span class="ident">get_default_dir</span></span>(<span>self) > str</span>
</code></dt>
<dd>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def get_default_dir(self) -&gt; str:
&#34;&#34;&#34;Get the default configuration directory.&#34;&#34;&#34;
return self.config.defaultdir</code></pre>
</details>
<div class="desc"><p>Get the default configuration directory.</p></div>
</dd>
<dt id="connpy.services.config_service.ConfigService.get_settings"><code class="name flex">
<span>def <span class="ident">get_settings</span></span>(<span>self) > Dict[str, Any]</span>
</code></dt>
<dd>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def get_settings(self) -&gt; Dict[str, Any]:
&#34;&#34;&#34;Get the global configuration settings block.&#34;&#34;&#34;
settings = self.config.config.copy()
settings[&#34;configfolder&#34;] = self.config.defaultdir
return settings</code></pre>
</details>
<div class="desc"><p>Get the global configuration settings block.</p></div>
</dd>
<dt id="connpy.services.config_service.ConfigService.set_config_folder"><code class="name flex">
<span>def <span class="ident">set_config_folder</span></span>(<span>self, folder_path: str)</span>
</code></dt>
<dd>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def set_config_folder(self, folder_path: str):
&#34;&#34;&#34;Set the default location for config file by writing to ~/.config/conn/.folder&#34;&#34;&#34;
if not os.path.isdir(folder_path):
raise ConnpyError(f&#34;readable_dir:{folder_path} is not a valid path&#34;)
pathfile = os.path.join(self.config.anchor_path, &#34;.folder&#34;)
folder = os.path.abspath(folder_path).rstrip(&#39;/&#39;)
try:
with open(pathfile, &#34;w&#34;) as f:
f.write(str(folder))
except Exception as e:
raise ConnpyError(f&#34;Failed to save config folder: {e}&#34;)</code></pre>
</details>
<div class="desc"><p>Set the default location for config file by writing to ~/.config/conn/.folder</p></div>
</dd>
<dt id="connpy.services.config_service.ConfigService.update_setting"><code class="name flex">
<span>def <span class="ident">update_setting</span></span>(<span>self, key, value)</span>
</code></dt>
<dd>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def update_setting(self, key, value):
&#34;&#34;&#34;Update a setting in the configuration file.&#34;&#34;&#34;
self.config.config[key] = value
self.config._saveconfig(self.config.file)</code></pre>
</details>
<div class="desc"><p>Update a setting in the configuration file.</p></div>
</dd>
</dl>
<h3>Inherited members</h3>
<ul class="hlist">
<li><code><b><a title="connpy.services.base.BaseService" href="base.html#connpy.services.base.BaseService">BaseService</a></b></code>:
<ul class="hlist">
<li><code><a title="connpy.services.base.BaseService.set_reserved_names" href="base.html#connpy.services.base.BaseService.set_reserved_names">set_reserved_names</a></code></li>
</ul>
</li>
</ul>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="connpy.services" href="index.html">connpy.services</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="connpy.services.config_service.ConfigService" href="#connpy.services.config_service.ConfigService">ConfigService</a></code></h4>
<ul class="">
<li><code><a title="connpy.services.config_service.ConfigService.apply_theme_from_file" href="#connpy.services.config_service.ConfigService.apply_theme_from_file">apply_theme_from_file</a></code></li>
<li><code><a title="connpy.services.config_service.ConfigService.encrypt_password" href="#connpy.services.config_service.ConfigService.encrypt_password">encrypt_password</a></code></li>
<li><code><a title="connpy.services.config_service.ConfigService.get_default_dir" href="#connpy.services.config_service.ConfigService.get_default_dir">get_default_dir</a></code></li>
<li><code><a title="connpy.services.config_service.ConfigService.get_settings" href="#connpy.services.config_service.ConfigService.get_settings">get_settings</a></code></li>
<li><code><a title="connpy.services.config_service.ConfigService.set_config_folder" href="#connpy.services.config_service.ConfigService.set_config_folder">set_config_folder</a></code></li>
<li><code><a title="connpy.services.config_service.ConfigService.update_setting" href="#connpy.services.config_service.ConfigService.update_setting">update_setting</a></code></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.11.5</a>.</p>
</footer>
</body>
</html>