@@ -9,13 +9,10 @@ use crate::{Language, RunResult, ValidationResult};
99use oauth2:: basic:: BasicClient ;
1010use oauth2:: prelude:: * ;
1111use oauth2:: {
12- AuthUrl , ClientId , ClientSecret , ResourceOwnerPassword , ResourceOwnerUsername , TokenResponse ,
13- TokenUrl ,
12+ AuthUrl , ClientId , ClientSecret , ResourceOwnerPassword , ResourceOwnerUsername , TokenUrl ,
1413} ;
1514use reqwest:: { blocking:: Client , Url } ;
16- use serde:: de:: DeserializeOwned ;
1715use std:: collections:: HashMap ;
18- use std:: fmt:: Debug ;
1916use std:: io:: Write ;
2017use std:: path:: Path ;
2118use std:: path:: PathBuf ;
@@ -29,14 +26,23 @@ pub type Token =
2926/// A struct for interacting with the TestMyCode service, including authentication
3027pub struct TmcCore {
3128 client : Client ,
32- config_dir : PathBuf ,
29+ config_dir : PathBuf , // not used yet
3330 api_url : Url ,
3431 auth_url : Url ,
3532 token : Option < Token > ,
3633}
3734
3835// TODO: cache API results?
3936impl TmcCore {
37+ /// Creates a new TmcCore with the given config directory and root URL.
38+ ///
39+ /// # Errors
40+ /// This function will return an error if parsing the root_url fails.
41+ ///
42+ /// # Examples
43+ /// ```rust,no_run
44+ /// let core = TmcCore::new(Path::new("./config"), "https://tmc.mooc.fi".to_string()).unwrap();
45+ /// ```
4046 pub fn new ( config_dir : PathBuf , root_url : String ) -> Result < Self > {
4147 // guarantee a trailing slash, otherwise join will drop the last component
4248 let root_url = if root_url. ends_with ( '/' ) {
@@ -56,13 +62,33 @@ impl TmcCore {
5662 } )
5763 }
5864
65+ /// Creates a new TmcCore with the given root URL. The config directory is set according to dirs::cache_dir.
66+ ///
67+ /// # Errors
68+ /// This function will return an error if parsing the root_url fails, or if fetching the cache directory fails (see dirs::cache_dir()).
69+ ///
70+ /// # Examples
71+ /// ```rust,no_run
72+ /// let core = TmcCore::new_in_config("https://tmc.mooc.fi".to_string()).unwrap();
73+ /// ```
5974 pub fn new_in_config ( root_url : String ) -> Result < Self > {
6075 let config_dir = dirs:: cache_dir ( ) . ok_or ( CoreError :: CacheDir ) ?;
6176 Self :: new ( config_dir, root_url)
6277 }
6378
6479 /// Attempts to log in with the given credentials, returns an error if an authentication token is already present.
6580 /// Username can be the user's username or email.
81+ ///
82+ /// # Errors
83+ /// This function will return an error if the core has already been authenticated,
84+ /// if the client_name is malformed and leads to a malformed URL,
85+ /// or if there is some error during the token exchange (see oauth2::Client::excange_password).
86+ ///
87+ /// # Examples
88+ /// ```rust,no_run
89+ /// let mut core = TmcCore::new_in_config("https://tmc.mooc.fi".to_string()).unwrap();
90+ /// core.authenticate("client", "user".to_string(), "pass".to_string()).unwrap();
91+ /// ```
6692 pub fn authenticate (
6793 & mut self ,
6894 client_name : & str ,
@@ -104,16 +130,34 @@ impl TmcCore {
104130 }
105131
106132 /// Fetches all organizations.
133+ ///
134+ /// # Errors
135+ /// Returns an error if there's some problem reaching the API, or if the API returns an error.
107136 pub fn get_organizations ( & self ) -> Result < Vec < Organization > > {
108137 self . organizations ( )
109138 }
110139
111- /// UNIMPLEMENTED
140+ # [ deprecated = "unimplemented" ]
112141 pub fn send_diagnostics ( & self ) {
113142 unimplemented ! ( )
114143 }
115144
116- /// Downloads the given exercises.
145+ /// Downloads the given exercises. Overwrites existing exercises if they exist.
146+ ///
147+ /// # Errors
148+ /// Returns an error if there's some problem reaching the API, or if the API returns an error.
149+ /// The method extracts zip archives, which may fail.
150+ ///
151+ ///
152+ /// # Examples
153+ /// ```rust,no_run
154+ /// let core = TmcCore::new_in_config("https://tmc.mooc.fi".to_string()).unwrap();
155+ /// // authenticate
156+ /// core.download_or_update_exercises(vec![
157+ /// (1234, Path::new("./exercises/1234")),
158+ /// (2345, Path::new("./exercises/2345")),
159+ /// ]);
160+ /// ```
117161 pub fn download_or_update_exercises ( & self , exercises : Vec < ( usize , & Path ) > ) -> Result < ( ) > {
118162 for ( exercise_id, target) in exercises {
119163 let zip_file = NamedTempFile :: new ( ) . map_err ( CoreError :: TempFile ) ?;
@@ -124,16 +168,25 @@ impl TmcCore {
124168 }
125169
126170 /// Fetches the course's information.
171+ ///
172+ /// # Errors
173+ /// Returns an error if there's some problem reaching the API, or if the API returns an error.
127174 pub fn get_course_details ( & self , course_id : usize ) -> Result < CourseDetails > {
128175 self . core_course ( course_id)
129176 }
130177
131178 /// Fetches all courses under the given organization.
179+ ///
180+ /// # Errors
181+ /// Returns an error if there's some problem reaching the API, or if the API returns an error.
132182 pub fn list_courses ( & self , organization_slug : & str ) -> Result < Vec < Course > > {
133183 self . organization_courses ( organization_slug)
134184 }
135185
136186 /// Sends the given submission as a paste.
187+ ///
188+ /// # Errors
189+ /// Returns an error if there's some problem reaching the API, or if the API returns an error.
137190 pub fn paste_with_comment (
138191 & self ,
139192 submission_url : Url ,
@@ -150,7 +203,11 @@ impl TmcCore {
150203 self . post_submission_to_paste ( submission_url, file. path ( ) , paste_message, locale)
151204 }
152205
153- /// Runs checkstyle for the project.
206+ /// Checks the coding style for the project.
207+ ///
208+ /// # Errors
209+ /// Returns an error if no matching language plugin for the project is found,
210+ /// or if the plugin returns an error while trying to run the style check.
154211 pub fn run_checkstyle (
155212 & self ,
156213 path : & Path ,
@@ -160,11 +217,18 @@ impl TmcCore {
160217 }
161218
162219 /// Runs tests for the project.
220+ ///
221+ /// # Errors
222+ /// Returns an error if no matching language plugin for the project is found,
223+ /// or if the plugin returns an error while trying to run the tests.
163224 pub fn run_tests ( & self , path : & Path ) -> Result < RunResult > {
164225 Ok ( task_executor:: run_tests ( path) ?)
165226 }
166227
167228 /// Sends feedback.
229+ ///
230+ /// # Errors
231+ /// Returns an error if there's some problem reaching the API, or if the API returns an error.
168232 pub fn send_feedback (
169233 & self ,
170234 feedback_url : Url ,
@@ -173,12 +237,16 @@ impl TmcCore {
173237 self . post_feedback ( feedback_url, feedback)
174238 }
175239
176- /// UNIMPLEMENTED
240+ # [ deprecated = "unimplemented" ]
177241 pub fn send_snapshot_events ( & self ) {
178242 unimplemented ! ( )
179243 }
180244
181245 /// Sends the submission to the server.
246+ ///
247+ /// # Errors
248+ /// Returns an error if there's some problem reaching the API, or if the API returns an error.
249+ /// The method compresses the submission and writes it into a temporary archive, which may fail.
182250 pub fn submit (
183251 & self ,
184252 submission_url : Url ,
@@ -199,6 +267,18 @@ impl TmcCore {
199267 /// If an exercise's id is not found in the checksum map, it is considered new.
200268 /// If an id is found, it is compared to the current one. If they are different,
201269 /// it is considered updated.
270+ ///
271+ /// # Errors
272+ /// Returns an error if there's some problem reaching the API, or if the API returns an error.
273+ ///
274+ /// # Examples
275+ /// ```rust,no_run
276+ /// let core = TmcCore::new_in_config("https://tmc.mooc.fi".to_string()).unwrap();
277+ /// // authenticate
278+ /// let mut checksums = std::collections::HashMap::new();
279+ /// checksums.insert(1234, "exercisechecksum");
280+ /// let update_result = core.get_exercise_updates(600, checksums).unwrap();
281+ /// ```
202282 pub fn get_exercise_updates (
203283 & self ,
204284 course_id : usize ,
@@ -226,16 +306,26 @@ impl TmcCore {
226306 }
227307
228308 /// Mark the review as read on the server.
309+ ///
310+ /// # Errors
311+ /// Returns an error if there's some problem reaching the API, or if the API returns an error.
229312 pub fn mark_review_as_read ( & self , review_update_url : String ) -> Result < ( ) > {
230313 self . mark_review ( review_update_url, true )
231314 }
232315
233316 /// Fetches all reviews.
317+ ///
318+ /// # Errors
319+ /// Returns an error if there's some problem reaching the API, or if the API returns an error.
234320 pub fn get_unread_reviews ( & self , reviews_url : Url ) -> Result < Vec < Review > > {
235321 self . get_json_from_url ( reviews_url)
236322 }
237323
238324 /// Request code review.
325+ ///
326+ /// # Errors
327+ /// Returns an error if there's some problem reaching the API, or if the API returns an error.
328+ /// The method compresses the project and writes a temporary archive, which may fail.
239329 pub fn request_code_review (
240330 & self ,
241331 submission_url : Url ,
@@ -253,6 +343,10 @@ impl TmcCore {
253343 }
254344
255345 /// Downloads the model solution from the given url.
346+ ///
347+ /// # Errors
348+ /// Returns an error if there's some problem reaching the API, or if the API returns an error.
349+ /// The method extracts the downloaded model solution archive, which may fail.
256350 pub fn download_model_solution ( & self , solution_download_url : Url , target : & Path ) -> Result < ( ) > {
257351 let zip_file = NamedTempFile :: new ( ) . map_err ( CoreError :: TempFile ) ?;
258352 self . download_from ( solution_download_url, zip_file. path ( ) ) ?;
@@ -261,6 +355,10 @@ impl TmcCore {
261355 }
262356
263357 /// Checks the status of a submission on the server.
358+ ///
359+ /// # Errors
360+ /// Returns an error if the core has not been authenticated,
361+ /// or if there's some problem reaching the API, or if the API returns an error.
264362 pub fn check_submission ( & self , submission_url : & str ) -> Result < SubmissionProcessingStatus > {
265363 if self . token . is_none ( ) {
266364 return Err ( CoreError :: AuthRequired ) ;
0 commit comments