def pysdk_checking(self):
        logger.debug("\n--------------- isogeo-pysdk ---------------")
        logger.debug("Checking credentials")
        try:
            isogeo = Isogeo(self.app_id, self.app_secrets)
            isogeo.connect()
        except OSError as e:
            logger.debug("Credentials issue : {}".format(e))
            return
        except ValueError as e:
            logger.debug("Credentials issue : {}".format(e))
            return

        if self.search_type == "init":
            result = isogeo.search(
                whole_share=0, page_size=0, augment=0, tags_as_dicts=1
            )
        else:
            query = " ".join(list(self.checked_kw.keys()))
            result = isogeo.search(
                whole_share=0, page_size=0, augment=0, tags_as_dicts=1, query=query
            )

        self.tags_expected = result.get("tags")
        self.kw_expected_nb = len(self.tags_expected.get("keywords"))
        self.ui.lbl_expected.setText(
            "Expected : {} resources and {} keywords".format(
                result.get("total"), self.kw_expected_nb
            )
        )
        logger.debug(
            "isogeo-pysdk validates the authentication file, {} accessible resources".format(
                result.get("total")
            )
        )
Пример #2
0
class TestIsogeo(unittest.TestCase):

    # ------------ Basic methods ---------------------------------------------
    def setUp(self):
        """Before"""
        # reading config file
        settings_file = "../isogeo_pysdk/isogeo_params.ini"
        if not path.isfile(settings_file):
            return
        else:
            pass
        config = ConfigParser.SafeConfigParser()
        config.read(settings_file)
        self.share_id = config.get('auth', 'app_id')
        self.share_token = config.get('auth', 'app_secret')

        self.isogeo = Isogeo(client_id=self.share_id,
                             client_secret=self.share_token)
        self.jeton = self.isogeo.connect()
     
    def tearDown(self):
        """After"""
        # print("Cleaned up!")

    # ------------ Tests methods ---------------------------------------------

    def test_authentication(self):
        """Authentication and connection to Isogeo API"""
        # jeton = isogeo.connect()

    def test_connection(self):
        """Authentication and connection to Isogeo API"""
        self.jeton = self.isogeo.connect()

    def test_search(self):
        """Isogeo API search"""
        search_empty = self.isogeo.search(self.jeton)
 
        assert(type(search_empty) != unicode)
        assert(type(search_empty) == dict)
        assert("envelope" in search_empty.keys())
        assert("limit" in search_empty.keys())
        assert("offset" in search_empty.keys())
        assert("query" in search_empty.keys())
        assert("results" in search_empty.keys())
        assert("tags" in search_empty.keys())
        assert("total" in search_empty.keys())
        assert(type(search_empty.get("results")) == list)
Пример #3
0
class IsogeoAPI():  # Une classe qui hérite de la classe Isogeo
    """ Make easier connecting and requesting to Isogeo's API using isogeo-pysdk package.
    Online resources:
    * Full isogeo-pysdk doc at : https://isogeo-api-pysdk.readthedocs.io/en/latest/index.html
    * Full Isogeo's API doc at : http://help.isogeo.com/api

    :param str file_name: name of the credential file
    """
    def __init__(self, file_name: str = "client_secrets.json") -> object:
        # création du chemin vers le fichier d'authentification
        self.json_file = "{}/{}".format("/".join(__file__.split("\\")[:-1]),
                                        file_name)
        # récupérétion des informations d'authentification contenues dans le fichier
        self.client_id = utils.credentials_loader(
            self.json_file).get("client_id")
        self.client_secret = utils.credentials_loader(
            self.json_file).get("client_secret")
        # connexion à l'API et récupération du token
        self.isogeo = Isogeo(
            client_id=self.client_id,
            client_secret=self.client_secret,
            auth_mode="group",
            auto_refresh_url="https://id.api.isogeo.com/oauth/token",
            platform="prod")
        self.isogeo.connect()

    # Méthode permettant d'effectuer les différents types de requête à l'API
    def request_maker(self,
                      filter_request: bool = 0,
                      filter_query: str = None) -> dict:
        """Request API about the resources shared with the application wich credential file allow access.
        Using a method of isogeo_pysdk's Isogeo class to return the number and the tags of searched resources.

        :param bool filter_request: 0 [DEFAULT] to search all the resources shared in the application / 1 to filter the request
        :param str filter_query: with filter_request = 1, character string for 'query' parameter of * isogeo_pysdk.Isogeo.search() * method
        """
        if filter_request == 1:
            search = self.isogeo.search(page_size=0,
                                        augment=0,
                                        tags_as_dicts=1,
                                        query=filter_query)
        else:
            search = self.isogeo.search(page_size=0,
                                        augment=0,
                                        tags_as_dicts=1)
        # retourne les valeurs des champs ainsi que le nombre de métadonnées filtrées
        return search.tags, search.total
