示例#1
0
    def test_delete_url_instance(self):
        """Test delete url instance."""
        save_url_instance(self.url)
        self.assertEqual(self.url, get_url_instance())

        delete_url_instance()
        self.assertEqual(default_domain, get_url_instance())
    def upload_relationship(self, api, relationship_type, attributes=None):
        """Upload relationship data.

        :param api: Api url to upload party
        :type api: str

        :param relationship_type: Relationship type
        :type relationship_type: str

        :param attributes: Project-specific attributes that are defined
                           through the project's questionnaire
        :type attributes: dict
        """
        post_data = {
            'tenure_type': relationship_type,
        }

        if attributes:
            post_data['attributes'] = attributes

        connector = ApiConnect(get_url_instance() + api)
        status, result = connector.patch_json(Utilities.json_dumps(post_data))

        if status:
            self.set_status(
                self.tr('Relationship updated.')
            )
        else:
            self.set_status(
                Utilities.extract_error_detail(result)
            )
    def upload_parties(self, api, party_name, party_type, attributes=None):
        """Upload party data.

        :param api: Api url to upload party
        :type api: str

        :param party_name: Party name
        :type party_name: str

        :param party_type: Party type
        :type party_type: str

        :param attributes: Project-specific attributes that are defined
                           through the project's questionnaire
        :type attributes: dict
        """
        post_data = {
            'name': party_name,
            'type': party_type
        }

        if attributes:
            post_data['attributes'] = attributes

        connector = ApiConnect(get_url_instance() + api)
        status, result = connector.patch_json(Utilities.json_dumps(post_data))

        if status:
            self.set_status(
                self.tr('Party updated.')
            )
        else:
            self.set_status(
                Utilities.extract_error_detail(result)
            )
    def __init__(self,
                 organization_slug,
                 project_slug,
                 new_questionnaire,
                 on_finished=None):
        """Constructor.

        It will get Questionnaire from organization_slug and project_slug

        :param organization_slug: Organization slug for Questionnaire
        :type organization_slug: Str

        :param project_slug: Project slug for Questionnaire
        :type project_slug: Str

        :param new_questionnaire: New Questionnaire to be updated
        :type new_questionnaire: Str

        :param on_finished: (optional) function that catch result request
        :type on_finished: Function
        """
        request_url = get_url_instance() + self.api_url
        request_url = request_url % {
            'organization_slug': organization_slug,
            'project_slug': project_slug
        }
        super(UpdateQuestionnaire, self).__init__(request_url, on_finished)
        self.on_finished = on_finished
        self.connect_json_put(new_questionnaire)
示例#5
0
    def set_widgets(self):
        """Set all widgets."""
        self.text_test_connection_button = self.test_connection_button.text()
        self.ok_label.setVisible(False)
        self.save_button.setEnabled(False)

        self.test_connection_button.clicked.connect(self.login)
        self.save_button.clicked.connect(self.save_authtoken)
        self.clear_button.setText(tr('Clear'))

        self.clear_button.setEnabled(True)
        self.clear_button.clicked.connect(self.clear_information)
        self.url_input.setText(get_url_instance())

        # If login information exists
        if not self.auth_token:
            self.auth_token = get_authtoken()

        if self.auth_token:
            self.test_connection_button.setEnabled(False)
            self.username_input.setText(get_setting('username'))
            self.username_input.setReadOnly(True)
            self.password_input.setReadOnly(True)
            self.username_input.setStyleSheet(
                "QLineEdit { background-color: '#d9d9d9'; color: '#5b5b5b'; "
                "selection-background-color: '#969292'; }")
            self.password_input.setStyleSheet(
                "QLineEdit { background-color: '#d9d9d9'; color: '#5b5b5b'; "
                "selection-background-color: '#969292'; }")
            self.token_status.setText(tr('Auth token is saved.'))
        else:
            self.token_status.setText(tr('Auth token is empty.'))
    def all_organizations(self):
        """Get all organizations.

        :return: Tuple of status request and list of organizations
                  (if request failed return failure messages).
        :rtype: (bool, list/str)
        """
        network = NetworkMixin(get_url_instance() + self.api_url)
        return self._call_api(network, paginated=True)
