timer-bot 1.7__tar.gz → 1.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,11 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ 1.8 (2024-12-01)
5
+ ----------------
6
+
7
+ - Upgrade to discord-py-interactions 5.13
8
+
4
9
  1.7 (2024-02-06)
5
10
  ----------------
6
11
 
@@ -1,28 +1,26 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: timer-bot
3
- Version: 1.7
4
- Summary: "Discord Timer Bot",
5
- Home-page: http://github.com/lionel-panhaleux/timer-bot
6
- Author: lionelpx
7
- Author-email: lionel.panhaleux@gmail.com
8
- License: "MIT"
9
- Keywords: discord game timer
10
- Classifier: Development Status :: 4 - Beta
3
+ Version: 1.8
4
+ Summary: Discord Timer Bot
5
+ Author-email: Lionel Panhaleux <lionel.panhaleux+timer@gmail.com>
6
+ Project-URL: Repository, https://github.com/lionel-panhaleux/timer-bot
7
+ Keywords: Discord,timer
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Development Status :: 5 - Production/Stable
11
12
  Classifier: Intended Audience :: Other Audience
12
13
  Classifier: Natural Language :: English
13
14
  Classifier: Operating System :: OS Independent
14
- Classifier: Environment :: Console
15
- Classifier: Programming Language :: Python :: 3
16
- Classifier: Programming Language :: Python :: 3.11
17
- Classifier: Topic :: Other/Nonlisted Topic
15
+ Classifier: Environment :: Web Environment
16
+ Requires-Python: >=3.11
18
17
  Description-Content-Type: text/markdown
19
18
  License-File: LICENSE
20
- Requires-Dist: discord-py-interactions<5
19
+ Requires-Dist: discord-py-interactions>5.13
20
+ Requires-Dist: uvloop>0.21
21
21
  Provides-Extra: dev
22
22
  Requires-Dist: black; extra == "dev"
23
- Requires-Dist: doc8; extra == "dev"
24
- Requires-Dist: flake8; extra == "dev"
25
- Requires-Dist: pytest; extra == "dev"
23
+ Requires-Dist: ruff; extra == "dev"
26
24
  Requires-Dist: zest.releaser[recommended]; extra == "dev"
27
25
 
28
26
  # timer
@@ -0,0 +1,40 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "timer-bot"
7
+ version = "1.8"
8
+ authors = [
9
+ { name = "Lionel Panhaleux", email = "lionel.panhaleux+timer@gmail.com" },
10
+ ]
11
+ description = "Discord Timer Bot"
12
+ keywords = ["Discord", "timer"]
13
+ readme = "README.md"
14
+ requires-python = ">=3.11"
15
+ classifiers = [
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.11",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Development Status :: 5 - Production/Stable",
20
+ "Intended Audience :: Other Audience",
21
+ "Natural Language :: English",
22
+ "Operating System :: OS Independent",
23
+ "Environment :: Web Environment",
24
+ ]
25
+ dependencies = ["discord-py-interactions>5.13", "uvloop>0.21"]
26
+
27
+ [project.optional-dependencies]
28
+ dev = ["black", "ruff", "zest.releaser[recommended]"]
29
+
30
+ [project.scripts]
31
+ timer-bot = "src.timer_bot:main"
32
+
33
+ [project.urls]
34
+ Repository = "https://github.com/lionel-panhaleux/timer-bot"
35
+
36
+ [tool.setuptools.packages.find]
37
+ include = ["src*"]
38
+
39
+ [tool.zest-releaser]
40
+ create-wheel = true
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -5,19 +5,35 @@ import os
5
5
 
6
6
  import interactions
7
7
 
8
+ import interactions.api.events
9
+ import interactions.client.errors
10
+
8
11
 
9
12
  logger = logging.getLogger()
10
13
  bot = interactions.Client(
11
14
  token=os.getenv("DISCORD_TOKEN") or "",
12
- intents=interactions.Intents.DEFAULT,
15
+ # intents=interactions.Intents.new(guild_messages=True),
16
+ delete_unused_application_cmds=True,
17
+ debug_scope=161406117686149120 if __debug__ else interactions.MISSING,
18
+ logging_level=logging.DEBUG if __debug__ else logging.INFO,
13
19
  )
14
- TIMERS = {}
15
20
 
16
21
 
