Skip to content

Move package metadata into pyproject.toml and all other python code into separate file #4970

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 46 commits into from
Feb 7, 2025
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
a6f02b7
Move package metadata into pyproject.toml and all other python code i…
marthacryan Jan 14, 2025
7be470b
Cleanup extra changes
marthacryan Jan 14, 2025
7170a51
Revert changes to command names
marthacryan Jan 14, 2025
6a2d9bc
Add version attr
marthacryan Jan 14, 2025
37807da
Add correct output directory for artifacts
marthacryan Jan 14, 2025
41cd025
Move version into separate file
marthacryan Jan 15, 2025
7fd6870
Attempt to fix version issues
marthacryan Jan 16, 2025
cdd0204
Attempt to fix version issues
marthacryan Jan 16, 2025
48cc36a
Merge with master
marthacryan Jan 30, 2025
9795406
Add pip install editable to CI config
marthacryan Jan 30, 2025
39750d5
Add version attribute
marthacryan Jan 30, 2025
937ad46
Remove extra reference to version.py
marthacryan Jan 30, 2025
0d06ded
Code format
marthacryan Jan 30, 2025
ca9aa0a
Explicitly import importlib.metadata
marthacryan Jan 30, 2025
ec7c557
Add __name__ == main wrapper around command line arg parsing
marthacryan Jan 30, 2025
6ea167d
update to python 3.9 for dev build to fix importlib error
marthacryan Jan 30, 2025
6f40cdc
Remove unnecessary widget version
marthacryan Jan 30, 2025
2ef2559
Update version of python for dev build CI
marthacryan Jan 30, 2025
634c787
Add pip install editable
marthacryan Jan 30, 2025
8abdeaf
Add pyproject.toml to conda recipe
marthacryan Jan 30, 2025
dafa57f
Fix filepath in conda recipe
marthacryan Jan 30, 2025
370efcd
Fix accessing of pyproject.toml version in conda recipe
marthacryan Feb 3, 2025
dc1b55b
Merge with master
marthacryan Feb 4, 2025
011d410
Remove setup.py from root
marthacryan Feb 4, 2025
48e7de3
Fix filepath in commands.py
marthacryan Feb 4, 2025
d1905cb
Use new variable name for project root in commands.py
marthacryan Feb 4, 2025
f68d997
Remove conda from CI and release
marthacryan Feb 4, 2025
2a366ef
Add license file and pytest to pyproject.toml
marthacryan Feb 4, 2025
69897ae
Fix syntax issues with pyproject.toml
marthacryan Feb 4, 2025
bcfa6a7
Update release instructions
marthacryan Feb 4, 2025
1f1dae9
remove versioneer from manifest.in
marthacryan Feb 5, 2025
2ca6dae
Pin narwhals version
marthacryan Feb 5, 2025
a7499c1
Update pyproject.toml
marthacryan Feb 5, 2025
56d2096
Remove wheel install from CI
marthacryan Feb 5, 2025
ac57d7d
Merge branch 'use-pyprojecttoml' of github.com:plotly/plotly.py into …
marthacryan Feb 5, 2025
c6992fc
Update pin of pandas instead of narwhals
marthacryan Feb 5, 2025
5111cfa
Merge branch 'master' of github.com:plotly/plotly.py into use-pyproje…
marthacryan Feb 5, 2025
15a7028
Move tests out of the plotly directory
marthacryan Feb 6, 2025
f3db071
Rename any references to plotly/tests with just tests
marthacryan Feb 6, 2025
6acd25a
Move plotly_utils tests into root tests directory
marthacryan Feb 6, 2025
0c343ef
Reset filepath to one that will cause import to fail
marthacryan Feb 6, 2025
98f2c8f
Fix filepath in optional_imports test
marthacryan Feb 6, 2025
28a5b74
Update filepaths to plotly_utils tests
marthacryan Feb 6, 2025
39032fb
Black
marthacryan Feb 6, 2025
4573074
Black
marthacryan Feb 6, 2025
10b2b87
Merge with master
marthacryan Feb 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 5 additions & 9 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -351,18 +351,12 @@ jobs:
pip install --upgrade pip wheel
pip install -r ./test_requirements/requirements_38_core.txt black inflect
pip install jupyterlab
- run:
name: Update jupyter widget plotly.js version
command: |
cd packages/python/plotly
. venv/bin/activate
python setup.py updateplotlywidgetversion
- run:
name: Update plotly.js to dev
command: |
cd packages/python/plotly
. venv/bin/activate
python setup.py updateplotlyjsdev
python commands.py updateplotlyjsdev
- run:
name: Test core
command: |
Expand All @@ -385,7 +379,8 @@ jobs:
command: |
cd packages/python/plotly
. venv/bin/activate
python setup.py sdist
pip install build
python -m build --sdist --wheel -o dist
when: always
- store_artifacts:
path: packages/python/plotly/dist
Expand Down Expand Up @@ -426,7 +421,8 @@ jobs:
eval "$(conda shell.bash hook)"
conda activate env
cd packages/python/plotly
python setup.py sdist bdist_wheel
pip install build
python -m build --sdist --wheel -o dist
cp -R dist ../../../output/dist
git status

