The branch, twofactorauth has been updated via fcb891c13b7e1d434c9f40ad522e6a52215f2f21 (commit) from df35eae6552bb6f03757ece2da849efa90ad536b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: x2go/__init__.py | 12 ++-- x2go/cleanup.py | 9 +++ x2go/client.py | 209 +++++++++++++++++++++++++++--------------------------- x2go/forward.py | 28 ++++---- x2go/guardian.py | 6 +- x2go/inifiles.py | 32 ++++----- x2go/log.py | 14 ++-- x2go/printing.py | 196 +++++++++++++++++++++++++++++++++++++------------- x2go/registry.py | 33 +++------ 9 files changed, 315 insertions(+), 224 deletions(-) The diff of changes is: diff --git a/x2go/__init__.py b/x2go/__init__.py index d93b0ce..3f30976 100644 --- a/x2go/__init__.py +++ b/x2go/__init__.py @@ -31,7 +31,7 @@ API Concept Python X2go consists of quite a few classes. Furthermore, Python X2go is quite heavily taking advantage of Python\'s - threading features. As, when providing a library like Python + threading features. When providing a library like Python X2go, it is always quite a task to keep the library code compatible with former versions of the same library. This is intended for Python X2go, but with some restraints. @@ -54,7 +54,7 @@ API Concept Any other of the Python X2go classes may be subject to internal changes and the way of addressing these classes in code may vary between versions. - If you use them, so please be warned. + If you directly use them in your own applications, so please be warned. API Structure @@ -68,11 +68,11 @@ API Structure ... - The X2goClient class flattens the complex structure behind it into many - X2goClient methods that you can use in your own C{MyX2goClient} instances. + The L{X2goClient} class flattens the complex structure of Python X2go into + many L{X2goClient} methods that you can use in your own C{MyX2goClient} instances. - However, it might be handy, to retrieve a whole X2go session instance - from the X2goClient instance. This can be achieved by the + However, it might be handy to retrieve a whole X2go session instance + from the L{X2goClient} instance. This can be achieved by the L{X2goClient.register_session()} method:: import x2go diff --git a/x2go/cleanup.py b/x2go/cleanup.py index 1c38ccd..72aa038 100644 --- a/x2go/cleanup.py +++ b/x2go/cleanup.py @@ -45,6 +45,15 @@ def x2go_cleanup(e=None, session=None, threads=[]): sys.exit(0) except (KeyboardInterrupt, SystemExit): x2go.x2go_cleanup() + + @param e: if L{x2go_cleanup} got called as we caught an exception this can be the C{Exception} that + we might process at the end of the clean-up (or if clean-up failed or was not appropriate) + @type e: C{exception} + @param session: an L{X2goSession} object + @type session: C{instance} + @param threads: a list of threads to clean up + @type threads: C{list} + """ if session is None: active_threads = threading.enumerate() diff --git a/x2go/client.py b/x2go/client.py index 75ed361..9bb7dc8 100644 --- a/x2go/client.py +++ b/x2go/client.py @@ -19,15 +19,9 @@ # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. """\ -L{X2goClient} class - use this class as parent class in your Python-based -X2go applications. - L{X2goClient} is a public API class. Use this class in your Python X2go based -applications. - -The L{X2goClient} class supports registry based multiple sessions, with it you -can gain access to you X2go client's configuration files. - +applications. Use it as a parent class for your own object oriented L{X2goClient}'ish +class implementation. Supported Features ================== @@ -35,19 +29,20 @@ Supported Features - X2go multi-session management - keep track of initiated sessions - - grant access to X2go client config files: settings, printing, sessions - as normally found in C{~/.x2goclient} + - grant access to X2go client config files: C{settings}, C{printing}, C{sessions} + and C{xconfig} (Windows only) as normally found in C{~/.x2goclient} - instantiate an X2go session by a set of Python parameters - - load a session profile from x2goclient's »sessions« configuration file - and start the in this way pre-configured session + - load a session profile from x2goclient's C{sessions} configuration file + and start the---profile-based pre-configured---session - sharing of local folders with remote X2go sessions - enabling and mangaging X2go printing (real printing, viewing as PDF, saving to a local folder or executing a custom »print« command + - transparent tunneling of audio (Pulseaudio, ESD) - LDAP support for X2go server clusters (NOT IMPLEMENTED YET) Non-Profile Sessions ==================== - A new non-profile based X2go session within an X2goClient instance is setup in the + A new non-profile based X2go session within an L{X2goClient} instance is setup in the following way: - import the Python X2go module and call the session constructor:: @@ -80,8 +75,8 @@ Non-Profile Sessions Profiled Sessions ================= - A new profile based (i.e. using pre-defined session profiles) X2go session within an - X2goClient instance is setup in a much easier way: + A new profile based X2go session (i.e. using pre-defined session profiles) within an + L{X2goClient} instance is setup in a much easier way: - import the Python X2go module and call the session constructor:: @@ -112,11 +107,11 @@ Session Suspending/Terminating You can suspend or terminate your sessions by calling the follwing commands:: - x2go_client.suspend_session(x2go_profile_id) + x2go_client.suspend_session(x2go_sess_uuid) resp.:: - x2go_client.terminate_session(x2go_profile_id) + x2go_client.terminate_session(x2go_sess_uuid) """ __NAME__ = 'x2goclient-pylib' @@ -142,13 +137,13 @@ from defaults import X2GO_CLIENT_ROOTDIR as _X2GO_CLIENT_ROOTDIR class X2goClient(object): """\ - The X2goClient implements is THE public Python X2go API. With it you can + The X2goClient implements _THE_ public Python X2go API. With it you can construct your own X2go client application in Python. Most methods in this class require that you have registered a session with a remote X2go server (passing of session options, initialization of the session object etc.) and connected to it (authentication). For these two steps - use the methods L{X2goClient.register_session()} and L{X2goClient.connect_session()}. + use these methods: L{X2goClient.register_session()} and L{X2goClient.connect_session()}. """ session_profiles = None session_registry = None @@ -162,7 +157,7 @@ class X2goClient(object): @type logger: L{X2goLogger} instance @param loglevel: if no X2goLogger object has been supplied a new one will be constructed with the given loglevel - @type loglevel: int + @type loglevel: C{int} """ if logger is None: @@ -183,7 +178,7 @@ class X2goClient(object): Query the local user's username (i.e. the user running the X2go client). @return: the local username this X2goClient instance runs as - @rtype: str + @rtype: C{str} """ return _CURRENT_LOCAL_USER @@ -201,42 +196,46 @@ class X2goClient(object): A profile is a pre-defined set of session options stored in a sessions - profile file (i.e. a configuration file). Normally such a session profiles are - is stored in C{~/.x2goclient/sessions} or globally (for all users on the - client) in /etc/x2goclient/sessions. If needed, you can also create multiple - X2go sessions from one session profile. + profile file (i.e. a configuration file). Normally such session profiles are + stored in C{~/.x2goclient/sessions} or globally (for all users on the + client) in C{/etc/x2goclient/sessions}. + + Of coures, Python X2go supports starting multiple X2go sessions from the same + session profile simultaneously. - L{X2goClient.register_session()} accepts the same set of parameters - as the L{X2goSession} constructor. + This method (L{X2goClient.register_session()}) accepts a similar set of parameters + as the L{X2goSession} constructor itself. Alternatively, you can also pass a profile name or a profile id - to this method. When this is done, all session parameters are first derived - from the session's profile. Additional X2goSession parameters passed to - this method will override the option value in the session profile. + to this method. When this is done, Python X2go tries to find the specified session + in the C{sessions} configuration and then derives the necessary session parameters + from the session's profile configuration. Additional L{X2goSession} parameters can + also be passed to this method, they will override the option values retrieved from + the session profile. @param server: hostname of the remote X2go server - @type server: str + @type server: C{str} @param profile_id: id (config section name) of a session profile to load from your session config - @type profile_id: str + @type profile_id: C{str} @param profile_name: name of a session profile to load from your session config - @type profile_name: str + @type profile_name: C{str} @param printing: enable X2go printing support for the to-be-registered X2go session - @type printing: bool + @type printing: C{bool} @param share_local_folders: a list of local folders (as strings) to be shared directly after session start up @type share_local_folders: list @param return_object: normally this method returns a unique session UUID. If C{return_object} is set to C{True} an X2goRegisteredSession object will be returned instead - @type return_object: bool + @type return_object: C{bool} @param kwargs: any option that is also valid for L{X2goSession.__init__()} - @type kwargs: dict + @type kwargs: C{dict} @return: a unique identifier (UUID) for the newly registered X2go session (or an X2goRegisteredSession object if C{return_object} is set to True - @rtype: str + @rtype: C{str} """ if profile_id and self.session_profiles.has_profile_id(profile_id): @@ -285,14 +284,14 @@ class X2goClient(object): def get_session_username(self, session_uuid): """\ - After an X2go session has been setup up you can query the + After an X2go session has been set up you can query the username the remote sessions runs as. @param session_uuid: the X2go session's UUID registry hash - @type session_uuid: str + @type session_uuid: C{str} @return: the remote username the X2go session runs as - @rtype: str + @rtype: C{str} """ return self.session_registry(session_uuid).get_username() @@ -300,12 +299,12 @@ class X2goClient(object): def get_session_server(self, session_uuid): """\ - After a session has been setup up you can query the + After a session has been set up you can query the hostname of the host the session is connected to (or about to connect to). @param session_uuid: the X2go sessions UUID registry hash - @type session_uuid: str + @type session_uuid: C{str} @return: the host an X2go session is connected to (as an C{(addr,port)} tuple) @@ -317,19 +316,19 @@ class X2goClient(object): def get_session(self, session_uuid): """\ - Retrieve the complete X2goSession object that has been + Retrieve the complete L{X2goSession} object that has been registered under the given session registry hash. - This method exist mainly for debugging. The returned - X2goSession class is not a Python X2go public API class. - If you use it in your applications, note that method names + NOTE: This method exist mainly for debugging and internal use. The returned + L{X2goSession} class is not a Python X2go public API class. + If you use it in your applications, note that method names and options or syntax might change in the future. To retrieve a public API based session object, use the L{get_registered_session()}. @param session_uuid: the X2go session's UUID registry hash - @type session_uuid: str + @type session_uuid: C{str} @return: the L{X2goSession} instance @rtype: obj @@ -338,17 +337,19 @@ class X2goClient(object): return self.session_registry(session_uuid).session_object __get_session = get_session with_session = __get_session + """Alias for L{get_session()}.""" def get_registered_session(self, session_uuid): """\ - Retrieve the complete X2goRegisteredSession object that has been + Retrieve the complete L{X2goRegisteredSession} object that has been registered under the given session registry hash. - X2goRegisteredSession is one of Python X2go's public API classes - and may safely be used in user applications. + L{X2goRegisteredSession} is one of Python X2go's public API classes + and may safely be used in user applications to operate on individual + sessions. @param session_uuid: the X2go session's UUID registry hash - @type session_uuid: str + @type session_uuid: C{str} @return: the L{X2goRegisteredSession} instance @rtype: obj @@ -357,6 +358,7 @@ class X2goClient(object): return self.session_registry(session_uuid) __get_registered_session = get_registered_session with_registered_session = __get_registered_session + """Alias for L{get_registered_session()}.""" def get_session_name(self, session_uuid): """\ @@ -364,10 +366,10 @@ class X2goClient(object): been registered under C{session_uuid}. @param session_uuid: the X2go session's UUID registry hash - @type session_uuid: str + @type session_uuid: C{str} @return: X2go session name - @rtype: str + @rtype: C{str} """ return self.session_registry(session_uuid).get_session_name() @@ -380,20 +382,20 @@ class X2goClient(object): corresponding session. @param session_uuid: the X2go session's UUID registry hash - @type session_uuid: str + @type session_uuid: C{str} @param password: the user's password for the X2go server that is going to be connected to - @type password: str + @type password: C{str} @param add_to_known_hosts: non-Paramiko option, if C{True} paramiko.AutoAddPolicy() is used as missing-host-key-policy. If set to C{False} paramiko.RejectPolicy() is used - @type add_to_known_hosts: bool + @type add_to_known_hosts: C{bool} @param force_password_auth: disable SSH pub/priv key authentication mechanisms completely - @type force_password_auth: bool + @type force_password_auth: C{bool} @return: returns True if this method has been successful - @rtype: bool + @rtype: C{bool} """ return self.session_registry(session_uuid).connect(password=password, @@ -407,29 +409,30 @@ class X2goClient(object): If X2go client-side printing is enable within an X2go session you can use this method to alter the way how incoming print spool jobs are handled/processed. - Currently, there are four different print actions available, define as individual - print action classes: + Currently, there are four different print actions available, each defined as an individual + print action class: - - B{PDFVIEW} (L{X2goPrintActionPDFVIEW}): view incoming spool jobs (a PDF file) + - B{PDFVIEW} (L{X2goPrintActionPDFVIEW}): view an incoming spool job (a PDF file) locally in a PDF viewer - - B{PDFSAVE} (L{X2goPrintActionPDFSAVE}): save incoming spool jobs (a PDF file) + - B{PDFSAVE} (L{X2goPrintActionPDFSAVE}): save an incoming spool job (a PDF file) under a nice name in a designated folder - - B{PRINT} (L{X2goPrintActionPRINT}): really print the incoming spool job + - B{PRINT} (L{X2goPrintActionPRINT}): really print the incoming spool job on a real printing device - B{PRINTCMD} L{X2goPrintActionPRINTCMD}: on each incoming spool job execute an external command that lets the client user handle the further processing of the - print job file (PDF file) + print job (PDF) file Each of the print action classes accepts different print action arguments. For detail - information on this please refer to the constructor methods of each class individually. + information on these print action arguments please refer to the constructor methods of + each class individually. @param session_uuid: the X2go session's UUID registry hash - @type session_uuid: str + @type session_uuid: C{str} @param print_action: one of the named above print actions, either as string or class instance - @type print_action: str or instance + @type print_action: C{str} or C{instance} @param kwargs: additional information for the given print action (print action arguments), for possible print action arguments and their values see each individual print action class - @type kwargs: dict + @type kwargs: C{dict} """ self.session_registry(session_uuid).set_print_action(print_action=print_action, **kwargs) @@ -438,7 +441,7 @@ class X2goClient(object): def start_session(self, session_uuid): """\ Start a new X2go session on the remote X2go server. This method - will open---if everything has been successful till here--the X2go + will open---if everything has been successful till here---the X2go session window. Before calling this method you have to register your desired session @@ -446,10 +449,10 @@ class X2goClient(object): connect to it with L{connect_session} (authentication). @param session_uuid: the X2go sessions UUID registry hash - @type session_uuid: str + @type session_uuid: C{str} @return: returns True if this method has been successful - @rtype: bool + @rtype: C{bool} """ return self.session_registry(session_uuid).start() @@ -462,12 +465,12 @@ class X2goClient(object): called). @param session_uuid: the X2go session's UUID registry hash - @type session_uuid: str + @type session_uuid: C{str} @param session_name: the server-side name of an X2go session - @type session_name: str + @type session_name: C{str} @return: returns True if this method has been successful - @rtype: bool + @rtype: C{bool} """ return self.session_registry(session_uuid).resume(session_name) @@ -491,13 +494,13 @@ class X2goClient(object): name (as shown e.g. in x2golistsessions output). @param session_uuid: the X2go session's UUID registry hash - @type session_uuid: str + @type session_uuid: C{str} @param session_name: the server-side name of an X2go session (for non-associated session suspend) - @type session_name: str + @type session_name: C{str} @return: returns True if this method has been successful - @rtype: bool + @rtype: C{bool} """ if session_name: @@ -531,12 +534,12 @@ class X2goClient(object): server-side X2go session name to this method. @param session_uuid: the X2go session's UUID registry hash - @type session_uuid: str + @type session_uuid: C{str} @param session_name: the server-side name of an X2go session - @type session_name: str + @type session_name: C{str} @return: returns True if this method has been successful - @rtype: bool + @rtype: C{bool} """ if session_name: @@ -561,10 +564,10 @@ class X2goClient(object): instantiated this X2goClient object. @param session_uuid: the X2go session's UUID registry hash - @type session_uuid: str + @type session_uuid: C{str} @return: X2go session profile name - @rtype: str + @rtype: C{str} """ return self.session_registry(session_uuid).get_profile_name() @@ -584,10 +587,10 @@ class X2goClient(object): X2go session registration by C{register_session}. @param session_uuid: the session profile name - @type session_uuid: str + @type session_uuid: C{str} @return: the X2go session profile's id - @rtype: str + @rtype: C{str} """ return self.session_registry(session_uuid).profile_id @@ -599,10 +602,10 @@ class X2goClient(object): in a healthy state. @param session_uuid: the X2go session's UUID registry hash - @type session_uuid: str + @type session_uuid: C{str} @return: C{True} if session is ok, C{False} otherwise - @rtype: bool + @rtype: C{bool} """ return self.session_registry(session_uuid).session_ok() @@ -614,10 +617,10 @@ class X2goClient(object): and running. @param session_uuid: the X2go session's UUID registry hash - @type session_uuid: str + @type session_uuid: C{str} @return: C{True} if session is running, C{False} otherwise - @rtype: bool + @rtype: C{bool} """ return self.session_registry(session_uuid).is_running() @@ -629,10 +632,10 @@ class X2goClient(object): is in suspended state. @param session_uuid: the X2go session's UUID registry hash - @type session_uuid: str + @type session_uuid: C{str} @return: C{True} if session is suspended, C{False} otherwise - @rtype: bool + @rtype: C{bool} """ return self.session_registry(session_uuid).is_suspended() @@ -644,10 +647,10 @@ class X2goClient(object): has terminated. @param session_uuid: the X2go session's UUID registry hash - @type session_uuid: str + @type session_uuid: C{str} @return: C{True} if session has terminated, C{False} otherwise - @rtype: bool + @rtype: C{bool} """ return self.session_registry(session_uuid).has_terminated() @@ -662,13 +665,13 @@ class X2goClient(object): desktop icon on your remote session's desktop. @param session_uuid: the X2go session's UUID registry hash - @type session_uuid: str + @type session_uuid: C{str} @param folder_name: the full path to an existing folder on the local (client-side) file system - @type folder_name: str + @type folder_name: C{str} @return: returns C{True} if the local folder has been successfully mounted - @rtype: bool + @rtype: C{bool} """ return self.session_registry(session_uuid).share_local_folder(folder_name=folder_name) @@ -689,7 +692,7 @@ class X2goClient(object): L{X2goClient.connect_session()}. @param session_uuid: the X2go session's UUID registry hash - @type session_uuid: str + @type session_uuid: C{str} """ session = self.session_registry(session_uuid).session_object @@ -710,7 +713,7 @@ class X2goClient(object): L{X2goClient.connect_session()}. @param session_uuid: the X2go session's UUID registry hash - @type session_uuid: str + @type session_uuid: C{str} """ session = self.session_registry(session_uuid).session_object @@ -768,10 +771,10 @@ class X2goClient(object): @param profile_id_or_name: name or id of an X2go session profile as found in the sessions configuration file - @type profile_id_or_name: str + @type profile_id_or_name: C{str} @return: a Python dictionary with session profile options - @rtype: dict + @rtype: C{dict} """ return self.session_profiles.get_profile_config(profile_id_or_name) @@ -784,10 +787,10 @@ class X2goClient(object): is C{profile_name} @param profile_name: the session profile name - @type profile_name: str + @type profile_name: C{str} @return: the session profile's id - @rtype: str + @rtype: C{str} """ return self.session_profiles.get_profile_id(profile_name) @@ -799,10 +802,10 @@ class X2goClient(object): is C{profile_id} @param profile_id: the session profile id - @type profile_id: str + @type profile_id: C{str} @return: the session profile's name - @rtype: str + @rtype: C{str} """ return self.session_profiles.get_profile_name(profile_id) diff --git a/x2go/forward.py b/x2go/forward.py index 7e0d476..e8f9d2c 100644 --- a/x2go/forward.py +++ b/x2go/forward.py @@ -42,19 +42,19 @@ class X2goFwServer(StreamServer): through an external proxy command launched by L{X2goProxy}. @param listener: listen on TCP/IP socket C{(<IP>, <Port>)} - @type listener: tuple + @type listener: C{tuple} @param remote_host: hostname or IP of remote host (in case of X2go mostly localhost) - @type remote_host: str + @type remote_host: C{str} @param remote_port: port of remote host - @type remote_port: int + @type remote_port: C{int} @param ssh_transport: a valid Paramiko/SSH transport object - @type ssh_transport: class + @type ssh_transport: C{instance} @param logger: you can pass an L{X2goLogger} object to the L{X2goFwServer} constructor - @type logger: L{X2goLogger} instance + @type logger: C{instance} @param loglevel: if no L{X2goLogger} object has been supplied a new one will be constructed with the given loglevel - @type loglevel: int + @type loglevel: C{int} """ def __init__ (self, listener, remote_host, remote_port, ssh_transport, logger=None, loglevel=log.loglevel_DEFAULT,): @@ -75,9 +75,9 @@ class X2goFwServer(StreamServer): Handle for SSH/Paramiko forwarding tunnel. @param fw_socket: local end of the forwarding tunnel - @type fw_socket: class + @type fw_socket: C{instance} @param address: unused/ignored - @type address: tuple + @type address: C{tuple} """ try: @@ -127,17 +127,17 @@ def start_forward_tunnel(local_port, remote_host, remote_port, ssh_transport, lo The tunnel is used to transport X2go graphics data through a proxy application like nxproxy. @param local_port: local starting point of the forwarding tunnel - @type local_port: int + @type local_port: C{int} @param remote_host: from the endpoint of the tunnel, connect to host C{<remote_host>}... - @type remote_host: str + @type remote_host: C{str} @param remote_port: ... on port C{<remote_port>} - @type remote_port: int + @type remote_port: C{int} @param ssh_transport: the Paramiko/SSH transport (i.e. the X2go sessions Paramiko/SSH transport object) @param logger: an X2goLogger object - @type logger: class + @type logger: C{instance} @return: returns an L{X2goFwServer} instance - @rtype: instance + @rtype: C{instance} """ fw_server = X2goFwServer(('localhost', local_port), remote_host, remote_port, ssh_transport, logger=logger) @@ -153,7 +153,7 @@ def stop_forward_tunnel(fw_server): Tear down a given Paramiko/SSH port forwarding tunnel. @param fw_server: an L{X2goFwServer} instance as returned by the L{start_forward_tunnel()} function - @type fw_server: instance + @type fw_server: C{instance} """ fw_server.stop() diff --git a/x2go/guardian.py b/x2go/guardian.py index 748d019..4c2fa8d 100644 --- a/x2go/guardian.py +++ b/x2go/guardian.py @@ -59,12 +59,12 @@ class X2goSessionGuardian(threading.Thread): def __init__(self, session, logger=None, loglevel=log.loglevel_DEFAULT): """\ @param session: the L{X2goSession} that is controlled by this L{X2goSessionGuardian} - @type session: L{X2goSession} instance + @type session: C{instance} @param logger: you can pass an L{X2goLogger} object to the L{X2goSessionGuardian} constructor - @type logger: L{X2goLogger} instance + @type logger: C{instance} @param loglevel: if no L{X2goLogger} object has been supplied a new one will be constructed with the given loglevel - @type loglevel: int + @type loglevel: C{int} """ if logger is None: diff --git a/x2go/inifiles.py b/x2go/inifiles.py index 5ddd441..24282b5 100644 --- a/x2go/inifiles.py +++ b/x2go/inifiles.py @@ -64,9 +64,9 @@ class X2goIniFile(object): """\ @param config_files: a list of configuration files names (e.g. a global filename and a user's home directory filename) - @type config_files: list + @type config_files: C{list} @param defaults: a cascaded Python dicitionary structure with ini file defaults (to override - Python X2go's hard coded defaults in L{default} + Python X2go's hard coded defaults in L{defaults} @type defaults: dict @param logger: you can pass an L{X2goLogger} object to the L{X2goFwServer} constructor @@ -122,11 +122,11 @@ class X2goIniFile(object): method. @param section: the ini file section - @type section: str + @type section: C{str} @param key: the ini file key in the given section - @type key: str + @type key: C{str} @param value: the value for the given section and key - @type value: str, list, bool, ... + @type value: C{str}, C{list}, C{bool}, ... """ if type(value) is types.StringType: @@ -158,11 +158,11 @@ class X2goIniFile(object): does not have any effect on configuration files. @param section: the ini file section - @type section: str + @type section: C{str} @param key: the ini file key in the given section - @type key: str + @type key: C{str} @param value: the value for the given section and key - @type value: str, list, bool, ... + @type value: C{str}, C{list}, C{bool}, ... """ if not self.iniConfig.has_section(section): @@ -187,13 +187,13 @@ class X2goIniFile(object): def get_type(self, section, key): """\ - Retrieve a value type for a given section section and key. The returned + Retrieve a value type for a given section and key. The returned value type is based on the default values dictionary. @param section: the ini file section - @type section: str + @type section: C{str} @param key: the ini file key in the given section - @type key: str + @type key: C{str} @return: a Python variable type @rtype: class @@ -206,9 +206,9 @@ class X2goIniFile(object): Retrieve a value for a given section and key. @param section: the ini file section - @type section: str + @type section: C{str} @param key: the ini file key in the given section - @type key: str + @type key: C{str} @return: the value for the given section and key @rtype: class @@ -254,11 +254,7 @@ class X2goIniFile(object): @property def printable_config_file(self): """\ - Returns a printable configuration file. - - @return: multi-line string that looks like an ini configuration file - when printed - @rtype: str + Returns a printable configuration file as a multi-line string. """ stdout = cStringIO.StringIO() diff --git a/x2go/log.py b/x2go/log.py index bff885c..638296e 100644 --- a/x2go/log.py +++ b/x2go/log.py @@ -60,11 +60,11 @@ class X2goLogger(object): def __init__(self, name=sys.argv[0], loglevel=loglevel_DEFAULT, tag=None): """\ @param name: name of the programme that uses Python X2go - @type name: str + @type name: C{str} @param loglevel: log level for Python X2go - @type loglevel: int + @type loglevel: C{int} @param tag: additional tag for all log entries - @type tag: str + @type tag: C{str} """ self.name = os.path.basename(name) @@ -77,11 +77,11 @@ class X2goLogger(object): Log a message. @param msg: log message text - @type msg: str + @type msg: C{str} @param loglevel: log level of this message - @type loglevel: int + @type loglevel: C{int} @param tag: additional tag for this log entry - @type tag: str + @type tag: C{str} """ if tag is None: @@ -98,7 +98,7 @@ class X2goLogger(object): Set log level by name. @param loglevel_name: name of loglevel to be set - @type loglevel_name: str + @type loglevel_name: C{str} """ if type(loglevel_name) is types.IntegerType: diff --git a/x2go/printing.py b/x2go/printing.py index 29add2e..1d360de 100644 --- a/x2go/printing.py +++ b/x2go/printing.py @@ -87,16 +87,16 @@ class X2goClientPrinting(inifiles.X2goIniFile): """\ @param config_files: a list of configuration files names (e.g. a global filename and a user's home directory filename) - @type config_files: list + @type config_files: C{list} @param defaults: a cascaded Python dicitionary structure with ini file defaults (to override - Python X2go's hard coded defaults in L{default} - @type defaults: dict + Python X2go's hard coded defaults in L{defaults} + @type defaults: C{dict} @param logger: you can pass an L{X2goLogger} object to the L{X2goPrintAction} constructor - @type logger: L{X2goLogger} instance + @type logger: C{instance} @param loglevel: if no L{X2goLogger} object has been supplied a new one will be constructed with the given loglevel - @type loglevel: int + @type loglevel: C{int} """ inifiles.X2goIniFile.__init__(self, config_files, defaults=defaults, logger=logger, loglevel=loglevel) @@ -150,10 +150,10 @@ class X2goPrintAction(object): @param logger: you can pass an L{X2goLogger} object to the L{X2goPrintAction} constructor - @type logger: L{X2goLogger} instance + @type logger: C{instance} @param loglevel: if no L{X2goLogger} object has been supplied a new one will be constructed with the given loglevel - @type loglevel: int + @type loglevel: C{int} """ if logger is None: @@ -167,9 +167,6 @@ class X2goPrintAction(object): """\ Return the X2go print action's name. - @return: the print action's name - @rtype: string - """ return self.__name__ @@ -178,16 +175,20 @@ class X2goPrintAction(object): """\ Return the X2go print action's description text. - @return: the print action\'s description - @rtype: string - """ return self.__description__ - def do_print(self, pdf_file, job_title): + def do_print(self, pdf_file, job_title, spool_dir, ): """\ Perform the defined print action (doing nothing in L{X2goPrintAction} parent class). + @param pdf_file: PDF file name as placed in to the X2go spool directory + @type pdf_file: C{str} + @param job_title: human readable print job title + @type job_title: C{str} + @param spool_dir: location of the X2go client's spool directory + @type spool_dir: C{str} + """ pass @@ -216,26 +217,34 @@ class X2goPrintActionPDFVIEW(X2goPrintAction): pdfview_cmd = None - def __init__(self, pdfview_cmd=None, **kwargs): + def __init__(self, pdfview_cmd=None, logger=None, loglevel=log.loglevel_DEFAULT): """\ @param pdfview_cmd: command that starts the external PDF viewer application - @type pdfview_cmd: string + @type pdfview_cmd: C{str} @param logger: you can pass an L{X2goLogger} object to the - L{X2goPrintAction} constructor - @type logger: L{X2goLogger} instance + L{X2goPrintActionPDFVIEW} constructor + @type logger: C{instance} @param loglevel: if no L{X2goLogger} object has been supplied a new one will be constructed with the given loglevel - @type loglevel: int + @type loglevel: C{int} """ if pdfview_cmd is None: pdfview_cmd = defaults.DEFAULT_PDFVIEW_CMD self.pdfview_cmd = pdfview_cmd - X2goPrintAction.__init__(self, **kwargs) + X2goPrintAction.__init__(self, logger=logger, loglevel=loglevel) def do_print(self, pdf_file, job_title, spool_dir, ): """\ - STILL UNDOCUMENTED + Open an incoming X2go print job (PDF file) in an external PDF viewer application. + + @param pdf_file: PDF file name as placed in to the X2go spool directory + @type pdf_file: C{str} + @param job_title: human readable print job title + @type job_title: C{str} + @param spool_dir: location of the X2go client's spool directory + @type spool_dir: C{str} + """ _hr_filename = self._humanreadable_filename(pdf_file, job_title, spool_dir, ) shutil.copy2(pdf_file, _hr_filename) @@ -254,7 +263,7 @@ class X2goPrintActionPDFVIEW(X2goPrintAction): class X2goPrintActionPDFSAVE(X2goPrintAction): """\ - STILL UNDOCUMENTED + Print action that saves incoming print jobs to a local folder. """ __name__ = 'PDFSAVE' @@ -262,19 +271,33 @@ class X2goPrintActionPDFSAVE(X2goPrintAction): save_to_folder = None - def __init__(self, save_to_folder=None, *args, **kwargs): + def __init__(self, save_to_folder=None, logger=None, loglevel=log.loglevel_DEFAULT): """\ - STILL UNDOCUMENTED + @param save_to_folder: saving location for incoming print jobs (PDF files) + @type save_to_folder: C{str} + @param logger: you can pass an L{X2goLogger} object to the + L{X2goPrintActionPDFSAVE} constructor + @type logger: C{instance} + @param loglevel: if no L{X2goLogger} object has been supplied a new one will be + constructed with the given loglevel + @type loglevel: C{int} """ if save_to_folder is None: save_to_folder = os.path.expanduser(defaults.DEFAULT_PDFSAVE_LOCATION) self.save_to_folder = save_to_folder - X2goPrintAction.__init__(self, *args, **kwargs) + X2goPrintAction.__init__(self, logger=None, loglevel=loglevel) - def do_print(self, pdf_file, job_title, spool_dir, ): + def do_print(self, pdf_file, job_title, spool_dir): """\ - STILL UNDOCUMENTED + Save an incoming X2go print job (PDF file) to a local folder. + + @param pdf_file: PDF file name as placed in to the X2go spool directory + @type pdf_file: C{str} + @param job_title: human readable print job title + @type job_title: C{str} + @param spool_dir: location of the X2go client's spool directory + @type spool_dir: C{str} """ dest_file = self._humanreadable_filename(pdf_file, job_title, target_path=self.save_to_folder) @@ -287,23 +310,37 @@ class X2goPrintActionPDFSAVE(X2goPrintAction): class X2goPrintActionPRINT(X2goPrintAction): """\ - STILL UNDOCUMENTED + Print action that actually prints an incoming print job file. """ __name__ = 'PRINT' __decription__= 'UNIX/Win32GDI printing' - def __init__(self, printer=None, *args, **kwargs): + def __init__(self, printer=None, logger=None, loglevel=log.loglevel_DEFAULT): """\ - STILL UNDOCUMENTED + @param printer: name of the preferred printer, if C{None} the system's/user's default printer will be used + @type printer: C{str} + @param logger: you can pass an L{X2goLogger} object to the + L{X2goPrintAction} constructor + @type logger: C{instance} + @param loglevel: if no L{X2goLogger} object has been supplied a new one will be + constructed with the given loglevel + @type loglevel: C{int} """ self.printer = printer - X2goPrintAction.__init__(self, *args, **kwargs) + X2goPrintAction.__init__(self, logger=logger, loglevel=loglevel) def do_print(self, pdf_file, job_title, spool_dir, ): """\ - STILL UNDOCUMENTED + Actually really print an incoming X2go print job (PDF file) to a local printer device. + + @param pdf_file: PDF file name as placed in to the X2go spool directory + @type pdf_file: C{str} + @param job_title: human readable print job title + @type job_title: C{str} + @param spool_dir: location of the X2go client's spool directory + @type spool_dir: C{str} """ _hr_filename = self._humanreadable_filename(pdf_file, job_title, spool_dir) @@ -343,26 +380,61 @@ class X2goPrintActionPRINT(X2goPrintAction): class X2goPrintActionPRINTCMD(X2goPrintAction): """\ - STILL UNDOCUMENTED + Print action that calls an external command for further processing of incoming print jobs. + + The print job's PDF filename will be prepended as last argument to the print command + used in L{X2goPrintActionPRINTCMD} instances. """ __name__ = 'PRINTCMD' __decription__= 'Print via a command (like LPR)' - def __init__(self, print_cmd=None, *args, **kwargs): + def __init__(self, print_cmd=None, logger=None, loglevel=log.loglevel_DEFAULT): """\ - STILL UNDOCUMENTED + @param print_cmd: external command to be called on incoming print jobs + @type print_cmd: C{str} + @param logger: you can pass an L{X2goLogger} object to the + L{X2goPrintAction} constructor + @type logger: C{instance} + @param loglevel: if no L{X2goLogger} object has been supplied a new one will be + constructed with the given loglevel + @type loglevel: C{int} """ if print_cmd is None: print_cmd = defaults.DEFAULT_PRINTCMD_CMD self.print_cmd = print_cmd - X2goPrintAction.__init__(self, *args, **kwargs) + X2goPrintAction.__init__(self, logger=logger, loglevel=loglevel) + + def do_print(self, pdf_file, job_title, spool_dir): + """\ + Execute an external command that has been defined on construction + of this L{X2goPrintActionPRINTCMD} instance. + + @param pdf_file: PDF file name as placed in to the X2go spool directory + @type pdf_file: C{str} + @param job_title: human readable print job title + @type job_title: C{str} + @param spool_dir: location of the X2go client's spool directory + @type spool_dir: C{str} + + """ + _hr_filename = self._humanreadable_filename(pdf_file, job_title, spool_dir) + shutil.copy2(pdf_file, _hr_filename) + self.logger('executing external command »%s« on PDF file %s' % (self.print_cmd, _hr_filename), loglevel=log.loglevel_NOTICE) + cmd_line = self.print_cmd.split() + cmd_line.append(_hr_filename) + self.logger('executing external command: %s' % " ".join(cmd_line), loglevel=log.loglevel_DEBUG) + p = subprocess.Popen(cmd_line, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=_PRINT_ENV) + + # this is nasty!!!! + gevent.sleep(20) class X2goPrintQueue(threading.Thread): """\ - STILL UNDOCUMENTED + If X2go printing is supported in a particaluar L{X2goSession} instance + this class provides a sub-thread for handling incoming X2go print jobs. """ print_action = None @@ -371,16 +443,19 @@ class X2goPrintQueue(threading.Thread): active_jobs = {} job_history = [] - def __init__(self, spool_dir=None, print_action=None, print_action_args={}, logger=None, loglevel=log.loglevel_DEFAULT): + def __init__(self, print_action=None, print_action_args={}, logger=None, loglevel=log.loglevel_DEFAULT): """\ - STILL UNDOCUMENTED - + @param print_action: name or instance of either of the possible X2go print action classes + @type print_action: C{str} or instance + @param print_action_args: depending of the chosen C{print_action} this dictionary may contain different + values; the C{print_action_args} will be passed on to the X2go print action instance constructor, so + refer to either of these: L{X2goPrintActionPDFVIEW.__init__()}, L{X2goPrintActionPRINT.__init__()} et al. @param logger: you can pass an L{X2goLogger} object to the L{X2goProxy} constructor - @type logger: L{X2goLogger} instance + @type logger: C{instance} @param loglevel: if no L{X2goLogger} object has been supplied a new one will be constructed with the given loglevel - @type loglevel: int + @type loglevel: C{int} """ if logger is None: @@ -389,7 +464,6 @@ class X2goPrintQueue(threading.Thread): self.logger = copy.deepcopy(logger) self.logger.tag = __NAME__ - self.spool_dir = spool_dir if print_action is not None: self.set_print_action(print_action, logger=logger, **print_action_args) threading.Thread.__init__(self) @@ -421,7 +495,7 @@ class X2goPrintQueue(threading.Thread): def stop_thread(self): """\ - Stops this L{X2goRevFwTunnel} thread completely. + Stops this L{X2goPrintQueue} thread completely. """ self.pause() @@ -444,7 +518,8 @@ class X2goPrintQueue(threading.Thread): def set_print_action(self, print_action, **kwargs): """\ - STILL UNDOCUMENTED + Modify the print action of this L{X2goPrintQueue} thread during runtime. The + change of print action will be valid for the next incoming print job. """ if print_action in defaults.X2GO_PRINT_ACTIONS.keys(): @@ -455,7 +530,7 @@ class X2goPrintQueue(threading.Thread): def run(self): """\ - STILL UNDOCUMENTED + Start this L{X2goPrintQueue} thread... """ self.logger('starting print queue thread: %s' % repr(self), loglevel=log.loglevel_DEBUG) @@ -489,7 +564,23 @@ class X2goPrintQueue(threading.Thread): def x2go_printjob_handler(job_file=None, pdf_file=None, job_title=None, print_action=None, parent_thread=None, logger=None, ): """\ - STILL UNDOCUMENTED + This function is called as a handler function for each incoming X2go print job + represented by the class L{X2goPrintJob}. + + The handler function will (re-)read the »printing« configuration file (if no + explicit C{print_action} is passed to this function...). It then will + execute the C{<print_action>.do_print()} command. + + @param pdf_file: PDF file name as placed in to the X2go spool directory + @type pdf_file: C{str} + @param job_title: human readable print job title + @type job_title: C{str} + @param print_action: an instance of either of the possible C{X2goPrintActionXXX} classes + @type print_action: C{X2goPrintActionXXX} nstance + @param parent_thread: the L{X2goPrintQueue} thread that actually created this handler's L{X2goPrintJob} instance + @type parent_thread: C{instance} + @param logger: the L{X2goPrintQueue}'s logging instance + @type logger: C{instance} """ if print_action is None: @@ -512,12 +603,19 @@ def x2go_printjob_handler(job_file=None, pdf_file=None, job_title=None, print_ac class X2goPrintJob(threading.Thread): """\ - STILL UNDOCUMENTED + For each X2go print job we create a sub-thread that let's + the print job be processed in the background. + + As a handler for this class the function L{x2go_printjob_handler()} + is used. """ def __init__(self, **kwargs): """\ - STILL UNDOCUMENTED + Construct the X2go print job thread... + + All parameters (**kwargs) are passed through to the constructor + of C{threading.Thread()}. """ threading.Thread.__init__(self, **kwargs) diff --git a/x2go/registry.py b/x2go/registry.py index 74bf195..afdf5a9 100644 --- a/x2go/registry.py +++ b/x2go/registry.py @@ -231,12 +231,7 @@ class X2goRegisteredSession(object): def get_profile_name(self): """\ - Retrieve the profile name of the session that has been registered - under C{session_hash} - - - @param session_hash: the X2go session's UUID registry hash - @type session_hash: str + Retrieve the profile name of this registered session. @return: X2go client profile name of the session @rtype: str @@ -247,11 +242,7 @@ class X2goRegisteredSession(object): def get_profile_id(self): """\ - Retrieve the session profile id of the session whose profile name - is C{profile_name} - - @param profile_name: the session profile name - @type profile_name: str + Retrieve this registered session's profile id. @return: the session profile's id @rtype: str @@ -266,12 +257,9 @@ class X2goRegisteredSession(object): def session_ok(self): """\ - Test if the X2go session registered as C{session_uuid} is + Test if this registered X2go session is in a healthy state. - @param session_uuid: the X2go session's UUID registry hash - @type session_uuid: str - @return: C{True} if session is ok, C{False} otherwise @rtype: bool @@ -281,8 +269,7 @@ class X2goRegisteredSession(object): def is_running(self): """\ - Test if the X2go session registered as C{session_uuid} is up - and running. + Test if this registered X2go session is up and running. @return: C{True} if session is running, C{False} otherwise @rtype: bool @@ -293,8 +280,7 @@ class X2goRegisteredSession(object): def is_suspended(self): """\ - Test if the X2go session registered as C{session_uuid} - is in suspended state. + Test if this registered X2go session is in suspended state. @return: C{True} if session is suspended, C{False} otherwise @rtype: bool @@ -305,8 +291,7 @@ class X2goRegisteredSession(object): def has_terminated(self): """\ - Test if the X2go session registered as C{session_uuid} - has terminated. + Test if this registered X2go session has terminated. @return: C{True} if session has terminated, C{False} otherwise @rtype: bool @@ -317,14 +302,14 @@ class X2goRegisteredSession(object): def share_local_folder(self, folder_name): """\ - Share a local folder with the X2go session registered as C{session_uuid}. + Share a local folder with this registered X2go session. @param folder_name: the full path to an existing folder on the local file system @type folder_name: str - @return: returns C{True} if the local folder has been successfully mounted within the - X2go server session registerd as UUID C{session_uuid} + @return: returns C{True} if the local folder has been successfully mounted within + this registered X2go server session @rtype: bool """ hooks/post-receive -- python-x2go.git (Python X2Go Client API) This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "python-x2go.git" (Python X2Go Client API).