dcicutils 7.6.0.2b9__tar.gz → 7.7.0.1b1__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of dcicutils might be problematic. Click here for more details.
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/LICENSE.txt +1 -1
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/PKG-INFO +1 -1
- dcicutils-7.7.0.1b1/dcicutils/item_model_utils.py +224 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/lang_utils.py +7 -8
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/qa_checkers.py +0 -9
- dcicutils-7.7.0.1b1/dcicutils/testing_utils.py +37 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/pyproject.toml +3 -9
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/setup.py +3 -4
- dcicutils-7.6.0.2b9/dcicutils/contribution_scripts.py +0 -39
- dcicutils-7.6.0.2b9/dcicutils/contribution_utils.py +0 -570
- dcicutils-7.6.0.2b9/dcicutils/license_utils.py +0 -863
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/README.rst +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/__init__.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/base.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/beanstalk_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/cloudformation_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/codebuild_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/command_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/common.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/creds_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/data_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/deployment_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/diff_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/docker_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/ecr_scripts.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/ecr_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/ecs_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/env_base.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/env_manager.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/env_scripts.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/env_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/env_utils_legacy.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/es_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/exceptions.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/ff_mocks.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/ff_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/function_cache_decorator.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/glacier_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/jh_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/kibana/dashboards.json +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/kibana/readme.md +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/log_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/misc_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/obfuscation_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/opensearch_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/project_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/qa_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/redis_tools.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/redis_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/s3_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/scripts/publish_to_pypi.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/secrets_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/snapshot_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/ssl_certificate_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/task_utils.py +0 -0
- {dcicutils-7.6.0.2b9 → dcicutils-7.7.0.1b1}/dcicutils/trace_utils.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
The MIT License
|
2
2
|
|
3
|
-
Copyright 2017
|
3
|
+
Copyright 2017 President and Fellows of Harvard College.
|
4
4
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
@@ -0,0 +1,224 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from dataclasses import dataclass, field
|
4
|
+
from functools import lru_cache
|
5
|
+
from typing import Any, Dict, Iterable, List, Mapping, Optional, Tuple, Union
|
6
|
+
|
7
|
+
import structlog
|
8
|
+
|
9
|
+
from . import ff_utils
|
10
|
+
|
11
|
+
|
12
|
+
logger = structlog.getLogger(__name__)
|
13
|
+
|
14
|
+
LinkTo = Union[str, Dict[str, Any]]
|
15
|
+
|
16
|
+
|
17
|
+
def get_link_to(
|
18
|
+
existing_item: PortalItem,
|
19
|
+
link_to: LinkTo,
|
20
|
+
item_to_create: PortalItem,
|
21
|
+
) -> Union[str, PortalItem]:
|
22
|
+
"""Create new item model from existing one for given linkTo.
|
23
|
+
|
24
|
+
LinkTos be identifiers (e.g. UUIDs) or (partially) embedded objects.
|
25
|
+
|
26
|
+
Follow rules of existing item model for fetching linkTo via
|
27
|
+
request. If not fetching via request, then make item model from
|
28
|
+
existing properties if possible.
|
29
|
+
"""
|
30
|
+
fetch_links = existing_item.should_fetch_links()
|
31
|
+
identifier = get_item_identifier(link_to)
|
32
|
+
if fetch_links and identifier:
|
33
|
+
return item_to_create.from_identifier_and_existing_item(
|
34
|
+
identifier, existing_item
|
35
|
+
)
|
36
|
+
if isinstance(link_to, Mapping):
|
37
|
+
return item_to_create.from_properties_and_existing_item(link_to, existing_item)
|
38
|
+
return link_to
|
39
|
+
|
40
|
+
|
41
|
+
def get_item_identifier(item: LinkTo) -> str:
|
42
|
+
if isinstance(item, str):
|
43
|
+
return item
|
44
|
+
if isinstance(item, Mapping):
|
45
|
+
return item.get(PortalItem.UUID, "")
|
46
|
+
|
47
|
+
|
48
|
+
@dataclass(frozen=True)
|
49
|
+
class PortalItem:
|
50
|
+
ACCESSION = "accession"
|
51
|
+
AT_ID = "@id"
|
52
|
+
TYPE = "@type"
|
53
|
+
UUID = "uuid"
|
54
|
+
|
55
|
+
properties: Dict[str, Any]
|
56
|
+
auth: Optional[Dict[str, Any]] = field(default=None, hash=False)
|
57
|
+
fetch_links: Optional[bool] = field(default=False, hash=False)
|
58
|
+
|
59
|
+
def __repr__(self) -> str:
|
60
|
+
return f"{self.__class__.__name__}({self._uuid})"
|
61
|
+
|
62
|
+
@property
|
63
|
+
def _uuid(self) -> str:
|
64
|
+
return self.properties.get(self.UUID, "")
|
65
|
+
|
66
|
+
@property
|
67
|
+
def _at_id(self) -> str:
|
68
|
+
return self.properties.get(self.AT_ID, "")
|
69
|
+
|
70
|
+
@property
|
71
|
+
def _accession(self) -> str:
|
72
|
+
return self.properties.get(self.ACCESSION, "")
|
73
|
+
|
74
|
+
@property
|
75
|
+
def _types(self) -> List[str]:
|
76
|
+
return self.properties.get(self.TYPE, [])
|
77
|
+
|
78
|
+
def should_fetch_links(self) -> bool:
|
79
|
+
return self.fetch_links
|
80
|
+
|
81
|
+
def get_auth(self) -> Union[Dict[str, Any], None]:
|
82
|
+
return self.auth
|
83
|
+
|
84
|
+
def get_properties(self) -> Dict[str, Any]:
|
85
|
+
return self.properties
|
86
|
+
|
87
|
+
def get_accession(self) -> str:
|
88
|
+
return self._accession
|
89
|
+
|
90
|
+
def get_uuid(self) -> str:
|
91
|
+
return self._uuid
|
92
|
+
|
93
|
+
def get_at_id(self) -> str:
|
94
|
+
return self._at_id
|
95
|
+
|
96
|
+
def get_types(self) -> List[str]:
|
97
|
+
return self._types
|
98
|
+
|
99
|
+
def _get_link_tos(
|
100
|
+
self, link_tos: Iterable[LinkTo], item_to_create: PortalItem
|
101
|
+
) -> List[Union[str, PortalItem]]:
|
102
|
+
return [self._get_link_to(link_to, item_to_create) for link_to in link_tos]
|
103
|
+
|
104
|
+
def _get_link_to(
|
105
|
+
self,
|
106
|
+
link_to: LinkTo,
|
107
|
+
item_to_create: PortalItem,
|
108
|
+
) -> Union[str, PortalItem]:
|
109
|
+
return get_link_to(self, link_to, item_to_create)
|
110
|
+
|
111
|
+
@classmethod
|
112
|
+
def from_properties(
|
113
|
+
cls,
|
114
|
+
properties: Dict[str, Any],
|
115
|
+
fetch_links: bool = False,
|
116
|
+
auth: Dict[str, Any] = None,
|
117
|
+
**kwargs: Any,
|
118
|
+
) -> PortalItem:
|
119
|
+
return cls(properties, fetch_links=fetch_links, auth=auth)
|
120
|
+
|
121
|
+
@classmethod
|
122
|
+
def from_identifier_and_auth(
|
123
|
+
cls, identifier: str, auth: Dict[str, Any], fetch_links=False, **kwargs: Any
|
124
|
+
) -> PortalItem:
|
125
|
+
properties = cls._get_item_via_auth(identifier, auth)
|
126
|
+
return cls.from_properties(properties, auth=auth, fetch_links=fetch_links)
|
127
|
+
|
128
|
+
@classmethod
|
129
|
+
def _get_item_via_auth(
|
130
|
+
cls,
|
131
|
+
identifier: str,
|
132
|
+
auth: Dict[str, Any],
|
133
|
+
add_on: Optional[str] = "frame=object",
|
134
|
+
) -> Dict[str, Any]:
|
135
|
+
hashable_auth = cls._make_hashable_auth(auth)
|
136
|
+
return cls._get_and_cache_item_via_auth(identifier, hashable_auth, add_on)
|
137
|
+
|
138
|
+
@classmethod
|
139
|
+
def _make_hashable_auth(cls, auth: Mapping[str, str]) -> Tuple[Tuple[str, str]]:
|
140
|
+
"""Assuming nothing nested here."""
|
141
|
+
return tuple(auth.items())
|
142
|
+
|
143
|
+
@classmethod
|
144
|
+
def _undo_make_hashable_auth(
|
145
|
+
cls, hashable_auth: Tuple[Tuple[str, str]]
|
146
|
+
) -> Dict[str, Any]:
|
147
|
+
return dict(hashable_auth)
|
148
|
+
|
149
|
+
@classmethod
|
150
|
+
@lru_cache(maxsize=256)
|
151
|
+
def _get_and_cache_item_via_auth(
|
152
|
+
cls,
|
153
|
+
identifier: str,
|
154
|
+
hashable_auth: Tuple[Tuple[str, Any]],
|
155
|
+
add_on: Optional[str] = None,
|
156
|
+
) -> Dict[str, Any]:
|
157
|
+
"""Save on requests by caching items."""
|
158
|
+
auth = cls._undo_make_hashable_auth(hashable_auth)
|
159
|
+
try:
|
160
|
+
result = ff_utils.get_metadata(identifier, key=auth, add_on=add_on)
|
161
|
+
except Exception as e:
|
162
|
+
result = {}
|
163
|
+
logger.error(f"Error getting metadata for {identifier}: {e}")
|
164
|
+
return result
|
165
|
+
|
166
|
+
@classmethod
|
167
|
+
def from_identifier_and_existing_item(
|
168
|
+
cls, identifier: str, existing_item: PortalItem, **kwargs: Any
|
169
|
+
) -> PortalItem:
|
170
|
+
fetch_links = existing_item.should_fetch_links()
|
171
|
+
auth = existing_item.get_auth()
|
172
|
+
if auth:
|
173
|
+
return cls.from_identifier_and_auth(
|
174
|
+
identifier, auth, fetch_links=fetch_links
|
175
|
+
)
|
176
|
+
raise RuntimeError("Unable to fetch given identifier without auth key")
|
177
|
+
|
178
|
+
@classmethod
|
179
|
+
def from_properties_and_existing_item(
|
180
|
+
cls, properties: Dict[str, Any], existing_item: PortalItem, **kwargs: Any
|
181
|
+
) -> PortalItem:
|
182
|
+
fetch_links = existing_item.should_fetch_links()
|
183
|
+
auth = existing_item.get_auth()
|
184
|
+
return cls.from_properties(properties, fetch_links=fetch_links, auth=auth)
|
185
|
+
|
186
|
+
|
187
|
+
@dataclass(frozen=True)
|
188
|
+
class NestedProperty:
|
189
|
+
properties: Dict[str, Any]
|
190
|
+
parent_item: Optional[PortalItem] = field(default=None, hash=False)
|
191
|
+
|
192
|
+
def __repr__(self) -> str:
|
193
|
+
return f"{self.__class__.__name__}(parent={self.parent_item.__repr__()})"
|
194
|
+
|
195
|
+
def get_properties(self) -> Dict[str, Any]:
|
196
|
+
return self.properties
|
197
|
+
|
198
|
+
def get_parent_item(self) -> Union[PortalItem, None]:
|
199
|
+
return self.parent_item
|
200
|
+
|
201
|
+
def _get_link_tos(
|
202
|
+
self, link_tos: LinkTo, item_to_create: PortalItem
|
203
|
+
) -> List[Union[str, PortalItem]]:
|
204
|
+
return [self._get_link_to(link_to, item_to_create) for link_to in link_tos]
|
205
|
+
|
206
|
+
def _get_link_to(
|
207
|
+
self,
|
208
|
+
link_to: LinkTo,
|
209
|
+
item_to_create: PortalItem,
|
210
|
+
) -> Union[str, PortalItem]:
|
211
|
+
if self.parent_item:
|
212
|
+
return get_link_to(self.parent_item, link_to, item_to_create)
|
213
|
+
if isinstance(link_to, Mapping):
|
214
|
+
return item_to_create.from_properties(link_to)
|
215
|
+
return link_to
|
216
|
+
|
217
|
+
@classmethod
|
218
|
+
def from_properties(
|
219
|
+
cls,
|
220
|
+
properties: Dict[str, Any],
|
221
|
+
parent_item: Optional[PortalItem] = None,
|
222
|
+
**kwargs: Any,
|
223
|
+
) -> NestedProperty:
|
224
|
+
return cls(properties, parent_item=parent_item)
|
@@ -198,13 +198,13 @@ class EnglishUtils:
|
|
198
198
|
_PREFIX_PATTERN_FOR_A = re.compile("^(%s)" % "|".join({
|
199
199
|
"[^aeioux]", # Consonants other than x need 'a' (bicycle, dog, etc.)
|
200
200
|
"x[aeiouy]", # x followed by any vowel makes it pronounceable like a consonant (xylophone), so needs 'a'
|
201
|
-
"uni([^aeiuym]|[aeiuy][^aeiy])", # things starting with "uni" are pronounced like "yuni", so need "a"
|
201
|
+
"uni([^aeiuym]|[aeiuy][^aeiy])", # things starting with with "uni" are pronounced like "yuni", so need "a"
|
202
202
|
}), flags=re.IGNORECASE)
|
203
203
|
|
204
204
|
@classmethod
|
205
205
|
def select_a_or_an(cls, word):
|
206
206
|
"""
|
207
|
-
Uses a heuristic to try to select the appropriate article (
|
207
|
+
Uses a heuristic to try to select the appropriate article ('a' or 'an') for a given English noun.
|
208
208
|
select_a_or_an("gene") => 'a'
|
209
209
|
select_a_or_an("accession") => 'an'
|
210
210
|
"""
|
@@ -278,7 +278,7 @@ class EnglishUtils:
|
|
278
278
|
"Possible options are foo, bar and baz."
|
279
279
|
|
280
280
|
:param items: the items to enumerate
|
281
|
-
:param possible: whether to use the word 'possible' before the given kind (default True), or
|
281
|
+
:param possible: whether to use the word 'possible' before the given kind (default True), or an string to use
|
282
282
|
:param kind: the kind of items being enumerated (default "option")
|
283
283
|
:param quote: whether to put quotes around each option
|
284
284
|
:param capitalize: whether to capitalize the first letter of the sentence (default True)
|
@@ -351,7 +351,7 @@ class EnglishUtils:
|
|
351
351
|
@classmethod
|
352
352
|
def there_are(cls, items, *, kind: str = "thing", count: Optional[int] = None, there: str = "there",
|
353
353
|
capitalize=True, joiner=None, zero: object = "no", punctuate=None, punctuate_none=None,
|
354
|
-
use_article=False, show=True, context=None, tense='present',
|
354
|
+
use_article=False, show=True, context=None, tense='present',
|
355
355
|
**joiner_options) -> str:
|
356
356
|
"""
|
357
357
|
Constructs a sentence that enumerates a set of things.
|
@@ -366,7 +366,6 @@ class EnglishUtils:
|
|
366
366
|
:param punctuate: in the case of one or more values (not zero), whether to end with a period (default False)
|
367
367
|
:param punctuate_none: in the case of no values or not showing values, whether to end with a period
|
368
368
|
(default True if show is True, and otherwise is the same as the value of punctuate)
|
369
|
-
:param punctuation_mark: if specified, something to use at the end if punctuating
|
370
369
|
:param use_article: whether to put 'a' or 'an' in front of each option (default False)
|
371
370
|
:param joiner_options: additional (keyword) options to be used with a joiner function if one is supplied
|
372
371
|
:param show: whether to show the items if there are any (default True)
|
@@ -407,7 +406,7 @@ class EnglishUtils:
|
|
407
406
|
if context:
|
408
407
|
part1 += f" {context}"
|
409
408
|
if n == 0 or not show:
|
410
|
-
punctuation =
|
409
|
+
punctuation = "." if punctuate_none else ""
|
411
410
|
return part1 + punctuation
|
412
411
|
else:
|
413
412
|
if use_article:
|
@@ -418,7 +417,7 @@ class EnglishUtils:
|
|
418
417
|
joined = ", ".join(items)
|
419
418
|
else:
|
420
419
|
joined = joiner(items, **joiner_options)
|
421
|
-
punctuation =
|
420
|
+
punctuation = "." if punctuate else ""
|
422
421
|
return f"{part1}: {joined}{punctuation}"
|
423
422
|
|
424
423
|
@classmethod
|
@@ -473,7 +472,7 @@ class EnglishUtils:
|
|
473
472
|
f" of the form '<n1> <unit1> <n2> <unit2>...': {s!r}")
|
474
473
|
kwargs = {}
|
475
474
|
for i in range(len(parts) // 2):
|
476
|
-
# Canonicalize "1 week" or "1 weeks" to "weeks": 1.0 for inclusion as kwarg to timedelta
|
475
|
+
# Canonicalize "1 week" or "1 weeks" to "weeks": 1.0 for inclusion as kwarg to to timedelta
|
477
476
|
# Uses specialized knowledge that all time units don't end in "s" but pluralize with "+s"
|
478
477
|
value = float(parts[2 * i])
|
479
478
|
units = parts[2 * i + 1].rstrip(',s') + "s"
|
@@ -8,7 +8,6 @@ import warnings
|
|
8
8
|
from collections import defaultdict
|
9
9
|
from typing import Optional, List, Dict, Type
|
10
10
|
from typing_extensions import Literal
|
11
|
-
from .contribution_utils import Contributions
|
12
11
|
from .lang_utils import conjoined_list, n_of, there_are
|
13
12
|
from .misc_utils import PRINT, remove_prefix, remove_suffix, getattr_customized, CustomizableProperty
|
14
13
|
|
@@ -437,11 +436,3 @@ def confirm_no_uses(*, where: str, patterns: Dict[str, str],
|
|
437
436
|
detail += f"\n In {file}, {summarize(matches)}."
|
438
437
|
message = f"{n_of(n, 'problem')} detected:" + detail
|
439
438
|
raise AssertionError(message)
|
440
|
-
|
441
|
-
|
442
|
-
class ContributionsChecker:
|
443
|
-
|
444
|
-
@classmethod
|
445
|
-
def validate(cls):
|
446
|
-
contributions = Contributions() # no repo specified, so use current directory
|
447
|
-
contributions.show_repo_contributors(error_class=AssertionError)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
from contextlib import contextmanager
|
2
|
+
from types import ModuleType
|
3
|
+
from typing import Any, Iterator, Optional
|
4
|
+
from unittest import mock
|
5
|
+
|
6
|
+
|
7
|
+
AN_UNLIKELY_RETURN_VALUE = "unlikely return value"
|
8
|
+
|
9
|
+
|
10
|
+
@contextmanager
|
11
|
+
def patch_context(
|
12
|
+
to_patch: object,
|
13
|
+
return_value: Any = AN_UNLIKELY_RETURN_VALUE,
|
14
|
+
module: Optional[ModuleType] = None,
|
15
|
+
**kwargs,
|
16
|
+
) -> Iterator[mock.MagicMock]:
|
17
|
+
"""Mock out the given object.
|
18
|
+
|
19
|
+
Essentially mock.patch_object with some hacks to enable linting
|
20
|
+
on the object to patch instead of providing as a string.
|
21
|
+
|
22
|
+
Depending on import structure, adding the module to patch may be
|
23
|
+
required.
|
24
|
+
"""
|
25
|
+
if isinstance(to_patch, property):
|
26
|
+
to_patch = to_patch.fget
|
27
|
+
new_callable = mock.PropertyMock
|
28
|
+
else:
|
29
|
+
new_callable = mock.MagicMock
|
30
|
+
if module is None:
|
31
|
+
target = f"{to_patch.__module__}.{to_patch.__qualname__}"
|
32
|
+
else:
|
33
|
+
target = f"{module.__name__}.{to_patch.__qualname__}"
|
34
|
+
with mock.patch(target, new_callable=new_callable, **kwargs) as mocked_item:
|
35
|
+
if return_value != AN_UNLIKELY_RETURN_VALUE:
|
36
|
+
mocked_item.return_value = return_value
|
37
|
+
yield mocked_item
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "dcicutils"
|
3
|
-
version = "7.
|
3
|
+
version = "7.7.0.1b1"
|
4
4
|
description = "Utility package for interacting with the 4DN Data Portal and other 4DN resources"
|
5
5
|
authors = ["4DN-DCIC Team <support@4dnucleome.org>"]
|
6
6
|
license = "MIT"
|
@@ -70,7 +70,6 @@ coverage = ">=7.2.3"
|
|
70
70
|
# coveralls = ">=3.3.1"
|
71
71
|
flake8 = ">=3.9.2"
|
72
72
|
flaky = ">=3.7.0"
|
73
|
-
pip-licenses = "^3.5.5"
|
74
73
|
pytest = ">=4.5.0"
|
75
74
|
pytest-cov = ">=2.7.1"
|
76
75
|
pytest-mock = ">=1.11.0"
|
@@ -80,18 +79,13 @@ pytest-runner = ">=5.1"
|
|
80
79
|
|
81
80
|
[tool.poetry.scripts]
|
82
81
|
publish-to-pypi = "dcicutils.scripts.publish_to_pypi:main"
|
83
|
-
|
82
|
+
|
84
83
|
|
85
84
|
[tool.pytest.ini_options]
|
86
85
|
addopts = "--basetemp=/tmp/pytest"
|
87
86
|
redis_exec = "/usr/local/bin/redis-server"
|
88
87
|
filterwarnings = [
|
89
|
-
|
90
|
-
"ignore:distutils Version classes are deprecated. Use packaging.version instead.:DeprecationWarning",
|
91
|
-
"ignore:Setuptools is replacing distutils.:UserWarning",
|
92
|
-
# This is a pip-licenses problem (still present in 3.5.5):
|
93
|
-
"ignore:pkg_resources is deprecated as an API:DeprecationWarning",
|
94
|
-
"ignore:Boto3 will no longer support Python 3.7 starting December 13, 2023.*:",
|
88
|
+
"ignore::DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.",
|
95
89
|
]
|
96
90
|
markers = [
|
97
91
|
"working: test should work",
|
@@ -33,13 +33,12 @@ install_requires = \
|
|
33
33
|
'webtest>=2.0.34,<3.0.0']
|
34
34
|
|
35
35
|
entry_points = \
|
36
|
-
{'console_scripts': ['publish-to-pypi =
|
37
|
-
'
|
38
|
-
'dcicutils.contribution_scripts:show_contributors_main']}
|
36
|
+
{'console_scripts': ['publish-to-pypi = '
|
37
|
+
'dcicutils.scripts.publish_to_pypi:main']}
|
39
38
|
|
40
39
|
setup_kwargs = {
|
41
40
|
'name': 'dcicutils',
|
42
|
-
'version': '7.
|
41
|
+
'version': '7.7.0.1b1',
|
43
42
|
'description': 'Utility package for interacting with the 4DN Data Portal and other 4DN resources',
|
44
43
|
'long_description': '=====\nutils\n=====\n\nCheck out our full documentation `here <https://dcic-utils.readthedocs.io/en/latest/>`_\n\nThis repository contains various utility modules shared amongst several projects in the 4DN-DCIC. It is meant to be used internally by the DCIC team and externally as a Python API to `Fourfront <https://data.4dnucleome.org>`_\\ , the 4DN data portal.\n\npip installable as the ``dcicutils`` package with: ``pip install dcicutils``\n\nSee `this document <https://dcic-utils.readthedocs.io/en/latest/getting_started.html>`_ for tips on getting started. `Go here <https://dcic-utils.readthedocs.io/en/latest/examples.html>`_ for examples of some of the most useful functions.\n\n\n.. image:: https://travis-ci.org/4dn-dcic/utils.svg?branch=master\n :target: https://travis-ci.org/4dn-dcic/utils\n :alt: Build Status\n\n\n.. image:: https://coveralls.io/repos/github/4dn-dcic/utils/badge.svg?branch=master\n :target: https://coveralls.io/github/4dn-dcic/utils?branch=master\n :alt: Coverage\n\n.. image:: https://readthedocs.org/projects/dcic-utils/badge/?version=latest\n :target: https://dcic-utils.readthedocs.io/en/latest/?badge=latest\n :alt: Documentation Status\n',
|
45
44
|
'author': '4DN-DCIC Team',
|
@@ -1,39 +0,0 @@
|
|
1
|
-
import argparse
|
2
|
-
|
3
|
-
from dcicutils.command_utils import script_catch_errors, ScriptFailure
|
4
|
-
from .contribution_utils import Contributions, PROJECT_HOME
|
5
|
-
|
6
|
-
|
7
|
-
EPILOG = __doc__
|
8
|
-
|
9
|
-
|
10
|
-
def show_contributors(repo, exclude_fork=None, verbose=False, save_contributors=False, test=False):
|
11
|
-
contributions = Contributions(repo=repo, exclude_fork=exclude_fork, verbose=verbose)
|
12
|
-
if save_contributors:
|
13
|
-
contributions.save_contributor_data()
|
14
|
-
contributions.show_repo_contributors(error_class=ScriptFailure if test else None)
|
15
|
-
|
16
|
-
|
17
|
-
def show_contributors_main(*, simulated_args=None):
|
18
|
-
parser = argparse.ArgumentParser( # noqa - PyCharm wrongly thinks the formatter_class is specified wrong here.
|
19
|
-
description=(f"Show authors of a specified repository, which will be presumed"
|
20
|
-
f" to have been cloned as a subdirectory of $PROJECT_HOME ({PROJECT_HOME})"),
|
21
|
-
epilog=EPILOG,
|
22
|
-
formatter_class=argparse.RawDescriptionHelpFormatter,
|
23
|
-
)
|
24
|
-
parser.add_argument('repo', default=None,
|
25
|
-
help="name of repository to show contributors for")
|
26
|
-
parser.add_argument('--exclude', '-x', default=None,
|
27
|
-
help="name of repository that repo was forked from, whose contributors to exclude")
|
28
|
-
parser.add_argument('--save-contributors', '-s', action="store_true", default=False,
|
29
|
-
help="whether to store contributor data to CONTRIBUTORS.json")
|
30
|
-
parser.add_argument('--test', '-t', action="store_true", default=False,
|
31
|
-
help="whether to treat this as a test, erring if a cache update is needed")
|
32
|
-
parser.add_argument('--verbose', '-v', action="store_true", default=False,
|
33
|
-
help="whether to do verbose output while working")
|
34
|
-
args = parser.parse_args(args=simulated_args)
|
35
|
-
|
36
|
-
with script_catch_errors():
|
37
|
-
|
38
|
-
show_contributors(repo=args.repo, exclude_fork=args.exclude, verbose=args.verbose,
|
39
|
-
save_contributors=args.save_contributors, test=args.test)
|