nemo-library


Namenemo-library JSON
Version 1.1.12 PyPI version JSON
download
home_pageNone
SummaryA library for uploading data to and downloading reports from NEMO cloud solution
upload_time2024-08-29 12:26:00
maintainerNone
docs_urlNone
authorGunnar Schug
requires_pythonNone
licenseNone
keywords
VCS
bugtrack_url
requirements beautifulsoup4 bleach boto3 botocore build certifi charset-normalizer coverage docutils et-xmlfile hubspot-api-client idna importlib_metadata iniconfig jaraco.classes jaraco.context jaraco.functools jmespath keyring markdown-it-py mdurl more-itertools nh3 numpy openpyxl packaging pandas pandoc pkginfo pluggy plumbum ply Pygments pyproject_hooks pytest pytest-cov python-dateutil pytz readme_renderer requests requests-toolbelt rfc3986 rich s3transfer setuptools six soupsieve twine tzdata urllib3 webencodings wheel zipp
Travis-CI No Travis.
coveralls test coverage No coveralls.
            NEMO Library
============

This library helps you with access to NEMO APIs

Installation
============

::

   pip install nemo_library

Sources
=======

please find all sources on github:
https://github.com/H3rm1nat0r/nemo_library

configuration
=============

please create a file “config.ini”. This is an example for the content:

::

   [nemo_library]
   nemo_url = https://enter.nemo-ai.com
   tenant = <your tenant>
   userid = <your userid>
   password = <your password>
   environment = [prod|dev|demo]
   hubspot_api_token = <your API token, if you are going to use the HubSpot adapter, blank if not used>

If you don’t want to pass userid/password in a file (which is readable
to everybody that has access to the file), you can use Windows
Credential Manager or MacOS key chain to store your password. Please use
“nemo_library” as “Program name”. As an alternative, you can
programmatically set your password by using this code

.. code:: python

   from nemo_library.sub_password_handler import *

   service_name = "nemo_library"
   username = "my_username"
   password = "my_password"

   pm = PasswordManager(service_name, username)

   # Set password
   pm.set_password(password)
   print(f"Password for user '{username}' in service '{service_name}' has been stored.")

   # Retrieve password
   retrieved_password = pm.get_password()
   if retrieved_password:
       print(f"The stored password for user '{username}' is: {retrieved_password}")
   else:
       print(f"No password found for user '{username}' in service '{service_name}'.")

Methods
=======

Projects
--------

getProjectList method
~~~~~~~~~~~~~~~~~~~~~

Return list of projects (as pandas Dataframe)

.. code:: python

   from nemo_library import NemoLibrary

   nl = NemoLibrary()
   df = nl.getProjectList()

getProjectID method
~~~~~~~~~~~~~~~~~~~

Return internal id of project identified by given project name as shown
in the NEMO UI

.. code:: python

   from nemo_library import NemoLibrary

   nl = NemoLibrary()
   print(nl.getProjectID(projectname="Business Processes"))

ReUploadFile method
~~~~~~~~~~~~~~~~~~~

ReUpload a CSV file into an existing project

.. code:: python

   from nemo_library import NemoLibrary

   nl = NemoLibrary()
   nl.ReUploadFile(projectname="21 CRM", filename="./csv/hubspot.csv")

Args: - projectname (str): Name of the project. - filename (str): Name
of the file to be uploaded. - update_project_settings (bool, optional):
Whether to update project settings after ingestion. Defaults to True. -
datasource_ids (list[dict], optional): List of datasource identifiers
for V3 ingestion. Defaults to None. - global_fields_mapping (list[dict],
optional): Global fields mapping for V3 ingestion. Defaults to None. -
version (int, optional): Version of the ingestion process (2 or 3).
Defaults to 2 - trigger_only (bool, optional): Whether to trigger only
without waiting for task completion. Applicable for V3. Defaults to
False.

V2 uploads a file plain into the project. V3 merges the data with the
Business Processes project (needs more parameters)

synchronizeCsvColsAndImportedColumns method
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Sychronize columns with CSV file and NEMO meta data. This method
compares the list of columns found in CSV with the list of columns
defined in meta data and adds or removes missing or not-any-longer-used
columns to and from meta data. For performance reasons, you should not
use it on a daily base, but after changes in the source, it makes sense
to call it before uploading a file.

