Skip to content

Commit e70c7b3

Browse files
Merge pull request #2552 from LMFDB/master
master -> prod
2 parents 0fdcd66 + 4090c0e commit e70c7b3

File tree

92 files changed

+2247
-544
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

92 files changed

+2247
-544
lines changed

.coveragerc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# .coveragerc to control coverage.py
22
[run]
3-
branch = True
4-
parallel = True
3+
#branch = True
4+
#parallel = True
55

66
[report]
77
# Regexes for lines to exclude from consideration

.gitignore

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ static/MathJax
1414

1515
flasklog
1616

17+
# Testing files
18+
htmlcov
19+
.coverage*
20+
.pytest_cache/
21+
1722
# vim swap files
1823
.*.sw?
1924
# backup files
@@ -22,8 +27,7 @@ paul_scripts
2227

2328
local.sh
2429

25-
lmfdb/cover
26-
lmfdb/.coverage
27-
.coverage
2830
.DS_Store
2931
.idea/
32+
LMFDBinventory.log
33+
LMFDBtransactions_inv.log

.travis.yml

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ install:
2929
- parallel --version
3030
# install the latest pyflakes
3131
- pip install pyflakes --user
32-
# install the latest codecov
33-
- pip install codecov --user
32+
# install the latest coveralls
33+
- pip install coveralls --user
3434
- export PATH=${HOME}/.local/bin/:${PATH}
3535
# install SAGE with GAP already built in
3636
- export SAGE_VERSION=8.1
@@ -47,22 +47,11 @@ install:
4747
- ${SAGE} -python -c 'from sage.all import gap;G = gap.TransitiveGroup(9, 2); print G'
4848
# install LMFDB requirements
4949
- ${SAGE} -pip install -r requirements.txt
50-
# hack nosetests to run in parallel, otherwise all the processes try to write into the same file
51-
# this equivalent to have parallel = True in .coveragerc (but nosetests overwrites)
52-
# we also disable the coverage report in nosetests
53-
- wget https://raw.githubusercontent.com/edgarcosta/binary-pkg/master/patches/cover.py.patch
54-
- patch ${SAGE_DIR}/local/lib/python2.7/site-packages/nose/plugins/cover.py cover.py.patch --verbose
5550

5651
before_script:
57-
# make the testmatch a environment variable
58-
# alternatively one could, try to escape the string accordingly
59-
# however, due to the nested calling of sage and then parallel
60-
# it gets quite tricky.
61-
- export TESTMATCH='"(?:^|\/)[Tt]est_"'
62-
- export COVERAGE='--with-coverage --cover-package=lmfdb'
6352
# assert that m0.lmfdb.xyz accepts our connections
6453
- nc -vz m0.lmfdb.xyz 27017
65-
# create a list of files and folder where we will run the nosetests
54+
# create a list of files and folder where we will run the tests
6655
- ls lmfdb/*.py > list
6756
- ls -d lmfdb/*/ >> list
6857
# how much free ram do we have
@@ -74,19 +63,15 @@ script:
7463
# run pyflakes
7564
- pyflakes lmfdb/ > pyflakeslog
7665
- if [[ $(wc -l < pyflakeslog) != 0 ]]; then echo "ERROR pyflakes failed!"; cat pyflakeslog; else echo "PASS pyflakes is happy!"; fi
77-
# run nosetests in parallel with the aid of parallel
78-
# we cannot use the option --processes in nosetests, as MongoDB doesn't support forking
79-
# usually we have at most 4gb of RAM per test, we should avoid running many jobs at once
80-
- ${SAGE} -sh -c 'parallel --joblog joblog --jobs 3 --results nosetests --group --progress --verbose -a list ${SAGE_DIR}/local/bin/nosetests --verbosity=3 -s --testmatch=${TESTMATCH} ${COVERAGE}'
66+
# Check that pytest is installed
67+
- ${SAGE} -sh -c "pytest --version"
68+
# This runs without fail
69+
- ${SAGE} -sh -c "pytest --verbose -s --cov=lmfdb"
8170

8271
after_failure:
8372
- if [[ $(wc -l < pyflakeslog) != 0 ]]; then echo "ERROR pyflakes failed!"; cat pyflakeslog; else echo "PASS pyflakes is happy!"; fi
84-
# print the logs with failed tests
85-
- grep 'FAILED' -r nosetests -l > greplog ; cat greplog
86-
- parallel -a greplog echo ERROR in filename = '{}' \; cat '{}' \; echo \;
8773

8874
after_success:
8975
- ls -a
90-
- coverage combine
91-
- codecov
92-
76+
#- COVERALLS_PARALLEL=true coveralls
77+
- coveralls

lmfdb/WebCharacter.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from sage.all import gcd, Rational, power_mod, Integers, gp, xsrange
55
from flask import url_for
66
import lmfdb
7-
from lmfdb.utils import make_logger
7+
from lmfdb.utils import make_logger, web_latex_split_on_pm
88
logger = make_logger("DC")
99
from lmfdb.nfutils.psort import ideal_label, ideal_from_label
1010
from WebNumberField import WebNumberField
@@ -789,7 +789,11 @@ def genvalues(self): return None
789789
@property
790790
def indlabel(self): return None
791791
def value(self, *args): return None
792-
def charsums(self, *args): return False
792+
793+
@property
794+
def charsums(self, *args):
795+
return False
796+
793797
def gauss_sum(self, *args): return None
794798
def jacobi_sum(self, *args): return None
795799
def kloosterman_sum(self, *args): return None
@@ -1239,9 +1243,9 @@ def title(self):
12391243
return "Group of Hecke characters modulo %s"%(self.modulus)
12401244

12411245
@property
1242-
def nf_pol(self):
1246+
def nfpol(self):
12431247
#return self.nf.web_poly()
1244-
return self.k.polynomial()._latex_()
1248+
return web_latex_split_on_pm(self.k.polynomial())
12451249

12461250
@property
12471251
def codegen(self):

lmfdb/abvar/fq/main.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ def abelian_varieties_by_gqi(g, q, iso):
107107
return render_template("show-abvarfq.html",
108108
properties2=cl.properties(),
109109
credit=abvarfq_credit,
110-
title='Abelian Variety isogeny class %s over $%s$'%(label, cl.field()),
110+
title='Abelian Variety Isogeny Class %s over $%s$'%(label, cl.field()),
111111
bread=bread,
112112
cl=cl,
113113
learnmore=learnmore_list())
@@ -196,7 +196,7 @@ def abelian_variety_search(**args):
196196
info['report'] = 'displaying matches %s-%s of %s' %(start + 1, min(nres, start+count), nres)
197197
else:
198198
info['report'] = 'displaying all %s matches' % nres
199-
t = 'Abelian Variety search results'
199+
t = 'Abelian Variety Search Results'
200200
return render_template("abvarfq-search-results.html", info=info, credit=abvarfq_credit, bread=bread, title=t)
201201

202202
def abelian_variety_browse(**args):
@@ -269,7 +269,7 @@ def abelian_variety_browse(**args):
269269
def search_input_error(info=None, bread=None):
270270
if info is None: info = {'err':'','query':{}}
271271
if bread is None: bread = get_bread(('Search Results', '.'))
272-
return render_template("abvarfq-search-results.html", info=info, title='Abelian Variety search input error', bread=bread)
272+
return render_template("abvarfq-search-results.html", info=info, title='Abelian Variety Search Input Error', bread=bread)
273273

274274
@abvarfq_page.route("/<label>")
275275
def by_label(label):
@@ -338,21 +338,21 @@ def download_search(info):
338338

339339
@abvarfq_page.route("/Completeness")
340340
def completeness_page():
341-
t = 'Completeness of the Weil polynomial data'
341+
t = 'Completeness of the Weil Polynomial Data'
342342
bread = get_bread(('Completeness', '.'))
343343
return render_template("single.html", kid='dq.av.fq.extent',
344344
credit=abvarfq_credit, title=t, bread=bread, learnmore=learnmore_list_remove('Completeness'))
345345

346346
@abvarfq_page.route("/Source")
347347
def how_computed_page():
348-
t = 'Source of the Weil polynomial data'
348+
t = 'Source of the Weil Polynomial Data'
349349
bread = get_bread(('Source', '.'))
350350
return render_template("single.html", kid='dq.av.fq.source',
351351
credit=abvarfq_credit, title=t, bread=bread, learnmore=learnmore_list_remove('Source'))
352352

353353
@abvarfq_page.route("/Labels")
354354
def labels_page():
355-
t = 'Labels for isogeny classes of abelian varieties'
355+
t = 'Labels for Isogeny Classes of Abelian Varieties'
356356
bread = get_bread(('Labels', '.'))
357357
return render_template("single.html", kid='av.fq.lmfdb_label',
358358
credit=abvarfq_credit, title=t, bread=bread, learnmore=learnmore_list_remove('Labels'))

lmfdb/api/api.py

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,7 @@ def collection_indexed_keys(collection):
7070
input: cursor for the collection
7171
output: a set with all the keys indexed
7272
"""
73-
indexed_keys = set({});
74-
for name, val in collection.index_information().iteritems():
75-
if name != '_id_':
76-
#print val['key']
77-
for key, _ in val['key']:
78-
#print key
79-
indexed_keys.add(key)
80-
return indexed_keys
81-
73+
return set([t[0] for t in sum([val['key'] for name, val in collection.index_information().iteritems() if name!='_id_'],[])])
8274

8375
def get_database_info(show_hidden=False):
8476
C = base.getDBConnection()
@@ -191,7 +183,7 @@ def api_query(db, collection, id = None):
191183
return flask.abort(404)
192184
single_object = True
193185
data = []
194-
api_logger.info("API query: id = '%s', fields = '%s'" % (id, fields))
186+
api_logger.debug("API query: id = '%s', fields = '%s'" % (id, fields))
195187
# if id looks like an ObjectId, assume it is and try to find it
196188
if len(id) == 24 and re.match('[0-9a-f]+$', id.strip()):
197189
data = C[db][collection].find_one({'_id':ObjectId(id)},projection=fields)
@@ -239,6 +231,8 @@ def api_query(db, collection, id = None):
239231

240232
# assure that one of the keys of the query is indexed
241233
# however, this doesn't assure that the query will be fast...
234+
#print("Keys in query: {}".format(q.keys()))
235+
#print("Keys indexed in collection {}.{}: {}".format(db,collection,collection_indexed_keys(C[db][collection])))
242236
if q != {} and len(set(q.keys()).intersection(collection_indexed_keys(C[db][collection]))) == 0:
243237
flash_error("no key in the query %s is indexed.", q)
244238
return flask.redirect(url_for(".api_query", db=db, collection=collection))
@@ -257,7 +251,7 @@ def api_query(db, collection, id = None):
257251
sort = None
258252

259253
# executing the query "q" and replacing the _id in the result list
260-
api_logger.info("API query: q = '%s', fields = '%s', sort = '%s', offset = %s" % (q, fields, sort, offset))
254+
api_logger.debug("API query: q = '%s', fields = '%s', sort = '%s', offset = %s" % (q, fields, sort, offset))
261255
from pymongo.errors import ExecutionTimeout
262256
try:
263257
data = list(C[db][collection].find(q, projection = fields, sort=sort).skip(offset).limit(100).max_time_ms(10000))

lmfdb/api/templates/api.html

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,20 +63,21 @@ <h4>Examples</h4>
6363
<a href='{{ url_for(".api_query", db="elliptic_curves", collection="curves", rank="i2", torsion="i5")}}'><code>?rank=i2&amp;torsion=i5</code></a>.
6464
</li>
6565
<li>
66-
A list of strings (string encoded integers) for the <code>ainvs</code> parameter of an elliptic curve is
67-
<a href='{{ url_for(".api_query", db="elliptic_curves", collection="curves", ainvs="ls0;1;1;-840;39800", _format="yaml", _delim=";")}}'>
68-
<code>?ainvs=ls0;1;1;-840;39800&amp;_format=yaml&amp;_delim=;</code></a>,
69-
where the delimiter is "<code>;</code>" and the result formatted in YAML.
66+
A string encoding a list of integers for the <code>xainvs</code> parameter of an elliptic curve is
67+
<a href='{{ url_for(".api_query", db="elliptic_curves", collection="curves", xainvs="s[0,1,1,-840,39800]", _format="yaml")}}'>
68+
<code>?xainvs=s[0,1,1,-840,39800]&amp;_format=yaml</code></a>,
69+
the result formatted in YAML.
7070
</li>
71+
{#
7172
<li>
7273
This query <a href='{{ url_for('.api_query', db="elliptic_curves", collection="curves", isogeny_matrix="py[[1,13],[13,1]]", _format="json") }}'>?isogeny_matrix=py[[1,13],[13,1]]</a>
7374
returns elliptic curves where the isogeny matrix is $\left(\begin{smallmatrix}1 & 13\\ 13 & 1\end{smallmatrix}\right)$.
7475
</li>
76+
#}
7577
<li>
76-
To see those elliptic curves, where the <code>ainvs</code> list contains the string-encoded integer <code>-769</code>
77-
and the field <code>non-surjective_primes</code> contains the integer number 3:
78-
{% set kw = {"non-surjective_primes" : "ci3"} %}
79-
<a href='{{ url_for(".api_query", db="elliptic_curves", collection="curves", ainvs="cs-769", **kw) }}'>?ainvs=cs-769&amp;non-surjective_primes=ci3</a>.
78+
To see those elliptic curves, where the field <code>torsion_structure</code> contains the list [2,2], encoded as a list of strings:
79+
<a href='{{ url_for(".api_query", db="elliptic_curves",
80+
collection="curves", torsion_structure="ls2;2", _delim=";")}}'>?torsion_structure=ls2;2&amp;_delim=;</a>.
8081
</li>
8182
<li>To only retrieve the fields <code>authors</code> and <code>last_author</code> of the knowl documents,
8283
query <a href="{{ url_for('.api_query', db='knowledge', collection='knowls', _fields='authors,last_author') }}"</a>?_fields=authors,last_author</a>.

lmfdb/api/test_api.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# -*- coding: utf-8 -*-
2+
from lmfdb.base import LmfdbTest
3+
4+
class ApiTest(LmfdbTest):
5+
6+
7+
def test_api_home(self):
8+
r"""
9+
Check that the top-level api page works
10+
"""
11+
data = self.tc.get("/api", follow_redirects=True).data
12+
assert "API for accessing the LMFDB Database" in data
13+
14+
def test_api_databases(self):
15+
r"""
16+
Check that one collection from each database works
17+
"""
18+
dbs = [ ['HTPicard','picard'], ['Lattices','lat'],
19+
['Lfunctions','Lfunctions'],
20+
['MaassWaveForms','Coefficients'],
21+
['SL2Zsubgroups','groups'], ['abvar','fq_isog'],
22+
['artin','representations'], ['bmfs','forms'],
23+
['curve_automorphisms','passports'],
24+
['elliptic_curves','curves'],
25+
['genus2_curves','curves'],
26+
['halfintegralmf','forms'], ['hgm','motives'],
27+
['hmfs','forms'], ['localfields','fields'],
28+
['mod_l_eigenvalues','modlmf'],
29+
['mod_l_galois','reps'],
30+
['modularforms2','dimension_table'],
31+
['numberfields','fields'],
32+
['sato_tate_groups','st_groups'],
33+
['siegel_modular_forms','dimensions'],['transitivegroups','groups'],
34+
['characters','Dirichlet_char_modl'],
35+
['finite_fields','finite_fields'],
36+
['hecke_algebras','hecke_algebras'],
37+
['embedded_mfs','mfs'], ['belyi','passports']]
38+
for db, coll in dbs:
39+
data = self.tc.get("/api/{}/{}".format(db,coll), follow_redirects=True).data
40+
assert "JSON" in data
41+
42+
def test_api_examples_html(self):
43+
r"""
44+
Check that the sample queries on the top page all work (html output)
45+
"""
46+
queries = ['elliptic_curves/curves/?rank=i2&torsion=i5',
47+
#'elliptic_curves/curves/?isogeny_matrix=py[[1,13],[13,1]]', # no index on isogeny_matrix
48+
'elliptic_curves/curves/?xainvs=cs-1215&torsion_structure=ls2;2&_delim=;',
49+
'knowledge/knowls/?_fields=authors,last_author',
50+
'knowledge/knowls/?_fields=content,authors&_sort=timestamp']
51+
for query in queries:
52+
data = self.tc.get("/api/{}".format(query), follow_redirects=True).data
53+
assert 'Query: <code><a href="/api/' in data
54+
assert not "Error:" in data
55+
56+
def test_api_examples_yaml(self):
57+
r"""
58+
Check that the sample queries on the top page all work (yaml output)
59+
"""
60+
queries = [#'elliptic_curves/curves/?ainvs=ls0;1;1;-840;39800&_format=yaml&_delim=;', # no index on ainvs
61+
'elliptic_curves/curves/?xainvs=s[0,1,1,-840,39800]&_format=yaml']
62+
for query in queries:
63+
data = self.tc.get("/api/{}".format(query), follow_redirects=True).data
64+
assert "!!python/unicode 'x-coordinates_of_integral_points': !!python/unicode '[-42,-39,-21,0,15,21,24,42,77,126,231,302,420,609,1560,3444,14595]'" in data
65+
assert not "Error:" in data
66+
67+
def test_api_examples_json(self):
68+
r"""
69+
Check that the sample queries on the top page all work (json output)
70+
"""
71+
query = 'numberfields/fields/?signature=s2,5&_format=json'
72+
data = self.tc.get("/api/{}".format(query), follow_redirects=True).data
73+
assert '"label": "12.2.167630295667.1"' in data
74+
75+
76+
def test_api_usage(self):
77+
r"""
78+
Check that the queries used by ODK demo all work
79+
"""
80+
queries = ['transitivegroups/groups?_format=json&label=1T1',
81+
'transitivegroups/groups?_format=json&label=8T3',
82+
'elliptic_curves/curves?_format=json&label=11a1']
83+
for query in queries:
84+
data = self.tc.get("/api/{}".format(query), follow_redirects=True).data
85+
if '1T1' in query:
86+
assert '"name": "Trivial group"' in data
87+
if '8T3' in query:
88+
assert '"name": "E(8)=2[x]2[x]2"' in data
89+
if '11a1' in query:
90+
assert '"equation": "\\\\( y^2 + y = x^{3} - x^{2} - 10 x - 20 \\\\)"' in data

lmfdb/artin_representations/databases/Dokchitser_databases.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
artin_location = ("artin", "representations")
22
galois_group_location = ("artin", "field_data")
3-
#artin_location = ("artin", "representations_new")
4-
#galois_group_location = ("artin", "field_data_new")
3+
artin_location = ("artin", "representations_new")
4+
galois_group_location = ("artin", "field_data_new")
5+
56

67
from type_generation import String, Array, Dict, Int, Anything
78

@@ -57,6 +58,7 @@ class IndexAt1(Int):
5758
Dokchitser_ArtinRepresentation = Dict({
5859
"_id": Anything,
5960
"Baselabel": String,
61+
"Container": Anything,
6062
"Dim": Int,
6163
"Indicator": Int,
6264
"Conductor": TooLargeInt,

0 commit comments

Comments
 (0)