Skip to content

Commit

Permalink
Update dependencies (#83)
Browse files Browse the repository at this point in the history
* prevent install in python2, drop support 3.4, testing enhancements

	modified:   .gitignore
	modified:   .travis.yml
	modified:   Makefile
	modified:   Pipfile
	modified:   bwapi/bwresources.py
	modified:   setup.cfg
	modified:   setup.py

* fix linting errors, default pytest args

* fix wrong exception catch

* added targets to phony list in Makefile

* version consistency, black formatting
  • Loading branch information
Colin Sullivan authored Sep 19, 2019
1 parent 7faf0ee commit 2e029f8
Show file tree
Hide file tree
Showing 11 changed files with 203 additions and 141 deletions.
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,14 @@ var/
.mypy_cache/
Pipfile.lock
.ipynb_checkpoints/

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/
12 changes: 4 additions & 8 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,15 @@ matrix:
- python: 3.5
- python: 3.6
- python: 3.7
dist: xenial
sudo: true
- python: 3.7-dev
dist: xenial
sudo: true
- python: 3.8-dev
dist: xenial
sudo: true

install:
- pip install --upgrade setuptools wheel
- python setup.py install
- pip install .
- pip install pytest-cov pytest-sugar responses flake8

script:
- python setup.py test
- flake8 setup.py bwapi tests --exit-zero
- pytest -vv --cov=bwapi

16 changes: 7 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: clean clean-test clean-pyc clean-build test
.PHONY: clean clean-test clean-pyc clean-build test lint coverage upload dist bumpversion-patch bumpversion-minor bumpversion-major install install-dev

## remove all build, test, coverage and Python artifacts
clean: clean-build clean-pyc clean-test
Expand Down Expand Up @@ -32,15 +32,13 @@ lint: clean
pipenv run flake8 bwapi tests --exit-zero

## run tests with the default Python
test:
pipenv run pytest
test: lint
pipenv run pytest -vv --cov=bwapi

## check code coverage quickly with the default Python
coverage:
pipenv run coverage run --source bwapi -m pytest
pipenv run coverage report -m
pipenv run coverage html

coverage: clean
pipenv run pytest -vv --cov=bwapi --cov-report html --cov-report term
@echo '✨ 🍰 ✨ Open "htmlcov/index.html" in your browser to view report'
## upload wheel
upload: dist
pipenv run twine upload -r pypi dist/bwapi*
Expand Down Expand Up @@ -76,4 +74,4 @@ install-dev: clean
# See <https://gist.github.com/klmr/575726c7e05d8780505a> for explanation.
.PHONY: show-help
show-help:
@echo "$$(tput bold)Available rules:$$(tput sgr0)";echo;sed -ne"/^## /{h;s/.*//;:d" -e"H;n;s/^## //;td" -e"s/:.*//;G;s/\\n## /---/;s/\\n/ /g;p;}" ${MAKEFILE_LIST}|LC_ALL='C' sort -f|awk -F --- -v n=$$(tput cols) -v i=19 -v a="$$(tput setaf 6)" -v z="$$(tput sgr0)" '{printf"%s%*s%s ",a,-i,$$1,z;m=split($$2,w," ");l=n-i;for(j=1;j<=m;j++){l-=length(w[j])+1;if(l<= 0){l=n-i-length(w[j])-1;printf"\n%*s ",-i," ";}printf"%s ",w[j];}printf"\n";}'|more $(shell test $(shell uname) == Darwin && echo '-Xr')
@echo "$$(tput bold)Available rules:$$(tput sgr0)";echo;sed -ne"/^## /{h;s/.*//;:d" -e"H;n;s/^## //;td" -e"s/:.*//;G;s/\\n## /---/;s/\\n/ /g;p;}" ${MAKEFILE_LIST}|LC_ALL='C' sort -f|awk -F --- -v n=$$(tput cols) -v i=19 -v a="$$(tput setaf 6)" -v z="$$(tput sgr0)" '{printf"%s%*s%s ",a,-i,$$1,z;m=split($$2,w," ");l=n-i;for(j=1;j<=m;j++){l-=length(w[j])+1;if(l<= 0){l=n-i-length(w[j])-1;printf"\n%*s ",-i," ";}printf"%s ",w[j];}printf"\n";}'
4 changes: 3 additions & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ coverage = "*"
pydocstyle = "*"
better-exceptions = "*"
jupyterlab = "*"
black = "==18.9b0"
black = "==19.3b0"
pytest-cov = "*"
pytest-sugar = "*"

[packages]
bwapi = {editable = true,path = "."}
2 changes: 1 addition & 1 deletion bwapi/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Top-level package for bwapi."""

__version__ = "4.0.1"
__version__ = "4.0.2"
6 changes: 4 additions & 2 deletions bwapi/bwdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ def get_date_range_comparison(
"results"
]

## Channels
# Channels

def get_fb_analytics(self, name=None, startDate=None, **kwargs):
"""
Expand Down Expand Up @@ -939,7 +939,9 @@ def _fill_params(self, name, startDate, data):
if isinstance(name, str):
if not self.check_resource_exists(name):
logger.error(
"Could not find {} with name {}".format(self.resource_type, name)
"Could not find {} with name {}".format(
self.resource_type, name
)
)
else:
id_list.append(self.get_resource_id(name))
Expand Down
4 changes: 3 additions & 1 deletion bwapi/bwproject.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ def validate_query_search(self, **kwargs):
valid_search = self.request(
verb=requests.get, address="query-validation", params=kwargs
)
return valid_search

def validate_rule_search(self, **kwargs):
"""
Expand All @@ -154,6 +155,7 @@ def validate_rule_search(self, **kwargs):
valid_search = self.request(
verb=requests.get, address="query-validation/searchwithin", params=kwargs
)
return valid_search

def request(self, verb, address, params={}, data={}):
"""
Expand Down Expand Up @@ -294,7 +296,7 @@ def get_project(self, project):
try:
int(project)
numerical = True
except:
except ValueError:
numerical = False

for p in projects:
Expand Down
116 changes: 71 additions & 45 deletions bwapi/bwresources.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@
"""

import json
import datetime
from . import filters
import requests
import threading
from . import bwdata
import logging


logger = logging.getLogger("bwapi")


class AmbiguityError(ValueError):
'''Simple class to make errors when handling resource IDs more clear'''
"""Simple class to make errors when handling resource IDs more clear"""

pass


class BWResource:
"""
This class is a superclass for brandwatch resources (queries, groups, mentions, tags, sitelists, authorlists, locationlists and signals).
Expand Down Expand Up @@ -58,27 +58,43 @@ def reload(self):
}

