Skip to content

Commit ffb0a05

Browse files
authored
Merge pull request #7 from sh-alireza/master
some bugs fixed, ready for pypi
2 parents fe7cbf1 + 150ab39 commit ffb0a05

11 files changed

+409
-132
lines changed

Diff for: CHANGELOG.md

+13-6
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,19 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7-
## [Unreleased]
8-
-
7+
## [1.2.0] - 2023-06-29
8+
## changed
9+
- All modules receive timings as input
10+
- The raw output can be saved in a preferred format, either json, html, or both
11+
- The demo has been updated
12+
13+
## [1.1.0] - 2023-06-29
14+
## changed
15+
- Old syntax fixed
16+
- Made compatible to run in docker
17+
- Demo Added
18+
19+
## Adam Cupal
920
## [1.0.2] - 2019-02-22
1021
### Changed
1122
- added option to runner to pass custom parameters
@@ -18,7 +29,3 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1829
## [1.0.0] - 2019-02-05
1930
### Added
2031
- Base runner
21-
22-
[Unreleased]: https://github.com/adamcupial/lighthouse-python/compare/1.0.1...HEAD
23-
[1.0.1]: https://github.com/adamcupial/lighthouse-python/compare/1.0.0...1.0.1
24-
[1.0.2]: https://github.com/adamcupial/lighthouse-python/compare/1.0.1...1.0.2

Diff for: LICENSE

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2019 Adam Cupiał
3+
Copyright (c) 2023 Adam Cupiał & alireza sharifi
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

Diff for: README.md

+15-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Lighthouse runner for python
22

