Skip to content

Commit b4b3b80

Browse files
committed
Try #63:
2 parents b7f7b90 + 91943ac commit b4b3b80

File tree

5 files changed

+293
-115
lines changed

5 files changed

+293
-115
lines changed

src/AWSConfig.jl

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
"""
2+
AWSConfig
3+
4+
Most `AWSCore` functions take an `AWSConfig` object as the first argument.
5+
This type holds [`AWSCredentials`](@ref), region, and output configuration.
6+
7+
# Constructors
8+
9+
AWSConfig(; profile, creds, region, output)
10+
11+
Construct an `AWSConfig` object with the given profile, credentials, region, and output
12+
format. All keyword arguments have default values and are thus optional.
13+
14+
* `profile`: Profile name passed to [`AWSCredentials`](@ref), or `nothing` (default)
15+
* `creds`: `AWSCredentials` object, constructed using `profile` if not provided
16+
* `region`: Region, read from `AWS_DEFAULT_REGION` if present, otherwise `"us-east-1"`
17+
* `output`: Output format, defaulting to JSON (`"json"`)
18+
19+
# Examples
20+
21+
```julia-repl
22+
julia> AWSConfig(profile="example", region="ap-southeast-2")
23+
AWSConfig(creds=AWSCredentials("AKIDEXAMPLE", "wJa..."), region="ap-southeast-2", output="json")
24+
```
25+
"""
26+
mutable struct AWSConfig <: AbstractDict{Symbol,Any} # XXX: Remove subtype after deprecation
27+
creds::AWSCredentials
28+
region::String
29+
output::String
30+
# XXX: The `_extras` field will be removed after the deprecation period
31+
_extras::Dict{Symbol,Any}
32+
end
33+
34+
function AWSConfig(; profile=nothing,
35+
creds=AWSCredentials(profile=profile),
36+
region=get(ENV, "AWS_DEFAULT_REGION", "us-east-1"),
37+
output="json",
38+
kwargs...)
39+
AWSConfig(creds, region, output, kwargs)
40+
end
41+
42+
function Base.show(io::IO, conf::AWSConfig)
43+
print(io, "AWSConfig(creds=AWSCredentials(")
44+
show(io, conf.creds.access_key_id)
45+
print(io, ", \"", conf.creds.secret_key[1:3], "...\"), region=")
46+
show(io, conf.region)
47+
print(io, ", output=")
48+
show(io, conf.output)
49+
print(io, ')')
50+
if !isempty(conf._extras)
51+
println(io, "\n Additional contents (SHOULD BE REMOVED):")
52+
join(io, [string(" :", k, " => ", v) for (k, v) in conf._extras], '\n')
53+
end
54+
end
55+
56+
# Overrides needed because of the AbstractDict subtyping
57+
Base.summary(io::IO, conf::AWSConfig) = "AWSConfig"
58+
Base.show(io::IO, ::MIME{Symbol("text/plain")}, conf::AWSConfig) = show(io, conf)
59+
60+
function Base.Dict(conf::AWSConfig)
61+
d = copy(conf._extras)
62+
for f in [:creds, :region, :output]
63+
d[f] = getfield(conf, f)
64+
end
65+
d
66+
end
67+
68+
# TODO: Implement copy for AWSCredentials
69+
Base.copy(conf::AWSConfig) = AWSConfig(conf.creds, conf.region, conf.output, copy(conf._extras))
70+
71+
# Relics of using `SymbolDict`. We'll implement the entire `AbstractDict` interface
72+
# with informative deprecation messages depending on how the functions are used:
73+
# if users are storing and accessing the information that corresponds to the fields
74+
# of the type, pretend like we're just using `@deprecate`. If they try it with other
75+
# information, tell them it won't be possible soon.
76+
77+
_isfield(x::Symbol) = (x === :creds || x === :region || x === :output)
78+
79+
function _depmsg(store::Bool)
80+
if store
81+
verb = "storing"
82+
preposition = "in"
83+
else
84+
verb = "retrieving"
85+
preposition = "from"
86+
end
87+
string(verb, " information other than credentials, region, and output format ",
88+
preposition, " an `AWSConfig` object is deprecated; use another data ",
89+
"structure to store this information.")
90+
end
91+
92+
function _depsig(old::String, new::String="")
93+
s = "`" * old * "` is deprecated"
94+
if isempty(new)
95+
s *= "; in the future, no information other than credentials, region, and output " *
96+
"format will be stored in an `AWSConfig` object."
97+
else
98+
s *= ", use `" * new * "` instead."
99+
end
100+
s
101+
end
102+
103+
using Base: @deprecate, depwarn
104+
import Base: merge, merge!, keytype, valtype
105+
106+
@deprecate AWSConfig(pairs::Pair...) AWSConfig(; pairs...)
107+
@deprecate aws_config AWSConfig
108+
@deprecate merge(d::AbstractDict, conf::AWSConfig) merge(d, Dict(conf))
109+
@deprecate merge!(d::AbstractDict, conf::AWSConfig) merge!(d, Dict(conf))
110+
@deprecate keytype(conf::AWSConfig) Symbol
111+
@deprecate valtype(conf::AWSConfig) Any
112+
113+
function Base.setindex!(conf::AWSConfig, val, var::Symbol)
114+
if _isfield(var)
115+
depwarn(_depsig("setindex!(conf::AWSConfig, val, var::Symbol",
116+
"setfield!(conf, var, val)"), :setindex!)
117+
setfield!(conf, var, val)
118+
else
119+
depwarn(_depmsg(true), :setindex!)
120+
conf._extras[var] = val
121+
end
122+
end
123+
124+
function Base.getindex(conf::AWSConfig, x::Symbol)
125+
if _isfield(x)
126+
depwarn(_depsig("getindex(conf::AWSConfig, x::Symbol)",
127+
"getfield(conf, x)"), :getindex)
128+
getfield(conf, x)
129+
else
130+
depwarn(_depmsg(false), :getindex)
131+
conf._extras[x]
132+
end
133+
end
134+
135+
function Base.get(conf::AWSConfig, field::Symbol, alternative)
136+
if _isfield(field)
137+
depwarn(_depsig("get(conf::AWSConfig, field::Symbol, alternative)",
138+
"getfield(conf, field)"), :get)
139+
getfield(conf, field)
140+
else
141+
depwarn(_depmsg(false), :get)
142+
get(conf._extras, field, alternative)
143+
end
144+
end
145+
146+
function Base.haskey(conf::AWSConfig, field::Symbol)
147+
depwarn(_depsig("haskey(conf::AWSConfig, field::Symbol)"), :haskey)
148+
_isfield(field) || haskey(conf._extras, field)
149+
end
150+
151+
function Base.keys(conf::AWSConfig)
152+
depwarn(_depsig("keys(conf::AWSConfig)"), :keys)
153+
keys(Dict(conf))
154+
end
155+
156+
function Base.values(conf::AWSConfig)
157+
depwarn(_depsig("values(conf::AWSConfig)"), :values)
158+
values(Dict(conf))
159+
end
160+
161+
function Base.merge(conf::AWSConfig, d::AbstractDict{Symbol,<:Any})
162+
c = copy(conf)
163+
for (k, v) in d
164+
if _isfield(k)
165+
depwarn("`merge(conf::AWSConf, d::AbstractDict)` is deprecated, set fields " *
166+
"directly instead.", :merge)
167+
setfield!(c, k, v)
168+
else
169+
Base.depwarn(_depmsg(true), :merge)
170+
c._extras[k] = v
171+
end
172+
end
173+
c
174+
end
175+
176+
function Base.merge!(conf::AWSConfig, d::AbstractDict{Symbol,<:Any})
177+
for (k, v) in d
178+
if _isfield(k)
179+
depwarn("`merge!(conf::AWSConf, d::AbstractDict)` is deprecated, set fields " *
180+
"directly instead.", :merge!)
181+
setfield!(conf, k, v)
182+
else
183+
depwarn(_depmsg(true), :merge!)
184+
conf._extras[k] = v
185+
end
186+
end
187+
conf
188+
end
189+
190+
function Base.iterate(conf::AWSConfig, state...)
191+
depwarn("in the future, `AWSConfig` objects will not be iterable.", :iterate)
192+
iterate(Dict(conf), state...)
193+
end
194+
195+
function Base.push!(conf::AWSConfig, (k, v)::Pair{Symbol,<:Any})
196+
if _isfield(conf, k)
197+
depwarn(_depsig("push!(conf::AWSConfig, p::Pair)",
198+
"setfield!(conf, first(p), last(p))"), :push!)
199+
setfield!(conf, k, v)
200+
else
201+
Base.depwarn(_depmsg(true), :push!)
202+
push!(conf._extras, k => v)
203+
end
204+
end
205+
206+
function Base.in((k, v)::Pair, conf::AWSConfig)
207+
depwarn("`in(p::Pair, conf::AWSConfig)` is deprecated.", :in)
208+
(_isfield(k) && getfield(conf, k) == v) || in(p, conf._extras)
209+
end

0 commit comments

Comments
 (0)