Skip to content

Commit 49b8200

Browse files
author
Andrew J Westlake
committed
Fixed cfg(feature = ...) conditions
1 parent 4fa9eca commit 49b8200

File tree

5 files changed

+172
-35
lines changed

5 files changed

+172
-35
lines changed

pyo3-asyncio-macros/src/lib.rs

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,32 @@ pub fn tokio_main(args: TokenStream, item: TokenStream) -> TokenStream {
107107
tokio::main(args, item, true)
108108
}
109109

110+
/// Registers an `async-std` test with the `pyo3-asyncio` test harness.
111+
///
112+
/// This attribute is meant to mirror the `#[test]` attribute and allow you to mark a function for
113+
/// testing within an integration test. Like the `#[async_std::test]` attribute, it will accept
114+
/// `async` test functions, but it will also accept blocking functions as well.
115+
///
116+
/// # Examples
117+
/// ```ignore
118+
/// use std::{time::Duration, thread};
119+
///
120+
/// use pyo3::prelude::*;
121+
///
122+
/// // async test function
123+
/// #[pyo3_asyncio::async_std::test]
124+
/// async fn test_async_sleep() -> PyResult<()> {
125+
/// async_std::task::sleep(Duration::from_secs(1)).await;
126+
/// Ok(())
127+
/// }
128+
///
129+
/// // blocking test function
130+
/// #[pyo3_asyncio::async_std::test]
131+
/// fn test_blocking_sleep() -> PyResult<()> {
132+
/// thread::sleep(Duration::from_secs(1));
133+
/// Ok(())
134+
/// }
135+
/// ```
110136
#[cfg(not(test))] // NOTE: exporting main breaks tests, we should file an issue.
111137
#[proc_macro_attribute]
112138
pub fn async_std_test(_attr: TokenStream, item: TokenStream) -> TokenStream {
@@ -153,6 +179,32 @@ pub fn async_std_test(_attr: TokenStream, item: TokenStream) -> TokenStream {
153179
result.into()
154180
}
155181

182+
/// Registers a `tokio` test with the `pyo3-asyncio` test harness.
183+
///
184+
/// This attribute is meant to mirror the `#[test]` attribute and allow you to mark a function for
185+
/// testing within an integration test. Like the `#[tokio::test]` attribute, it will accept `async`
186+
/// test functions, but it will also accept blocking functions as well.
187+
///
188+
/// # Examples
189+
/// ```ignore
190+
/// use std::{time::Duration, thread};
191+
///
192+
/// use pyo3::prelude::*;
193+
///
194+
/// // async test function
195+
/// #[pyo3_asyncio::tokio::test]
196+
/// async fn test_async_sleep() -> PyResult<()> {
197+
/// tokio::time::sleep(Duration::from_secs(1)).await;
198+
/// Ok(())
199+
/// }
200+
///
201+
/// // blocking test function
202+
/// #[pyo3_asyncio::tokio::test]
203+
/// fn test_blocking_sleep() -> PyResult<()> {
204+
/// thread::sleep(Duration::from_secs(1));
205+
/// Ok(())
206+
/// }
207+
/// ```
156208
#[cfg(not(test))] // NOTE: exporting main breaks tests, we should file an issue.
157209
#[proc_macro_attribute]
158210
pub fn tokio_test(_attr: TokenStream, item: TokenStream) -> TokenStream {
@@ -247,6 +299,30 @@ impl Parse for TestMainArgs {
247299
}
248300
}
249301

302+
/// Provides the custom `Test` structure for the `pyo3-asyncio` `#[test]` attributes
303+
///
304+
/// This macro _must_ be expanded at the root of the test crate. Its main purpose is to manage the
305+
/// boilerplate for the `inventory` crate.
306+
///
307+
/// The following `test_main!()` macro:
308+
///
309+
/// ```ignore
310+
/// pyo3_asyncio::testing::test_main!(#[pyo3_asyncio::async_std::main], "Example Test Suite");
311+
/// ```
312+
///
313+
/// Is equivalent to this expansion:
314+
///
315+
/// ```ignore
316+
/// use pyo3::prelude::*;
317+
///
318+
/// pyo3_asyncio::testing::test_structs!();
319+
///
320+
/// #[pyo3_asyncio::async_std::main]
321+
/// async fn main() -> PyResult<()> {
322+
/// pyo3_asyncio::testing::test_main_body!("Example Test Suite");
323+
/// Ok(())
324+
/// }
325+
/// ```
250326
#[cfg(not(test))]
251327
#[proc_macro]
252328
pub fn test_structs(_args: TokenStream) -> TokenStream {
@@ -272,6 +348,30 @@ pub fn test_structs(_args: TokenStream) -> TokenStream {
272348
result.into()
273349
}
274350

351+
/// Expands the `pyo3-asyncio` test harness call within the `main` fn.
352+
///
353+
/// This macro collects the test structures from the `inventory` boilerplate and forwards them to
354+
/// the test harness.
355+
///
356+
/// The following `test_main!()` macro:
357+
///
358+
/// ```ignore
359+
/// pyo3_asyncio::testing::test_main!(#[pyo3_asyncio::async_std::main], "Example Test Suite");
360+
/// ```
361+
///
362+
/// Is equivalent to this expansion:
363+
///
364+
/// ```ignore
365+
/// use pyo3::prelude::*;
366+
///
367+
/// pyo3_asyncio::testing::test_structs!();
368+
///
369+
/// #[pyo3_asyncio::async_std::main]
370+
/// async fn main() -> PyResult<()> {
371+
/// pyo3_asyncio::testing::test_main_body!("Example Test Suite");
372+
/// Ok(())
373+
/// }
374+
/// ```
275375
#[cfg(not(test))]
276376
#[proc_macro]
277377
pub fn test_main_body(args: TokenStream) -> TokenStream {
@@ -281,13 +381,31 @@ pub fn test_main_body(args: TokenStream) -> TokenStream {
281381
let args = pyo3_asyncio::testing::parse_args(#suite_name);
282382

283383
pyo3_asyncio::testing::test_harness(
284-
inventory::iter::<Test>().map(|test| test.clone()).collect(), args
384+
inventory::iter::<crate::Test>().map(|test| test.clone()).collect(), args
285385
)
286386
.await?;
287387
};
288388
result.into()
289389
}
290390

391+
/// The standard `pyo3-asyncio` test harness `main` fn boilerplate.
392+
///
393+
/// This macro combines the `test_structs!` and `test_main_body!` macros to provide the full
394+
/// boilerplate for the `pyo3-asyncio` test harness in one line.
395+
///
396+
/// # Examples
397+
///
398+
/// `test_main!` for the `tokio` runtime:
399+
/// ```ignore
400+
/// # #[cfg(all(feature = "tokio-runtime", feature = "attributes"))]
401+
/// pyo3_asyncio::testing::test_main!(#[pyo3_asyncio::tokio::main], "Example Test Suite");
402+
/// ```
403+
///
404+
/// `test_main!` for the `async-std` runtime:
405+
/// ```ignore
406+
/// # #[cfg(all(feature = "async-std-runtime", feature = "attributes"))]
407+
/// pyo3_asyncio::testing::test_main!(#[pyo3_asyncio::async_std::main], "Example Test Suite");
408+
/// ```
291409
#[cfg(not(test))]
292410
#[proc_macro]
293411
pub fn test_main(args: TokenStream) -> TokenStream {

src/async_std.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ use pyo3::prelude::*;
55

66
use crate::generic::{self, JoinError, Runtime};
77

8-
/// <span class="module-item stab portability" style="display: inline; border-radius: 3px; padding: 2px; font-size: 80%; line-height: 1.2;"><code>attributes</code></span> Sets up the `async-std` runtime and runs an async fn as main
8+
/// <span class="module-item stab portability" style="display: inline; border-radius: 3px; padding: 2px; font-size: 80%; line-height: 1.2;"><code>attributes</code></span> Provides the boilerplate for the `async-std` runtime and runs an async fn as main
99
#[cfg(feature = "attributes")]
1010
pub use pyo3_asyncio_macros::async_std_main as main;
1111

12-
/// <span class="module-item stab portability" style="display: inline; border-radius: 3px; padding: 2px; font-size: 80%; line-height: 1.2;"><code>attributes</code></span> Registers an `async-std` test with the `pyo3-asyncio` test harness
13-
#[cfg(feature = "attributes")]
12+
/// <span class="module-item stab portability" style="display: inline; border-radius: 3px; padding: 2px; font-size: 80%; line-height: 1.2;"><code>attributes</code></span>
13+
/// <span class="module-item stab portability" style="display: inline; border-radius: 3px; padding: 2px; font-size: 80%; line-height: 1.2;"><code>testing</code></span>
14+
/// Registers an `async-std` test with the `pyo3-asyncio` test harness
15+
#[cfg(all(feature = "attributes", feature = "testing"))]
1416
pub use pyo3_asyncio_macros::async_std_test as test;
1517

1618
struct AsyncStdJoinError;

src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ pub mod doc_test {
130130
};
131131
}
132132

133-
#[cfg(feature = "async-std-runtime attributes")]
133+
#[cfg(all(feature = "async-std-runtime", feature = "attributes"))]
134134
doctest!("../README.md", readme_md);
135135
}
136136

@@ -403,10 +403,10 @@ fn dump_err(py: Python<'_>) -> impl FnOnce(PyErr) + '_ {
403403

404404
/// Alias crate as pyo3_asyncio for test_structs! macro expansion
405405
#[cfg(test)]
406-
#[cfg(feature = "testing attributes")]
406+
#[cfg(all(feature = "testing", feature = "attributes"))]
407407
use crate as pyo3_asyncio;
408408

409409
// Expand test structs in crate root to allow lib tests to be compile-checked (but not ran)
410410
#[cfg(test)]
411-
#[cfg(feature = "testing attributes")]
411+
#[cfg(all(feature = "testing", feature = "attributes"))]
412412
testing::test_structs!();

src/testing.rs

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@
3030
//! [`#[pyo3_asyncio::async_std::test]`](crate::async_std::test) and run them automatically.
3131
//!
3232
//! `pytests/test_example.rs` for the `tokio` runtime:
33-
//! ```
34-
//! # #[cfg(feature = "tokio-runtime attributes")]
33+
//! ```ignore
34+
//! # #[cfg(all(feature = "tokio-runtime", feature = "attributes"))]
3535
//! pyo3_asyncio::testing::test_main!(#[pyo3_asyncio::tokio::main], "Example Test Suite");
3636
//! ```
3737
//!
3838
//! `pytests/test_example.rs` for the `async-std` runtime:
39-
//! ```
40-
//! # #[cfg(feature = "async-std-runtime attributes")]
39+
//! ```ignore
40+
//! # #[cfg(all(feature = "async-std-runtime", feature = "attributes"))]
4141
//! pyo3_asyncio::testing::test_main!(#[pyo3_asyncio::async_std::main], "Example Test Suite");
4242
//! ```
4343
//!
@@ -73,7 +73,7 @@
7373
//!
7474
//! For `async-std` use the [`pyo3_asyncio::async_std::test`](crate::async_std::test) attribute:
7575
//! ```
76-
//! # #[cfg(feature = "async-std-runtime attributes")]
76+
//! # #[cfg(all(feature = "async-std-runtime", feature = "attributes"))]
7777
//! # mod tests {
7878
//! use std::{time::Duration, thread};
7979
//!
@@ -96,23 +96,27 @@
9696
//! #
9797
//! # // Doctests don't detect main fn when using the test_main!() macro, so we expand it into the
9898
//! # // components of that macro instead.
99-
//! # #[cfg(feature = "async-std-runtime attributes")]
99+
//! #
100+
//! # #[cfg(all(feature = "async-std-runtime", feature = "attributes"))]
101+
//! # use pyo3::prelude::*;
102+
//! #
103+
//! # #[cfg(all(feature = "async-std-runtime", feature = "attributes"))]
100104
//! # pyo3_asyncio::testing::test_structs!();
101105
//! #
102-
//! # #[cfg(feature = "async-std-runtime attributes")]
106+
//! # #[cfg(all(feature = "async-std-runtime", feature = "attributes"))]
103107
//! # #[pyo3_asyncio::async_std::main]
104108
//! # async fn main() -> pyo3::PyResult<()> {
105109
//! # pyo3_asyncio::testing::test_main_body!("Example Test Suite");
106110
//! #
107111
//! # Ok(())
108112
//! # }
109-
//! # #[cfg(not(feature = "async-std-runtime attributes"))]
113+
//! # #[cfg(not(all(feature = "async-std-runtime", feature = "attributes")))]
110114
//! # fn main() {}
111115
//! ```
112116
//!
113117
//! For `tokio` use the [`pyo3_asyncio::tokio::test`](crate::tokio::test) attribute:
114118
//! ```
115-
//! # #[cfg(feature = "tokio-runtime attributes")]
119+
//! # #[cfg(all(feature = "tokio-runtime", feature = "attributes"))]
116120
//! # mod tests {
117121
//! use std::{time::Duration, thread};
118122
//!
@@ -135,17 +139,20 @@
135139
//! #
136140
//! # // Doctests don't detect main fn when using the test_main!() macro, so we expand it into the
137141
//! # // components of that macro instead.
138-
//! # #[cfg(feature = "tokio-runtime attributes")]
142+
//! # #[cfg(all(feature = "tokio-runtime", feature = "attributes"))]
143+
//! # use pyo3::prelude::*;
144+
//! #
145+
//! # #[cfg(all(feature = "tokio-runtime", feature = "attributes"))]
139146
//! # pyo3_asyncio::testing::test_structs!();
140147
//! #
141-
//! # #[cfg(feature = "tokio-runtime attributes")]
148+
//! # #[cfg(all(feature = "tokio-runtime", feature = "attributes"))]
142149
//! # #[pyo3_asyncio::tokio::main]
143150
//! # async fn main() -> PyResult<()> {
144151
//! # pyo3_asyncio::testing::test_main_body!("Example Test Suite");
145152
//! #
146153
//! # Ok(())
147154
//! # }
148-
//! # #[cfg(not(feature = "tokio-runtime attributes"))]
155+
//! # #[cfg(not(all(feature = "tokio-runtime", feature = "attributes")))]
149156
//! # fn main() {}
150157
//! ```
151158
//!
@@ -172,37 +179,43 @@
172179
//!
173180
//! `my-crate/src/lib.rs`
174181
//! ```
175-
//! # #[cfg(any(feature = "async-std-runtime attributes", feature = "tokio-runtime attributes"))]
182+
//! # #[cfg(all(
183+
//! # any(feature = "async-std-runtime", feature = "tokio-runtime"),
184+
//! # feature = "attributes"
185+
//! # ))]
176186
//! pyo3_asyncio::testing::test_structs!();
177187
//!
178-
//! # #[cfg(any(feature = "async-std-runtime attributes", feature = "tokio-runtime attributes"))]
188+
//! # #[cfg(all(
189+
//! # any(feature = "async-std-runtime", feature = "tokio-runtime"),
190+
//! # feature = "attributes"
191+
//! # ))]
179192
//! mod tests {
180193
//! use pyo3::prelude::*;
181-
//!
182-
//! use crate as pyo3_asyncio;
183194
//!
184-
//! # #[cfg(feature = "async-std-runtime attributes")]
195+
//! # #[cfg(feature = "async-std-runtime")]
185196
//! #[pyo3_asyncio::async_std::test]
186197
//! async fn test_async_std_async_test_compiles() -> PyResult<()> {
187198
//! Ok(())
188199
//! }
189-
//! # #[cfg(feature = "async-std-runtime attributes")]
200+
//! # #[cfg(feature = "async-std-runtime")]
190201
//! #[pyo3_asyncio::async_std::test]
191202
//! fn test_async_std_sync_test_compiles() -> PyResult<()> {
192203
//! Ok(())
193204
//! }
194205
//!
195-
//! # #[cfg(feature = "tokio-runtime attributes")]
206+
//! # #[cfg(feature = "tokio-runtime")]
196207
//! #[pyo3_asyncio::tokio::test]
197208
//! async fn test_tokio_async_test_compiles() -> PyResult<()> {
198209
//! Ok(())
199210
//! }
200-
//! # #[cfg(feature = "tokio-runtime attributes")]
211+
//! # #[cfg(feature = "tokio-runtime")]
201212
//! #[pyo3_asyncio::tokio::test]
202213
//! fn test_tokio_sync_test_compiles() -> PyResult<()> {
203214
//! Ok(())
204215
//! }
205216
//! }
217+
//!
218+
//! # fn main() {}
206219
//! ```
207220
//!
208221
//! #### Expanding `test_main!()` for Doc Tests
@@ -223,27 +236,26 @@
223236
//!
224237
//! The following `test_main!()` macro:
225238
//!
226-
//! ```
227-
//! # #[cfg(feature = "async-std-runtime attributes")]
239+
//! ```ignore
228240
//! pyo3_asyncio::testing::test_main!(#[pyo3_asyncio::async_std::main], "Example Test Suite");
229241
//! ```
230242
//!
231243
//! Is equivalent to this expansion:
232244
//!
233245
//! ```
234-
//! # #[cfg(feature = "async-std-runtime attributes")]
246+
//! # #[cfg(all(feature = "async-std-runtime", feature = "attributes"))]
235247
//! use pyo3::prelude::*;
236248
//!
237-
//! # #[cfg(feature = "async-std-runtime attributes")]
249+
//! # #[cfg(all(feature = "async-std-runtime", feature = "attributes"))]
238250
//! pyo3_asyncio::testing::test_structs!();
239251
//!
240-
//! # #[cfg(feature = "async-std-runtime attributes")]
252+
//! # #[cfg(all(feature = "async-std-runtime", feature = "attributes"))]
241253
//! #[pyo3_asyncio::async_std::main]
242254
//! async fn main() -> PyResult<()> {
243255
//! pyo3_asyncio::testing::test_main_body!("Example Test Suite");
244256
//! Ok(())
245257
//! }
246-
//! # #[cfg(not(feature = "async-std-runtime attributes"))]
258+
//! # #[cfg(not(all(feature = "async-std-runtime", feature = "attributes")))]
247259
//! # fn main() {}
248260
//! ```
249261
@@ -254,14 +266,17 @@ use futures::stream::{self, StreamExt};
254266
use pyo3::prelude::*;
255267

256268
/// <span class="module-item stab portability" style="display: inline; border-radius: 3px; padding: 2px; font-size: 80%; line-height: 1.2;"><code>attributes</code></span>
269+
/// Provides the boilerplate for the `pyo3-asyncio` test harness in one line
257270
#[cfg(feature = "attributes")]
258271
pub use pyo3_asyncio_macros::test_main;
259272

260273
/// <span class="module-item stab portability" style="display: inline; border-radius: 3px; padding: 2px; font-size: 80%; line-height: 1.2;"><code>attributes</code></span>
274+
/// Provides the `Test` structure and the `inventory` boilerplate for the `pyo3-asyncio` test harness
261275
#[cfg(feature = "attributes")]
262276
pub use pyo3_asyncio_macros::test_structs;
263277

264278
/// <span class="module-item stab portability" style="display: inline; border-radius: 3px; padding: 2px; font-size: 80%; line-height: 1.2;"><code>attributes</code></span>
279+
/// Expands the `pyo3-asyncio` test harness call within the `main` fn
265280
#[cfg(feature = "attributes")]
266281
pub use pyo3_asyncio_macros::test_main_body;
267282

0 commit comments

Comments
 (0)