Expand Down
6 changes: 3 additions & 3 deletions contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ Then run the `updateplotlyjs` command with:

```bash
$ cd packages/python/plotly
$ python setup.py updateplotlyjs
$ python commands.py updateplotlyjs
```

This will download new versions of `plot-schema.json` and `plotly.min.js` from
Expand All @@ -236,7 +236,7 @@ For dev branches, it is also possible to use `updateplotlyjsdev` in two configur

If your devbranch is part of the official plotly.js repository, you can use
```bash
python setup.py updateplotlyjsdev --devrepo reponame --devbranch branchname
python commands.py updateplotlyjsdev --devrepo reponame --devbranch branchname
```
to update to development versions of `plotly.js`. This will fetch the `plotly.js` in the CircleCI artifact of the branch `branchname` of the repo `reponame`. If `--devrepo` or `--devbranch` are omitted, `updateplotlyjsdev` defaults using `plotly/plotly.js` and `master` respectively.

Expand All @@ -252,7 +252,7 @@ $ npm pack
$ mv plotly.js-*.tgz plotly.js.tgz

# In your plotly.py/packages/python/plotly/ directory:
$ python setup.py updateplotlyjsdev --local /path/to/your/plotly.js/
$ python commands.py updateplotlyjsdev --local /path/to/your/plotly.js/
```

## Testing
Expand Down
304 changes: 304 additions & 0 deletions packages/python/plotly/commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,304 @@
import os
import sys
import time
import platform
import json
import shutil

from subprocess import check_call
from distutils import log

here = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.dirname(os.path.dirname(os.path.dirname(here)))
node_root = os.path.join(project_root, "packages", "python", "plotly", "js")
is_repo = os.path.exists(os.path.join(project_root, ".git"))
node_modules = os.path.join(node_root, "node_modules")
targets = [
os.path.join(here, "plotly", "package_data", "widgetbundle.js"),
]

npm_path = os.pathsep.join(
[
os.path.join(node_root, "node_modules", ".bin"),
os.environ.get("PATH", os.defpath),
]
)

# Load plotly.js version from js/package.json
def plotly_js_version():
path = os.path.join(here, "js", "package.json")
with open(path, "rt") as f:
package_json = json.load(f)
version = package_json["dependencies"]["plotly.js"]
version = version.replace("^", "")

return version


# install package.json dependencies using npm
def install_js_deps(local):
npmName = "npm"
if platform.system() == "Windows":
npmName = "npm.cmd"

try:
check_call([npmName, "--version"])
has_npm = True
except:
has_npm = False


skip_npm = os.environ.get("SKIP_NPM", False)
if skip_npm:
log.info("Skipping npm-installation")
return

if not has_npm:
log.error(
"`npm` unavailable. If you're running this command using sudo, make sure `npm` is available to sudo"
)

env = os.environ.copy()
env["PATH"] = npm_path

if has_npm:
log.info(
"Installing build dependencies with npm. This may take a while..."
)
check_call(
[npmName, "install"],
cwd=node_root,
stdout=sys.stdout,
stderr=sys.stderr,
)
if local is not None:
plotly_archive = os.path.join(local, "plotly.js.tgz")
check_call(
[npmName, "install", plotly_archive],
cwd=node_root,
stdout=sys.stdout,
stderr=sys.stderr,
)
check_call(
[npmName, "run", "build"],
cwd=node_root,
stdout=sys.stdout,
stderr=sys.stderr,
)
os.utime(node_modules, None)

for t in targets:
if not os.path.exists(t):
msg = "Missing file: %s" % t
raise ValueError(msg)

# Generate class hierarchy from Plotly JSON schema
def run_codegen():
if sys.version_info < (3, 8):
raise ImportError("Code generation must be executed with Python >= 3.8")

from codegen import perform_codegen

perform_codegen()


def overwrite_schema_local(uri):
path = os.path.join(here, "codegen", "resources", "plot-schema.json")
shutil.copyfile(uri, path)


def overwrite_schema(url):
import requests

req = requests.get(url)
assert req.status_code == 200
path = os.path.join(here, "codegen", "resources", "plot-schema.json")
with open(path, "wb") as f:
f.write(req.content)


def overwrite_bundle_local(uri):
path = os.path.join(here, "plotly", "package_data", "plotly.min.js")
shutil.copyfile(uri, path)


def overwrite_bundle(url):
import requests

req = requests.get(url)
print('url:', url)
assert req.status_code == 200
path = os.path.join(here, "plotly", "package_data", "plotly.min.js")
with open(path, "wb") as f:
f.write(req.content)


def overwrite_plotlyjs_version_file(plotlyjs_version):
path = os.path.join(here, "plotly", "offline", "_plotlyjs_version.py")
with open(path, "w") as f:
f.write(
"""\
# DO NOT EDIT
# This file is generated by the updatebundle commands.py command
__plotlyjs_version__ = "{plotlyjs_version}"
""".format(
plotlyjs_version=plotlyjs_version
)
)

def request_json(url):
import requests

req = requests.get(url)
return json.loads(req.content.decode("utf-8"))


def get_latest_publish_build_info(repo, branch):
url = (
r"https://circleci.com/api/v1.1/project/github/"
r"{repo}/tree/{branch}?limit=100&filter=completed"
).format(repo=repo, branch=branch)

branch_jobs = request_json(url)

# Get most recent successful publish build for branch
builds = [
j
for j in branch_jobs
if j.get("workflows", {}).get("job_name", None) == "publish-dist"
and j.get("status", None) == "success"
]
build = builds[0]

# Extract build info
return {p: build[p] for p in ["vcs_revision", "build_num", "committer_date"]}


def get_bundle_schema_local(local):
plotly_archive = os.path.join(local, "plotly.js.tgz")
plotly_bundle = os.path.join(local, "dist/plotly.min.js")
plotly_schemas = os.path.join(local, "dist/plot-schema.json")
return plotly_archive, plotly_bundle, plotly_schemas


def get_bundle_schema_urls(build_num):
url = (
"https://circleci.com/api/v1.1/project/github/"
"plotly/plotly.js/{build_num}/artifacts"
).format(build_num=build_num)

artifacts = request_json(url)

# Find archive
archives = [a for a in artifacts if a.get("path", None) == "plotly.js.tgz"]
archive = archives[0]

# Find bundle
bundles = [a for a in artifacts if a.get("path", None) == "dist/plotly.min.js"]
bundle = bundles[0]

# Find schema
schemas = [a for a in artifacts if a.get("path", None) == "dist/plot-schema.json"]
schema = schemas[0]

return archive["url"], bundle["url"], schema["url"]


# Download latest version of the plot-schema JSON file
def update_schema(plotly_js_version):
url = (
"https://raw.githubusercontent.com/plotly/plotly.js/"
"v%s/dist/plot-schema.json" % plotly_js_version
)
overwrite_schema(url)

# Download latest version of the plotly.js bundle
def update_bundle(plotly_js_version):
url = (
"https://raw.githubusercontent.com/plotly/plotly.js/"
"v%s/dist/plotly.min.js" % plotly_js_version
)
overwrite_bundle(url)

# Write plotly.js version file
plotlyjs_version = plotly_js_version
overwrite_plotlyjs_version_file(plotlyjs_version)

# Update project to a new version of plotly.js
def update_plotlyjs(plotly_js_version):
update_bundle(plotly_js_version)
update_schema(plotly_js_version)
run_codegen()

# Update the plotly.js schema and bundle from master
def update_schema_bundle_from_master():

if "--devrepo" in sys.argv:
devrepo = sys.argv[sys.argv.index("--devrepo") + 1]
else:
devrepo = "plotly/plotly.js"

if "--devbranch" in sys.argv:
devbranch = sys.argv[sys.argv.index("--devbranch") + 1]
else:
devbranch = "master"

if "--local" in sys.argv:
local = sys.argv[sys.argv.index("--local") + 1]
else:
local = None

if local is None:
build_info = get_latest_publish_build_info(devrepo, devbranch)

archive_url, bundle_url, schema_url = get_bundle_schema_urls(
build_info["build_num"]
)

# Update bundle in package data
overwrite_bundle(bundle_url)

# Update schema in package data
overwrite_schema(schema_url)
else:
# this info could be more informative but
# it doesn't seem as useful in a local context
# and requires dependencies and programming.
build_info = {"vcs_revision": "local", "committer_date": str(time.time())}
devrepo = local
devbranch = ""

archive_uri, bundle_uri, schema_uri = get_bundle_schema_local(local)
overwrite_bundle_local(bundle_uri)
overwrite_schema_local(schema_uri)

# Update plotly.js url in package.json
package_json_path = os.path.join(node_root, "package.json")
with open(package_json_path, "r") as f:
package_json = json.load(f)

# Replace version with bundle url
package_json["dependencies"]["plotly.js"] = (
archive_url if local is None else archive_uri
)
with open(package_json_path, "w") as f:
json.dump(package_json, f, indent=2)

# update plotly.js version in _plotlyjs_version
rev = build_info["vcs_revision"]
date = str(build_info["committer_date"])
version = "_".join([devrepo, devbranch, date[:10], rev[:8]])
overwrite_plotlyjs_version_file(version)
install_js_deps(local)

# Update project to a new development version of plotly.js
def update_plotlyjs_dev():
update_schema_bundle_from_master()
run_codegen()

if "updateplotlyjsdev" in sys.argv:
update_plotlyjs_dev()
elif "updateplotlyjs" in sys.argv:
print(plotly_js_version())
update_plotlyjs(plotly_js_version())

3 changes: 3 additions & 0 deletions packages/python/plotly/plotly/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,6 @@ def hist_series(data_frame, **kwargs):
skip += ["figsize", "bins", "legend"]
new_kwargs = {k: kwargs[k] for k in kwargs if k not in skip}
return histogram(data_frame, **new_kwargs)

__version__ = "6.3.0"
version = __version__
Loading