Skip to content

Commit

Permalink
Merge branch 'phil/add-facebook-marketing-activities-stream' of githu…
Browse files Browse the repository at this point in the history
…b.com:PhilipCorr/airbyte into marcos/test-pr-10655
  • Loading branch information
marcosmarxm committed Mar 1, 2022
2 parents 05504e5 + 61e6d45 commit 8dee538
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,5 @@ RUN pip install .
ENV AIRBYTE_ENTRYPOINT "python /airbyte/integration_code/main.py"
ENTRYPOINT ["python", "/airbyte/integration_code/main.py"]


LABEL io.airbyte.version=0.2.36
LABEL io.airbyte.version=0.2.37
LABEL io.airbyte.name=airbyte/source-facebook-marketing
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,19 @@
"cursor_field": null,
"destination_sync_mode": "append",
"primary_key": null
},
{
"stream": {
"name": "activities",
"json_schema": {},
"supported_sync_modes": ["full_refresh", "incremental"],
"source_defined_cursor": true,
"default_cursor_field": ["event_time"],
"namespace": null
},
"sync_mode": "incremental",
"cursor_field": null,
"destination_sync_mode": "append"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"properties": {
"actor_id": {
"type": ["null", "string"]
},
"actor_name": {
"type": ["null", "string"]
},
"application_id": {
"type": ["null", "string"]
},
"application_name": {
"type": ["null", "string"]
},
"date_time_in_timezone": {
"type": ["null", "string"]
},
"event_time": {
"type": "string",
"format": "date-time"
},
"event_type": {
"type": ["null", "string"]
},
"extra_data": {
"type": ["null", "string"]
},
"object_id": {
"type": ["null", "string"]
},
"object_name": {
"type": ["null", "string"]
},
"object_type": {
"type": ["null", "string"]
},
"translated_event_type": {
"type": ["null", "string"]
}
},
"type": ["null", "object"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from source_facebook_marketing.api import API
from source_facebook_marketing.spec import ConnectorConfig
from source_facebook_marketing.streams import (
Activities,
AdAccount,
AdCreatives,
Ads,
Expand Down Expand Up @@ -61,7 +62,6 @@ def streams(self, config: Mapping[str, Any]) -> List[Type[Stream]]:
start_date=config.start_date,
end_date=config.end_date,
)

streams = [
AdAccount(api=api),
AdSets(api=api, start_date=config.start_date, end_date=config.end_date, include_deleted=config.include_deleted),
Expand All @@ -77,6 +77,7 @@ def streams(self, config: Mapping[str, Any]) -> List[Type[Stream]]:
Campaigns(api=api, start_date=config.start_date, end_date=config.end_date, include_deleted=config.include_deleted),
Images(api=api, start_date=config.start_date, end_date=config.end_date, include_deleted=config.include_deleted),
Videos(api=api, start_date=config.start_date, end_date=config.end_date, include_deleted=config.include_deleted),
Activities(api=api, start_date=config.start_date, end_date=config.end_date, include_deleted=config.include_deleted),
]

return self._update_insights_streams(insights=config.custom_insights, args=insights_args, streams=streams)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#

from .streams import (
Activities,
AdAccount,
AdCreatives,
Ads,
Expand Down Expand Up @@ -34,4 +35,5 @@
"Campaigns",
"Images",
"Videos",
"Activities",
]
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
import logging
from typing import Any, Iterable, List, Mapping, Optional

import pendulum
import requests
from airbyte_cdk.models import SyncMode
from cached_property import cached_property
from facebook_business.adobjects.abstractobject import AbstractObject
from facebook_business.adobjects.adaccount import AdAccount as FBAdAccount

from .base_insight_streams import AdsInsights
Expand Down Expand Up @@ -93,6 +95,45 @@ def list_objects(self, params: Mapping[str, Any]) -> Iterable:
return self._api.account.get_campaigns(params=params)


class Activities(FBMarketingIncrementalStream):
"""doc: https://developers.facebook.com/docs/marketing-api/reference/ad-activity"""

entity_prefix = "activity"
cursor_field = "event_time"
primary_key = None

def list_objects(self, fields: List[str], params: Mapping[str, Any]) -> Iterable:
return self._api.account.get_activities(fields=fields, params=params)

def read_records(
self,
sync_mode: SyncMode,
cursor_field: List[str] = None,
stream_slice: Mapping[str, Any] = None,
stream_state: Mapping[str, Any] = None,
) -> Iterable[Mapping[str, Any]]:
"""Main read method used by CDK"""
loaded_records_iter = self.list_objects(fields=self.fields, params=self.request_params(stream_state=stream_state))

for record in loaded_records_iter:
if isinstance(record, AbstractObject):
yield record.export_all_data() # convert FB object to dict
else:
yield record # execute_in_batch will emmit dicts

def _state_filter(self, stream_state: Mapping[str, Any]) -> Mapping[str, Any]:
"""Additional filters associated with state if any set"""
state_value = stream_state.get(self.cursor_field)
since = self._start_date if not state_value else pendulum.parse(state_value)

potentially_new_records_in_the_past = self._include_deleted and not stream_state.get("include_deleted", False)
if potentially_new_records_in_the_past:
self.logger.info(f"Ignoring bookmark for {self.name} because of enabled `include_deleted` option")
since = self._start_date

return {"since": since.int_timestamp}


class Videos(FBMarketingIncrementalStream):
"""See: https://developers.facebook.com/docs/marketing-api/reference/video"""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def test_check_connection_exception(self, api, config, logger_mock):
def test_streams(self, config, api):
streams = SourceFacebookMarketing().streams(config)

assert len(streams) == 14
assert len(streams) == 15

def test_spec(self):
spec = SourceFacebookMarketing().spec()
Expand Down
2 changes: 2 additions & 0 deletions docs/integrations/sources/facebook-marketing.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ This Source is capable of syncing the following tables and their data:
* [AdInsights](https://developers.facebook.com/docs/marketing-api/reference/adgroup/insights/)
* [AdAccount](https://developers.facebook.com/docs/marketing-api/reference/ad-account)
* [Images](https://developers.facebook.com/docs/marketing-api/reference/ad-image)
* [Activities](https://developers.facebook.com/docs/marketing-api/reference/ad-activity)

You can segment the AdInsights table into parts based on the following information. Each part will be synced as a separate table if normalization is enabled:

Expand Down Expand Up @@ -103,6 +104,7 @@ As a summary, custom insights allows to replicate only some fields, resulting in

| Version | Date | Pull Request | Subject |
| :--- | :--- | :--- | :--- |
| 0.2.37 | 2022-02-28 | [10655](https://github.com/airbytehq/airbyte/pull/10655) | Add Activities stream |
| 0.2.36 | 2022-02-24 | [10588](https://github.com/airbytehq/airbyte/pull/10588) | Fix `execute_in_batch` for large amount of requests |
| 0.2.35 | 2022-02-18 | [10348](https://github.com/airbytehq/airbyte/pull/10348) | Add 104 error code to backoff triggers |
| 0.2.34 | 2022-02-17 | [10180](https://github.com/airbytehq/airbyte/pull/9805) | Performance and reliability fixes |
Expand Down

1 comment on commit 8dee538

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SonarQube Report

SonarQube report for Airbyte Connectors Source Facebook Marketing(#10767)

Measures

Name Value Name Value Name Value
Reliability Rating A Duplicated Lines (%) 0.0 Duplicated Blocks 0
Coverage 89.4 Security Rating A Lines of Code 1120
Vulnerabilities 0 Code Smells 93 Lines to Cover 832
Bugs 0 Quality Gate Status OK Blocker Issues 0
Critical Issues 0 Major Issues 3 Minor Issues 90

Detected Issues

Rule File Description Message
python:mypy_override (MINOR) streams/streams.py:105 Check that method override is compatible with base class Signature of "list_objects" incompatible with supertype "FBMarketingStream" . Code line: def list_objects(self, fields: List[str], params: Mapping[str, Any...
python:mypy_no_any_return (MINOR) streams/streams.py:106 Reject returning value with "Any" type if return type is not "Any" Returning Any from function declared to return "Iterable[Any]" . Code line: return self._api.account.get_activities(fields=fields, params=...
python:mypy_arg_type (MINOR) streams/streams.py:116 Check argument types in calls Argument "stream_state" to "request_params" of "FBMarketingIncrementalStream" has incompatible type "Optional[Mapping[str, Any]]"; expected "Mapping[str, Any]" . Code line: ...ds=self.fields, params=self.request_params(stream_state=stream_state))
python:mypy_attr_defined (MINOR) streams/streams.py:127 Check that attribute exists Module has no attribute "parse" . Code line: ...since = self.start_date if not state_value else pendulum.parse(state...
python:mypy_no_redef (MINOR) streams/base_streams.py:76 Check that each name is defined once Name "api_batch" already defined on line 69 . Code line: api_batch: FacebookAdsApiBatch = self._api.api.new_bat...
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:80 Check that attribute exists "Mapping[str, Any]" has no attribute "start_date" . Code line: Activities(api=api, start_date=config.start_date, end_date...
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:80 Check that attribute exists "Mapping[str, Any]" has no attribute "end_date" . Code line: ...(api=api, start_date=config.start_date, end_date=config.end_date, incl...
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:80 Check that attribute exists "Mapping[str, Any]" has no attribute "include_deleted" . Code line: ..._date, end_date=config.end_date, include_deleted=config.include_delete...
python:mypy_assignment (MINOR) streams/streams.py:101 Check that assigned value is compatible with target Incompatible types in assignment (expression has type "str", base class "FBMarketingStream" defined the type as "None") . Code line: entity_prefix = "activity"
python:mypy_assignment (MINOR) streams/streams.py:103 Check that assigned value is compatible with target Incompatible types in assignment (expression has type "None", base class "FBMarketingStream" defined the type as "str") . Code line: primary_key = None
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:44 Check that attribute exists "Mapping[str, Any]" has no attribute "end_date" . Code line: if pendulum.instance(config.end_date) < pendulum.instance(conf...
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:44 Check that attribute exists "Mapping[str, Any]" has no attribute "start_date" . Code line: ...ulum.instance(config.end_date) < pendulum.instance(config.start_date):
python:mypy_no_redef (MINOR) source_facebook_marketing/source.py:57 Check that each name is defined once Name "config" already defined on line 51 . Code line: config: ConnectorConfig = ConnectorConfig.parse_obj(config)
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:77 Check that attribute exists "Mapping[str, Any]" has no attribute "start_date" . Code line: Campaigns(api=api, start_date=config.start_date, end_date=...
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:77 Check that attribute exists "Mapping[str, Any]" has no attribute "end_date" . Code line: ...(api=api, start_date=config.start_date, end_date=config.end_date, incl...
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:77 Check that attribute exists "Mapping[str, Any]" has no attribute "include_deleted" . Code line: ..._date, end_date=config.end_date, include_deleted=config.include_delete...
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:79 Check that attribute exists "Mapping[str, Any]" has no attribute "start_date" . Code line: Videos(api=api, start_date=config.start_date, end_date=con...
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:79 Check that attribute exists "Mapping[str, Any]" has no attribute "end_date" . Code line: ...(api=api, start_date=config.start_date, end_date=config.end_date, incl...
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:79 Check that attribute exists "Mapping[str, Any]" has no attribute "include_deleted" . Code line: ..._date, end_date=config.end_date, include_deleted=config.include_delete...
python:mypy_misc (MINOR) source_facebook_marketing/spec.py:18 Miscellaneous other checks Enum() expects a string, tuple, list or dict literal as the second argument . Code line: ValidFields = Enum("ValidEnums", AdsInsights.Field.dict)
python:mypy_misc (MINOR) source_facebook_marketing/spec.py:19 Miscellaneous other checks Enum() expects a string, tuple, list or dict literal as the second argument . Code line: ValidBreakdowns = Enum("ValidBreakdowns", AdsInsights.Breakdowns.__dic...
python:mypy_name_defined (MINOR) source_facebook_marketing/spec.py:20 Check that name is defined Enum() expects a string, tuple, list or dict literal as the second argument [misc] ValidActionBreakdowns = Enum("ValidActionBreakdowns", AdsInsights.Acti...
python:mypy_attr_defined (MINOR) streams/init.py:5 Check that attribute exists Module "source_facebook_marketing.streams.streams" does not explicitly export attribute "AdsInsights"; implicit reexport disabled . Code line: from .streams import (
python:mypy_arg_type (MINOR) streams/async_job.py:149 Check argument types in calls Argument "jobs" to "update_in_batch" has incompatible type "List[InsightAsyncJob]"; expected "List[AsyncJob]" . Code line: update_in_batch(api=self._api, jobs=self._jobs)
python:mypy_return_value (MINOR) streams/async_job.py:236 Check that return value is compatible with signature Incompatible return value type (got "List[InsightAsyncJob]", expected "List[AsyncJob]") . Code line: return jobs
python:mypy_unreachable (MINOR) streams/async_job.py:266 Warn about unreachable statements or expressions Statement is unreachable . Code line: end_time = self._finish_time or pendulum.now()
python:mypy_index (MINOR) streams/async_job.py:315 Check indexing operations Value of type "Optional[Any]" is not indexable . Code line: job_status = self._job["async_status"]
python:mypy_index (MINOR) streams/async_job.py:316 Check indexing operations Value of type "Optional[Any]" is not indexable . Code line: percent = self._job["async_percent_completion"]
python:mypy_operator (MINOR) streams/async_job.py:319 Check that operator is valid for operands Unsupported operand types for < ("Duration" and "None") . Code line: if self.elapsed_time > self.job_timeout:
python:mypy_assignment (MINOR) streams/async_job.py:321 Check that assigned value is compatible with target Incompatible types in assignment (expression has type "DateTime", variable has type "None") . Code line: self._finish_time = pendulum.now()
python:mypy_assignment (MINOR) streams/async_job.py:325 Check that assigned value is compatible with target Incompatible types in assignment (expression has type "DateTime", variable has type "None") . Code line: self._finish_time = pendulum.now() # TODO: is not actual ...
python:mypy_assignment (MINOR) streams/async_job.py:328 Check that assigned value is compatible with target Incompatible types in assignment (expression has type "DateTime", variable has type "None") . Code line: self._finish_time = pendulum.now()
python:mypy_attr_defined (MINOR) streams/async_job.py:330 Check that attribute exists "None" has no attribute "in_seconds" . Code line: ...er.info(f"{self}: has status {job_status} after {self.elapsed_time.in_...
python:mypy_var_annotated (MINOR) streams/async_job_manager.py:43 Require variable annotation if type can't be inferred Need type annotation for "_running_jobs" (hint: "_running_jobs: List[] = ...") . Code line: self._running_jobs = []
python:mypy_no_any_return (MINOR) streams/async_job_manager.py:136 Reject returning value with "Any" type if return type is not "Any" Returning Any from function declared to return "float" . Code line: return min(throttle.per_account, throttle.per_application)
python:mypy_name_defined (MINOR) streams/base_insight_streams.py:58 Check that name is defined Need type annotation for "breakdowns" (hint: "breakdowns: List[] = ...") [var-annotated] breakdowns = []
python:mypy_var_annotated (MINOR) streams/base_insight_streams.py:79 Require variable annotation if type can't be inferred Need type annotation for "_completed_slices" (hint: "_completed_slices: Set[] = ...") . Code line: self._completed_slices = set()
python:mypy_no_any_return (MINOR) streams/base_insight_streams.py:85 Reject returning value with "Any" type if return type is not "Any" Returning Any from function declared to return "str" . Code line: return casing.camel_to_snake(name)
python:mypy_override (MINOR) streams/base_insight_streams.py:88 Check that method override is compatible with base class Signature of "primary_key" incompatible with supertype "FBMarketingStream" . Code line: def primary_key(self) -> Optional[Union[str, List[str], List[List[...
python:mypy_index (MINOR) streams/base_insight_streams.py:103 Check indexing operations Value of type "Optional[Mapping[str, Any]]" is not indexable . Code line: job = stream_slice["insight_job"]
python:mypy_attr_defined (MINOR) streams/base_insight_streams.py:130 Check that attribute exists Module has no attribute "parse" . Code line: self._cursor_value = pendulum.parse(value[self.cursor_field])....
python:mypy_attr_defined (MINOR) streams/base_insight_streams.py:131 Check that attribute exists Module has no attribute "parse" . Code line: self._completed_slices = set(pendulum.parse(v).date() for v in...
python:S5886 (MAJOR) streams/base_insight_streams.py:144 Function return types should be consistent with their type hint Return a value of type "Iterator" instead of "list" or update function "_date_intervals" type hint.
python:mypy_return_value (MINOR) streams/base_insight_streams.py:144 Check that return value is compatible with signature Incompatible return value type (got "List[]", expected "Iterator[Any]") . Code line: return []
python:mypy_no_any_return (MINOR) streams/base_insight_streams.py:146 Reject returning value with "Any" type if return type is not "Any" Returning Any from function declared to return "Iterator[Any]" . Code line: return date_range.range("days", self.time_increment)
python:mypy_attr_defined (MINOR) streams/base_insight_streams.py:168 Check that attribute exists Module has no attribute "Period"; maybe "period"? . Code line: interval = pendulum.Period(ts_start, ts_end)
python:mypy_name_defined (MINOR) streams/base_insight_streams.py:188 Check that name is defined Incompatible types in assignment (expression has type "Mapping[str, Any]", variable has type "MutableMapping[str, Any]") [assignment] self.state = stream_state
python:S1134 (MAJOR) streams/base_insight_streams.py:216 Track uses of "FIXME" tags Take the required action to fix the issue indicated by this "FIXME" comment.
python:mypy_override (MINOR) streams/base_insight_streams.py:229 Check that method override is compatible with base class Signature of "request_params" incompatible with supertype "FBMarketingIncrementalStream" . Code line: def request_params(self, **kwargs) -> MutableMapping[str, Any]:
python:mypy_no_any_return (MINOR) streams/base_insight_streams.py:254 Reject returning value with "Any" type if return type is not "Any" Returning Any from function declared to return "Mapping[str, Any]" . Code line: return schema
python:mypy_assignment (MINOR) streams/base_streams.py:92 Check that assigned value is compatible with target Incompatible types in assignment (expression has type "Iterable[MutableMapping[str, Any]]", variable has type "Generator[Any, None, None]") . Code line: loaded_records_iter = self.execute_in_batch(loaded_records...
python:mypy_attr_defined (MINOR) streams/base_streams.py:161 Check that attribute exists Module has no attribute "parse" . Code line: max_cursor = max(pendulum.parse(state_value), pendulum.parse(r...
python:mypy_override (MINOR) streams/base_streams.py:170 Check that method override is compatible with base class Signature of "request_params" incompatible with supertype "FBMarketingStream" . Code line: def request_params(self, stream_state: Mapping[str, Any], **kwargs...
python:mypy_attr_defined (MINOR) streams/base_streams.py:179 Check that attribute exists Module has no attribute "parse" . Code line: ...value = self.start_date if not state_value else pendulum.parse(state...
python:mypy_attr_defined (MINOR) streams/base_streams.py:225 Check that attribute exists Module has no attribute "parse" . Code line: self._cursor_value = pendulum.parse(value[self.cursor_field])
python:mypy_attr_defined (MINOR) streams/base_streams.py:238 Check that attribute exists Module has no attribute "parse" . Code line: record_cursor_value = pendulum.parse(latest_record[self.cursor...
python:mypy_arg_type (MINOR) streams/base_streams.py:261 Check argument types in calls Argument "stream_state" to "request_params" of "FBMarketingIncrementalStream" has incompatible type "Optional[Mapping[str, Any]]"; expected "Mapping[str, Any]" . Code line: ...lf.list_objects(params=self.request_params(stream_state=stream_state))
python:mypy_attr_defined (MINOR) streams/base_streams.py:263 Check that attribute exists Module has no attribute "parse" . Code line: if self._cursor_value and pendulum.parse(record[self.curso...
python:mypy_import (MINOR) streams/streams.py:10 Require that imported module can be found or has stubs Library stubs not installed for "requests" (or incompatible with Python 3.7) . Code line: import requests
python:mypy_assignment (MINOR) streams/streams.py:42 Check that assigned value is compatible with target Incompatible types in assignment (expression has type "str", base class "FBMarketingStream" defined the type as "None") . Code line: entity_prefix = "adcreative"
python:mypy_index (MINOR) streams/streams.py:64 Check indexing operations Unsupported target for indexed assignment ("Mapping[str, Any]") . Code line: record["thumbnail_data_url"] = fetch_thumbnail_data_ur...
python:mypy_arg_type (MINOR) streams/streams.py:64 Check argument types in calls Argument 1 to "fetch_thumbnail_data_url" has incompatible type "Optional[Any]"; expected "str" . Code line: ..."thumbnail_data_url"] = fetch_thumbnail_data_url(record.get("thumbnail...
python:mypy_no_any_return (MINOR) streams/streams.py:68 Reject returning value with "Any" type if return type is not "Any" Returning Any from function declared to return "Iterable[Any]" . Code line: return self._api.account.get_ad_creatives(params=params)
python:mypy_assignment (MINOR) streams/streams.py:74 Check that assigned value is compatible with target Incompatible types in assignment (expression has type "str", base class "FBMarketingStream" defined the type as "None") . Code line: entity_prefix = "ad"
python:mypy_no_any_return (MINOR) streams/streams.py:77 Reject returning value with "Any" type if return type is not "Any" Returning Any from function declared to return "Iterable[Any]" . Code line: return self._api.account.get_ads(params=params)
python:mypy_assignment (MINOR) streams/streams.py:83 Check that assigned value is compatible with target Incompatible types in assignment (expression has type "str", base class "FBMarketingStream" defined the type as "None") . Code line: entity_prefix = "adset"
python:mypy_no_any_return (MINOR) streams/streams.py:86 Reject returning value with "Any" type if return type is not "Any" Returning Any from function declared to return "Iterable[Any]" . Code line: return self._api.account.get_ad_sets(params=params)
python:mypy_assignment (MINOR) streams/streams.py:92 Check that assigned value is compatible with target Incompatible types in assignment (expression has type "str", base class "FBMarketingStream" defined the type as "None") . Code line: entity_prefix = "campaign"
python:mypy_no_any_return (MINOR) streams/streams.py:95 Reject returning value with "Any" type if return type is not "Any" Returning Any from function declared to return "Iterable[Any]" . Code line: return self._api.account.get_campaigns(params=params)
python:mypy_assignment (MINOR) streams/streams.py:140 Check that assigned value is compatible with target Incompatible types in assignment (expression has type "str", base class "FBMarketingStream" defined the type as "None") . Code line: entity_prefix = "video"
python:mypy_no_any_return (MINOR) streams/streams.py:143 Reject returning value with "Any" type if return type is not "Any" Returning Any from function declared to return "Iterable[Any]" . Code line: return self._api.account.get_ad_videos(params=params)
python:mypy_no_any_return (MINOR) streams/streams.py:161 Reject returning value with "Any" type if return type is not "Any" Returning Any from function declared to return "Iterable[Any]" . Code line: return self._api.account.get_ad_images(params=params, fields=s...
python:mypy_var_annotated (MINOR) streams/streams.py:188 Require variable annotation if type can't be inferred Need type annotation for "breakdowns" (hint: "breakdowns: List[] = ...") . Code line: breakdowns = []
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:78 Check that attribute exists "Mapping[str, Any]" has no attribute "end_date" . Code line: ...(api=api, start_date=config.start_date, end_date=config.end_date, incl...
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:78 Check that attribute exists "Mapping[str, Any]" has no attribute "start_date" . Code line: Images(api=api, start_date=config.start_date, end_date=con...
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:78 Check that attribute exists "Mapping[str, Any]" has no attribute "include_deleted" . Code line: ..._date, end_date=config.end_date, include_deleted=config.include_delete...
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:69 Check that attribute exists "Mapping[str, Any]" has no attribute "fetch_thumbnail_images" . Code line: ... AdCreatives(api=api, fetch_thumbnail_images=config.fetch_thumbnai...
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:83 Check that attribute exists "Mapping[str, Any]" has no attribute "custom_insights" . Code line: ... return self._update_insights_streams(insights=config.custom_insight...
python:mypy_no_any_return (MINOR) source_facebook_marketing/source.py:109 Reject returning value with "Any" type if return type is not "Any" Returning Any from function declared to return "List[Type[Any]]" . Code line: return streams
python:mypy_no_any_return (MINOR) source_facebook_marketing/source.py:121 Reject returning value with "Any" type if return type is not "Any" Returning Any from function declared to return "List[Type[Any]]" . Code line: return streams + insights_custom_streams
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:63 Check that attribute exists "Mapping[str, Any]" has no attribute "end_date" . Code line: end_date=config.end_date,
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:67 Check that attribute exists "Mapping[str, Any]" has no attribute "end_date" . Code line: ...(api=api, start_date=config.start_date, end_date=config.end_date, incl...
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:67 Check that attribute exists "Mapping[str, Any]" has no attribute "include_deleted" . Code line: ..._date, end_date=config.end_date, include_deleted=config.include_delete...
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:67 Check that attribute exists "Mapping[str, Any]" has no attribute "start_date" . Code line: AdSets(api=api, start_date=config.start_date, end_date=con...
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:68 Check that attribute exists "Mapping[str, Any]" has no attribute "start_date" . Code line: Ads(api=api, start_date=config.start_date, end_date=config...
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:68 Check that attribute exists "Mapping[str, Any]" has no attribute "end_date" . Code line: ...(api=api, start_date=config.start_date, end_date=config.end_date, incl...
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:68 Check that attribute exists "Mapping[str, Any]" has no attribute "include_deleted" . Code line: ..._date, end_date=config.end_date, include_deleted=config.include_delete...
python:S1700 (MAJOR) source_facebook_marketing/api.py:158 A field should not duplicate the name of its containing class Rename field "api"
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:46 Check that attribute exists "Mapping[str, Any]" has no attribute "account_id" . Code line: api = API(account_id=config.account_id, access_token=config.ac...
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:46 Check that attribute exists "Mapping[str, Any]" has no attribute "access_token" . Code line: ... = API(account_id=config.account_id, access_token=config.access_token)
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:58 Check that attribute exists "Mapping[str, Any]" has no attribute "account_id" . Code line: api = API(account_id=config.account_id, access_token=config.ac...
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:58 Check that attribute exists "Mapping[str, Any]" has no attribute "access_token" . Code line: ... = API(account_id=config.account_id, access_token=config.access_token)
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:62 Check that attribute exists "Mapping[str, Any]" has no attribute "start_date" . Code line: start_date=config.start_date,

Coverage (89.4%)

File Coverage File Coverage
source_facebook_marketing/init.py 100.0 source_facebook_marketing/api.py 83.2
source_facebook_marketing/source.py 100.0 source_facebook_marketing/spec.py 100.0
source_facebook_marketing/streams/init.py 100.0 source_facebook_marketing/streams/async_job.py 100.0
source_facebook_marketing/streams/async_job_manager.py 95.9 source_facebook_marketing/streams/base_insight_streams.py 91.2
source_facebook_marketing/streams/base_streams.py 74.4 source_facebook_marketing/streams/common.py 97.4
source_facebook_marketing/streams/streams.py 76.3

Please sign in to comment.