Skip to content

Commit 5a032b9

Browse files
committed
Refactor WHMCS API client models to use Pydantic for data validation and serialization
- Updated WHMCSBaseResponse, WHMCSErrorResponse, and WHMCSSuccessResponse classes to inherit from Pydantic's BaseModel. - Implemented field validation using Pydantic's field_validator for result attributes. - Added methods for JSON serialization and deserialization in response models. - Removed old Swagger-generated code and replaced it with Pydantic's functionality for better type safety and validation. - Enhanced REST client to support SOCKS proxies and improved request handling. - Cleaned up and optimized the request method in RESTClientObject for better readability and maintainability. - Added type hints and improved documentation throughout the codebase.
1 parent d74c134 commit 5a032b9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+4542
-5966
lines changed

.github/workflows/python.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# NOTE: This file is auto generated by OpenAPI Generator.
2+
# URL: https://openapi-generator.tech
3+
#
4+
# ref: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
5+
6+
name: whmcs_client Python package
7+
8+
on: [push, pull_request]
9+
10+
jobs:
11+
build:
12+
13+
runs-on: ubuntu-latest
14+
strategy:
15+
matrix:
16+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
17+
18+
steps:
19+
- uses: actions/checkout@v4
20+
- name: Set up Python ${{ matrix.python-version }}
21+
uses: actions/setup-python@v4
22+
with:
23+
python-version: ${{ matrix.python-version }}
24+
- name: Install dependencies
25+
run: |
26+
python -m pip install --upgrade pip
27+
pip install -r requirements.txt
28+
pip install -r test-requirements.txt
29+
- name: Test with pytest
30+
run: |
31+
pytest --cov=whmcs_client

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ coverage.xml
4545
*,cover
4646
.hypothesis/
4747
venv/
48+
.venv/
4849
.python-version
50+
.pytest_cache
4951

5052
# Translations
5153
*.mo

.gitlab-ci.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# NOTE: This file is auto generated by OpenAPI Generator.
2+
# URL: https://openapi-generator.tech
3+
#
4+
# ref: https://docs.gitlab.com/ee/ci/README.html
5+
# ref: https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Python.gitlab-ci.yml
6+
7+
stages:
8+
- test
9+
10+
.pytest:
11+
stage: test
12+
script:
13+
- pip install -r requirements.txt
14+
- pip install -r test-requirements.txt
15+
- pytest --cov=whmcs_client
16+
17+
pytest-3.9:
18+
extends: .pytest
19+
image: python:3.9-alpine
20+
pytest-3.10:
21+
extends: .pytest
22+
image: python:3.10-alpine
23+
pytest-3.11:
24+
extends: .pytest
25+
image: python:3.11-alpine
26+
pytest-3.12:
27+
extends: .pytest
28+
image: python:3.12-alpine
29+
pytest-3.13:
30+
extends: .pytest
31+
image: python:3.13-alpine
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
# Swagger Codegen Ignore
2-
# Generated by swagger-codegen https://github.com/swagger-api/swagger-codegen
1+
# OpenAPI Generator Ignore
2+
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
33

44
# Use this file to prevent files from being overwritten by the generator.
55
# The patterns follow closely to .gitignore or .dockerignore.
66

77
# As an example, the C# client generator defines ApiClient.cs.
8-
# You can make changes and tell Swagger Codgen to ignore just this file by uncommenting the following line:
8+
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
99
#ApiClient.cs
1010

1111
# You can match any string of characters against a directory, file or extension with a single asterisk (*):

.openapi-generator/FILES

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
.github/workflows/python.yml
2+
.gitignore
3+
.gitlab-ci.yml
4+
.travis.yml
5+
README.md
6+
docs/AddClientResponse.md
7+
docs/AddOrderResponse.md
8+
docs/DefaultApi.md
9+
docs/UpdateClientResponse.md
10+
docs/WHMCSBaseResponse.md
11+
docs/WHMCSErrorResponse.md
12+
docs/WHMCSSuccessResponse.md
13+
git_push.sh
14+
pyproject.toml
15+
requirements.txt
16+
setup.cfg
17+
setup.py
18+
test-requirements.txt
19+
test/__init__.py
20+
tox.ini
21+
whmcs_client/__init__.py
22+
whmcs_client/api/__init__.py
23+
whmcs_client/api/default_api.py
24+
whmcs_client/api_client.py
25+
whmcs_client/api_response.py
26+
whmcs_client/configuration.py
27+
whmcs_client/exceptions.py
28+
whmcs_client/models/__init__.py
29+
whmcs_client/models/add_client_response.py
30+
whmcs_client/models/add_order_response.py
31+
whmcs_client/models/update_client_response.py
32+
whmcs_client/models/whmcs_base_response.py
33+
whmcs_client/models/whmcs_error_response.py
34+
whmcs_client/models/whmcs_success_response.py
35+
whmcs_client/py.typed
36+
whmcs_client/rest.py