Пример #4
0
    def pysdk_checking(self):
        logger.debug("\n------------------ isogeo-pysdk ------------------")
        logger.debug("Checking credentials")
        try:
            isogeo = Isogeo(self.app_id, self.app_secrets)
            isogeo.connect()
        except OSError as e:
            logger.debug("Credentials issue : {}".format(e))
            return
        except ValueError as e:
            logger.debug("Credentials issue : {}".format(e))
            return

        self.md_expected = isogeo.search(whole_share=0, page_size=0,
                                         augment=0).get("total")
        self.ui.lbl_expected.setText("{} expected resources".format(
            self.md_expected))
        logger.debug(
            "isogeo-pysdk validates the authentication file, {} accessible resources"
            .format(self.md_expected))
Пример #5
0
    def _update_db(self):
        """Update metadata list from API."""
        # get stored metadata
        db_mds = Metadata.objects.all()
        db_wgs = Workgroup.objects.all()

        # connect to isogeo
        isogeo = Isogeo(client_id=settings.ISOGEO_CLIENT_ID,
                        client_secret=settings.ISOGEO_CLIENT_SECRET,
                        lang="fr")
        token = isogeo.connect()
        search = isogeo.search(token,
                                  # page_size=10,
                                  order_by="modified",
                                  # whole_share=0,
                                  # sub_resources=["events"]
                                  )
        # tags
        tags = search.get("tags")
        for tag in tags:
            if tag.startswith("owner"):
                new_owner = Workgroup(isogeo_uuid=tag[6:-1],
                                      label=tags.get(tag))
                new_owner.save()


        # metadatas
        # for md in search.get("results"):
        #     try:
        #         new_md = Metadata(isogeo_id=md.get("_id"),
        #                           title=md.get("title", "No title"),
        #                           name=md.get("name"),
        #                           abstract=md.get("abstract"),
        #                           md_dt_crea=md.get("_created"),
        #                           md_dt_update=md.get("_modified"),
        #                           rs_dt_crea=md.get("created"),
        #                           rs_dt_update=md.get("modified"),
        #                           source=True)
        #         new_md.save()
        #         logging.info("Metadata added")
        #     except IntegrityError:
        #         # in case of duplicated offer
        #         logging.error("Metadata already existed")
        #         continue
        logging.info("{} metadata added")
Пример #6
0
# load .env file
load_dotenv("./env/lille.env", override=True)

if __name__ == "__main__":

    # ############################### MIGRATING & SAVING ###############################
    # API client instanciation
    isogeo = Isogeo(
        client_id=environ.get("ISOGEO_API_USER_LEGACY_CLIENT_ID"),
        client_secret=environ.get("ISOGEO_API_USER_LEGACY_CLIENT_SECRET"),
        auth_mode="user_legacy",
        auto_refresh_url="{}/oauth/token".format(environ.get("ISOGEO_ID_URL")),
        platform=environ.get("ISOGEO_PLATFORM", "qa"),
    )
    isogeo.connect(
        username=environ.get("ISOGEO_USER_NAME"),
        password=environ.get("ISOGEO_USER_PASSWORD"),
    )

    workgroup_uuid = environ.get("ISOGEO_ORIGIN_WORKGROUP")

    # Search about all workgroup metadatas because there are less than 800
    whole_md_search = isogeo.search(group=workgroup_uuid,
                                    whole_results=True,
                                    include="all")
    isogeo.close()

    li_md = [md for md in whole_md_search.results if md.get("name")]

    print("{} metadatas loaded from {} workgroup".format(
        whole_md_search.total, workgroup_uuid))
Пример #7
0
config = configparser.SafeConfigParser()
config.read(settings_file)

share_id = config.get('auth', 'app_id')
share_token = config.get('auth', 'app_secret')
last_exe = config.get('metrics', 'last_exe')
last_total = int(config.get('metrics', 'last_total'))


# ------------ Real start ----------------
# instanciating Isogeo class
isogeo = Isogeo(client_id=share_id,
                client_secret=share_token,
                lang="fr")

token = isogeo.connect()

# Windows 10 notifications class
notif = ToastNotifier()