示例#7
0
    def upload_parties(self):
        """Upload party from this project."""
        self.set_status(tr('Uploading parties'))

        party = 0

        # reset progress bar
        current_progress = 0
        self.set_progress_bar(current_progress)
        total_layer = len(self.data['locations']['features'])
        progress_block = 100 / total_layer

        post_url = self._url_post_parties()

        if not post_url:
            # Project is not uploaded
            return

        for layer in self.data['locations']['features']:
            if 'party_name' in layer['fields'] and \
                            'party_type' in layer['fields']:
                post_data = {
                    'name': layer['fields']['party_name'],
                    'type': layer['fields']['party_type']
                }

                post_data = Utilities.json_dumps(post_data)

                connector = ApiConnect(get_url_instance() + post_url)
                status, result = self._call_json_post(connector, post_data)

                if status:
                    party += 1
                    try:
                        result_dict = result
                        if 'id' in result_dict:
                            layer['party_id'] = result_dict['id']
                    except ValueError as e:
                        LOGGER.exception('message')
                else:
                    self.set_progress_bar(0)
                    self.set_status(Utilities.extract_error_detail(result))
            else:
                self.set_status(tr('No party attributes found'))
            current_progress += progress_block
            self.set_progress_bar(current_progress)

        if party == 0:
            self.set_status(tr('Not uploading any party'))
        else:
            self.set_status(
                tr('Finished uploading {party} party'.format(party=party)))

        self.set_progress_bar(100)
示例#8
0
    def upload_project(self):
        """Upload project to cadasta."""
        # check requirement attributes
        if self.check_requirement():
            return

        self.set_status(tr('Uploading project'))
        self.current_progress = 0
        self.set_progress_bar(self.current_progress)

        post_data = {
            'name': self.data['project_name'],
            'description': self.data['description'],
            'extent': self.data['extent'],
            'access': 'private' if self.data['private'] else 'public',
            'contacts': self.data['contacts']
        }

        if self.data['project_url']:
            post_data['urls'] = [self.data['project_url']]

        post_url = '/api/v1/organizations/%s/projects/' % (
            self.data['organisation']['slug'])

        post_data = Utilities.json_dumps(post_data)

        connector = ApiConnect(get_url_instance() + post_url)
        status, result = self._call_json_post(connector, post_data)

        self.set_progress_bar(self.current_progress + self.upload_increment)
        self.set_status(tr('Finished uploading project'))

        if status:
            self.project_upload_result = result
            upload_questionnaire_attribute = False
            # create questionnaire first
            # after creating location, questionnaire is blocked
            if self.data['questionnaire']:
                upload_questionnaire_attribute = True
                self.upload_questionnaire_project()
            total_locations = len(self.data['locations']['features'])
            if total_locations > 0:
                self.upload_locations(upload_questionnaire_attribute)
                self.upload_parties()
                self.upload_relationships()
            self.rerender_saved_layer()
            self.set_progress_bar(100)
        else:
            self.set_progress_bar(0)
            self.set_status(Utilities.extract_error_detail(result))

        self.set_status(tr('Finished'))
        self.parent.close()
示例#9
0
    def __init__(self, on_finished=None):
        """Constructor.

        :param on_finished: (optional) function that catch result request
        :type on_finished: Function
        """
        request_url = get_url_instance() + self.api_url
        if not get_setting('public_project'):
            request_url += '?permissions=project.update'
        super(Project, self).__init__(request_url)
        self.on_finished = on_finished
        self.connect_get_paginated()
示例#10
0
    def upload_relationships(self):
        """Upload relationships attribute to cadasta."""
        self.set_status(tr('Uploading relationship'))

        # reset progress bar
        current_progress = 0
        self.set_progress_bar(current_progress)
        total_layer = len(self.data['locations']['features'])
        progress_block = 100 / total_layer

        relationship = 0

        url = self._url_post_relationships()

        for layer in self.data['locations']['features']:

            if 'relationship_type' in layer['fields'] and \
                            'spatial_id' in layer and \
                            'party_id' in layer:

                post_data = {
                    'tenure_type': layer['fields']['relationship_type'],
                    'spatial_unit': layer['spatial_id'],
                    'party': layer['party_id']
                }

                post_data = Utilities.json_dumps(post_data)

                connector = ApiConnect(get_url_instance() + url)
                status, result = self._call_json_post(connector, post_data)

                if status:
                    relationship += 1
                else:
                    self.set_progress_bar(0)
                    self.set_status(Utilities.extract_error_detail(result))
            else:
                self.set_status(tr('No relationship attributes found'))

            current_progress += progress_block
            self.set_progress_bar(current_progress)

        if relationship == 0:
            self.set_status(tr('Not uploading any relationship'))
        else:
            self.set_status(
                tr('Finished uploading {num} relationship'.format(
                    num=relationship)))

        self.set_progress_bar(100)
