Skip to content

Commit

Permalink
Merge pull request #4 from HealthITAU/fix/pydantic2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Yoshify authored Jul 20, 2023
2 parents 468017a + 6fd78fc commit 372888b
Show file tree
Hide file tree
Showing 746 changed files with 818 additions and 4,458 deletions.
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ __pycache__/

test.py
gen.py
setup.cfg
setup.py

# C extensions
*.so
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
requests
pydantic<2
pydantic>=2
jinja2
3 changes: 3 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[metadata]
description_file=README.md
license_files=LICENSE
37 changes: 37 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from setuptools import setup
from setuptools import find_packages
import subprocess
import os

pycw_version = subprocess.run(['git', 'describe', '--tags'], stdout=subprocess.PIPE).stdout.decode('utf-8').strip()
with open(os.path.join(os.path.dirname(__file__), 'README.md')) as file:
long_description = file.read()

setup(
name='pyconnectwise',
version=pycw_version,
license='gpl-3.0',
author="Health IT",
author_email='[email protected]',
description='A full-featured Python client for the ConnectWise API\'s',
long_description=long_description,
long_description_content_type='text/markdown',
url='https://github.com/HealthITAU/pyconnectwise',
keywords=['ConnectWise', 'Manage', 'Automate', 'API', 'Python', 'Client', 'Annotated', 'Typed', 'MSP'],
install_requires=[
'requests',
'pydantic>=2',
'jinja2'
],
classifiers=[
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
'Topic :: Software Development :: Libraries :: Python Modules',
'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.10',
],
package_dir = {"":"src"},
packages = find_packages(where="src"),
python_requires = ">=3.10.1"
)
4 changes: 2 additions & 2 deletions src/pyconnectwise/endpoints/base/connectwise_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,14 +163,14 @@ def _parse_many(self, model_type: Type[T], data: list[dict[str, Any]]) -> list[T
# ideally, we'd use the model's parse method, but
# due to issues validating optional fields in the ConnectWise Manage schema
# we have to use the construct method instead until a better solution is found
return [model_type.construct(**d) for d in data]
return [model_type.model_construct(**d) for d in data]

def _parse_one(self, model_type: Type[T], data: dict[str, Any]) -> T:
# use the model's construct method to create instances from the data
# ideally, we'd use the model's parse method, but
# due to issues validating optional fields in the ConnectWise Manage schema
# we have to use the construct method instead until a better solution is found
return model_type.construct(**data)
return model_type.model_construct(**data)

def id(self: TSelf, id: int) -> TSelf:
"""
Expand Down
52 changes: 30 additions & 22 deletions src/pyconnectwise/models/base/connectwise_model.py
Original file line number Diff line number Diff line change
@@ -1,49 +1,57 @@
from __future__ import annotations
from pydantic import BaseModel
from pydantic import BaseModel, ConfigDict
from pyconnectwise.utils.naming import to_camel_case
from typing import Optional, Type, Any, TypeVar

Model = TypeVar('Model', bound='BaseModel')

class ConnectWiseModel(BaseModel):

class Config:
alias_generator = to_camel_case
allow_population_by_field_name = True
use_enum_values = True
model_config = ConfigDict(alias_generator=to_camel_case, populate_by_name=True, use_enum_values=True, protected_namespaces=())

@classmethod
def construct(cls: Type['ConnectWiseModel'], **values: Any) -> 'ConnectWiseModel':
def model_construct(cls: Type['ConnectWiseModel'], **values: Any) -> 'ConnectWiseModel':
"""
Overriding Pydantics construct method to allow for nested models.
"""
m = cls.__new__(cls)
fields_values: dict[str, Any] = {}
defaults: dict[str, Any] = {}

def handle_nested_model(field, value):
if issubclass(field.type_, BaseModel):
if issubclass(type(field.annotation), BaseModel):
if isinstance(value, list):
return [field.type_.construct(**v) for v in value]
return [field.annotation.model_construct(**v) for v in value]
else:
return field.type_.construct(**value)
return field.annotation.model_construct(**value)
else:
return value

for name, field in cls.__fields__.items():
if field.alt_alias and field.alias in values:
for name, field in cls.model_fields.items():
if field.alias and field.alias in values:
fields_values[name] = handle_nested_model(field, values[field.alias])
elif name in values:
fields_values[name] = handle_nested_model(field, values[name])
elif not field.required:
fields_values[name] = field.get_default()
else:
value = values.get(name)
if value is None:
fields_values[name] = None
continue
fields_values[name] = handle_nested_model(field, value)
elif not field.is_required():
defaults[name] = field.get_default(call_default_factory=True)
fields_values.update(defaults)

_extra: dict[str, Any] | None = None
if cls.model_config.get('extra') == 'allow':
_extra = {}
for k, v in values.items():
_extra[k] = v
else:
fields_values.update(values)
object.__setattr__(m, '__dict__', fields_values)
object.__setattr__(m, '__fields_set__', set(values.keys()))
m._init_private_attributes()
object.__setattr__(m, '__pydantic_fields_set__', fields_values.keys())
if not cls.__pydantic_root_model__:
object.__setattr__(m, '__pydantic_extra__', _extra)

if cls.__pydantic_post_init__:
m.model_post_init(None)
elif not cls.__pydantic_root_model__:
# Note: if there are any private attributes, cls.__pydantic_post_init__ would exist
# Since it doesn't, that means that `__pydantic_private__` should be set to None
object.__setattr__(m, '__pydantic_private__', None)

return m
7 changes: 1 addition & 6 deletions src/pyconnectwise/models/manage/AccountingBatchModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,4 @@ class AccountingBatchModel(ConnectWiseModel):
export_expenses_flag: bool
export_products_flag: bool
closed_flag: bool
_info: dict[str, str]

class Config:
alias_generator = to_camel_case
allow_population_by_field_name = True
use_enum_values = True
_info: dict[str, str]
7 changes: 1 addition & 6 deletions src/pyconnectwise/models/manage/AccountingPackageModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,4 @@
class AccountingPackageModel(ConnectWiseModel):
id: int
identifier: str
name: str

class Config:
alias_generator = to_camel_case
allow_population_by_field_name = True
use_enum_values = True
name: str
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,4 @@ class AccountingPackageReferenceModel(ConnectWiseModel):
id: int
identifier: Identifier
name: str
_info: dict[str, str]

class Config:
alias_generator = to_camel_case
allow_population_by_field_name = True
use_enum_values = True
_info: dict[str, str]
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,4 @@ class AccountingPackageSetupModel(ConnectWiseModel):
send_component_amount_flag: bool
send_uom_flag: bool
include_cogs_entries_flag: bool
include_cogs_drop_ship_flag: bool

class Config:
alias_generator = to_camel_case
allow_population_by_field_name = True
use_enum_values = True
include_cogs_drop_ship_flag: bool
7 changes: 1 addition & 6 deletions src/pyconnectwise/models/manage/ActivityModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,4 @@ class ActivityModel(ConnectWiseModel):
mobile_guid: str
currency: CurrencyReferenceModel
_info: dict[str, str]
custom_fields: list[CustomFieldValueModel]

class Config:
alias_generator = to_camel_case
allow_population_by_field_name = True
use_enum_values = True
custom_fields: list[CustomFieldValueModel]
7 changes: 1 addition & 6 deletions src/pyconnectwise/models/manage/ActivityReferenceModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,4 @@
class ActivityReferenceModel(ConnectWiseModel):
id: int
name: str
_info: dict[str, str]

class Config:
alias_generator = to_camel_case
allow_population_by_field_name = True
use_enum_values = True
_info: dict[str, str]
7 changes: 1 addition & 6 deletions src/pyconnectwise/models/manage/ActivityStatusInfoModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,4 @@ class ActivityStatusInfoModel(ConnectWiseModel):
inactive_flag: bool
closed_flag: bool
default_flag: bool
_info: dict[str, str]

class Config:
alias_generator = to_camel_case
allow_population_by_field_name = True
use_enum_values = True
_info: dict[str, str]
7 changes: 1 addition & 6 deletions src/pyconnectwise/models/manage/ActivityStatusModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,4 @@ class ActivityStatusModel(ConnectWiseModel):
inactive_flag: bool
spawn_followup_flag: bool
closed_flag: bool
_info: dict[str, str]

class Config:
alias_generator = to_camel_case
allow_population_by_field_name = True
use_enum_values = True
_info: dict[str, str]
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,4 @@
class ActivityStatusReferenceModel(ConnectWiseModel):
id: int
name: str
_info: dict[str, str]

class Config:
alias_generator = to_camel_case
allow_population_by_field_name = True
use_enum_values = True
_info: dict[str, str]
7 changes: 1 addition & 6 deletions src/pyconnectwise/models/manage/ActivityStopwatchModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,4 @@ class ActivityStopwatchModel(ConnectWiseModel):
status: Status
total_pause_time: int
work_role: WorkRoleReferenceModel
work_type: WorkTypeReferenceModel

class Config:
alias_generator = to_camel_case
allow_population_by_field_name = True
use_enum_values = True
work_type: WorkTypeReferenceModel
7 changes: 1 addition & 6 deletions src/pyconnectwise/models/manage/ActivityTypeModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,4 @@ class ActivityTypeModel(ConnectWiseModel):
email_flag: bool
memo_flag: bool
history_flag: bool
_info: dict[str, str]

class Config:
alias_generator = to_camel_case
allow_population_by_field_name = True
use_enum_values = True
_info: dict[str, str]
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,4 @@
class ActivityTypeReferenceModel(ConnectWiseModel):
id: int
name: str
_info: dict[str, str]

class Config:
alias_generator = to_camel_case
allow_population_by_field_name = True
use_enum_values = True
_info: dict[str, str]
7 changes: 1 addition & 6 deletions src/pyconnectwise/models/manage/AdditionModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,4 @@ class AdditionModel(ConnectWiseModel):
agreement_status: AgreementStatus
invoice_grouping: InvoiceGroupingReferenceModel
_info: dict[str, str]
custom_fields: list[CustomFieldValueModel]

class Config:
alias_generator = to_camel_case
allow_population_by_field_name = True
use_enum_values = True
custom_fields: list[CustomFieldValueModel]
7 changes: 1 addition & 6 deletions src/pyconnectwise/models/manage/AddressFormatInfoModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,4 @@ class AddressFormatInfoModel(ConnectWiseModel):
id: int
name: str
default_flag: bool
_info: dict[str, str]

class Config:
alias_generator = to_camel_case
allow_population_by_field_name = True
use_enum_values = True
_info: dict[str, str]
7 changes: 1 addition & 6 deletions src/pyconnectwise/models/manage/AddressFormatModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,4 @@ class AddressFormatModel(ConnectWiseModel):
country_ids: list[int]
add_all_countries: bool
remove_all_countries: bool
_info: dict[str, str]

class Config:
alias_generator = to_camel_case
allow_population_by_field_name = True
use_enum_values = True
_info: dict[str, str]
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,4 @@
class AddressFormatReferenceModel(ConnectWiseModel):
id: int
name: str
_info: dict[str, str]

class Config:
alias_generator = to_camel_case
allow_population_by_field_name = True
use_enum_values = True
_info: dict[str, str]
7 changes: 1 addition & 6 deletions src/pyconnectwise/models/manage/AdjustmentDetailModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,4 @@ class AdjustmentDetailModel(ConnectWiseModel):
quantity_adjusted: int
serial_number: str
adjustment: AdjustmentReferenceModel
_info: dict[str, str]

class Config:
alias_generator = to_camel_case
allow_population_by_field_name = True
use_enum_values = True
_info: dict[str, str]
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,4 @@
class AdjustmentDetailReferenceModel(ConnectWiseModel):
id: int
name: str
_info: dict[str, str]

class Config:
alias_generator = to_camel_case
allow_population_by_field_name = True
use_enum_values = True
_info: dict[str, str]
Loading

0 comments on commit 372888b

Please sign in to comment.