From b69623971f3c5db48092ed85953e36947a7de33b Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Wed, 15 Apr 2026 10:11:00 +0100 Subject: [PATCH 01/14] add support for search v2 --- tests/test_integration.py | 5 +++++ trading_ig/rest.py | 13 +++++++++++++ 2 files changed, 18 insertions(+) diff --git a/tests/test_integration.py b/tests/test_integration.py index 954065b..e3344ff 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -461,6 +461,11 @@ def test_search_markets(self, ig_service: IGService): response = ig_service.search_markets(search_term) assert isinstance(response, pd.DataFrame) + def test_search_markets_v2(self, ig_service: IGService): + epics = "CS.D.GBPUSD.TODAY.IP" + response = ig_service.search_markets_v2(epics) + assert isinstance(response, pd.DataFrame) + def test_fetch_historical_prices_by_epic_and_numpoints(self, ig_service: IGService): response = ig_service.fetch_historical_prices_by_epic_and_num_points( "CS.D.EURUSD.MINI.IP", "h", 4 diff --git a/trading_ig/rest.py b/trading_ig/rest.py index 4e3c620..aaf1236 100644 --- a/trading_ig/rest.py +++ b/trading_ig/rest.py @@ -1569,6 +1569,19 @@ def search_markets(self, search_term, session=None): data = pd.DataFrame(data["markets"]) return data + def search_markets_v2(self, epics, session=None): + """Returns all markets matching the epics""" + self.non_trading_rate_limit_pause_or_pass() + version = "2" + endpoint = "/markets" + params = {"epics": epics} + action = "read" + response = self._req(action, endpoint, params, session, version) + data = self.parse_response(response.text) + if self.return_dataframe: + data = pd.DataFrame(data["marketDetails"]) + return data + def format_prices(self, prices, version, flag_calc_spread=False): """ Format prices data as a DataFrame with hierarchical columns From 1c44e5a23cb11c14e814f1b89e9b8394df7230ba Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Wed, 15 Apr 2026 10:12:19 +0100 Subject: [PATCH 02/14] better dates in integration tests --- tests/test_integration.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/test_integration.py b/tests/test_integration.py index e3344ff..46b9a2d 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -163,8 +163,8 @@ def test_fetch_account_activity_by_period(self, ig_service: IGService): assert isinstance(response, pd.DataFrame) def test_fetch_account_activity_by_date(self, ig_service: IGService): - to_date = datetime.now() - from_date = to_date - timedelta(days=7) + to_date = datetime.now() - timedelta(days=30) + from_date = to_date - timedelta(days=60) response = ig_service.fetch_account_activity_by_date(from_date, to_date) assert isinstance(response, pd.DataFrame) @@ -174,23 +174,23 @@ def test_fetch_account_activity_v2_span(self, ig_service: IGService): assert isinstance(response, pd.DataFrame) def test_fetch_account_activity_v2_dates(self, ig_service): - to_date = datetime(2021, 7, 31) - from_date = to_date - timedelta(days=7) + to_date = datetime.now() - timedelta(days=30) + from_date = to_date - timedelta(days=60) response = ig_service.fetch_account_activity_v2( from_date=from_date, to_date=to_date ) assert isinstance(response, pd.DataFrame) def test_fetch_account_activity_from(self, ig_service: IGService): - to_date = datetime.now() - timedelta(days=3) - from_date = to_date - timedelta(days=7) + to_date = datetime.now() - timedelta(days=30) + from_date = to_date - timedelta(days=60) response = ig_service.fetch_account_activity(from_date=from_date) assert isinstance(response, pd.DataFrame) assert response.shape[1] == 9 def test_fetch_account_activity_from_to(self, ig_service: IGService): - to_date = datetime(2023, 7, 18) - from_date = to_date - timedelta(days=7) + to_date = datetime.now() - timedelta(days=30) + from_date = to_date - timedelta(days=60) response = ig_service.fetch_account_activity( from_date=from_date, to_date=to_date ) @@ -198,8 +198,8 @@ def test_fetch_account_activity_from_to(self, ig_service: IGService): assert response.shape[1] == 9 def test_fetch_account_activity_detailed(self, ig_service): - to_date = datetime(2023, 7, 18) - from_date = to_date - timedelta(days=7) + to_date = datetime.now() - timedelta(days=30) + from_date = to_date - timedelta(days=60) response = ig_service.fetch_account_activity( from_date=from_date, to_date=to_date, detailed=True ) @@ -208,7 +208,7 @@ def test_fetch_account_activity_detailed(self, ig_service): def test_fetch_account_activity_old(self, ig_service: IGService): from_date = datetime(1970, 1, 1) - to_date = from_date + timedelta(days=7) + to_date = from_date + timedelta(days=60) response = ig_service.fetch_account_activity( from_date=from_date, to_date=to_date ) @@ -216,8 +216,8 @@ def test_fetch_account_activity_old(self, ig_service: IGService): assert response.shape[0] == 0 def test_fetch_account_activity_fiql(self, ig_service: IGService): - to_date = datetime(2023, 7, 18) - from_date = to_date - timedelta(days=30) + to_date = datetime.now() - timedelta(days=30) + from_date = to_date - timedelta(days=60) response = ig_service.fetch_account_activity( from_date=from_date, to_date=to_date, fiql_filter="channel==PUBLIC_WEB_API" ) From 76897d56b5b6eaddc0113d0513a4ebf5081c3bc9 Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Wed, 15 Apr 2026 10:16:43 +0100 Subject: [PATCH 03/14] disable skip --- .github/workflows/integration-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml index 9427926..12eab74 100644 --- a/.github/workflows/integration-test.yml +++ b/.github/workflows/integration-test.yml @@ -8,7 +8,7 @@ on: jobs: build: - if: github.repository == 'ig-python/trading-ig' + # if: github.repository == 'ig-python/trading-ig' runs-on: ubuntu-latest steps: From 3370953078f870754272dde91d880a95685645b0 Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Wed, 15 Apr 2026 12:57:44 +0100 Subject: [PATCH 04/14] project config migrated to uv --- pyproject.toml | 91 +++++++++++++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 41 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 517ef25..29b7e25 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,15 +1,26 @@ -[tool.poetry] +[build-system] +requires = ["uv_build>=0.11.6,<0.12.0"] +build-backend = "uv_build" + +[project] name = "trading-ig" version = "0.0.23" description = "A lightweight Python wrapper for the IG Markets API" -authors = ["Femto Trader ", "Andy Geach "] -maintainers = ["Andy Geach "] -license = "BSD-3-Clause" +authors = [ + { name = "Femto Trader", email = "femto.trader@gmail.com" }, + { name = "Andy Geach", email = "andy@bugorfeature.net" }, +] +requires-python = ">=3.10,<4" readme = "README.rst" -homepage = "https://github.com/ig-python/trading-ig" -repository = "https://github.com/ig-python/trading-ig" -documentation = "https://trading-ig.readthedocs.io/" -keywords = ["trading", "spread betting", "CFDs"] +license = "BSD-3-Clause" +maintainers = [ + { name = "Andy Geach", email = "andy@bugorfeature.net" } +] +keywords = [ + "trading", + "spread betting", + "CFDs", +] classifiers = [ "Development Status :: 3 - Alpha", "Environment :: Console", @@ -18,47 +29,45 @@ classifiers = [ "Operating System :: OS Independent", "Programming Language :: Cython", "Programming Language :: Python", - "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Topic :: Scientific/Engineering", "Topic :: Software Development :: Libraries", - "License :: OSI Approved :: BSD License", +] +dependencies = [ + "requests>=2.24,<3", + "pycryptodome>=3.9,<4", + "requests-cache>=0.5,<0.6", + "six>=1.15,<2", + "lightstreamer-client-lib==1.0.3", ] -[tool.poetry.dependencies] -python = "^3.9" -requests = "^2.24" -pycryptodome = "^3.9" -requests-cache = "^0.5" -six = "^1.15" -lightstreamer-client-lib = "^1.0.3" +[project.optional-dependencies] +pandas = ["pandas>=2,<3"] +munch = ["munch>=2.5,<3"] +tenacity = ["tenacity>=8,<9"] -pandas = {version = "^2", optional = true} -munch = {version = "^2.5", optional = true} -tenacity = {version = "^8", optional = true} +[project.urls] +Homepage = "https://github.com/ig-python/trading-ig" +Repository = "https://github.com/ig-python/trading-ig" +Documentation = "https://trading-ig.readthedocs.io/" +Issues = "https://github.com/ig-python/trading-ig/issues" -[tool.poetry.extras] -pandas = ["pandas"] -munch = ["munch"] -tenacity = ["tenacity"] -sphinx = ["sphinx"] -docs = [ - "sphinx" +[dependency-groups] +dev = [ + "flake8>=7,<8", + "pytest>=8,<9", + "responses>=0.25,<0.26", + "coveralls>=3,<4", + "sphinx", + "sphinx-rtd-theme", + "black==23.3.0", ] -[tool.poetry.group.dev.dependencies] -flake8 = "^7" -pytest = "^8" -responses = "^0.25" -coveralls = "^3" -sphinx-rtd-theme = {version = "^1.0.0", optional = true} -black = "23.3.0" - -[tool.poetry.urls] -"Issues" = "https://github.com/ig-python/trading-ig/issues" - -[build-system] -requires = ["poetry-core>=2.0.0,<3.0.0"] -build-backend = "poetry.core.masonry.api" +[tool.uv.build-backend] +module-name = "trading_ig" +module-root = "" From 13b2f4ad4cf6749a20f1d111791b7828ddd7022c Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Wed, 15 Apr 2026 13:29:01 +0100 Subject: [PATCH 05/14] run unit tests with uv --- .github/workflows/unit-test.yml | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 6ca19bc..f4fee0e 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -13,25 +13,22 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [ "3.10", "3.11", "3.12" ] + python-version: [ "3.10" ] + # python-version: [ "3.10", "3.11", "3.12" ] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 + - name: Install uv and setup Python + uses: astral-sh/setup-uv@v7 with: + version: "0.11.6" python-version: ${{ matrix.python-version }} - - name: Install Poetry - uses: abatilo/actions-poetry@v3 - with: - poetry-version: "latest" - - name: Install dependencies run: | - poetry install --extras "pandas munch tenacity" + uv sync --locked --all-extras --dev - name: Prettify with black uses: psf/black@stable @@ -40,8 +37,8 @@ jobs: - name: Lint with flake8 run: | - poetry run flake8 trading_ig docs sample tests + uv run flake8 trading_ig docs sample tests - name: Unit tests with pytest run: | - poetry run pytest --ignore=tests/test_integration.py + uv run pytest --ignore=tests/test_integration.py From d3b73b4f3c3bdcd3871ace3335f12170a15c1bc8 Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Wed, 15 Apr 2026 13:33:59 +0100 Subject: [PATCH 06/14] don't expect uv.lock file --- .github/workflows/unit-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index f4fee0e..15414a9 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -28,7 +28,7 @@ jobs: - name: Install dependencies run: | - uv sync --locked --all-extras --dev + uv sync --all-extras --dev - name: Prettify with black uses: psf/black@stable From 9ee73aa4a64b5fe7c72bcfac216a35c028e6f50a Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Wed, 15 Apr 2026 13:42:09 +0100 Subject: [PATCH 07/14] lint with ruff --- .github/workflows/unit-test.yml | 4 ++-- pyproject.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 15414a9..ef5eb4a 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -35,9 +35,9 @@ jobs: with: version: "23.3.0" - - name: Lint with flake8 + - name: Lint with ruff run: | - uv run flake8 trading_ig docs sample tests + uv run ruff check trading_ig docs sample tests - name: Unit tests with pytest run: | diff --git a/pyproject.toml b/pyproject.toml index 29b7e25..0eee17c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,7 +59,7 @@ Issues = "https://github.com/ig-python/trading-ig/issues" [dependency-groups] dev = [ - "flake8>=7,<8", + "ruff", "pytest>=8,<9", "responses>=0.25,<0.26", "coveralls>=3,<4", From b3399974798b73f90ddee33ad333d25722b936de Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Wed, 15 Apr 2026 14:03:56 +0100 Subject: [PATCH 08/14] prettify with ruff instead of black --- .github/workflows/unit-test.yml | 7 +++---- pyproject.toml | 1 - sample/rest.ipynb | 9 +++++---- tests/test_activities.py | 1 - tests/test_historical_prices.py | 8 ++------ tests/test_historical_prices_flat.py | 4 +--- tests/test_positions.py | 1 - trading_ig/lightstreamer.py | 3 +-- trading_ig/rest.py | 7 +++---- 9 files changed, 15 insertions(+), 26 deletions(-) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index ef5eb4a..237ab69 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -30,10 +30,9 @@ jobs: run: | uv sync --all-extras --dev - - name: Prettify with black - uses: psf/black@stable - with: - version: "23.3.0" + - name: Check code prettiness with ruff + run: | + uv run ruff format --check - name: Lint with ruff run: | diff --git a/pyproject.toml b/pyproject.toml index 0eee17c..f7b15a5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -65,7 +65,6 @@ dev = [ "coveralls>=3,<4", "sphinx", "sphinx-rtd-theme", - "black==23.3.0", ] [tool.uv.build-backend] diff --git a/sample/rest.ipynb b/sample/rest.ipynb index 6783168..f9f06c2 100644 --- a/sample/rest.ipynb +++ b/sample/rest.ipynb @@ -33,7 +33,7 @@ "service.create_session()\n", "\n", "# creating a v3 session\n", - "#service.create_session(version=\"3\")" + "# service.create_session(version=\"3\")" ] }, { @@ -78,7 +78,7 @@ " resolution=\"D\",\n", " start_date=\"2024-01-01\",\n", " end_date=\"2024-01-22\",\n", - " format=service.flat_prices\n", + " format=service.flat_prices,\n", ")\n", "\n", "data[\"prices\"]" @@ -103,10 +103,10 @@ "source": [ "from pathlib import Path\n", "\n", - "save_path = Path('~').expanduser() / \"prices.csv\"\n", + "save_path = Path(\"~\").expanduser() / \"prices.csv\"\n", "print(f\"saving historic prices to {save_path}\")\n", "\n", - "data[\"prices\"].to_csv(save_path, date_format=\"%Y-%m-%dT%H:%M:%S%z\")\n" + "data[\"prices\"].to_csv(save_path, date_format=\"%Y-%m-%dT%H:%M:%S%z\")" ] }, { @@ -127,6 +127,7 @@ "outputs": [], "source": [ "from datetime import datetime, timedelta\n", + "\n", "to_date = datetime.now()\n", "from_date = to_date - timedelta(days=7)\n", "\n", diff --git a/tests/test_activities.py b/tests/test_activities.py index 88f564f..5a3e1d6 100644 --- a/tests/test_activities.py +++ b/tests/test_activities.py @@ -7,7 +7,6 @@ class TestActivities: - """ unit tests for activities """ diff --git a/tests/test_historical_prices.py b/tests/test_historical_prices.py index 8d098e9..0d139e8 100644 --- a/tests/test_historical_prices.py +++ b/tests/test_historical_prices.py @@ -125,9 +125,7 @@ def test_historical_prices_v3_num_points_bad_numpoints(self): responses.GET, "https://demo-api.ig.com/gateway/deal/prices/MT.D.GC.Month2.IP", headers={"CST": "abc123", "X-SECURITY-TOKEN": "xyz987"}, - json={ - "errorCode": "Unable to convert value=3.14159 to type= Integer int" - }, # noqa + json={"errorCode": "Unable to convert value=3.14159 to type= Integer int"}, # noqa status=400, ) @@ -420,9 +418,7 @@ def test_historical_prices_by_epic_and_num_points_bad_numpoints(self): responses.GET, "https://demo-api.ig.com/gateway/deal/prices/MT.D.GC.Month2.IP", headers={"CST": "abc123", "X-SECURITY-TOKEN": "xyz987"}, - json={ - "errorCode": "Unable to convert value=3.14159 to type= Integer int" - }, # noqa + json={"errorCode": "Unable to convert value=3.14159 to type= Integer int"}, # noqa status=400, ) diff --git a/tests/test_historical_prices_flat.py b/tests/test_historical_prices_flat.py index 029105b..c1a5add 100644 --- a/tests/test_historical_prices_flat.py +++ b/tests/test_historical_prices_flat.py @@ -130,9 +130,7 @@ def test_historical_prices_v3_num_points_bad_numpoints(self): responses.GET, "https://demo-api.ig.com/gateway/deal/prices/MT.D.GC.Month2.IP", headers={"CST": "abc123", "X-SECURITY-TOKEN": "xyz987"}, - json={ - "errorCode": "Unable to convert value=3.14159 to type= Integer int" - }, # noqa + json={"errorCode": "Unable to convert value=3.14159 to type= Integer int"}, # noqa status=400, ) diff --git a/tests/test_positions.py b/tests/test_positions.py index e69a0dc..e746992 100644 --- a/tests/test_positions.py +++ b/tests/test_positions.py @@ -5,7 +5,6 @@ class TestPositions: - """ unit tests for position methods """ diff --git a/trading_ig/lightstreamer.py b/trading_ig/lightstreamer.py index 65e2a97..0d6be9c 100644 --- a/trading_ig/lightstreamer.py +++ b/trading_ig/lightstreamer.py @@ -191,8 +191,7 @@ def connect(self): if not notify and sys.platform.startswith("linux"): log.warning( - "systemd.daemon not available, " - "no watchdog notifications will be sent." + "systemd.daemon not available, no watchdog notifications will be sent." ) self._stream_connection = self._call( diff --git a/trading_ig/rest.py b/trading_ig/rest.py index aaf1236..692c3e4 100644 --- a/trading_ig/rest.py +++ b/trading_ig/rest.py @@ -359,10 +359,9 @@ def _get_session(self, session): if session is None: session = self.session # requests Session else: - assert isinstance( - session, Session - ), "session must be not %s" % type( - session + assert isinstance(session, Session), ( + "session must be not %s" + % type(session) ) session = session return session From 8a8bb3a5f186000e517c78f903aa717eb64f3b89 Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Wed, 15 Apr 2026 14:20:48 +0100 Subject: [PATCH 09/14] 3.10, 3.11, 3.12 --- .github/workflows/unit-test.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 237ab69..48b0d30 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -13,8 +13,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [ "3.10" ] - # python-version: [ "3.10", "3.11", "3.12" ] + python-version: [ "3.10", "3.11", "3.12" ] steps: From 3ddb3d1687403bfe688b54aeaff0fc41cdf41991 Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Wed, 15 Apr 2026 15:24:56 +0100 Subject: [PATCH 10/14] integration test uses uv --- .github/workflows/integration-test.yml | 36 ++++++++++---------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml index 7264edc..6cab2c6 100644 --- a/.github/workflows/integration-test.yml +++ b/.github/workflows/integration-test.yml @@ -2,8 +2,8 @@ name: trading-ig integration test on: - schedule: - - cron: '25 2 * * 1-4' +# schedule: +# - cron: '25 2 * * 1-4' workflow_dispatch: jobs: @@ -12,27 +12,18 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - name: Set up Python 3.10 - uses: actions/setup-python@v5 + - uses: actions/checkout@v6 + + - name: Install uv and setup Python + uses: astral-sh/setup-uv@v7 with: + version: "0.11.6" python-version: "3.10" - - name: Install Poetry - uses: abatilo/actions-poetry@v4 - with: - poetry-version: "latest" - - name: Setup a local virtual environment - run: | - poetry config virtualenvs.create true --local - poetry config virtualenvs.in-project true --local - - uses: actions/cache@v3 - name: Define a cache for the virtual environment based on the dependencies lock file - with: - path: ./.venv - key: venv-${{ hashFiles('poetry.lock') }} + - name: Install dependencies run: | - poetry install --extras "pandas munch tenacity" + uv sync --all-extras --dev + - name: Integration test with pytest env: IG_SERVICE_USERNAME: ${{ secrets.IG_SERVICE_USERNAME }} @@ -41,10 +32,11 @@ jobs: IG_SERVICE_ACC_TYPE: ${{ secrets.IG_SERVICE_ACC_TYPE }} IG_SERVICE_ACC_NUMBER: ${{ secrets.IG_SERVICE_ACC_NUMBER_1 }} run: | - poetry run coverage run -m --source=trading_ig pytest --log-cli-level=DEBUG --log-format="%(asctime)s %(levelname)s %(message)s" --log-date-format="%Y-%m-%d %H:%M:%S" - poetry run coverage report + uv run coverage run -m --source=trading_ig pytest --log-cli-level=DEBUG --log-format="%(asctime)s %(levelname)s %(message)s" --log-date-format="%Y-%m-%d %H:%M:%S" + uv run coverage report + - name: Coveralls env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - poetry run coveralls --service=github + uv run coveralls --service=github From c0b5ad3172d5bb229642a081ae95363d9687cb61 Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Wed, 15 Apr 2026 15:25:08 +0100 Subject: [PATCH 11/14] publish with uv --- .github/workflows/python-publish.yml | 32 +++++++++++++++++----------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index eba0be8..078d817 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -10,19 +10,25 @@ jobs: runs-on: ubuntu-latest + environment: + name: pypi + + permissions: + id-token: write + contents: read + steps: - - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v5 + - name: Checkout + uses: actions/checkout@v6 + + - name: Install uv and Python + uses: astral-sh/setup-uv@v7 with: + version: "0.11.6" python-version: "3.10" - - name: Install Poetry - uses: abatilo/actions-poetry@v3 - with: - poetry-version: "latest" - - name: Build and publish - env: - PYPI_USERNAME: __token__ - PYPI_PASSWORD: ${{ secrets.PYPI_TOKEN }} - run: | - poetry publish -u $PYPI_USERNAME -p $PYPI_PASSWORD --build + + - name: Build + run: uv build + + - name: Publish + run: uv publish From 1718ecb99a0ca26fd21d96e232df15713708d3cd Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Wed, 15 Apr 2026 15:25:22 +0100 Subject: [PATCH 12/14] docs updated for uv use --- README.rst | 24 ++---------------------- docs/source/faq.rst | 30 ++++++++++++++++-------------- docs/source/quickstart.rst | 25 ++----------------------- 3 files changed, 20 insertions(+), 59 deletions(-) diff --git a/README.rst b/README.rst index a84e655..6fd0c7f 100644 --- a/README.rst +++ b/README.rst @@ -62,33 +62,13 @@ For full details, see `pyproject.toml `_. - -Adding to an existing Poetry project:: - - $ poetry add trading-ig - -With all the optional dependencies:: - - $ poetry add trading-ig[pandas,munch,tenacity] - -Cloning the project with Poetry:: - - $ git clone https://github.com/ig-python/trading-ig - $ cd trading-ig - $ poetry install - -And with all optional dependencies:: - - $ poetry install --extras "pandas munch tenacity" - Installing with pip:: $ pip install trading-ig -And with all optional dependencies:: +Installing with all optional dependencies:: - $ pip install trading-ig pandas munch tenacity + $ pip install "trading-ig[pandas, munch, tenacity]" What if I need help? -------------------- diff --git a/docs/source/faq.rst b/docs/source/faq.rst index 83eb47e..fda4fbd 100644 --- a/docs/source/faq.rst +++ b/docs/source/faq.rst @@ -212,33 +212,33 @@ solutions: How do I check my PR will pass CI checks? ----------------------------------------- This project uses some automated continuous integration (CI) processes whenever -any code is committed, or if someone creates a PR. There are unit tests, code -formatting with ``black``, and linting with ``flake8``. In addition, an -integration test gets executed every night. The integration test takes a long -time due to the :ref:`rate limits`. Before making a PR, please make -sure the tests pass - PRs will be rejected if they do not. For code formatting:: +any code is committed, or if someone creates a PR. There are unit tests, and code +formatting and linting with ``ruff``. In addition, an integration test gets +executed every night. The integration test takes a long time due to the +:ref:`rate limits`. Before making a PR, please make sure the tests +pass - PRs will be rejected if they do not. For code formatting:: - $ poetry run black . + $ uv run ruff format and for linting:: - $ poetry run flake8 trading_ig docs sample tests + $ uv run ruff check trading_ig docs sample tests for unit tests:: - $ poetry run pytest --ignore=tests/test_integration.py + $ uv run pytest --ignore=tests/test_integration.py for integration tests:: - $ poetry run pytest tests/test_integration.py + $ uv run pytest tests/test_integration.py for unit and integration tests:: - $ poetry run pytest + $ uv run pytest for all tests, including one *really* long running one that tests v3 sessions:: - $ poetry run pytest --runslow + $ uv run pytest --runslow .. _v2_or_v3_sessions: @@ -332,10 +332,12 @@ An issue without all this information may be ignored and/or closed without respo What happened to ``setup.py`` and ``requirements.txt``? ------------------------------------------------------------- -Early versions of this project used the standard ``setup.py`` config, with a ``requirements.txt`` file describing -dependencies. `Poetry `_ -support was added with version 0.0.10 (July 2021). The old style config was removed with version 0.0.14 +Early versions of this project used the standard ``setup.py`` config, with a +``requirements.txt`` file describing dependencies. `Poetry `_ +support was added with version 0.0.10 (July 2021).The old style config was +removed with version 0.0.14. +We switched to `uv `_ in April 2026. .. _why-is-pandas-an-optional-dependency-in-pyproject-toml: .. _optional-dependencies: diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst index cb86312..b5f456a 100644 --- a/docs/source/quickstart.rst +++ b/docs/source/quickstart.rst @@ -4,34 +4,13 @@ Quickstart Installation ------------ -This project uses `Poetry `_. - -Adding to an existing Poetry project:: - - $ poetry add trading-ig - -With all the optional dependencies:: - - $ poetry add trading-ig[pandas,munch,tenacity] - -Cloning the project with Poetry:: - - $ git clone https://github.com/ig-python/trading-ig - $ cd trading-ig - $ poetry install - -And with all optional dependencies:: - - $ poetry install --extras "pandas munch tenacity" - Installing with pip:: $ pip install trading-ig -And with all optional dependencies:: - - $ pip install trading-ig pandas munch tenacity +Installing with all optional dependencies:: + $ pip install "trading-ig[pandas, munch, tenacity]" Configuration ------------- From 93e5e36bd7759df1bb3089c5928a1e63e7808a29 Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Wed, 15 Apr 2026 17:15:27 +0100 Subject: [PATCH 13/14] fix code formatting --- docs/source/faq.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/faq.rst b/docs/source/faq.rst index fda4fbd..b2486a1 100644 --- a/docs/source/faq.rst +++ b/docs/source/faq.rst @@ -77,7 +77,7 @@ exceeded one of the limits. You can query the limits associated with either a LIVE or DEMO API key after logging on by calling:: -IGService.get_client_apps() + IGService.get_client_apps() This is the rate used when a new IGService object is created with the use_rate_limiter kwarg set as True. From 041fed9f12bcaeca424fc571ce79cae4473b51ce Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Wed, 15 Apr 2026 17:15:50 +0100 Subject: [PATCH 14/14] no need for flake8 config any more --- .flake8 | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 .flake8 diff --git a/.flake8 b/.flake8 deleted file mode 100644 index da0f1a7..0000000 --- a/.flake8 +++ /dev/null @@ -1,4 +0,0 @@ -[flake8] -max-line-length = 88 -extend-ignore = E203 -exclude = __pycache__,build,dist,notes