示例#11
0
    def __init__(self, organization_slug, on_finished=None):
        """Constructor.

        :param organization_slug: Organization slug for getting projects
        :type organization_slug: str

        :param on_finished: (optional) function that catch result request
        :type on_finished: Function
        """
        request_url = get_url_instance() + (self.api_url % organization_slug)

        super(OrganizationProject, self).__init__(request_url,
                                                  on_finished=on_finished)
        self.connect_get_paginated()
    def summary_organization(self, slug):
        """Get detail summary organization.

        :param slug: organization slug
        :type slug: str

        :return: Tuple of status request and summary of organization
                  (if request failed return failure messages).
        :rtype: (bool, dict/str)
        """
        if not slug:
            return False, None
        network = NetworkMixin(get_url_instance() + self.api_url + slug + '/')
        return self._call_api(network)
    def organizations_project_filtered(self, permissions=None):
        """Get organizations with permission to list and add project.

        :return: Tuple of status request and list of organizations
                  (if request failed return failure messages).
        :rtype: (bool, list/str)
        """
        if not permissions:
            filter_permissions = '?permissions=project.create,project.list'
        else:
            filter_permissions = '?permissions=' + permissions
        network = NetworkMixin(get_url_instance() + self.api_url +
                               filter_permissions)
        return self._call_api(network, paginated=True)
示例#14
0
    def __init__(self, on_finished=None, permissions=None):
        """Constructor.

        :param on_finished: (optional) function that catch result request
        :type on_finished: Function

        :param permissions: (optional) permissions filter
        :type permissions: str
        """
        request_url = get_url_instance() + self.api_url

        if permissions:
            request_url += self.permission_query + permissions

        super(OrganizationList, self).__init__(request_url)
        self.on_finished = on_finished
        self.connect_get_paginated()
    def add_new_locations(self, geometry, location_type, attributes=None):
        """Add new location

        :param geometry: Location geojson geometry
        :type geometry: str

        :param location_type: Location type
        :type location_type: str

        :param attributes: Project-specific attributes that are defined
           through the project's questionnaire
        :type attributes: dict
        """
        api = u'/api/v1/organizations/{organization_slug}/projects/' \
              u'{project_slug}/spatial/'.format(
                organization_slug=self.project['organization']['slug'],
                project_slug=self.project['slug'])

        post_data = {
            'geometry': geometry
        }

        if location_type:
            post_data['type'] = location_type

        if attributes:
            post_data['attributes'] = attributes

        connector = ApiConnect(get_url_instance() + api)
        status, result = connector.post_json(Utilities.json_dumps(post_data))

        if status:
            self.set_status(
                self.tr('Location added.')
            )
            return result['properties']['id']
        else:
            self.set_status(
                Utilities.extract_error_detail(result)
            )
            return None
    def upload_update_locations(
            self,
            api,
            geometry,
            location_type,
            attributes=None):
        """Upload update location data.

        :param api: Api url to upload location
        :type api: str

        :param geometry: Location geojson geometry
        :type geometry: str

        :param location_type: Location type
        :type location_type: str

        :param attributes: Project-specific attributes that are defined
                   through the project's questionnaire
        :type attributes: dict
        """
        post_data = {
            'geometry': geometry,
            'type': location_type
        }

        if attributes:
            post_data['attributes'] = attributes

        connector = ApiConnect(get_url_instance() + api)
        status, result = connector.patch_json(Utilities.json_dumps(post_data))

        if status:
            self.set_status(
                self.tr('Location updated.')
            )
        else:
            self.set_status(
                Utilities.extract_error_detail(result)
            )