.openapi-generator/VERSION

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
7.13.0

.swagger-codegen/VERSION

Lines changed: 0 additions & 1 deletion
This file was deleted.

.travis.yml

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
# ref: https://docs.travis-ci.com/user/languages/python
22
language: python
33
python:
4-
- "3.2"
5-
- "3.3"
6-
- "3.4"
7-
- "3.5"
8-
#- "3.5-dev" # 3.5 development branch
9-
#- "nightly" # points to the latest development branch e.g. 3.6-dev
4+
- "3.9"
5+
- "3.10"
6+
- "3.11"
7+
- "3.12"
8+
- "3.13"
9+
# uncomment the following if needed
10+
#- "3.13-dev" # 3.13 development branch
11+
#- "nightly" # nightly build
1012
# command to install dependencies
11-
install: "pip install -r requirements.txt"
13+
install:
14+
- "pip install -r requirements.txt"
15+
- "pip install -r test-requirements.txt"
1216
# command to run tests
13-
script: nosetests
17+
script: pytest --cov=whmcs_client

README.md

Lines changed: 136 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,29 @@
11
# whmcs-api-client
2-
Python client for the WHMCS API. WHMCS (Web Host Manager Complete Solution) provides a single API endpoint that handles multiple operations through different 'action' parameters. This client supports various WHMCS operations for managing clients, orders, and other resources. Authentication is handled through username/password or API credentials. All requests are sent as form-encoded data to the /api.php endpoint.
2+
Python client for the WHMCS API.
33