# ------------ REAL START ----------------------------
latest_data_modified = isogeo.search(token,
                                     page_size=10,
                                     order_by="modified",
                                     whole_share=0,
                                     sub_resources=["events"]
                                     )

# parsing the previous date
last_exe = dtparse(last_exe).strftime("%a %d %B %Y (%H:%M)")
# last_exe = last_exe.decode("Latin1")
Пример #8
0
        logging.info("\n{0}: ".format(gs))
        ReadGeoServer(gs, dico_gs, 'GeoServer')

        # print(dico_gs)
        # print(dico_gs.keys())
        # print(dico_gs.get('ayants-droits')[1].get("BD_TOPO_2015_VOIES_FERREES_ET_AUTRES"))
        # print(dico_gs.get('ayants-droits')[1].get("bd_topo_reseau_routier_route_primaire"))
        # print(dico_gs.get('ayants-droits')[1].keys())
        # print(dico_gs.get('layers'))

    # ------------------------------------------------------------------------

    # ------------ ISOGEO ----------------------------------------------------
    # instanciating the class
    isogeo = Isogeo(client_id=app_id, client_secret=app_secret, lang=app_lang)
    token = isogeo.connect()

    search_results = isogeo.search(token)
    search_results = search_results.get('results')

    # ------------------------------------------------------------------------

    # ## EXCELs ############
    # -- WMS -------------------------------------------------------
    wb_gs_full = Workbook()
    dest_gs_full = '{}_gs_full.xlsx'.format(out_prefix)

    ws_gs_full = wb_gs_full.active
    ws_gs_full.title = "GEOSERVER - FULL"

    ws_gs_full["A1"] = "GS_WORKSPACE"
Пример #9
0
    # ignore warnings related to the QA self-signed cert
    if environ.get("ISOGEO_PLATFORM").lower() == "qa":
        urllib3.disable_warnings()

    # for oAuth2 Backend (Client Credentials Grant) Flow
    isogeo = Isogeo(
        auth_mode="group",
        client_id=environ.get("ISOGEO_API_GROUP_CLIENT_ID"),
        client_secret=environ.get("ISOGEO_API_GROUP_CLIENT_SECRET"),
        auto_refresh_url="{}/oauth/token".format(environ.get("ISOGEO_ID_URL")),
        platform=environ.get("ISOGEO_PLATFORM", "qa"),
    )

    # getting a token
    isogeo.connect()

    # ------------ Isogeo search --------------------------
    search_results = isogeo.search(
        include="all",
        specific_md=(
            "70f1192f67ac43e5987800ead18effb2",
            "b140d9a92c20416d97c3cdc12dc12607",
        ),
    )
    isogeo.close()  # close session

    # ------------ REAL START ----------------------------
    # output folder
    Path("_output/").mkdir(exist_ok=True)
Пример #10
0
config = ConfigParser.SafeConfigParser()
config.read(settings_file)

share_id = config.get('auth', 'app_id')
share_token = config.get('auth', 'app_secret')

# ------------ Real start ----------------
# instanciating the class
isogeo = Isogeo(client_id=share_id,
                client_secret=share_token)

# check which sub resources are available
print(isogeo.sub_resources_available)

# getting a token
jeton = isogeo.connect()

# let's search for metadatas!
print(dir(isogeo))
search = isogeo.search(jeton)

print(sorted(search.keys()))
print(search.get('query'))
print("Total count of metadatas shared: ", search.get("total"))
print("Count of resources got by request: {}\n".format(len(search.get("results"))))