示例#17
0
    def upload_questionnaire_project(self):
        """Upload questionnaire."""
        self.set_status(tr('Update questionnaire'))
        post_url = '/api/v1/organizations/' \
                   '%s/projects/%s/questionnaire/' % (
                       self.data['organisation']['slug'],
                       self.project_upload_result['slug']
                   )

        post_data = QByteArray()
        post_data.append(self.data['questionnaire'])

        connector = ApiConnect(get_url_instance() + post_url)
        status, result = self._call_json_put(connector, post_data)

        self.set_status(tr('Finished update questionnaire'))
        if status:
            self.set_progress_bar(self.current_progress +
                                  self.upload_increment)
        else:
            self.set_progress_bar(0)
            self.set_status(Utilities.extract_error_detail(result))
    def send_update_request(self, post_data):
        """Send update request to server and return the responses

        :param post_data: Data to post
        :type post_data: json string

        :returns: Tuple of request status and error message
        :rtype: ( bool, str )
        """
        update_url = '/api/v1/organizations/%s/projects/%s/' % (
            self.project['organization']['slug'], self.project['slug'])
        network = NetworkMixin(get_url_instance() + update_url)
        network.connect_json_patch(json.dumps(post_data))
        while not network.is_finished():
            QCoreApplication.processEvents()

        if not network.error:
            return True, network.get_json_results()
        else:
            return False, \
                   '{"code" : %s, "result": %s}' % (
                       str(network.http_code), network.results.data()
                   )
示例#19
0
    def __init__(self, organization_slug, project_slug, on_finished=None):
        """Constructor.

        :param organization_slug: Organization slug for getting spatial
        :type organization_slug: str

        :param project_slug: Project slug for getting spatial
        :type project_slug: str

        :param on_finished: (optional) function that catch result request
        :type on_finished: Function
        """

        self.organization_slug = organization_slug
        self.project_slug = project_slug

        request_url = get_url_instance() + (self.api_url %
                                            (organization_slug, project_slug))
        super(OrganizationProjectSpatial,
              self).__init__(request_url,
                             on_finished=on_finished,
                             geojson=True)
        self.connect_get_paginated()
    def __init__(self, organization_slug, project_slug, on_finished=None):
        """Constructor.

        It will get Questionnaire from organization_slug and project_slug

        :param organization_slug: Organization slug for Questionnaire
        :type organization_slug: Str

        :param project_slug: Project slug for Questionnaire
        :type project_slug: Str

        :param on_finished: (optional) function that catch result request
        :type on_finished: Function
        """
        self.organization_slug = organization_slug
        self.project_slug = project_slug
        request_url = get_url_instance() + self.api_url
        request_url = request_url % {
            'organization_slug': organization_slug,
            'project_slug': project_slug
        }
        super(GetQuestionnaire, self).__init__(request_url, on_finished)
        self.on_finished = on_finished
        self.connect_get()
    def relationships_layer(self, vector_layers):
        """Create relationship layer.

        :param vector_layers: List of QGS vector layer in memory
        :type vector_layers: list of QgsVectorLayer

        :return: Relationship layer
        :rtype: QgsVectorLayer
        """

        organization_slug = self.project['organization']['slug']
        project_slug = self.project['slug']
        attribute = 'relationships'

        api = u'/api/v1/organizations/{organization_slug}/projects/' \
              u'{project_slug}/spatial/{spatial_unit_id}/relationships/'

        csv_path = get_csv_path(organization_slug, project_slug, attribute)

        if os.path.isfile(csv_path):
            os.remove(csv_path)

        relationship_layer = tools.create_memory_layer(
            layer_name='%s/%s/%s' %
            (organization_slug, project_slug, attribute),
            geometry=QGis.NoGeometry,
            fields=[
                QgsField('spatial_id', QVariant.String, "string"),
                QgsField('rel_id', QVariant.String, "string"),
                QgsField('rel_name', QVariant.String, "string"),
                QgsField('party_id', QVariant.String, "string"),
                QgsField('attributes', QVariant.String, "string"),
            ])

        QgsMapLayerRegistry.instance().addMapLayer(relationship_layer)

        for vector_layer in vector_layers:
            # Add relationship layer id to spatial attribute table
            spatial_id_index = vector_layer.fieldNameIndex('id')

            for index, feature in enumerate(vector_layer.getFeatures()):
                attributes = feature.attributes()
                spatial_unit_id = attributes[spatial_id_index]
                spatial_api = api.format(organization_slug=organization_slug,
                                         project_slug=project_slug,
                                         spatial_unit_id=spatial_unit_id)
                connector = ApiConnect(get_url_instance() + spatial_api)
                status, results = connector.get(paginated=True)

                if not status or len(results) == 0:
                    continue

                try:
                    for result in results:
                        relationship_layer.startEditing()
                        fet = QgsFeature()
                        questionnaire_attr = result['attributes']
                        if not questionnaire_attr:
                            questionnaire_attr = '-'
                        else:
                            questionnaire_attr = json.dumps(questionnaire_attr)
                        fet.setAttributes([
                            attributes[spatial_id_index],
                            result['id'],
                            result['tenure_type'],
                            result['party']['id'],
                            questionnaire_attr,
                        ])
                        relationship_layer.addFeature(fet, True)
                        relationship_layer.commitChanges()
                except (IndexError, KeyError):
                    continue

        self.process_attributes(relationship_layer)

        Utilities.add_tabular_layer(relationship_layer, organization_slug,
                                    project_slug, attribute)

        return relationship_layer
    def parties_layer(self):
        """Create parties layer.

        :param vector_layer: QGS vector layer in memory
        :type vector_layer: QgsVectorLayer
        """

        organization_slug = self.project['organization']['slug']
        project_slug = self.project['slug']
        attribute = 'parties'

        csv_path = get_csv_path(organization_slug, project_slug, attribute)

        if os.path.isfile(csv_path):
            os.remove(csv_path)

        api = u'/api/v1/organizations/{organization_slug}/projects/' \
              u'{project_slug}/parties/'.format(
                organization_slug=organization_slug,
                project_slug=project_slug)

        connector = ApiConnect(get_url_instance() + api)
        status, results = connector.get(paginated=True)

        if not status:
            return

        party_layer = tools.create_memory_layer(
            layer_name='%s/%s/%s' %
            (organization_slug, project_slug, attribute),
            geometry=QGis.NoGeometry,
            fields=[
                QgsField('id', QVariant.String, "string"),
                QgsField('name', QVariant.String, "string"),
                QgsField('type', QVariant.String, "string"),
                QgsField('attributes', QVariant.String, "string"),
            ])

        QgsMapLayerRegistry.instance().addMapLayer(party_layer)

        for party in results:
            party_layer.startEditing()
            feature = QgsFeature()
            questionnaire_attr = party['attributes']
            if not questionnaire_attr:
                questionnaire_attr = '-'
            else:
                questionnaire_attr = json.dumps(questionnaire_attr)
            feature.setAttributes([
                party['id'], party['name'], party['type'], questionnaire_attr
            ])
            party_layer.addFeature(feature, True)
            party_layer.commitChanges()
            QCoreApplication.processEvents()

        self.process_attributes(party_layer)

        Utilities.add_tabular_layer(party_layer, organization_slug,
                                    project_slug, attribute)

        return party_layer
