Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve typing #2 #747

Merged
merged 2 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 0 additions & 5 deletions .flake8

This file was deleted.

15 changes: 0 additions & 15 deletions .pylintrc

This file was deleted.

2 changes: 1 addition & 1 deletion office365/directory/applications/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def remove_certificate(self, thumbprint):
Remove a certificate from an application.
:param str thumbprint: The unique identifier for the password.
"""
raise NotImplemented("")
raise NotImplementedError("")

def add_password(self, display_name):
"""Adds a strong password to an application.
Expand Down
27 changes: 20 additions & 7 deletions office365/entity.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
from typing import TYPE_CHECKING, Optional, TypeVar

from typing_extensions import Self

from office365.runtime.client_object import ClientObject
from office365.runtime.paths.entity import EntityPath
from office365.runtime.paths.resource_path import ResourcePath
from office365.runtime.queries.delete_entity import DeleteEntityQuery
from office365.runtime.queries.update_entity import UpdateEntityQuery

if TYPE_CHECKING:
from office365.graph_client import GraphClient


T = TypeVar("T")


class Entity(ClientObject):
class Entity(ClientObject[T]):
"""Base entity"""

def update(self):
# type: () -> Self
"""Updates the entity."""
qry = UpdateEntityQuery(self)
self.context.add_query(qry)
return self

def delete_object(self):
# type: () -> Self
"""Deletes the entity."""
qry = DeleteEntityQuery(self)
self.context.add_query(qry)
Expand All @@ -23,30 +35,31 @@ def delete_object(self):

@property
def context(self):
"""
:rtype: office365.graph_client.GraphClient
"""
# type: () -> GraphClient
"""Return the Graph Client context."""
return self._context

@property
def entity_type_name(self):
# type: () -> str
if self._entity_type_name is None:
name = type(self).__name__
self._entity_type_name = "microsoft.graph." + name[0].lower() + name[1:]
return self._entity_type_name

@property
def id(self):
"""The unique identifier of the entity.
:rtype: str or None
"""
# type: () -> Optional[str]
"""The unique identifier of the entity."""
return self.properties.get("id", None)

@property
def property_ref_name(self):
# type: () -> str
return "id"

def set_property(self, name, value, persist_changes=True):
# type: (str, T, bool) -> Self
super(Entity, self).set_property(name, value, persist_changes)
if name == self.property_ref_name:
if self._resource_path is None:
Expand Down
6 changes: 4 additions & 2 deletions office365/entity_collection.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from typing import TypeVar
from typing import TYPE_CHECKING, TypeVar, Any

from office365.graph_client import GraphClient
from office365.runtime.client_object_collection import ClientObjectCollection
from office365.runtime.compat import is_string_type
from office365.runtime.paths.item import ItemPath
from office365.runtime.paths.resource_path import ResourcePath
from office365.runtime.queries.create_entity import CreateEntityQuery

if TYPE_CHECKING:
from office365.graph_client import GraphClient

T = TypeVar("T")


Expand Down
3 changes: 2 additions & 1 deletion office365/graph_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
from office365.runtime.auth.token_response import TokenResponse
from office365.runtime.client_runtime_context import ClientRuntimeContext
from office365.runtime.http.http_method import HttpMethod
from office365.runtime.http.request_options import RequestOptions
from office365.runtime.odata.request import ODataRequest
from office365.runtime.odata.v4.batch_request import ODataV4BatchRequest
from office365.runtime.odata.v4.json_format import V4JsonFormat
Expand All @@ -68,7 +69,7 @@ class GraphClient(ClientRuntimeContext):
"""Graph Service client"""

def __init__(self, acquire_token_callback):
# type: (Callable[None, dict]) -> None
# type: (Callable[..., dict]) -> None
"""
:param () -> dict acquire_token_callback: Acquire token function
"""
Expand Down
5 changes: 3 additions & 2 deletions office365/onedrive/driveitems/driveItem.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class DriveItem(BaseItem):
OneDrive and SharePoint are returned as driveItem resources"""

def get_by_path(self, url_path):
# type: (str) -> DriveItem
"""
Retrieve DriveItem by server relative path

Expand Down Expand Up @@ -236,8 +237,8 @@ def upload_file(self, path_or_file):

def get_content(self, format_name=None):
"""
Download the contents of the primary stream (file) of a DriveItem. O
nly driveItems with the file property can be downloaded.
Download the contents of the primary stream (file) of a DriveItem.
Only driveItems with the file property can be downloaded.

:type format_name: str or None
"""
Expand Down
65 changes: 30 additions & 35 deletions office365/runtime/client_object.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@
from __future__ import annotations

import datetime
from typing import TypeVar
from typing import TYPE_CHECKING, Generic, Optional, TypeVar

from typing_extensions import Self

from office365.runtime.client_runtime_context import ClientRuntimeContext
from office365.runtime.client_value import ClientValue
from office365.runtime.odata.json_format import ODataJsonFormat
from office365.runtime.odata.query_options import QueryOptions
from office365.runtime.odata.type import ODataType
from office365.runtime.odata.v3.json_light_format import JsonLightFormat
from office365.runtime.paths.resource_path import ResourcePath