# get one random resource
hatnumber = randrange(0, len(search.get("results")))
my_resource = isogeo.resource(jeton,
                              search.get("results")[hatnumber].get("_id"),
                              sub_resources=isogeo.sub_resources_available,
Пример #11
0
    config.read(settings_file)

    share_id = config.get('auth', 'app_id')
    share_token = config.get('auth', 'app_secret')

    # ------------ Real start ----------------
    proxies = {'http': 'http://s-olfeo1.cab.local:3129',
               'https': 'https://s-olfeo1.cab.local:3129'}
    # instanciating the class
    isogeo = Isogeo(client_id=share_id,
                    client_secret=share_token,
                    proxy=proxies
                    )

    # getting a token
    jeton = isogeo.connect()

    # let's search for metadatas!
    search = isogeo.search(jeton)
    print("Total count of metadatas shared: ", search.get("total"))
    print("Count of resources got by request: {}\n".format(len(search.get("results"))))

    # make a list of path
    # settings_dict = {s: dict(config.items(s)) for s in config.sections()}
##    path_dict = {md.get("name"): dict(config.items(md)) for md in search.get("results")}
    names_dict = {}
    for md_isogeo in search.get("results"):
        if md_isogeo.get("type")in ["vectorDataset", "rasterDataset"] and md_isogeo.get("name"):
            names_dict[md_isogeo.get("name")] = md_isogeo.get("abstract")
        else:
            pass
Пример #12
0
class IsogeoSearchForm(ttk.Frame):
    def __init__(self, master=None, async_loop=None):
        tk.Frame.__init__(self, master)
        self.async_loop = async_loop

        # basics
        # master.resizable(width=True, height=True)
        master.title(
            "Isogeo Python SDK v{} - Sample desktop search form".format(pysdk_version)
        )
        master.focus_force()
        self.grid(sticky="NSWE")
        self.grid_propagate(1)

        # styling
        self.style = ttk.Style(self)

        self.s1 = tk.PhotoImage(
            master=self, name="search1", data=data, format="gif -index 0"
        )
        self.s2 = tk.PhotoImage(
            master=self, name="search2", data=data, format="gif -index 1"
        )

        self.style.element_create(
            "Search.field",
            "image",
            "search1",
            ("focus", "search2"),
            border=[22, 7, 14],
            sticky="ew",
        )

        self.style.layout(
            "Search.entry",
            [
                (
                    "Search.field",
                    {
                        "sticky": "nswe",
                        "border": 1,
                        "children": [
                            (
                                "Entry.padding",
                                {
                                    "sticky": "nswe",
                                    "children": [
                                        ("Entry.textarea", {"sticky": "nswe"})
                                    ],
                                },
                            )
                        ],
                    },
                )
            ],
        )
        self.style.configure("Search.entry")

        # frames
        fr_global = ttk.Frame(self, name="global")
        fr_search = ttk.Frame(self, name="search_form")

        # UI vars
        self.app_name = StringVar(fr_global, "Sample desktop form")
        self.app_total = StringVar(fr_global, "0")
        self.app_url = StringVar(fr_global, "http://isogeo-api-pysdk.readthedocs.io")
        self.app_results = StringVar(fr_search, "0")

        # -- WIDGETS CREATION -------------------------------------------------
        # add widgets
        lbl_app_name = tk.Label(fr_global, textvariable=self.app_name)
        lbl_app_total = ttk.Label(fr_global, textvariable=self.app_total)
        btn_app_url = ttk.Button(
            fr_global,
            text="APP Website",
            command=lambda: self.worker_allocator(
                async_loop=self.async_loop, to_do="open_web", **{"url": self.app_url}
            ),
        )

        lbl_actions = ttk.Label(fr_search, text="Linked action")
        lbl_contacts = ttk.Label(fr_search, text="Contact")
        lbl_formats = ttk.Label(fr_search, text="Source format")
        lbl_inspires = ttk.Label(fr_search, text="INSPIRE theme")
        lbl_keywords = ttk.Label(fr_search, text="Keyword")
        lbl_licenses = ttk.Label(fr_search, text="License")
        lbl_owners = ttk.Label(fr_search, text="Owner")
        lbl_shares = ttk.Label(fr_search, text="Share")
        lbl_srs = ttk.Label(fr_search, text="Source spatial reference system")
        lbl_types = ttk.Label(fr_search, text="Type")

        # add form widgets
        self.ent_search = AutocompleteEntry(
            fr_search, style="Search.entry", width=20, completevalues=list()
        )

        self.cb_actions = AutocompleteCombobox(fr_search)
        self.cb_contacts = AutocompleteCombobox(fr_search)
        self.cb_formats = AutocompleteCombobox(fr_search)
        self.cb_inspires = AutocompleteCombobox(fr_search)
        self.cb_keywords = AutocompleteCombobox(fr_search)
        self.cb_licenses = AutocompleteCombobox(fr_search)
        self.cb_owners = AutocompleteCombobox(fr_search)
        self.cb_shares = AutocompleteCombobox(fr_search)
        self.cb_srs = AutocompleteCombobox(fr_search)
        self.cb_types = AutocompleteCombobox(fr_search)

        lbl_results = ttk.Label(fr_search, textvariable=self.app_results)

        btn_reset = ttk.Button(
            master,
            text="Reset",
            command=lambda: self.worker_allocator(
                async_loop=self.async_loop, to_do="form_clear", **{"clear": 1}
            ),
        )
        btn_close = ttk.Button(master, text="Close", command=master.destroy)

        # after UI build
        self.worker_allocator(
            async_loop=self.async_loop, to_do="form_clear", **{"clear": 1}
        )

        # -- WIDGETS PLACEMENT ------------------------------------------------
        d_pad = {"padx": 5, "pady": 5, "sticky": "NSEW"}

        lbl_app_name.grid(row=0, column=0, **d_pad)
        btn_app_url.grid(row=1, column=0, **d_pad)
        lbl_app_total.grid(row=2, column=0, **d_pad)

        self.ent_search.grid(row=1, columnspan=3, **d_pad)

        self.cb_actions.grid(row=3, column=0, **d_pad)
        self.cb_contacts.grid(row=3, column=1, **d_pad)
        self.cb_formats.grid(row=3, column=2, **d_pad)
        self.cb_inspires.grid(row=5, column=0, **d_pad)
        self.cb_keywords.grid(row=5, column=1, **d_pad)
        self.cb_licenses.grid(row=5, column=2, **d_pad)
        self.cb_owners.grid(row=7, column=0, **d_pad)
        self.cb_shares.grid(row=7, column=1, **d_pad)
        self.cb_srs.grid(row=7, column=2, **d_pad)
        self.cb_types.grid(row=9, column=1, **d_pad)

        lbl_actions.grid(row=2, column=0, **d_pad)
        lbl_contacts.grid(row=2, column=1, **d_pad)
        lbl_formats.grid(row=2, column=2, **d_pad)
        lbl_inspires.grid(row=4, column=0, **d_pad)
        lbl_keywords.grid(row=4, column=1, **d_pad)
        lbl_licenses.grid(row=4, column=2, **d_pad)
        lbl_owners.grid(row=6, column=0, **d_pad)
        lbl_shares.grid(row=6, column=1, **d_pad)
        lbl_srs.grid(row=6, column=2, **d_pad)
        lbl_types.grid(row=8, column=1, **d_pad)

        lbl_results.grid(row=22, column=0, columnspan=2, **d_pad)

        fr_global.grid(row=0, columnspan=1, **d_pad)
        fr_search.grid(row=1, columnspan=1, **d_pad)

        btn_reset.grid(row=2, column=0, sticky="NSW", padx=5, pady=5)
        btn_close.grid(row=2, column=0, sticky="NSE", padx=5, pady=5)

        # connecting comboboxes event
        self.cb_actions.bind("<<ComboboxSelected>>", self.cbs_manager)
        self.cb_contacts.bind("<<ComboboxSelected>>", self.cbs_manager)
        self.cb_formats.bind("<<ComboboxSelected>>", self.cbs_manager)
        self.cb_inspires.bind("<<ComboboxSelected>>", self.cbs_manager)
        self.cb_keywords.bind("<<ComboboxSelected>>", self.cbs_manager)
        self.cb_licenses.bind("<<ComboboxSelected>>", self.cbs_manager)
        self.cb_owners.bind("<<ComboboxSelected>>", self.cbs_manager)
        self.cb_shares.bind("<<ComboboxSelected>>", self.cbs_manager)
        self.cb_srs.bind("<<ComboboxSelected>>", self.cbs_manager)
        self.cb_types.bind("<<ComboboxSelected>>", self.cbs_manager)

    # -- TASKS HUB ------------------------------------------------------------
    def cbs_manager(self, event):
        self.worker_allocator(
            async_loop=self.async_loop, to_do="form_update", **{"clear": 0}
        )

    def worker_allocator(self, async_loop, to_do, **kwargs):
        """ Handler starting the asyncio part. """
        d = kwargs
        threading.Thread(
            target=self._asyncio_thread, args=(async_loop, to_do, d)
        ).start()

    def _asyncio_thread(self, async_loop, to_do, kwargus):
        if to_do == "form_clear":
            async_loop.run_until_complete(self.fill_form(clear=1))
        elif to_do == "form_update":
            async_loop.run_until_complete(self.fill_form(clear=0))
        elif to_do == "open_web":
            async_loop.run_until_complete(self.open_url(kwargus.get("url").get()))
        else:
            pass

    # -- ASYNC METHODS --------------------------------------------------------
    async def open_url(self, url):
        open_new_tab(url)

    async def fill_form(self, clear=0):
        if not hasattr(self, "isogeo"):
            self._init_isogeo()
        else:
            logging.info("App is already connected to Isogeo API")
            pass

        # search
        if clear:
            # clear
            self.ent_search.delete(0, "end")
            self.cb_actions.set("")
            self.cb_contacts.set("")
            self.cb_formats.set("")
            self.cb_inspires.set("")
            self.cb_keywords.set("")
            self.cb_licenses.set("")
            self.cb_owners.set("")
            self.cb_shares.set("")
            self.cb_srs.set("")
            self.cb_types.set("")
            # new search
            search = self.isogeo.search(
                self.token, page_size=0, whole_share=0, augment=1, tags_as_dicts=1
            )
            app_total = results_total = search.get("total")
            self.app_total.set("Total: {} metadata".format(app_total))
        else:
            query = self.ent_search.get() + " "
            query += self.tags.get("actions").get(self.cb_actions.get(), "") + " "
            query += self.tags.get("contacts").get(self.cb_contacts.get(), "") + " "
            query += self.tags.get("formats").get(self.cb_formats.get(), "") + " "
            query += self.tags.get("inspires").get(self.cb_inspires.get(), "") + " "
            query += self.tags.get("keywords").get(self.cb_keywords.get(), "") + " "
            query += self.tags.get("licenses").get(self.cb_licenses.get(), "") + " "
            query += self.tags.get("owners").get(self.cb_owners.get(), "") + " "
            query += self.tags.get("shares").get(self.cb_shares.get(), "") + " "
            query += self.tags.get("srs").get(self.cb_srs.get(), "") + " "
            query += self.tags.get("types").get(self.cb_types.get(), "") + " "
            search = self.isogeo.search(
                self.token,
                page_size=0,
                whole_share=0,
                augment=1,
                tags_as_dicts=1,
                query=query,
            )
            results_total = search.get("total")
            logging.debug(search.get("query"))
        self.tags = search.get("tags")

        # set values
        self.app_results.set("Results count: {} metadata".format(results_total))
        self.ent_search.set_completion_list(list(self.tags.get("keywords").values()))
        self.cb_actions.set_completion_list(list(self.tags.get("actions")))
        self.cb_contacts.set_completion_list(list(self.tags.get("contacts")))
        self.cb_formats.set_completion_list(list(self.tags.get("formats")))
        self.cb_inspires.set_completion_list(list(self.tags.get("inspires")))
        self.cb_keywords.set_completion_list(list(self.tags.get("keywords")))
        self.cb_licenses.set_completion_list(list(self.tags.get("licenses")))
        self.cb_owners.set_completion_list(list(self.tags.get("owners")))
        self.cb_shares.set_completion_list(list(self.tags.get("shares")))
        self.cb_srs.set_completion_list(list(self.tags.get("srs")))
        self.cb_types.set_completion_list(list(self.tags.get("types")))

    def _init_isogeo(self):
        api_credentials = utils.credentials_loader("client_secrets.json")
        self.isogeo = Isogeo(
            client_id=api_credentials.get("client_id"),
            client_secret=api_credentials.get("client_secret"),
        )
        self.token = self.isogeo.connect()
        # app properties
        self.isogeo.get_app_properties(self.token)
        self.app_props = self.isogeo.app_properties
        self.app_name.set(
            "Authenticated application: {}".format(self.app_props.get("name"))
        )
        self.app_url.set(self.app_props.get("url", "https://www.isogeo.com"))
Пример #13
0
class IsogeoApiMngr(object):
    """Isogeo API manager."""

    # Isogeo API wrapper
    isogeo = Isogeo
    token = str
    # ui reference - authentication form
    ui_auth_form = QtWidgets.QDialog
    auth_form_request_url = "https://www.isogeo.com"

    # api parameters
    api_app_id = ""
    api_app_secret = ""
    api_platform = "prod"
    api_app_type = "group"
    api_url_base = "https://v1.api.isogeo.com/"
    api_url_auth = "https://id.api.isogeo.com/oauth/authorize"
    api_url_token = "https://id.api.isogeo.com/oauth/token"
    api_url_redirect = "http://localhost:5000/callback"

    proxies = app_utils.proxy_settings()

    # plugin credentials storage parameters
    credentials_storage = {"QSettings": 0, "oAuth2_file": 0}
    auth_folder = ""

    # API URLs - Prod
    platform, api_url, app_url, csw_url, mng_url, oc_url, ssl = app_utils.set_base_url(
        "prod"
    )

    def __init__(self):
        super(IsogeoApiMngr, self)

    # MANAGER -----------------------------------------------------------------
    def manage_api_initialization(self):
        """Perform several operations to use Isogeo API:

        1. check if existing credentials are stored somewhere
        2. check if credentials are valid requesting Isogeo API ID
        """
        # try to retrieve existing credentials from potential sources
        self.credentials_storage["QSettings"] = self.credentials_check_qsettings()
        self.credentials_storage["oAuth2_file"] = self.credentials_check_file()

        # update class attributes from credentials found
        if self.credentials_storage.get("QSettings"):
            self.credentials_update("QSettings")
            logger.debug("Credentials used: QSettings")
        elif self.credentials_storage.get("oAuth2_file"):
            self.credentials_update("oAuth2_file")
            logger.debug("Credentials used: client_secrets file")
        else:
            logger.info("No credentials found. Opening the authentication form...")
            self.display_auth_form()
            return False

        # start api wrapper
        try:
            logger.debug("Start connection attempts")
            # client connexion
            self.isogeo = Isogeo(
                auth_mode="group",
                client_id=self.api_app_id,
                client_secret=self.api_app_secret,
                auto_refresh_url=self.api_url_token,
                lang=current_locale.name()[:2],
                platform=self.api_platform,
                proxy=app_utils.proxy_settings(),
                timeout=(30, 200),
            )
            # handle forced SSL verification
            if int(getenv("OAUTHLIB_INSECURE_TRANSPORT", 0)) == 1:
                logger.info("Forced disabled SSL verification")
                self.ssl = False
                self.isogeo.ssl = False
                app_utils.ssl = False

            # start connection
            self.isogeo.connect()
            logger.debug("Authentication succeeded")
            return True
        except ValueError as e:
            logger.error(e)
            self.display_auth_form()
        except EnvironmentError as e:
            logger.error(e)
        except Exception as e:
            logger.error(e)
            self.display_auth_form()

    # CREDENTIALS LOCATORS ----------------------------------------------------
    def credentials_check_qsettings(self):
        """Retrieve Isogeo API credentials within APP QSettings."""
        if "auth" in qsettings.childGroups() and qsettings.contains("auth/app_id"):
            logger.debug("Credentials found within QSettings: isogeo/")
            return True
        else:
            logger.debug("No Isogeo credentials found within QSettings.")
            return False

    def credentials_check_file(self):
        """Retrieve Isogeo API credentials from a file stored inside the
        plugin _auth subfolder.
        """
        credentials_filepath = path.join(self.auth_folder, "client_secrets.json")
        # check if a client_secrets.json fil is stored inside the _auth subfolder
        if not path.isfile(credentials_filepath):
            logger.debug("No credential files found: {}".format(credentials_filepath))
            return False
        # check file structure
        try:
            app_utils.credentials_loader(credentials_filepath)
            logger.debug("Credentials found in {}".format(credentials_filepath))
        except Exception as e:
            logger.debug(e)
            return False
        # end of method
        return True

    # CREDENTIALS SAVER -------------------------------------------------------
    def credentials_storer(self, store_location="QSettings"):
        """Store class credentials attributes into the specified store_location.

        :param store_location str: name of targetted store location. Options:
            - QSettings
        """
        if store_location == "QSettings":
            qsettings.setValue("auth/app_id", self.api_app_id)
            qsettings.setValue("auth/app_secret", self.api_app_secret)
            qsettings.setValue("auth/app_type", self.api_app_type)
            qsettings.setValue("auth/platform", self.api_platform)
            qsettings.setValue("auth/url_base", self.api_url_base)
            qsettings.setValue("auth/url_auth", self.api_url_auth)
            qsettings.setValue("auth/url_token", self.api_url_token)
            qsettings.setValue("auth/url_redirect", self.api_url_redirect)
        else:
            pass
        logger.debug("Credentials stored into: {}".format(store_location))

    def credentials_update(self, credentials_source="QSettings"):
        """Update class attributes from specified credentials source."""
        # update class attributes
        if credentials_source == "QSettings":
            self.api_app_id = qsettings.value("auth/app_id", "")
            self.api_app_secret = qsettings.value("auth/app_secret", "")
            self.api_app_type = qsettings.value("auth/app_type", "group")
            self.api_platform = qsettings.value("auth/platform", "prod")
            self.api_url_base = qsettings.value(
                "auth/url_base", "https://v1.api.isogeo.com/"
            )
            self.api_url_auth = qsettings.value(
                "auth/url_auth", "https://id.api.isogeo.com/oauth/authorize"
            )
            self.api_url_token = qsettings.value(
                "auth/url_token", "https://id.api.isogeo.com/oauth/token"
            )
            self.api_url_redirect = qsettings.value(
                "auth/url_redirect", "http://localhost:5000/callback"
            )
        elif credentials_source == "oAuth2_file":
            creds = app_utils.credentials_loader(
                path.join(self.auth_folder, "client_secrets.json")
            )
            self.api_app_id = creds.get("client_id")
            self.api_app_secret = creds.get("client_secret")
            self.api_app_type = creds.get("type", "group")
            self.api_platform = creds.get("platform", "prod")
            self.api_url_base = creds.get("uri_base")
            self.api_url_auth = creds.get("uri_auth")
            self.api_url_token = creds.get("uri_token")
            self.api_url_redirect = creds.get("uri_redirect")
        else:
            pass

        logger.debug(
            "Credentials updated from: {}. Application connected to the platform '{}' using CLIENT_ID: {}".format(
                credentials_source, self.api_platform, self.api_app_id
            )
        )

    # AUTHENTICATION FORM -----------------------------------------------------
    def display_auth_form(self):
        """Show authentication form with prefilled fields."""
        # connect widgets
        self.ui_auth_form.chb_isogeo_editor.stateChanged.connect(
            lambda: qsettings.setValue(
                "user/editor", int(self.ui_auth_form.chb_isogeo_editor.isChecked())
            )
        )
        self.ui_auth_form.btn_ok_cancel.clicked.connect(self.ui_auth_form.close)
        # button to request an account by email
        self.ui_auth_form.btn_account_new.pressed.connect(
            partial(app_utils.open_urls, [self.auth_form_request_url])
        )

        # fillfull auth form fields from stored settings
        self.ui_auth_form.btn_ok_cancel.setEnabled(0)
        self.ui_auth_form.ent_app_id.setText(self.api_app_id)
        self.ui_auth_form.ent_app_secret.setText(self.api_app_secret)
        self.ui_auth_form.lbl_api_url_value.setText(self.api_url_base)
        self.ui_auth_form.chb_isogeo_editor.setChecked(
            qsettings.value("user/editor", 0)
        )
        # display
        logger.debug("Authentication form filled and ready to be launched.")
        self.ui_auth_form.show()
        self.ui_auth_form.setFocus()

    def credentials_uploader(self):
        """Get file selected by the user and loads API credentials into plugin.
        If the selected is compliant, credentials are loaded from then it's
        moved inside ./_auth subfolder.
        """
        selected_file = app_utils.open_FileNameDialog(self.ui_auth_form)
        logger.debug(
            "Credentials file picker (QFileDialog) returned: {}".format(selected_file)
        )
        # test file path
        try:
            in_creds_path = Path(selected_file[0])
            assert in_creds_path.exists()
        except FileExistsError:
            logger.error(
                FileExistsError(
                    "No auth file selected or path is incorrect: {}".format(
                        selected_file[0]
                    )
                )
            )
            return False
        except Exception as e:
            logger.error(e)
            return False

        # test file structure
        try:
            api_credentials = app_utils.credentials_loader(in_creds_path.resolve())
        except Exception as e:
            logger.error("Selected file is bad formatted: {}".format(e))
            return False

        # rename previous credentials file
        creds_dest_path = Path(self.auth_folder) / "client_secrets.json"
        if creds_dest_path.is_file():
            creds_dest_path_renamed = Path(
                self.auth_folder
            ) / "old_client_secrets_{}.json".format(int(time.time()))
            rename(creds_dest_path.resolve(), creds_dest_path_renamed.resolve())
            logger.debug(
                "`./_auth/client_secrets.json already existed`. Previous file has been renamed."
            )
        else:
            pass
        # move new credentials file into ./_auth dir
        rename(in_creds_path.resolve(), creds_dest_path.resolve())
        logger.debug(
            "Selected credentials file has been moved into plugin './_auth' subfolder"
        )

        # check validity
        try:
            self.isogeo = Isogeo(
                auth_mode="group",
                client_id=api_credentials.get("client_id"),
                client_secret=api_credentials.get("client_secret"),
                auto_refresh_url=api_credentials.get("uri_token"),
                platform=api_credentials.get("platform"),
                proxy=app_utils.proxy_settings(),
            )
        except Exception as e:
            logger.debug(e)
            return False

        # set form
        self.ui_auth_form.ent_app_id.setText(api_credentials.get("client_id"))
        self.ui_auth_form.ent_app_secret.setText(api_credentials.get("client_secret"))
        self.ui_auth_form.lbl_api_url_value.setText(api_credentials.get("uri_auth"))
        self.ui_auth_form.btn_ok_cancel.setEnabled(1)

        # update class attributes from file
        self.credentials_update(credentials_source="oAuth2_file")

        # store into QSettings if existing
        self.credentials_storer(store_location="QSettings")