Skip to content

Commit

Permalink
Merge branch 'master' into george/fb-marketing
Browse files Browse the repository at this point in the history
  • Loading branch information
Phlair committed Apr 29, 2022
2 parents cfa3699 + 6565315 commit 0fb5d03
Show file tree
Hide file tree
Showing 258 changed files with 5,721 additions and 1,883 deletions.
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.36.3-alpha
current_version = 0.36.5-alpha
commit = False
tag = False
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\-[a-z]+)?
Expand Down
4 changes: 2 additions & 2 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@


### SHARED ###
VERSION=0.36.3-alpha
VERSION=0.36.5-alpha

# When using the airbyte-db via default docker image
CONFIG_ROOT=/data
Expand Down Expand Up @@ -40,7 +40,7 @@ DATABASE_PASSWORD=docker
DATABASE_HOST=db
DATABASE_PORT=5432
DATABASE_DB=airbyte
# translate manually DATABASE_URL=jdbc:postgresql://${DATABASE_HOST}:${DATABASE_PORT/${DATABASE_DB} (do not include the username or password here)
# translate manually DATABASE_URL=jdbc:postgresql://${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_DB} (do not include the username or password here)
DATABASE_URL=jdbc:postgresql://db:5432/airbyte
JOBS_DATABASE_MINIMUM_FLYWAY_MIGRATION_VERSION=0.29.15.001

Expand Down
37 changes: 0 additions & 37 deletions .github/workflows/documentation.yml

This file was deleted.

1 change: 1 addition & 0 deletions .github/workflows/publish-command.yml
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ jobs:
run: |
git add -u
git commit -m "auto-bump connector version"
git pull origin ${{ github.event.inputs.gitref }}
git push origin ${{ github.event.inputs.gitref }}
- name: Add Version Bump Success Comment
if: github.event.inputs.comment-id && github.event.inputs.auto-bump-version == 'true' && success()
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/slash-commands.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ jobs:
commands: |
test
test-performance
build-connector
publish-connector
publish
publish-external
publish-cdk
Expand Down
1 change: 0 additions & 1 deletion airbyte-api/src/main/openapi/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3143,7 +3143,6 @@ components:
WebBackendConnectionCreate:
type: object
required:
- connection
- sourceId
- destinationId
- status
Expand Down
2 changes: 1 addition & 1 deletion airbyte-bootloader/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ARG JDK_VERSION=17.0.1
FROM openjdk:${JDK_VERSION}-slim

ARG VERSION=0.36.3-alpha
ARG VERSION=0.36.5-alpha

