rtutil: Add RTDateTime class.
See comments for rationale.
This commit is contained in:
		
							parent
							
								
									9e33b2795c
								
							
						
					
					
						commit
						7335282e5a
					
				
					 3 changed files with 58 additions and 0 deletions
				
			
		|  | @ -5,6 +5,7 @@ | ||||||
| # Full copyright and licensing details can be found at toplevel file | # Full copyright and licensing details can be found at toplevel file | ||||||
| # LICENSE.txt in the repository. | # LICENSE.txt in the repository. | ||||||
| 
 | 
 | ||||||
|  | import datetime | ||||||
| import functools | import functools | ||||||
| import logging | import logging | ||||||
| import mimetypes | import mimetypes | ||||||
|  | @ -13,6 +14,7 @@ import re | ||||||
| import sqlite3 | import sqlite3 | ||||||
| import urllib.parse as urlparse | import urllib.parse as urlparse | ||||||
| 
 | 
 | ||||||
|  | import dateutil.parser | ||||||
| import rt | import rt | ||||||
| 
 | 
 | ||||||
| from pathlib import Path | from pathlib import Path | ||||||
|  | @ -21,6 +23,7 @@ from . import data | ||||||
| from beancount.core import data as bc_data | from beancount.core import data as bc_data | ||||||
| 
 | 
 | ||||||
| from typing import ( | from typing import ( | ||||||
|  |     cast, | ||||||
|     overload, |     overload, | ||||||
|     Callable, |     Callable, | ||||||
|     Iterable, |     Iterable, | ||||||
|  | @ -40,6 +43,28 @@ TicketAttachmentIds = Tuple[str, Optional[str]] | ||||||
| _LinkCache = MutableMapping[TicketAttachmentIds, Optional[str]] | _LinkCache = MutableMapping[TicketAttachmentIds, Optional[str]] | ||||||
| _URLLookup = Callable[..., Optional[str]] | _URLLookup = Callable[..., Optional[str]] | ||||||
| 
 | 
 | ||||||
|  | class RTDateTime(datetime.datetime): | ||||||
|  |     """Construct datetime objects from strings returned by RT | ||||||
|  | 
 | ||||||
|  |     Typical usage looks like:: | ||||||
|  | 
 | ||||||
|  |         ticket = rt_client.get_ticket(...) | ||||||
|  |         created = RTDateTime(ticket.get('Created')) | ||||||
|  |     """ | ||||||
|  |     # Normally I'd just write a function to do this, but having a dedicated | ||||||
|  |     # class helps support query-report: the class can pull double duty to both | ||||||
|  |     # parse the data from RT, and determine proper output formatting. | ||||||
|  |     # The RT REST API returns datetimes in the user's configured timezone, and | ||||||
|  |     # there doesn't seem to be any API call that tells you what that is. You | ||||||
|  |     # have to live with the object being timezone-naive. | ||||||
|  |     def __new__(cls, source: str) -> 'RTDateTime': | ||||||
|  |         if not source or source == 'Not set': | ||||||
|  |             retval = datetime.datetime.min | ||||||
|  |         else: | ||||||
|  |             retval = dateutil.parser.parse(source) | ||||||
|  |         return cast(RTDateTime, retval) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| class RTLinkCache(_LinkCache): | class RTLinkCache(_LinkCache): | ||||||
|     """Cache RT links to disk |     """Cache RT links to disk | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								setup.py
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								setup.py
									
										
									
									
									
								
							|  | @ -17,6 +17,7 @@ setup( | ||||||
|         # 1.4.1 crashes when trying to save some documents. |         # 1.4.1 crashes when trying to save some documents. | ||||||
|         'odfpy>=1.4.0,!=1.4.1',  # Debian:python3-odf |         'odfpy>=1.4.0,!=1.4.1',  # Debian:python3-odf | ||||||
|         'pdfminer.six>=20200101', |         'pdfminer.six>=20200101', | ||||||
|  |         'python-dateutil>=2.7',  # Debian:python3-dateutil | ||||||
|         'PyYAML>=3.0',  # Debian:python3-yaml |         'PyYAML>=3.0',  # Debian:python3-yaml | ||||||
|         'regex',  # Debian:python3-regex |         'regex',  # Debian:python3-regex | ||||||
|         'rt>=2.0', |         'rt>=2.0', | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ | ||||||
| # LICENSE.txt in the repository. | # LICENSE.txt in the repository. | ||||||
| 
 | 
 | ||||||
| import contextlib | import contextlib | ||||||
|  | import datetime | ||||||
| import itertools | import itertools | ||||||
| import logging | import logging | ||||||
| import re | import re | ||||||
|  | @ -287,3 +288,34 @@ def test_txn_with_urls_with_fmts(rt): | ||||||
|         f'<{DEFAULT_RT_URL}{statement_path}>', |         f'<{DEFAULT_RT_URL}{statement_path}>', | ||||||
|         '[stmt.txt]', |         '[stmt.txt]', | ||||||
|     ]) |     ]) | ||||||
|  | 
 | ||||||
|  | @pytest.mark.parametrize('arg,exp_num,exp_offset', [ | ||||||
|  |     # These correspond to the different datetime formats available through | ||||||
|  |     # RT's user settings. | ||||||
|  |     ('Mon Mar 1 01:01:01 2021', 1, None), | ||||||
|  |     ('2021-03-02 02:02:02', 2, None), | ||||||
|  |     ('2021-03-03T03:03:03-0500', 3, -18000), | ||||||
|  |     ('Thu, 4 Mar 2021 04:04:04 -0600', 4, -21600), | ||||||
|  |     ('Fri, 5 Mar 2021 05:05:05 GMT', 5, 0), | ||||||
|  |     ('20210306T060606Z', 6, 0), | ||||||
|  |     ('Sun, Mar 7, 2021 07:07:07 AM', 7, None), | ||||||
|  |     ('Sun, Mar 14, 2021 02:14:14 PM', 14, None), | ||||||
|  | ]) | ||||||
|  | def test_rt_datetime(arg, exp_num, exp_offset): | ||||||
|  |     actual = rtutil.RTDateTime(arg) | ||||||
|  |     assert actual.year == 2021 | ||||||
|  |     assert actual.month == 3 | ||||||
|  |     assert actual.day == exp_num | ||||||
|  |     assert actual.hour == exp_num | ||||||
|  |     assert actual.minute == exp_num | ||||||
|  |     assert actual.second == exp_num | ||||||
|  |     if exp_offset is None: | ||||||
|  |         assert actual.tzinfo is None | ||||||
|  |     else: | ||||||
|  |         assert actual.tzinfo.utcoffset(None).total_seconds() == exp_offset | ||||||
|  | 
 | ||||||
|  | @pytest.mark.parametrize('arg', ['Not set', '', None]) | ||||||
|  | def test_rt_datetime_empty(arg): | ||||||
|  |     actual = rtutil.RTDateTime(arg) | ||||||
|  |     assert actual == datetime.datetime.min | ||||||
|  |     assert actual.tzinfo is None | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Brett Smith
						Brett Smith