Here’s some example code from Gunnar’s reporting

.. code:: python

   nl = NemoLibrary()
   if synch_columns:
       nl.synchronizeCsvColsAndImportedColumns(
           projectname=PROJECT_NAME_SNR0,
           filename=folder_reporting_input_pa() + "/snr0_NEMO.csv",
       )
       time.sleep(120)
   nl.ReUploadFile(
       projectname=PROJECT_NAME_SNR0,
       filename=folder_reporting_input_pa() + "/snr0_NEMO.csv",
   )

Reports
-------

LoadReport method
~~~~~~~~~~~~~~~~~

Load a report from NEMO and return this as pandas dataframe

.. code:: python

   from nemo_library import NemoLibrary

   nl = NemoLibrary()
   df = nl.LoadReport(report_guid="b82cfed8-81a7-44e0-b3da-c76454540697")

project_id
^^^^^^^^^^

Optional parameter. If you want to get reports for non-default ERP
projects. Please provide the project GUID (you can retrieve them by
running getProjectList)

report_guid
^^^^^^^^^^^

This methode takes 1 mandatory parameter, the report_guid. You can find
“your” guid in NEMO meta data. Just open the definition of the report in
meta data and copy the GUID from your browser URL.

The report “(SAMPLE) Replenishment Time Analysis Purchased Parts” for
example has this URL:
https://enter.nemo-ai.com/nemo/metadata/report/b82cfed8-81a7-44e0-b3da-c76454540697
and thus the GUID you need is then
“b82cfed8-81a7-44e0-b3da-c76454540697”

max_pages
^^^^^^^^^

By default all pages from the report are loaded. You can optionally
restrict the amount of data by providing max_pages parameter and you’ll
get not more than this number of pages (usually 1 page holds 20 records)

InfoZoom / NEMO synchronization
-------------------------------

There are two thinkable ways of synchronization between InfoZoom and
NEMO. At the moment, we support InfoZoom –> NEMO direction only. The
other way is on my wish list, but not implemented yet

InfoZoom –> NEMO
~~~~~~~~~~~~~~~~

When synchronizing an InfoZoom (FOX) file with NEMO, there are two
thinks to think about - data: data can easily uploaded using the above
mentioned “ReUploadFile” method (maybe you need to use InfoZoom batch
commands to extract the data first). But it’s on my list as well to make
this more automatic - meta data: this is the point, where this library
is the closest to a final solution

exportMetadata
^^^^^^^^^^^^^^

Exports metadata from an InfoZoom file using the InfoZoom executable.

.. code:: python

   from nemo_library import NemoLibrary

   nl = NemoLibrary()
   nl.exportMetadata(infozoomexe="C:\\Program Files (x86)\\NEMO\\InfoZoom 2025\\InfoZoom.exe",infozoomfile="D:\\temp\\SNr.fox",metadatafile="D:\\temp\\SNr.metadata.csv")

This code snipped calls exportMetadata method which itself opens
InfoZoom (identified by the given executable path), then opens the given
fox file, openes the metadata view and finally exports the metadata file
into the given CSV file (delimiter ;, UTF-8-Format).

This is the first step needed to synchronize the FOX meta data with
NEMO.

synchMetadataWithFocus
~~~~~~~~~~~~~~~~~~~~~~

Synchronizes metadata from a given CSV file with the NEMO project
metadata.

This method reads metadata from a CSV file, processes it, and
synchronizes it with the metadata of a specified NEMO project. It
handles the creation of groups first and then processes individual
attributes.

.. code:: python

   from nemo_library import NemoLibrary

   nl = NemoLibrary()
   projectId = nl.getProjectID(projectname="VH0001_21_XVH001_SNrNemo")
   nl.synchMetadataWithFocus(metadatafile="d:\\temp\\SNr.metadata.csv", projectId=projectId)

This code snipped gets the projectid identified by its name in NEMO and
then synchronizes the meta data (exported by synchMetadataWithFocus)
with NEMO.

At the moment the following pieces are synchronized - Groups (and sub
groups and sub sub groups etc) - sequence of attributes (and allocation
with groups)

This is a list of pieces that are currently ignored - Couples - Formulae
- case statements - aggregations - this list is not complete

