1 // Copyright Daniel Wallin 2006. Use, modification and distribution is
2 // subject to the Boost Software License, Version 1.0. (See accompanying
3 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4
5 #include "boost_python.hpp"
6 #include <boost/python/tuple.hpp>
7 #include <boost/python/stl_iterator.hpp>
8 #include "bytes.hpp"
9 #include <libtorrent/torrent_handle.hpp>
10 #include <libtorrent/torrent_info.hpp>
11 #include <libtorrent/torrent_status.hpp>
12 #include <libtorrent/entry.hpp>
13 #include <libtorrent/peer_info.hpp>
14 #include "libtorrent/announce_entry.hpp"
15 #include <libtorrent/storage.hpp>
16 #include <libtorrent/disk_interface.hpp>
17 #include "gil.hpp"
18
19 using namespace boost::python;
20 using namespace lt;
21
22 #ifdef _MSC_VER
23 #pragma warning(push)
24 // warning c4996: x: was declared deprecated
25 #pragma warning( disable : 4996 )
26 #endif
27
28 namespace
29 {
30
url_seeds(torrent_handle & handle)31 list url_seeds(torrent_handle& handle)
32 {
33 list ret;
34 std::set<std::string> urls;
35 {
36 allow_threading_guard guard;
37 urls = handle.url_seeds();
38 }
39
40 for (std::set<std::string>::iterator i(urls.begin())
41 , end(urls.end()); i != end; ++i)
42 ret.append(*i);
43 return ret;
44 }
45
http_seeds(torrent_handle & handle)46 list http_seeds(torrent_handle& handle)
47 {
48 list ret;
49 std::set<std::string> urls;
50 {
51 allow_threading_guard guard;
52 urls = handle.http_seeds();
53 }
54
55 for (std::set<std::string>::iterator i(urls.begin())
56 , end(urls.end()); i != end; ++i)
57 ret.append(*i);
58 return ret;
59 }
60
piece_availability(torrent_handle & handle)61 list piece_availability(torrent_handle& handle)
62 {
63 list ret;
64 std::vector<int> avail;
65 {
66 allow_threading_guard guard;
67 handle.piece_availability(avail);
68 }
69
70 for (auto const a : avail)
71 ret.append(a);
72 return ret;
73 }
74
piece_priorities(torrent_handle & handle)75 list piece_priorities(torrent_handle& handle)
76 {
77 list ret;
78 std::vector<download_priority_t> prio;
79 {
80 allow_threading_guard guard;
81 prio = handle.get_piece_priorities();
82 }
83
84 for (auto const p : prio)
85 ret.append(p);
86 return ret;
87 }
88
89 } // namespace unnamed
90
file_progress(torrent_handle & handle,int flags)91 list file_progress(torrent_handle& handle, int flags)
92 {
93 std::vector<std::int64_t> p;
94
95 {
96 allow_threading_guard guard;
97 std::shared_ptr<const torrent_info> ti = handle.torrent_file();
98 if (ti)
99 {
100 p.reserve(ti->num_files());
101 handle.file_progress(p, flags);
102 }
103 }
104
105 list result;
106
107 for (std::vector<std::int64_t>::iterator i(p.begin()), e(p.end()); i != e; ++i)
108 result.append(*i);
109
110 return result;
111 }
112
get_peer_info(torrent_handle const & handle)113 list get_peer_info(torrent_handle const& handle)
114 {
115 std::vector<peer_info> pi;
116
117 {
118 allow_threading_guard guard;
119 handle.get_peer_info(pi);
120 }
121
122 list result;
123
124 for (std::vector<peer_info>::iterator i = pi.begin(); i != pi.end(); ++i)
125 result.append(*i);
126
127 return result;
128 }
129
130 namespace
131 {
132 template <typename T>
extract_fn(object o)133 T extract_fn(object o)
134 {
135 return boost::python::extract<T>(o);
136 }
137 }
138
prioritize_pieces(torrent_handle & info,object o)139 void prioritize_pieces(torrent_handle& info, object o)
140 {
141 stl_input_iterator<object> begin(o), end;
142 if (begin == end) return;
143
144 // determine which overload should be selected. the one taking a list of
145 // priorities or the one taking a list of piece -> priority mappings
146 bool const is_piece_list = extract<std::pair<piece_index_t, download_priority_t>>(*begin).check();
147
148 if (is_piece_list)
149 {
150 std::vector<std::pair<piece_index_t, download_priority_t>> piece_list;
151 std::transform(begin, end, std::back_inserter(piece_list)
152 , &extract_fn<std::pair<piece_index_t, download_priority_t>>);
153 info.prioritize_pieces(piece_list);
154 }
155 else
156 {
157 std::vector<download_priority_t> priority_vector;
158 std::transform(begin, end, std::back_inserter(priority_vector)
159 , &extract_fn<download_priority_t>);
160 info.prioritize_pieces(priority_vector);
161 }
162 }
163
prioritize_files(torrent_handle & info,object o)164 void prioritize_files(torrent_handle& info, object o)
165 {
166 stl_input_iterator<download_priority_t> begin(o), end;
167 info.prioritize_files(std::vector<download_priority_t>(begin, end));
168 }
169
file_priorities(torrent_handle & handle)170 list file_priorities(torrent_handle& handle)
171 {
172 list ret;
173 std::vector<download_priority_t> priorities = handle.get_file_priorities();
174
175 for (auto const p : priorities)
176 ret.append(p);
177
178 return ret;
179 }
180
file_prioritity0(torrent_handle & h,file_index_t index)181 download_priority_t file_prioritity0(torrent_handle& h, file_index_t index)
182 {
183 return h.file_priority(index);
184 }
185
file_prioritity1(torrent_handle & h,file_index_t index,download_priority_t prio)186 void file_prioritity1(torrent_handle& h, file_index_t index, download_priority_t prio)
187 {
188 return h.file_priority(index, prio);
189 }
190
dict_to_announce_entry(dict d,announce_entry & ae)191 void dict_to_announce_entry(dict d, announce_entry& ae)
192 {
193 ae.url = extract<std::string>(d["url"]);
194 if (d.has_key("tier"))
195 ae.tier = extract<std::uint8_t>(d["tier"]);
196 if (d.has_key("fail_limit"))
197 ae.fail_limit = extract<std::uint8_t>(d["fail_limit"]);
198 }
199
replace_trackers(torrent_handle & h,object trackers)200 void replace_trackers(torrent_handle& h, object trackers)
201 {
202 object iter(trackers.attr("__iter__")());
203
204 std::vector<announce_entry> result;
205
206 for (;;)
207 {
208 handle<> entry(allow_null(PyIter_Next(iter.ptr())));
209
210 if (entry == handle<>())
211 break;
212
213 if (extract<announce_entry>(object(entry)).check())
214 {
215 result.push_back(extract<announce_entry>(object(entry)));
216 }
217 else
218 {
219 dict d;
220 d = extract<dict>(object(entry));
221 announce_entry ae;
222 dict_to_announce_entry(d, ae);
223 result.push_back(ae);
224 }
225 }
226
227 allow_threading_guard guard;
228 h.replace_trackers(result);
229 }
230
add_tracker(torrent_handle & h,dict d)231 void add_tracker(torrent_handle& h, dict d)
232 {
233 announce_entry ae;
234 dict_to_announce_entry(d, ae);
235 h.add_tracker(ae);
236 }
237
238 namespace
239 {
240 #if defined BOOST_ASIO_HAS_STD_CHRONO
241 using std::chrono::system_clock;
242 #else
243 using boost::chrono::system_clock;
244 #endif
245
to_ptime(time_point tpt)246 time_t to_ptime(time_point tpt)
247 {
248 return system_clock::to_time_t(system_clock::now()
249 + duration_cast<system_clock::duration>(tpt - clock_type::now()));
250 }
251 }
252
trackers(torrent_handle & h)253 list trackers(torrent_handle& h)
254 {
255 list ret;
256 std::vector<announce_entry> const trackers = h.trackers();
257 for (std::vector<announce_entry>::const_iterator i = trackers.begin(), end(trackers.end()); i != end; ++i)
258 {
259 dict d;
260 d["url"] = i->url;
261 d["trackerid"] = i->trackerid;
262 d["tier"] = i->tier;
263 d["fail_limit"] = i->fail_limit;
264 d["source"] = i->source;
265 d["verified"] = i->verified;
266
267 #if TORRENT_ABI_VERSION == 1
268 if (!i->endpoints.empty())
269 {
270 announce_endpoint const& aep = i->endpoints.front();
271 d["message"] = aep.message;
272 dict last_error;
273 last_error["value"] = aep.last_error.value();
274 last_error["category"] = aep.last_error.category().name();
275 d["last_error"] = last_error;
276 if (aep.next_announce > min_time()) {
277 d["next_announce"] = to_ptime(aep.next_announce);
278 }
279 else {
280 d["next_announce"] = object();
281 }
282 if (aep.min_announce > min_time()) {
283 d["min_announce"] = to_ptime(aep.min_announce);
284 }
285 else {
286 d["min_announce"] = object();
287 }
288 d["scrape_incomplete"] = aep.scrape_incomplete;
289 d["scrape_complete"] = aep.scrape_complete;
290 d["scrape_downloaded"] = aep.scrape_downloaded;
291 d["fails"] = aep.fails;
292 d["updating"] = aep.updating;
293 d["start_sent"] = aep.start_sent;
294 d["complete_sent"] = aep.complete_sent;
295 }
296 else
297 {
298 d["message"] = std::string();
299 dict last_error;
300 last_error["value"] = 0;
301 last_error["category"] = "";
302 d["last_error"] = last_error;
303 d["next_announce"] = object();
304 d["min_announce"] = object();
305 d["scrape_incomplete"] = 0;
306 d["scrape_complete"] = 0;
307 d["scrape_downloaded"] = 0;
308 d["fails"] = 0;
309 d["updating"] = false;
310 d["start_sent"] = false;
311 d["complete_sent"] = false;
312 }
313 #endif
314
315 list aeps;
316 for (auto const& aep : i->endpoints)
317 {
318 dict e;
319 e["message"] = aep.message;
320 e["local_address"] = boost::python::make_tuple(aep.local_endpoint.address().to_string(), aep.local_endpoint.port());
321 dict last_error;
322 last_error["value"] = aep.last_error.value();
323 last_error["category"] = aep.last_error.category().name();
324 e["last_error"] = last_error;
325 if (aep.next_announce > min_time()) {
326 e["next_announce"] = to_ptime(aep.next_announce);
327 }
328 else {
329 e["next_announce"] = object();
330 }
331 if (aep.min_announce > min_time()) {
332 e["min_announce"] = to_ptime(aep.min_announce);
333 }
334 else {
335 e["min_announce"] = object();
336 }
337 e["scrape_incomplete"] = aep.scrape_incomplete;
338 e["scrape_complete"] = aep.scrape_complete;
339 e["scrape_downloaded"] = aep.scrape_downloaded;
340 e["fails"] = aep.fails;
341 e["updating"] = aep.updating;
342 e["start_sent"] = aep.start_sent;
343 e["complete_sent"] = aep.complete_sent;
344 aeps.append(e);
345 }
346 d["endpoints"] = aeps;
347
348 #if TORRENT_ABI_VERSION == 1
349 d["send_stats"] = i->send_stats;
350 #endif
351 ret.append(d);
352 }
353 return ret;
354 }
355
get_download_queue(torrent_handle & handle)356 list get_download_queue(torrent_handle& handle)
357 {
358 list ret;
359
360 std::vector<partial_piece_info> downloading;
361
362 {
363 allow_threading_guard guard;
364 handle.get_download_queue(downloading);
365 }
366
367 for (std::vector<partial_piece_info>::iterator i = downloading.begin()
368 , end(downloading.end()); i != end; ++i)
369 {
370 dict partial_piece;
371 partial_piece["piece_index"] = i->piece_index;
372 partial_piece["blocks_in_piece"] = i->blocks_in_piece;
373 list block_list;
374 for (int k = 0; k < i->blocks_in_piece; ++k)
375 {
376 dict block_info;
377 block_info["state"] = i->blocks[k].state;
378 block_info["num_peers"] = i->blocks[k].num_peers;
379 block_info["bytes_progress"] = i->blocks[k].bytes_progress;
380 block_info["block_size"] = i->blocks[k].block_size;
381 block_info["peer"] = boost::python::make_tuple(
382 i->blocks[k].peer().address().to_string()
383 , i->blocks[k].peer().port());
384 block_list.append(block_info);
385 }
386 partial_piece["blocks"] = block_list;
387
388 ret.append(partial_piece);
389 }
390
391 return ret;
392 }
393
set_metadata(torrent_handle & handle,std::string const & buf)394 void set_metadata(torrent_handle& handle, std::string const& buf)
395 {
396 handle.set_metadata(buf);
397 }
398
399 #if TORRENT_ABI_VERSION == 1
400
get_torrent_info(torrent_handle const & h)401 std::shared_ptr<const torrent_info> get_torrent_info(torrent_handle const& h)
402 {
403 allow_threading_guard guard;
404 return h.torrent_file();
405 }
406
407 #endif // TORRENT_ABI_VERSION
408
add_piece_str(torrent_handle & th,piece_index_t piece,char const * data,add_piece_flags_t const flags)409 void add_piece_str(torrent_handle& th, piece_index_t piece, char const *data
410 , add_piece_flags_t const flags)
411 {
412 th.add_piece(piece, data, flags);
413 }
414
add_piece_bytes(torrent_handle & th,piece_index_t piece,bytes data,add_piece_flags_t const flags)415 void add_piece_bytes(torrent_handle& th, piece_index_t piece, bytes data
416 , add_piece_flags_t const flags)
417 {
418 th.add_piece(piece, data.arr.c_str(), flags);
419 }
420
421 class dummy5 {};
422 class dummy {};
423 class dummy4 {};
424 class dummy6 {};
425 class dummy7 {};
426 class dummy8 {};
427 class dummy15 {};
428
429 using by_value = return_value_policy<return_by_value>;
bind_torrent_handle()430 void bind_torrent_handle()
431 {
432 // arguments are: number of seconds and tracker index
433 void (torrent_handle::*force_reannounce0)(int, int, reannounce_flags_t) const = &torrent_handle::force_reannounce;
434
435 #if TORRENT_ABI_VERSION == 1
436 bool (torrent_handle::*super_seeding0)() const = &torrent_handle::super_seeding;
437 void (torrent_handle::*super_seeding1)(bool) const = &torrent_handle::super_seeding;
438 #endif
439 void (torrent_handle::*set_flags0)(torrent_flags_t) const = &torrent_handle::set_flags;
440 void (torrent_handle::*set_flags1)(torrent_flags_t, torrent_flags_t) const = &torrent_handle::set_flags;
441
442 download_priority_t (torrent_handle::*piece_priority0)(piece_index_t) const = &torrent_handle::piece_priority;
443 void (torrent_handle::*piece_priority1)(piece_index_t, download_priority_t) const = &torrent_handle::piece_priority;
444
445 void (torrent_handle::*move_storage0)(std::string const&, lt::move_flags_t) const = &torrent_handle::move_storage;
446 void (torrent_handle::*rename_file0)(file_index_t, std::string const&) const = &torrent_handle::rename_file;
447
448 #if TORRENT_ABI_VERSION == 1
449 #ifdef TORRENT_WINDOWS
450 void (torrent_handle::*move_storage1)(std::wstring const&, int) const = &torrent_handle::move_storage;
451 void (torrent_handle::*rename_file1)(file_index_t, std::wstring const&) const = &torrent_handle::rename_file;
452 #endif
453 #endif
454
455 std::vector<open_file_state> (torrent_handle::*file_status0)() const = &torrent_handle::file_status;
456
457 #define _ allow_threads
458
459 enum_<move_flags_t>("move_flags_t")
460 .value("always_replace_files", move_flags_t::always_replace_files)
461 .value("fail_if_exist", move_flags_t::fail_if_exist)
462 .value("dont_replace", move_flags_t::dont_replace)
463 ;
464
465 #if TORRENT_ABI_VERSION == 1
466 enum_<deprecated_move_flags_t>("deprecated_move_flags_t")
467 .value("always_replace_files", deprecated_move_flags_t::always_replace_files)
468 .value("fail_if_exist", deprecated_move_flags_t::fail_if_exist)
469 .value("dont_replace", deprecated_move_flags_t::dont_replace)
470 ;
471 #endif
472
473 {
474 scope s = class_<torrent_handle>("torrent_handle")
475 .def(self == self)
476 .def(self != self)
477 .def(self < self)
478 .def("__hash__", (std::size_t (*)(torrent_handle const&))&libtorrent::hash_value)
479 .def("get_peer_info", get_peer_info)
480 .def("status", _(&torrent_handle::status), arg("flags") = 0xffffffff)
481 .def("get_download_queue", get_download_queue)
482 .def("file_progress", file_progress, arg("flags") = 0)
483 .def("trackers", trackers)
484 .def("replace_trackers", replace_trackers)
485 .def("add_tracker", add_tracker)
486 .def("add_url_seed", _(&torrent_handle::add_url_seed))
487 .def("remove_url_seed", _(&torrent_handle::remove_url_seed))
488 .def("url_seeds", url_seeds)
489 .def("add_http_seed", _(&torrent_handle::add_http_seed))
490 .def("remove_http_seed", _(&torrent_handle::remove_http_seed))
491 .def("http_seeds", http_seeds)
492 .def("torrent_file", _(&torrent_handle::torrent_file))
493 .def("set_metadata", set_metadata)
494 .def("is_valid", _(&torrent_handle::is_valid))
495 .def("pause", _(&torrent_handle::pause), arg("flags") = 0)
496 .def("resume", _(&torrent_handle::resume))
497 .def("clear_error", _(&torrent_handle::clear_error))
498 .def("queue_position", _(&torrent_handle::queue_position))
499 .def("queue_position_up", _(&torrent_handle::queue_position_up))
500 .def("queue_position_down", _(&torrent_handle::queue_position_down))
501 .def("queue_position_top", _(&torrent_handle::queue_position_top))
502 .def("queue_position_bottom", _(&torrent_handle::queue_position_bottom))
503
504 .def("add_piece", add_piece_str)
505 .def("add_piece", add_piece_bytes)
506 .def("read_piece", _(&torrent_handle::read_piece))
507 .def("have_piece", _(&torrent_handle::have_piece))
508 .def("set_piece_deadline", _(&torrent_handle::set_piece_deadline)
509 , (arg("index"), arg("deadline"), arg("flags") = 0))
510 .def("reset_piece_deadline", _(&torrent_handle::reset_piece_deadline), (arg("index")))
511 .def("clear_piece_deadlines", _(&torrent_handle::clear_piece_deadlines), (arg("index")))
512 .def("piece_availability", &piece_availability)
513 .def("piece_priority", _(piece_priority0))
514 .def("piece_priority", _(piece_priority1))
515 .def("prioritize_pieces", &prioritize_pieces)
516 .def("get_piece_priorities", &piece_priorities)
517 .def("prioritize_files", &prioritize_files)
518 .def("get_file_priorities", &file_priorities)
519 .def("file_priority", &file_prioritity0)
520 .def("file_priority", &file_prioritity1)
521 .def("file_status", _(file_status0))
522 .def("save_resume_data", _(&torrent_handle::save_resume_data), arg("flags") = 0)
523 .def("need_save_resume_data", _(&torrent_handle::need_save_resume_data))
524 .def("force_reannounce", _(force_reannounce0)
525 , (arg("seconds") = 0, arg("tracker_idx") = -1, arg("flags") = reannounce_flags_t{}))
526 #ifndef TORRENT_DISABLE_DHT
527 .def("force_dht_announce", _(&torrent_handle::force_dht_announce))
528 #endif
529 .def("scrape_tracker", _(&torrent_handle::scrape_tracker), arg("index") = -1)
530 .def("flush_cache", &torrent_handle::flush_cache)
531 .def("set_upload_limit", _(&torrent_handle::set_upload_limit))
532 .def("upload_limit", _(&torrent_handle::upload_limit))
533 .def("set_download_limit", _(&torrent_handle::set_download_limit))
534 .def("download_limit", _(&torrent_handle::download_limit))
535 .def("connect_peer", &torrent_handle::connect_peer, (arg("endpoint"), arg("source")=0, arg("flags")=0xd))
536 .def("set_max_uploads", &torrent_handle::set_max_uploads)
537 .def("max_uploads", _(&torrent_handle::max_uploads))
538 .def("set_max_connections", &torrent_handle::set_max_connections)
539 .def("max_connections", _(&torrent_handle::max_connections))
540 .def("move_storage", _(move_storage0), (arg("path"), arg("flags") = move_flags_t::always_replace_files))
541 .def("info_hash", _(&torrent_handle::info_hash))
542 .def("force_recheck", _(&torrent_handle::force_recheck))
543 .def("rename_file", _(rename_file0))
544 .def("set_ssl_certificate", &torrent_handle::set_ssl_certificate, (arg("cert"), arg("private_key"), arg("dh_params"), arg("passphrase")=""))
545 .def("flags", _(&torrent_handle::flags))
546 .def("set_flags", _(set_flags0))
547 .def("set_flags", _(set_flags1))
548 .def("unset_flags", _(&torrent_handle::unset_flags))
549 // deprecated
550 #if TORRENT_ABI_VERSION == 1
551 .def("piece_priorities", &piece_priorities)
552 .def("file_priorities", &file_priorities)
553 .def("stop_when_ready", _(&torrent_handle::stop_when_ready))
554 .def("super_seeding", super_seeding1)
555 .def("auto_managed", _(&torrent_handle::auto_managed))
556 .def("set_priority", _(&torrent_handle::set_priority))
557 .def("get_torrent_info", &get_torrent_info)
558 .def("super_seeding", super_seeding0)
559 .def("write_resume_data", _(&torrent_handle::write_resume_data))
560 .def("is_seed", _(&torrent_handle::is_seed))
561 .def("is_finished", _(&torrent_handle::is_finished))
562 .def("has_metadata", _(&torrent_handle::has_metadata))
563 .def("use_interface", &torrent_handle::use_interface)
564 .def("name", _(&torrent_handle::name))
565 .def("is_paused", _(&torrent_handle::is_paused))
566 .def("is_auto_managed", _(&torrent_handle::is_auto_managed))
567 .def("set_upload_mode", _(&torrent_handle::set_upload_mode))
568 .def("set_share_mode", _(&torrent_handle::set_share_mode))
569 .def("apply_ip_filter", &torrent_handle::apply_ip_filter)
570 .def("set_sequential_download", _(&torrent_handle::set_sequential_download))
571 .def("set_peer_upload_limit", &torrent_handle::set_peer_upload_limit)
572 .def("set_peer_download_limit", &torrent_handle::set_peer_download_limit)
573 .def("set_ratio", _(&torrent_handle::set_ratio))
574 .def("save_path", _(&torrent_handle::save_path))
575 .def("set_tracker_login", &torrent_handle::set_tracker_login)
576 #ifdef TORRENT_WINDOWS
577 .def("move_storage", _(move_storage1), (arg("path"), arg("flags") = always_replace_files))
578 .def("rename_file", _(rename_file1))
579 #endif
580 #endif
581 ;
582
583 s.attr("ignore_min_interval") = torrent_handle::ignore_min_interval;
584 s.attr("overwrite_existing") = torrent_handle::overwrite_existing;
585 s.attr("piece_granularity") = int(torrent_handle::piece_granularity);
586 s.attr("graceful_pause") = torrent_handle::graceful_pause;
587 s.attr("flush_disk_cache") = torrent_handle::flush_disk_cache;
588 s.attr("save_info_dict") = torrent_handle::save_info_dict;
589 s.attr("only_if_modified") = torrent_handle::only_if_modified;
590 s.attr("alert_when_available") = torrent_handle::alert_when_available;
591 s.attr("query_distributed_copies") = torrent_handle::query_distributed_copies;
592 s.attr("query_accurate_download_counters") = torrent_handle::query_accurate_download_counters;
593 s.attr("query_last_seen_complete") = torrent_handle::query_last_seen_complete;
594 s.attr("query_pieces") = torrent_handle::query_pieces;
595 s.attr("query_verified_pieces") = torrent_handle::query_verified_pieces;
596 }
597
598 class_<open_file_state>("open_file_state")
599 .add_property("file_index", make_getter((&open_file_state::file_index), by_value()))
600 .def_readonly("last_use", &open_file_state::last_use)
601 .def_readonly("open_mode", &open_file_state::open_mode)
602 ;
603
604 {
605 scope s = class_<dummy>("file_open_mode");
606 s.attr("read_only") = file_open_mode::read_only;
607 s.attr("write_only") = file_open_mode::write_only;
608 s.attr("read_write") = file_open_mode::read_write;
609 s.attr("rw_mask") = file_open_mode::rw_mask;
610 s.attr("sparse") = file_open_mode::sparse;
611 s.attr("no_atime") = file_open_mode::no_atime;
612 s.attr("random_access") = file_open_mode::random_access;
613 #if TORRENT_ABI_VERSION == 1
614 s.attr("locked") = 0;
615 #endif
616 }
617
618 enum_<torrent_handle::file_progress_flags_t>("file_progress_flags")
619 .value("piece_granularity", torrent_handle::piece_granularity)
620 ;
621
622 {
623 scope s = class_<dummy6>("add_piece_flags_t");
624 s.attr("overwrite_existing") = torrent_handle::overwrite_existing;
625 }
626
627 {
628 scope s = class_<dummy7>("pause_flags_t");
629 s.attr("graceful_pause") = torrent_handle::graceful_pause;
630 }
631
632 {
633 scope s = class_<dummy4>("save_resume_flags_t");
634 s.attr("flush_disk_cache") = torrent_handle::flush_disk_cache;
635 s.attr("save_info_dict") = torrent_handle::save_info_dict;
636 s.attr("only_if_modified") = torrent_handle::only_if_modified;
637 }
638
639 {
640 scope s = class_<dummy15>("reannounce_flags_t");
641 s.attr("ignore_min_interval") = torrent_handle::ignore_min_interval;
642 }
643
644 {
645 scope s = class_<dummy8>("deadline_flags_t");
646 s.attr("alert_when_available") = torrent_handle::alert_when_available;
647 }
648
649 {
650 scope s = class_<dummy5>("status_flags_t");
651 s.attr("query_distributed_copies") = torrent_handle::query_distributed_copies;
652 s.attr("query_accurate_download_counters") = torrent_handle::query_accurate_download_counters;
653 s.attr("query_last_seen_complete") = torrent_handle::query_last_seen_complete;
654 s.attr("query_pieces") = torrent_handle::query_pieces;
655 s.attr("query_verified_pieces") = torrent_handle::query_verified_pieces;
656 }
657
658 }
659
660 #ifdef _MSC_VER
661 #pragma warning(pop)
662 #endif
663