def get_resource_id(self, resource=None):
'''Takes in a resource ID or name and returns the resource ID. Raises an error if an ambiguous name is provided (e.g. if user calls this function with 'Query1' and there is actually a query and a logo query with that name)
'''
"""Takes in a resource ID or name and returns the resource ID. Raises an error if an ambiguous name is provided (e.g. if user calls this function with 'Query1' and there is actually a query and a logo query with that name)
"""
if not resource:
return "" # return empty string rather than none to avoid stringified "None" becoming part of the url of an API call
return (
""
) # return empty string rather than none to avoid stringified "None" becoming part of the url of an API call
if isinstance(resource, int):
if resource not in self.names.keys():
raise KeyError('Could not find the resource ID {} in the project'.format(resource))
resource_id = resource
raise KeyError(
"Could not find the resource ID {} in the project".format(resource)
)
resource_id = resource
elif isinstance(resource, str):
entries = [resource_id for resource_id, name in self.names.items() if name == resource]
entries = [
resource_id
for resource_id, name in self.names.items()
if name == resource
]
if len(entries) > 1:
raise AmbiguityError('The resource name {} is ambiguous: {}'.format(resource, entries))
raise AmbiguityError(
"The resource name {} is ambiguous: {}".format(resource, entries)
)
if entries:
return entries[0]
else:
try:
try:
resource_id = int(resource)
except:
raise KeyError('Could not find the resource name {} in the project'.format(resource))
except ValueError:
raise KeyError(
"Could not find the resource name {} in the project".format(
resource
)
)
if resource_id not in self.names.keys():
raise KeyError('Could not find the resource ID {} in the project'.format(resource))
raise KeyError(
"Could not find the resource ID {} in the project".format(resource)
)
if resource_id:
return resource_id

