def test_action(): action = Action("Testing") assert action.type == "Testing" assert repr(action) assert "%" not in repr(action) actions = Action.get_actions() assert len(actions) == 1 assert list(actions.values())[0] is action assert Action.get_current_action() is action # Will test .get_percent() details = action.export() assert details["action_type"] == "Testing" assert details["progress"] == 0.0 assert isinstance(details["uid"], str) # Test progress property setter action.progress = 100.0 details = action.export() assert details["progress"] == 100.0 Action.finish_action() actions = Action.get_actions() assert len(actions) == 0 assert Action.get_current_action() is None
def get_action(self): action = Action.get_current_action(self._thread_id) if action is None: action = self._action if action is None: action = IdleAction() return action
def get_action(self): action = Action.get_current_action(self._thread_id) if action is None: action = self._action if action is None: action = IdleAction() return action
def test_file_action(tmp): parent = tmp() parent.mkdir() filepath = parent / "test.txt" size = filepath.write_bytes(b"This is Sparta!") action = FileAction("Mocking", filepath, size) assert action.type == "Mocking" assert not action.empty # Will test .get_percent() details = action.export() assert details["action_type"] == "Mocking" assert details["progress"] == 0.0 assert isinstance(details["uid"], str) assert details["size"] == size assert details["name"] == filepath.name assert details["filepath"] == str(filepath) assert Action.get_current_action() is action # Test repr() when .get_percent() > 0 action.size = 42 action.progress = 4.2 assert repr(action) == "Mocking('test.txt'[42]-10.0)" Action.finish_action() assert action.finished
def function(a, b=1): # There should be 1 action, automatically created by the decorator action = Action.get_current_action() assert action assert action.type == "Testing tooltip!" return a * b
def test_tooltip(): @tooltip("Testing tooltip!") def function(a, b=1): # There should be 1 action, automatically created by the decorator action = Action.get_current_action() assert action assert action.type == "Testing tooltip!" return a * b # There is no Action right now assert Action.get_current_action() is None function(4.2, b=10) # There should be no action now that the function has been called assert Action.get_current_action() is None
def test_action(): action = Action("Testing") assert action.type == "Testing" assert repr(action) assert "%" not in repr(action) actions = Action.get_actions() assert len(actions) == 1 assert list(actions.values())[0] == action assert Action.get_current_action() == action # Will test .get_percent() details = action.export() assert details["last_transfer"] == "Testing" assert details["progress"] == 0.0 assert isinstance(details["uid"], str) Action.finish_action() actions = Action.get_actions() assert len(actions) == 0 assert Action.get_current_action() is None
def _read_data(self, file_object, buffer_size): while True: current_action = Action.get_current_action() if current_action is not None and current_action.suspend: break # Check if synchronization thread was suspended if self.check_suspended is not None: self.check_suspended('File upload: %s' % file_object.name) r = file_object.read(buffer_size) if not r: break if current_action is not None: current_action.progress += buffer_size yield r
def _read_data(self, file_object, buffer_size): while True: current_action = Action.get_current_action() if current_action is not None and current_action.suspend: break # Check if synchronization thread was suspended if self.check_suspended is not None: self.check_suspended('File upload: %s' % file_object.name) r = file_object.read(buffer_size) if not r: break if current_action is not None: current_action.progress += buffer_size yield r
def suspend_client(self, reason): if self.is_paused() or self._stopped: raise ThreadInterrupt # Verify thread status thread_id = current_thread().ident for thread in self._threads: if hasattr(thread, "worker") and isinstance(thread.worker, Processor): if thread.worker._thread_id == thread_id and thread.worker._continue == False: raise ThreadInterrupt # Get action current_file = None action = Action.get_current_action() if isinstance(action, FileAction): client = self.get_local_client() current_file = client.get_path(action.filepath) if current_file is not None and self._folder_lock is not None and current_file.startswith(self._folder_lock): log.debug("PairInterrupt '%s' because lock on '%s'", current_file, self._folder_lock) raise PairInterrupt
def suspend_client(self, reason): if self.is_paused() or self._stopped: raise ThreadInterrupt # Verify thread status thread_id = current_thread().ident for thread in self._threads: if hasattr(thread, "worker") and isinstance(thread.worker, Processor): if (thread.worker._thread_id == thread_id and thread.worker._continue == False): raise ThreadInterrupt # Get action current_file = None action = Action.get_current_action() if isinstance(action, FileAction): client = self.get_local_client() current_file = client.get_path(action.filepath) if (current_file is not None and self._folder_lock is not None and current_file.startswith(self._folder_lock)): log.debug("PairInterrupt '%s' because lock on '%s'", current_file, self._folder_lock) raise PairInterrupt
def test_file_action(tmp): parent = tmp() parent.mkdir() filepath = parent / "test.txt" size = filepath.write_bytes(b"This is Sparta!") action = FileAction("Mocking", filepath) assert action.type == "Mocking" # Will test .get_percent() details = action.export() assert details["last_transfer"] == "Mocking" assert details["progress"] == 0.0 assert isinstance(details["uid"], str) assert details["size"] == size assert details["name"] == filepath.name assert details["filepath"] == str(filepath) assert Action.get_current_action() == action Action.finish_action() assert action.finished
def do_get(self, url, file_out=None, digest=None, digest_algorithm=None): log.trace( 'Downloading file from %r to %r with digest=%s, digest_algorithm=%s', url, file_out, digest, digest_algorithm) h = None if digest is not None: if digest_algorithm is None: digest_algorithm = guess_digest_algorithm(digest) log.trace('Guessed digest algorithm from digest: %s', digest_algorithm) digester = getattr(hashlib, digest_algorithm, None) if digester is None: raise ValueError('Unknow digest method: ' + digest_algorithm) h = digester() headers = self._get_common_headers() base_error_message = ( "Failed to connect to Nuxeo server %r with user %r") % ( self.server_url, self.user_id) try: log.trace("Calling '%s' with headers: %r", url, headers) req = urllib2.Request(url, headers=headers) response = self.opener.open(req, timeout=self.blob_timeout) current_action = Action.get_current_action() # Get the size file if (current_action and response is not None and response.info() is not None): current_action.size = int(response.info().getheader( 'Content-Length', 0)) if file_out is not None: locker = self.unlock_path(file_out) try: with open(file_out, "wb") as f: while True: # Check if synchronization thread was suspended if self.check_suspended is not None: self.check_suspended('File download: %s' % file_out) buffer_ = response.read(self.get_download_buffer()) if buffer_ == '': break if current_action: current_action.progress += ( self.get_download_buffer()) f.write(buffer_) if h is not None: h.update(buffer_) if digest is not None: actual_digest = h.hexdigest() if digest != actual_digest: if os.path.exists(file_out): os.remove(file_out) raise CorruptedFile( "Corrupted file %r: expected digest = %s, actual digest = %s" % (file_out, digest, actual_digest)) return None, file_out finally: self.lock_path(file_out, locker) else: result = response.read() if h is not None: h.update(result) if digest is not None: actual_digest = h.hexdigest() if digest != actual_digest: raise CorruptedFile( "Corrupted file: expected digest = %s, actual digest = %s" % (digest, actual_digest)) return result, None except urllib2.HTTPError as e: if e.code == 401 or e.code == 403: raise Unauthorized(self.server_url, self.user_id, e.code) else: e.msg = base_error_message + ": HTTP error %d" % e.code raise e except Exception as e: if hasattr(e, 'msg'): e.msg = base_error_message + ": " + e.msg raise
def do_get(self, url, file_out=None, digest=None, digest_algorithm=None): log.trace('Downloading file from %r to %r with digest=%s, digest_algorithm=%s', url, file_out, digest, digest_algorithm) h = None if digest is not None: if digest_algorithm is None: digest_algorithm = guess_digest_algorithm(digest) log.trace('Guessed digest algorithm from digest: %s', digest_algorithm) digester = getattr(hashlib, digest_algorithm, None) if digester is None: raise ValueError('Unknow digest method: ' + digest_algorithm) h = digester() headers = self._get_common_headers() base_error_message = ( "Failed to connect to Nuxeo server %r with user %r" ) % (self.server_url, self.user_id) try: log.trace("Calling '%s' with headers: %r", url, headers) req = urllib2.Request(url, headers=headers) response = self.opener.open(req, timeout=self.blob_timeout) current_action = Action.get_current_action() # Get the size file if (current_action and response is not None and response.info() is not None): current_action.size = int(response.info().getheader( 'Content-Length', 0)) if file_out is not None: locker = self.unlock_path(file_out) try: with open(file_out, "wb") as f: while True: # Check if synchronization thread was suspended if self.check_suspended is not None: self.check_suspended('File download: %s' % file_out) buffer_ = response.read(FILE_BUFFER_SIZE) if buffer_ == '': break if current_action: current_action.progress += FILE_BUFFER_SIZE f.write(buffer_) if h is not None: h.update(buffer_) if digest is not None: actual_digest = h.hexdigest() if digest != actual_digest: if os.path.exists(file_out): os.remove(file_out) raise CorruptedFile("Corrupted file %r: expected digest = %s, actual digest = %s" % (file_out, digest, actual_digest)) return None, file_out finally: self.lock_path(file_out, locker) else: result = response.read() if h is not None: h.update(result) if digest is not None: actual_digest = h.hexdigest() if digest != actual_digest: raise CorruptedFile("Corrupted file: expected digest = %s, actual digest = %s" % (digest, actual_digest)) return result, None except urllib2.HTTPError as e: if e.code == 401 or e.code == 403: raise Unauthorized(self.server_url, self.user_id, e.code) else: e.msg = base_error_message + ": HTTP error %d" % e.code raise e except Exception as e: if hasattr(e, 'msg'): e.msg = base_error_message + ": " + e.msg raise
def execute(self, command, url=None, op_input=None, timeout=-1, check_params=True, void_op=False, extra_headers=None, file_out=None, **params): """Execute an Automation operation""" if check_params: self._check_params(command, params) if url is None: url = self.automation_url + command headers = { "Content-Type": "application/json+nxrequest", "Accept": "application/json+nxentity, */*", "X-NXproperties": "*", # Keep compatibility with old header name "X-NXDocumentProperties": "*", } if void_op: headers.update({"X-NXVoidOperation": "true"}) if self.repository != DEFAULT_REPOSITORY_NAME: headers.update({"X-NXRepository": self.repository}) if extra_headers is not None: headers.update(extra_headers) headers.update(self._get_common_headers()) json_struct = {'params': {}} for k, v in params.items(): if v is None: continue if k == 'properties': s = "" for propname, propvalue in v.items(): s += "%s=%s\n" % (propname, propvalue) json_struct['params'][k] = s.strip() else: json_struct['params'][k] = v if op_input: json_struct['input'] = op_input data = json.dumps(json_struct) cookies = self._get_cookies() log.trace( "Calling %s with headers %r, cookies %r" " and JSON payload %r", url, headers, cookies, data) req = urllib2.Request(url, data, headers) timeout = self.timeout if timeout == -1 else timeout try: resp = self.opener.open(req, timeout=timeout) except Exception as e: self._log_details(e) raise current_action = Action.get_current_action() if current_action and current_action.progress is None: current_action.progress = 0 if file_out is not None: locker = self.unlock_path(file_out) try: with open(file_out, "wb") as f: while True: # Check if synchronization thread was suspended if self.check_suspended is not None: self.check_suspended('File download: %s' % file_out) buffer_ = resp.read(self.get_download_buffer()) if buffer_ == '': break if current_action: current_action.progress += ( self.get_download_buffer()) f.write(buffer_) return None, file_out finally: self.lock_path(file_out, locker) else: return self._read_response(resp, url)
def do_get(self, url, file_out=None, digest=None, digest_algorithm=None): h = None if digest is not None: if digest_algorithm is None: digest_algorithm = guess_digest_algorithm(digest) digester = getattr(hashlib, digest_algorithm, None) if digester is None: raise ValueError('Unknow digest method: ' + digest_algorithm) h = digester() headers = self._get_common_headers() base_error_message = ( "Failed to connect to Nuxeo server %r with user %r" ) % (self.server_url, self.user_id) try: log.trace("Calling '%s' with headers: %r", url, headers) req = urllib2.Request(url, headers=headers) response = self.opener.open(req, timeout=self.blob_timeout) current_action = Action.get_current_action() # Get the size file if (current_action and response is not None and response.info() is not None): current_action.size = int(response.info().getheader( 'Content-Length', 0)) if file_out is not None: locker = self.unlock_path(file_out) try: with open(file_out, "wb") as f: while True: # Check if synchronization thread was suspended if self.check_suspended is not None: self.check_suspended('File download: %s' % file_out) buffer_ = response.read(self.get_download_buffer()) if buffer_ == '': break if current_action: current_action.progress += ( self.get_download_buffer()) f.write(buffer_) if h is not None: h.update(buffer_) if self._remote_error is not None: # Simulate a configurable remote (e.g. network or # server) error for the tests raise self._remote_error if self._local_error is not None: # Simulate a configurable local error (e.g. "No # space left on device") for the tests raise self._local_error if digest is not None and digest != h.hexdigest(): if os.path.exists(file_out): os.remove(file_out) raise CorruptedFile("Corrupted file") return None, file_out finally: self.lock_path(file_out, locker) else: result = response.read() if h is not None: h.update(result) if digest is not None and digest != h.hexdigest(): raise CorruptedFile("Corrupted file") return result, None except urllib2.HTTPError as e: if e.code == 401 or e.code == 403: raise Unauthorized(self.server_url, self.user_id, e.code) else: e.msg = base_error_message + ": HTTP error %d" % e.code raise e except Exception as e: if hasattr(e, 'msg'): e.msg = base_error_message + ": " + e.msg raise
def action(self): if self._action is None: self._action = Action.get_current_action(self._thread_id) if self._action is None: self._action = IdleAction() return self._action
def execute(self, command, op_input=None, timeout=-1, check_params=True, void_op=False, extra_headers=None, file_out=None, **params): """Execute an Automation operation""" if self._remote_error is not None: # Simulate a configurable (e.g. network or server) error for the # tests raise self._remote_error if check_params: self._check_params(command, params) url = self.automation_url + command headers = { "Content-Type": "application/json+nxrequest", "Accept": "application/json+nxentity, */*", "X-NXproperties": "*", # Keep compatibility with old header name "X-NXDocumentProperties": "*", } if void_op: headers.update({"X-NXVoidOperation": "true"}) if self.repository != DEFAULT_REPOSITORY_NAME: headers.update({"X-NXRepository": self.repository}) if extra_headers is not None: headers.update(extra_headers) headers.update(self._get_common_headers()) json_struct = {'params': {}} for k, v in params.items(): if v is None: continue if k == 'properties': s = "" for propname, propvalue in v.items(): s += "%s=%s\n" % (propname, propvalue) json_struct['params'][k] = s.strip() else: json_struct['params'][k] = v if op_input: json_struct['input'] = op_input log.trace("Dumping JSON structure: %s", json_struct) data = json.dumps(json_struct) cookies = self._get_cookies() log.trace("Calling %s with headers %r, cookies %r" " and JSON payload %r", url, headers, cookies, data) req = urllib2.Request(url, data, headers) timeout = self.timeout if timeout == -1 else timeout try: resp = self.opener.open(req, timeout=timeout) except Exception as e: self._log_details(e) raise current_action = Action.get_current_action() if current_action and current_action.progress is None: current_action.progress = 0 if file_out is not None: locker = self.unlock_path(file_out) try: with open(file_out, "wb") as f: while True: # Check if synchronization thread was suspended if self.check_suspended is not None: self.check_suspended('File download: %s' % file_out) buffer_ = resp.read(self.get_download_buffer()) if buffer_ == '': break if current_action: current_action.progress += ( self.get_download_buffer()) f.write(buffer_) if self._remote_error is not None: # Simulate a configurable remote (e.g. network or # server) error for the tests raise self._remote_error if self._local_error is not None: # Simulate a configurable local error (e.g. "No # space left on device") for the tests raise self._local_error return None, file_out finally: self.lock_path(file_out, locker) else: return self._read_response(resp, url)
def execute(self, command, url=None, op_input=None, timeout=-1, check_params=False, void_op=False, extra_headers=None, enrichers=None, file_out=None, **params): """Execute an Automation operation""" if check_params: self._check_params(command, params) if url is None: url = self.automation_url + command headers = { "Content-Type": "application/json+nxrequest", "Accept": "application/json+nxentity, */*", "X-NXproperties": "*", # Keep compatibility with old header name "X-NXDocumentProperties": "*", } if void_op: headers.update({"X-NXVoidOperation": "true"}) if self.repository != 'default': headers.update({"X-NXRepository": self.repository}) if extra_headers is not None: headers.update(extra_headers) if enrichers is not None: headers.update({ 'X-NXenrichers.document': ', '.join(enrichers), }) headers.update(self._get_common_headers()) json_struct = {'params': {}} for k, v in params.items(): if v is None: continue if k == 'properties': s = "" for propname, propvalue in v.items(): s += "%s=%s\n" % (propname, propvalue) json_struct['params'][k] = s.strip() else: json_struct['params'][k] = v if op_input: json_struct['input'] = op_input data = json.dumps(json_struct) cookies = self._get_cookies() log.trace("Calling %s with headers %r, cookies %r" " and JSON payload %r", url, headers, cookies, data) req = urllib2.Request(url, data, headers) timeout = self.timeout if timeout == -1 else timeout try: resp = self.opener.open(req, timeout=timeout) except Exception as e: log_details = self._log_details(e) if isinstance(log_details, tuple): _, _, _, error = log_details if error and error.startswith("Unable to find batch"): raise InvalidBatchException() raise e current_action = Action.get_current_action() if current_action and current_action.progress is None: current_action.progress = 0 if file_out is not None: locker = self.unlock_path(file_out) try: with open(file_out, "wb") as f: while True: # Check if synchronization thread was suspended if self.check_suspended is not None: self.check_suspended('File download: %s' % file_out) buffer_ = resp.read(FILE_BUFFER_SIZE) if buffer_ == '': break if current_action: current_action.progress += FILE_BUFFER_SIZE f.write(buffer_) return None, file_out finally: self.lock_path(file_out, locker) else: return self._read_response(resp, url)