Skip to content

Instantly share code, notes, and snippets.

@JorgeMadson
Last active September 19, 2019 14:41
Show Gist options
  • Save JorgeMadson/976ace71a6277243b2e7d85565258b3c to your computer and use it in GitHub Desktop.
Save JorgeMadson/976ace71a6277243b2e7d85565258b3c to your computer and use it in GitHub Desktop.
Cache in Python

Technical challenge

Here is the description of what you'll need to implement and answer on this technical challenge.

Challenges

You'll answer the 4 following challenges.

1. Cache function ✔️

Implement a function (on the same module - request.py) to cache requests preventing unecessary calls. You MUST use this Redis module as a cache service.

Note: You may use any Python version and import other modules, unless they implement cache services.

2. Date formatting ✔️ Codepen link

Implement a JavaScript code (on the same file - date-format.html) that replaces the date value of all elements (that have js-date-format class) with the value of the time passed from now (new Date()). Use the following format:

  • 1 second ago OR X seconds ago
  • 1 minute ago OR X minutes ago
  • 1 hour ago OR X hours ago
  • Date in ISO format (original format)

Example:

Working example

Note: You should use ecmascript 6 features but may not use any framework or add any dependency.

3. Apply style ✔️ Codepen link

Implement the CSS code to make the component on component.html look like the desired mockup below.

Mockup:

Desired mockup

Note #1: You should use new CSS features and add classes as you need, but try not to change the HTML structure.

Note #2: We recommend you try using BEM.

4. Question ✔️

Send us your answer for the following question:

What are the main HTTP verbs used in REST applications and what are they meant for?

Answer:

The main HTTP verbs are used for doing CRUD operations:

get -> for consulting data (READ)

post -> creating data (CREATE)

put -> editing data (UPDATE)

delete -> deleting data (DELETE)