示例#23
0
    def upload_locations(self, update_questionnaire_attribute):
        """Upload project locations to cadasta.

        :param update_questionnaire_attribute: Boolean to check if it need to
         upload the attributes
        :type update_questionnaire_attribute: bool
        """
        self.set_status(tr('Uploading locations'))
        total_locations = len(self.data['locations']['features'])
        progress_left = \
            (100 - self.current_progress - self.upload_increment) \
            / total_locations

        post_url = '/api/v1/organizations/%s/projects/%s/spatial/' % (
            self.data['organisation']['slug'],
            self.project_upload_result['slug'])

        failed = 0

        try:
            questionnaire = json.loads(self.questionnaire)
        except ValueError:
            questionnaire = {}

        for location in self.data['locations']['features']:
            post_data = {
                'geometry': location['geometry'],
                'type': location['fields']['location_type']
            }

            if update_questionnaire_attribute:
                if location['properties']:
                    post_data['attributes'] = location['properties']
                for key, value in post_data['attributes'].iteritems():
                    # Set None to empty string
                    if not value:
                        post_data['attributes'][key] = u''
                if 'id' in post_data['attributes']:
                    del post_data['attributes']['id']

                for question in \
                        questionnaire['question_groups'][0]['questions']:
                    if question['name'] not in post_data['attributes']:
                        post_data['attributes'][question['name']] = u''

            connector = ApiConnect(get_url_instance() + post_url)
            post_data = Utilities.json_dumps(post_data)
            status, result = self._call_json_post(connector, post_data)

            if status:
                self.set_progress_bar(self.current_progress + progress_left)
                try:
                    result_obj = result
                    if 'properties' in result_obj:
                        location['spatial_id'] = result_obj['properties']['id']
                except ValueError as e:
                    LOGGER.exception('message')
            else:
                self.set_progress_bar(0)
                self.set_status(Utilities.extract_error_detail(result))
                failed += 1

        self.set_progress_bar(100)

        if failed == 0:
            self.set_status(tr('Finished uploading all locations'))
        else:
            self.set_status(tr('Finish with %d failed' % failed))
示例#24
0
 def test_save_url_instance(self):
     """Test save url instance."""
     save_url_instance(self.url)
     self.assertEqual(self.url, get_url_instance())