runtilities 2.3.0.dev1__tar.gz → 3.0.0.dev1__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.
Files changed (42) hide show
  1. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/PKG-INFO +1 -1
  2. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/runsignup.py +47 -71
  3. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/version.py +1 -1
  4. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/runtilities.egg-info/PKG-INFO +1 -1
  5. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/README.md +0 -0
  6. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/__init__.py +0 -0
  7. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/analyzeagegrade.py +0 -0
  8. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/athlinks.py +0 -0
  9. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/athlinksresults.py +0 -0
  10. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/comparegpx.py +0 -0
  11. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/competitor.py +0 -0
  12. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/competitor2csv.py +0 -0
  13. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/getweather.py +0 -0
  14. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/gpx2kml.py +0 -0
  15. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/parseralogxml.py +0 -0
  16. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/parseresults.py +0 -0
  17. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/parserun-bk3.py +0 -0
  18. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/parsetcx.py +0 -0
  19. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/ra2membersfile.py +0 -0
  20. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/racewx-render.py +0 -0
  21. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/racewx.py +0 -0
  22. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/renderclubagstats.py +0 -0
  23. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/runningahead.py +0 -0
  24. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/runningaheadmembers.py +0 -0
  25. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/runningaheadparticipants.py +0 -0
  26. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/runningaheadresults.py +0 -0
  27. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/strava.py +0 -0
  28. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/textnormalize.py +0 -0
  29. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/ultrasignup.py +0 -0
  30. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/ultrasignupresults.py +0 -0
  31. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/xmldict.py +0 -0
  32. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/xmldict1.py +0 -0
  33. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/xmldict2.py +0 -0
  34. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/running/xmlreader.py +0 -0
  35. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/runtilities.egg-info/SOURCES.txt +0 -0
  36. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/runtilities.egg-info/dependency_links.txt +0 -0
  37. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/runtilities.egg-info/entry_points.txt +0 -0
  38. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/runtilities.egg-info/not-zip-safe +0 -0
  39. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/runtilities.egg-info/requires.txt +0 -0
  40. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/runtilities.egg-info/top_level.txt +0 -0
  41. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/setup.cfg +0 -0
  42. {runtilities-2.3.0.dev1 → runtilities-3.0.0.dev1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: runtilities
3
- Version: 2.3.0.dev1
3
+ Version: 3.0.0.dev1
4
4
  Summary: running related scripts
5
5
  Home-page: http://github.com/louking/running
6
6
  Author: Lou King
@@ -1,25 +1,3 @@
1
- ###########################################################################################
2
- # runsignup - access methods for runsignup.com
3
- #
4
- # Date Author Reason
5
- # ---- ------ ------
6
- # 12/31/17 Lou King Create from runningahead.com
7
- #
8
- # Copyright 2017 Lou King
9
- #
10
- # Licensed under the Apache License, Version 2.0 (the "License");
11
- # you may not use this file except in compliance with the License.
12
- # You may obtain a copy of the License at
13
- #
14
- # http://www.apache.org/licenses/LICENSE-2.0
15
- #
16
- # Unless required by applicable law or agreed to in writing, software
17
- # distributed under the License is distributed on an "AS IS" BASIS,
18
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
- # See the License for the specific language governing permissions and
20
- # limitations under the License.
21
- #
22
- ###########################################################################################
23
1
  '''
24
2
  runsignup - access methods for runsignup.com
25
3
  ===================================================
@@ -52,10 +30,6 @@ names = NameDenormalizer()
52
30
 
53
31
  # use api.runsignup.com per https://info.runsignup.com/2025/08/06/upgrading-our-api-infrastructure-for-ai-api-runsignup-com/
54
32
 
55
- # login API (deprecated)
56
- login_url = 'https://api.runsignup.com/rest/login'
57
- logout_url = 'https://api.runsignup.com/rest/logout'
58
-
59
33
  # methods
60
34
  members_url = 'https://api.runsignup.com/rest/club/{club_id}/members'
61
35
  getrace_url = 'https://api.runsignup.com/rest/race/{race_id}'
@@ -78,17 +52,21 @@ class RunSignUp():
78
52
  '''
79
53
  access methods for RunSignUp.com
80
54
 
81
- either key and secret OR email and password should be supplied
82
- key and secret take precedence
55
+ key and secret should be supplied for authenticated access
56
+
57
+ per https://info.runsignup.com/2026/07/17/new-api-registration-requirements/, all API callers must
58
+ register (free) and supply the resulting token/secret on every call starting 2027-01-01; existing
59
+ api_key/api_secret credentials are unaffected and continue to be required alongside these
83
60
 
84
61
  :param key: key from runsignup (direct key, no OAuth)
85
62
  :param secret: secret from runsignup (direct secret, no OAuth)
86
- :param email: email for use by Login API (deprecated)
87
- :param password: password for use by Login API (deprecated)
63
+ :param api_reg_token: API caller registration token, sent as rsu_api_reg GET parameter
64
+ :param api_reg_secret: API caller registration secret, sent as X-RSU-API-REG-SECRET header
88
65
  :param debug: set to True for debug logging of http requests, default False
89
66
  '''
90
67
 
91
- def __init__(self, userpriv=False, key=None, secret=None, email=None, password=None, debug=False):
68
+ def __init__(self, userpriv=False, key=None, secret=None,
69
+ api_reg_token=None, api_reg_secret=None, debug=False):
92
70
  """
93
71
  initialize
94
72
  """
@@ -108,27 +86,20 @@ class RunSignUp():
108
86
  requests_log.setLevel(logging.NOTSET)
109
87
  requests_log.propagate = False
110
88
 
111
- self.userpriv = False
112
- if (not key and not email):
113
- self.userpriv = True
89
+ self.userpriv = not key
114
90
  if (key and not secret) or (secret and not key):
115
91
  raise parameterError('key and secret must be supplied together')
116
- if (email and not password) or (password and not email):
117
- raise parameterError('email and password must be supplied together')
92
+ if (api_reg_token and not api_reg_secret) or (api_reg_secret and not api_reg_token):
93
+ raise parameterError('api_reg_token and api_reg_secret must be supplied together')
118
94
 
119
95
  self.key = key
120
96
  self.secret = secret
121
- self.email = email
122
- self.password = password
97
+ self.api_reg_token = api_reg_token
98
+ self.api_reg_secret = api_reg_secret
123
99
  self.debug = debug
124
100
  self.client_credentials = {}
125
101
 
126
- if self.userpriv:
127
- self.credentials_type = 'none'
128
- elif key:
129
- self.credentials_type = 'key'
130
- else:
131
- self.credentials_type = 'login'
102
+ self.credentials_type = 'none' if self.userpriv else 'key'
132
103
 
133
104
  def __enter__(self):
134
105
  self.open()
@@ -142,22 +113,18 @@ class RunSignUp():
142
113
  # set up session for multiple requests
143
114
  self.session = requests.Session()
144
115
 
116
+ # per https://info.runsignup.com/2026/07/17/new-api-registration-requirements/, registration
117
+ # secret is sent as a header, applies regardless of credentials_type
118
+ if self.api_reg_secret:
119
+ self.session.headers.update({'X-RSU-API-REG-SECRET': self.api_reg_secret})
120
+
145
121
  if not self.userpriv:
146
- # key / secret supplied - this take precedence
147
- if self.credentials_type == 'key':
148
- self.client_credentials = {'api_key' : self.key,
149
- 'api_secret' : self.secret}
150
-
151
- # email / password supplied
152
- else:
153
- # login to runsignup - note temporary keys will expire 1 hour after last API call
154
- # see https://api.runsignup.com/API/login/POST
155
- r = requests.post(login_url, params={'format' : 'json'}, data={'email' : self.email, 'password' : self.password})
156
- resp = r.json()
157
-
158
- self.credentials_type = 'login'
159
- self.client_credentials = {'tmp_key' : resp['tmp_key'],
160
- 'tmp_secret' : resp['tmp_secret']}
122
+ self.client_credentials = {'api_key' : self.key,
123
+ 'api_secret' : self.secret}
124
+
125
+ # registration token is sent as a GET parameter alongside whichever credentials were set above
126
+ if self.api_reg_token:
127
+ self.client_credentials['rsu_api_reg'] = self.api_reg_token
161
128
 
162
129
  def close(self):
163
130
  '''
@@ -166,8 +133,6 @@ class RunSignUp():
166
133
  self.client_credentials = {}
167
134
  self.session.close()
168
135
 
169
- # TODO: should we also log out?
170
-
171
136
  def members(self, club_id, **kwargs):
172
137
  '''
173
138
  return members accessible to this application
@@ -420,7 +385,8 @@ class RunSignUp():
420
385
  return data
421
386
 
422
387
  #----------------------------------------------------------------------
423
- def updatemembercache(club_id, membercachefilename, key=None, secret=None, email=None, password=None, debug=False):
388
+ def updatemembercache(club_id, membercachefilename, key=None, secret=None,
389
+ api_reg_token=None, api_reg_secret=None, debug=False):
424
390
  if debug:
425
391
  # set up debug logging
426
392
  thislogger.setLevel(logging.DEBUG)
@@ -431,7 +397,8 @@ def updatemembercache(club_id, membercachefilename, key=None, secret=None, email
431
397
  thislogger.propagate = True
432
398
 
433
399
  # set up access to RunSignUp
434
- rsu = RunSignUp(key=key, secret=secret, email=email, password=password, debug=debug)
400
+ rsu = RunSignUp(key=key, secret=secret,
401
+ api_reg_token=api_reg_token, api_reg_secret=api_reg_secret, debug=debug)
435
402
  rsu.open()
436
403
 
437
404
  # transform from RunSignUp to membercache format
@@ -608,7 +575,8 @@ def updatemembercache(club_id, membercachefilename, key=None, secret=None, email
608
575
  return rsumembers
609
576
 
610
577
  #----------------------------------------------------------------------
611
- def members2csv(club_id, key, secret, mapping, filepath=None, encoding=None):
578
+ def members2csv(club_id, key, secret, mapping, filepath=None, encoding=None,
579
+ api_reg_token=None, api_reg_secret=None):
612
580
  '''
613
581
  Access club_id through RunSignUp API to retrieve members. Return
614
582
  list of members as if csv file. Optionally save csv file.
@@ -619,11 +587,13 @@ def members2csv(club_id, key, secret, mapping, filepath=None, encoding=None):
619
587
  :param mapping: OrderedDict {'outfield1':'infield1', 'outfield2':outfunction(inrec), ...} or ['inoutfield1', 'inoutfield2', ...]
620
588
  :param normfile: (optional) pathname to save csv file
621
589
  :param encoding: (optional) encoding to use for file
590
+ :param api_reg_token: API caller registration token, sent as rsu_api_reg GET parameter
591
+ :param api_reg_secret: API caller registration secret, sent as X-RSU-API-REG-SECRET header
622
592
  :rtype: csv file records, as list
623
593
  '''
624
594
 
625
595
  # get the members from the RunSignUp API
626
- with RunSignUp(key=key, secret=secret) as rsu:
596
+ with RunSignUp(key=key, secret=secret, api_reg_token=api_reg_token, api_reg_secret=api_reg_secret) as rsu:
627
597
  members = rsu.members(club_id)
628
598
 
629
599
  filerows = record2csv(members, mapping, filepath, encoding=encoding)
@@ -879,12 +849,15 @@ class RunSignupFluent(UniversalClient):
879
849
  '''
880
850
  Fluent interface to RunSignUp API -- see https://universal-client.readthedocs.io
881
851
  '''
882
- def __init__(self, key=None, secret=None, debug=False):
852
+ def __init__(self, key=None, secret=None, api_reg_token=None, api_reg_secret=None, debug=False):
883
853
  '''
884
854
  initialize RunSignUp Fluent client
885
855
 
886
856
  :param key: api key for RunSignUp
887
857
  :param secret: api secret for RunSignUp
858
+ :param api_reg_token: API caller registration token, sent as rsu_api_reg GET parameter -- see
859
+ https://info.runsignup.com/2026/07/17/new-api-registration-requirements/
860
+ :param api_reg_secret: API caller registration secret, sent as X-RSU-API-REG-SECRET header
888
861
  :param debug: debug flag
889
862
  '''
890
863
  # rsuservice = Oauth2Service(
@@ -898,9 +871,12 @@ class RunSignupFluent(UniversalClient):
898
871
  self._params = params = {'api_key' : key,
899
872
  'api_secret' : secret,
900
873
  'format' : 'json' }
901
-
902
- super().__init__(
903
- url='https://api.runsignup.com/rest',
904
- params=params,
905
- )
874
+ if api_reg_token:
875
+ params['rsu_api_reg'] = api_reg_token
876
+
877
+ client_kwargs = {'url': 'https://api.runsignup.com/rest', 'params': params}
878
+ if api_reg_secret:
879
+ client_kwargs['headers'] = {'X-RSU-API-REG-SECRET': api_reg_secret}
880
+
881
+ super().__init__(**client_kwargs)
906
882
 
@@ -1,2 +1,2 @@
1
1
  # this string is used for the version string in the documentation, as well as the egg
2
- __version__ = '2.3.0.dev1'
2
+ __version__ = '3.0.0.dev1'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: runtilities
3
- Version: 2.3.0.dev1
3
+ Version: 3.0.0.dev1
4
4
  Summary: running related scripts
5
5
  Home-page: http://github.com/louking/running
6
6
  Author: Lou King