2026-04-17 18:42:08 -03:00
<!doctype html>
< html lang = "en" >
< head >
< meta charset = "utf-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1, minimum-scale=1" >
2026-05-28 18:22:00 -03:00
< meta name = "generator" content = "pdoc3 0.11.5" >
2026-04-17 18:42:08 -03:00
< title > connpy.cli.sync_handler 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.5 em }# content { padding : 20 px }# sidebar { padding : 1.5 em ; overflow : hidden }# sidebar > * : last-child { margin-bottom : 2 cm }. http-server-breadcrumbs { font-size : 130 % ; margin : 0 0 15 px 0 }# footer { font-size : .75 em ; padding : 5 px 30 px ; border-top : 1 px solid #ddd ; text-align : right }# footer p { margin : 0 0 0 1 em ; display : inline-block }# footer p : last-child { margin-right : 30 px } h1 , h2 , h3 , h4 , h5 { font-weight : 300 } h1 { font-size : 2.5 em ; line-height : 1.1 em } h2 { font-size : 1.75 em ; margin : 2 em 0 .50 em 0 } h3 { font-size : 1.4 em ; margin : 1.6 em 0 .7 em 0 } h4 { margin : 0 ; font-size : 105 % } h1 : target , h2 : target , h3 : target , h4 : target , h5 : target , h6 : target { background : var ( -- highlight - color ); padding : .2 em 0 } a { color : #058 ; text-decoration : none ; transition : color .2 s ease-in-out } a : visited { color : #503 } a : hover { color : #b62 }. title code { font-weight : bold } h2 [ id ^= "header-" ] { margin-top : 2 em }. ident { color : #900 ; font-weight : bold } pre code { font-size : .8 em ; line-height : 1.4 em ; padding : 1 em ; display : block } code { background : #f3f3f3 ; font-family : "DejaVu Sans Mono" , monospace ; padding : 1 px 4 px ; overflow-wrap : break-word } h1 code { background : transparent } pre { border-top : 1 px solid #ccc ; border-bottom : 1 px solid #ccc ; margin : 1 em 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 : 1 px solid #ddd }# index ul { padding : 0 }# index h4 { margin-top : .6 em ; 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 : 2 em } dl dl : last-child { margin-bottom : 4 em } dd { margin : 0 0 1 em 3 em }# header-classes + dl > dd { margin-bottom : 3 em } dd dd { margin-left : 2 em } dd p { margin : 10 px 0 }. name { background : #eee ; font-size : .85 em ; padding : 5 px 10 px ; 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 : .4 em }. inherited { color : #999 ; border-left : 5 px solid #eee ; padding-left : 1 em }. inheritance em { font-style : normal ; font-weight : bold }. desc h2 { font-weight : 400 ; font-size : 1.25 em }. desc h3 { font-size : 1 em }. desc dt code { background : inherit }. source > summary , . git-link-div { color : #666 ; text-align : right ; font-weight : 400 ; font-size : .8 em ; text-transform : uppercase }. source summary > * { white-space : nowrap ; cursor : pointer }. git-link { color : inherit ; margin-left : 1 em }. source pre { max-height : 500 px ; overflow : auto ; margin : 0 }. source pre code { font-size : 12 px ; 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 : 1 em } img { max-width : 100 % } td { padding : 0 .5 em }. admonition { padding : .1 em 1 em ; margin : 1 em 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 : 100 vh ; overflow : auto ; position : sticky ; top : 0 }# content { width : 70 % ; max-width : 100 ch ; padding : 3 em 4 em ; border-left : 1 px solid #ddd } pre code { font-size : 1 em }. name { font-size : 1 em } main { display : flex ; flex-direction : row-reverse ; justify-content : flex-end }. toc ul ul , # index ul ul { padding-left : 1 em }. toc > ul > li { margin-top : .5 em }}</ 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 : 1 px 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.cli.sync_handler</ 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.cli.sync_handler.SyncHandler" >< code class = "flex name class" >
< span > class < span class = "ident" > SyncHandler</ span ></ span >
< span > (</ span >< span > app)</ span >
</ code ></ dt >
< dd >
< details class = "source" >
< summary >
< span > Expand source code</ span >
</ summary >
< pre >< code class = "python" > class SyncHandler:
def __init__(self, app):
self.app = app
def dispatch(self, args):
action = getattr(args, " action" , None)
actions = {
" login" : self.login,
" logout" : self.logout,
" status" : self.status,
" list" : self.list_backups,
" once" : self.once,
" restore" : self.restore,
" start" : self.start,
" stop" : self.stop
}
handler = actions.get(action)
if handler:
return handler(args)
return self.status(args)
def login(self, args):
self.app.services.sync.login()
def logout(self, args):
self.app.services.sync.logout()
def status(self, args):
status = self.app.services.sync.check_login_status()
enabled = self.app.services.sync.sync_enabled
remote = self.app.services.sync.sync_remote
printer.info(f" Login Status: {status}" )
printer.info(f" Auto-Sync: {' Enabled' if enabled else ' Disabled' }" )
printer.info(f" Sync Remote Nodes: {' Yes' if remote else ' No' }" )
def list_backups(self, args):
backups = self.app.services.sync.list_backups()
if backups:
yaml_output = yaml.dump(backups, sort_keys=False, default_flow_style=False)
printer.custom(" backups" , "" )
print(yaml_output)
else:
printer.info(" No backups found or not logged in." )
def once(self, args):
# Manual backup. We check if we should include remote nodes
remote_data = None
if self.app.services.sync.sync_remote and self.app.services.mode == " remote" :
inventory = self.app.services.nodes.get_inventory()
# Merge with local settings
local_settings = self.app.services.config_svc.get_settings()
local_settings.pop(" configfolder" , None)
# Maintain proper config structure: {config: {}, connections: {}, profiles: {}}
remote_data = {
" config" : local_settings,
" connections" : inventory.get(" connections" , {}),
" profiles" : inventory.get(" profiles" , {})
}
if self.app.services.sync.compress_and_upload(remote_data):
printer.success(" Manual backup completed." )
def restore(self, args):
import inquirer
file_id = getattr(args, " id" , None)
# Segmented flags
restore_config = getattr(args, " restore_config" , False)
restore_nodes = getattr(args, " restore_nodes" , False)
# If neither is specified, we restore ALL (backwards compatibility)
if not restore_config and not restore_nodes:
restore_config = True
restore_nodes = True
# 1. Analyze what we are about to restore
info = self.app.services.sync.analyze_backup_content(file_id)
if not info:
printer.error(" Could not analyze backup content." )
return
# 2. Show detailed info
printer.info(" Restoration Details:" )
if restore_config:
print(f" - Local Settings: Yes" )
print(f" - RSA Key (.osk): {' Yes' if info[' has_key' ] else ' No' }" )
if restore_nodes:
target = " REMOTE" if self.app.services.mode == " remote" else " LOCAL"
print(f" - Nodes: {info[' nodes' ]}" )
print(f" - Folders: {info[' folders' ]}" )
print(f" - Profiles: {info[' profiles' ]}" )
print(f" - Destination: {target}" )
print("" )
questions = [inquirer.Confirm(" confirm" , message=" Do you want to proceed with the restoration?" , default=False)]
answers = inquirer.prompt(questions)
if not answers or not answers[" confirm" ]:
printer.info(" Restore cancelled." )
return
# 3. Perform the actual restore
if self.app.services.sync.restore_backup(
file_id=file_id,
restore_config=restore_config,
restore_nodes=restore_nodes,
app_instance=self.app
):
printer.success(" Restore completed successfully." )
def start(self, args):
self.app.services.config_svc.update_setting(" sync" , True)
self.app.services.sync.sync_enabled = True
printer.success(" Auto-sync enabled." )
def stop(self, args):
self.app.services.config_svc.update_setting(" sync" , False)
self.app.services.sync.sync_enabled = False
printer.success(" Auto-sync disabled." )</ code ></ pre >
</ details >
< div class = "desc" ></ div >
< h3 > Methods</ h3 >
< dl >
< dt id = "connpy.cli.sync_handler.SyncHandler.dispatch" >< code class = "name flex" >
< span > def < span class = "ident" > dispatch</ span ></ span > (< span > self, args)</ span >
</ code ></ dt >
< dd >
< details class = "source" >
< summary >
< span > Expand source code</ span >
</ summary >
< pre >< code class = "python" > def dispatch(self, args):
action = getattr(args, " action" , None)
actions = {
" login" : self.login,
" logout" : self.logout,
" status" : self.status,
" list" : self.list_backups,
" once" : self.once,
" restore" : self.restore,
" start" : self.start,
" stop" : self.stop
}
handler = actions.get(action)
if handler:
return handler(args)
return self.status(args)</ code ></ pre >
</ details >
< div class = "desc" ></ div >
</ dd >
< dt id = "connpy.cli.sync_handler.SyncHandler.list_backups" >< code class = "name flex" >
< span > def < span class = "ident" > list_backups</ span ></ span > (< span > self, args)</ span >
</ code ></ dt >
< dd >
< details class = "source" >
< summary >
< span > Expand source code</ span >
</ summary >
< pre >< code class = "python" > def list_backups(self, args):
backups = self.app.services.sync.list_backups()
if backups:
yaml_output = yaml.dump(backups, sort_keys=False, default_flow_style=False)
printer.custom(" backups" , "" )
print(yaml_output)
else:
printer.info(" No backups found or not logged in." )</ code ></ pre >
</ details >
< div class = "desc" ></ div >
</ dd >
< dt id = "connpy.cli.sync_handler.SyncHandler.login" >< code class = "name flex" >
< span > def < span class = "ident" > login</ span ></ span > (< span > self, args)</ span >
</ code ></ dt >
< dd >
< details class = "source" >
< summary >
< span > Expand source code</ span >
</ summary >
< pre >< code class = "python" > def login(self, args):
self.app.services.sync.login()</ code ></ pre >
</ details >
< div class = "desc" ></ div >
</ dd >
< dt id = "connpy.cli.sync_handler.SyncHandler.logout" >< code class = "name flex" >
< span > def < span class = "ident" > logout</ span ></ span > (< span > self, args)</ span >
</ code ></ dt >
< dd >
< details class = "source" >
< summary >
< span > Expand source code</ span >
</ summary >
< pre >< code class = "python" > def logout(self, args):
self.app.services.sync.logout()</ code ></ pre >
</ details >
< div class = "desc" ></ div >
</ dd >
< dt id = "connpy.cli.sync_handler.SyncHandler.once" >< code class = "name flex" >
< span > def < span class = "ident" > once</ span ></ span > (< span > self, args)</ span >
</ code ></ dt >
< dd >
< details class = "source" >
< summary >
< span > Expand source code</ span >
</ summary >
< pre >< code class = "python" > def once(self, args):
# Manual backup. We check if we should include remote nodes
remote_data = None
if self.app.services.sync.sync_remote and self.app.services.mode == " remote" :
inventory = self.app.services.nodes.get_inventory()
# Merge with local settings
local_settings = self.app.services.config_svc.get_settings()
local_settings.pop(" configfolder" , None)
# Maintain proper config structure: {config: {}, connections: {}, profiles: {}}
remote_data = {
" config" : local_settings,
" connections" : inventory.get(" connections" , {}),
" profiles" : inventory.get(" profiles" , {})
}
if self.app.services.sync.compress_and_upload(remote_data):
printer.success(" Manual backup completed." )</ code ></ pre >
</ details >
< div class = "desc" ></ div >
</ dd >
< dt id = "connpy.cli.sync_handler.SyncHandler.restore" >< code class = "name flex" >
< span > def < span class = "ident" > restore</ span ></ span > (< span > self, args)</ span >
</ code ></ dt >
< dd >
< details class = "source" >
< summary >
< span > Expand source code</ span >
</ summary >
< pre >< code class = "python" > def restore(self, args):
import inquirer
file_id = getattr(args, " id" , None)
# Segmented flags
restore_config = getattr(args, " restore_config" , False)
restore_nodes = getattr(args, " restore_nodes" , False)
# If neither is specified, we restore ALL (backwards compatibility)
if not restore_config and not restore_nodes:
restore_config = True
restore_nodes = True
# 1. Analyze what we are about to restore
info = self.app.services.sync.analyze_backup_content(file_id)
if not info:
printer.error(" Could not analyze backup content." )
return
# 2. Show detailed info
printer.info(" Restoration Details:" )
if restore_config:
print(f" - Local Settings: Yes" )
print(f" - RSA Key (.osk): {' Yes' if info[' has_key' ] else ' No' }" )
if restore_nodes:
target = " REMOTE" if self.app.services.mode == " remote" else " LOCAL"
print(f" - Nodes: {info[' nodes' ]}" )
print(f" - Folders: {info[' folders' ]}" )
print(f" - Profiles: {info[' profiles' ]}" )
print(f" - Destination: {target}" )
print("" )
questions = [inquirer.Confirm(" confirm" , message=" Do you want to proceed with the restoration?" , default=False)]
answers = inquirer.prompt(questions)
if not answers or not answers[" confirm" ]:
printer.info(" Restore cancelled." )
return
# 3. Perform the actual restore
if self.app.services.sync.restore_backup(
file_id=file_id,
restore_config=restore_config,
restore_nodes=restore_nodes,
app_instance=self.app
):
printer.success(" Restore completed successfully." )</ code ></ pre >
</ details >
< div class = "desc" ></ div >
</ dd >
< dt id = "connpy.cli.sync_handler.SyncHandler.start" >< code class = "name flex" >
< span > def < span class = "ident" > start</ span ></ span > (< span > self, args)</ span >
</ code ></ dt >
< dd >
< details class = "source" >
< summary >
< span > Expand source code</ span >
</ summary >
< pre >< code class = "python" > def start(self, args):
self.app.services.config_svc.update_setting(" sync" , True)
self.app.services.sync.sync_enabled = True
printer.success(" Auto-sync enabled." )</ code ></ pre >
</ details >
< div class = "desc" ></ div >
</ dd >
< dt id = "connpy.cli.sync_handler.SyncHandler.status" >< code class = "name flex" >
< span > def < span class = "ident" > status</ span ></ span > (< span > self, args)</ span >
</ code ></ dt >
< dd >
< details class = "source" >
< summary >
< span > Expand source code</ span >
</ summary >
< pre >< code class = "python" > def status(self, args):
status = self.app.services.sync.check_login_status()
enabled = self.app.services.sync.sync_enabled
remote = self.app.services.sync.sync_remote
printer.info(f" Login Status: {status}" )
printer.info(f" Auto-Sync: {' Enabled' if enabled else ' Disabled' }" )
printer.info(f" Sync Remote Nodes: {' Yes' if remote else ' No' }" )</ code ></ pre >
</ details >
< div class = "desc" ></ div >
</ dd >
< dt id = "connpy.cli.sync_handler.SyncHandler.stop" >< code class = "name flex" >
< span > def < span class = "ident" > stop</ span ></ span > (< span > self, args)</ span >
</ code ></ dt >
< dd >
< details class = "source" >
< summary >
< span > Expand source code</ span >
</ summary >
< pre >< code class = "python" > def stop(self, args):
self.app.services.config_svc.update_setting(" sync" , False)
self.app.services.sync.sync_enabled = False
printer.success(" Auto-sync disabled." )</ code ></ pre >
</ details >
< div class = "desc" ></ div >
</ dd >
</ dl >
</ 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.cli" href = "index.html" > connpy.cli</ a ></ code ></ li >
</ ul >
</ li >
< li >< h3 >< a href = "#header-classes" > Classes</ a ></ h3 >
< ul >
< li >
< h4 >< code >< a title = "connpy.cli.sync_handler.SyncHandler" href = "#connpy.cli.sync_handler.SyncHandler" > SyncHandler</ a ></ code ></ h4 >
< ul class = "two-column" >
< li >< code >< a title = "connpy.cli.sync_handler.SyncHandler.dispatch" href = "#connpy.cli.sync_handler.SyncHandler.dispatch" > dispatch</ a ></ code ></ li >
< li >< code >< a title = "connpy.cli.sync_handler.SyncHandler.list_backups" href = "#connpy.cli.sync_handler.SyncHandler.list_backups" > list_backups</ a ></ code ></ li >
< li >< code >< a title = "connpy.cli.sync_handler.SyncHandler.login" href = "#connpy.cli.sync_handler.SyncHandler.login" > login</ a ></ code ></ li >
< li >< code >< a title = "connpy.cli.sync_handler.SyncHandler.logout" href = "#connpy.cli.sync_handler.SyncHandler.logout" > logout</ a ></ code ></ li >
< li >< code >< a title = "connpy.cli.sync_handler.SyncHandler.once" href = "#connpy.cli.sync_handler.SyncHandler.once" > once</ a ></ code ></ li >
< li >< code >< a title = "connpy.cli.sync_handler.SyncHandler.restore" href = "#connpy.cli.sync_handler.SyncHandler.restore" > restore</ a ></ code ></ li >
< li >< code >< a title = "connpy.cli.sync_handler.SyncHandler.start" href = "#connpy.cli.sync_handler.SyncHandler.start" > start</ a ></ code ></ li >
< li >< code >< a title = "connpy.cli.sync_handler.SyncHandler.status" href = "#connpy.cli.sync_handler.SyncHandler.status" > status</ a ></ code ></ li >
< li >< code >< a title = "connpy.cli.sync_handler.SyncHandler.stop" href = "#connpy.cli.sync_handler.SyncHandler.stop" > stop</ a ></ code ></ li >
</ ul >
</ li >
</ ul >
</ li >
</ ul >
</ nav >
</ main >
< footer id = "footer" >
2026-05-28 18:22:00 -03:00
< p > Generated by < a href = "https://pdoc3.github.io/pdoc" title = "pdoc: Python API documentation generator" >< cite > pdoc</ cite > 0.11.5</ a > .</ p >
2026-04-17 18:42:08 -03:00
</ footer >
</ body >
</ html >