From e74669f977736e09138bdfe26f8952f58817a750 Mon Sep 17 00:00:00 2001 From: Matti Lamppu Date: Sun, 22 Aug 2021 21:57:52 +0300 Subject: [PATCH] Add source code links to documentation. --- README.md | 311 +++++++++++++++++++++++++++--------- dynamics/query_functions.py | 114 ++++++------- setup.cfg | 2 +- 3 files changed, 291 insertions(+), 136 deletions(-) diff --git a/README.md b/README.md index a229c27..6dc4853 100644 --- a/README.md +++ b/README.md @@ -149,7 +149,7 @@ client.DELETE() from dynamics import DynamicsClient ``` -#### *DynamicsClient(...)* +#### *[DynamicsClient(...)](dynamics/client.py#L129)* - api_url: str - Url in form: 'https://[Organization URI]/api/data/v{api_version}' - token_url: str - Url in form: 'https://[Dynamics Token URI]/path/to/token' @@ -163,7 +163,7 @@ created in Dynamics, and granting it an appropriate security role. --- -#### *DynamicsClient.from_environment()* +#### *[DynamicsClient.from_environment()](dynamics/client.py#L181)* Create a Dynamics client from environment variables: @@ -175,7 +175,7 @@ Create a Dynamics client from environment variables: --- -#### *DynamicsClient.request_counter: int → int* +#### *[DynamicsClient.request_counter](dynamics/client.py#L115): int → int* How many request have been made by the client so far. @@ -189,7 +189,7 @@ client = DynamicsClient(...) --- -#### *client.GET(...) → List[Dict[str, Any]]* +#### *[client.GET(...)](dynamics/client.py#L298) → List[Dict[str, Any]]* - not_found_ok: bool = False - No entities found should not raise NotFound error, but return empty list instead. @@ -197,7 +197,8 @@ client = DynamicsClient(...) Make a GET request to the Dataverse API with currently added query options. -**Error Simplification Available**: This and the other HTTP-method -functions are decorated with a decorator, +[**Error Simplification Available**](dynamics/client.py#L84): +This and the other HTTP-method -functions are decorated with a decorator, that can take some extra options: `simplify_errors` (If set `True`, will simplify all errors occurring during the excecution of the function to just a single DynamicsException with a default error message) and `raise_separately` (A list exception types to exclude from the simplification, @@ -206,50 +207,42 @@ hide implementation details recieved in errors from frontend users. --- -#### *client.POST(...) → Dict[str, Any]* +#### *[client.POST(...)](dynamics/client.py#L362) → Dict[str, Any]* - data: Dict[str, Any] - POST data. Create new row in a table or execute an API action or function. Must have 'table' query option set. -**Error Simplification Available**: See client.GET() +[**Error Simplification Available**](dynamics/client.py#L84): See client.GET() --- -#### *client.PATCH(...) → Dict[str, Any]* +#### *[client.PATCH(...)](dynamics/client.py#L387) → Dict[str, Any]* - data: Dict[str, Any] - PATCH data. Update row in a table. Must have 'table' and 'row_id' query option set. -**Error Simplification Available**: See client.GET() +[**Error Simplification Available**](dynamics/client.py#L84): See client.GET() --- -#### *client.DELETE() → None* +#### *[client.DELETE()](dynamics/client.py#L413) → None* Delete row in a table. Must have 'table' and 'row_id' query option set. -**Error Simplification Available**: See client.GET() +[**Error Simplification Available**](dynamics/client.py#L84): See client.GET() --- -#### *client.fetch_schema(...) → Optional[str]* - -- to_file: bool = False - Save to a file instead of returning as string. - -Fetch XML schema of the available table, actions, and relational aspects of the data. - ---- - -#### *client.current_query() → str* +#### *[client.current_query()](dynamics/client.py#L202) → str* Current compiled query string. --- -#### *client.headers → Dict[str, str]* +#### *[client.headers](dynamics/client.py#L242) → Dict[str, str]* Note: Read only. To set headers, use `client[name] = value`. Similarly, you can get headers with `client[name]`. @@ -258,13 +251,13 @@ Currently set request headers. Doesn't include per method default headers. --- -#### *client.reset_query() → None* +#### *[client.reset_query()](dynamics/client.py#L246) → None* Resets all client options and headers. --- -#### *client.set_default_headers(...) → None* +#### *[client.set_default_headers(...)](dynamics/client.py#L264) → None* - method: Literal["get", "post", "patch", "delete"] @@ -273,7 +266,7 @@ Does not override user added headers. ___ -#### *client.actions: [Actions](dynamics/api_actions.py)* +#### *[client.actions](dynamics/client.py#L152): [Actions](dynamics/api_actions.py)* Injected instance of predefined Dynamics actions. Calling methods under this property execute the actions without needing to use the POST, PATCH, or DELETE methods. It is recommended to read the @@ -282,7 +275,7 @@ and how to [Use Web API Actions](https://docs.microsoft.com/en-us/powerapps/deve ___ -#### *client.functions: [Functions](dynamics/api_functions.py)* +#### *[client.functions](dynamics/client.py#L154): [Functions](dynamics/api_functions.py)* Injected instance of predefined Dynamics functions. Calling methods under this property run the functions without needing to use the GET method. It is recommended to read the @@ -291,20 +284,20 @@ and how to [Use Web API Functions](https://docs.microsoft.com/en-us/powerapps/de --- -#### *client.table: str → str* +#### *[client.table](dynamics/client.py#L433): str → str* Set the table to search in. --- -#### *client.action: str → str* +#### *[client.action](dynamics/client.py#L442): str → str* Set the Dynamics Web API action or function to use. Most of the time you don't need to set this, since you can use the `.actions` and `.functions` attributes to make these queries. --- -#### *client.row_id: str → str* +#### *[client.row_id](dynamics/client.py#L467): str → str* Search only from the table row with this id. If the table has an alternate key defined, you can use @@ -313,7 +306,7 @@ Alternate keys are not enabled by default in Dynamics, so those might not work a --- -#### *client.add_ref_to_property: str → str* +#### *[client.add_ref_to_property](dynamics/client.py#L481): str → str* Add reference for this navigation property. This indicates, that POST data will contain the API url to a matching row id @@ -326,7 +319,7 @@ for new rows can be done on create with this in POST data: --- -#### *client.pre_expand: str → str* +#### *[client.pre_expand](dynamics/client.py#L498): str → str* Expand/navigate to some linked table in this table before taking any query options into account. @@ -335,7 +328,7 @@ if all you are looking for is under this table anyway. --- -#### *client.show_annotations: bool → bool* +#### *[client.show_annotations](dynamics/client.py#L511): bool → bool* Show annotations for returned data, e.g. enum values, GUID names, etc by setting `Prefer: odata.include-annotations="*"` header. @@ -343,7 +336,7 @@ Helpful for development and debugging. --- -#### *client.select(...) → List[str]* +#### *[client.select(...)](dynamics/client.py#L526) → List[str]* - items: List[str] - Columns to select. @@ -351,7 +344,7 @@ Set `$select` statement. Limits the properties returned from the current table. --- -#### *client.expand(...) → Dict[str, Optional[ExpandType]]* +#### *[client.expand(...)](dynamics/client.py#L542) → Dict[str, Optional[ExpandType]]* - items: Dict[str, Optional[ExpandType]] - What linked tables (a.k.a. naviagation properties) to expand and @@ -385,7 +378,7 @@ expand statements, so long as the total is 10. --- -#### *client.filter(...) → Union[Set[str], List[str]]* +#### *[client.filter(...)](dynamics/client.py#L603) → Union[Set[str], List[str]]* - items: Union[Set[str], List[str]] - If a list-object, 'and' the items. If a set-object, 'or' the items. @@ -396,7 +389,7 @@ You can input the filters as strings, or use the included `ftr` object to constr --- -#### *client.apply(...) → str* +#### *[client.apply(...)](dynamics/client.py#L658) → str* - statement: str - aggregate, groupby, or filter apply-string. @@ -407,7 +400,7 @@ You can input the apply-statement as a string, or use the included `apl`-object --- -#### *client.top(...) → int* +#### *[client.top(...)](dynamics/client.py#L686) → int* - number: int - Maximum number of results to return. @@ -419,7 +412,7 @@ Also, using `$top` will override `Prefer: odata.maxpagesize=...` header preferen --- -#### *client.orderby(...) → Dict[str, Literal["asc", "desc"]]* +#### *[client.orderby(...)](dynamics/client.py#L704) → Dict[str, Literal["asc", "desc"]]* - items: Dict[str, Literal["asc", "desc"]] - Key indicates the column to order, and value indicates ascending (asc) or descending (desc) order respectively. @@ -428,7 +421,7 @@ Set `$orderby` statement. Specifies the order in which items are returned. --- -#### *client.count(...) → bool* +#### *[client.count(...)](dynamics/client.py#L729) → bool* - value: bool - If True, include the count (otherwise not included by default). @@ -439,7 +432,7 @@ Note: You should not use `client.count(...)` and `client.top(...)` in the same q --- -#### *client.pagesize: int → int* +#### *[client.pagesize](dynamics/client.py#L748): int → int* Specify the number of tables to return in a page. By default, this is set to 5000, which is the maximum. @@ -456,17 +449,17 @@ If [Django REST framework](https://www.django-rest-framework.org/) is installed, exceptions subclass from rest_framework.exceptions.APIException, otherwise a similar class is created and used instead. -* DynamicsException - Dynamics Web API call failed -* ParseError - Malformed request -* AuthenticationFailed - Incorrect authentication credentials -* PermissionDenied - You do not have permission to perform this action -* NotFound - Not found -* MethodNotAllowed - Method x not allowed -* DuplicateRecordError - Trying to save a duplicate record -* PayloadTooLarge - Request length is too large -* APILimitsExceeded - Dynamics Web API limits were exceeded -* OperationNotImplemented - Requested operation isn't implemented -* WebAPIUnavailable - Web API service isn't available +* [DynamicsException](dynamics/exceptions.py#L43) - Dynamics Web API call failed +* [ParseError](dynamics/exceptions.py#L52) - Malformed request +* [AuthenticationFailed](dynamics/exceptions.py#L58) - Incorrect authentication credentials +* [PermissionDenied](dynamics/exceptions.py#L64) - You do not have permission to perform this action +* [NotFound](dynamics/exceptions.py#L70) - Not found +* [MethodNotAllowed](dynamics/exceptions.py#L76) - Method x not allowed +* [DuplicateRecordError](dynamics/exceptions.py#L87) - Trying to save a duplicate record +* [PayloadTooLarge](dynamics/exceptions.py#L94) - Request length is too large +* [APILimitsExceeded](dynamics/exceptions.py#L100) - Dynamics Web API limits were exceeded +* [OperationNotImplemented](dynamics/exceptions.py#L120) - Requested operation isn't implemented +* [WebAPIUnavailable](dynamics/exceptions.py#L126) - Web API service isn't available --- @@ -482,12 +475,12 @@ and how to [Query data using the Web API](https://docs.microsoft.com/en-us/power ### Comparison operations: -#### *ftr.eq(...) → str* -#### *ftr.ne(...) → str* -#### *ftr.gt(...) → str* -#### *ftr.ge(...) → str* -#### *ftr.lt(...) → str* -#### *ftr.le(...) → str* +#### *[ftr.eq(...)](dynamics/query_functions.py#L171) → str* +#### *[ftr.ne(...)](dynamics/query_functions.py#L183) → str* +#### *[ftr.gt(...)](dynamics/query_functions.py#L195) → str* +#### *[ftr.ge(...)](dynamics/query_functions.py#L207) → str* +#### *[ftr.lt(...)](dynamics/query_functions.py#L219) → str* +#### *[ftr.le(...)](dynamics/query_functions.py#L231) → str* - column: str - Column to apply the operation to. - value: Union[str, int, float, bool, None] - Value to compare against. - lambda_indicator: str = None - If this operation is evaluated inside a lambda operation, @@ -496,20 +489,20 @@ and how to [Query data using the Web API](https://docs.microsoft.com/en-us/power ### Logical operations: -#### *ftr.and_(...) → str* -#### *ftr.or_(...) → str* +#### *[ftr.and_(...)](dynamics/query_functions.py#L245) → str* +#### *[ftr.or_(...)](dynamics/query_functions.py#L254) → str* - **args*: str - Other filter operation strings to and/or together. - ***kwargs*: If has `group=True` - Group the operation inside parentheses. -#### *ftr.not_(...) → str* +#### *[ftr.not_(...)](dynamics/query_functions.py#L263) → str* - operation: str - Invert this operation. Only works on standard operators! - group : bool = False - Group the operation inside parentheses. ### Standard query functions: -#### *ftr.contains(...) → str* -#### *ftr.endswith(...) → str* -#### *ftr.startswith(...) → str* +#### *[ftr.contains(...)](dynamics/query_functions.py#L270) → str* +#### *[ftr.endswith(...)](dynamics/query_functions.py#L282) → str* +#### *[ftr.startswith(...)](dynamics/query_functions.py#L294) → str* - column: str - Column to apply the operation to. - value: Union[str, int, float, bool, None] - Value to compare against. - lambda_indicator: str = None - If this operation is evaluated inside a lambda operation, @@ -518,8 +511,8 @@ and how to [Query data using the Web API](https://docs.microsoft.com/en-us/power ### Lambda operations: -#### *ftr.any_(...) → str* -#### *ftr.all_(...) → str* +#### *[ftr.any_(...)](dynamics/query_functions.py#L308) → str* +#### *[ftr.all_(...)](query_functions.py#L330) → str* - collection: str - Name of the collection-valued navigation property for some table, for the members of which the given operation is evaluated. - indicator: str - Item indicator to use inside the statement, typically a single letter. @@ -527,12 +520,174 @@ and how to [Query data using the Web API](https://docs.microsoft.com/en-us/power - operation: str = None - Operation(s) evaluated inside this operation. - lambda_indicator: str = None - If this operation is evaluated inside a lambda operation, provide the lambda operations item indicator here. -- group: bool = False - Group the operation inside parentheses.' +- group: bool = False - Group the operation inside parentheses. ### Special query functions: -`ftr`-object contains a number of other special query functions. Have a look at the -list of functions in the [source code](dynamics/query_functions.py). +#### *[ftr.in_(...)](dynamics/query_functions.py#L353) → str* +#### *[ftr.not_in(...)](dynamics/query_functions.py#L358) → str* +- column: str - Column to check. +- values: List[Union[str, int, float, bool, None]] - Values to evaluate against. +- lambda_indicator: str = None - If this operation is evaluated inside a lambda operation, + provide the lambda operations item indicator here. +- group: bool = False - Group the operation inside parentheses. + +Evaluate whether the value in the given column exists/doesn't exist in a list of values. + +#### *[ftr.between(...)](dynamics/query_functions.py#L363) → str* +#### *[ftr.not_between(...)](dynamics/query_functions.py#L370) → str* +- column: str - Column to check. +- values: Tuple[Union[str, int, float], Union[str, int, float]] - Values that define the range. +- lambda_indicator: str = None - If this operation is evaluated inside a lambda operation, + provide the lambda operations item indicator here. +- group: bool = False - Group the operation inside parentheses. + +Evaluate whether the value in the given column is/is not between two values. + +#### *[ftr.contain_values(...)](dynamics/query_functions.py#L377) → str* +#### *[ftr.not_contain_values(...)](dynamics/query_functions.py#L382) → str* +- column: str - Column to check. +- values: List[Union[str, int, float, bool, None]] - Values that the column may contain. +- lambda_indicator: str = None - If this operation is evaluated inside a lambda operation, + provide the lambda operations item indicator here. +- group: bool = False - Group the operation inside parentheses. + +Evaluate whether the value in the given column contains/doesn't contain the listed values. + +#### *[ftr.above(...)](dynamics/query_functions.py#L391) → str* +#### *[ftr.above_or_equal(...)](dynamics/query_functions.py#L396) → str* +#### *[ftr.under(...)](dynamics/query_functions.py#L401) → str* +#### *[ftr.under_or_equal(...)](dynamics/query_functions.py#L406) → str* +#### *[ftr.not_under(...)](dynamics/query_functions.py#L411) → str* +- column: str - Column to check. +- ref: Union[str, int, float, bool, None] - Referenced +- lambda_indicator: str = None - If this operation is evaluated inside a lambda operation, + provide the lambda operations item indicator here. +- group: bool = False - Group the operation inside parentheses. + +Evaluates whether the value in column is +above/above or equal/under/under or equal/not under ref in the hierarchy. + +#### *[ftr.today(...)](dynamics/query_functions.py#L418) → str* +#### *[ftr.tomorrow(...)](dynamics/query_functions.py#L418) → str* +#### *[ftr.yesterday(...)](dynamics/query_functions.py#L418) → str* +- column: str - Column to check. +- lambda_indicator: str = None - If this operation is evaluated inside a lambda operation, + provide the lambda operations item indicator here. +- group: bool = False - Group the operation inside parentheses. + +Evaluates whether the value in the given column equals today's/tomorrow's/yesterday’s date. + +#### *[ftr.on(...)](dynamics/query_functions.py#L435) → str* +#### *[ftr.on_or_after(...)](dynamics/query_functions.py#L440) → str* +#### *[ftr.on_or_before(...)](dynamics/query_functions.py#L445) → str* +- column: str - Column to check. +- date: str - ISO date string (format: YYYY-mm-ddTHH:MM:SSZ) to evaluate against. +- lambda_indicator: str = None - If this operation is evaluated inside a lambda operation, + provide the lambda operations item indicator here. +- group: bool = False - Group the operation inside parentheses. + +Evaluates whether the date in the given column is on/on or after/on or before the specified date. + +#### *[ftr.this_month(...)](dynamics/query_functions.py#L522) → str* +#### *[ftr.this_week(...)](dynamics/query_functions.py#L527) → str* +#### *[ftr.this_year(...)](dynamics/query_functions.py#L532) → str* +#### *[ftr.last_month(...)](dynamics/query_functions.py#L554) → str* +#### *[ftr.last_week(...)](dynamics/query_functions.py#L559) → str* +#### *[ftr.last_year(...)](dynamics/query_functions.py#L564) → str* +#### *[ftr.next_month(...)](dynamics/query_functions.py#L581) → str* +#### *[ftr.next_week(...)](dynamics/query_functions.py#L586) → str* +#### *[ftr.next_year(...)](dynamics/query_functions.py#L591) → str* +- column: str - Column to check. +- lambda_indicator: str = None - If this operation is evaluated inside a lambda operation, + provide the lambda operations item indicator here. +- group: bool = False - Group the operation inside parentheses. + +Evaluates whether the date in the given column is within the current/last/next month/week/year. + +#### *[ftr.last_7_days(...)](dynamics/query_functions.py#L539) → str* +- column: str - Column to check. +- lambda_indicator: str = None - If this operation is evaluated inside a lambda operation, + provide the lambda operations item indicator here. +- group: bool = False - Group the operation inside parentheses. + +Evaluates whether the date in the given column in the last 7 days. + +#### *[ftr.last_x_days(...)](dynamics/query_functions.py#L598) → str* +#### *[ftr.last_x_hours(...)](dynamics/query_functions.py#L613) → str* +#### *[ftr.last_x_months(...)](dynamics/query_functions.py#L618) → str* +#### *[ftr.last_x_weeks(...)](dynamics/query_functions.py#L623) → str* +#### *[ftr.last_x_years(...)](dynamics/query_functions.py#L628) → str* +#### *[ftr.next_x_days(...)](dynamics/query_functions.py#L635) → str* +#### *[ftr.next_x_hours(...)](dynamics/query_functions.py#L650) → str* +#### *[ftr.next_x_months(...)](dynamics/query_functions.py#L655) → str* +#### *[ftr.next_x_weeks(...)](dynamics/query_functions.py#L660) → str* +#### *[ftr.next_x_years(...)](dynamics/query_functions.py#L665) → str* +#### *[ftr.older_than_x_days(...)](dynamics/query_functions.py#L672) → str* +#### *[ftr.older_than_x_hours(...)](dynamics/query_functions.py#L677) → str* +#### *[ftr.older_than_x_minutes(...)](dynamics/query_functions.py#L682) → str* +#### *[ftr.older_than_x_months(...)](dynamics/query_functions.py#L687) → str* +#### *[ftr.older_than_x_weeks(...)](dynamics/query_functions.py#L692) → str* +#### *[ftr.older_than_x_years(...)](dynamics/query_functions.py#L697) → str* +- column: str - Column to check. +- x: int - How many of the specified unit to check for. +- lambda_indicator: str = None - If this operation is evaluated inside a lambda operation, + provide the lambda operations item indicator here. +- group: bool = False - Group the operation inside parentheses. + +Evaluates whether the date in the given column in the last x/in the next x/is older than x specified units. + +#### *[ftr.in_fiscal_period(...)](dynamics/query_functions.py#L452) → str* +#### *[ftr.in_fiscal_period_and_year(...)](dynamics/query_functions.py#L457) → str* +#### *[ftr.in_fiscal_year(...)](dynamics/query_functions.py#L473) → str* +#### *[ftr.in_or_after_fiscal_period_and_year(...)](dynamics/query_functions.py#L478) → str* +#### *[ftr.in_or_before_fiscal_period_and_year(...)](dynamics/query_functions.py#L494) → str* +#### *[ftr.this_fiscal_period(...)](dynamics/query_functions.py#L512) → str* +#### *[ftr.this_fiscal_year(...)](dynamics/query_functions.py#L517) → str* +#### *[ftr.last_fiscal_period(...)](dynamics/query_functions.py#L544) → str* +#### *[ftr.last_fiscal_year(...)](dynamics/query_functions.py#L549) → str* +#### *[ftr.next_fiscal_period(...)](dynamics/query_functions.py#L571) → str* +#### *[ftr.next_fiscal_year(...)](dynamics/query_functions.py#L576) → str* +#### *[ftr.last_x_fiscal_periods(...)](dynamics/query_functions.py#L603) → str* +#### *[ftr.last_x_fiscal_years(...)](dynamics/query_functions.py#L608) → str* +#### *[ftr.next_x_fiscal_periods(...)](dynamics/query_functions.py#L640) → str* +#### *[ftr.next_x_fiscal_periods(...)](dynamics/query_functions.py#L645) → str* +- column: str - Column to check. +- Needed based on function: + - period: int - Fiscal period to evaluate against. + - year: int - Fiscal year to evaluate against. + - x: int - How many of the specified unit to check for. +- lambda_indicator: str = None - If this operation is evaluated inside a lambda operation, + provide the lambda operations item indicator here. +- group: bool = False - Group the operation inside parentheses. + +Evaluates value in the given column against specified fiscal period(s) and/or year(s). + +#### *[ftr.equal_business_id(...)](dynamics/query_functions.py#L704) → str* +#### *[ftr.not_business_id(...)](dynamics/query_functions.py#L709) → str* +- column: str - Column to check. +- lambda_indicator: str = None - If this operation is evaluated inside a lambda operation, + provide the lambda operations item indicator here. +- group: bool = False - Group the operation inside parentheses. + +Evaluates whether the value in the given column is equal/not equal to the specified business ID. + +#### *[ftr.equal_user_id(...)](dynamics/query_functions.py#L716) → str* +#### *[ftr.not_user_id(...)](dynamics/query_functions.py#L721) → str* +- column: str - Column to check. +- lambda_indicator: str = None - If this operation is evaluated inside a lambda operation, + provide the lambda operations item indicator here. +- group: bool = False - Group the operation inside parentheses. + +Evaluates whether the value in the given column is equal/not equal to the ID of the user. + +#### *[ftr.equal_user_language(...)](dynamics/query_functions.py#L728) → str* +#### *[ftr.equal_user_or_user_hierarchy(...)](dynamics/query_functions.py#L733) → str* +#### *[ftr.equal_user_or_user_hierarchy_and_teams(...)](dynamics/query_functions.py#L738) → str* +#### *[ftr.equal_user_or_user_teams(...)](dynamics/query_functions.py#L744) → str* +#### *[ftr.equal_user_teams(...)](dynamics/query_functions.py#L749) → str* + +Evaluates whether the value in the given column is equal to the what's asked. --- @@ -546,20 +701,20 @@ Object that holds `$apply` string construction convenience methods. It is recomm [Aggregate and grouping results](https://docs.microsoft.com/en-us/powerapps/developer/data-platform/webapi/query-data-web-api#aggregate-and-grouping-results) and the [FetchXML aggregation documentation](https://docs.microsoft.com/en-us/powerapps/developer/data-platform/use-fetchxml-aggregation) -#### *apl.groupby(...) → str* +#### *[apl.groupby(...)](dynamics/apply_functions.py#L21) → str* - columns: List[str] - Columns to group by. - aggregate: str = None - Aggregate grouped results by this `apl.aggregate`-function. Group results by columns, optionally aggregate. -#### *apl.aggregate(...) → str* +#### *[apl.aggregate(...)](dynamics/apply_functions.py#L31) → str* - col_: str - Column to aggregate over. - with_: Literal["average", "sum", "min", "max", "count"] - How to aggregate the columns. - as_: str - Aggregate result alias. Aggregate column with some aggregation function, and alias the result under some name. -#### *apl.filter(...) → str* +#### *[apl.filter(...)](dynamics/apply_functions.py#L41) → str* - by: filter_type - Filter results by this filter string before applying grouping. Use the `ftr`-object to construct this. - group_by_columns: List[str] - Columns to group by. @@ -579,27 +734,27 @@ The most common case is missing data in the Dynamics database, in which case Non Normalizer can be used to convert this to, e.g., an empty string, or any other default value. They can also be used to specify numeric data as float or int. -#### *as_int(...) → int* +#### *[as_int(...)](dynamics/normalizers.py#L21) → int* - value: Any - Value to normalize. - default: int = 0 - Default to return if casting value to int fails. -#### *as_float(...) → float* +#### *[as_float(...)](dynamics/normalizers.py#L30) → float* - value: Any - Value to normalize. - default: int = 0.0 - Default to return if casting value to float fails. -#### *as_str(...) → str* +#### *[as_str(...)](dynamics/normalizers.py#L39) → str* - value: Any - Value to normalize. - default: int = "" - Default to return if casting value to string fails. -#### *as_bool(...) → bool* +#### *[as_bool(...)](dynamics/normalizers.py#L48) → bool* - value: Any - Value to normalize. - default: int = False - Default to return if casting value to bool fails. -#### *str_as_datetime(...) → datetime* +#### *[str_as_datetime(...)](dynamics/normalizers.py#L55) → datetime* - value: str - Value to normalize. - default: Any = None - Default to return if casting value to datetime fails. @@ -616,7 +771,7 @@ from dynamics.utils import * This library includes a number of helpful utilities. -#### *to_dynamics_date_format(...) → str* +#### *[to_dynamics_date_format(...)](dynamics/utils.py#L29) → str* - date: datetime - Datetime object to convert. - from_timezone: str = None - Name of the timezone, from 'pytz.all_timezones', the date is in. @@ -625,7 +780,7 @@ Convert a datetime-object to Dynamics compatible ISO formatted date string. --- -#### *from_dynamics_date_format(...) → datetime* +#### *[from_dynamics_date_format(...)](dynamics/utils.py#L47) → datetime* - date: str - ISO datestring from Dynamics database, in form: YYYY-mm-ddTHH:MM:SSZ. - to_timezone: str = "UCT" - Name of the timezone, from 'pytz.all_timezones', to convert the date to. @@ -636,7 +791,7 @@ Convert a ISO datestring from Dynamics database to a datetime-object. --- -#### *cache* +#### *[cache](dynamics/utils.py#L129) → [SQLiteCache:](dynamics/utils.py#L91)* Instance of a SQLite based cache that the client uses to store the auth token so that it can be reused between client instances. Django's cache is prefered to this, if it is installed. diff --git a/dynamics/query_functions.py b/dynamics/query_functions.py index 2c30670..d0abf7d 100644 --- a/dynamics/query_functions.py +++ b/dynamics/query_functions.py @@ -9,7 +9,7 @@ """ from uuid import UUID -from typing import Union, Optional +from typing import Union, Optional, List, Tuple __all__ = [ @@ -50,7 +50,7 @@ def _group(result: str, group: bool) -> str: return f"({result})" if group else result @staticmethod - def _listify(values: list[field_type]) -> str: + def _listify(values: List[field_type]) -> str: return f"""[{','.join([f"{FTR._type(value, quotes=True)}" for value in values])}]""" @staticmethod @@ -152,7 +152,7 @@ def _special_two_values( @staticmethod def _special_many_values( name: str, - values: list[field_type], + values: List[field_type], operator: str, lambda_indicator: Optional[str], group: bool, @@ -350,37 +350,37 @@ def all_( # Special query functions - value checks @staticmethod - def in_(column: str, values: list[field_type], lambda_indicator: str = None, group: bool = False) -> str: + def in_(column: str, values: List[field_type], lambda_indicator: str = None, group: bool = False) -> str: """Evaluate whether the value in the given column exists in a list of values.""" return FTR._special_many_values(column, values, "In", lambda_indicator, group) @staticmethod - def not_in(column: str, values: list[field_type], lambda_indicator: str = None, group: bool = False) -> str: - """Evaluate whether the value in the given column doesn't exists in a list of values.""" + def not_in(column: str, values: List[field_type], lambda_indicator: str = None, group: bool = False) -> str: + """Evaluate whether the value in the given column doesn't exist in a list of values.""" return FTR._special_many_values(column, values, "NotIn", lambda_indicator, group) @staticmethod def between( - column: str, values: tuple[comp_type, comp_type], lambda_indicator: str = None, group: bool = False + column: str, values: Tuple[comp_type, comp_type], lambda_indicator: str = None, group: bool = False ) -> str: """Evaluate whether the value in the given column is between two values.""" return FTR._special_many_values(column, list(values), "Between", lambda_indicator, group) @staticmethod def not_between( - column: str, values: tuple[comp_type, comp_type], lambda_indicator: str = None, group: bool = False + column: str, values: Tuple[comp_type, comp_type], lambda_indicator: str = None, group: bool = False ) -> str: """Evaluate whether the value in the given column is not between two values.""" return FTR._special_many_values(column, list(values), "NotBetween", lambda_indicator, group) @staticmethod - def contain_values(column: str, values: list[field_type], lambda_indicator: str = None, group: bool = False) -> str: + def contain_values(column: str, values: List[field_type], lambda_indicator: str = None, group: bool = False) -> str: """Evaluate whether the value in the given column contains the listed values.""" return FTR._special_many_values(column, values, "ContainValues", lambda_indicator, group) @staticmethod def not_contain_values( - column: str, values: list[field_type], lambda_indicator: str = None, group: bool = False + column: str, values: List[field_type], lambda_indicator: str = None, group: bool = False ) -> str: """Evaluate whether the value in the given column doesn't contain the listed values.""" return FTR._special_many_values(column, values, "DoesNotContainValues", lambda_indicator, group) @@ -432,32 +432,32 @@ def yesterday(column: str, lambda_indicator: str = None, group: bool = False) -> # Special query functions - dates - on @staticmethod - def on(column: str, date: comp_type, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is on the specified date.""" + def on(column: str, date: str, lambda_indicator: str = None, group: bool = False) -> str: + """Evaluates whether the date in the given column is on the specified date.""" return FTR._special_single_value(column, date, "On", lambda_indicator, group) @staticmethod - def on_or_after(column: str, date: comp_type, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is on or after the specified date.""" + def on_or_after(column: str, date: str, lambda_indicator: str = None, group: bool = False) -> str: + """Evaluates whether the date in the given column is on or after the specified date.""" return FTR._special_single_value(column, date, "OnOrAfter", lambda_indicator, group) @staticmethod - def on_or_before(column: str, date: comp_type, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is on or before the specified date.""" + def on_or_before(column: str, date: str, lambda_indicator: str = None, group: bool = False) -> str: + """Evaluates whether the date in the given column is on or before the specified date.""" return FTR._special_single_value(column, date, "OnOrBefore", lambda_indicator, group) # Special query functions - dates - in @staticmethod def in_fiscal_period(column: str, period: int, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the specified fiscal period.""" + """Evaluates whether the date in the given column is within the specified fiscal period.""" return FTR._special_single_value(column, period, "InFiscalPeriod", lambda_indicator, group, ref_quotes=False) @staticmethod def in_fiscal_period_and_year( column: str, period: int, year: int, lambda_indicator: str = None, group: bool = False ) -> str: - """Evaluates whether the value in the given column is within the specified fiscal period and year.""" + """Evaluates whether the date in the given column is within the specified fiscal period and year.""" return FTR._special_two_values( column, period, @@ -471,14 +471,14 @@ def in_fiscal_period_and_year( @staticmethod def in_fiscal_year(column: str, year: int, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the specified fiscal year.""" + """Evaluates whether the date in the given column is within the specified fiscal year.""" return FTR._special_single_value(column, year, "InFiscalYear", lambda_indicator, group, ref_quotes=False) @staticmethod def in_or_after_fiscal_period_and_year( column: str, period: int, year: int, lambda_indicator: str = None, group: bool = False ) -> str: - """Evaluates whether the value in the given column is within or after the specified fiscal period and year.""" + """Evaluates whether the date in the given column is within or after the specified fiscal period and year.""" return FTR._special_two_values( column, period, @@ -494,7 +494,7 @@ def in_or_after_fiscal_period_and_year( def in_or_before_fiscal_period_and_year( column: str, period: int, year: int, lambda_indicator: str = None, group: bool = False ) -> str: - """Evaluates whether the value in the given column is within, or before the specified fiscal period and year.""" + """Evaluates whether the date in the given column is within, or before the specified fiscal period and year.""" return FTR._special_two_values( column, period, @@ -510,192 +510,192 @@ def in_or_before_fiscal_period_and_year( @staticmethod def this_fiscal_period(column: str, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the current fiscal period.""" + """Evaluates whether the date in the given column is within the current fiscal period.""" return FTR._special_name_only(column, "ThisFiscalPeriod", lambda_indicator, group) @staticmethod def this_fiscal_year(column: str, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the current fiscal year.""" + """Evaluates whether the date in the given column is within the current fiscal year.""" return FTR._special_name_only(column, "ThisFiscalYear", lambda_indicator, group) @staticmethod def this_month(column: str, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the current month.""" + """Evaluates whether the date in the given column is within the current month.""" return FTR._special_name_only(column, "ThisMonth", lambda_indicator, group) @staticmethod def this_week(column: str, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the current week.""" + """Evaluates whether the date in the given column is within the current week.""" return FTR._special_name_only(column, "ThisWeek", lambda_indicator, group) @staticmethod def this_year(column: str, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the current year.""" + """Evaluates whether the date in the given column is within the current year.""" return FTR._special_name_only(column, "ThisYear", lambda_indicator, group) # Special query functions - dates - last @staticmethod def last_7_days(column: str, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the last seven days including today.""" + """Evaluates whether the date in the given column is within the last seven days including today.""" return FTR._special_name_only(column, "Last7Days", lambda_indicator, group) @staticmethod def last_fiscal_period(column: str, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the last fiscal period.""" + """Evaluates whether the date in the given column is within the last fiscal period.""" return FTR._special_name_only(column, "LastFiscalPeriod", lambda_indicator, group) @staticmethod def last_fiscal_year(column: str, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the last fiscal year.""" + """Evaluates whether the date in the given column is within the last fiscal year.""" return FTR._special_name_only(column, "LastFiscalYear", lambda_indicator, group) @staticmethod def last_month(column: str, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the last month.""" + """Evaluates whether the date in the given column is within the last month.""" return FTR._special_name_only(column, "LastMonth", lambda_indicator, group) @staticmethod def last_week(column: str, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the last week.""" + """Evaluates whether the date in the given column is within the last week.""" return FTR._special_name_only(column, "LastWeek", lambda_indicator, group) @staticmethod def last_year(column: str, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the last year.""" + """Evaluates whether the date in the given column is within the last year.""" return FTR._special_name_only(column, "LastYear", lambda_indicator, group) # Special query functions - dates - next @staticmethod def next_fiscal_period(column: str, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is in the next fiscal period.""" + """Evaluates whether the date in the given column is in the next fiscal period.""" return FTR._special_name_only(column, "NextFiscalPeriod", lambda_indicator, group) @staticmethod def next_fiscal_year(column: str, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is in the next fiscal year.""" + """Evaluates whether the date in the given column is in the next fiscal year.""" return FTR._special_name_only(column, "NextFiscalYear", lambda_indicator, group) @staticmethod def next_month(column: str, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is in the next month.""" + """Evaluates whether the date in the given column is in the next month.""" return FTR._special_name_only(column, "NextMonth", lambda_indicator, group) @staticmethod def next_week(column: str, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is in the next week.""" + """Evaluates whether the date in the given column is in the next week.""" return FTR._special_name_only(column, "NextWeek", lambda_indicator, group) @staticmethod def next_year(column: str, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the next year.""" + """Evaluates whether the date in the given column is within the next year.""" return FTR._special_name_only(column, "NextYear", lambda_indicator, group) # Special query functions - dates - last x @staticmethod def last_x_days(column: str, x: int, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the last X days.""" + """Evaluates whether the date in the given column is within the last X days.""" return FTR._special_single_value(column, x, "LastXDays", lambda_indicator, group, ref_quotes=False) @staticmethod def last_x_fiscal_periods(column: str, x: int, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the last X fiscal periods.""" + """Evaluates whether the date in the given column is within the last X fiscal periods.""" return FTR._special_single_value(column, x, "LastXFiscalPeriods", lambda_indicator, group, ref_quotes=False) @staticmethod def last_x_fiscal_years(column: str, x: int, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the last X fiscal years.""" + """Evaluates whether the date in the given column is within the last X fiscal years.""" return FTR._special_single_value(column, x, "LastXFiscalYears", lambda_indicator, group, ref_quotes=False) @staticmethod def last_x_hours(column: str, x: int, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the last X hours.""" + """Evaluates whether the date in the given column is within the last X hours.""" return FTR._special_single_value(column, x, "LastXHours", lambda_indicator, group, ref_quotes=False) @staticmethod def last_x_months(column: str, x: int, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the last X months.""" + """Evaluates whether the date in the given column is within the last X months.""" return FTR._special_single_value(column, x, "LastXMonths", lambda_indicator, group, ref_quotes=False) @staticmethod def last_x_weeks(column: str, x: int, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the last X weeks.""" + """Evaluates whether the date in the given column is within the last X weeks.""" return FTR._special_single_value(column, x, "LastXWeeks", lambda_indicator, group, ref_quotes=False) @staticmethod def last_x_years(column: str, x: int, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the last X years.""" + """Evaluates whether the date in the given column is within the last X years.""" return FTR._special_single_value(column, x, "LastXYears", lambda_indicator, group, ref_quotes=False) # Special query functions - dates - next x @staticmethod def next_x_days(column: str, x: int, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the next X days.""" + """Evaluates whether the date in the given column is within the next X days.""" return FTR._special_single_value(column, x, "NextXDays", lambda_indicator, group, ref_quotes=False) @staticmethod def next_x_fiscal_periods(column: str, x: int, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the next X fiscal periods.""" + """Evaluates whether the date in the given column is within the next X fiscal periods.""" return FTR._special_single_value(column, x, "NextXFiscalPeriods", lambda_indicator, group, ref_quotes=False) @staticmethod def next_x_fiscal_years(column: str, x: int, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the next X fiscal years.""" + """Evaluates whether the date in the given column is within the next X fiscal years.""" return FTR._special_single_value(column, x, "NextXFiscalYears", lambda_indicator, group, ref_quotes=False) @staticmethod def next_x_hours(column: str, x: int, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the next X hours.""" + """Evaluates whether the date in the given column is within the next X hours.""" return FTR._special_single_value(column, x, "NextXHours", lambda_indicator, group, ref_quotes=False) @staticmethod def next_x_months(column: str, x: int, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the next X months.""" + """Evaluates whether the date in the given column is within the next X months.""" return FTR._special_single_value(column, x, "NextXMonths", lambda_indicator, group, ref_quotes=False) @staticmethod def next_x_weeks(column: str, x: int, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the next X weeks.""" + """Evaluates whether the date in the given column is within the next X weeks.""" return FTR._special_single_value(column, x, "NextXWeeks", lambda_indicator, group, ref_quotes=False) @staticmethod def next_x_years(column: str, x: int, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is within the next X years.""" + """Evaluates whether the date in the given column is within the next X years.""" return FTR._special_single_value(column, x, "NextXYears", lambda_indicator, group, ref_quotes=False) # Special query functions - dates - older than x @staticmethod def older_than_x_days(column: str, x: int, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is older than the specified amount of days.""" + """Evaluates whether the date in the given column is older than the specified amount of days.""" return FTR._special_single_value(column, x, "OlderThanXDays", lambda_indicator, group, ref_quotes=False) @staticmethod def older_than_x_hours(column: str, x: int, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is older than the specified amount of hours.""" + """Evaluates whether the date in the given column is older than the specified amount of hours.""" return FTR._special_single_value(column, x, "OlderThanXHours", lambda_indicator, group, ref_quotes=False) @staticmethod def older_than_x_minutes(column: str, x: int, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is older than the specified amount of minutes.""" + """Evaluates whether the date in the given column is older than the specified amount of minutes.""" return FTR._special_single_value(column, x, "OlderThanXMinutes", lambda_indicator, group, ref_quotes=False) @staticmethod def older_than_x_months(column: str, x: int, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is older than the specified amount of moths.""" + """Evaluates whether the date in the given column is older than the specified amount of moths.""" return FTR._special_single_value(column, x, "OlderThanXMonths", lambda_indicator, group, ref_quotes=False) @staticmethod def older_than_x_weeks(column: str, x: int, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is older than the specified amount of weeks.""" + """Evaluates whether the date in the given column is older than the specified amount of weeks.""" return FTR._special_single_value(column, x, "OlderThanXWeeks", lambda_indicator, group, ref_quotes=False) @staticmethod def older_than_x_years(column: str, x: int, lambda_indicator: str = None, group: bool = False) -> str: - """Evaluates whether the value in the given column is older than the specified amount of years.""" + """Evaluates whether the date in the given column is older than the specified amount of years.""" return FTR._special_single_value(column, x, "OlderThanXYears", lambda_indicator, group, ref_quotes=False) # Special query functions - business id checks diff --git a/setup.cfg b/setup.cfg index 5a85e25..893269b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,7 +1,7 @@ [metadata] name = dynamics-client -version = 0.1.0 +version = 0.1.1 author = Matti Lamppu author_email = lamppu.matti.akseli@gmail.com description = Client for making Web API request from a Microsoft Dynamics 365 Database.