netsuitesdk


Namenetsuitesdk JSON
Version 2.21.0 PyPI version JSON
download
home_pagehttps://github.com/fylein/netsuite-sdk-py
SummaryPython SDK for accessing the NetSuite SOAP webservice
upload_time2023-08-29 09:45:19
maintainer
docs_urlNone
authorSiva Narayanan
requires_python
licenseMIT
keywords netsuite api python sdk
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage
            # netsuite-sdk-py

Netsuite-sdk-py is a Python SDK. It uses the SOAP client library zeep(https://python-zeep.readthedocs.io/en/master/) for accessing NetSuite resources via the NetSuite SOAP web service SuiteTalk(http://www.netsuite.com/portal/platform/developer/suitetalk.shtml), but hides the complexity from the SDK user.

## Installation

	$ pip install netsuitesdk 

## Get Started

There are two ways to access a NetSuite account via web services: 
- Use token-based auth (TBA) (within each request). This is the mechanism supported by this SDK.
- Use email, password, role and account id to login and start a session. This is not supported by this SDK

### Token-based Auth

First, setup TBA credentials using environment variables.

```
# TBA credentials
export NS_ACCOUNT=xxxx
export NS_CONSUMER_KEY=xxxx
export NS_CONSUMER_SECRET=xxxx
export NS_TOKEN_KEY=xxxx
export NS_TOKEN_SECRET=xxxx

```

The following snippet shows how to use TBA to initialize the SDK.

```python
import os
import itertools
import json
from netsuitesdk import NetSuiteConnection

def connect_tba():
    NS_ACCOUNT = os.getenv('NS_ACCOUNT')
    NS_CONSUMER_KEY = os.getenv('NS_CONSUMER_KEY')
    NS_CONSUMER_SECRET = os.getenv('NS_CONSUMER_SECRET')
    NS_TOKEN_KEY = os.getenv('NS_TOKEN_KEY')
    NS_TOKEN_SECRET = os.getenv('NS_TOKEN_SECRET')
    nc = NetSuiteConnection(
        account=NS_ACCOUNT,
        consumer_key=NS_CONSUMER_KEY,
        consumer_secret=NS_CONSUMER_SECRET,
        token_key=NS_TOKEN_KEY,
        token_secret=NS_TOKEN_SECRET
    )
    return nc

nc = connect_tba()

# Use get_all methods to get all objects of certain types
currencies = nc.currencies.get_all()
locations = nc.locations.get_all()
departments = nc.departments.get_all()
classifications = nc.classifications.get_all()
subsidiaries = nc.subsidiaries.get_all()
expense_categories = nc.expense_categories.get_all()
employees = nc.employees.get_all()
all_accounts = list(itertools.islice(nc.accounts.get_all_generator(), 100))
accounts = [a for a in all_accounts if a['acctType'] == '_expense']
vendor_bills = list(itertools.islice(nc.vendor_bills.get_all_generator(), 10))
vendors = list(itertools.islice(nc.vendors.get_all_generator(), 10))
vendor_payments = nc.vendor_payments.get_all()

data = {
  'accounts': accounts,
  'classifications': classifications,
  'departments': departments,
  'locations': locations,
  'currencies': currencies,
  'vendors': vendors,
  'vendor_bills': vendor_bills,
  'subsidiaries': subsidiaries,
  'expense_categories': expense_categories,
  'employees': employees,
  'vendor_payments': vendor_payments
}
with open('/tmp/netsuite.json', 'w') as oj:
	oj.write(json.dumps(data, default=str, indent=2))

# There are also generator methods to iterate over potentially large lists
for c in nc.currencies.get_all_generator():
    print(c)

# Get a specific object
nc.currencies.get(internalId='1')

# Post operation is only supported on vendor_bills, expense_reports, journal_entries and vendor_payments currently (see tests on how to construct vendor bill, expense report and journal entry)
vb = {...}
nc.vendor_bills.post(vb)

er = {...}
nc.expense_reports.post(er)

je = {...}
nc.journal_entries.post(je)

vp = {...}
nc.vendor_payments.post(vp)

### Upsert Files
file = open('receipt.pdf', 'rb').read()

created_folder = nc.folders.post(
    {
        "externalId": 'new-folder',
        "name": 'Receipts'
    }
)

uploaded_file = nc.files.post({
    "externalId": "receipt 1",
    "name": 'receipt.pdf',
    'content': file,
    'fileType': '_PDF',
    "folder": {
                "name": None,
                "internalId": 695,
                "externalId": 'new-folder',
                "type": "folder"
            }
    }
)
```

<!-- ### Password-based Auth

Password-based auth is less preferred. You can set the following environment variables for convenience:

```
export NS_EMAIL=xxxx
export NS_PASSWORD=xxxx
export NS_ROLE=xxx
export NS_ACCOUNT=xxxx
export NS_APPID=xxxx
```

Here's a snippet that shows how the client can be initialized.

```python
import os

from netsuitesdk import NetSuiteClient

def connect_password():
    NS_EMAIL = os.getenv("NS_EMAIL")
    NS_PASSWORD = os.getenv("NS_PASSWORD")
    NS_ROLE = os.getenv("NS_ROLE")
    NS_ACCOUNT = os.getenv("NS_ACCOUNT")
    NS_APPID = os.getenv("NS_APPID")

    ns = NetSuiteClient(account=NS_ACCOUNT)
    ns.login(email=NS_EMAIL, password=NS_PASSWORD, role=NS_ROLE, application_id=NS_APPID)
    return ns

ns = connect_password()

# Do things with ns..

ns.logout()
``` -->

### Remarks and possible errors regarding authentication
**Note:** NetSuite requires two-factor authentication (2FA) for
all Administrator and other highly privileged roles in all NetSuite accounts.
Instead, you can login with a non-highly privileged role or use
token based authentication (TBA) with your requests. For TBA, see below.

If login fails, a NetSuiteLoginError is thrown. 

For more information about NetSuite authentication, see:
	(https://docs.oracle.com/cloud/latest/netsuitecs_gs/NSATH/NSATH.pdf)


<!-- ### Get Request
A basic example (`ns` is a reference to a `NetSuiteClient` instance):
```python
vendor = ns.get('vendor', internalId=ref.internalId)
ns.print_values(vendor)
```

### Search
To perform a search request, use `NetSuite.search`.
The SDK provides some utility functions/classes:

- `basic_stringfield_search`: A basic example (`ns` is a reference to a `NetSuiteClient` instance):
```python
records = ns.basic_stringfield_search(type_name='Vendor',
                                attribute='entityId',
                                value='Alexander Valley Vineyards',
                                operator='is')
print(records[0].internalId)
```

- `PaginatedSearch` (in utils.py):
Its usage can be seen inside the utility function `NetSuiteClient.paginated_search`

### Upsert
Basic example(`ns` is a reference to a `NetSuiteClient` instance):
```python
vendor = ns.Vendor()
vendor.externalId = 'test_vendor'
vendor.companyName = 'Another Test Inc.'
ref = ns.upsert(record=vendor)
```

### UpsertList
Basic example(`ns` is a reference to a `NetSuiteClient` instance):
```python
customer1 = ns.Customer(externalId='customer', email='test1@example.com')
customer2 = ns.Customer(externalId='another_customer', email='test2@example.com')
ns.upsertList(records=[customer1, customer2])
``` -->


## Integration Tests

To run integration tests, you will set both login and TBA credentials for an actual Netsuite account with the right permissions. 
```
# TBA credentials
export NS_ACCOUNT=xxxx
export NS_CONSUMER_KEY=xxxx
export NS_CONSUMER_SECRET=xxxx
export NS_TOKEN_KEY=xxxx
export NS_TOKEN_SECRET=xxxx

python -m pytest test/integration
```
Currently the code coverage is at 90%

To run integration tests on a newly added / modified file

```python
python -m pytest -vv test/integration/test_filename.py; 

```

## Code coverage

To get code coverage report, run this command:

```python
python -m pytest --cov=netsuitesdk

<snipped output>
Name                                                   Stmts   Miss  Cover   
----------------------------------------------------------------------------
netsuitesdk/__init__.py                                    4      0   100%
netsuitesdk/api/__init__.py                                0      0   100%
netsuitesdk/api/accounts.py                                6      0   100%
netsuitesdk/api/adv_inter_company_journal_entries.py       7      0   100%
netsuitesdk/api/base.py                                   90      9    90%   
netsuitesdk/api/classifications.py                         6      0   100%
netsuitesdk/api/currencies.py                             10      0   100%
netsuitesdk/api/custom_record_types.py                    11      0   100%
netsuitesdk/api/custom_records.py                         17      0   100%
netsuitesdk/api/customers.py                              21      0   100%
netsuitesdk/api/departments.py                             6      0   100%
netsuitesdk/api/employees.py                              34      0   100%
netsuitesdk/api/expense_categories.py                      6      0   100%
netsuitesdk/api/expense_reports.py                        58      2    97%   
netsuitesdk/api/files.py                                  23      0   100%
netsuitesdk/api/folders.py                                17      0   100%
netsuitesdk/api/journal_entries.py                        41      0   100%
netsuitesdk/api/locations.py                               6      0   100%
netsuitesdk/api/price_level.py                             6      0   100%
netsuitesdk/api/projects.py                                6      0   100%
netsuitesdk/api/subsidiaries.py                            6      0   100%
netsuitesdk/api/tax_groups.py                              6      0   100%
netsuitesdk/api/tax_items.py                               6      0   100%
netsuitesdk/api/vendor_bills.py                           55      1    98%  
netsuitesdk/api/vendor_payments.py                        46      1    98%   
netsuitesdk/api/vendors.py                                21      0   100%
netsuitesdk/connection.py                                 68      0   100%
netsuitesdk/internal/__init__.py                           0      0   100%
netsuitesdk/internal/client.py                           305     79    74%   
netsuitesdk/internal/constants.py                          4      0   100%
netsuitesdk/internal/exceptions.py                        16      3    81%   
netsuitesdk/internal/netsuite_types.py                     2      0   100%
netsuitesdk/internal/utils.py                             40      4    90%   
----------------------------------------------------------------------------
TOTAL                                                    950     99    90%

```

To get an html report, run this command:

```python
python -m pytest --cov=netsuitesdk --cov-report html:cov_html
```

We want to maintain code coverage of more than 90% for this project at all times.

## Documentation
Documentation can be found in the docs/_build/html folder (open index.html) and soon in readthedocs.
For contributors: to build the documentation (cd to /docs and) run `make buildapi`
as well as `make html`

## Contributions

We are actively accepting contributions. Please mail shwetabh.kumar@fylehq.com if you wish to collaborate on this. (Please write test cases for new additions.)

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/fylein/netsuite-sdk-py",
    "name": "netsuitesdk",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "netsuite,api,python,sdk",
    "author": "Siva Narayanan",
    "author_email": "siva@fyle.in",
    "download_url": "https://files.pythonhosted.org/packages/aa/43/bfaae8df096048747d7cad61c7a8085053162d2d8a2bf2fac799f431a6a2/netsuitesdk-2.21.0.tar.gz",
    "platform": null,
    "description": "# netsuite-sdk-py\n\nNetsuite-sdk-py is a Python SDK. It uses the SOAP client library zeep(https://python-zeep.readthedocs.io/en/master/) for accessing NetSuite resources via the NetSuite SOAP web service SuiteTalk(http://www.netsuite.com/portal/platform/developer/suitetalk.shtml), but hides the complexity from the SDK user.\n\n## Installation\n\n\t$ pip install netsuitesdk \n\n## Get Started\n\nThere are two ways to access a NetSuite account via web services: \n- Use token-based auth (TBA) (within each request). This is the mechanism supported by this SDK.\n- Use email, password, role and account id to login and start a session. This is not supported by this SDK\n\n### Token-based Auth\n\nFirst, setup TBA credentials using environment variables.\n\n```\n# TBA credentials\nexport NS_ACCOUNT=xxxx\nexport NS_CONSUMER_KEY=xxxx\nexport NS_CONSUMER_SECRET=xxxx\nexport NS_TOKEN_KEY=xxxx\nexport NS_TOKEN_SECRET=xxxx\n\n```\n\nThe following snippet shows how to use TBA to initialize the SDK.\n\n```python\nimport os\nimport itertools\nimport json\nfrom netsuitesdk import NetSuiteConnection\n\ndef connect_tba():\n    NS_ACCOUNT = os.getenv('NS_ACCOUNT')\n    NS_CONSUMER_KEY = os.getenv('NS_CONSUMER_KEY')\n    NS_CONSUMER_SECRET = os.getenv('NS_CONSUMER_SECRET')\n    NS_TOKEN_KEY = os.getenv('NS_TOKEN_KEY')\n    NS_TOKEN_SECRET = os.getenv('NS_TOKEN_SECRET')\n    nc = NetSuiteConnection(\n        account=NS_ACCOUNT,\n        consumer_key=NS_CONSUMER_KEY,\n        consumer_secret=NS_CONSUMER_SECRET,\n        token_key=NS_TOKEN_KEY,\n        token_secret=NS_TOKEN_SECRET\n    )\n    return nc\n\nnc = connect_tba()\n\n# Use get_all methods to get all objects of certain types\ncurrencies = nc.currencies.get_all()\nlocations = nc.locations.get_all()\ndepartments = nc.departments.get_all()\nclassifications = nc.classifications.get_all()\nsubsidiaries = nc.subsidiaries.get_all()\nexpense_categories = nc.expense_categories.get_all()\nemployees = nc.employees.get_all()\nall_accounts = list(itertools.islice(nc.accounts.get_all_generator(), 100))\naccounts = [a for a in all_accounts if a['acctType'] == '_expense']\nvendor_bills = list(itertools.islice(nc.vendor_bills.get_all_generator(), 10))\nvendors = list(itertools.islice(nc.vendors.get_all_generator(), 10))\nvendor_payments = nc.vendor_payments.get_all()\n\ndata = {\n  'accounts': accounts,\n  'classifications': classifications,\n  'departments': departments,\n  'locations': locations,\n  'currencies': currencies,\n  'vendors': vendors,\n  'vendor_bills': vendor_bills,\n  'subsidiaries': subsidiaries,\n  'expense_categories': expense_categories,\n  'employees': employees,\n  'vendor_payments': vendor_payments\n}\nwith open('/tmp/netsuite.json', 'w') as oj:\n\toj.write(json.dumps(data, default=str, indent=2))\n\n# There are also generator methods to iterate over potentially large lists\nfor c in nc.currencies.get_all_generator():\n    print(c)\n\n# Get a specific object\nnc.currencies.get(internalId='1')\n\n# Post operation is only supported on vendor_bills, expense_reports, journal_entries and vendor_payments currently (see tests on how to construct vendor bill, expense report and journal entry)\nvb = {...}\nnc.vendor_bills.post(vb)\n\ner = {...}\nnc.expense_reports.post(er)\n\nje = {...}\nnc.journal_entries.post(je)\n\nvp = {...}\nnc.vendor_payments.post(vp)\n\n### Upsert Files\nfile = open('receipt.pdf', 'rb').read()\n\ncreated_folder = nc.folders.post(\n    {\n        \"externalId\": 'new-folder',\n        \"name\": 'Receipts'\n    }\n)\n\nuploaded_file = nc.files.post({\n    \"externalId\": \"receipt 1\",\n    \"name\": 'receipt.pdf',\n    'content': file,\n    'fileType': '_PDF',\n    \"folder\": {\n                \"name\": None,\n                \"internalId\": 695,\n                \"externalId\": 'new-folder',\n                \"type\": \"folder\"\n            }\n    }\n)\n```\n\n<!-- ### Password-based Auth\n\nPassword-based auth is less preferred. You can set the following environment variables for convenience:\n\n```\nexport NS_EMAIL=xxxx\nexport NS_PASSWORD=xxxx\nexport NS_ROLE=xxx\nexport NS_ACCOUNT=xxxx\nexport NS_APPID=xxxx\n```\n\nHere's a snippet that shows how the client can be initialized.\n\n```python\nimport os\n\nfrom netsuitesdk import NetSuiteClient\n\ndef connect_password():\n    NS_EMAIL = os.getenv(\"NS_EMAIL\")\n    NS_PASSWORD = os.getenv(\"NS_PASSWORD\")\n    NS_ROLE = os.getenv(\"NS_ROLE\")\n    NS_ACCOUNT = os.getenv(\"NS_ACCOUNT\")\n    NS_APPID = os.getenv(\"NS_APPID\")\n\n    ns = NetSuiteClient(account=NS_ACCOUNT)\n    ns.login(email=NS_EMAIL, password=NS_PASSWORD, role=NS_ROLE, application_id=NS_APPID)\n    return ns\n\nns = connect_password()\n\n# Do things with ns..\n\nns.logout()\n``` -->\n\n### Remarks and possible errors regarding authentication\n**Note:** NetSuite requires two-factor authentication (2FA) for\nall Administrator and other highly privileged roles in all NetSuite accounts.\nInstead, you can login with a non-highly privileged role or use\ntoken based authentication (TBA) with your requests. For TBA, see below.\n\nIf login fails, a NetSuiteLoginError is thrown. \n\nFor more information about NetSuite authentication, see:\n\t(https://docs.oracle.com/cloud/latest/netsuitecs_gs/NSATH/NSATH.pdf)\n\n\n<!-- ### Get Request\nA basic example (`ns` is a reference to a `NetSuiteClient` instance):\n```python\nvendor = ns.get('vendor', internalId=ref.internalId)\nns.print_values(vendor)\n```\n\n### Search\nTo perform a search request, use `NetSuite.search`.\nThe SDK provides some utility functions/classes:\n\n- `basic_stringfield_search`: A basic example (`ns` is a reference to a `NetSuiteClient` instance):\n```python\nrecords = ns.basic_stringfield_search(type_name='Vendor',\n                                attribute='entityId',\n                                value='Alexander Valley Vineyards',\n                                operator='is')\nprint(records[0].internalId)\n```\n\n- `PaginatedSearch` (in utils.py):\nIts usage can be seen inside the utility function `NetSuiteClient.paginated_search`\n\n### Upsert\nBasic example(`ns` is a reference to a `NetSuiteClient` instance):\n```python\nvendor = ns.Vendor()\nvendor.externalId = 'test_vendor'\nvendor.companyName = 'Another Test Inc.'\nref = ns.upsert(record=vendor)\n```\n\n### UpsertList\nBasic example(`ns` is a reference to a `NetSuiteClient` instance):\n```python\ncustomer1 = ns.Customer(externalId='customer', email='test1@example.com')\ncustomer2 = ns.Customer(externalId='another_customer', email='test2@example.com')\nns.upsertList(records=[customer1, customer2])\n``` -->\n\n\n## Integration Tests\n\nTo run integration tests, you will set both login and TBA credentials for an actual Netsuite account with the right permissions. \n```\n# TBA credentials\nexport NS_ACCOUNT=xxxx\nexport NS_CONSUMER_KEY=xxxx\nexport NS_CONSUMER_SECRET=xxxx\nexport NS_TOKEN_KEY=xxxx\nexport NS_TOKEN_SECRET=xxxx\n\npython -m pytest test/integration\n```\nCurrently the code coverage is at 90%\n\nTo run integration tests on a newly added / modified file\n\n```python\npython -m pytest -vv test/integration/test_filename.py; \n\n```\n\n## Code coverage\n\nTo get code coverage report, run this command:\n\n```python\npython -m pytest --cov=netsuitesdk\n\n<snipped output>\nName                                                   Stmts   Miss  Cover   \n----------------------------------------------------------------------------\nnetsuitesdk/__init__.py                                    4      0   100%\nnetsuitesdk/api/__init__.py                                0      0   100%\nnetsuitesdk/api/accounts.py                                6      0   100%\nnetsuitesdk/api/adv_inter_company_journal_entries.py       7      0   100%\nnetsuitesdk/api/base.py                                   90      9    90%   \nnetsuitesdk/api/classifications.py                         6      0   100%\nnetsuitesdk/api/currencies.py                             10      0   100%\nnetsuitesdk/api/custom_record_types.py                    11      0   100%\nnetsuitesdk/api/custom_records.py                         17      0   100%\nnetsuitesdk/api/customers.py                              21      0   100%\nnetsuitesdk/api/departments.py                             6      0   100%\nnetsuitesdk/api/employees.py                              34      0   100%\nnetsuitesdk/api/expense_categories.py                      6      0   100%\nnetsuitesdk/api/expense_reports.py                        58      2    97%   \nnetsuitesdk/api/files.py                                  23      0   100%\nnetsuitesdk/api/folders.py                                17      0   100%\nnetsuitesdk/api/journal_entries.py                        41      0   100%\nnetsuitesdk/api/locations.py                               6      0   100%\nnetsuitesdk/api/price_level.py                             6      0   100%\nnetsuitesdk/api/projects.py                                6      0   100%\nnetsuitesdk/api/subsidiaries.py                            6      0   100%\nnetsuitesdk/api/tax_groups.py                              6      0   100%\nnetsuitesdk/api/tax_items.py                               6      0   100%\nnetsuitesdk/api/vendor_bills.py                           55      1    98%  \nnetsuitesdk/api/vendor_payments.py                        46      1    98%   \nnetsuitesdk/api/vendors.py                                21      0   100%\nnetsuitesdk/connection.py                                 68      0   100%\nnetsuitesdk/internal/__init__.py                           0      0   100%\nnetsuitesdk/internal/client.py                           305     79    74%   \nnetsuitesdk/internal/constants.py                          4      0   100%\nnetsuitesdk/internal/exceptions.py                        16      3    81%   \nnetsuitesdk/internal/netsuite_types.py                     2      0   100%\nnetsuitesdk/internal/utils.py                             40      4    90%   \n----------------------------------------------------------------------------\nTOTAL                                                    950     99    90%\n\n```\n\nTo get an html report, run this command:\n\n```python\npython -m pytest --cov=netsuitesdk --cov-report html:cov_html\n```\n\nWe want to maintain code coverage of more than 90% for this project at all times.\n\n## Documentation\nDocumentation can be found in the docs/_build/html folder (open index.html) and soon in readthedocs.\nFor contributors: to build the documentation (cd to /docs and) run `make buildapi`\nas well as `make html`\n\n## Contributions\n\nWe are actively accepting contributions. Please mail shwetabh.kumar@fylehq.com if you wish to collaborate on this. (Please write test cases for new additions.)\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Python SDK for accessing the NetSuite SOAP webservice",
    "version": "2.21.0",
    "project_urls": {
        "Homepage": "https://github.com/fylein/netsuite-sdk-py"
    },
    "split_keywords": [
        "netsuite",
        "api",
        "python",
        "sdk"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "3553eda46e00c030b5370aeb8b41374961c45ef119c7fd11acf6ef73f78aa941",
                "md5": "a62c1b265e94bc4f4050de8a0ade8f8b",
                "sha256": "437438e009d0e558ac29db8b59a8779dd393316d273682f27ad80f6943bd1557"
            },
            "downloads": -1,
            "filename": "netsuitesdk-2.21.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "a62c1b265e94bc4f4050de8a0ade8f8b",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 41994,
            "upload_time": "2023-08-29T09:45:17",
            "upload_time_iso_8601": "2023-08-29T09:45:17.925370Z",
            "url": "https://files.pythonhosted.org/packages/35/53/eda46e00c030b5370aeb8b41374961c45ef119c7fd11acf6ef73f78aa941/netsuitesdk-2.21.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "aa43bfaae8df096048747d7cad61c7a8085053162d2d8a2bf2fac799f431a6a2",
                "md5": "bb048e9a76d54fa431ca7944e5e5061a",
                "sha256": "bc0082af5bfb28e07e05e19875e5dc573b96946735fb43d4892b1c6c9a54f0d1"
            },
            "downloads": -1,
            "filename": "netsuitesdk-2.21.0.tar.gz",
            "has_sig": false,
            "md5_digest": "bb048e9a76d54fa431ca7944e5e5061a",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 29138,
            "upload_time": "2023-08-29T09:45:19",
            "upload_time_iso_8601": "2023-08-29T09:45:19.579173Z",
            "url": "https://files.pythonhosted.org/packages/aa/43/bfaae8df096048747d7cad61c7a8085053162d2d8a2bf2fac799f431a6a2/netsuitesdk-2.21.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-08-29 09:45:19",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "fylein",
    "github_project": "netsuite-sdk-py",
    "travis_ci": false,
    "coveralls": true,
    "github_actions": true,
    "requirements": [],
    "lcname": "netsuitesdk"
}
        
Elapsed time: 0.11067s