4-
This Python package is automatically generated by the [Swagger Codegen](https://github.com/swagger-api/swagger-codegen) project:
4+
WHMCS (Web Host Manager Complete Solution) provides a single API endpoint that handles
5+
multiple operations through different 'action' parameters. This client supports various
6+
WHMCS operations for managing clients, orders, and other resources.
7+
8+
Authentication is handled through username/password or API credentials.
9+
All requests are sent as form-encoded data to the /api.php endpoint.
10+
11+
12+
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
513

614
- API version: 1.0.0
7-
- Package version: 1.0.2
8-
- Build package: io.swagger.codegen.v3.generators.python.PythonClientCodegen
15+
- Package version: 1.0.3
16+
- Generator version: 7.13.0
17+
- Build package: org.openapitools.codegen.languages.PythonClientCodegen
918

1019
## Requirements.
1120

12-
Python 2.7 and 3.4+
21+
Python 3.9+
1322

1423
## Installation & Usage
1524
### pip install
1625

17-
If the python package is hosted on Github, you can install directly from Github
26+
If the python package is hosted on a repository, you can install directly using:
1827

1928
```sh
2029
pip install git+https://github.com/GIT_USER_ID/GIT_REPO_ID.git
@@ -23,7 +32,7 @@ pip install git+https://github.com/GIT_USER_ID/GIT_REPO_ID.git
2332

2433
Then import the package:
2534
```python
26-
import whmcs_client
35+
import whmcs_client
2736
```
2837

2938
### Setuptools
@@ -40,26 +49,130 @@ Then import the package:
4049
import whmcs_client
4150
```
4251

52+
### Tests
53+
54+
Execute `pytest` to run the tests.
55+
4356
## Getting Started
4457

4558
Please follow the [installation procedure](#installation--usage) and then run the following:
4659

4760
```python
48-
from __future__ import print_function
49-
import time
61+
5062
import whmcs_client
5163
from whmcs_client.rest import ApiException
5264
from pprint import pprint
5365

54-
# create an instance of the API class
55-
api_instance = whmcs_client.DefaultApi(whmcs_client.ApiClient(configuration))
66+
# Defining the host is optional and defaults to https://your-whmcs-instance.com/includes
67+
# See configuration.py for a list of all supported configuration parameters.
68+
configuration = whmcs_client.Configuration(
69+
host = "https://your-whmcs-instance.com/includes"
70+
)
71+
72+
73+
74+
# Enter a context with an instance of the API client
75+
with whmcs_client.ApiClient(configuration) as api_client:
76+
# Create an instance of the API class
77+
api_instance = whmcs_client.DefaultApi(api_client)
78+
username = 'username_example' # str | Admin username/API identifier (optional)
79+
password = 'password_example' # str | Admin password/API secret (optional)
80+
accesskey = 'accesskey_example' # str | Optional API access key (optional)
81+
responsetype = json # str | Response format (optional) (default to json)
82+
action = 'action_example' # str | Must be 'AddOrder' (optional)
83+
owner_user_id = 56 # int | The ID of the user that should own the client (optional)
84+
firstname = 'firstname_example' # str | First name of the client (optional)
85+
lastname = 'lastname_example' # str | Last name of the client (optional)
86+
companyname = 'companyname_example' # str | Company name (optional)
87+
email = 'email_example' # str | Email address of the client (optional)
88+
address1 = 'address1_example' # str | Address line 1 (optional)
89+
address2 = 'address2_example' # str | Address line 2 (optional)
90+
city = 'city_example' # str | City (optional)
91+
state = 'state_example' # str | State (optional)
92+
postcode = 'postcode_example' # str | Postal code (optional)
93+
country = 'country_example' # str | 2 character ISO country code (optional)
94+
phonenumber = 'phonenumber_example' # str | Phone number (optional)
95+
tax_id = 'tax_id_example' # str | Client's tax ID (optional)
96+
password2 = 'password2_example' # str | Password for the new user account (optional)
97+
securityqid = 56 # int | Security question ID (optional)
98+
securityqans = 'securityqans_example' # str | Security question answer (optional)
99+
currency = 56 # int | Currency ID (optional)
100+
groupid = 56 # int | Client group ID (optional)
101+
customfields = ['customfields_example'] # List[str] | Array of base64 encoded serialized array of product custom field values (optional)
102+
language = 'language_example' # str | Default language setting (optional)
103+
clientip = 'clientip_example' # str | The IP address to associate with the order (optional)
104+
notes = 'notes_example' # str | Admin only notes (optional)
105+
marketingoptin = True # bool | Opt-in to marketing emails (optional)
106+
noemail = True # bool | Set to true to suppress the Order Confirmation email being sent (optional)
107+
skipvalidation = True # bool | Ignore required field validation (optional)
108+
clientid = 56 # int | The ID of the client to add the order for (optional)
109+
clientemail = 'clientemail_example' # str | The email address of the client to update (optional)
110+
status = 'status_example' # str | The status (e.g., Active) (optional)
111+
paymentmethod = 'paymentmethod_example' # str | The payment method for the order in the system format (e.g., paypal, mailin) (optional)
112+
email_preferences_general = True # bool | Receive general emails (optional)
113+
email_preferences_product = True # bool | Receive product emails (optional)
114+
email_preferences_domain = True # bool | Receive domain emails (optional)
115+
email_preferences_invoice = True # bool | Receive invoice emails (optional)
116+
email_preferences_support = True # bool | Receive support emails (optional)
117+
email_preferences_affiliate = True # bool | Receive affiliate emails (optional)
118+
clearcreditcard = True # bool | Clear stored credit card details (optional)
119+
latefeeoveride = True # bool | Override Late Fees setting (optional)
120+
overideduenotices = True # bool | Override Overdue Notices setting (optional)
121+
taxexempt = True # bool | Exempt from tax collections (optional)
122+
separateinvoices = True # bool | Group items into one invoice (optional)
123+
disableautocc = True # bool | Enable/disable automatic credit card processing (optional)
124+
overrideautoclose = True # bool | Enable/disable automatic account closure (optional)
125+
pid = [56] # List[int] | Array of product IDs to add to the order (optional)
126+
qty = [56] # List[int] | Array of product quantities (optional)
127+
domain = ['domain_example'] # List[str] | Array of domain names associated with the products/domains (optional)
128+
billingcycle = ['billingcycle_example'] # List[str] | Array of billing cycles for the products (optional)
129+
domaintype = ['domaintype_example'] # List[str] | For domain registrations, array of register or transfer values (optional)
130+
regperiod = [56] # List[int] | For domain registrations, the registration periods for the domains (optional)
131+
idnlanguage = ['idnlanguage_example'] # List[str] | For IDN domain registrations, the language codes for the domains (optional)
132+
eppcode = ['eppcode_example'] # List[str] | For domain transfers, the EPP codes for the domains being transferred (optional)
133+
nameserver1 = 'nameserver1_example' # str | The first nameserver to apply to all domains in the order (optional)
134+
nameserver2 = 'nameserver2_example' # str | The second nameserver to apply to all domains in the order (optional)
135+
nameserver3 = 'nameserver3_example' # str | The third nameserver to apply to all domains in the order (optional)
136+
nameserver4 = 'nameserver4_example' # str | The fourth nameserver to apply to all domains in the order (optional)
137+
nameserver5 = 'nameserver5_example' # str | The fifth nameserver to apply to all domains in the order (optional)
138+
configoptions = ['configoptions_example'] # List[str] | Array of base64 encoded serialized array of product configurable options values (optional)
139+
priceoverride = [3.4] # List[float] | Override the price of the product being ordered (optional)
140+
promocode = 'promocode_example' # str | The promotion code to apply to the order (optional)
141+
promooverride = True # bool | Should the promotion apply to the order even without matching promotional products (optional)
142+
affid = 56 # int | The affiliate ID to associate with the order (optional)
143+
noinvoice = True # bool | Set to true to suppress the invoice generating for the whole order (optional)
144+
noinvoiceemail = True # bool | Set to true to suppress the Invoice Created email being sent for the order (optional)
145+
addons = ['addons_example'] # List[str] | Array of comma separated lists of addons to create on order with the products (optional)
146+
addonsqty = ['addonsqty_example'] # List[str] | Array of comma-separated lists of quantities for addons associated with products (optional)
147+
hostname = ['hostname_example'] # List[str] | Array of hostnames for VPS/Dedicated Server orders (optional)
148+
ns1prefix = ['ns1prefix_example'] # List[str] | Array of first nameserver prefixes for VPS/Dedicated servers (e.g., ns1 in ns1.hostname.com) (optional)
149+
ns2prefix = ['ns2prefix_example'] # List[str] | Array of second nameserver prefixes for VPS/Dedicated servers (e.g., ns2 in ns2.hostname.com) (optional)
150+
rootpw = ['rootpw_example'] # List[str] | Array of desired root passwords for VPS/Dedicated servers (optional)
151+
contactid = 56 # int | The ID of the contact, associated with the client, that should apply to all domains in the order (optional)
152+
dnsmanagement = [True] # List[bool] | Add DNS Management to the Domain Order (optional)
153+
domainfields = ['domainfields_example'] # List[str] | Array of base64 encoded serialized array of TLD Specific Field Values (optional)
154+
emailforwarding = [True] # List[bool] | Add Email Forwarding to the Domain Order (optional)
155+
idprotection = [True] # List[bool] | Add ID Protection to the Domain Order (optional)
156+
domainpriceoverride = [3.4] # List[float] | Override the price of the registration price on the domain being ordered (optional)
157+
domainrenewoverride = [3.4] # List[float] | Override the price of the renewal price on the domain being ordered (optional)
158+
domainrenewals = None # Dict[str, int] | A name -> value object of domainName -> renewalPeriod renewals to add an order for (optional)
159+
addonid = 56 # int | The Addon ID for an Addon Only Order (optional)
160+
addonidqty = 56 # int | The quantity of addons in an addon-only order (optional)
161+
serviceid = 56 # int | The service ID for the addon only order (optional)
162+
addonids = [56] # List[int] | Array of addon IDs for an Addon Only Order (optional)
163+
addonidsqty = [56] # List[int] | Array of quantities for an addon-only order (optional)
164+
serviceids = [56] # List[int] | Array of service IDs to associate the addons for an Addon Only order (optional)
165+
servicerenewals = [56] # List[int] | Array of service IDs to be on-demand renewed (optional)
166+
addonrenewals = [56] # List[int] | Array of service addon IDs to be on-demand renewed (optional)
167+
168+
try:
169+
# Execute WHMCS API action
170+
api_response = api_instance.api_post(username=username, password=password, accesskey=accesskey, responsetype=responsetype, action=action, owner_user_id=owner_user_id, firstname=firstname, lastname=lastname, companyname=companyname, email=email, address1=address1, address2=address2, city=city, state=state, postcode=postcode, country=country, phonenumber=phonenumber, tax_id=tax_id, password2=password2, securityqid=securityqid, securityqans=securityqans, currency=currency, groupid=groupid, customfields=customfields, language=language, clientip=clientip, notes=notes, marketingoptin=marketingoptin, noemail=noemail, skipvalidation=skipvalidation, clientid=clientid, clientemail=clientemail, status=status, paymentmethod=paymentmethod, email_preferences_general=email_preferences_general, email_preferences_product=email_preferences_product, email_preferences_domain=email_preferences_domain, email_preferences_invoice=email_preferences_invoice, email_preferences_support=email_preferences_support, email_preferences_affiliate=email_preferences_affiliate, clearcreditcard=clearcreditcard, latefeeoveride=latefeeoveride, overideduenotices=overideduenotices, taxexempt=taxexempt, separateinvoices=separateinvoices, disableautocc=disableautocc, overrideautoclose=overrideautoclose, pid=pid, qty=qty, domain=domain, billingcycle=billingcycle, domaintype=domaintype, regperiod=regperiod, idnlanguage=idnlanguage, eppcode=eppcode, nameserver1=nameserver1, nameserver2=nameserver2, nameserver3=nameserver3, nameserver4=nameserver4, nameserver5=nameserver5, configoptions=configoptions, priceoverride=priceoverride, promocode=promocode, promooverride=promooverride, affid=affid, noinvoice=noinvoice, noinvoiceemail=noinvoiceemail, addons=addons, addonsqty=addonsqty, hostname=hostname, ns1prefix=ns1prefix, ns2prefix=ns2prefix, rootpw=rootpw, contactid=contactid, dnsmanagement=dnsmanagement, domainfields=domainfields, emailforwarding=emailforwarding, idprotection=idprotection, domainpriceoverride=domainpriceoverride, domainrenewoverride=domainrenewoverride, domainrenewals=domainrenewals, addonid=addonid, addonidqty=addonidqty, serviceid=serviceid, addonids=addonids, addonidsqty=addonidsqty, serviceids=serviceids, servicerenewals=servicerenewals, addonrenewals=addonrenewals)
171+
print("The response of DefaultApi->api_post:\n")
172+
pprint(api_response)
173+
except ApiException as e:
174+
print("Exception when calling DefaultApi->api_post: %s\n" % e)
56175

57-
try:
58-
# Execute WHMCS API action
59-
api_response = api_instance.api_post()
60-
pprint(api_response)
61-
except ApiException as e:
62-
print("Exception when calling DefaultApi->api_post: %s\n" % e)
63176
```
64177

65178
## Documentation for API Endpoints
@@ -70,25 +183,25 @@ Class | Method | HTTP request | Description
70183
------------ | ------------- | ------------- | -------------
71184
*DefaultApi* | [**api_post**](docs/DefaultApi.md#api_post) | **POST** /api.php | Execute WHMCS API action
72185

186+
73187
## Documentation For Models
74188

75-
- [AddClientRequest](docs/AddClientRequest.md)
76189
- [AddClientResponse](docs/AddClientResponse.md)
77-
- [AddOrderRequest](docs/AddOrderRequest.md)
78190
- [AddOrderResponse](docs/AddOrderResponse.md)
79-
- [RequestBody](docs/RequestBody.md)
80-
- [UpdateClientRequest](docs/UpdateClientRequest.md)
81191
- [UpdateClientResponse](docs/UpdateClientResponse.md)
82-
- [WHMCSBaseRequest](docs/WHMCSBaseRequest.md)
83192
- [WHMCSBaseResponse](docs/WHMCSBaseResponse.md)
84193
- [WHMCSErrorResponse](docs/WHMCSErrorResponse.md)
85194
- [WHMCSSuccessResponse](docs/WHMCSSuccessResponse.md)
86195

196+
197+
<a id="documentation-for-authorization"></a>
87198
## Documentation For Authorization
88199

89-
All endpoints do not require authorization.
200+
Endpoints do not require authorization.
90201

91202

92203
## Author
93204

94205

206+
207+

config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"packageName": "whmcs_client",
33
"projectName": "whmcs-api-client",
4-
"packageVersion": "1.0.2",
4+
"packageVersion": "1.0.3",
55
"packageUrl": "https://github.com/truehostcloud/whmcs-python-client",
66
"packageCompany": "Truehost",
77
"packageAuthor": "William Mwai",

0 commit comments

Comments
 (0)