ENV APPLICATION airbyte-bootloader
ENV VERSION ${VERSION}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@
* returning a list for query results. In addition, we provide helper functions that will just
* return a single value (see: {@link JsonPaths#getSingleValue(JsonNode, String)}). These should
* only be used if it is not possible for a query to return more than one value.
*
* Note: Package private as most uses of JsonPaths seems like they can be hidden inside other
* commons libraries (i.e. Jsons and JsonsSchemas). If this assumption proves incorrect, we can open
* it up.
*/
class JsonPaths {
public class JsonPaths {

private static final Logger LOGGER = LoggerFactory.getLogger(JsonPaths.class);

static final String JSON_PATH_START_CHARACTER = "$";
static final String JSON_PATH_LIST_SPLAT = "[*]";
static final String JSON_PATH_FIELD_SEPARATOR = ".";

// set default configurations at start up to match our JSON setup.
static {
Configuration.setDefaults(new Configuration.Defaults() {
Expand Down Expand Up @@ -82,6 +82,18 @@ public Set<Option> options() {
});
}

public static String empty() {
return JSON_PATH_START_CHARACTER;
}

public static String appendField(final String jsonPath, final String field) {
return jsonPath + JSON_PATH_FIELD_SEPARATOR + field;
}

public static String appendAppendListSplat(final String jsonPath) {
return jsonPath + JSON_PATH_LIST_SPLAT;
}

/*
* This version of the JsonPath Configuration object allows queries to return to the path of values
* instead of the values that were found.
Expand Down
185 changes: 179 additions & 6 deletions airbyte-commons/src/main/java/io/airbyte/commons/json/JsonSchemas.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,51 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.airbyte.commons.io.IOs;
import io.airbyte.commons.resources.MoreResources;
import io.airbyte.commons.util.MoreIterators;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.extern.slf4j.Slf4j;

// todo (cgardens) - we need the ability to identify jsonschemas that Airbyte considers invalid for
// a connector (e.g. "not" keyword).
@Slf4j
public class JsonSchemas {

private static final String JSON_SCHEMA_ENUM_KEY = "enum";
private static final String JSON_SCHEMA_TYPE_KEY = "type";
private static final String JSON_SCHEMA_PROPERTIES_KEY = "properties";
private static final String JSON_SCHEMA_ITEMS_KEY = "items";

// all JSONSchema types.
private static final String ARRAY_TYPE = "array";
private static final String OBJECT_TYPE = "object";
private static final String STRING_TYPE = "string";
private static final String NUMBER_TYPE = "number";
private static final String BOOLEAN_TYPE = "boolean";
private static final String NULL_TYPE = "null";
private static final String ONE_OF_TYPE = "oneOf";
private static final String ALL_OF_TYPE = "allOf";
private static final String ANY_OF_TYPE = "anyOf";

private static final String ARRAY_JSON_PATH = "[]";

private static final Set<String> COMPOSITE_KEYWORDS = Set.of(ONE_OF_TYPE, ALL_OF_TYPE, ANY_OF_TYPE);

/**
* JsonSchema supports to ways of declaring type. `type: "string"` and `type: ["null", "string"]`.
* This method will mutate a JsonNode with a type field so that the output type is the array
Expand All @@ -25,16 +61,16 @@ public class JsonSchemas {
* @param jsonNode - a json object with children that contain types.
*/
public static void mutateTypeToArrayStandard(final JsonNode jsonNode) {
if (jsonNode.get("type") != null && !jsonNode.get("type").isArray()) {
final JsonNode type = jsonNode.get("type");
((ObjectNode) jsonNode).putArray("type").add(type);
if (jsonNode.get(JSON_SCHEMA_TYPE_KEY) != null && !jsonNode.get(JSON_SCHEMA_TYPE_KEY).isArray()) {
final JsonNode type = jsonNode.get(JSON_SCHEMA_TYPE_KEY);
((ObjectNode) jsonNode).putArray(JSON_SCHEMA_TYPE_KEY).add(type);
}
}

/*
* JsonReferenceProcessor relies on all of the json in consumes being in a file system (not in a
* jar). This method copies all of the json configs out of the jar into a temporary directory so
* that JsonReferenceProcessor can find them.
* JsonReferenceProcessor relies on all the json in consumes being in a file system (not in a jar).
* This method copies all the json configs out of the jar into a temporary directory so that
* JsonReferenceProcessor can find them.
*/
public static <T> Path prepareSchemas(final String resourceDir, final Class<T> klass) {
try {
Expand All @@ -59,4 +95,141 @@ public static <T> Path prepareSchemas(final String resourceDir, final Class<T> k
}
}

public static void traverseJsonSchema(final JsonNode jsonSchemaNode, final BiConsumer<JsonNode, String> consumer) {
traverseJsonSchemaInternal(jsonSchemaNode, JsonPaths.empty(), consumer);
}

/**
* Traverse a JsonSchema object. At each node, optionally map a value.
*
* @param jsonSchema - JsonSchema object to traverse
* @param mapper - accepts the current node and the path to that node. if it returns an empty
* optional, nothing will be collected, otherwise, whatever is returned will be collected and
* returned by the final collection.
* @param <T> - type of objects being collected
* @return - collection of all items that were collected during the traversal. Returns a { @link
* Collection } because there is no order or uniqueness guarantee so neither List nor Set
* make sense.
*/
public static <T> Collection<T> traverseJsonSchemaWithCollector(final JsonNode jsonSchema, final BiFunction<JsonNode, String, Optional<T>> mapper) {
final List<T> collectors = new ArrayList<>();
traverseJsonSchema(jsonSchema, (node, path) -> mapper.apply(node, path).ifPresent(collectors::add));
return collectors;
}

/**
* Traverses a JsonSchema object. It returns the path to each node that meet the provided condition.
* The paths are return in JsonPath format
*
* @param obj - JsonSchema object to traverse
* @param predicate - predicate to determine if the path for a node should be collected.
* @return - collection of all paths that were collected during the traversal.
*/
public static Set<String> collectJsonPathsThatMeetCondition(final JsonNode obj, final Predicate<JsonNode> predicate) {
return new HashSet<>(traverseJsonSchemaWithCollector(obj, (node, path) -> {
if (predicate.test(node)) {
return Optional.of(path);
} else {
return Optional.empty();
}
}));
}

/**
* Recursive, depth-first implementation of { @link JsonSchemas#traverseJsonSchema(final JsonNode
* jsonNode, final BiConsumer<JsonNode, List<String>> consumer) }. Takes path as argument so that
* the path can be passsed to the consumer.
*
* @param jsonSchemaNode - jsonschema object to traverse.
* @param path - path from the first call of traverseJsonSchema to the current node.
* @param consumer - consumer to be called at each node. it accepts the current node and the path to
* the node from the root of the object passed at the root level invocation
*/
// todo (cgardens) - replace with easier to understand traversal logic from SecretsHelper.
private static void traverseJsonSchemaInternal(final JsonNode jsonSchemaNode,
final String path,
final BiConsumer<JsonNode, String> consumer) {
if (!jsonSchemaNode.isObject()) {
throw new IllegalArgumentException(String.format("json schema nodes should always be object nodes. path: %s actual: %s", path, jsonSchemaNode));
}

consumer.accept(jsonSchemaNode, path);
// if type is missing assume object. not official JsonSchema, but it seems to be a common
// compromise.
final List<String> nodeTypes = getTypeOrObject(jsonSchemaNode);

for (final String nodeType : nodeTypes) {
switch (nodeType) {
// case BOOLEAN_TYPE, NUMBER_TYPE, STRING_TYPE, NULL_TYPE -> do nothing after consumer.accept above.
case ARRAY_TYPE -> {
final String newPath = JsonPaths.appendAppendListSplat(path);
// hit every node.
// log.error("array: " + jsonSchemaNode);
traverseJsonSchemaInternal(jsonSchemaNode.get(JSON_SCHEMA_ITEMS_KEY), newPath, consumer);
}
case OBJECT_TYPE -> {
final Optional<String> comboKeyWordOptional = getKeywordIfComposite(jsonSchemaNode);
if (jsonSchemaNode.has(JSON_SCHEMA_PROPERTIES_KEY)) {
for (final Iterator<Entry<String, JsonNode>> it = jsonSchemaNode.get(JSON_SCHEMA_PROPERTIES_KEY).fields(); it.hasNext();) {
final Entry<String, JsonNode> child = it.next();
final String newPath = JsonPaths.appendField(path, child.getKey());
// log.error("obj1: " + jsonSchemaNode);
traverseJsonSchemaInternal(child.getValue(), newPath, consumer);
}
} else if (comboKeyWordOptional.isPresent()) {
for (final JsonNode arrayItem : jsonSchemaNode.get(comboKeyWordOptional.get())) {
// log.error("obj2: " + jsonSchemaNode);
traverseJsonSchemaInternal(arrayItem, path, consumer);
}
} else {
throw new IllegalArgumentException(
"malformed JsonSchema object type, must have one of the following fields: properties, oneOf, allOf, anyOf in " + jsonSchemaNode);
}
}
}
}
}

/**
* If the object uses JSONSchema composite functionality (e.g. oneOf, anyOf, allOf), detect it and
* return which one it is using.
*
* @param node - object to detect use of composite functionality.
* @return the composite functionality being used, if not using composite functionality, empty.
*/
private static Optional<String> getKeywordIfComposite(final JsonNode node) {
for (final String keyWord : COMPOSITE_KEYWORDS) {
if (node.has(keyWord)) {
return Optional.ofNullable(keyWord);
}
}
return Optional.empty();
}

public static List<String> getTypeOrObject(final JsonNode jsonNode) {
final List<String> types = getType(jsonNode);
if (types.isEmpty()) {
return List.of(OBJECT_TYPE);
} else {
return types;
}
}

public static List<String> getType(final JsonNode jsonNode) {
if (jsonNode.has(JSON_SCHEMA_TYPE_KEY)) {
if (jsonNode.get(JSON_SCHEMA_TYPE_KEY).isArray()) {
return MoreIterators.toList(jsonNode.get(JSON_SCHEMA_TYPE_KEY).iterator())
.stream()
.map(JsonNode::asText)
.collect(Collectors.toList());
} else {
return List.of(jsonNode.get(JSON_SCHEMA_TYPE_KEY).asText());
}
}
if (jsonNode.has(JSON_SCHEMA_ENUM_KEY)) {
return List.of(STRING_TYPE);
}
return Collections.emptyList();
}

}
Loading

1 comment on commit 0fb5d03

@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(#12390)

Measures

Name Value Name Value Name Value
Duplicated Blocks 0 Reliability Rating A Lines of Code 1191
Duplicated Lines (%) 0.0 Code Smells 95 Coverage 90.7
Lines to Cover 853 Security Rating A Quality Gate Status OK
Vulnerabilities 0 Bugs 0 Blocker Issues 0
Critical Issues 0 Major Issues 1 Minor Issues 94

Detected Issues

Rule File Description Message
python:mypy_import (MINOR) source_facebook_marketing/source.py:9 Require that imported module can be found or has stubs Library stubs not installed for "requests" (or incompatible with Python 3.9) . Code line: import requests
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:86 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_arg_type (MINOR) source_facebook_marketing/source.py:120 Check argument types in calls Argument 1 to "set" has incompatible type "Optional[List[ValidFields]]"; expected "Iterable[ValidFields]" . Code line: fields=list(set(insight.fields)),
python:mypy_arg_type (MINOR) source_facebook_marketing/source.py:120 Check argument types in calls Argument 1 to "set" has incompatible type "Optional[List[ValidFields]]"; expected "Iterable[Any]" . Code line: fields=list(set(insight.fields)),
python:mypy_arg_type (MINOR) source_facebook_marketing/source.py:121 Check argument types in calls Argument 1 to "set" has incompatible type "Optional[List[ValidBreakdowns]]"; expected "Iterable[ValidBreakdowns]" . Code line: breakdowns=list(set(insight.breakdowns)),
python:mypy_arg_type (MINOR) source_facebook_marketing/source.py:121 Check argument types in calls Argument 1 to "set" has incompatible type "Optional[List[ValidBreakdowns]]"; expected "Iterable[Any]" . Code line: breakdowns=list(set(insight.breakdowns)),
python:mypy_arg_type (MINOR) source_facebook_marketing/source.py:122 Check argument types in calls Argument 1 to "set" has incompatible type "Optional[List[ValidActionBreakdowns]]"; expected "Iterable[ValidActionBreakdowns]" . Code line: action_breakdowns=list(set(insight.action_breakdowns))...
python:mypy_arg_type (MINOR) source_facebook_marketing/source.py:122 Check argument types in calls Argument 1 to "set" has incompatible type "Optional[List[ValidActionBreakdowns]]"; expected "Iterable[Any]" . Code line: action_breakdowns=list(set(insight.action_breakdowns))...
python:mypy_attr_defined (MINOR) streams/base_streams.py:246 Check that attribute exists Module has no attribute "parse" . Code line: record_cursor_value = pendulum.parse(record[self.cursor_fi...
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:83 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:83 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:83 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_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:45 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:45 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:60 Check that each name is defined once Name "config" already defined on line 54 . Code line: config: ConnectorConfig = ConnectorConfig.parse_obj(config)
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: Campaigns(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_attr_defined (MINOR) source_facebook_marketing/source.py:82 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:82 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:82 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:152 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:247 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:277 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:326 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:327 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:330 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:332 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:336 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:339 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:341 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:81 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:87 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:90 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:105 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:141 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:142 Check that attribute exists Module has no attribute "parse" . Code line: self._completed_slices = set(pendulum.parse(v).date() for v in...
python:mypy_attr_defined (MINOR) streams/base_insight_streams.py:180 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:200 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:mypy_override (MINOR) streams/base_insight_streams.py:240 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:265 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_arg_type (MINOR) streams/base_streams.py:244 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_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.9) . 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:81 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:81 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:81 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:72 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_no_any_return (MINOR) source_facebook_marketing/source.py:112 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:130 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:66 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:70 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:70 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:70 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:71 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:71 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:71 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:164 A field should not duplicate the name of its containing class Rename field "api"
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:48 Check that attribute exists "Mapping[str, Any]" has no attribute "account_id" . Code line: api = API(account_id=config.account_id, access_token=confi...
python:mypy_attr_defined (MINOR) source_facebook_marketing/source.py:48 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:61 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:61 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:65 Check that attribute exists "Mapping[str, Any]" has no attribute "start_date" . Code line: start_date=config.start_date,

Coverage (90.7%)

File Coverage File Coverage
source_facebook_marketing/init.py 100.0 source_facebook_marketing/api.py 90.6
source_facebook_marketing/source.py 97.4 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 89.9
source_facebook_marketing/streams/base_streams.py 76.4 source_facebook_marketing/streams/common.py 97.6
source_facebook_marketing/streams/streams.py 77.3

Please sign in to comment.