3+
## About This Repository
4+
This repository is based on the original work of [Adam Cupiał](https://github.com/adamcupial) and was forked from his [lighthouse-python](https://github.com/adamcupial/lighthouse-python) repository. While the original repository had not been updated in five years, I found it to be a valuable resource and decided to update it (I have made some changes, fixed some bugs) and turn it into a package for PyPI. I want to acknowledge the original author for creating the foundation of this project and making it available to the community.
5+
6+
37
## Description
48
This library is a simple wrapper around lighthouse-cli runner that runs the audit and parses a result in friendly manner.
59

@@ -10,17 +14,21 @@ npm install -g lighthouse
1014
```
1115

1216
```bash
13-
pip install git+https://github.com/adamcupial/lighthouse-python.git#egg=lighthouse
17+
pip install lighthouse-python-plus
1418
```
1519

1620
## Usage
1721

1822
```python
1923
from lighthouse import LighthouseRunner
2024

21-
report = LighthouseRunner('https://webdesign-log.pl', form_factor='desktop', quiet=False).report
25+
TIMINGS = [
26+
'speed-index'
27+
]
28+
29+
report = LighthouseRunner('https://github.com/adamcupial', form_factor='desktop', quiet=False, timings=TIMINGS).report
2230
assert report.score['performance'] > 0.5
23-
print(report.audits['performance'].failed)
31+
print(report.audits(0.5)['performance'].failed)
2432
```
2533

2634
report has 3 properties:
@@ -29,9 +37,11 @@ report has 3 properties:
2937
- timings: returns dict where keys are timings and values are timedelta objects
3038
- audits: dict where keys are categories and values are objects with passed and failed lists attached
3139

40+
To see all the usage examples of this library, please check out the [demo](demo) folder.
41+
3242
## Dependencies
33-
- python 2.7+
34-
- node package lighthouse installed
43+
- python 3.6+
44+
- node package lighthouse>=10.3.0 installed
3545

3646
## Changes
3747
[You can find all changes in CHANGELOG!](CHANGELOG.md)

Diff for: demo/demo_batch_runner.py

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from lighthouse import BatchRunner
2+
3+
4+
urls = ["https://amazon.com","https://alibaba.com"]
5+
form_factors = ["mobile","desktop"]
6+
7+
TIMINGS = [
8+
'first-contentful-paint',
9+
'speed-index',
10+
'interactive',
11+
]
12+
13+
# settings are as the same as the pagespeed.web.dev
14+
additional_settings = [
15+
"--throttling.cpuSlowdownMultiplier=4",
16+
"--throttling.connectionType=4g",
17+
"--throttling.downloadThroughputKbps=1638.4",
18+
"--throttling.rttMs=150",
19+
"--screenEmulation.disabled=false",
20+
"--screenEmulation.width=412",
21+
"--screenEmulation.height=823",
22+
"--screenEmulation.deviceScaleFactor=1.75",
23+
"--axe.enable=true",
24+
"--axe.version=4.7.0",
25+
]
26+
27+
batch_runner = BatchRunner(urls,form_factors,quiet=False,additional_settings=additional_settings,repeats=2,timings=TIMINGS)
28+
29+
print(batch_runner.reports)

Diff for: demo/demo_repeat_runner.py

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from lighthouse import LighthouseRepeatRunner
2+
3+
4+
url="https://github.com"
5+
6+
TIMINGS = [
7+
'first-contentful-paint',
8+
'speed-index',
9+
'interactive',
10+
]
11+
12+
# settings are as the same as the pagespeed.web.dev
13+
additional_settings = [
14+
"--throttling.cpuSlowdownMultiplier=4",
15+
"--throttling.connectionType=4g",
16+
"--throttling.downloadThroughputKbps=1638.4",
17+
"--throttling.rttMs=150",
18+
"--screenEmulation.disabled=false",
19+
"--screenEmulation.width=412",
20+
"--screenEmulation.height=823",
21+
"--screenEmulation.deviceScaleFactor=1.75",
22+
"--axe.enable=true",
23+
"--axe.version=4.7.0",
24+
]
25+
26+
repeat_runner = LighthouseRepeatRunner(url,"desktop",quiet=False,additional_settings=additional_settings,repeats=2,timings=TIMINGS)
27+
28+
print(repeat_runner.report.score)
29+
print(repeat_runner.report.timings)

Diff for: demo/demo_runner.py

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from lighthouse import LighthouseRunner
2+
3+
4+
url="https://github.com"
5+
6+
TIMINGS = [
7+
'first-contentful-paint',
8+
'speed-index',
9+
'interactive',
10+
]
11+
12+
# settings are as the same as the pagespeed.web.dev
13+
additional_settings = [
14+
"--throttling.cpuSlowdownMultiplier=4",
15+
"--throttling.connectionType=4g",
16+
"--throttling.downloadThroughputKbps=1638.4",
17+
"--throttling.rttMs=150",
18+
"--screenEmulation.disabled=false",
19+
"--screenEmulation.width=412",
20+
"--screenEmulation.height=823",
21+
"--screenEmulation.deviceScaleFactor=1.75",
22+
"--axe.enable=true",
23+
"--axe.version=4.7.0",
24+
]
25+
26+
runner = LighthouseRunner(url,"mobile",quiet=False,additional_settings=additional_settings,
27+
timings=TIMINGS,output_type='both',output_dir='./outputs')
28+
29+
print(runner.report.score)
30+
print(runner.report.timings)
31+
print(runner.report.audits(0.86)['performance'].passed)

Diff for: lighthouse/__init__.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
from .runner import LighthouseRunner, LighthouseRepeatRunner
2-
from .batch import BatchRunner
1+
from .runner import LighthouseRunner, LighthouseRepeatRunner, BatchRunner

Diff for: lighthouse/batch.py

-31
This file was deleted.

Diff for: lighthouse/report.py

+37-35
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,36 @@
1-
# this python file uses the following encoding utf-8
2-
3-
# Python Standard Library
1+
# Standard library modules
42
from collections import namedtuple
53
from datetime import timedelta
4+
from typing import Dict, List
65

76

8-
AuditResult = namedtuple('AuditResult', ['title', 'score', 'display'])
7+
AuditResult = namedtuple('AuditResult', ['id','title', 'score', 'display','numval','numunit'])
98
AuditCategoryResult = namedtuple('AuditCategoryResult', ['passed', 'failed'])
109

11-
BASE_TIMINGS = [
12-
'first-contentful-paint',
13-
'speed-index',
14-
'interactive',
15-
'first-meaningful-paint',
16-
'first-cpu-idle',
17-
'estimated-input-latency',
18-
'time-to-first-byte',
19-
]
20-
"""list(str) default list of timings"""
21-
22-
23-
class LighthouseReport(object):
10+
class LighthouseReport:
2411
"""
25-
Lighthouse report abstract
12+
Represents a Lighthouse report.
2613
27-
Should provide more pleasant report then the lighthouse JSON.
14+
Provides a more user-friendly interface to the Lighthouse JSON report.
2815
"""
2916

30-
def __init__(self, data, timings=BASE_TIMINGS):
17+
def __init__(self, data: Dict, timings: List[str] = []):
3118
"""
3219
Args:
33-
data (dict): JSON loaded lighthouse report
34-
timings (list(str), optional): list of timings
35-
to gather
20+
data (dict): JSON loaded Lighthouse report
21+
22+
timings (list(str), optional): List of timings to gather
23+
from Lighthouse report. Defaults to an empty list.
3624
"""
3725

3826
self.__data = data
3927
self.__timings = timings
4028

4129
@property
42-
def score(self):
43-
""" Dictionary of lighthouse's category name: score (0 to 1) """
30+
def score(self) -> Dict[str, float]:
31+
"""
32+
Dictionary of Lighthouse category names and their corresponding scores (0 to 1).
33+
"""
4434

4535
return {
4636
k: v.get('score', 0)
@@ -49,24 +39,29 @@ def score(self):
4939
}
5040

5141
@property
52-
def timings(self):
53-
""" Dictionary of lighthouse's timings names: timedelta times """
42+
def timings(self) -> Dict[str, timedelta]:
43+
"""
44+
Dictionary of Lighthouse timing names and their corresponding times as timedeltas.
45+
"""
5446

5547
return {
56-
k: timedelta(milliseconds=v.get('rawValue'))
48+
k: timedelta(milliseconds=v.get('numericValue'))
5749
for k, v
5850
in self.__data['audits'].items()
5951
if k in self.__timings
6052
}
6153

62-
@property
63-
def audits(self):
54+
def audits(self, score_thresh: float = 1) -> Dict[str, AuditCategoryResult]:
6455
"""
65-
Dictionary of audits as category name: object with passed/failed keys
66-
with lists attached.
56+
Returns a dictionary of Lighthouse audits, grouped by category, with passed/failed
57+
keys and lists of passed/failed audits attached.
58+
59+
Args:
60+
score_thresh (float, optional): The minimum score required for an audit to be considered
61+
passed. Defaults to 1 (all audits must pass).
6762
"""
68-
res = {}
6963

64+
res = {}
7065
for category, data in self.__data['categories'].items():
7166
all_audit_refs = [
7267
x.get('id')
@@ -76,23 +71,30 @@ def audits(self):
7671
sdm_to_reject = ['manual', 'notApplicable', 'informative']
7772
passed_audits = [
7873
AuditResult(**{
74+
'id': v['id'],
7975
'title': v['title'],
8076
'score': v['score'],
8177
'display': v.get('displayValue'),
78+
'numval': v.get('numericValue'),
79+
'numunit': v.get('numericUnit'),
8280
})
8381
for k, v in all_audits.items()
84-
if v.get('score', 0) == 1 and
82+
if v.get('score',0) is not None and
83+
v.get('score', 0) >= score_thresh and
8584
v.get('scoreDisplayMode') not in sdm_to_reject
8685
]
8786

8887
failed_audits = [
8988
AuditResult(**{
89+
'id': v['id'],
9090
'title': v['title'],
9191
'score': v['score'],
9292
'display': v.get('displayValue'),
93+
'numval': v.get('numericValue'),
94+
'numunit': v.get('numericUnit'),
9395
})
9496
for k, v in all_audits.items()
95-
if v.get('score', 0) < 1 and
97+
if (v.get('score',0) is None or v.get('score', 0) < score_thresh) and
9698
v.get('scoreDisplayMode') not in sdm_to_reject
9799
]
98100

0 commit comments

Comments
 (0)