def write_back(self, force=False, **kwargs): """Write back data to the server. The write back only happens if the file was modified (that is the write, writelines or truncate method was called at least one time). Keyword arguments: force -- always write back data to server (regardless if it was modified or not) (default: False) kwargs -- optional parameters for the writeback http request (like query parameters) """ if not self._modified and not force: return if self._fobj is None: self._init_fobj(read_required=True) request = Osc.get_osc().get_reqobj() http_method = _get_http_method(request, self.wb_method) if 'schema' not in kwargs: kwargs['schema'] = self._schema data = None filename = '' if hasattr(self._fobj, 'getvalue'): data = self._fobj.getvalue() else: filename = self._fobj.name self._fobj.flush() wb_path = self.wb_path or self.path http_method(wb_path, data=data, filename=filename, **kwargs) self._modified = False
def _init(apiurl): """Initialize osc library. apiurl is the apiurl which should be used. """ if hasattr(apiurl, 'extend') and len(set(apiurl)) > 1: msg = ("Different apiurls are not supported at the moment: " "%s (using %s)" % (', '.join(apiurl), apiurl[0])) logger().info(msg) apiurl = apiurl[0] conf_filename = os.environ.get('OSC_CONFIG', '~/.oscrc') conf_filename = os.path.expanduser(conf_filename) cp = SafeConfigParser({'plaintext_password': True, 'aliases': ''}) cp.read(conf_filename) apiurl = apiurl.strip('/') if apiurl == 'api': apiurl = 'https://api.opensuse.org' for section in cp.sections(): aliases = cp.get(section, 'aliases', raw=True) aliases = aliases.split(',') if section.strip('/') == apiurl or apiurl in aliases: user = cp.get(section, 'user', raw=True) password = None if cp.has_option(section, 'pass'): password = cp.get(section, 'pass', raw=True) if cp.has_option(section, 'passx'): password = cp.get(section, 'pass', raw=True) password = password.decode('base64').decode('bz2') if (cp.has_option(section, 'keyring') and cp.getboolean(section, 'keyring')): try: import keyring host = urlparse.urlparse(apiurl).hostname password = keyring.get_password(host, user) except ImportError: msg = ("keyring module not available but '%s' " "stores password there") % conf_filename raise ValueError(msg) if password is None: msg = "No password provided for %s" % section raise ValueError(msg) if '://' not in section: section = 'https://{0}'.format(section) Osc.init(section, username=user, password=password) return section
def _init(apiurl): conf_filename = os.environ.get('OSC_CONFIG', '~/.oscrc') conf_filename = os.path.expanduser(conf_filename) cp = SafeConfigParser({'plaintext_password': True, 'aliases': ''}) cp.read(conf_filename) apiurl = apiurl.strip('/') if apiurl == 'api': apiurl = 'https://api.opensuse.org' for section in cp.sections(): aliases = cp.get(section, 'aliases', raw=True) aliases = aliases.split(',') if section.strip('/') == apiurl or apiurl in aliases: user = cp.get(section, 'user', raw=True) password = cp.get(section, 'pass', raw=True) if cp.has_option(section, 'passx'): password = cp.get(section, 'pass', raw=True) password = password.decode('base64').decode('bz2') Osc.init(section, username=user, password=password) return section
def _perform_request(project, repository, arch, package, **kwargs): """Performs http request and returns response object. Keyword arguments: kwargs -- optional parameters for the http request (like query parameters) """ path = "/build/%s/%s/%s/%s" % (project, repository, arch, package) request = Osc.get_osc().get_reqobj() return request.get(path, **kwargs)
def _commit_filelist(self, xml_data, **kwargs): request = Osc.get_osc().get_reqobj() path = "/source/%s/%s" % (self.project, self.name) query = {'cmd': 'commitfilelist'} if self.is_expanded(): # the expanded check is not neccessary query['keeplink'] = '1' query['expand'] = '1' query.update(kwargs) f = request.post(path, data=xml_data, apiurl=self.apiurl, content_type='application/xml', **query) return fromstring(f.read(), directory=Directory, entry=File, linkinfo=Linkinfo)
def log(self, **kwargs): """Get the commit log. Keyword arguments: **kwargs -- optional parameters for the http request """ request = Osc.get_osc().get_reqobj() path = "/source/%s/%s/_history" % (self.project, self.name) if 'schema' not in kwargs: kwargs['schema'] = Package.HISTORY_SCHEMA f = request.get(path, **kwargs) return fromstring(f.read())
def find(cls, path, method='GET', **kwargs): """Get the remote model from the server. path is the url path. Keyword arguments: method -- the http method (default: 'GET') kwargs -- parameters for the http request (like query parameters, schema etc.) """ request = Osc.get_osc().get_reqobj() http_method = _get_http_method(request, method) xml_data = http_method(path, **kwargs).read() return cls(xml_data=xml_data)
def list(self, **kwargs): """List all files for this package. Keyword arguments: **kwargs -- optional parameters for the http request """ request = Osc.get_osc().get_reqobj() path = "/source/%s/%s" % (self.project, self.name) if 'schema' not in kwargs: kwargs['schema'] = Package.LIST_SCHEMA f = request.get(path, **kwargs) directory = fromstring(f.read(), directory=Directory, entry=File, linkinfo=Linkinfo) # this is needed by the file class directory.set('project', self.project) return directory
def list(self, **kwargs): """List all packages for this project. Keyword arguments: **kwargs -- optional parameters for the http request """ request = Osc.get_osc().get_reqobj() path = '/source/' + self.name if 'schema' not in kwargs: kwargs['schema'] = Project.LIST_SCHEMA f = request.get(path, **kwargs) entries = fromstring(f.read()) r = [] # using an xml representation for the <entry /> makes no # sense for e in entries.iterfind('entry'): r.append(Package(self.name, e.get('name'))) return r
def add_review(self, **kwargs): """Adds a review to the request. Keyword arguments: by_user -- adds a by_user review (default: None) by_group -- adds a by_group review (default: None) by_project -- adds a by_project review (default: None) by_package -- adds a by_package review (default: None) comment -- an optional comment (default: None) **kwargs -- optional parameters for the http request """ path = Request.GET_PATH % {'reqid': self.get('id')} query = {'cmd': 'addreview'} query.update(kwargs) request = Osc.get_osc().get_reqobj() request.post(path, **query) f = request.get(path) self._read_xml_data(f.read())
def store(self, path, method='PUT', **kwargs): """Store the xml to the server. Keyword arguments: path -- the url path (default: '') method -- the http method (default: 'PUT') kwargs -- parameters for the http request (like query parameters, post data etc.) """ self.validate() request = Osc.get_osc().get_reqobj() http_method = _get_http_method(request, method) if 'data' not in kwargs: kwargs['data'] = self.tostring() if 'schema' not in kwargs: kwargs['schema'] = self._store_schema # FIXME: api.o.o does not like this for requests kwargs['content_type'] = 'application/xml' return http_method(path, **kwargs)
def _find(path, xp, tag_class={}, **kwargs): """Returns a Collection with objects which match the xpath. path is the remote path which is used for the http request. xp is the xpath which is used for the search (either an Expression object or a string). Keyword arguments: tag_class -- a dict which maps tag names to classes (see util.xml.fromstring for the details) (default: {}) **kwargs -- optional parameters for the http request """ request = Osc.get_osc().get_reqobj() xpath = xp if hasattr(xp, 'tostring'): xpath = xp.tostring() f = request.get(path, match=xpath, **kwargs) return fromstring(f.read(), **tag_class)
def builddepinfo(self, reverse=False, **kwargs): """Get the builddepinfo. If reverse is True a reverse builddepinfo lookup is done. Keyword arguments: **kwargs -- optional parameters for the http request """ package = self.package or "_repository" path = "/build/%s/%s/%s/%s/_builddepinfo" % (self.project, self.repository, self.arch, package) request = Osc.get_osc().get_reqobj() view = "pkgnames" if reverse: view = "revpkgnames" if "schema" not in kwargs: kwargs["schema"] = BuildResult.BUILDDEPINFO_SCHEMA f = request.get(path, view=view, **kwargs) # no custom parser needed atm return fromstring(f.read())
def _change_state(self, state, review=None, **kwargs): """Changes the state of the request. state is the new state of the request. Keyword arguments: review -- change state of review review (default: None) **kwargs -- optional parameters for the http request """ path = Request.GET_PATH % {'reqid': self.get('id')} query = {'cmd': 'changestate', 'newstate': state} if review is not None: query['cmd'] = 'changereviewstate' for kind in ('by_user', 'by_group', 'by_project', 'by_package'): query[kind] = review.get(kind, '') query.update(kwargs) request = Osc.get_osc().get_reqobj() request.post(path, **query) f = request.get(path) self._read_xml_data(f.read())
def __init__(self, project="", package="", repository="", arch="", xml_data="", binarytype="", data=None, **kwargs): """Constructs a new BuildInfo object. A ValueError is raised if xml_data is specified and project or package or repository or arch. A ValueError is raised if no binarytype is specified and the buildinfo has no file element. Keyword arguments: project -- the project (default: '') package -- the package (default: '') repository -- the repository (default: '_repository') arch -- the architecture (default: '') xml_data -- a xml str which contains a buildinfo element (default: '') binarytype -- the package type of the bdep elements (rpm, deb etc.) (default: '') data -- a specfile or cpio archive which is POSTed to the server (default: None) **kwargs -- optional parameters for the http request """ if ( (project or package or repository or arch) and xml_data or not (project and repository and arch) and not xml_data ): msg = "Either project, package, repository, arch or xml_data" raise ValueError(msg) elif not xml_data: package = package or "_repository" path = "/build/%s/%s/%s/%s/_buildinfo" % (project, repository, arch, package) request = Osc.get_osc().get_reqobj() if data is None: f = request.get(path, **kwargs) else: f = request.post(path, data=data, **kwargs) xml_data = f.read() self._xml = fromstring(xml_data, bdep=BuildDependency) self._calculate_binarytype(binarytype)
def builddepinfo(self, reverse=False, **kwargs): """Get the builddepinfo. If reverse is True a reverse builddepinfo lookup is done. Keyword arguments: **kwargs -- optional parameters for the http request """ package = self.package or '_repository' path = "/build/%s/%s/%s/%s/_builddepinfo" % (self.project, self.repository, self.arch, package) request = Osc.get_osc().get_reqobj() view = 'pkgnames' if reverse: view = 'revpkgnames' if 'schema' not in kwargs: kwargs['schema'] = BuildResult.BUILDDEPINFO_SCHEMA f = request.get(path, view=view, **kwargs) # no custom parser needed atm return fromstring(f.read())
def result(self, **kwargs): """Get the build result. Keyword arguments: package -- limit results to package (default: '') repository -- limit results repository arch -- limit results to arch kwargs -- optional arguments for the http request Note: package, repository and arch may override the current package, repository and arch instance attributes. """ package = kwargs.pop("package", self.package) repository = kwargs.pop("repository", self.repository) arch = kwargs.pop("arch", self.arch) request = Osc.get_osc().get_reqobj() path = "/build/%s/_result" % self.project if "schema" not in kwargs: kwargs["schema"] = BuildResult.RESULT_SCHEMA f = request.get(path, package=package, repository=repository, arch=arch, **kwargs) results = fromstring(f.read(), status=Status) return results
def __init__(self, project='', package='', repository='', arch='', xml_data='', binarytype='', data=None, **kwargs): """Constructs a new BuildInfo object. A ValueError is raised if xml_data is specified and project or package or repository or arch. A ValueError is raised if no binarytype is specified and the buildinfo has no file element. Keyword arguments: project -- the project (default: '') package -- the package (default: '') repository -- the repository (default: '_repository') arch -- the architecture (default: '') xml_data -- a xml str which contains a buildinfo element (default: '') binarytype -- the package type of the bdep elements (rpm, deb etc.) (default: '') data -- a specfile or cpio archive which is POSTed to the server (default: None) **kwargs -- optional parameters for the http request """ if ((project or package or repository or arch) and xml_data or not (project and repository and arch) and not xml_data): msg = 'Either project, package, repository, arch or xml_data' raise ValueError(msg) elif not xml_data: package = package or '_repository' path = "/build/%s/%s/%s/%s/_buildinfo" % (project, repository, arch, package) request = Osc.get_osc().get_reqobj() if data is None: f = request.get(path, **kwargs) else: f = request.post(path, data=data, **kwargs) xml_data = f.read() self._xml = fromstring(xml_data, bdep=BuildDependency) self._calculate_binarytype(binarytype)
def result(self, **kwargs): """Get the build result. Keyword arguments: package -- limit results to package (default: '') repository -- limit results repository arch -- limit results to arch kwargs -- optional arguments for the http request Note: package, repository and arch may override the current package, repository and arch instance attributes. """ package = kwargs.pop('package', self.package) repository = kwargs.pop('repository', self.repository) arch = kwargs.pop('arch', self.arch) request = Osc.get_osc().get_reqobj() path = "/build/%s/_result" % self.project if 'schema' not in kwargs: kwargs['schema'] = BuildResult.RESULT_SCHEMA f = request.get(path, package=package, repository=repository, arch=arch, **kwargs) results = fromstring(f.read(), status=Status) return results
def delete(cls, path, method='DELETE', **kwargs): """Delete a remote resource. path is the url path. Return True if the resource was successfully deleted. If the resource do not exist anymore (code 404) False is returned. Keyword arguments: method -- the http method (default: 'DELETE') kwargs -- parameters for the http request (like query parameters, schema etc.) """ request = Osc.get_osc().get_reqobj() http_method = _get_http_method(request, method) try: http_method(path, **kwargs).read() except HTTPError as e: if e.code == 404: return False raise return True
def setUp(self): super(OscTest, self).setUp() Osc.init(self.apiurl, validate=True)
def _init_read(self): request = Osc.get_osc().get_reqobj() http_method = _get_http_method(request, self.method) self._fobj = http_method(self.path, **self.kwargs) self._remote_size = int(self._fobj.headers.get('Content-Length', -1))