if TYPE_CHECKING:
from office365.runtime.client_object_collection import ClientObjectCollection

T = TypeVar("T", bound="ClientObject")

T = TypeVar("T")
P_T = TypeVar("P_T")
"""Property Type."""


class ClientObject(object):
class ClientObject(Generic[T]):
def __init__(self, context, resource_path=None, parent_collection=None):
"""
Base client object which define named properties and relationships of an entity

:type parent_collection: office365.runtime.client_object_collection.ClientObjectCollection or None
:type resource_path: office365.runtime.paths.resource_path.ResourcePath or None
:type context: office365.runtime.client_runtime_context.ClientRuntimeContext
"""
# type: (ClientRuntimeContext, Optional[ResourcePath], Optional[ClientObjectCollection]) -> None
"""Base client object which define named properties and relationships of an entity."""
self._properties = {}
self._ser_property_names = []
self._query_options = QueryOptions()
Expand All @@ -29,9 +35,8 @@ def __init__(self, context, resource_path=None, parent_collection=None):
self._resource_path = resource_path

def clear(self):
"""
Resets client object's state
"""
# type: () -> Self
"""Resets client object's state."""
self._properties = {
k: v
for k, v in self._properties.items()
Expand All @@ -42,11 +47,8 @@ def clear(self):
return self

def execute_query(self):
"""
Submit request(s) to the server

:type self: T
"""
# type: () -> Self
"""Submit request(s) to the server."""
self.context.execute_query()
return self

Expand Down Expand Up @@ -79,14 +81,13 @@ def after_execute(self, action, *args, **kwargs):
return self

def get(self):
"""
Retrieves a client object from the server
:type self: T
"""
# type: () -> Self
"""Retrieves a client object from the server."""
self.context.load(self)
return self

def is_property_available(self, name):
# type: (str) -> bool
"""Returns a Boolean value that indicates whether the specified property has been retrieved or set.

:param str name: A property name
Expand All @@ -96,16 +97,13 @@ def is_property_available(self, name):
return False

def expand(self, names):
"""
Specifies the related resources to be included in line with retrieved resources

:type self: T
:type names: list[str]
"""
# type: (list[str]) -> Self
"""Specifies the related resources to be included in line with retrieved resources."""
self.query_options.expand = names
return self

def select(self, names):
# type: (list[str]) -> Self
"""
Allows to request a limited set of properties

Expand All @@ -122,6 +120,7 @@ def remove_from_parent_collection(self):
return self

def _persist_changes(self, name):
# type: (str) -> Self
"""
Marks a property as a serializable
:param str name: A property name
Expand All @@ -131,19 +130,15 @@ def _persist_changes(self, name):
return self

def get_property(self, name, default_value=None):
"""
Gets property value

:type name: str
:type default_value: P_T
:rtype: P_T
"""
# type: (str, P_T) -> P_T
"""Gets property value."""
if default_value is None:
normalized_name = name[0].lower() + name[1:]
default_value = getattr(self, normalized_name, None)
return self._properties.get(name, default_value)

def set_property(self, name, value, persist_changes=True):
# type: (str, P_T, bool) -> Self
"""Sets property value

:param str name: Property name
Expand Down
2 changes: 1 addition & 1 deletion office365/runtime/client_object_collection.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Generic, Iterator, Optional, TypeVar
from typing import Generic, Iterator, List, Optional, TypeVar

from typing_extensions import Self

Expand Down
5 changes: 3 additions & 2 deletions office365/runtime/client_runtime_context.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import abc
from time import sleep
from typing import TypeVar
from typing import TYPE_CHECKING

from office365.runtime.client_request_exception import ClientRequestException
from office365.runtime.client_result import ClientResult
Expand All @@ -9,7 +9,8 @@
from office365.runtime.queries.client_query import ClientQuery
from office365.runtime.queries.read_entity import ReadEntityQuery

T = TypeVar("T", bound="ClientObject")
if TYPE_CHECKING:
from office365.runtime.client_object import T


class ClientRuntimeContext(object):
Expand Down
2 changes: 1 addition & 1 deletion office365/sharepoint/excel/excel_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ def pending_request(self):
pass

def get_workbook(self, list_name, file_name):
raise NotImplemented("get_workbook")
raise NotImplementedError("get_workbook")
24 changes: 23 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,28 @@ description-file = README.md
profile=black

[flake8]
# These error codes can be fixed, but since it touches many files the
# suggestion is to do it one code at a time to reduce review effort
# F401 - imported but unused
extend-ignore = E203, E501, W503, F401
# F841 - local variable defined but never used
extend-ignore = E203, E501, W503, F401, F841
max-line-length = 88
exclude =
generator/metadata
office365/runtime/compat.py

[pylint]
max-line-length=120
# all codes: http://pylint-messages.wikidot.com/all-codes
disable=
C0103,
C0303,
C0111,
C0415, # import-outside-toplevel
C0112, # empty-docstring
C0209, # consider-using f-string
C0114, # missing-module-docstring
R1725, # super-with-arguments

[pylint.FORMAT]
max-line-length = 121