HubSpot
-------

HubSpot is the very first CRM product that we support in this library.
This adapter provides a method that uses the HubSpot API to extract
deals and their history (deal changes as well as documented
communication) and finally uploads this into a NEMO project given by
it’s name.

If you want to use this, you have to enable this feature in Hubspot
first. Steps: - create a private app in HubSpot (e.g. export for NEMO) -
you are given an API token and a secret. Note them and enter the API
token in the config.ini-file. Example:

::

   hubspot_api_token = <your API token>

-  provide read access to all objects, e.g. crm.schemas.deals.read, etc.

Then you can use the HubSpot adapter like in this example:

.. code:: python

   nl = NemoLibrary()
   nl.FetchDealFromHubSpotAndUploadToNEMO(projectname="21 CRM Activities")

Contributions
=============

Contributions are welcome! If you would like to suggest improvements or
have found a bug, please open an issue or submit a pull request.

License
=======

This project is released under the Unlicense. You can find the full text
of the Unlicense in the `UNLICENSE <UNLICENSE>`__ file. This means that
the code is released into the public domain, and you are free to use,
modify, distribute, and do whatever you want with it, without any
restrictions or requirements.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "nemo-library",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": null,
    "author": "Gunnar Schug",
    "author_email": "GunnarSchug81@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/49/ee/4c0c88fd31a50c445e7d9f475e59feac28792757bb22ecb1d2317f12d0ed/nemo_library-1.1.12.tar.gz",
    "platform": null,
    "description": "NEMO Library\n============\n\nThis library helps you with access to NEMO APIs\n\nInstallation\n============\n\n::\n\n   pip install nemo_library\n\nSources\n=======\n\nplease find all sources on github:\nhttps://github.com/H3rm1nat0r/nemo_library\n\nconfiguration\n=============\n\nplease create a file \u201cconfig.ini\u201d. This is an example for the content:\n\n::\n\n   [nemo_library]\n   nemo_url = https://enter.nemo-ai.com\n   tenant = <your tenant>\n   userid = <your userid>\n   password = <your password>\n   environment = [prod|dev|demo]\n   hubspot_api_token = <your API token, if you are going to use the HubSpot adapter, blank if not used>\n\nIf you don\u2019t want to pass userid/password in a file (which is readable\nto everybody that has access to the file), you can use Windows\nCredential Manager or MacOS key chain to store your password. Please use\n\u201cnemo_library\u201d as \u201cProgram name\u201d. As an alternative, you can\nprogrammatically set your password by using this code\n\n.. code:: python\n\n   from nemo_library.sub_password_handler import *\n\n   service_name = \"nemo_library\"\n   username = \"my_username\"\n   password = \"my_password\"\n\n   pm = PasswordManager(service_name, username)\n\n   # Set password\n   pm.set_password(password)\n   print(f\"Password for user '{username}' in service '{service_name}' has been stored.\")\n\n   # Retrieve password\n   retrieved_password = pm.get_password()\n   if retrieved_password:\n       print(f\"The stored password for user '{username}' is: {retrieved_password}\")\n   else:\n       print(f\"No password found for user '{username}' in service '{service_name}'.\")\n\nMethods\n=======\n\nProjects\n--------\n\ngetProjectList method\n~~~~~~~~~~~~~~~~~~~~~\n\nReturn list of projects (as pandas Dataframe)\n\n.. code:: python\n\n   from nemo_library import NemoLibrary\n\n   nl = NemoLibrary()\n   df = nl.getProjectList()\n\ngetProjectID method\n~~~~~~~~~~~~~~~~~~~\n\nReturn internal id of project identified by given project name as shown\nin the NEMO UI\n\n.. code:: python\n\n   from nemo_library import NemoLibrary\n\n   nl = NemoLibrary()\n   print(nl.getProjectID(projectname=\"Business Processes\"))\n\nReUploadFile method\n~~~~~~~~~~~~~~~~~~~\n\nReUpload a CSV file into an existing project\n\n.. code:: python\n\n   from nemo_library import NemoLibrary\n\n   nl = NemoLibrary()\n   nl.ReUploadFile(projectname=\"21 CRM\", filename=\"./csv/hubspot.csv\")\n\nArgs: - projectname (str): Name of the project. - filename (str): Name\nof the file to be uploaded. - update_project_settings (bool, optional):\nWhether to update project settings after ingestion. Defaults to True. -\ndatasource_ids (list[dict], optional): List of datasource identifiers\nfor V3 ingestion. Defaults to None. - global_fields_mapping (list[dict],\noptional): Global fields mapping for V3 ingestion. Defaults to None. -\nversion (int, optional): Version of the ingestion process (2 or 3).\nDefaults to 2 - trigger_only (bool, optional): Whether to trigger only\nwithout waiting for task completion. Applicable for V3. Defaults to\nFalse.\n\nV2 uploads a file plain into the project. V3 merges the data with the\nBusiness Processes project (needs more parameters)\n\nsynchronizeCsvColsAndImportedColumns method\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nSychronize columns with CSV file and NEMO meta data. This method\ncompares the list of columns found in CSV with the list of columns\ndefined in meta data and adds or removes missing or not-any-longer-used\ncolumns to and from meta data. For performance reasons, you should not\nuse it on a daily base, but after changes in the source, it makes sense\nto call it before uploading a file.\n\nHere\u2019s some example code from Gunnar\u2019s reporting\n\n.. code:: python\n\n   nl = NemoLibrary()\n   if synch_columns:\n       nl.synchronizeCsvColsAndImportedColumns(\n           projectname=PROJECT_NAME_SNR0,\n           filename=folder_reporting_input_pa() + \"/snr0_NEMO.csv\",\n       )\n       time.sleep(120)\n   nl.ReUploadFile(\n       projectname=PROJECT_NAME_SNR0,\n       filename=folder_reporting_input_pa() + \"/snr0_NEMO.csv\",\n   )\n\nReports\n-------\n\nLoadReport method\n~~~~~~~~~~~~~~~~~\n\nLoad a report from NEMO and return this as pandas dataframe\n\n.. code:: python\n\n   from nemo_library import NemoLibrary\n\n   nl = NemoLibrary()\n   df = nl.LoadReport(report_guid=\"b82cfed8-81a7-44e0-b3da-c76454540697\")\n\nproject_id\n^^^^^^^^^^\n\nOptional parameter. If you want to get reports for non-default ERP\nprojects. Please provide the project GUID (you can retrieve them by\nrunning getProjectList)\n\nreport_guid\n^^^^^^^^^^^\n\nThis methode takes 1 mandatory parameter, the report_guid. You can find\n\u201cyour\u201d guid in NEMO meta data. Just open the definition of the report in\nmeta data and copy the GUID from your browser URL.\n\nThe report \u201c(SAMPLE) Replenishment Time Analysis Purchased Parts\u201d for\nexample has this URL:\nhttps://enter.nemo-ai.com/nemo/metadata/report/b82cfed8-81a7-44e0-b3da-c76454540697\nand thus the GUID you need is then\n\u201cb82cfed8-81a7-44e0-b3da-c76454540697\u201d\n\nmax_pages\n^^^^^^^^^\n\nBy default all pages from the report are loaded. You can optionally\nrestrict the amount of data by providing max_pages parameter and you\u2019ll\nget not more than this number of pages (usually 1 page holds 20 records)\n\nInfoZoom / NEMO synchronization\n-------------------------------\n\nThere are two thinkable ways of synchronization between InfoZoom and\nNEMO. At the moment, we support InfoZoom \u2013> NEMO direction only. The\nother way is on my wish list, but not implemented yet\n\nInfoZoom \u2013> NEMO\n~~~~~~~~~~~~~~~~\n\nWhen synchronizing an InfoZoom (FOX) file with NEMO, there are two\nthinks to think about - data: data can easily uploaded using the above\nmentioned \u201cReUploadFile\u201d method (maybe you need to use InfoZoom batch\ncommands to extract the data first). But it\u2019s on my list as well to make\nthis more automatic - meta data: this is the point, where this library\nis the closest to a final solution\n\nexportMetadata\n^^^^^^^^^^^^^^\n\nExports metadata from an InfoZoom file using the InfoZoom executable.\n\n.. code:: python\n\n   from nemo_library import NemoLibrary\n\n   nl = NemoLibrary()\n   nl.exportMetadata(infozoomexe=\"C:\\\\Program Files (x86)\\\\NEMO\\\\InfoZoom 2025\\\\InfoZoom.exe\",infozoomfile=\"D:\\\\temp\\\\SNr.fox\",metadatafile=\"D:\\\\temp\\\\SNr.metadata.csv\")\n\nThis code snipped calls exportMetadata method which itself opens\nInfoZoom (identified by the given executable path), then opens the given\nfox file, openes the metadata view and finally exports the metadata file\ninto the given CSV file (delimiter ;, UTF-8-Format).\n\nThis is the first step needed to synchronize the FOX meta data with\nNEMO.\n\nsynchMetadataWithFocus\n~~~~~~~~~~~~~~~~~~~~~~\n\nSynchronizes metadata from a given CSV file with the NEMO project\nmetadata.\n\nThis method reads metadata from a CSV file, processes it, and\nsynchronizes it with the metadata of a specified NEMO project. It\nhandles the creation of groups first and then processes individual\nattributes.\n\n.. code:: python\n\n   from nemo_library import NemoLibrary\n\n   nl = NemoLibrary()\n   projectId = nl.getProjectID(projectname=\"VH0001_21_XVH001_SNrNemo\")\n   nl.synchMetadataWithFocus(metadatafile=\"d:\\\\temp\\\\SNr.metadata.csv\", projectId=projectId)\n\nThis code snipped gets the projectid identified by its name in NEMO and\nthen synchronizes the meta data (exported by synchMetadataWithFocus)\nwith NEMO.\n\nAt the moment the following pieces are synchronized - Groups (and sub\ngroups and sub sub groups etc) - sequence of attributes (and allocation\nwith groups)\n\nThis is a list of pieces that are currently ignored - Couples - Formulae\n- case statements - aggregations - this list is not complete\n\nHubSpot\n-------\n\nHubSpot is the very first CRM product that we support in this library.\nThis adapter provides a method that uses the HubSpot API to extract\ndeals and their history (deal changes as well as documented\ncommunication) and finally uploads this into a NEMO project given by\nit\u2019s name.\n\nIf you want to use this, you have to enable this feature in Hubspot\nfirst. Steps: - create a private app in HubSpot (e.g.\u00a0export for NEMO) -\nyou are given an API token and a secret. Note them and enter the API\ntoken in the config.ini-file. Example:\n\n::\n\n   hubspot_api_token = <your API token>\n\n-  provide read access to all objects, e.g.\u00a0crm.schemas.deals.read, etc.\n\nThen you can use the HubSpot adapter like in this example:\n\n.. code:: python\n\n   nl = NemoLibrary()\n   nl.FetchDealFromHubSpotAndUploadToNEMO(projectname=\"21 CRM Activities\")\n\nContributions\n=============\n\nContributions are welcome! If you would like to suggest improvements or\nhave found a bug, please open an issue or submit a pull request.\n\nLicense\n=======\n\nThis project is released under the Unlicense. You can find the full text\nof the Unlicense in the `UNLICENSE <UNLICENSE>`__ file. This means that\nthe code is released into the public domain, and you are free to use,\nmodify, distribute, and do whatever you want with it, without any\nrestrictions or requirements.\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "A library for uploading data to and downloading reports from NEMO cloud solution",
    "version": "1.1.12",
    "project_urls": {
        "Github": "https://github.com/H3rm1nat0r/nemo_library",
        "NEMO": "https://enter.nemo-ai.com/nemo/"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "3949f70bc74004e6879ad3732f4c87db3163932979e61396854c227c2ab5e89c",
                "md5": "e56310937f3b9282309618227ee566c9",
                "sha256": "e93651503abaebd4e934995343a6688462adb8000a384ed21a1d88be2bbaaec7"
            },
            "downloads": -1,
            "filename": "nemo_library-1.1.12-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "e56310937f3b9282309618227ee566c9",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 41999,
            "upload_time": "2024-08-29T12:25:58",
            "upload_time_iso_8601": "2024-08-29T12:25:58.330727Z",
            "url": "https://files.pythonhosted.org/packages/39/49/f70bc74004e6879ad3732f4c87db3163932979e61396854c227c2ab5e89c/nemo_library-1.1.12-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "49ee4c0c88fd31a50c445e7d9f475e59feac28792757bb22ecb1d2317f12d0ed",
                "md5": "9895d05a8cb4288492ed9dcbfc023ddf",
                "sha256": "b9962d9904357a2828ce20bc28ac85740cc47ea6fc497fbc66ffe760195645be"
            },
            "downloads": -1,
            "filename": "nemo_library-1.1.12.tar.gz",
            "has_sig": false,
            "md5_digest": "9895d05a8cb4288492ed9dcbfc023ddf",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 43216,
            "upload_time": "2024-08-29T12:26:00",
            "upload_time_iso_8601": "2024-08-29T12:26:00.086765Z",
            "url": "https://files.pythonhosted.org/packages/49/ee/4c0c88fd31a50c445e7d9f475e59feac28792757bb22ecb1d2317f12d0ed/nemo_library-1.1.12.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-08-29 12:26:00",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "H3rm1nat0r",
    "github_project": "nemo_library",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [
        {
            "name": "beautifulsoup4",
            "specs": []
        },
        {
            "name": "bleach",
            "specs": []
        },
        {
            "name": "boto3",
            "specs": []
        },
        {
            "name": "botocore",
            "specs": []
        },
        {
            "name": "build",
            "specs": []
        },
        {
            "name": "certifi",
            "specs": []
        },
        {
            "name": "charset-normalizer",
            "specs": []
        },
        {
            "name": "coverage",
            "specs": []
        },
        {
            "name": "docutils",
            "specs": []
        },
        {
            "name": "et-xmlfile",
            "specs": []
        },
        {
            "name": "hubspot-api-client",
            "specs": []
        },
        {
            "name": "idna",
            "specs": []
        },
        {
            "name": "importlib_metadata",
            "specs": []
        },
        {
            "name": "iniconfig",
            "specs": []
        },
        {
            "name": "jaraco.classes",
            "specs": []
        },
        {
            "name": "jaraco.context",
            "specs": []
        },
        {
            "name": "jaraco.functools",
            "specs": []
        },
        {
            "name": "jmespath",
            "specs": []
        },
        {
            "name": "keyring",
            "specs": []
        },
        {
            "name": "markdown-it-py",
            "specs": []
        },
        {
            "name": "mdurl",
            "specs": []
        },
        {
            "name": "more-itertools",
            "specs": []
        },
        {
            "name": "nh3",
            "specs": []
        },
        {
            "name": "numpy",
            "specs": []
        },
        {
            "name": "openpyxl",
            "specs": []
        },
        {
            "name": "packaging",
            "specs": []
        },
        {
            "name": "pandas",
            "specs": []
        },
        {
            "name": "pandoc",
            "specs": []
        },
        {
            "name": "pkginfo",
            "specs": []
        },
        {
            "name": "pluggy",
            "specs": []
        },
        {
            "name": "plumbum",
            "specs": []
        },
        {
            "name": "ply",
            "specs": []
        },
        {
            "name": "Pygments",
            "specs": []
        },
        {
            "name": "pyproject_hooks",
            "specs": []
        },
        {
            "name": "pytest",
            "specs": []
        },
        {
            "name": "pytest-cov",
            "specs": []
        },
        {
            "name": "python-dateutil",
            "specs": []
        },
        {
            "name": "pytz",
            "specs": []
        },
        {
            "name": "readme_renderer",
            "specs": []
        },
        {
            "name": "requests",
            "specs": []
        },
        {
            "name": "requests-toolbelt",
            "specs": []
        },
        {
            "name": "rfc3986",
            "specs": []
        },
        {
            "name": "rich",
            "specs": []
        },
        {
            "name": "s3transfer",
            "specs": []
        },
        {
            "name": "setuptools",
            "specs": []
        },
        {
            "name": "six",
            "specs": []
        },
        {
            "name": "soupsieve",
            "specs": []
        },
        {
            "name": "twine",
            "specs": []
        },
        {
            "name": "tzdata",
            "specs": []
        },
        {
            "name": "urllib3",
            "specs": []
        },
        {
            "name": "webencodings",
            "specs": []
        },
        {
            "name": "wheel",
            "specs": []
        },
        {
            "name": "zipp",
            "specs": []
        }
    ],
    "lcname": "nemo-library"
}
        
Elapsed time: 0.32747s