*patch -> can be used to UPDATE too, instead of sending all the data with new info, with patch you can send only the new info.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>CrossKnowledge - Code challenge</title>
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<article class="article">
<header class="header">
<div class="header__list">
<div class="header__list--item-bold">
Avengers: Infinity War
</div>
<div>
156 minutes
</div>
</div>
<div class="rating">
85% <img class="image image__responsive" src="https://www.rottentomatoes.com/assets/pizza-pie/images/icons/global/cf-lg.3c29eff04f2.png" alt="">
</div>
</header>
<div">
<img class="image" src="https://resizing.flixster.com/N_yw0Y6mc-zM1A0RI8irg5urW6Y=/fit-in/200x296.2962962962963/v1.bTsxMjcwMDQ5MztqOzE4MDExOzEyMDA7MTY4ODsyNTAw">
<a class="link__button" href="https://www.rottentomatoes.com/m/avengers_infinity_war" target="_blank">
Check review
</a>
</div>
<footer>
<p class="footer--margin_1em">
An unprecedented cinematic journey ten years in the making and spanning the entire Marvel Cinematic Universe, Marvel Studios' "Avengers: Infinity War" brings to the screen the ultimate, deadliest showdown of all time. The Avengers and their Super Hero allies must be willing to sacrifice all in an attempt to defeat the powerful Thanos before his blitz of devastation and ruin puts an end to the universe.
</p>
</footer>
</article>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>CrossKnowledge - Code challenge</title>
</head>
<body style="display: flex; flex-direction: column;">
<script>
// This will create elements for testing every second
(() => {
let counter = 0;
function diffFromInitialDate(date) {
let parsedDate = new Date(date).valueOf();
let timeDiff = Math.round((new Date().valueOf() - parsedDate) / 1000);
return timeDiff;
}
function findHtmlElement() {
let allElements = document.getElementsByClassName('js-date-format');
for (let index = 0; index < allElements.length; index++) {
const element = allElements[index];
replaceHtmlElementValue(element);
}
}
function replaceHtmlElementValue(element) {
element.innerHTML = timeAgoFormat(element.dateTime);
}
function createHtmlElement() {
let el = document.createElement("time");
el.className = 'js-date-format';
const creationTime = new Date().toISOString();
console.log(creationTime);
el.dateTime = creationTime;
el.innerHTML = creationTime;
document.body.appendChild(el);
counter++;
console.log('I decided to use only 5 dates, but this value can change.');
if (counter === 5) {
clearInterval(intervalId);
}
}
function timeAgoFormat(time) {
let parsedTime = diffFromInitialDate(time);
if (parsedTime < 2) {
return `${parsedTime} second ago`;
}
if (59 < parsedTime && parsedTime < 3600) {
const minutes = Math.round(parsedTime / 60);
//const seconds = parsedTime % 60;
return `${minutes} ${minutes < 2 ? 'minute' : 'minutes'} ago`;
//and ${seconds} ${seconds < 2 ? 'second' : 'seconds'} ago`;
}
if (3599 < parsedTime) {
let hours = Math.round(parsedTime / 3600);
//const minutes = Math.round((parsedTime % 3600) / 60);
return `${hours} ${hours < 2 ? 'hour' : 'hours'} ago`;
//and ${minutes} ${minutes < 2 ? 'minute' : 'minutes'}`;
}
return `${parsedTime} seconds ago`;
};
let intervalId = setInterval(createHtmlElement, 1000);
setInterval(findHtmlElement, 1000);
})();
</script>
</body>
</html>
import requests
import redis
redis_db = redis.StrictRedis(host="localhost", port=6379, db=0)
# print(redis_db.keys())
""" Save the response of GET on redis for 15 minutes for caching """
def get(url, parameters=None):
have_cache = redis_db.get(url)
if have_cache is not None:
print('from cache')
return redis_db.get(url)
else:
print('included in cache')
response = requests.get(url, params=parameters).json()
redis_db.set(url, response.text)
redis_db.expire(url, 15 * 60)
return redis_db.get(url)
""" We have to refresh the cache for post, put, patch or delete, because they change the request response """
def post(url, parameters=None, data=None):
""" Post data to an URL and returns the response """
response = requests.post(url, params=parameters, data=data).json()
redis_db.set(url, response.txt)
redis_db.expire(url, 15 * 60)
return redis_db.get(url)
def put(url, parameters=None, data=None):
""" Put data to an resource and returns the response """
response = requests.put(url, params=parameters, data=data).json()
redis_db.set(url, response.txt)
redis_db.expire(url, 15 * 60)
return redis_db.get(url)
def patch(url, parameters=None, data=None):
""" Patches an resource and returns the response """
response = requests.patch(url, params=parameters, data=data).json()
redis_db.set(url, response.txt)
redis_db.expire(url, 15 * 60)
return redis_db.get(url)
def delete(url, parameters=None, data=None):
""" Requests the deletion of an resource and returns the response """
response = requests.delete(url, params=parameters, data=data).json()
redis_db.set(url, response.txt)
redis_db.expire(url, 15 * 60)
return redis_db.get(url)
r = get('https://jsonplaceholder.typicode.com/posts/1')
print(r)
.article {
font-family: 'Roboto', sans-serif;
margin: 0 auto;
background-color: #f7f7f7;
border-color: #e9e9e9;
max-width: 20.5rem;
}
.header {
display: flex;
justify-content: space-between;
height: 3rem;
padding: 1em;
}
.header__list {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.header__list--item-bold {
font-weight: bold;
}
.rating {
display: flex;
align-items: center;
justify-content: flex-end;
}
.rating__tomato {
max-width: 1em;
max-height: 1em;
}
.footer--margin_1em {
margin: 1em;
}
.image {
display: flex;
max-width: 100%;
max-height: 100%;
margin: 0 auto;
}
.link__button {
text-decoration: none;
position: absolute;
left: calc(50% - 5.5rem);
margin-top: -5rem;
margin-left: auto;
margin-right: auto;
padding: 0.60em 3em;
background: #a5a5a4;
color: black;
border: 0.125em solid white;
border-radius: 1em;
}
/* Responsive Design */
@media only screen and (max-device-width: 480px) {
.article {
max-width: 100%;
}
.header {
height: 5rem;
font-size: 2.5rem;
}
.link__button {
left: calc(50% - 17rem);
margin-top: -13rem;
font-size: 3rem;
}
.image {
width: 100%;
}
.image__responsive {
height: 100%;
width: auto;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment