Skip to content

Commit 6c45ef3

Browse files
committed
Starter code for chapter 10, using sqlalchemy.
1 parent cfd9ae4 commit 6c45ef3

Some content is hidden

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

65 files changed

+1526
-0
lines changed

.gitignore

+8
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,11 @@ app/ch09_sqlalchmey/final/.idea/dataSources.local.xml
123123
app/ch09_sqlalchmey/final/.idea/dataSources/583a04da-ae18-4c33-bbf0-6a3e12d3db43.xml
124124
app/ch09_sqlalchmey/final/.idea/dataSources/8589e457-43bb-4280-ba68-787968d5cb61.xml
125125
app/ch09_sqlalchmey/final/pypi_org/db/pypi.sqlite
126+
app/ch09_sqlalchemy/final/.idea/dataSources.local.xml
127+
app/ch09_sqlalchemy/final/.idea/misc.xml
128+
app/ch09_sqlalchemy/final/.idea/modules.xml
129+
app/ch09_sqlalchemy/final/.idea/dataSources/583a04da-ae18-4c33-bbf0-6a3e12d3db43.xml
130+
app/ch09_sqlalchemy/final/.idea/dataSources/8589e457-43bb-4280-ba68-787968d5cb61.xml
131+
app/ch09_sqlalchemy/starter/.idea/misc.xml
132+
app/ch09_sqlalchemy/starter/.idea/modules.xml
133+
pypi.sqlite
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import os
2+
3+
import flask
4+
import pypi_org.data.db_session as db_session
5+
6+
app = flask.Flask(__name__)
7+
8+
9+
def main():
10+
register_blueprints()
11+
setup_db()
12+
app.run(debug=True)
13+
14+
15+
def setup_db():
16+
db_file = os.path.join(
17+
os.path.dirname(__file__),
18+
'db',
19+
'pypi.sqlite')
20+
21+
db_session.global_init(db_file)
22+
23+
24+
def register_blueprints():
25+
from pypi_org.views import home_views
26+
from pypi_org.views import package_views
27+
from pypi_org.views import cms_views
28+
29+
app.register_blueprint(package_views.blueprint)
30+
app.register_blueprint(home_views.blueprint)
31+
app.register_blueprint(cms_views.blueprint)
32+
33+
34+
if __name__ == '__main__':
35+
main()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Add all your SQLAlchemy models here.
2+
# This allows us to import just this file when
3+
# we need to preload the models and ensure they
4+
# are all loaded.
5+
6+
# noinspection PyUnresolvedReferences
7+
import pypi_org.data.downloads
8+
# noinspection PyUnresolvedReferences
9+
import pypi_org.data.languages
10+
# noinspection PyUnresolvedReferences
11+
import pypi_org.data.licenses
12+
# noinspection PyUnresolvedReferences
13+
import pypi_org.data.maintainers
14+
# noinspection PyUnresolvedReferences
15+
import pypi_org.data.package
16+
# noinspection PyUnresolvedReferences
17+
import pypi_org.data.releases
18+
# noinspection PyUnresolvedReferences
19+
import pypi_org.data.users
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import sqlalchemy as sa
2+
import sqlalchemy.orm as orm
3+
4+
from pypi_org.data.modelbase import SqlAlchemyBase
5+
6+
factory = None
7+
8+
9+
def global_init(db_file: str):
10+
global factory
11+
12+
if factory:
13+
return
14+
15+
if not db_file or not db_file.strip():
16+
raise Exception("You must specify a db file.")
17+
18+
conn_str = 'sqlite:///' + db_file.strip()
19+
print("Connecting to DB with {}".format(conn_str))
20+
21+
engine = sa.create_engine(conn_str, echo=False)
22+
factory = orm.sessionmaker(bind=engine)
23+
24+
# noinspection PyUnresolvedReferences
25+
import pypi_org.data.__all_models
26+
27+
SqlAlchemyBase.metadata.create_all(engine)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import datetime
2+
import sqlalchemy
3+
from pypi_org.data.modelbase import SqlAlchemyBase
4+
5+
6+
class Download(SqlAlchemyBase):
7+
__tablename__ = 'downloads'
8+
9+
id = sqlalchemy.Column(sqlalchemy.BigInteger, primary_key=True, autoincrement=True)
10+
created_date = sqlalchemy.Column(sqlalchemy.DateTime, default=datetime.datetime.now, index=True)
11+
12+
package_id = sqlalchemy.Column(sqlalchemy.String, index=True)
13+
release_id = sqlalchemy.Column(sqlalchemy.BigInteger, index=True)
14+
15+
ip_address = sqlalchemy.Column(sqlalchemy.String)
16+
user_agent = sqlalchemy.Column(sqlalchemy.String)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import datetime
2+
import sqlalchemy
3+
from pypi_org.data.modelbase import SqlAlchemyBase
4+
5+
6+
class ProgrammingLanguage(SqlAlchemyBase):
7+
__tablename__ = 'languages'
8+
9+
id = sqlalchemy.Column(sqlalchemy.String, primary_key=True)
10+
created_date = sqlalchemy.Column(sqlalchemy.DateTime, default=datetime.datetime.now, index=True)
11+
description = sqlalchemy.Column(sqlalchemy.String)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import datetime
2+
import sqlalchemy
3+
from pypi_org.data.modelbase import SqlAlchemyBase
4+
5+
6+
class License(SqlAlchemyBase):
7+
__tablename__ = 'licenses'
8+
9+
id = sqlalchemy.Column(sqlalchemy.String, primary_key=True)
10+
created_date = sqlalchemy.Column(sqlalchemy.DateTime, default=datetime.datetime.now, index=True)
11+
description = sqlalchemy.Column(sqlalchemy.String)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import sqlalchemy
2+
from pypi_org.data.modelbase import SqlAlchemyBase
3+
4+
5+
class Maintainer(SqlAlchemyBase):
6+
__tablename__ = 'maintainers'
7+
8+
user_id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
9+
package_id = sqlalchemy.Column(sqlalchemy.String, primary_key=True)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import sqlalchemy.ext.declarative as dec
2+
3+
SqlAlchemyBase = dec.declarative_base()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import datetime
2+
from typing import List
3+
4+
import sqlalchemy as sa
5+
import sqlalchemy.orm as orm
6+
from pypi_org.data.modelbase import SqlAlchemyBase
7+
from pypi_org.data.releases import Release
8+
9+
10+
class Package(SqlAlchemyBase):
11+
__tablename__ = 'packages'
12+
13+
id = sa.Column(sa.String, primary_key=True)
14+
created_date = sa.Column(sa.DateTime, default=datetime.datetime.now, index=True)
15+
summary = sa.Column(sa.String, nullable=False)
16+
description = sa.Column(sa.String, nullable=True)
17+
18+
home_page = sa.Column(sa.String)
19+
docs_url = sa.Column(sa.String)
20+
package_url = sa.Column(sa.String)
21+
22+
author_name = sa.Column(sa.String)
23+
author_email = sa.Column(sa.String, index=True)
24+
25+
license = sa.Column(sa.String, index=True)
26+
27+
# releases relationship
28+
releases: List[Release] = orm.relation("Release", order_by=[
29+
Release.major_ver.desc(),
30+
Release.minor_ver.desc(),
31+
Release.build_ver.desc(),
32+
], back_populates='package')
33+
34+
def __repr__(self):
35+
return '<Package {}>'.format(self.id)
36+
37+
38+
# p = Package() # one query
39+
#
40+
# print(p.id)
41+
# print("All releases")
42+
# for r in p.releases:
43+
# print("{}.{}.{}".format(r.major_ver, r.minor_ver, r.build_ver))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import datetime
2+
import sqlalchemy
3+
import sqlalchemy.orm as orm
4+
from pypi_org.data.modelbase import SqlAlchemyBase
5+
6+
7+
class Release(SqlAlchemyBase):
8+
__tablename__ = 'releases'
9+
10+
id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True, autoincrement=True)
11+
12+
major_ver = sqlalchemy.Column(sqlalchemy.BigInteger, index=True)
13+
minor_ver = sqlalchemy.Column(sqlalchemy.BigInteger, index=True)
14+
build_ver = sqlalchemy.Column(sqlalchemy.BigInteger, index=True)
15+
16+
created_date = sqlalchemy.Column(sqlalchemy.DateTime, default=datetime.datetime.now, index=True)
17+
comment = sqlalchemy.Column(sqlalchemy.String)
18+
url = sqlalchemy.Column(sqlalchemy.String)
19+
size = sqlalchemy.Column(sqlalchemy.BigInteger)
20+
21+
# Package relationship
22+
package_id = sqlalchemy.Column(sqlalchemy.String, sqlalchemy.ForeignKey("packages.id"))
23+
package = orm.relation('Package')
24+
25+
@property
26+
def version_text(self):
27+
return '{}.{}.{}'.format(self.major_ver, self.minor_ver, self.build_ver)
28+
29+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import datetime
2+
import sqlalchemy
3+
from pypi_org.data.modelbase import SqlAlchemyBase
4+
5+
6+
class User(SqlAlchemyBase):
7+
__tablename__ = 'users'
8+
9+
id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True, autoincrement=True)
10+
name = sqlalchemy.Column(sqlalchemy.String, nullable=True)
11+
email = sqlalchemy.Column(sqlalchemy.String, index=True, unique=True, nullable=True)
12+
hashed_password = sqlalchemy.Column(sqlalchemy.String, nullable=True, index=True)
13+
created_date = sqlalchemy.Column(sqlalchemy.DateTime, default=datetime.datetime.now, index=True)
14+
profile_image_url = sqlalchemy.Column(sqlalchemy.String)
15+
last_login = sqlalchemy.Column(sqlalchemy.DateTime, default=datetime.datetime.now, index=True)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Just here so git will create this folder.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
from functools import wraps
2+
3+
import flask
4+
5+
6+
def response(*, mimetype: str = None, template_file: str = None):
7+
def response_inner(f):
8+
# print("Wrapping in response {}".format(f.__name__), flush=True)
9+
10+
@wraps(f)
11+
def view_method(*args, **kwargs):
12+
response_val = f(*args, **kwargs)
13+
if isinstance(response_val, flask.Response):
14+
return response_val
15+
16+
if isinstance(response_val, dict):
17+
model = dict(response_val)
18+
else:
19+
model = dict()
20+
21+
if template_file and not isinstance(response_val, dict):
22+
raise Exception(
23+
"Invalid return type {}, we expected a dict as the return value.".format(type(response_val)))
24+
25+
if template_file:
26+
response_val = flask.render_template(template_file, **response_val)
27+
28+
resp = flask.make_response(response_val)
29+
resp.model = model
30+
if mimetype:
31+
resp.mimetype = mimetype
32+
33+
return resp
34+
35+
return view_method
36+
37+
return response_inner
38+
39+
#
40+
# def template(template_file: str = None):
41+
# def template_inner(f):
42+
# @wraps(f)
43+
# def view_method(*args, **kwargs):
44+
# data_dict = f(*args, **kwargs)
45+
# if not isinstance(data_dict, dict):
46+
# raise Exception(
47+
# "Invalid return type {}, we expected a dict as the return value.".format(type(data_dict)))
48+
#
49+
# return flask.render_template(template_file, **data_dict)
50+
#
51+
# return view_method
52+
#
53+
# return template_inner
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
fake_db = {
2+
'/company/history': {
3+
'page_title': 'Company history',
4+
'page_details': 'Details about company history...',
5+
},
6+
'/company/employees': {
7+
'page_title': 'Our team',
8+
'page_details': 'Details about company employees ...',
9+
},
10+
}
11+
12+
13+
def get_page(url: str) -> dict:
14+
if not url:
15+
return {}
16+
17+
url = url.strip().lower()
18+
url = '/' + url.lstrip('/')
19+
20+
page = fake_db.get(url, {})
21+
return page
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
def get_latest_packages():
2+
return [
3+
{'name': 'flask', 'version': '1.2.3'},
4+
{'name': 'sqlalchemy', 'version': '2.2.0'},
5+
{'name': 'passlib', 'version': '3.0.0'},
6+
]

0 commit comments

Comments
 (0)