Expand Down Expand Up @@ -110,9 +126,7 @@ def get(self, name=None):
All information for the specified resource, or a list of information on every resource of that type in the account.
"""
id_num = self.get_resource_id(resource=name)
return self.project.get(
endpoint=self.specific_endpoint + "/" + str(id_num)
)
return self.project.get(endpoint=self.specific_endpoint + "/" + str(id_num))

def upload(self, create_only=False, modify_only=False, **kwargs):
"""
Expand Down Expand Up @@ -154,7 +168,9 @@ def upload_all(self, data_list, create_only=False, modify_only=False):
endpoint=self.specific_endpoint + "/" + str(resource_id),
data=filled_data,
)
elif not self.check_resource_exists(name) and not modify_only: #if resource does not exist
elif (
not self.check_resource_exists(name) and not modify_only
): # if resource does not exist
response = self.project.post(
endpoint=self.specific_endpoint, data=filled_data
)
Expand All @@ -178,12 +194,14 @@ def rename(self, name, new_name):
Raises:
KeyError: If the resource does not exist.
"""
if not self.check_resource_exists(name): #if the resource does not exist
if not self.check_resource_exists(name): # if the resource does not exist
raise KeyError(
"Cannot rename a " + self.resource_type + " which does not exist", name
)
else:
info = self.get(name=name) # will raise error if ambiguous name provided, so we should be okay to provide a name from this point forward (it won't be ambiguous if we get past this stage)
info = self.get(
name=name
) # will raise error if ambiguous name provided, so we should be okay to provide a name from this point forward (it won't be ambiguous if we get past this stage)
info.pop("name")
self.upload(name=name, new_name=new_name, **info)

Expand All @@ -209,8 +227,10 @@ def delete_all(self, names):
if resource_id in self.names.keys():
self.project.delete(
endpoint=self.specific_endpoint + "/" + str(resource_id)
)
logger.info("{} {} deleted".format(self.resource_type, self.names[resource_id]))
)
logger.info(
"{} {} deleted".format(self.resource_type, self.names[resource_id])
)

self.reload()

Expand Down Expand Up @@ -353,8 +373,7 @@ def get_mention(self, **kwargs):
params = self._fill_mention_params(kwargs)
resource_id = self.get_resource_id(kwargs["name"])
mention = self.project.get(
endpoint="query/" + str(resource_id) + "/mentionfind",
params=params,
endpoint="query/" + str(resource_id) + "/mentionfind", params=params
)

if "errors" in mention:
Expand Down Expand Up @@ -446,11 +465,13 @@ def _fill_data(self, data):

if ("name" not in data) or ("includedTerms" not in data):
raise KeyError("Need name and includedTerms to post query", data)
if self.check_resource_exists(data["name"]): #if resource exists, create value for filled['id']
if self.check_resource_exists(
data["name"]
): # if resource exists, create value for filled['id']
filled["id"] = self.get_resource_id(data["name"])
if "new_name" in data:
filled["name"] = data["new_name"]
else: #if resource doesn't exist, add name to filled dictionary
else: # if resource doesn't exist, add name to filled dictionary
filled["name"] = data["name"]

filled["includedTerms"] = data["includedTerms"]
Expand All @@ -476,10 +497,8 @@ def _fill_data(self, data):
def _fill_mention_params(self, data):
if "name" not in data:
raise KeyError("Must specify query or group name", data)
elif not self.check_resource_exists(data["name"]): #if resource does not exist
raise KeyError(
"Could not find " + self.resource_type + " " + data["name"]
)
elif not self.check_resource_exists(data["name"]): # if resource does not exist
raise KeyError("Could not find " + self.resource_type + " " + data["name"])
if ("url" not in data) and ("resourceId" not in data):
raise KeyError("Must provide either a url or a resourceId", data)

Expand Down Expand Up @@ -676,7 +695,9 @@ def _fill_data(self, data):
filled = {}
if ("name" not in data) or ("queries" not in data):
raise KeyError("Need name and queries to upload group", data)
if self.check_resource_exists(data["name"]): #if resource exists, create value for filled['id']
if self.check_resource_exists(
data["name"]
): # if resource exists, create value for filled['id']
filled["id"] = self.get_resource_id(data["name"])

if "new_name" in data:
Expand All @@ -687,8 +708,11 @@ def _fill_data(self, data):
queries = data["queries"]
query_ids = [self.queries.get_resource_id(resource=x) for x in queries]

#now we have a reliable list of ids, we can turn this into a list of dictionaries in the form [{'name': 'MyQuery', 'id': 1111}]
filled['queries'] = [{'name':self.queries.names[resource_id], 'id':resource_id} for resource_id in query_ids]
# now we have a reliable list of ids, we can turn this into a list of dictionaries in the form [{'name': 'MyQuery', 'id': 1111}]
filled["queries"] = [
{"name": self.queries.names[resource_id], "id": resource_id}
for resource_id in query_ids
]
filled["shared"] = data["shared"] if "shared" in data else "public"
filled["sharedProjectIds"] = (
data["sharedProjectIds"]
Expand Down Expand Up @@ -830,7 +854,9 @@ def _fill_data(self, data):

if ("name" not in data) or ("authors" not in data):
raise KeyError("Need name and authors to upload authorlist", data)
if self.check_resource_exists(data["name"]): #if resource exists, create value for filled['id']
if self.check_resource_exists(
data["name"]
): # if resource exists, create value for filled['id']
filled["id"] = self.get_resource_id(data["name"])

if "new_name" in data:
Expand Down Expand Up @@ -881,7 +907,9 @@ def _fill_data(self, data):
if ("name" not in data) or ("domains" not in data):
raise KeyError("Need name and domains to upload sitelist", data)

if self.check_resource_exists(data["name"]): #if resource exists, create value for filled['id']
if self.check_resource_exists(
data["name"]
): # if resource exists, create value for filled['id']
filled["id"] = self.get_resource_id(data["name"])

if "new_name" in data:
Expand Down Expand Up @@ -1274,11 +1302,11 @@ def upload_all(self, data_list, create_only=False, modify_only=False):
rules = []

for rule in data_list:
rule = { **rule }
if 'filter' in rule:
rule['filter'] = {
**rule['filter'],
'projectId': self.project.project_id
rule = {**rule}
if "filter" in rule:
rule["filter"] = {
**rule["filter"],
"projectId": self.project.project_id,
}
rules.append(rule)

Expand All @@ -1287,7 +1315,7 @@ def upload_all(self, data_list, create_only=False, modify_only=False):
)

for rule in rules:
if "backfill" in rule and rule["backfill"] == True:
if "backfill" in rule and rule["backfill"]:
self.project.post(
endpoint="bulkactions/rule/" + str(rules_to_id[rule["name"]])
)
Expand Down Expand Up @@ -1422,9 +1450,7 @@ def get(self, name=None):
else:
exit()
elif not self.check_resource_exists(name):
raise KeyError(
"Could not find " + self.resource_type + ": " + name
)
raise KeyError("Could not find " + self.resource_type + ": " + name)
else:
resource_id = self.get_resource_id(name)
ruledata = self.project.get(
Expand Down
Loading

0 comments on commit 2e029f8

Please sign in to comment.