17
- @bot.event
22
+ @interactions.listen()
18
23
  async def on_ready():
19
24
  """Login success"""
20
- logger.info(f"Logged in as {bot.me.name}")
25
+ logger.info(f"Logged in as {bot.user.username}")
26
+
27
+
28
+ @interactions.listen()
29
+ async def on_startup():
30
+ """Startup success"""
31
+ logger.info(f"Started")
32
+
33
+
34
+ @interactions.listen()
35
+ async def on_error(error: interactions.api.events.Error):
36
+ logger.error("API error: %s", error)
21
37
 
22
38
 
23
39
  #: fixed list of times on which to send a notification
@@ -49,39 +65,47 @@ RUNNING_TIMER_HELP = (
49
65
  class Timer:
50
66
  """Timer object: one per channel"""
51
67
 
52
- def __init__(self, channel, author, time, secured, log_prefix=""):
68
+ def __init__(
69
+ self,
70
+ channel: interactions.GuildChannel,
71
+ author: interactions.Member,
72
+ time: int,
73
+ secured: bool,
74
+ log_prefix: str = "",
75
+ ):
53
76
  self.channel = channel
54
77
  self.author = author
55
78
  self.secured = secured
56
- self.start_time = 0
57
- self.total_time = time
58
- self.time_left = time
79
+ self.start_time: float = 0
80
+ self.total_time: int = 0
81
+ self.time_left: float = 0
59
82
  self.log_prefix = log_prefix + "|internal"
60
- self.thresholds = []
61
- for limit in THRESHOLDS:
62
- if time > limit:
63
- self.thresholds.append(limit)
64
- # add a threshold on every hour
65
- for limit in range(1, time // 3600 + 1):
66
- self.thresholds.append(limit * 3600)
83
+ self.thresholds: list[int] = []
84
+ self.adjust_time(time)
67
85
  # internals
68
86
  self.message: Optional[interactions.Message] = None
69
87
  self.countdown_future = None # waiting for time to refresh
70
88
  self.resume_future = None # waiting for resume
71
89
 
90
+ def adjust_time(self, time: int):
91
+ self.total_time += time
92
+ self.time_left += time
93
+ self.thresholds = [limit for limit in THRESHOLDS if self.time_left > limit]
94
+ # add a threshold on every hour
95
+ for limit in range(1, int(self.time_left // 3600) + 1):
96
+ self.thresholds.append(limit * 3600)
97
+
72
98
  async def countdown(self):
73
99
  """Countdown: update embed, send notifications"""
74
100
  while self.time_left > 0:
75
101
  # update time_left
76
102
  if not self.resume_future:
77
- self.time_left = max(
78
- 0,
79
- self.total_time - max(0, bot._loop.time() - self.start_time),
80
- )
103
+ time_spent = max(0, asyncio.get_event_loop().time() - self.start_time)
104
+ self.time_left = max(0, self.total_time - time_spent)
81
105
  await self._send_or_update_message()
82
106
  # update frequency depends on time left
83
107
  if self.resume_future:
84
- paused_time = bot._loop.time()
108
+ paused_time = asyncio.get_event_loop().time()
85
109
  try:
86
110
  logging.debug(f"[{self.log_prefix}] Wait for resume")
87
111
  await self.resume_future
@@ -92,7 +116,7 @@ class Timer:
92
116
  finally: # in any case resume.
93
117
  logging.debug(f"[{self.log_prefix}] Timer resume")
94
118
  self.resume_future = None
95
- self.start_time += bot._loop.time() - paused_time
119
+ self.start_time += asyncio.get_event_loop().time() - paused_time
96
120
  else:
97
121
  if self.time_left < DISPLAY_SECONDS + 30:
98
122
  # minimum because of Discord rate limitation
@@ -113,7 +137,7 @@ class Timer:
113
137
  """Run the timer, update the client.TIMERS map accordingly."""
114
138
  logging.debug(f"[{self.log_prefix}] Run")
115
139
  TIMERS[self.channel] = self
116
- self.start_time = bot._loop.time()
140
+ self.start_time = asyncio.get_event_loop().time()
117
141
  try:
118
142
  await self.countdown()
119
143
  except asyncio.CancelledError:
@@ -191,19 +215,22 @@ class Timer:
191
215
  embeds = [interactions.Embed(title=title, description=description)]
192
216
  if self.message:
193
217
  try:
194
- await self.message.edit(embeds=embeds, components=components)
218
+ self.message = await self.message.edit(
219
+ embeds=embeds, components=components
220
+ )
195
221
  # messages older than 1h cannot be edited too much, at some point it fails
196
- except interactions.LibraryException as e:
222
+ except interactions.errors.LibraryException as e:
197
223
  logger.info("Failed to edit message: %s", e)
198
224
  old_message = self.message
199
225
  self.message = await self.channel.send(
200
226
  embeds=embeds, components=components
201
227
  )
202
- try:
203
- await old_message.delete()
204
- except interactions.LibraryException as e:
205
- logger.info("Failed to delete old message: %s", e)
206
- pass
228
+ if old_message:
229
+ try:
230
+ await old_message.delete()
231
+ except interactions.errors.LibraryException as e:
232
+ logger.info("Failed to delete old message: %s", e)
233
+ pass
207
234
  else:
208
235
  self.message = await self.channel.send(embeds=embeds, components=components)
209
236
  if self.thresholds and self.thresholds[-1] >= self.time_left >= 0:
@@ -236,29 +263,15 @@ class Timer:
236
263
  return "time!"
237
264
 
238
265
 
239
- @bot.event(name="on_message_create")
240
- async def on_message_create(message: interactions.Message):
241
- """Main message loop"""
242
- if message.author.id == bot.me.id:
243
- return
244
-
245
- if message.content.lower().startswith("timer "):
246
- await message.reply(
247
- "This bot switched to slash commands. Use `/timer` instead."
248
- )
249
-
266
+ TIMERS: dict[interactions.Snowflake : Timer] = {}
267
+ timer_base = interactions.SlashCommand(name="timer")
250
268
 
251
- @bot.command(name="timer")
252
- async def base_timer_command(ctx: interactions.CommandContext):
253
- pass
254
269
 
255
-
256
- def _get_prefix(ctx: interactions.CommandContext):
270
+ def _get_prefix(ctx: interactions.SlashContext):
257
271
  """Prefix used for log messages"""
258
272
  if ctx.guild:
259
273
  prefix = f"{ctx.guild.name}"
260
274
  logger.debug("CTX: %s", ctx)
261
- logger.debug("extras: %s", ctx._extras)
262
275
  logger.debug("channel: %s", ctx.channel)
263
276
  logger.debug("channel_id: %s", ctx.channel_id)
264
277
  if ctx.channel:
@@ -268,36 +281,34 @@ def _get_prefix(ctx: interactions.CommandContext):
268
281
  return prefix
269
282
 
270
283
 
271
- @base_timer_command.subcommand(
272
- name="start",
273
- description="Start a timer",
274
- options=[
275
- interactions.Option(
276
- name="hours",
277
- description="Number of hours",
278
- type=interactions.OptionType.INTEGER,
279
- required=True,
280
- min_value=0,
281
- max_value=24,
282
- ),
283
- interactions.Option(
284
- name="minutes",
285
- description="Number of minutes",
286
- type=interactions.OptionType.INTEGER,
287
- required=False,
288
- min_value=0,
289
- max_value=59,
290
- ),
291
- interactions.Option(
292
- name="secured",
293
- description="Only the owner can modify a secure timer (default false)",
294
- type=interactions.OptionType.BOOLEAN,
295
- required=False,
296
- ),
297
- ],
284
+ @timer_base.subcommand(
285
+ sub_cmd_name="start",
286
+ sub_cmd_description="Start a timer",
287
+ )
288
+ @interactions.slash_option(
289
+ name="hours",
290
+ opt_type=interactions.OptionType.INTEGER,
291
+ description="Number of hours",
292
+ required=True,
293
+ min_value=0,
294
+ max_value=24,
295
+ )
296
+ @interactions.slash_option(
297
+ name="minutes",
298
+ opt_type=interactions.OptionType.INTEGER,
299
+ description="Number of minutes",
300
+ required=False,
301
+ min_value=0,
302
+ max_value=59,
303
+ )
304
+ @interactions.slash_option(
305
+ name="secured",
306
+ opt_type=interactions.OptionType.BOOLEAN,
307
+ description="Only the owner can modify a secure timer (default false)",
308
+ required=False,
298
309
  )
299
310
  async def timer_start(
300
- ctx: interactions.CommandContext,
311
+ ctx: interactions.SlashContext,
301
312
  hours: int,
302
313
  minutes: int = 0,
303
314
  secured: bool = False,
@@ -306,9 +317,7 @@ async def timer_start(
306
317
  # channel info will miss from threads and voice channels chats
307
318
  # see https://github.com/interactions-py/library/issues/1041
308
319
  if ctx.channel is interactions.MISSING:
309
- ctx.channel = interactions.Channel(
310
- _client=ctx.client, **(await ctx.client.get_channel(ctx.channel_id))
311
- )
320
+ ctx.channel = await ctx.client.get_channel(ctx.channel_id)
312
321
  prefix = _get_prefix(ctx)
313
322
  # timer already running in channel
314
323
  if ctx.channel_id in TIMERS:
@@ -329,7 +338,7 @@ async def timer_start(
329
338
  logger.info(f"[{prefix}] Start timer: {hours}h {minutes}min")
330
339
  try:
331
340
  await timer.run()
332
- except interactions.LibraryException:
341
+ except interactions.client.errors.LibraryException:
333
342
  await ctx.edit(
334
343
  "**Failed to start**\nTimer bot requires permission to send messages"
335
344
  )
@@ -346,39 +355,37 @@ async def timer_start(
346
355
  )
347
356
 
348
357
 
349
- @base_timer_command.subcommand(name="pause", description="pause the timer")
350
- async def timer_pause(ctx: interactions.CommandContext):
358
+ @timer_base.subcommand(sub_cmd_name="pause", sub_cmd_description="pause the timer")
359
+ async def timer_pause(ctx: interactions.SlashContext):
351
360
  """Pause the timer"""
352
361
  await _pause_timer(ctx)
353
362
 
354
363
 
355
- @base_timer_command.subcommand(name="resume", description="resume the timer")
356
- async def timer_resume(ctx: interactions.CommandContext):
364
+ @timer_base.subcommand(sub_cmd_name="resume", sub_cmd_description="resume the timer")
365
+ async def timer_resume(ctx: interactions.SlashContext):
357
366
  """Resume the timer"""
358
367
  await _resume_timer(ctx)
359
368
 
360
369
 
361
- @base_timer_command.subcommand(name="stop", description="stop the timer")
362
- async def timer_stop(ctx: interactions.CommandContext):
370
+ @timer_base.subcommand(sub_cmd_name="stop", sub_cmd_description="stop the timer")
371
+ async def timer_stop(ctx: interactions.SlashContext):
363
372
  """Stop the timer"""
364
373
  await _stop_timer(ctx)
365
374
 
366
375
 
367
- @base_timer_command.subcommand(
368
- name="add",
369
- description="Add time",
370
- options=[
371
- interactions.Option(
372
- name="minutes",
373
- description="Number of minutes",
374
- type=interactions.OptionType.INTEGER,
375
- required=True,
376
- min_value=1,
377
- max_value=1440,
378
- ),
379
- ],
376
+ @timer_base.subcommand(
377
+ sub_cmd_name="add",
378
+ sub_cmd_description="Add time",
380
379
  )
381
- async def timer_add(ctx: interactions.CommandContext, minutes: int):
380
+ @interactions.slash_option(
381
+ name="minutes",
382
+ opt_type=interactions.OptionType.INTEGER,
383
+ description="Number of minutes",
384
+ required=True,
385
+ min_value=1,
386
+ max_value=1440,
387
+ )
388
+ async def timer_add(ctx: interactions.SlashContext, minutes: int):
382
389
  """Add time to the timer"""
383
390
  timer = TIMERS.get(ctx.channel, None)
384
391
  if not timer:
@@ -393,29 +400,25 @@ async def timer_add(ctx: interactions.CommandContext, minutes: int):
393
400
  "This is a secured timer, only the owner can modify it.", ephemeral=True
394
401
  )
395
402
  return
396
- time = minutes * 60
397
- timer.total_time += time
398
- timer.time_left += time
403
+ timer.adjust_time(minutes * 60)
399
404
  await timer.refresh(resume=False)
400
- logger.info(f"[{prefix}] Added {time//60}min and refreshed")
405
+ logger.info(f"[{prefix}] Added {minutes}min and refreshed")
401
406
  await ctx.send(f"Time added ({minutes}min)")
402
407
 
403
408
 
404
- @base_timer_command.subcommand(
405
- name="sub",
406
- description="Substract time",
407
- options=[
408
- interactions.Option(
409
- name="minutes",
410
- description="Number of minutes",
411
- type=interactions.OptionType.INTEGER,
412
- required=True,
413
- min_value=1,
414
- max_value=1440,
415
- ),
416
- ],
409
+ @timer_base.subcommand(
410
+ sub_cmd_name="sub",
411
+ sub_cmd_description="Substract time",
412
+ )
413
+ @interactions.slash_option(
414
+ name="minutes",
415
+ opt_type=interactions.OptionType.INTEGER,
416
+ description="Number of minutes",
417
+ required=True,
418
+ min_value=1,
419
+ max_value=1440,
417
420
  )
418
- async def timer_sub(ctx: interactions.CommandContext, minutes: int):
421
+ async def timer_sub(ctx: interactions.SlashContext, minutes: int):
419
422
  """Substract time from the timer"""
420
423
  timer = TIMERS.get(ctx.channel, None)
421
424
  if not timer:
@@ -430,16 +433,16 @@ async def timer_sub(ctx: interactions.CommandContext, minutes: int):
430
433
  "This is a secured timer, only the owner can modify it.", ephemeral=True
431
434
  )
432
435
  return
433
- time = minutes * 60
434
- timer.total_time -= time
435
- timer.time_left -= time
436
+ timer.adjust_time(-minutes * 60)
436
437
  await timer.refresh(resume=False)
437
- logger.info(f"[{prefix}] Substracted {time//60}min and refreshed")
438
+ logger.info(f"[{prefix}] Substracted {minutes}min and refreshed")
438
439
  await ctx.send(f"Time substracted ({minutes}min)")
439
440
 
440
441
 
441
- @base_timer_command.subcommand(name="display", description="Display the timer anew")
442
- async def timer_display(ctx: interactions.CommandContext):
442
+ @timer_base.subcommand(
443
+ sub_cmd_name="display", sub_cmd_description="Display the timer anew"
444
+ )
445
+ async def timer_display(ctx: interactions.SlashContext):
443
446
  """Discplay the timer anew"""
444
447
  timer = TIMERS.get(ctx.channel, None)
445
448
  if not timer:
@@ -458,41 +461,41 @@ button_pause = interactions.Button(
458
461
  style=interactions.ButtonStyle.PRIMARY,
459
462
  label="Pause",
460
463
  custom_id="pause",
461
- emoji=interactions.Emoji(name="⏱"),
464
+ emoji=interactions.PartialEmoji.from_str("⏱"),
462
465
  )
463
466
 
464
467
  button_resume = interactions.Button(
465
468
  style=interactions.ButtonStyle.SUCCESS,
466
469
  label="Resume",
467
470
  custom_id="resume",
468
- emoji=interactions.Emoji(name="▶️"),
471
+ emoji=interactions.PartialEmoji.from_str("▶️"),
469
472
  )
470
473
 
471
474
  button_stop = interactions.Button(
472
475
  style=interactions.ButtonStyle.DANGER,
473
476
  label="Stop",
474
477
  custom_id="stop",
475
- emoji=interactions.Emoji(name="🛑"),
478
+ emoji=interactions.PartialEmoji.from_str("🛑"),
476
479
  )
477
480
 
478
481
 
479
- @bot.component("pause")
482
+ @interactions.component_callback("pause")
480
483
  async def button_pause_response(ctx: interactions.ComponentContext):
481
484
  await _pause_timer(ctx)
482
485
 
483
486
 
484
- @bot.component("resume")
487
+ @interactions.component_callback("resume")
485
488
  async def button_resume_response(ctx: interactions.ComponentContext):
486
489
  await _resume_timer(ctx)
487
490
 
488
491
 
489
- @bot.component("stop")
492
+ @interactions.component_callback("stop")
490
493
  async def button_stop_response(ctx: interactions.ComponentContext):
491
494
  await _stop_timer(ctx)
492
495
 
493
496
 
494
497
  async def _pause_timer(
495
- ctx: Union[interactions.CommandContext, interactions.ComponentContext]
498
+ ctx: Union[interactions.SlashContext, interactions.ComponentContext]
496
499
  ):
497
500
  timer = TIMERS.get(ctx.channel, None)
498
501
  if not timer:
@@ -519,7 +522,7 @@ async def _pause_timer(
519
522
 
520
523
 
521
524
  async def _resume_timer(
522
- ctx: Union[interactions.CommandContext, interactions.ComponentContext]
525
+ ctx: Union[interactions.SlashContext, interactions.ComponentContext]
523
526
  ):
524
527
  timer = TIMERS.get(ctx.channel, None)
525
528
  if not timer:
@@ -540,7 +543,7 @@ async def _resume_timer(
540
543
 
541
544
 
542
545
  async def _stop_timer(
543
- ctx: Union[interactions.CommandContext, interactions.ComponentContext]
546
+ ctx: Union[interactions.SlashContext, interactions.ComponentContext]
544
547
  ):
545
548
  timer = TIMERS.get(ctx.channel, None)
546
549
  if not timer:
@@ -558,6 +561,20 @@ async def _stop_timer(
558
561
  await ctx.send("Timer stopped", ephemeral=True)
559
562
 
560
563
 
564
+ bot.add_listener(on_ready)
565
+ bot.add_listener(on_startup)
566
+ bot.add_command(timer_start)
567
+ bot.add_command(timer_stop)
568
+ bot.add_command(timer_pause)
569
+ bot.add_command(timer_resume)
570
+ bot.add_command(timer_display)
571
+ bot.add_command(timer_add)
572
+ bot.add_command(timer_sub)
573
+ bot.add_component_callback(button_pause_response)
574
+ bot.add_component_callback(button_resume_response)
575
+ bot.add_component_callback(button_stop_response)
576
+
577
+
561
578
  def main():
562
579
  """Entrypoint"""
563
580
  logger.addHandler(logging.StreamHandler())
@@ -2,7 +2,6 @@ CHANGELOG.rst
2
2
  LICENSE
3
3
  MANIFEST.in
4
4
  README.md
5
- setup.cfg
6
- setup.py
5
+ pyproject.toml
7
6
  src/__init__.py
8
7
  src/timer_bot.py
timer-bot-1.7/setup.cfg DELETED
@@ -1,68 +0,0 @@
1
- [metadata]
2
- name = timer-bot
3
- version = 1.7
4
- author = lionelpx
5
- author_email = lionel.panhaleux@gmail.com
6
- url = http://github.com/lionel-panhaleux/timer-bot
7
- description = "Discord Timer Bot",
8
- long_description = file: README.md
9
- long_description_content_type = text/markdown
10
- license = "MIT"
11
- keywords = discord game timer
12
- classifiers =
13
- Development Status :: 4 - Beta
14
- Intended Audience :: Other Audience
15
- Natural Language :: English
16
- Operating System :: OS Independent
17
- Environment :: Console
18
- Programming Language :: Python :: 3
19
- Programming Language :: Python :: 3.11
20
- Topic :: Other/Nonlisted Topic
21
-
22
- [options]
23
- zip_safe = True
24
- include_package_data = True
25
- packages = find:
26
- setup_requires =
27
- setuptools
28
- install_requires =
29
- discord-py-interactions<5
30
-
31
- [options.entry_points]
32
- console_scripts =
33
- timer-bot = src.timer_bot:main
34
-
35
- [options.extras_require]
36
- dev =
37
- black
38
- doc8
39
- flake8
40
- pytest
41
- zest.releaser[recommended]
42
-
43
- [options.packages.find]
44
- exclude =
45
- tests
46
-
47
- [flake8]
48
- max-line-length = 88
49
- exclude = build, dist
50
- ignore = E203, W503
51
-
52
- [bdist_wheel]
53
- python-tag = py3
54
-
55
- [distutils]
56
- index-servers = pypi
57
-
58
- [tool:pytest]
59
- filterwarnings =
60
- ignore:.*format string will parse more strictly.*:DeprecationWarning
61
-
62
- [zest.releaser]
63
- create-wheel = yes
64
-
65
- [egg_info]
66
- tag_build =
67
- tag_date = 0
68
-
timer-bot-1.7/setup.py DELETED
@@ -1,4 +0,0 @@
1
- import setuptools
2
-
3
-
4
- setuptools.setup()
File without changes
File without changes
File without changes
File without changes